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
1bed5bf5
Commit
1bed5bf5
authored
Jan 15, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor arrays
parent
75ea8c19
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
124 additions
and
81 deletions
+124
-81
runtime.c
lib/runtime.c
+6
-11
Absyn.cpp
src/Absyn.cpp
+2
-2
Absyn.h
src/Absyn.h
+3
-1
Compiler.cpp
src/Compiler.cpp
+10
-13
Compiler.h
src/Compiler.h
+1
-8
TypeCheck.cpp
src/TypeCheck.cpp
+4
-2
BasicBlock.h
src/codeGen/BasicBlock.h
+1
-0
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+97
-44
No files found.
lib/runtime.c
View file @
1bed5bf5
...
@@ -6,6 +6,11 @@
...
@@ -6,6 +6,11 @@
#include <string.h>
#include <string.h>
#include <stdint.h>
#include <stdint.h>
void
error
()
{
puts
(
"runtime error"
);
exit
(
1
);
}
int
printInt
(
int
a
)
{
int
printInt
(
int
a
)
{
printf
(
"%d
\n
"
,
a
);
printf
(
"%d
\n
"
,
a
);
}
}
...
@@ -47,28 +52,18 @@ int readInt () {
...
@@ -47,28 +52,18 @@ int readInt () {
return
result
;
return
result
;
}
}
void
error
()
{
puts
(
"runtime error"
);
exit
(
1
);
}
char
*
__latte_mem_init
(
size_t
size
,
void
*
virtTab
)
{
char
*
__latte_mem_init
(
size_t
size
,
void
*
virtTab
)
{
char
*
buf
=
calloc
(
1
,
size
);
char
*
buf
=
calloc
(
1
,
size
);
if
(
!
buf
)
error
();
if
(
!
buf
)
error
();
*
((
void
**
)
buf
)
=
virtTab
;
*
((
void
**
)
buf
)
=
virtTab
;
return
buf
;
return
buf
;
}
}
char
*
__latte_mem_init_array
(
int
len
,
size_t
size
,
void
*
virtTab
)
{
char
*
__latte_mem_init_array
(
size_t
size
,
int
len
)
{
if
(
len
<
0
)
error
();
if
(
len
<
0
)
error
();
if
(
len
>
(
SIZE_MAX
-
4
)
/
size
)
error
();
if
(
len
>
(
SIZE_MAX
-
4
)
/
size
)
error
();
char
*
buf
=
calloc
(
1
,
4
+
len
*
size
);
char
*
buf
=
calloc
(
1
,
4
+
len
*
size
);
if
(
!
buf
)
error
();
if
(
!
buf
)
error
();
*
((
int
*
)
buf
)
=
len
;
// store length
*
((
int
*
)
buf
)
=
len
;
// store length
if
(
virtTab
)
{
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
{
*
((
void
**
)(
buf
+
4
+
i
*
size
))
=
virtTab
;
}
}
return
buf
;
return
buf
;
}
}
...
...
src/Absyn.cpp
View file @
1bed5bf5
...
@@ -2909,7 +2909,7 @@ bool Fun::isEqual(Type const *other, bool sub) const {
...
@@ -2909,7 +2909,7 @@ bool Fun::isEqual(Type const *other, bool sub) const {
bool
ClassT
::
isEqual
(
Type
const
*
other
,
bool
sub
)
const
{
bool
ClassT
::
isEqual
(
Type
const
*
other
,
bool
sub
)
const
{
if
(
const
ClassT
*
casted
=
dynamic_cast
<
const
ClassT
*>
(
other
))
{
if
(
const
ClassT
*
casted
=
dynamic_cast
<
const
ClassT
*>
(
other
))
{
auto
v1
=
pident_
->
var
.
lock
(),
v2
=
casted
->
pident_
->
var
.
lock
();
auto
v1
=
pident_
->
getVar
(),
v2
=
casted
->
pident_
->
getVar
();
if
(
!
v1
||
!
v2
)
return
false
;
if
(
!
v1
||
!
v2
)
return
false
;
if
(
v1
==
v2
)
return
true
;
if
(
v1
==
v2
)
return
true
;
if
(
!
sub
)
return
false
;
if
(
!
sub
)
return
false
;
...
@@ -2922,5 +2922,5 @@ bool ClassT::isEqual(Type const *other, bool sub) const {
...
@@ -2922,5 +2922,5 @@ bool ClassT::isEqual(Type const *other, bool sub) const {
}
}
ClassInfoPtr
ClassT
::
getClass
()
const
{
ClassInfoPtr
ClassT
::
getClass
()
const
{
return
dynamic_pointer_cast
<
ClassInfo
>
(
pident_
->
var
.
lock
());
return
dynamic_pointer_cast
<
ClassInfo
>
(
pident_
->
getVar
());
}
}
\ No newline at end of file
src/Absyn.h
View file @
1bed5bf5
...
@@ -273,7 +273,9 @@ class PIdent : public Visitable
...
@@ -273,7 +273,9 @@ class PIdent : public Visitable
{
{
public:
public:
String
string_
;
String
string_
;
std
::
weak_ptr
<
VarInfo
>
var
;
shared_ptr
<
VarInfo
>
var
;
shared_ptr
<
VarInfo
>
getVar
()
{
return
var
;
}
PIdent
(
const
PIdent
&
);
PIdent
(
const
PIdent
&
);
PIdent
&
operator
=
(
const
PIdent
&
);
PIdent
&
operator
=
(
const
PIdent
&
);
...
...
src/Compiler.cpp
View file @
1bed5bf5
...
@@ -78,8 +78,7 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
...
@@ -78,8 +78,7 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
RegisterAllocator
regGen
((
quadEnv
));
RegisterAllocator
regGen
((
quadEnv
));
regGen
.
allocate
();
regGen
.
allocate
();
}
catch
(
const
ParseError
&
e
)
{
}
catch
(
const
ParseError
&
e
)
{
printFunction
(
quadEnv
,
f
);
std
::
cerr
<<
"Register Allocator error: "
<<
e
.
what
()
<<
endl
;
throw
ParseError
(
buf
.
str
()
+
e
.
what
());
}
}
printFunction
(
quadEnv
,
f
);
printFunction
(
quadEnv
,
f
);
...
@@ -251,19 +250,16 @@ void Compiler::generateQAlloc(QAlloc &q) {
...
@@ -251,19 +250,16 @@ void Compiler::generateQAlloc(QAlloc &q) {
if
(
r
!=
Register
(
q
.
loc
))
if
(
r
!=
Register
(
q
.
loc
))
append
(
"PUSHL"
,
r
);
append
(
"PUSHL"
,
r
);
}
}
assert
(
q
.
virtSymbol
.
empty
()
||
!
q
.
count
);
if
(
q
.
virtSymbol
.
empty
()
)
{
if
(
q
.
count
)
{
append
(
"PUSHL"
,
"$0"
);
append
(
"PUSHL"
,
getRef
(
q
.
count
)
);
}
else
{
}
else
{
append
(
"PUSHL"
,
"$"
+
quote
(
q
.
virtSymbol
));
append
(
"PUSHL"
,
"$"
+
quote
(
q
.
virtSymbol
));
}
}
append
(
"PUSHL"
,
"$"
+
to_string
(
q
.
size
));
append
(
"PUSHL"
,
"$"
+
to_string
(
q
.
size
));
if
(
q
.
count
)
{
append
(
"PUSHL"
,
getRef
(
q
.
count
));
}
append
(
"CALL"
,
q
.
count
?
"__latte_mem_init_array"
:
"__latte_mem_init"
);
append
(
"CALL"
,
q
.
count
?
"__latte_mem_init_array"
:
"__latte_mem_init"
);
append
(
"ADDL"
,
"$"
+
to_string
(
q
.
count
?
12
:
8
),
"%esp"
);
append
(
"ADDL"
,
"$"
+
to_string
(
q
.
count
?
12
:
8
),
"%esp"
);
...
@@ -319,7 +315,7 @@ void Compiler::generateQCall(QCall &q) {
...
@@ -319,7 +315,7 @@ void Compiler::generateQCall(QCall &q) {
}
else
{
}
else
{
append
(
"CALL"
,
quote
(
mangleFunctionName
(
q
.
fn
)));
append
(
"CALL"
,
quote
(
mangleFunctionName
(
q
.
fn
)));
}
}
if
(
q
.
params
)
{
if
(
q
.
params
||
q
.
self
)
{
append
(
"ADDL"
,
"$"
+
to_string
(
q
.
params
*
4
+
(
q
.
self
?
4
:
0
)),
"%esp"
);
append
(
"ADDL"
,
"$"
+
to_string
(
q
.
params
*
4
+
(
q
.
self
?
4
:
0
)),
"%esp"
);
}
}
auto
popRegs
=
registersToSave
(
q
);
auto
popRegs
=
registersToSave
(
q
);
...
@@ -335,7 +331,7 @@ void Compiler::generateQCall(QCall &q) {
...
@@ -335,7 +331,7 @@ void Compiler::generateQCall(QCall &q) {
void
Compiler
::
generateQParam
(
QParam
&
q
)
{
void
Compiler
::
generateQParam
(
QParam
&
q
)
{
if
(
q
.
call
)
{
if
(
q
.
call
)
{
assert
(
q
.
num
>=
0
);
assert
(
q
.
num
>=
0
);
if
(
q
.
num
==
1
)
{
if
(
q
.
num
==
(
q
.
call
->
params
?
1
:
0
)
)
{
// first argument, need to save registers
// first argument, need to save registers
for
(
auto
r
:
registersToSave
(
*
q
.
call
))
{
for
(
auto
r
:
registersToSave
(
*
q
.
call
))
{
if
(
r
!=
Register
(
q
.
call
->
loc
))
if
(
r
!=
Register
(
q
.
call
->
loc
))
...
@@ -438,12 +434,13 @@ Op Compiler::generateCmp(const VariablePtr& l, Op op, const VariablePtr &r) {
...
@@ -438,12 +434,13 @@ Op Compiler::generateCmp(const VariablePtr& l, Op op, const VariablePtr &r) {
void
Compiler
::
generateQJumpCond
(
QJumpCond
&
q
)
{
void
Compiler
::
generateQJumpCond
(
QJumpCond
&
q
)
{
auto
thisBlock
=
q
.
block
;
auto
thisBlock
=
q
.
block
;
auto
tgBlock
=
q
.
target
->
block
;
auto
tgBlock
=
q
.
target
->
block
;
assert
(
thisBlock
&&
tgBlock
);
const
auto
&
map
=
tgBlock
->
getPhiMapping
(
thisBlock
);
const
auto
&
map
=
tgBlock
->
getPhiMapping
(
thisBlock
);
for
(
const
auto
&
phiVars
:
map
)
{
for
(
const
auto
&
phiVars
:
map
)
{
if
((
phiVars
.
first
->
info
&&
phiVars
.
second
->
info
&&
phiVars
.
first
->
info
!=
phiVars
.
second
->
info
)
||
if
((
phiVars
.
first
->
info
&&
phiVars
.
second
->
info
&&
phiVars
.
first
->
info
!=
phiVars
.
second
->
info
)
||
(
phiVars
.
first
->
localOffset
&&
phiVars
.
second
->
localOffset
&&
phiVars
.
first
->
localOffset
!=
phiVars
.
second
->
localOffset
)
||
(
phiVars
.
first
->
localOffset
&&
phiVars
.
second
->
localOffset
&&
phiVars
.
first
->
localOffset
!=
phiVars
.
second
->
localOffset
)
||
(
phiVars
.
first
->
registerColor
&&
phiVars
.
second
->
registerColor
&&
phiVars
.
first
->
registerColor
!=
phiVars
.
second
->
registerColor
)
(
phiVars
.
first
->
registerColor
&&
phiVars
.
second
->
registerColor
&&
phiVars
.
first
->
registerColor
!=
phiVars
.
second
->
registerColor
)
)
{
)
{
buf
<<
(
"// Unimplemented phi CondJump register XCHG
\n
"
);
buf
<<
(
"// Unimplemented phi CondJump register XCHG
\n
"
);
}
}
}
}
...
...
src/Compiler.h
View file @
1bed5bf5
...
@@ -85,10 +85,7 @@ public:
...
@@ -85,10 +85,7 @@ public:
}
}
auto
unused
(
const
QuadruplePtr
&
q
)
const
{
auto
unused
(
const
QuadruplePtr
&
q
)
const
{
auto
ret
=
to_set
(
::
aliveAfter
(
q
,
Register
::
assignable
));
return
available
()
-
to_set
(
::
aliveAfter
(
q
,
Register
::
assignable
));
ret
.
emplace
(
0
);
ret
-=
to_set
(
locks
);
return
ret
;
}
}
void
lock
(
Register
i
)
{
void
lock
(
Register
i
)
{
...
@@ -220,10 +217,6 @@ protected:
...
@@ -220,10 +217,6 @@ protected:
}
}
void
moveTo
(
VariablePtr
&
v
,
Register
tg
)
{
void
moveTo
(
VariablePtr
&
v
,
Register
tg
)
{
if
(
v
->
constExpr
)
{
append
(
"MOVL"
,
"$"
+
to_string
(
v
->
val
),
tg
);
return
;
}
auto
reg
=
Register
(
v
);
auto
reg
=
Register
(
v
);
if
(
reg
==
0
)
{
if
(
reg
==
0
)
{
append
(
"MOVL"
,
getRef
(
v
),
tg
);
append
(
"MOVL"
,
getRef
(
v
),
tg
);
...
...
src/TypeCheck.cpp
View file @
1bed5bf5
...
@@ -31,7 +31,7 @@ void TypeCheck::visitPIdent(PIdent *p_ident)
...
@@ -31,7 +31,7 @@ void TypeCheck::visitPIdent(PIdent *p_ident)
p_ident
->
var
=
var
;
p_ident
->
var
=
var
;
lastType
=
var
->
type
;
lastType
=
var
->
type
;
if
(
auto
ptr
=
dynamic_pointer_cast
<
ClassT
>
(
lastType
))
{
if
(
auto
ptr
=
dynamic_pointer_cast
<
ClassT
>
(
lastType
))
{
if
(
!
ptr
->
pident_
||
!
ptr
->
pident_
->
var
.
lock
())
if
(
!
ptr
->
pident_
||
!
ptr
->
pident_
->
getVar
())
throw
runtime_error
(
"either no pident or no var assigned found"
);
throw
runtime_error
(
"either no pident or no var assigned found"
);
}
}
}
}
...
@@ -247,6 +247,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
...
@@ -247,6 +247,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
VarInfoPtr
var
=
make_shared
<
VarInfo
>
(
for_each
->
pident_
,
for_each
->
type_
->
clone
());
VarInfoPtr
var
=
make_shared
<
VarInfo
>
(
for_each
->
pident_
,
for_each
->
type_
->
clone
());
binding
->
variables
<<
var
;
binding
->
variables
<<
var
;
for_each
->
pident_
->
var
=
var
;
scope
->
currentBinding
=
binding
;
scope
->
currentBinding
=
binding
;
for_each
->
stmt_
->
accept
(
this
);
for_each
->
stmt_
->
accept
(
this
);
...
@@ -319,7 +320,7 @@ void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
...
@@ -319,7 +320,7 @@ void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
throw
ParseError
(
"Class expected"
,
e_cls_mmbr
->
expr_
);
throw
ParseError
(
"Class expected"
,
e_cls_mmbr
->
expr_
);
}
}
ClassInfoPtr
klass
=
scope
->
classes
[
type
->
pident_
];
ClassInfoPtr
klass
=
scope
->
classes
[
type
->
pident_
];
assert
(
klass
==
type
->
pident_
->
var
.
lock
());
assert
(
klass
==
type
->
pident_
->
getVar
());
VarInfoPtr
var
=
klass
->
variables
[
e_cls_mmbr
->
pident_
];
VarInfoPtr
var
=
klass
->
variables
[
e_cls_mmbr
->
pident_
];
if
(
!
var
||
var
==
scope
->
variables
.
local
(
e_cls_mmbr
->
pident_
->
string_
))
{
if
(
!
var
||
var
==
scope
->
variables
.
local
(
e_cls_mmbr
->
pident_
->
string_
))
{
throw
UndefinedError
(
e_cls_mmbr
->
pident_
);
throw
UndefinedError
(
e_cls_mmbr
->
pident_
);
...
@@ -662,6 +663,7 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
...
@@ -662,6 +663,7 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
f
->
binding
=
binding
;
f
->
binding
=
binding
;
if
(
scope
->
currentClass
)
{
if
(
scope
->
currentClass
)
{
f
->
self
=
make_shared
<
VarInfo
>
(
"self"
,
scope
->
currentClass
->
type
);
f
->
self
=
make_shared
<
VarInfo
>
(
"self"
,
scope
->
currentClass
->
type
);
f
->
self
->
lineLocation
=
f
->
lineLocation
;
binding
->
variables
<<
f
->
self
;
binding
->
variables
<<
f
->
self
;
}
}
...
...
src/codeGen/BasicBlock.h
View file @
1bed5bf5
...
@@ -73,6 +73,7 @@ public:
...
@@ -73,6 +73,7 @@ public:
[[
nodiscard
]]
set
<
VariablePtr
>
inForBlock
(
const
BasicBlockPtr
&
q
)
const
{
[[
nodiscard
]]
set
<
VariablePtr
>
inForBlock
(
const
BasicBlockPtr
&
q
)
const
{
set
<
VariablePtr
>
ret
;
set
<
VariablePtr
>
ret
;
for
(
const
auto
&
var
:
b
->
findPhi
(
q
))
{
for
(
const
auto
&
var
:
b
->
findPhi
(
q
))
{
if
(
var
.
second
->
constExpr
)
continue
;
ret
.
emplace
(
var
.
second
);
ret
.
emplace
(
var
.
second
);
}
}
return
in
+
ret
;
return
in
+
ret
;
...
...
src/codeGen/QuadrupleGenerator.cpp
View file @
1bed5bf5
...
@@ -107,7 +107,7 @@ VariableLayout QuadrupleGenerator::captureEnv() {
...
@@ -107,7 +107,7 @@ VariableLayout QuadrupleGenerator::captureEnv() {
/// expressions
/// expressions
void
QuadrupleGenerator
::
visitEVar
(
EVar
*
p
)
{
void
QuadrupleGenerator
::
visitEVar
(
EVar
*
p
)
{
auto
var
=
p
->
pident_
->
var
.
lock
();
auto
var
=
p
->
pident_
->
getVar
();
lastVar
=
alloc
(
var
);
lastVar
=
alloc
(
var
);
if
(
var
->
isInstanceVariable
())
{
if
(
var
->
isInstanceVariable
())
{
auto
fn
=
scope
->
currentFunction
;
auto
fn
=
scope
->
currentFunction
;
...
@@ -281,13 +281,14 @@ void QuadrupleGenerator::visitEOr(EOr *p) {
...
@@ -281,13 +281,14 @@ void QuadrupleGenerator::visitEOr(EOr *p) {
leftValBlock
->
append
(
block
);
leftValBlock
->
append
(
block
);
auto
r
=
evalJump
(
p
->
expr_2
,
labelTrue
,
labelFalse
);
auto
r
=
evalJump
(
p
->
expr_2
,
labelTrue
,
labelFalse
);
if
(
!
r
)
return
;
if
(
r
->
constExpr
)
{
if
(
!
r
||
r
->
constExpr
)
{
assert
(
leftValBlock
->
quads
.
back
()
==
llq
);
assert
(
leftValBlock
->
quads
.
back
()
==
llq
);
leftValBlock
->
quads
.
pop_back
();
leftValBlock
->
quads
.
pop_back
();
// could merge basic blocks now, but why bother
// could merge basic blocks now, but why bother
lastVar
=
r
->
val
?
r
:
l
;
if
(
r
)
{
lastVar
=
r
->
val
?
r
:
l
;
}
}
else
{
}
else
{
auto
rightValBlock
=
block
;
auto
rightValBlock
=
block
;
flushBasicBlock
();
flushBasicBlock
();
...
@@ -321,17 +322,8 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
...
@@ -321,17 +322,8 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
}
}
lastVar
=
alloc
(
type
->
type_
->
clone
());
lastVar
=
alloc
(
type
->
type_
->
clone
());
lastVar
->
memory
=
true
;
lastVar
->
memory
=
true
;
if
(
type
->
type_
->
size
()
>
4
)
{
assert
(
type
->
type_
->
size
()
<=
4
);
// calculate quantifier, we multiply index because size is larger than 4
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
index
,
type
->
type_
->
size
(),
4
);
// 4 accounts for table length entry
auto
q
=
alloc
(
type
->
type_
->
size
());
auto
newIndex
=
alloc
();
// calculate var = index * quantifier
addQuad
<
QAssign
>
(
newIndex
,
index
,
Op
::
Mul
,
q
);
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
newIndex
,
1
,
4
);
// 4 accounts for table length entry
}
else
{
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
index
,
type
->
type_
->
size
(),
4
);
// 4 accounts for table length entry
}
Bool
b
;
Bool
b
;
if
(
type
->
type_
->
isEqual
(
&
b
))
{
if
(
type
->
type_
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
...
@@ -340,23 +332,13 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
...
@@ -340,23 +332,13 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
void
QuadrupleGenerator
::
visitEClsMmbr
(
EClsMmbr
*
p
)
{
void
QuadrupleGenerator
::
visitEClsMmbr
(
EClsMmbr
*
p
)
{
auto
l
=
evalJump
(
p
->
expr_
,
labelTrue
,
labelFalse
);
auto
l
=
evalJump
(
p
->
expr_
,
labelTrue
,
labelFalse
);
auto
var
=
p
->
pident_
->
var
.
lock
();
auto
var
=
p
->
pident_
->
getVar
();
assert
(
var
);
assert
(
var
);
// it cannot be function, as function might only be used in EApp and are handled directly there
// it cannot be function, as function might only be used in EApp and are handled directly there
assert
(
!
var
->
toFunction
());
assert
(
!
var
->
toFunction
());
// Array length calculation works because of arrayLengthVar that has offset 0
// Array length calculation works because of arrayLengthVar that has offset 0
size_t
offset
=
var
->
offset
;
lastVar
=
alloc
(
var
);
if
(
dynamic_cast
<
EIndexAcc
*>
(
p
->
expr_
))
{
addQuad
<
QAccess
>
(
lastVar
,
l
,
nullptr
,
0
,
var
->
offset
);
// opt if EIndexAcc is used inside visitEClsMmbr
auto
access
=
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
);
access
->
access
.
offset
+=
offset
;
l
->
info
=
var
;
lastVar
=
l
;
}
else
{
lastVar
=
alloc
(
var
);
auto
quad
=
make_shared
<
QAccess
>
(
lastVar
,
l
,
nullptr
,
0
,
offset
);
addQuad
(
quad
);
}
Bool
b
;
Bool
b
;
if
(
var
->
type
->
isEqual
(
&
b
))
{
if
(
var
->
type
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
...
@@ -371,10 +353,10 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
...
@@ -371,10 +353,10 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
// call tab[i].fun()
// call tab[i].fun()
// call obj.fun()
// call obj.fun()
self
=
evalExpr
(
mem
->
expr_
);
self
=
evalExpr
(
mem
->
expr_
);
info
=
static_pointer_cast
<
FunctionInfo
>
(
mem
->
pident_
->
var
.
lock
());
info
=
static_pointer_cast
<
FunctionInfo
>
(
mem
->
pident_
->
getVar
());
}
else
if
(
auto
ident
=
dynamic_cast
<
EVar
*>
(
p
->
expr_
))
{
}
else
if
(
auto
ident
=
dynamic_cast
<
EVar
*>
(
p
->
expr_
))
{
auto
klass
=
scope
->
currentFunction
->
klass
.
lock
();
auto
klass
=
scope
->
currentFunction
->
klass
.
lock
();
info
=
static_pointer_cast
<
FunctionInfo
>
(
ident
->
pident_
->
var
.
lock
());
info
=
static_pointer_cast
<
FunctionInfo
>
(
ident
->
pident_
->
getVar
());
auto
otherClass
=
info
->
klass
.
lock
();
auto
otherClass
=
info
->
klass
.
lock
();
if
(
otherClass
)
{
if
(
otherClass
)
{
// call fun() = self.fun()
// call fun() = self.fun()
...
@@ -416,20 +398,14 @@ void QuadrupleGenerator::visitENewArray(ENewArray *p) {
...
@@ -416,20 +398,14 @@ void QuadrupleGenerator::visitENewArray(ENewArray *p) {
// allocate enough memory with calloc, if it is class then init each entry...
// allocate enough memory with calloc, if it is class then init each entry...
auto
type
=
p
->
type_
;
auto
type
=
p
->
type_
;
size_t
size
=
type
->
size
();
size_t
size
=
type
->
size
();
string
virtSymbol
;
if
(
auto
klass
=
dynamic_cast
<
ClassT
*>
(
type
))
{
auto
info
=
klass
->
pident_
->
var
.
lock
()
->
toClass
();
size
=
info
->
size
;
virtSymbol
=
Compiler
::
getVirtName
(
info
);
}
auto
count
=
evalExpr
(
p
->
expr_
);
auto
count
=
evalExpr
(
p
->
expr_
);
lastVar
=
alloc
(
new
Array
(
type
->
clone
()));
lastVar
=
alloc
(
new
Array
(
type
->
clone
()));
addQuad
<
QAlloc
>
(
lastVar
,
size
,
virtSymbol
,
count
);
addQuad
<
QAlloc
>
(
lastVar
,
size
,
""
,
count
);
}
}
void
QuadrupleGenerator
::
visitENewClass
(
ENewClass
*
p
)
{
void
QuadrupleGenerator
::
visitENewClass
(
ENewClass
*
p
)
{
// allocate enough memory with calloc, setup virt table pointer.
// allocate enough memory with calloc, setup virt table pointer.
auto
info
=
p
->
pident_
->
var
.
lock
()
->
toClass
();
auto
info
=
p
->
pident_
->
getVar
()
->
toClass
();
size_t
size
=
info
->
size
;
size_t
size
=
info
->
size
;
string
virtSymbol
=
Compiler
::
getVirtName
(
info
);
string
virtSymbol
=
Compiler
::
getVirtName
(
info
);
lastVar
=
alloc
();
lastVar
=
alloc
();
...
@@ -439,7 +415,7 @@ void QuadrupleGenerator::visitENewClass(ENewClass *p) {
...
@@ -439,7 +415,7 @@ void QuadrupleGenerator::visitENewClass(ENewClass *p) {
/// statements
/// statements
void
QuadrupleGenerator
::
visitInit
(
Init
*
p
)
{
void
QuadrupleGenerator
::
visitInit
(
Init
*
p
)
{
auto
info
=
p
->
pident_
->
var
.
lock
();
auto
info
=
p
->
pident_
->
getVar
();
assert
(
info
);
assert
(
info
);
auto
var
=
evalExpr
(
p
->
expr_
);
auto
var
=
evalExpr
(
p
->
expr_
);
auto
loc
=
alloc
(
info
);
auto
loc
=
alloc
(
info
);
...
@@ -449,7 +425,7 @@ void QuadrupleGenerator::visitInit(Init *p) {
...
@@ -449,7 +425,7 @@ void QuadrupleGenerator::visitInit(Init *p) {
}
}
void
QuadrupleGenerator
::
visitNoInit
(
Init
*
p
)
{
void
QuadrupleGenerator
::
visitNoInit
(
Init
*
p
)
{
auto
info
=
p
->
pident_
->
var
.
lock
();
auto
info
=
p
->
pident_
->
getVar
();
assert
(
info
);
assert
(
info
);
auto
loc
=
alloc
(
info
);
auto
loc
=
alloc
(
info
);
addQuad
<
QAssign
>
(
loc
,
Op
::
Copy
,
alloc
(
0
));
addQuad
<
QAssign
>
(
loc
,
Op
::
Copy
,
alloc
(
0
));
...
@@ -531,8 +507,10 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) {
...
@@ -531,8 +507,10 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) {
if
(
condVar
->
constExpr
)
{
if
(
condVar
->
constExpr
)
{
assert
(
!
dynamic_pointer_cast
<
QJump
>
(
lastQuad
));
assert
(
!
dynamic_pointer_cast
<
QJump
>
(
lastQuad
));
if
(
condVar
->
val
)
{
if
(
condVar
->
val
)
{
addQuad
(
ifBranch
);
stmt_1
->
accept
(
this
);
stmt_1
->
accept
(
this
);
}
else
if
(
stmt_2
)
{
}
else
if
(
stmt_2
)
{
addQuad
(
elseBranch
);
stmt_2
->
accept
(
this
);
stmt_2
->
accept
(
this
);
}
}
return
;
return
;
...
@@ -647,8 +625,83 @@ void QuadrupleGenerator::visitSExp(SExp *p) {
...
@@ -647,8 +625,83 @@ void QuadrupleGenerator::visitSExp(SExp *p) {
evalExpr
(
p
->
expr_
);
evalExpr
(
p
->
expr_
);
}
}
void
QuadrupleGenerator
::
visitForEach
(
ForEach
*
p
)
{
void
QuadrupleGenerator
::
visitForEach
(
ForEach
*
expr
)
{
auto
tab
=
evalExpr
(
p
->
expr_
);
auto
cond
=
make_shared
<
QLabel
>
(
"for_cond"
);
// throw ParseError("ForEach is yet unimplemented!", p);
// TODO: implement
auto
arr
=
evalExpr
(
expr
->
expr_
);
addQuad
<
QJump
>
(
cond
);
auto
beforeBlock
=
flushBasicBlock
();
// jump <- loop -> cond
auto
loop
=
make_shared
<
QLabel
>
(
"for_loop"
);
addQuad
(
loop
);
// jump <- loop
// hook env
auto
env1
=
captureEnv
();
// produce all variables hooks
for
(
const
auto
&
change
:
env1
.
changes
)
{
if
(
!
change
.
second
.
first
)
continue
;
auto
info
=
change
.
first
;
info
->
loc
=
nullptr
;
alloc
(
info
);
}
VarInfoPtr
iter
=
make_shared
<
VarInfo
>
(
"_it"
,
make_shared
<
Int
>
());
auto
iter1
=
alloc
(
iter
);
// save hooks for later
env1
.
capture
();
// env2 starts with hooked variables
auto
env2
=
captureEnv
();
auto
loopFirstBlock
=
block
;
auto
iterInfo
=
expr
->
pident_
->
getVar
();
assert
(
iterInfo
);
auto
iterVar
=
alloc
(
iterInfo
);
addQuad
<
QAccess
>
(
iterVar
,
arr
,
iter1
,
4
,
4
);
expr
->
stmt_
->
accept
(
this
);
iter
->
loc
=
nullptr
;
auto
iter2
=
alloc
(
iter
);
addQuad
<
QAssign
>
(
iter2
,
iter1
,
Op
::
Plus
,
alloc
(
1
));
auto
loopLastBlock
=
flushBasicBlock
(
true
);
// jump <- cond
auto
condFirstBlock
=
block
;
addQuad
(
cond
);
// env2 contains changed hooks
env2
.
capture
();
// restore env1 pre-hook variables
env1
.
revert
();
beforeBlock
->
append
(
condFirstBlock
);
for
(
const
auto
&
p
:
env2
.
changes
)
{
auto
info
=
p
.
first
;
auto
hooked
=
p
.
second
.
first
;
auto
looped
=
p
.
second
.
second
;
if
(
!
hooked
)
continue
;
auto
orig
=
env1
.
changes
[
info
].
first
;
// save hooks if used
info
->
loc
=
hooked
;
// transition from pre-hook to hooked var [before -> cond]
condFirstBlock
->
addPhi
(
beforeBlock
,
hooked
,
orig
);
// transition from hooked var
condFirstBlock
->
addPhi
(
loopLastBlock
,
hooked
,
looped
);
// loopLastBlock doesn't need phi, it has only one incoming block
}
condFirstBlock
->
addPhi
(
beforeBlock
,
iter1
,
alloc
(
0
));
condFirstBlock
->
addPhi
(
loopLastBlock
,
iter1
,
iter2
);
auto
len
=
alloc
();
addQuad
<
QAccess
>
(
len
,
arr
,
nullptr
,
0
,
0
);
addQuad
<
QJumpCond
>
(
loop
,
iter1
,
Op
::
LT
,
len
);
auto
condLastBlock
=
flushBasicBlock
(
true
);
// jump -> loop
condLastBlock
->
append
(
loopFirstBlock
);
// next block is ready to use updated variables
}
}
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