Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Shen, Siran
wacc
Commits
01e6cfff
Commit
01e6cfff
authored
Mar 19, 2021
by
Tom Zhao
Browse files
Merge branch 'develop' of
https://gitlab.doc.ic.ac.uk/lab2021_spring/wacc_46
into develop
parents
ddafa6ad
f68b39d5
Changes
91
Hide whitespace changes
Inline
Side-by-side
antlr_config/WACCParser.g4
View file @
01e6cfff
...
...
@@ -77,7 +77,7 @@ assign_rhs : expr #Expr
arg_list : expr (COMMA expr)*;
struct_elem : IDENT (DOT IDENT)+;
new_struct : NEW IDENT OPEN_
CURLY_BRACKET
arg_list? CLOSE_
CURLY_BRACKET
;
new_struct : NEW IDENT OPEN_
PARENTHESES
arg_list? CLOSE_
PARENTHESES
;
pair_elem : FST expr #FstExpr
| SND expr #SndExpr
...
...
scripts/constantPropagationTest.sh
View file @
01e6cfff
...
...
@@ -25,11 +25,9 @@ for folder in ${VALID_EXAMPLES[@]}; do
echo
$file
./compile
-t
-o1
$file
>
"
${
EXECUTABLE_FILE_NAME
}
.log.txt"
mv
"
${
EXECUTABLE_FILE_NAME
}
.log.txt"
"
${
VALID_EXAMPLES_SRC_DIR
}${
folder
}
/
${
FILE_NAME
}
.log"
# if diff "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" -I scope; then
# (( COUNTER += 1 ))
# fi
if
diff
"
${
EXECUTABLE_FILE_NAME
}
.log.txt"
"
${
VALID_EXAMPLES_SRC_DIR
}${
folder
}
/
${
FILE_NAME
}
.log"
-I
scope
;
then
((
COUNTER +
=
1
))
fi
echo
"
$COUNTER
/
$((
$TOTAL_COUNT
))
files have been executed"
...
...
scripts/extensionValidTest.sh
View file @
01e6cfff
...
...
@@ -2,7 +2,7 @@
VALID_EXAMPLES
=(
"/binOctHex"
"/bitwise
Operation
"
"/bitwise"
"/do-while"
"/for"
"/import"
...
...
scripts/intelAssembleExecute.sh
View file @
01e6cfff
...
...
@@ -2,13 +2,13 @@
VALID_EXAMPLES
=(
#"/advanced"
#
"/array"
"/array"
"/basic"
"/expressions"
#
"/function"
"/function"
"/if"
"/IO"
#
"/pairs"
"/pairs"
#"/runtimeErr"
"/scope"
"/sequence"
...
...
@@ -44,7 +44,7 @@ for folder in ${VALID_EXAMPLES[@]}; do
./compile
-i
$file
2>
"
${
EXECUTABLE_FILE_NAME
}
.log.txt"
mv
"
${
FILE_NAME
}
.s"
"
${
EXECUTABLE_FILE_NAME
}
.s"
gcc
"
${
EXECUTABLE_FILE_NAME
}
.s"
-o
"
${
EXECUTABLE_FILE_NAME
}
"
./
"
${
EXECUTABLE_FILE_NAME
}
"
>
"
${
EXECUTABLE_OUTPUT_FILE
}
"
timeout
3
./
"
${
EXECUTABLE_FILE_NAME
}
"
>
"
${
EXECUTABLE_OUTPUT_FILE
}
"
# Generate the result from reference compiler
cat
<
(
echo
"N"
|
$REF_COMPILE
$file
-x
)
|
awk
'/===========================================================/ {x=!x; if(x) next} x==1 {print}'
>
temp
# Use the result generated by our compiler
...
...
src/Compiler.java
View file @
01e6cfff
...
...
@@ -52,7 +52,6 @@ public class Compiler {
File
sourceFile
=
new
File
(
args
[
0
]);
File
file
=
new
PreCompiler
(
sourceFile
).
preCompile
();
// System.out.println(file.getName());
// try-with-resources so that fis can be closed properly even when error occurs
try
(
FileInputStream
fis
=
new
FileInputStream
(
file
))
{
// Input stream of the file
...
...
src/PreCompiler.java
View file @
01e6cfff
...
...
@@ -73,8 +73,8 @@ public class PreCompiler {
str
=
str
.
split
(
commentMark
,
2
)[
0
];
if
(
str
.
contains
(
defineRuleContext
))
{
/* process and store the macros info */
String
[]
macro
=
str
.
split
(
" "
,
3
);
if
(
macro
.
length
!=
3
||
macro
[
0
].
length
()
!=
defineRuleContext
.
length
()
-
1
)
{
String
[]
macro
=
str
.
trim
().
split
(
" "
,
3
);
if
(
macro
.
length
!=
3
||
!
macro
[
0
].
equals
(
defineRuleContext
.
trim
())
)
{
mediateFile
.
delete
();
System
.
out
.
println
(
"Invalid macro at line "
+
lineCounter
);
System
.
exit
(
SYNTAX_ERROR_CODE
);
...
...
@@ -82,12 +82,12 @@ public class PreCompiler {
macros
.
add
(
new
MacroInfo
(
macro
[
1
],
macro
[
2
]));
}
else
if
(
str
.
contains
(
includeRuleContext
))
{
/* process and store the stdlib including info */
String
[]
tokens
=
str
.
split
(
"<"
,
2
);
String
[]
tokens
=
str
.
trim
().
split
(
"<"
,
2
);
/* e.g. include lib<a, b, c>, tokens[0] = include lib, tokens[1] = a, b, c> */
String
[]
prefix
=
tokens
[
0
].
split
(
" "
,
2
);
String
libName
=
prefix
[
1
];
String
libName
=
prefix
[
1
]
.
trim
()
;
List
<
String
>
typeParams
=
(
tokens
.
length
==
1
)
?
new
ArrayList
<>()
:
getTypeParam
(
tokens
[
1
],
lineCounter
,
prefix
[
0
].
length
()
==
includeRuleContext
.
length
()
-
1
,
mediateFile
);
lineCounter
,
prefix
[
0
].
equals
(
includeRuleContext
.
trim
())
,
mediateFile
);
imports
.
add
(
new
IncludeInfo
(
libName
,
typeParams
,
lineCounter
));
}
else
if
(
str
.
contains
(
programBodyMark
))
{
bw
.
write
(
str
+
"\n"
);
...
...
@@ -158,7 +158,7 @@ public class PreCompiler {
if
(
str
.
contains
(
defineRuleContext
))
{
/* get the lib's macro info, assume macros in stdlib are all valid */
String
[]
macro
=
str
.
split
(
" "
,
3
);
String
[]
macro
=
str
.
trim
().
split
(
" "
,
3
);
macros
.
add
(
new
MacroInfo
(
macro
[
1
],
macro
[
2
]));
}
else
{
bw
.
write
(
" "
+
str
+
"\n"
);
/* copy the content */
...
...
@@ -204,7 +204,11 @@ public class PreCompiler {
if
(
c
==
'<'
)
depth
++;
if
(
c
==
'>'
)
depth
--;
if
(
depth
==
0
)
{
if
(
c
==
'['
||
c
==
'('
)
{
mediateFile
.
delete
();
System
.
out
.
println
(
"Array or pair type are not supported: line "
+
lineNum
);
System
.
exit
(
SYNTAX_ERROR_CODE
);
}
else
if
(
depth
==
0
)
{
typeParams
.
add
(
token
.
toString
());
break
;
}
else
if
(
depth
==
1
&&
c
==
','
)
{
...
...
@@ -215,15 +219,7 @@ public class PreCompiler {
}
}
boolean
hasJunkAtEnd
=
false
;
for
(
i
=
i
+
1
;
i
<
str
.
length
();
i
++)
{
if
(
str
.
charAt
(
i
)
!=
' '
)
{
hasJunkAtEnd
=
true
;
break
;
}
}
if
(
hasJunkAtEnd
||
!
matchInclude
||
depth
!=
0
)
{
if
(
i
!=
str
.
length
()
-
1
||
!
matchInclude
||
depth
!=
0
)
{
mediateFile
.
delete
();
System
.
out
.
println
(
"Invalid include statement at line "
+
lineNum
);
System
.
exit
(
SYNTAX_ERROR_CODE
);
...
...
src/backend/InstructionGenerator.java
View file @
01e6cfff
package
backend
;
import
backend.arm.ARMInstructionGenerator
;
import
backend.arm.instructions.ARMInstruction
;
import
backend.common.LabelInstruction
;
import
backend.intel.IntelInstructionGenerator
;
import
backend.intel.instructions.IntelInstruction
;
import
java.util.ArrayList
;
import
java.util.List
;
import
utils.NodeVisitor
;
import
utils.frontend.symbolTable.SymbolTable
;
public
abstract
class
InstructionGenerator
<
T
extends
Instruction
>
implements
NodeVisitor
<
Void
>
{
/* the code section of the assembly code */
protected
final
List
<
T
>
instructions
;
/* record the current symbolTable used during instruction generation */
...
...
@@ -32,6 +28,10 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
protected
LabelInstruction
currBreakJumpToLabel
;
protected
LabelInstruction
currContinueJumpToLabel
;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
protected
int
breakSectionStackSize
;
protected
int
continueSectionStackSize
;
public
InstructionGenerator
()
{
instructions
=
new
ArrayList
<>();
currSymbolTable
=
null
;
...
...
@@ -40,5 +40,7 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
currBreakJumpToLabel
=
null
;
currContinueJumpToLabel
=
null
;
currForLoopSymbolTable
=
null
;
breakSectionStackSize
=
0
;
continueSectionStackSize
=
0
;
}
}
src/backend/InstructionPrinter.java
View file @
01e6cfff
package
backend
;
public
abstract
class
InstructionPrinter
{
public
abstract
String
translate
();
public
abstract
String
translate
();
}
src/backend/arm/ARMInstructionGenerator.java
View file @
01e6cfff
package
backend.arm
;
import
static
backend
.
arm
.
instructions
.
LDR
.
LdrMode
.*;
import
static
backend
.
arm
.
instructions
.
STR
.
StrMode
.*;
import
static
backend
.
arm
.
instructions
.
addressing
.
AddressingMode2
.
AddrMode2
.*;
import
static
backend
.
arm
.
instructions
.
arithmeticLogic
.
ARMArithmeticLogic
.
armUnopAsm
;
import
static
backend
.
arm
.
instructions
.
ARMInstructionRoutines
.
routineFunctionMap
;
import
static
backend
.
arm
.
instructions
.
LDR
.
LdrMode
.
LDR
;
import
static
backend
.
arm
.
instructions
.
LDR
.
LdrMode
.
LDRSB
;
import
static
backend
.
arm
.
instructions
.
STR
.
StrMode
.
STR
;
import
static
backend
.
arm
.
instructions
.
STR
.
StrMode
.
STRB
;
import
static
backend
.
arm
.
instructions
.
addressing
.
ARMImmediate
.
BitNum
.
CONST8
;
import
static
backend
.
arm
.
instructions
.
addressing
.
Operand2
.
Operand2Operator
.*;
import
static
backend
.
arm
.
instructions
.
addressing
.
AddressingMode2
.
AddrMode2
.
OFFSET
;
import
static
backend
.
arm
.
instructions
.
addressing
.
AddressingMode2
.
AddrMode2
.
PREINDEX
;
import
static
backend
.
arm
.
instructions
.
addressing
.
Operand2
.
Operand2Operator
.
ASR
;
import
static
backend
.
arm
.
instructions
.
addressing
.
Operand2
.
Operand2Operator
.
LSL
;
import
static
backend
.
arm
.
instructions
.
arithmeticLogic
.
ARMArithmeticLogic
.
armUnopAsm
;
import
static
frontend
.
node
.
expr
.
UnopNode
.
Unop
.
MINUS
;
import
static
utils
.
Utils
.
ARM_POINTER_SIZE
;
import
static
utils
.
Utils
.
BOOL_BASIC_TYPE
;
import
static
utils
.
Utils
.
BRANCH_HEADER
;
import
static
utils
.
Utils
.
CHAR_ARRAY_TYPE
;
import
static
utils
.
Utils
.
CHAR_BASIC_TYPE
;
import
static
utils
.
Utils
.
FALSE
;
import
static
utils
.
Utils
.
FUNC_HEADER
;
import
static
utils
.
Utils
.
INT_BASIC_TYPE
;
import
static
utils
.
Utils
.
MAIN_BODY_NAME
;
import
static
utils
.
Utils
.
MSG_HEADER
;
import
static
utils
.
Utils
.
PAIR_TYPE
;
import
static
utils
.
Utils
.
RoutineInstruction
;
import
static
utils
.
Utils
.
RoutineInstruction
.*;
import
static
utils
.
Utils
.
SystemCallInstruction
.*;
import
static
utils
.
Utils
.*;
import
static
backend
.
arm
.
instructions
.
ARMInstructionRoutines
.
routineFunctionMap
;
import
static
utils
.
backend
.
Cond
.*;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.*;
import
static
utils
.
Utils
.
RoutineInstruction
.
CHECK_ARRAY_BOUND
;
import
static
utils
.
Utils
.
RoutineInstruction
.
CHECK_DIVIDE_BY_ZERO
;
import
static
utils
.
Utils
.
RoutineInstruction
.
CHECK_NULL_POINTER
;
import
static
utils
.
Utils
.
RoutineInstruction
.
FREE_ARRAY
;
import
static
utils
.
Utils
.
RoutineInstruction
.
FREE_PAIR
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_BOOL
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_CHAR
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_INT
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_LN
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_REFERENCE
;
import
static
utils
.
Utils
.
RoutineInstruction
.
PRINT_STRING
;
import
static
utils
.
Utils
.
RoutineInstruction
.
READ_CHAR
;
import
static
utils
.
Utils
.
RoutineInstruction
.
READ_INT
;
import
static
utils
.
Utils
.
RoutineInstruction
.
THROW_OVERFLOW_ERROR
;
import
static
utils
.
Utils
.
RoutineInstruction
.
THROW_RUNTIME_ERROR
;
import
static
utils
.
Utils
.
STRING_BASIC_TYPE
;
import
static
utils
.
Utils
.
SystemCallInstruction
.
EXIT
;
import
static
utils
.
Utils
.
SystemCallInstruction
.
MALLOC
;
import
static
utils
.
Utils
.
TRUE
;
import
static
utils
.
Utils
.
WORD_SIZE
;
import
static
utils
.
backend
.
Cond
.
EQ
;
import
static
utils
.
backend
.
Cond
.
NE
;
import
static
utils
.
backend
.
Cond
.
NULL
;
import
static
utils
.
backend
.
Cond
.
VS
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
LR
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
PC
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
SP
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
r0
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
r1
;
import
static
utils
.
backend
.
register
.
arm
.
ARMConcreteRegister
.
r4
;
import
backend.Instruction
;
import
backend.InstructionGenerator
;
import
backend.arm.instructions.*
;
import
backend.arm.instructions.ARMInstruction
;
import
backend.arm.instructions.B
;
import
backend.arm.instructions.BL
;
import
backend.arm.instructions.Cmp
;
import
backend.arm.instructions.LDR
;
import
backend.arm.instructions.LDR.LdrMode
;
import
backend.arm.instructions.
STR.StrMode
;
import
backend.arm.instructions.
addressing.*
;
import
backend.arm.instructions.
arithmeticLogic.*
;
import
backend.arm.instructions.
LTORG
;
import
backend.arm.instructions.
Label
;
import
backend.arm.instructions.
Mov
;
import
backend.arm.instructions.Pop
;
import
backend.arm.instructions.Push
;
import
backend.arm.instructions.STR
;
import
backend.arm.instructions.STR.StrMode
;
import
backend.arm.instructions.addressing.ARMImmediate
;
import
backend.arm.instructions.addressing.AddressingMode2
;
import
backend.arm.instructions.addressing.ImmedAddress
;
import
backend.arm.instructions.addressing.Operand2
;
import
backend.arm.instructions.arithmeticLogic.ARMArithmeticLogic
;
import
backend.arm.instructions.arithmeticLogic.Add
;
import
backend.arm.instructions.arithmeticLogic.Sub
;
import
backend.common.address.Address
;
import
frontend.node.*
;
import
frontend.node.expr.*
;
import
frontend.node.FuncNode
;
import
frontend.node.ProgramNode
;
import
frontend.node.StructDeclareNode
;
import
frontend.node.expr.ArrayElemNode
;
import
frontend.node.expr.ArrayNode
;
import
frontend.node.expr.BinopNode
;
import
frontend.node.expr.BinopNode.Binop
;
import
frontend.node.expr.BoolNode
;
import
frontend.node.expr.CharNode
;
import
frontend.node.expr.ExprNode
;
import
frontend.node.expr.FunctionCallNode
;
import
frontend.node.expr.IdentNode
;
import
frontend.node.expr.IntegerNode
;
import
frontend.node.expr.PairElemNode
;
import
frontend.node.expr.PairNode
;
import
frontend.node.expr.StringNode
;
import
frontend.node.expr.StructElemNode
;
import
frontend.node.expr.StructNode
;
import
frontend.node.expr.UnopNode
;
import
frontend.node.expr.UnopNode.Unop
;
import
frontend.node.stat.*
;
import
frontend.node.stat.JumpNode.JumpContext
;
import
frontend.node.stat.AssignNode
;
import
frontend.node.stat.DeclareNode
;
import
frontend.node.stat.ExitNode
;
import
frontend.node.stat.ForNode
;
import
frontend.node.stat.FreeNode
;
import
frontend.node.stat.IfNode
;
import
frontend.node.stat.JumpNode
;
import
frontend.node.stat.JumpNode.JumpType
;
import
frontend.node.stat.PrintNode
;
import
frontend.node.stat.PrintlnNode
;
import
frontend.node.stat.ReadNode
;
import
frontend.node.stat.ReturnNode
;
import
frontend.node.stat.ScopeNode
;
import
frontend.node.stat.SkipNode
;
import
frontend.node.stat.StatNode
;
import
frontend.node.stat.SwitchNode
;
import
frontend.node.stat.SwitchNode.CaseStat
;
import
frontend.node.stat.WhileNode
;
import
frontend.type.Type
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -42,12 +125,10 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
utils.NodeVisitor
;
import
utils.backend.LabelGenerator
;
import
utils.backend.register.Register
;
import
utils.backend.register.arm.ARMConcreteRegister
;
import
utils.backend.register.arm.ARMConcreteRegisterAllocator
;
import
utils.backend.register.Register
;
import
utils.frontend.symbolTable.SymbolTable
;
public
class
ARMInstructionGenerator
extends
InstructionGenerator
<
ARMInstruction
>
{
...
...
@@ -55,36 +136,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
public
static
int
MAX_STACK_STEP
=
(
1
<<
10
);
/* const used in visitBinop, for checking multiply overflow */
public
static
int
ASR_SHIFT_CONST
=
31
;
/* the ARM concrete register allocator */
private
final
ARMConcreteRegisterAllocator
armRegAllocator
;
/* the .data section of the assembly code */
protected
final
Map
<
Label
,
String
>
dataSegmentMessages
;
/* call getLabel() on branchLabelGenerator to get label in the format of "L0, L1, L2, ..." */
protected
final
LabelGenerator
<
Label
>
branchLabelGenerator
;
/* call getLabel() on msgLabelGenerator to get label in the format of "msg_0, msg_1, msg_2, ..."*/
protected
final
LabelGenerator
<
Label
>
msgLabelGenerator
;
/* the ARM concrete register allocator */
private
final
ARMConcreteRegisterAllocator
armRegAllocator
;
/* a list of instructions for storing different helper functions
* would be appended to the end of instructions list while printing */
private
final
List
<
ARMInstruction
>
ARMRoutines
;
/* record which helpers already exist, we don't want repeated helper functions */
private
final
Set
<
RoutineInstruction
>
alreadyExist
;
/* call getLabel() on branchLabelGenerator to get label in the format of "L0, L1, L2, ..." */
protected
final
LabelGenerator
<
Label
>
branchLabelGenerator
;
/* call getLabel() on msgLabelGenerator to get label in the format of "msg_0, msg_1, msg_2, ..."*/
protected
final
LabelGenerator
<
Label
>
msgLabelGenerator
;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
private
int
loopStackSize
;
/* used for mapping type with its print routine function */
private
final
Map
<
Type
,
RoutineInstruction
>
typeRoutineMap
=
Map
.
of
(
INT_BASIC_TYPE
,
PRINT_INT
,
CHAR_BASIC_TYPE
,
PRINT_CHAR
,
BOOL_BASIC_TYPE
,
PRINT_BOOL
,
STRING_BASIC_TYPE
,
PRINT_STRING
,
CHAR_ARRAY_TYPE
,
PRINT_STRING
INT_BASIC_TYPE
,
PRINT_INT
,
CHAR_BASIC_TYPE
,
PRINT_CHAR
,
BOOL_BASIC_TYPE
,
PRINT_BOOL
,
STRING_BASIC_TYPE
,
PRINT_STRING
,
CHAR_ARRAY_TYPE
,
PRINT_STRING
);
/* recording the jump-to label for branching statement, i.e. break, continue */
private
Label
currBreakJumpToLabel
;
private
Label
currContinueJumpToLabel
;
public
ARMInstructionGenerator
()
{
super
();
...
...
@@ -143,7 +215,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* visit the content */
for
(
int
i
=
0
;
i
<
node
.
getElemCount
();
i
++)
{
visit
(
node
.
getElem
(
i
));
instructions
.
add
(
new
STR
(
armRegAllocator
.
curr
(),
new
AddressingMode2
(
OFFSET
,
addrReg
,
node
.
getElemOffset
(
i
)),
STR
));
instructions
.
add
(
new
STR
(
armRegAllocator
.
curr
(),
new
AddressingMode2
(
OFFSET
,
addrReg
,
node
.
getElemOffset
(
i
)),
STR
));
armRegAllocator
.
free
();
}
...
...
@@ -268,7 +341,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
List
<
Instruction
>
insList
=
ARMArithmeticLogic
.
binopInstruction
.
get
(
operator
)
.
binopAssemble
(
e1reg
,
e
1
reg
,
op2
,
operator
);
.
binopAssemble
(
e1reg
,
e
2
reg
,
op2
,
operator
);
instructions
.
addAll
(
insList
.
stream
().
map
(
i
->
(
ARMInstruction
)
i
).
collect
(
Collectors
.
toList
()));
if
(
operator
==
Binop
.
DIV
||
operator
==
Binop
.
MOD
)
{
checkAndAddRoutine
(
CHECK_DIVIDE_BY_ZERO
,
msgLabelGenerator
,
dataSegmentMessages
);
...
...
@@ -344,7 +417,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* 2 call function with B instruction */
String
overloadName
=
node
.
getFunction
().
getOverloadName
();
String
actualFuncName
=
(
overloadName
!=
null
)
?
overloadName
:
node
.
getFunction
().
getFunctionName
();
String
actualFuncName
=
(
overloadName
!=
null
)
?
overloadName
:
node
.
getFunction
().
getFunctionName
();
instructions
.
add
(
new
BL
(
FUNC_HEADER
+
actualFuncName
));
/* 3 add back stack pointer */
...
...
@@ -677,7 +751,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* accumulate function stack size, in case this scope is a function scope and contain return */
funcStackSize
+=
stackSize
;
loopStackSize
+=
stackSize
;
breakSectionStackSize
+=
stackSize
;
continueSectionStackSize
+=
stackSize
;
/* 2 visit statements
* set currentSymbolTable here, eliminate all other set symbol table in other statNode */
...
...
@@ -689,7 +764,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* decrease function stack size, as from this point stack is freed by the scope, not by return */
funcStackSize
-=
stackSize
;
loopStackSize
-=
stackSize
;
breakSectionStackSize
-=
stackSize
;
continueSectionStackSize
-=
stackSize
;
/* 3 restore stack */
incStack
(
stackSize
);
...
...
@@ -716,22 +792,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label
nextLabel
=
branchLabelGenerator
.
getLabel
().
asArmLabel
();
/* restore the last jump-to label after visiting the while-loop body */
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
;
Label
lastContinueJumpToLabel
=
currContinueJumpToLabel
;
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
==
null
?
null
:
currBreakJumpToLabel
.
asArmLabel
();
Label
lastContinueJumpToLabel
=
currContinueJumpToLabel
==
null
?
null
:
currContinueJumpToLabel
.
asArmLabel
();
currBreakJumpToLabel
=
nextLabel
;
currContinueJumpToLabel
=
testLabel
;
instructions
.
add
(
startLabel
);
/* record how much stack parent loop used */
int
prevLoopSize
=
loopStackSize
;
loopStackSize
=
0
;
int
prevBreakLoopSize
=
breakSectionStackSize
;
int
prevContinueLoopSize
=
continueSectionStackSize
;
breakSectionStackSize
=
0
;
continueSectionStackSize
=
0
;
/* 3 loop body */
visit
(
node
.
getBody
());
/* restore parent loop stack size */
loopStackSize
=
prevLoopSize
;
breakSectionStackSize
=
prevBreakLoopSize
;
continueSectionStackSize
=
prevContinueLoopSize
;
currBreakJumpToLabel
=
lastBreakJumpToLabel
;
currContinueJumpToLabel
=
lastContinueJumpToLabel
;
...
...
@@ -863,32 +944,35 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label
incrementLabel
=
branchLabelGenerator
.
getLabel
().
asArmLabel
();
/* restore the last jump-to label after visiting the for-loop body */
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
;
Label
lastContinueJumpToLabel
=
currContinueJumpToLabel
;
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
==
null
?
null
:
currBreakJumpToLabel
.
asArmLabel
();
Label
lastContinueJumpToLabel
=
currContinueJumpToLabel
==
null
?
null
:
currContinueJumpToLabel
.
asArmLabel
();
currBreakJumpToLabel
=
nextLabel
;
currContinueJumpToLabel
=
incrementLabel
;
instructions
.
add
(
new
B
(
NULL
,
condLabel
.
getName
()));
instructions
.
add
(
bodyLabel
);
currForLoopSymbolTable
=
node
.
getBody
().
getScope
();
/* record now much stack loop body have occupied */
int
prevLoopSize
=
loopStackSize
;
loopStackSize
=
0
;
int
prevBreakLoopSize
=
breakSectionStackSize
;
int
prevContinueLoopSize
=
continueSectionStackSize
;
breakSectionStackSize
=
0
;
continueSectionStackSize
=
0
;
visit
(
node
.
getBody
());
/* restore parent loop stack size */
loopStackSize
=
prevLoopSize
;
breakSectionStackSize
=
prevBreakLoopSize
;
continueSectionStackSize
=
prevContinueLoopSize
;
/* here we also need to append the for-loop increment at the end */
instructions
.
add
(
incrementLabel
);
visit
(
node
.
getIncrement
());
currBreakJumpToLabel
=
lastBreakJumpToLabel
;
Label
afterLabel
=
branchLabelGenerator
.
getLabel
();
currContinueJumpToLabel
=
afterLabel
;
currContinueJumpToLabel
=
lastContinueJumpToLabel
;
/* 3 add label for condition checking */
instructions
.
add
(
condLabel
);
...
...
@@ -901,7 +985,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
armRegAllocator
.
free
();
/* 4 conditional branch jump to the start of loop */
instructions
.
add
(
new
B
(
EQ
,
bodyLabel
.
getName
()));
/* 5 add the label for the following instructions after for-loop */
instructions
.
add
(
nextLabel
);
...
...
@@ -914,15 +998,12 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
@Override
public
Void
visitJumpNode
(
JumpNode
node
)
{
List
<
Instruction
>
addStack
=
new
ArrayList
<>();
/* this snippet is to deal with for-loop stack difference */
if
(!
node
.
getJumpType
().
equals
(
JumpType
.
BREAK
)
||
!
node
.
getJumpContext
().
equals
(
JumpContext
.
SWITCH
))
{
incStack
(
loopStackSize
);
}
if
(
node
.
getJumpType
().
equals
(
JumpType
.
BREAK
))
{
/* this snippet is to deal with for-loop stack difference */
incStack
(
breakSectionStackSize
);
instructions
.
add
(
new
B
(
NULL
,
currBreakJumpToLabel
.
getName
()));
}
else
if
(
node
.
getJumpType
().
equals
(
JumpType
.
CONTINUE
))
{
incStack
(
continueSectionStackSize
);
instructions
.
add
(
new
B
(
NULL
,
currContinueJumpToLabel
.
getName
()));
}
...
...
@@ -934,7 +1015,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
visit
(
node
.
getExpr
());
List
<
Label
>
cLabels
=
new
ArrayList
<>();
for
(
CaseStat
c
:
node
.
getCases
())
{
visit
(
c
.
getExpr
());
Label
cLabel
=
branchLabelGenerator
.
getLabel
().
asArmLabel
();
...
...
@@ -948,19 +1029,29 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label
afterLabel
=
branchLabelGenerator
.
getLabel
().
asArmLabel
();
/* restore the jump-to label after visiting the switch cases and default */
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
;
Label
lastBreakJumpToLabel
=
currBreakJumpToLabel
==
null
?
null
:
currBreakJumpToLabel
.
asArmLabel
();
currBreakJumpToLabel
=
afterLabel
;
instructions
.
add
(
new
B
(
NULL
,
defaultLabel
.
getName
()));
for
(
int
i
=
0
;
i
<
cLabels
.
size
();
i
++)
{
instructions
.
add
(
cLabels
.
get
(
i
));
/* record now much stack switch body have occupied */
int
prevLoopSize
=
breakSectionStackSize
;
breakSectionStackSize
=
0
;
visit
(
node
.
getCases
().
get
(
i
).
getBody
());
/* restore parent switch stack size */
breakSectionStackSize
=
prevLoopSize
;
}
int
prevLoopSize
=
breakSectionStackSize
;
breakSectionStackSize
=
0
;
instructions
.
add
(
defaultLabel
);
visit
(
node
.
getDefault
());
breakSectionStackSize
=
prevLoopSize
;
currBreakJumpToLabel
=
lastBreakJumpToLabel
;
instructions
.
add
(
afterLabel
);
...
...
@@ -972,7 +1063,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
while
(
stackSize
>
0
)
{
int
realStackSize
=
stackSize
/
MAX_STACK_STEP
>=
1
?
MAX_STACK_STEP
:
stackSize
;
instructions
.
add
(
new
Add
(
SP
,
SP
,
new
Operand2
(
realStackSize
)));
new
Operand2
(
realStackSize
)));
stackSize
=
stackSize
-
realStackSize
;
}
}
...
...
@@ -981,7 +1072,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
while
(
stackSize
>
0
)
{
int
realStackSize
=
stackSize
/
MAX_STACK_STEP
>=
1
?
MAX_STACK_STEP
:
stackSize
;
instructions
.
add
(
new
Sub
(
SP
,
SP
,
new
Operand2
(
realStackSize
)));
new
Operand2
(
realStackSize
)));
stackSize
=
stackSize
-
realStackSize
;
}
}
...
...
src/backend/arm/instructions/addressing/Operand2.java
View file @
01e6cfff
...
...
@@ -11,47 +11,60 @@ public class Operand2 extends Address {
private
final
ARMImmediate
immed
;
private
final
Operand2Operator
operator
;
private
final
Register
Rm
;
private
Operand2
(
Register
Rm
,
Operand2Operator
operator
,
ARMImmediate
immed
)
{