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
459ffddf
Commit
459ffddf
authored
Jan 09, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Dopychanie kolanem
parent
e694f348
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
437 additions
and
121 deletions
+437
-121
Makefile
Makefile
+6
-6
Compiler.cpp
src/Compiler.cpp
+159
-54
Compiler.h
src/Compiler.h
+72
-10
BasicBlock.h
src/codeGen/BasicBlock.h
+1
-1
Quadruple.h
src/codeGen/Quadruple.h
+22
-6
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+148
-43
QuadrupleGenerator.h
src/codeGen/QuadrupleGenerator.h
+28
-0
RegisterAllocator.cpp
src/codeGen/RegisterAllocator.cpp
+1
-1
No files found.
Makefile
View file @
459ffddf
...
@@ -3,14 +3,14 @@ CCFLAGS=-g -W -Wall -O0 -std=c++2a -Wno-unused-parameter
...
@@ -3,14 +3,14 @@ CCFLAGS=-g -W -Wall -O0 -std=c++2a -Wno-unused-parameter
.PHONY
:
clean distclean
.PHONY
:
clean distclean
all
:
latc
all
:
latc
_x86
clean
:
clean
:
rm
-f
*
.o latc Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
rm
-f
*
.o latc
_x86
Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
latc
:
Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o BasicBlock.o QuadrupleGenerator.o RegisterAllocator.o Latte.o
latc
_x86
:
Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o BasicBlock.o QuadrupleGenerator.o RegisterAllocator.o Latte.o
@
echo
"Linking latc..."
@
echo
"Linking latc
_x86
..."
${
CC
}
${
CCFLAGS
}
$^
-lstdc
++fs
-o
latc
${
CC
}
${
CCFLAGS
}
$^
-lstdc
++fs
-o
latc
_x86
Absyn.o
:
src/Absyn.cpp src/Absyn.h
Absyn.o
:
src/Absyn.cpp src/Absyn.h
${
CC
}
${
CCFLAGS
}
-c
src/Absyn.cpp
${
CC
}
${
CCFLAGS
}
-c
src/Absyn.cpp
...
@@ -30,7 +30,7 @@ Skeleton.o : src/Skeleton.cpp src/Skeleton.h src/Absyn.h
...
@@ -30,7 +30,7 @@ Skeleton.o : src/Skeleton.cpp src/Skeleton.h src/Absyn.h
TypeCheck.o
:
src/TypeCheck.cpp src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h
TypeCheck.o
:
src/TypeCheck.cpp src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h
${
CC
}
${
CCFLAGS
}
-c
src/TypeCheck.cpp
${
CC
}
${
CCFLAGS
}
-c
src/TypeCheck.cpp
Compiler.o
:
src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h src/codeGen/RegisterAllocator.h src/codeGen/Graph.h
Compiler.o
:
src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h src/codeGen/RegisterAllocator.h src/codeGen/Graph.h
src/codeGen/BasicBlock.h
${
CC
}
${
CCFLAGS
}
-c
src/Compiler.cpp
${
CC
}
${
CCFLAGS
}
-c
src/Compiler.cpp
Info.o
:
src/Info.cpp src/Info.h src/InfoList.h src/Absyn.h
Info.o
:
src/Info.cpp src/Info.h src/InfoList.h src/Absyn.h
...
...
src/Compiler.cpp
View file @
459ffddf
...
@@ -8,7 +8,6 @@
...
@@ -8,7 +8,6 @@
extern
std
::
filesystem
::
path
binaryPath
;
extern
std
::
filesystem
::
path
binaryPath
;
const
std
::
string
Compiler
::
extension
=
"s"
;
const
std
::
string
Compiler
::
extension
=
"s"
;
void
Compiler
::
externalCommand
(
std
::
filesystem
::
path
lat
)
{
void
Compiler
::
externalCommand
(
std
::
filesystem
::
path
lat
)
{
return
;
auto
obj
=
lat
;
auto
obj
=
lat
;
obj
.
replace_extension
(
"o"
);
obj
.
replace_extension
(
"o"
);
auto
cmd
=
std
::
string
(
"as --32 '"
)
+
lat
.
string
()
+
"' -o '"
+
obj
.
string
()
+
"'"
;
auto
cmd
=
std
::
string
(
"as --32 '"
)
+
lat
.
string
()
+
"' -o '"
+
obj
.
string
()
+
"'"
;
...
@@ -16,9 +15,10 @@ void Compiler::externalCommand(std::filesystem::path lat) {
...
@@ -16,9 +15,10 @@ void Compiler::externalCommand(std::filesystem::path lat) {
system
(
cmd
.
data
());
system
(
cmd
.
data
());
auto
lib
=
binaryPath
.
parent_path
()
/
"lib"
;
auto
lib
=
binaryPath
.
parent_path
()
/
"lib"
;
auto
runtime
=
lib
/
"runtime.o"
;
auto
runtime
=
lib
/
"runtime.o"
;
auto
libc
=
lib
/
"libc.a"
;
auto
result
=
obj
;
auto
result
=
obj
;
result
.
replace_extension
(
""
);
result
.
replace_extension
(
""
);
cmd
=
std
::
string
(
"ld -m elf_i386 -L'"
)
+
lib
.
string
()
+
"' '"
+
runtime
.
string
()
+
"' '"
+
obj
.
string
()
+
"' -o '"
+
result
.
string
()
+
"'"
;
cmd
=
std
::
string
(
"ld -m elf_i386 -L'"
)
+
lib
.
string
()
+
"' '"
+
runtime
.
string
()
+
"' '"
+
libc
.
string
()
+
"' '"
+
obj
.
string
()
+
"' -o '"
+
result
.
string
()
+
"'"
;
cerr
<<
cmd
<<
endl
;
cerr
<<
cmd
<<
endl
;
system
(
cmd
.
data
());
system
(
cmd
.
data
());
}
}
...
@@ -55,6 +55,9 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
...
@@ -55,6 +55,9 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
// c++ thiscall ecx, stack right-to-left (push c, push b, push a)
// c++ thiscall ecx, stack right-to-left (push c, push b, push a)
buf
<<
"
\"
"
<<
name
<<
"
\"
:
\n
"
;
buf
<<
"
\"
"
<<
name
<<
"
\"
:
\n
"
;
stringstream
asmGen
;
swap
(
buf
,
asmGen
);
exitLabel
=
make_shared
<
QLabel
>
(
"."
+
name
+
"_exit"
);
QuadrupleGenerator
::
Result
quadEnv
=
quadGen
.
compileFunction
(
f
);
QuadrupleGenerator
::
Result
quadEnv
=
quadGen
.
compileFunction
(
f
);
try
{
try
{
RegisterAllocator
regGen
((
quadEnv
));
RegisterAllocator
regGen
((
quadEnv
));
...
@@ -65,12 +68,28 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
...
@@ -65,12 +68,28 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
}
}
printFunction
(
quadEnv
);
printFunction
(
quadEnv
);
swap
(
buf
,
asmGen
);
// for (auto &b : quadEnv.blocks) {
// for (auto &b : quadEnv.blocks) {
// for (auto &q : b->quads) {
// for (auto &q : b->quads) {
// q->generateAsm(*this);
// q->generateAsm(*this);
// }
// }
// }
// }
uint
localsCount
=
temps
.
size
()
+
localInfos
.
size
();
for
(
auto
i
:
calleeSavedRegisters
)
append
(
"PUSH"
,
Register
(
i
));
buf
<<
"
\t
push %ebp
\n
"
"
\t
mov %esp, %ebp
\n
"
;
if
(
localsCount
)
{
buf
<<
"
\t
sub $"
+
to_string
(
localsCount
*
4
)
<<
",%esp
\n
"
;
}
buf
<<
asmGen
.
str
();
buf
<<
"
\"
"
<<
exitLabel
->
label
<<
"
\"
:
\n
"
<<
"MOVL %ebp, %esp
\n
"
"POP %ebp
\n
"
;
for
(
auto
i
:
calleeSavedRegisters
)
append
(
"POP"
,
Register
(
i
));
buf
<<
"RET
\n
"
;
for
(
auto
&
t
:
temps
)
t
->
localOffset
=
0
;
for
(
auto
&
t
:
temps
)
t
->
localOffset
=
0
;
for
(
auto
&
v
:
localInfos
)
v
->
localOffset
=
0
;
for
(
auto
&
v
:
localInfos
)
v
->
localOffset
=
0
;
...
@@ -81,30 +100,30 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
...
@@ -81,30 +100,30 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
void
Compiler
::
printFunction
(
QuadrupleGenerator
::
Result
quadEnv
)
{
void
Compiler
::
printFunction
(
QuadrupleGenerator
::
Result
quadEnv
)
{
int
blkNo
=
0
;
int
blkNo
=
0
;
for
(
const
auto
&
b
:
quadEnv
.
blocks
)
{
for
(
const
auto
&
b
:
quadEnv
.
blocks
)
{
buf
<<
"----------------------------------------------------------------------------
\n
"
;
cout
<<
"----------------------------------------------------------------------------
\n
"
;
buf
<<
"blok "
<<
blkNo
<<
" "
<<
b
->
getName
()
<<
endl
;
cout
<<
"blok "
<<
blkNo
<<
" "
<<
b
->
getName
()
<<
endl
;
/*
buf
<< "in: ";
/*
cout
<< "in: ";
for (auto in : b->in) {
for (auto in : b->in) {
buf
<< in->getName() << " ";
cout
<< in->getName() << " ";
}
}
buf
<< "\nouts: ";
cout
<< "\nouts: ";
for (auto out : b->out) {
for (auto out : b->out) {
buf
<< out->getName() << " ";
cout
<< out->getName() << " ";
}
}
buf
<< "\n";*/
cout
<< "\n";*/
if
(
!
b
->
flow
.
in
.
empty
())
{
if
(
!
b
->
flow
.
in
.
empty
())
{
buf
<<
"in: "
;
cout
<<
"in: "
;
for
(
const
auto
&
v
:
b
->
flow
.
in
)
{
for
(
const
auto
&
v
:
b
->
flow
.
in
)
{
buf
<<
v
->
name
<<
", "
;
cout
<<
v
->
name
<<
", "
;
}
}
buf
<<
"
\n
----------
\n
"
;
cout
<<
"
\n
----------
\n
"
;
}
}
if
(
!
b
->
flow
.
def
.
empty
())
{
if
(
!
b
->
flow
.
def
.
empty
())
{
buf
<<
"def: "
;
cout
<<
"def: "
;
for
(
const
auto
&
v
:
b
->
flow
.
def
)
{
for
(
const
auto
&
v
:
b
->
flow
.
def
)
{
buf
<<
v
->
name
<<
", "
;
cout
<<
v
->
name
<<
", "
;
}
}
buf
<<
"
\n
----------
\n
"
;
cout
<<
"
\n
----------
\n
"
;
}
}
for
(
const
auto
&
q
:
b
->
quads
)
{
for
(
const
auto
&
q
:
b
->
quads
)
{
auto
ret
=
q
->
toString
();
auto
ret
=
q
->
toString
();
...
@@ -115,35 +134,49 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
...
@@ -115,35 +134,49 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
if
(
c
==
'\t'
)
len
+=
8
-
(
len
%
8
);
if
(
c
==
'\t'
)
len
+=
8
-
(
len
%
8
);
}
}
for
(;
len
<
70
;
len
++
)
ret
+=
' '
;
for
(;
len
<
70
;
len
++
)
ret
+=
' '
;
buf
<<
ret
<<
" alive: "
;
cout
<<
ret
<<
" alive: "
;
for
(
auto
var
:
q
->
aliveAfter
)
for
(
auto
var
:
q
->
aliveAfter
)
buf
<<
var
->
name
<<
" "
;
cout
<<
var
->
name
<<
" "
;
buf
<<
endl
;
cout
<<
endl
;
cout
<<
"
\x1b
[37;1m"
;
stringstream
asmStr
;
swap
(
asmStr
,
buf
);
q
->
generateAsm
(
*
this
);
q
->
generateAsm
(
*
this
);
swap
(
asmStr
,
buf
);
buf
<<
asmStr
.
str
();
cout
<<
asmStr
.
str
();
cout
<<
"
\x1b
[0m"
;
}
}
}
}
if
(
!
b
->
flow
.
use
.
empty
())
{
if
(
!
b
->
flow
.
use
.
empty
())
{
buf
<<
"----------
\n
use: "
;
cout
<<
"----------
\n
use: "
;
for
(
const
auto
&
v
:
b
->
flow
.
use
)
{
for
(
const
auto
&
v
:
b
->
flow
.
use
)
{
buf
<<
v
->
name
<<
", "
;
cout
<<
v
->
name
<<
", "
;
}
}
buf
<<
"
\n
"
;
cout
<<
"
\n
"
;
}
}
if
(
!
b
->
flow
.
out
.
empty
())
{
if
(
!
b
->
flow
.
out
.
empty
())
{
buf
<<
"----------
\n
out: "
;
cout
<<
"----------
\n
out: "
;
for
(
const
auto
&
v
:
b
->
flow
.
out
)
{
for
(
const
auto
&
v
:
b
->
flow
.
out
)
{
buf
<<
v
->
name
<<
", "
;
cout
<<
v
->
name
<<
", "
;
}
}
buf
<<
"
\n
"
;
cout
<<
"
\n
"
;
}
}
blkNo
++
;
blkNo
++
;
}
}
generateStandardReturn
();
}
}
const
char
*
const
Compiler
::
regs
[
6
]
=
{
"eax"
,
"ebx"
,
"ecx"
,
"edx"
,
"esi"
,
"edi"
};
const
char
*
const
Compiler
::
regs
[
6
]
=
{
"eax"
,
"ebx"
,
"ecx"
,
"edx"
,
"edi"
,
"esi"
};
const
int
Compiler
::
callerSavedRegisters
[
2
]
=
{
2
,
3
};
const
int
Compiler
::
calleeSavedRegisters
[
3
]
=
{
1
,
4
,
5
};
string
Compiler
::
getRef
(
VariablePtr
&
v
)
{
string
Compiler
::
getRef
(
VariablePtr
&
v
)
{
if
(
v
->
registerColor
==
-
1
)
{
if
(
v
->
registerColor
==
-
1
)
{
if
(
v
->
constExpr
)
{
return
"$"
+
to_string
(
v
->
val
);
}
if
(
!
v
->
localOffset
)
{
if
(
!
v
->
localOffset
)
{
if
(
v
->
info
)
{
if
(
v
->
info
)
{
if
(
!
v
->
info
->
localOffset
)
{
if
(
!
v
->
info
->
localOffset
)
{
...
@@ -156,40 +189,50 @@ string Compiler::getRef(VariablePtr &v) {
...
@@ -156,40 +189,50 @@ string Compiler::getRef(VariablePtr &v) {
v
->
localOffset
=
4
*
(
temps
.
size
()
+
localInfos
.
size
());
v
->
localOffset
=
4
*
(
temps
.
size
()
+
localInfos
.
size
());
}
}
}
}
return
to_string
(
v
->
localOffset
)
+
"(%ebp)"
;
return
to_string
(
-
v
->
localOffset
)
+
"(%ebp)"
;
}
else
{
}
else
{
return
Register
(
v
);
return
Register
(
v
);
}
}
}
}
void
Compiler
::
generateQJumpCond
(
QJumpCond
&
q
)
{
// return QJump::generateAsm();
}
void
Compiler
::
generateQAlloc
(
QAlloc
&
q
)
{
void
Compiler
::
generateQAlloc
(
QAlloc
&
q
)
{
// memory = extension
throw
runtime_error
(
"Memory alloc unimplemented!"
);
}
}
void
Compiler
::
generateQWrite
(
QWrite
&
q
)
{
void
Compiler
::
generateQWrite
(
QWrite
&
q
)
{
// return Quadruple::generateAsm();
// memory = extension
throw
runtime_error
(
"Memory write unimplemented!"
);
}
}
void
Compiler
::
generateQAccess
(
QAccess
&
q
)
{
void
Compiler
::
generateQAccess
(
QAccess
&
q
)
{
// return Quadruple::generateAsm();
// memory = extension
throw
runtime_error
(
"Memory access unimplemented!"
);
}
}
void
Compiler
::
generateQReturn
(
QReturn
&
q
)
{
void
Compiler
::
generateQReturn
(
QReturn
&
q
)
{
// return Quadruple::generateAsm();
if
(
q
.
val
)
moveTo
(
q
.
val
,
0
);
append
(
"JMP"
,
"
\"
"
+
exitLabel
->
label
+
"
\"
"
);
}
}
void
Compiler
::
generateQCall
(
QCall
&
q
)
{
void
Compiler
::
generateQCall
(
QCall
&
q
)
{
// return Quadruple::generateAsm();
// return Quadruple::generateAsm();
if
(
q
.
self
)
{
throw
runtime_error
(
"Class call unimplemented!"
);
}
append
(
"CALL"
,
"
\"
"
+
mangleFunctionName
(
q
.
fn
)
+
"
\"
"
);
if
(
q
.
params
)
{
append
(
"ADDL"
,
"$"
+
to_string
(
q
.
params
*
4
),
"%esp"
);
}
auto
popRegs
=
registersToSave
(
q
);
for
(
auto
r
=
popRegs
.
rbegin
();
r
!=
popRegs
.
rend
();
r
++
)
{
append
(
"POPL"
,
*
r
);
}
if
(
q
.
aliveAfter
.
count
(
q
.
loc
))
{
moveTo
(
0
,
q
.
loc
);
}
}
}
void
Compiler
::
generateQParam
(
QParam
&
q
)
{
void
Compiler
::
generateQParam
(
QParam
&
q
)
{
...
@@ -200,20 +243,66 @@ void Compiler::generateQParam(QParam &q) {
...
@@ -200,20 +243,66 @@ void Compiler::generateQParam(QParam &q) {
if
(
reg
==
0
)
{
if
(
reg
==
0
)
{
q
.
param
->
localOffset
=
offset
;
q
.
param
->
localOffset
=
offset
;
}
else
{
}
else
{
append
(
"MOVL"
,
to_string
(
offset
)
+
"(%ebp)"
);
append
(
"MOVL"
,
to_string
(
-
offset
)
+
"(%ebp)"
,
reg
);
}
}
}
else
{
}
else
{
if
(
q
.
num
==
1
&&
q
.
call
)
{
// first argument, need to save registers
for
(
auto
r
:
registersToSave
(
*
q
.
call
))
{
append
(
"PUSHL"
,
r
);
}
}
append
(
"PUSHL"
,
getRef
(
q
.
param
));
append
(
"PUSHL"
,
getRef
(
q
.
param
));
}
}
}
}
void
Compiler
::
generateQJump
(
QJump
&
q
)
{
void
Compiler
::
generateQJump
(
QJump
&
q
)
{
// return Quadruple::generateAsm();
// return Quadruple::generateAsm();
// append("JMP", q.block.la)
append
(
"JMP"
,
getBlockLabelText
(
q
.
target
));
}
void
Compiler
::
generateQJumpCond
(
QJumpCond
&
q
)
{
auto
op
=
q
.
op
;
if
(
q
.
left
)
{
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
);
if
(
op
.
kind
()
==
Op
::
CMP
&&
op
!=
Op
::
EQ
&&
op
!=
Op
::
NEQ
)
op
=
op
.
neg
();
}
append
(
"CMP"
,
locL
,
locR
);
}
else
{
if
(
q
.
right
->
constExpr
)
{
if
((
op
==
Op
::
Not
)
^
q
.
right
->
val
)
{
generateQJump
(
q
);
}
return
;
}
auto
tg
=
moveToAnyRegister
(
q
.
right
);
append
(
"CMP"
,
tg
,
tg
);
}
if
(
op
.
kind
()
!=
Op
::
CMP
&&
op
.
kind
()
!=
Op
::
UNARY
)
throw
runtime_error
(
"Unexpected operator in compare"
);
string
operand
=
getOpName
(
op
);
// getOpName returns SETZ, SETNE, SET*, replace it to JMP
operand
.
replace
(
0
,
3
,
"J"
);
// if (operand == "SETZ" || operand == "SETNZ") {
//
// } else {
// operand.replace(0,3, "JMP");
// }
append
(
operand
,
getBlockLabelText
(
q
.
target
));
}
}
void
Compiler
::
generateQAssign
(
QAssign
&
q
)
{
void
Compiler
::
generateQAssign
(
QAssign
&
q
)
{
if
(
!
q
.
aliveAfter
.
count
(
q
.
loc
))
return
;
Register
tg
(
q
.
loc
);
Register
tg
(
q
.
loc
);
if
(
q
.
args
.
size
()
==
1
)
{
if
(
q
.
args
.
size
()
==
1
)
{
auto
&
arg
=
q
.
args
[
0
];
auto
&
arg
=
q
.
args
[
0
];
...
@@ -231,7 +320,8 @@ void Compiler::generateQAssign(QAssign &q) {
...
@@ -231,7 +320,8 @@ void Compiler::generateQAssign(QAssign &q) {
}
}
case
Op
:
:
Copy
:
{
case
Op
:
:
Copy
:
{
if
(
arg
->
constExpr
)
{
if
(
arg
->
constExpr
)
{
// TODO
append
(
"MOVL"
,
"$"
+
to_string
(
arg
->
val
),
getRef
(
q
.
loc
));
return
;
}
else
{
}
else
{
moveTo
(
arg
,
tg
);
moveTo
(
arg
,
tg
);
}
}
...
@@ -248,20 +338,23 @@ void Compiler::generateQAssign(QAssign &q) {
...
@@ -248,20 +338,23 @@ void Compiler::generateQAssign(QAssign &q) {
auto
&
i
=
q
.
args
[
0
],
&
j
=
q
.
args
[
1
];
auto
&
i
=
q
.
args
[
0
],
&
j
=
q
.
args
[
1
];
if
(
q
.
op
==
Op
::
Div
||
q
.
op
==
Op
::
Mod
)
{
if
(
q
.
op
==
Op
::
Div
||
q
.
op
==
Op
::
Mod
)
{
auto
edx
=
Register
(
"edx"
);
auto
edx
=
Register
(
"edx"
);
bool
backupEdx
=
edx
!=
tg
&&
edx
!=
Register
(
i
);
bool
edxAlive
=
false
;
if
(
backupEdx
)
append
(
"MOVL"
,
edx
,
"4(%esp)"
);
for
(
auto
&
alive
:
q
.
aliveAfter
)
auto
jLoc
=
edx
!=
Register
(
j
)
?
getRef
(
j
)
:
"4(%esp)"
;
if
(
Register
(
alive
)
==
edx
)
{
edxAlive
=
true
;
}
bool
backupEdx
=
edx
!=
tg
&&
edx
!=
Register
(
i
)
&&
(
edx
==
Register
(
j
)
||
edxAlive
);
if
(
backupEdx
)
append
(
"MOVL"
,
edx
,
"-4(%esp)"
);
auto
jLoc
=
edx
!=
Register
(
j
)
?
getRef
(
j
)
:
"-4(%esp)"
;
moveTo
(
i
,
0
);
moveTo
(
i
,
0
);
append
(
"CLTD"
);
// edx lost
append
(
"CLTD"
);
// edx lost
append
(
"IDIVL"
,
jLoc
);
append
(
"IDIVL"
,
jLoc
);
moveTo
(
q
.
op
==
Op
::
Mod
?
edx
:
0
,
getRef
(
q
.
loc
));
append
(
"MOVL"
,
q
.
op
==
Op
::
Mod
?
edx
:
0
,
getRef
(
q
.
loc
));
// restore unnecessary if j was in edx and becomes dead and was NOT coalesced
// restore unnecessary if j was in edx and becomes dead and was NOT coalesced
if
(
backupEdx
)
append
(
"MOVL"
,
"4(%esp)"
,
edx
);
// not easy to check if not coalesced, so move anyway
if
(
backupEdx
&&
edxAlive
)
append
(
"MOVL"
,
"-4(%esp)"
,
edx
);
return
;
return
;
}
else
if
(
q
.
op
<
Op
::
CMP
)
{
}
else
if
(
q
.
op
.
kind
()
==
Op
::
CMP
)
{
moveTo
(
i
,
tg
);
append
(
q
.
op
,
getRef
(
i
),
tg
);
}
else
{
auto
loc
=
getRef
(
i
);
auto
loc
=
getRef
(
i
);
if
(
Register
(
i
)
==
0
&&
Register
(
j
)
==
0
)
{
if
(
Register
(
i
)
==
0
&&
Register
(
j
)
==
0
)
{
moveTo
(
i
,
0
);
moveTo
(
i
,
0
);
...
@@ -270,6 +363,19 @@ void Compiler::generateQAssign(QAssign &q) {
...
@@ -270,6 +363,19 @@ void Compiler::generateQAssign(QAssign &q) {
append
(
"CMPL"
,
loc
,
getRef
(
j
));
append
(
"CMPL"
,
loc
,
getRef
(
j
));
append
(
q
.
op
,
tg
);
append
(
q
.
op
,
tg
);
}
else
{
assert
(
q
.
op
.
kind
()
==
Op
::
BINARY
);
bool
swapped
=
false
;
if
(
Register
(
j
)
==
tg
&&
tg
!=
0
)
{
swapped
=
true
;
swap
(
i
,
j
);
}
moveTo
(
i
,
tg
);
append
(
q
.
op
,
getRef
(
j
),
tg
);
if
(
swapped
)
{
if
(
q
.
op
==
Op
::
Minus
)
append
(
"NEG"
,
tg
);
}
}
}
}
}
if
(
tg
==
0
)
{
if
(
tg
==
0
)
{
...
@@ -278,6 +384,5 @@ void Compiler::generateQAssign(QAssign &q) {
...
@@ -278,6 +384,5 @@ void Compiler::generateQAssign(QAssign &q) {
}
}
void
Compiler
::
generateQLabel
(
QLabel
&
q
)
{
void
Compiler
::
generateQLabel
(
QLabel
&
q
)
{
// return Quadruple::generateAsm();
buf
<<
"
\"
"
<<
q
.
label
<<
"
\"
:"
<<
endl
;
}
}
src/Compiler.h
View file @
459ffddf
...
@@ -38,6 +38,13 @@ public:
...
@@ -38,6 +38,13 @@ public:
void
generateQJump
(
QJump
&
q
);
void
generateQJump
(
QJump
&
q
);
void
generateQAssign
(
QAssign
&
q
);
void
generateQAssign
(
QAssign
&
q
);
void
generateQLabel
(
QLabel
&
q
);
void
generateQLabel
(
QLabel
&
q
);
static
std
::
string
mangleFunctionName
(
const
FunctionInfoPtr
&
f
)
{
if
(
auto
c
=
f
->
klass
.
lock
())
{
return
c
->
name
+
"::"
+
f
->
name
;
}
return
f
->
name
;
}
private:
private:
std
::
filesystem
::
path
file
;
std
::
filesystem
::
path
file
;
std
::
stringstream
buf
;
std
::
stringstream
buf
;
...
@@ -52,7 +59,14 @@ private:
...
@@ -52,7 +59,14 @@ private:
class
Register
{
class
Register
{
public:
public:
Register
(
string
n
)
:
name
(
std
::
move
(
n
))
{};
Register
(
string
n
)
:
name
(
n
)
{
for
(
auto
reg
:
Compiler
::
regs
)
{
if
(
name
==
reg
)
{
return
;
}
}
throw
runtime_error
(
"Invalid register name"
);
};
Register
(
int
n
)
{
name
=
Compiler
::
regs
[
n
];
}
Register
(
int
n
)
{
name
=
Compiler
::
regs
[
n
];
}
Register
(
const
VariablePtr
&
v
)
{
name
=
Compiler
::
regs
[
v
->
registerColor
+
1
];
}
Register
(
const
VariablePtr
&
v
)
{
name
=
Compiler
::
regs
[
v
->
registerColor
+
1
];
}
string
name
;
string
name
;
...
@@ -61,16 +75,12 @@ private:
...
@@ -61,16 +75,12 @@ private:
bool
operator
!=
(
const
Register
&
other
)
const
{
return
name
!=
other
.
name
;
}
bool
operator
!=
(
const
Register
&
other
)
const
{
return
name
!=
other
.
name
;
}
};
};
static
std
::
string
mangleFunctionName
(
const
FunctionInfoPtr
&
f
)
{
if
(
auto
c
=
f
->
klass
.
lock
())
{
return
c
->
name
+
"::"
+
f
->
name
;
}
return
f
->
name
;
}
string
getRef
(
VariablePtr
&
v
);
string
getRef
(
VariablePtr
&
v
);
static
const
char
*
const
regs
[
6
];
static
const
char
*
const
regs
[
6
];
static
const
int
callerSavedRegisters
[
2
];
static
const
int
calleeSavedRegisters
[
3
];
static
string
getOpName
(
Quadruple
::
Op
op
)
{
static
string
getOpName
(
Quadruple
::
Op
op
)
{
switch
(
op
.
op
)
{
switch
(
op
.
op
)
{
...
@@ -79,10 +89,12 @@ private:
...
@@ -79,10 +89,12 @@ private:
case
Op
:
:
Mul
:
return
"IMULL"
;
case
Op
:
:
Mul
:
return
"IMULL"
;
case
Op
:
:
Div
:
case
Op
:
:
Div
:
case
Op
:
:
Mod
:
throw
runtime_error
(
"Impossible to handle division with default"
);
case
Op
:
:
Mod
:
throw
runtime_error
(
"Impossible to handle division with default"
);
case
Op
:
:
Not
:
return
"SETZ"
;
case
Op
:
:
Copy
:
return
"SETNZ"
;
case
Op
:
:
LT
:
return
"SETL"
;
case
Op
:
:
LT
:
return
"SETL"
;
case
Op
:
:
LE
:
return
"SETLE"
;
case
Op
:
:
LE
:
return
"SETLE"
;
case
Op
:
:
EQ
:
return
"SET
E
"
;
case
Op
:
:
EQ
:
return
"SET
Z
"
;
case
Op
:
:
NEQ
:
return
"SETN
E
"
;
case
Op
:
:
NEQ
:
return
"SETN
Z
"
;
case
Op
:
:
GE
:
return
"SETGE"
;
case
Op
:
:
GE
:
return
"SETGE"
;
case
Op
:
:
GT
:
return
"SETG"
;
case
Op
:
:
GT
:
return
"SETG"
;
default:
return
"Op"
+
to_string
(
op
.
op
)
+
"?"
;
default:
return
"Op"
+
to_string
(
op
.
op
)
+
"?"
;
...
@@ -121,7 +133,57 @@ private:
...
@@ -121,7 +133,57 @@ private:
}
}
void
append
(
string
cmd
,
string
op1
=
""
,
string
op2
=
""
,
string
op3
=
""
)
{
void
append
(
string
cmd
,
string
op1
=
""
,
string
op2
=
""
,
string
op3
=
""
)
{
buf
<<
"
\t
"
<<
cmd
<<
" "
<<
op1
<<
" "
<<
op2
<<
" "
<<
op3
<<
endl
;
append
({
cmd
,
op1
,
op2
,
op3
});
}
void
append
(
vector
<
string
>
ops
)
{
static
const
char
*
const
delimiters
=
"
\t
,,,,"
;
assert
(
ops
.
size
()
<
6
);
while
(
ops
.
size
()
&&
ops
.
back
().
empty
())
ops
.
pop_back
();
buf
<<
"
\t
"
;
for
(
uint
i
=
0
;
i
<
ops
.
size
();
i
++
)
{
buf
<<
delimiters
[
i
]
<<
ops
[
i
];
}
buf
<<
endl
;
}
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
"
\"
"
+
n
+
"
\"
"
;
}
shared_ptr
<
QLabel
>
exitLabel
;
void
generateStandardReturn
()
{
append
(
"JMP"
,
"
\"
"
+
exitLabel
->
label
+
"
\"
"
);
}
vector
<
Register
>
registersToSave
(
QCall
&
q
)
{
const
int
noRegs
=
sizeof
(
callerSavedRegisters
)
/
sizeof
(
*
callerSavedRegisters
);
bool
saved
[
noRegs
];
int
notSaved
=
noRegs
;
for
(
auto
&
i
:
saved
)
i
=
false
;
for
(
auto
&
live
:
q
.
aliveAfter
)
{
for
(
int
i
=
0
;
i
<
noRegs
;
i
++
)
{
int
r
=
callerSavedRegisters
[
i
];
if
(
!
saved
[
i
]
&&
Register
(
live
)
==
Register
(
r
))
{
saved
[
i
]
=
true
;
--
notSaved
;
}
}
if
(
notSaved
==
0
)
break
;
}
vector
<
Register
>
ret
;
for
(
int
i
=
0
;
i
<
noRegs
;
i
++
)
{
if
(
saved
[
i
])
ret
.
emplace_back
(
callerSavedRegisters
[
i
]);
}
return
ret
;
}
}
};
};
...
...
src/codeGen/BasicBlock.h
View file @
459ffddf
...
@@ -50,7 +50,7 @@ public:
...
@@ -50,7 +50,7 @@ public:
void
addPhi
(
const
BasicBlockPtr
&
blk
,
const
VariablePtr
&
local
,
VariablePtr
remote
)
{
void
addPhi
(
const
BasicBlockPtr
&
blk
,
const
VariablePtr
&
local
,
VariablePtr
remote
)
{
assert
(
blk
&&
local
&&
remote
);
assert
(
blk
&&
local
&&
remote
);
assert
(
local
->
info
&&
!
local
->
info
->
isInstanceVariable
());
assert
(
!
local
->
info
||
!
local
->
info
->
isInstanceVariable
());
auto
&
phiMap
=
findPhi
(
blk
);
auto
&
phiMap
=
findPhi
(
blk
);
phiMap
[
local
]
=
std
::
move
(
remote
);
phiMap
[
local
]
=
std
::
move
(
remote
);
}
}
...
...
src/codeGen/Quadruple.h
View file @
459ffddf
...
@@ -9,9 +9,9 @@
...
@@ -9,9 +9,9 @@
using
namespace
std
;
using
namespace
std
;
class
Compiler
;
class
Compiler
;
static
const
std
::
string
opNames
[]
=
{
"_U"
,
"
-"
,
"!"
,
"
"
,
"_UE"
,
static
const
std
::
string
opNames
[]
=
{
"_U"
,
"
!"
,
""
,
"-
"
,
"_UE"
,
"_B"
,
"+"
,
"-"
,
"*"
,
"/"
,
"%"
,
"&"
,
"|"
,
"^"
,
"_BE"
,
"_B"
,
"+"
,
"-"
,
"*"
,
"/"
,
"%"
,
"&"
,
"|"
,
"^"
,
"_BE"
,
"_C"
,
"<"
,
"
<="
,
"=="
,
"!="
,
">="
,
">
"
,
"_CE"
};
"_C"
,
"<"
,
"
>="
,
"<="
,
">"
,
"=="
,
"!=
"
,
"_CE"
};
class
Quadruple
:
public
enable_shared_from_this
<
Quadruple
>
{
class
Quadruple
:
public
enable_shared_from_this
<
Quadruple
>
{
public:
public:
...
@@ -19,22 +19,35 @@ public:
...
@@ -19,22 +19,35 @@ public:
public:
public:
enum
OpType
{
enum
OpType
{
UNARY
,
UNARY
,
N
eg
,
Not
,
Copy
,
UNARY_END
,
N
ot
,
Copy
,
Neg
,
UNARY_END
,
BINARY
,
BINARY
,
Plus
,
Minus
,
Mul
,
Div
,
Mod
,
And
,
Or
,
Xor
,
BINARY_END
,
Plus
,
Minus
,
Mul
,
Div
,
Mod
,
And
,
Or
,
Xor
,
BINARY_END
,
CMP
,
CMP
,
LT
,
LE
,
EQ
,
NEQ
,
GE
,
GT
,
CMP_END
LT
,
GE
,
LE
,
GT
,
EQ
,
NEQ
,
CMP_END
};
};
OpType
op
;
OpType
op
;
Op
(
OpType
op
=
UNARY
)
:
op
(
op
)
{};
Op
(
OpType
op
=
UNARY
)
:
op
(
op
)
{};
operator
OpType
()
const
{
return
op
;
};
operator
OpType
()
const
{
return
op
;
};
Op
neg
()
const
{
if
(
op
<=
Op
::
Copy
)
return
OpType
(
UNARY
+
1
+
((
int
)(
op
-
UNARY
-
1
)
^
1
));
if
(
op
>
Op
::
CMP
)
return
OpType
(
CMP
+
1
+
((
int
)(
op
-
CMP
-
1
)
^
1
));
throw
runtime_error
(
"Invalid argument to Op::neg()"
);
};
static
OpType
kind
(
OpType
op
)
{
static
OpType
kind
(
OpType
op
)
{
if
(
op
<=
UNARY_END
)
return
UNARY
;
if
(
op
<=
UNARY_END
)
return
UNARY
;
if
(
op
<=
BINARY_END
)
return
BINARY
;
if
(
op
<=
BINARY_END
)
return
BINARY
;
return
CMP
;
return
CMP
;
};
};
OpType
kind
()
const
{
return
Op
::
kind
(
*
this
);
};
static
const
std
::
string
&
name
(
OpType
op
)
{
static
const
std
::
string
&
name
(
OpType
op
)
{
return
opNames
[
op
];
return
opNames
[
op
];
}
}
...
@@ -71,7 +84,7 @@ public:
...
@@ -71,7 +84,7 @@ public:
std
::
string
toString
()
const
override
{
return
Quadruple
::
toString
()
+
"
\t
"
+
(
loc
?
(
loc
->
name
+
" := "
)
:
""
);
}
std
::
string
toString
()
const
override
{
return
Quadruple
::
toString
()
+
"
\t
"
+
(
loc
?
(
loc
->
name
+
" := "
)
:
""
);
}
vector
<
VariablePtr
>
definitions
()
const
override
{
vector
<
VariablePtr
>
definitions
()
const
override
{
auto
ret
=
Quadruple
::
definitions
();
auto
ret
=
Quadruple
::
definitions
();
if
(
loc
)
ret
.
emplace_back
(
loc
);
if
(
loc
&&
!
loc
->
constExpr
)
ret
.
emplace_back
(
loc
);
return
ret
;
return
ret
;
};
};
};
};
...
@@ -147,13 +160,16 @@ public:
...
@@ -147,13 +160,16 @@ public:
}
}
void
generateAsm
(
Compiler
&
c
)
override
;
void
generateAsm
(
Compiler
&
c
)
override
;
};
};
class
QCall
;
class
QParam
:
public
Quadruple
{
class
QParam
:
public
Quadruple
{
public:
public:
VariablePtr
param
;
VariablePtr
param
;
int
num
;
int
num
;
QParam
(
VariablePtr
param
,
int
num
)
:
param
(
std
::
move
(
param
)),
num
(
num
)
{};
shared_ptr
<
QCall
>
call
;
QParam
(
VariablePtr
param
,
int
num
,
shared_ptr
<
QCall
>
call
=
nullptr
)
:
param
(
std
::
move
(
param
)),
num
(
num
),
call
(
std
::
move
(
call
))
{};
std
::
string
toString
()
const
override
{
std
::
string
toString
()
const
override
{
if
(
num
<
0
)
{
if
(
num
<
0
)
{
...
...
src/codeGen/QuadrupleGenerator.cpp
View file @
459ffddf
...
@@ -46,10 +46,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
...
@@ -46,10 +46,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
for
(
const
auto
&
q
:
b
->
quads
)
{
for
(
const
auto
&
q
:
b
->
quads
)
{
q
->
index
=
index
++
;
q
->
index
=
index
++
;
if
(
auto
l
=
dynamic_pointer_cast
<
QLabel
>
(
q
))
{
if
(
auto
l
=
dynamic_pointer_cast
<
QLabel
>
(
q
))
{
if
(
!
l
->
label
.
empty
())
auto
old
=
l
->
label
;
l
->
label
=
to_string
(
label
++
)
+
"_"
+
l
->
label
;
l
->
label
=
"."
+
to_string
(
label
++
)
+
"_"
+
Compiler
::
mangleFunctionName
(
f
)
;
else
if
(
!
old
.
empty
())
l
->
label
=
to_string
(
label
++
)
;
l
->
label
+=
"_"
+
old
;
}
}
}
}
}
}
...
@@ -109,10 +109,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) {
...
@@ -109,10 +109,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) {
void
QuadrupleGenerator
::
visitELitTrue
(
ELitTrue
*
p
)
{
void
QuadrupleGenerator
::
visitELitTrue
(
ELitTrue
*
p
)
{
lastVar
=
alloc
(
1
);
lastVar
=
alloc
(
1
);
if
(
labelTrue
)
addQuad
<
QJump
>
(
labelTrue
);
}
}
void
QuadrupleGenerator
::
visitELitFalse
(
ELitFalse
*
p
)
{
void
QuadrupleGenerator
::
visitELitFalse
(
ELitFalse
*
p
)
{
lastVar
=
alloc
(
0
);
lastVar
=
alloc
(
0
);
if
(
labelFalse
)
addQuad
<
QJump
>
(
labelFalse
);
}
}
void
QuadrupleGenerator
::
visitEString
(
EString
*
p
)
{
void
QuadrupleGenerator
::
visitEString
(
EString
*
p
)
{
...
@@ -128,12 +130,20 @@ void QuadrupleGenerator::visitNeg(Neg *p) {
...
@@ -128,12 +130,20 @@ void QuadrupleGenerator::visitNeg(Neg *p) {
auto
var
=
evalExpr
(
p
->
expr_
);
auto
var
=
evalExpr
(
p
->
expr_
);
lastVar
=
alloc
();
lastVar
=
alloc
();
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Neg
,
var
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Neg
,
var
);
if
((
lastVar
->
constExpr
=
var
->
constExpr
))
{
lastVar
->
val
=
-
var
->
val
;
}
}
}
void
QuadrupleGenerator
::
visitNot
(
Not
*
p
)
{
void
QuadrupleGenerator
::
visitNot
(
Not
*
p
)
{
swap
(
labelTrue
,
labelFalse
);
auto
var
=
evalExpr
(
p
->
expr_
);
auto
var
=
evalExpr
(
p
->
expr_
);
swap
(
labelTrue
,
labelFalse
);
lastVar
=
alloc
();
lastVar
=
alloc
();
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Not
,
var
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Not
,
var
);
if
((
lastVar
->
constExpr
=
var
->
constExpr
))
{
lastVar
->
val
=
!
var
->
val
;
}
}
}
void
QuadrupleGenerator
::
visitEMul
(
EMul
*
p
)
{
void
QuadrupleGenerator
::
visitEMul
(
EMul
*
p
)
{
...
@@ -142,6 +152,16 @@ void QuadrupleGenerator::visitEMul(EMul *p) {
...
@@ -142,6 +152,16 @@ void QuadrupleGenerator::visitEMul(EMul *p) {
lastVar
=
alloc
();
lastVar
=
alloc
();
p
->
mulop_
->
accept
(
this
);
p
->
mulop_
->
accept
(
this
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
if
((
lastVar
->
constExpr
=
l
->
constExpr
&&
r
->
constExpr
))
{
if
(
op
==
Op
::
Mul
)
lastVar
->
val
=
l
->
val
*
r
->
val
;
else
if
(
r
->
val
==
0
)
throw
ParseError
(
"Division by 0"
,
p
);
else
if
(
op
==
Op
::
Div
)
lastVar
->
val
=
l
->
val
/
r
->
val
;
else
if
(
op
==
Op
::
Mod
)
lastVar
->
val
=
l
->
val
%
r
->
val
;
}
}
}
void
QuadrupleGenerator
::
visitEAdd
(
EAdd
*
p
)
{
void
QuadrupleGenerator
::
visitEAdd
(
EAdd
*
p
)
{
...
@@ -150,48 +170,120 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
...
@@ -150,48 +170,120 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
lastVar
=
alloc
();
lastVar
=
alloc
();
p
->
addop_
->
accept
(
this
);
p
->
addop_
->
accept
(
this
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
if
((
lastVar
->
constExpr
=
l
->
constExpr
&&
r
->
constExpr
))
{
if
(
op
==
Op
::
Minus
)
lastVar
->
val
=
l
->
val
-
r
->
val
;
else
if
(
op
==
Op
::
Plus
)
lastVar
->
val
=
l
->
val
+
r
->
val
;
}
}
}
void
QuadrupleGenerator
::
visitERel
(
ERel
*
p
)
{
void
QuadrupleGenerator
::
visitERel
(
ERel
*
p
)
{
auto
l
=
eval
Expr
(
p
->
expr_1
);
auto
l
=
eval
Jump
(
p
->
expr_1
,
nullptr
,
nullptr
);
auto
r
=
eval
Expr
(
p
->
expr_2
);
auto
r
=
eval
Jump
(
p
->
expr_2
,
nullptr
,
nullptr
);
lastVar
=
alloc
();
lastVar
=
alloc
();
p
->
relop_
->
accept
(
this
);
p
->
relop_
->
accept
(
this
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
if
((
lastVar
->
constExpr
=
l
->
constExpr
&&
r
->
constExpr
))
{
if
(
op
==
Op
::
LT
)
lastVar
->
val
=
l
->
val
<
r
->
val
;
else
if
(
op
==
Op
::
LE
)
lastVar
->
val
=
l
->
val
<=
r
->
val
;
else
if
(
op
==
Op
::
EQ
)
lastVar
->
val
=
l
->
val
==
r
->
val
;
else
if
(
op
==
Op
::
NEQ
)
lastVar
->
val
=
l
->
val
!=
r
->
val
;
else
if
(
op
==
Op
::
GE
)
lastVar
->
val
=
l
->
val
>=
r
->
val
;
else
if
(
op
==
Op
::
GT
)
lastVar
->
val
=
l
->
val
>
r
->
val
;
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
}
addLastVarCondJump
(
l
,
op
,
r
);
}
}
void
QuadrupleGenerator
::
visitEAnd
(
EAnd
*
p
)
{
void
QuadrupleGenerator
::
visitEAnd
(
EAnd
*
p
)
{
auto
l
=
evalExpr
(
p
->
expr_1
);
auto
labelAfter
=
make_shared
<
QLabel
>
(
"and_else"
);
auto
labelLeft
=
make_shared
<
QLabel
>
(
"use_left"
);
auto
l
=
evalJump
(
p
->
expr_1
,
nullptr
,
labelFalse
);
auto
labelAfter
=
make_shared
<
QLabel
>
(
"end_and"
);
if
(
!
l
)
return
;
if
(
l
->
constExpr
)
{
addQuad
<
QJumpCond
>
(
labelLeft
,
Op
::
Not
,
l
);
lastVar
=
l
->
val
?
evalJump
(
p
->
expr_2
,
labelTrue
,
labelFalse
)
:
l
;
auto
r
=
evalExpr
(
p
->
expr_2
);
// jest git skoczymy pozniej bo to constexpr
lastVar
=
alloc
();
return
;
}
else
{
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
r
);
auto
leftValBlock
=
block
;
addQuad
<
QJump
>
(
labelAfter
);
auto
llq
=
make_shared
<
QJumpCond
>
(
labelFalse
?
labelFalse
:
labelAfter
,
Op
::
Not
,
l
);
addQuad
(
labelLeft
);
addQuad
(
llq
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
alloc
(
0
));
flushBasicBlock
();
addQuad
(
labelAfter
);
leftValBlock
->
append
(
block
);
auto
r
=
evalJump
(
p
->
expr_2
,
labelTrue
,
labelFalse
);
if
(
!
r
||
r
->
constExpr
)
{
assert
(
leftValBlock
->
quads
.
back
()
==
llq
);
leftValBlock
->
quads
.
pop_back
();
// could merge basic blocks now, but why bother
if
(
r
)
{
lastVar
=
r
->
val
?
l
:
r
;
}
}
else
{
auto
rightValBlock
=
block
;
flushBasicBlock
();
addQuad
(
labelAfter
);
rightValBlock
->
append
(
block
);
leftValBlock
->
append
(
block
);
if
(
!
labelTrue
||
!
labelFalse
)
{
lastVar
=
alloc
();
block
->
addPhi
(
rightValBlock
,
lastVar
,
r
);
block
->
addPhi
(
leftValBlock
,
lastVar
,
l
);
}
else
{
lastVar
=
nullptr
;
}
}
}
}
}
void
QuadrupleGenerator
::
visitEOr
(
EOr
*
p
)
{
void
QuadrupleGenerator
::
visitEOr
(
EOr
*
p
)
{
auto
l
=
evalExpr
(
p
->
expr_1
);
auto
labelAfter
=
make_shared
<
QLabel
>
(
"or_else"
);
auto
labelLeft
=
make_shared
<
QLabel
>
(
"use_left"
);
auto
l
=
evalJump
(
p
->
expr_1
,
labelTrue
,
nullptr
);
auto
labelAfter
=
make_shared
<
QLabel
>
(
"end_or"
);
if
(
!
l
)
return
;
if
(
l
->
constExpr
)
{
addQuad
<
QJumpCond
>
(
labelLeft
,
Op
::
Copy
,
l
);
lastVar
=
l
->
val
?
l
:
evalJump
(
p
->
expr_2
,
labelTrue
,
labelFalse
);
// jest git skoczymy pozniej bo to constexpr
auto
r
=
evalExpr
(
p
->
expr_2
);
return
;
lastVar
=
alloc
();
}
else
{
auto
leftValBlock
=
block
;
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
r
);
auto
llq
=
make_shared
<
QJumpCond
>
(
labelTrue
?
labelTrue
:
labelAfter
,
Op
::
Copy
,
l
);
addQuad
<
QJump
>
(
labelAfter
);
addQuad
(
llq
);
addQuad
(
labelLeft
);
flushBasicBlock
();
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
alloc
(
1
));
leftValBlock
->
append
(
block
);
addQuad
(
labelAfter
);
auto
r
=
evalExpr
(
p
->
expr_2
);
if
(
!
r
)
return
;
if
(
r
->
constExpr
)
{
assert
(
leftValBlock
->
quads
.
back
()
==
llq
);
leftValBlock
->
quads
.
pop_back
();
// could merge basic blocks now, but why bother
lastVar
=
r
->
val
?
r
:
l
;
}
else
{
auto
rightValBlock
=
block
;
flushBasicBlock
();
addQuad
(
labelAfter
);
rightValBlock
->
append
(
block
);
leftValBlock
->
append
(
block
);
if
(
!
labelTrue
||
!
labelFalse
)
{
lastVar
=
alloc
();
block
->
addPhi
(
rightValBlock
,
lastVar
,
r
);
block
->
addPhi
(
leftValBlock
,
lastVar
,
l
);
}
else
{
lastVar
=
nullptr
;
}
}
}
}
}
/// complex extensions
/// complex extensions
...
@@ -219,6 +311,10 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
...
@@ -219,6 +311,10 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
}
}
auto
quad
=
make_shared
<
QAccess
>
(
lastVar
,
lhs
,
index
,
4
,
0
);
auto
quad
=
make_shared
<
QAccess
>
(
lastVar
,
lhs
,
index
,
4
,
0
);
addQuad
(
quad
);
addQuad
(
quad
);
Bool
b
;
if
(
type
->
type_
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
}
}
}
void
QuadrupleGenerator
::
visitEClsMmbr
(
EClsMmbr
*
p
)
{
void
QuadrupleGenerator
::
visitEClsMmbr
(
EClsMmbr
*
p
)
{
...
@@ -240,6 +336,10 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
...
@@ -240,6 +336,10 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
auto
quad
=
make_shared
<
QAccess
>
(
lastVar
,
l
,
nullptr
,
0
,
offset
);
auto
quad
=
make_shared
<
QAccess
>
(
lastVar
,
l
,
nullptr
,
0
,
offset
);
addQuad
(
quad
);
addQuad
(
quad
);
}
}
Bool
b
;
if
(
var
->
type
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
}
}
}
void
QuadrupleGenerator
::
visitEApp
(
EApp
*
p
)
{
void
QuadrupleGenerator
::
visitEApp
(
EApp
*
p
)
{
...
@@ -270,18 +370,24 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
...
@@ -270,18 +370,24 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
throw
ParseError
(
"Unimplemented EApp instantiation (neither EClsMmbr nor EVar"
,
p
);
throw
ParseError
(
"Unimplemented EApp instantiation (neither EClsMmbr nor EVar"
,
p
);
}
}
int
i
=
1
;
auto
call
=
make_shared
<
QCall
>
(
lastVar
,
info
,
p
->
listexpr_
->
size
(),
self
);
int
i
=
0
;
for
(
auto
param
:
*
p
->
listexpr_
)
{
for
(
auto
param
:
*
p
->
listexpr_
)
{
auto
var
=
evalExpr
(
param
);
auto
var
=
evalExpr
(
param
);
addQuad
<
QParam
>
(
var
,
i
++
);
addQuad
<
QParam
>
(
var
,
++
i
,
call
);
}
}
if
(
self
)
{
if
(
self
)
{
addQuad
<
QParam
>
(
self
,
0
);
addQuad
<
QParam
>
(
self
,
0
,
call
);
}
}
lastVar
=
alloc
();
lastVar
=
alloc
();
addQuad
<
QCall
>
(
lastVar
,
info
,
i
,
self
);
addQuad
(
call
);
Bool
b
;
if
(
info
->
type
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
}
}
}
void
QuadrupleGenerator
::
visitENewArray
(
ENewArray
*
p
)
{
void
QuadrupleGenerator
::
visitENewArray
(
ENewArray
*
p
)
{
...
@@ -387,17 +493,16 @@ void QuadrupleGenerator::visitCondElse(CondElse *p) {
...
@@ -387,17 +493,16 @@ void QuadrupleGenerator::visitCondElse(CondElse *p) {
}
}
void
QuadrupleGenerator
::
compileCond
(
Expr
*
expr_
,
Stmt
*
stmt_1
,
Stmt
*
stmt_2
)
{
void
QuadrupleGenerator
::
compileCond
(
Expr
*
expr_
,
Stmt
*
stmt_1
,
Stmt
*
stmt_2
)
{
// TODO: stmty nie składają się z jednego bloku tylko z wielu
auto
elseBranch
=
make_shared
<
QLabel
>
(
"if_else"
);
auto
elseBranch
=
make_shared
<
QLabel
>
(
"if_else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
ifBranch
=
make_shared
<
QLabel
>
(
"if_true"
);
auto
var
=
evalExpr
(
expr_
);
evalJump
(
expr_
,
ifBranch
,
elseBranch
);
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
envIf
=
captureEnv
(),
envElse
=
envIf
;
auto
envIf
=
captureEnv
(),
envElse
=
envIf
;
auto
stmtIfFirstBlock
=
block
;
auto
stmtIfFirstBlock
=
block
;
addQuad
<
QLabel
>
(
"if_true"
);
addQuad
(
ifBranch
);
stmt_1
->
accept
(
this
);
stmt_1
->
accept
(
this
);
addQuad
<
QJump
>
(
after
);
addQuad
<
QJump
>
(
after
);
auto
stmtIfLastBlock
=
flushBasicBlock
();
// jump -> after
auto
stmtIfLastBlock
=
flushBasicBlock
();
// jump -> after
...
...
src/codeGen/QuadrupleGenerator.h
View file @
459ffddf
...
@@ -30,6 +30,7 @@ private:
...
@@ -30,6 +30,7 @@ private:
VariablePtr
lastVar
;
VariablePtr
lastVar
;
int
lineno
;
int
lineno
;
shared_ptr
<
Scope
>
scope
;
shared_ptr
<
Scope
>
scope
;
shared_ptr
<
QLabel
>
labelTrue
,
labelFalse
;
VariablePtr
evalLVal
(
Visitable
*
expr
)
{
VariablePtr
evalLVal
(
Visitable
*
expr
)
{
auto
info
=
evalExpr
(
expr
)
->
info
;
auto
info
=
evalExpr
(
expr
)
->
info
;
...
@@ -55,6 +56,17 @@ private:
...
@@ -55,6 +56,17 @@ private:
return
ret
;
return
ret
;
}
}
VariablePtr
evalJump
(
Visitable
*
expr
,
shared_ptr
<
QLabel
>
tLabel
,
shared_ptr
<
QLabel
>
fLabel
)
{
if
(
!
expr
)
throw
runtime_error
(
"No expr to eval"
);
lineno
=
expr
->
lineno
;
swap
(
labelTrue
,
tLabel
);
swap
(
labelFalse
,
fLabel
);
auto
ret
=
evalExpr
(
expr
);
swap
(
labelTrue
,
tLabel
);
swap
(
labelFalse
,
fLabel
);
return
ret
;
}
VariablePtr
alloc
(
const
VarInfoPtr
&
info
)
{
VariablePtr
alloc
(
const
VarInfoPtr
&
info
)
{
if
(
info
->
loc
)
{
if
(
info
->
loc
)
{
return
info
->
loc
;
return
info
->
loc
;
...
@@ -84,6 +96,22 @@ private:
...
@@ -84,6 +96,22 @@ private:
return
quad
;
return
quad
;
}
}
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
);
addQuad
<
QJump
>
(
labelFalse
);
return
;
}
else
if
(
labelTrue
)
{
addQuad
<
QJumpCond
>
(
labelTrue
,
l
,
op
,
r
);
lastVar
=
alloc
(
0
);
}
else
if
(
labelFalse
)
{
addQuad
<
QJumpCond
>
(
labelFalse
,
l
,
op
.
neg
(),
r
);
lastVar
=
alloc
(
1
);
}
else
return
;
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
}
QuadruplePtr
lastQuad
;
QuadruplePtr
lastQuad
;
BasicBlockPtr
newBlock
()
{
BasicBlockPtr
newBlock
()
{
...
...
src/codeGen/RegisterAllocator.cpp
View file @
459ffddf
...
@@ -104,7 +104,7 @@ void RegisterAllocator::buildGraph() {
...
@@ -104,7 +104,7 @@ void RegisterAllocator::buildGraph() {
if
(
v
.
second
==
-
1
)
{
if
(
v
.
second
==
-
1
)
{
gNumSpill
++
;
gNumSpill
++
;
}
else
{
}
else
{
v
.
first
->
name
+=
"-r"
+
to_string
(
v
.
second
);
v
.
first
->
name
+=
"-r"
+
to_string
(
v
.
second
+
2
);
}
}
}
}
for
(
auto
&
v
:
g2
.
getAllocation
())
{
for
(
auto
&
v
:
g2
.
getAllocation
())
{
...
...
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