Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cs164_lab3
Manage
Activity
Members
Labels
Plan
Issues
1
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
recolic-hust
cs164_lab3
Commits
afecd941
There was a problem fetching the pipeline stages.
Verified
Commit
afecd941
authored
6 years ago
by
Recolic Keghart
Browse files
Options
Downloads
Plain Diff
merged
parents
2948129d
a2074e51
No related branches found
No related tags found
1 merge request
!1
merge init works
Pipeline
#295
passed with warnings with stages
in 24 minutes and 15 seconds
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/main/java/chocopy/pa3/CodeGenImpl.java
+116
-89
116 additions, 89 deletions
src/main/java/chocopy/pa3/CodeGenImpl.java
with
116 additions
and
89 deletions
src/main/java/chocopy/pa3/CodeGenImpl.java
+
116
−
89
View file @
afecd941
package
chocopy.pa3
;
import
java.nio.charset.Charset
;
import
java.nio.charset.StandardCharsets
;
import
java.util.*
;
import
chocopy.common.analysis.SymbolTable
;
import
chocopy.common.analysis.AbstractNodeAnalyzer
;
import
chocopy.common.analysis.types.SymbolType
;
import
chocopy.common.analysis.types.ValueType
;
import
chocopy.common.astnodes.*
;
import
chocopy.common.codegen.*
;
...
...
@@ -15,12 +13,12 @@ import static chocopy.common.codegen.RiscVBackend.Register.*;
/**
* This is where the main implementation of PA3 will live.
*
*
<p>
* A large part of the functionality has already been implemented
* in the base class, CodeGenBase. Make sure to read through that
* class, since you will want to use many of its fields
* and utility methods in this class when emitting code.
*
*
<p>
* Also read the PDF spec for details on what the base class does and
* what APIs it exposes for its sub-class (this one). Of particular
* importance is knowing what all the SymbolInfo classes contain.
...
...
@@ -71,27 +69,33 @@ emitJ($someFunc$saveRegContinue)
public
class
CodeGenImpl
extends
CodeGenBase
{
private
class
BetterRsicVBackend
{
private
final
RiscVBackend
backend
;
BetterRsicVBackend
(
RiscVBackend
_backend
)
{
backend
=
_backend
;
}
public
void
emitNoop
(
String
comment
)
{
if
(
comment
!=
null
)
{
if
(
comment
!=
null
)
{
backend
.
emitMV
(
ZERO
,
ZERO
,
"Noop: "
+
comment
);
}
}
public
void
emitPush
(
RiscVBackend
.
Register
reg
,
String
comment
)
{
backend
.
emitADDI
(
SP
,
SP
,
-
1
*
backend
.
getWordSize
(),
comment
);
backend
.
emitSW
(
reg
,
SP
,
0
,
comment
);
}
public
void
emitPop
(
RiscVBackend
.
Register
reg
,
String
comment
)
{
if
(
reg
!=
null
)
if
(
reg
!=
null
)
backend
.
emitLW
(
reg
,
SP
,
0
,
comment
);
backend
.
emitADDI
(
SP
,
SP
,
backend
.
getWordSize
(),
comment
);
}
public
void
emitCall
(
Label
calledLabel
,
String
comment
)
{
// Arguments should be already pushed to stack.
backend
.
emitJAL
(
calledLabel
,
comment
);
}
public
void
emitFunctionBegin
(
String
funcName
,
String
comment
)
{
emitNoop
(
comment
);
emitPush
(
RA
,
"backup my return address."
);
...
...
@@ -101,13 +105,14 @@ public class CodeGenImpl extends CodeGenBase {
backend
.
emitJ
(
new
Label
(
"$"
+
funcName
+
"$saveReg"
),
"Jump to save callee-saved registers"
);
backend
.
emitLocalLabel
(
new
Label
(
"$"
+
funcName
+
"$saveRegContinue"
),
"Begin real function codes:"
);
}
public
void
emitFunctionEnd
(
String
funcName
,
registerManager
regMgr
,
String
comment
)
{
// Return value should be in A0
List
<
RiscVBackend
.
Register
>
savedRegs
=
regMgr
.
registerToSaveAndRestoreInFunc
;
emitNoop
(
comment
);
backend
.
emitADDI
(
SP
,
FP
,
-(
2
+
savedRegs
.
size
())
*
backend
.
getWordSize
(),
"Revert all local variables on this dying frame."
);
for
(
int
i
=
savedRegs
.
size
();
i
-->
0
;
)
{
backend
.
emitADDI
(
SP
,
FP
,
-(
2
+
savedRegs
.
size
())
*
backend
.
getWordSize
(),
"Revert all local variables on this dying frame."
);
for
(
int
i
=
savedRegs
.
size
();
i
--
>
0
;
)
{
emitPop
(
savedRegs
.
get
(
i
),
"restore callee-saved reg."
);
}
emitPop
(
FP
,
"restore parent FP."
);
...
...
@@ -115,11 +120,12 @@ public class CodeGenImpl extends CodeGenBase {
backend
.
emitJR
(
RA
,
"Real return!"
);
backend
.
emitLocalLabel
(
new
Label
(
"$"
+
funcName
+
"$saveReg"
),
"Save callee-saved registers before use."
);
for
(
int
i
=
0
;
i
<
savedRegs
.
size
();
++
i
)
{
for
(
int
i
=
0
;
i
<
savedRegs
.
size
();
++
i
)
{
emitPush
(
savedRegs
.
get
(
i
),
"save callee-saved reg."
);
}
backend
.
emitJ
(
new
Label
(
"$"
+
funcName
+
"$saveRegContinue"
),
"go back to execute real function code."
);
}
public
void
emitPushIntVal
(
RiscVBackend
.
Register
tmpReg
,
Integer
val
,
String
comment
)
{
emitNoop
(
comment
);
backend
.
emitLI
(
tmpReg
,
val
,
"INT VAL"
);
...
...
@@ -132,6 +138,7 @@ public class CodeGenImpl extends CodeGenBase {
emitPush
(
tmpReg
,
null
);
backend
.
emitMV
(
tmpReg
,
SP
,
"Return INT address."
);
}
public
void
emitPushBoolVal
(
RiscVBackend
.
Register
tmpReg
,
Boolean
val
,
String
comment
)
{
emitNoop
(
comment
);
backend
.
emitLI
(
tmpReg
,
val
?
1
:
0
,
"BOOL VAL"
);
...
...
@@ -144,18 +151,19 @@ public class CodeGenImpl extends CodeGenBase {
emitPush
(
tmpReg
,
null
);
backend
.
emitMV
(
tmpReg
,
SP
,
"Return BOOL address."
);
}
public
void
emitPushStrVal
(
RiscVBackend
.
Register
tmpReg
,
String
val
,
String
comment
)
{
emitNoop
(
comment
);
byte
[]
bytes
=
val
.
getBytes
(
StandardCharsets
.
US_ASCII
);
byte
[]
bytes
=
val
.
getBytes
(
StandardCharsets
.
US_ASCII
);
int
dataLen
=
bytes
.
length
/
backend
.
getWordSize
()
+
1
;
// Equals to ceil((len+1) DIVIDE WORD_SIZE)
for
(
int
cter
=
0
;
cter
<
dataLen
;
++
cter
)
{
int
myRangeBegin
=
(
dataLen
-
cter
-
1
)
*
backend
.
getWordSize
();
for
(
int
cter
=
0
;
cter
<
dataLen
;
++
cter
)
{
int
myRangeBegin
=
(
dataLen
-
cter
-
1
)
*
backend
.
getWordSize
();
int
myRangeEnd
=
Math
.
min
(
myRangeBegin
+
backend
.
getWordSize
(),
bytes
.
length
);
int
curr
=
0
;
assert
backend
.
getWordSize
()
==
4
;
// curr should be 4 byte = int
String
debug_pushed_str
=
""
;
for
(
int
shift
=
0
;
shift
<
myRangeEnd
-
myRangeBegin
;
++
shift
)
{
for
(
int
shift
=
0
;
shift
<
myRangeEnd
-
myRangeBegin
;
++
shift
)
{
curr
+=
bytes
[
myRangeBegin
+
shift
]
<<
(
shift
*
8
);
debug_pushed_str
+=
Integer
.
toString
(
bytes
[
myRangeBegin
+
shift
])
+
" "
;
}
...
...
@@ -215,6 +223,7 @@ public class CodeGenImpl extends CodeGenBase {
private
Map
<
RiscVBackend
.
Register
,
Boolean
>
callerSavedUsageMap
;
// true if the reg is in use.
private
Map
<
RiscVBackend
.
Register
,
Boolean
>
calleeSavedUsageMap
;
// true if the reg is in use.
public
List
<
RiscVBackend
.
Register
>
registerToSaveAndRestoreInFunc
;
registerManager
()
{
callerSavedUsageMap
=
new
LinkedHashMap
<>();
calleeSavedUsageMap
=
new
LinkedHashMap
<>();
...
...
@@ -251,8 +260,8 @@ public class CodeGenImpl extends CodeGenBase {
// For converience: we call caller-saved register as `temp register`,
// call callee-saved register as `persist register` or `saved register`, because they should be saved before the function.
public
RiscVBackend
.
Register
borrowOneTmp
()
{
for
(
RiscVBackend
.
Register
reg
:
callerSavedUsageMap
.
keySet
())
{
if
(
callerSavedUsageMap
.
put
(
reg
,
true
)
==
false
)
{
for
(
RiscVBackend
.
Register
reg
:
callerSavedUsageMap
.
keySet
())
{
if
(
callerSavedUsageMap
.
put
(
reg
,
true
)
==
false
)
{
return
reg
;
}
}
...
...
@@ -260,9 +269,9 @@ public class CodeGenImpl extends CodeGenBase {
}
public
RiscVBackend
.
Register
borrowOnePersist
()
{
for
(
RiscVBackend
.
Register
reg
:
calleeSavedUsageMap
.
keySet
())
{
if
(
calleeSavedUsageMap
.
put
(
reg
,
true
)
==
false
)
{
if
(!
registerToSaveAndRestoreInFunc
.
contains
(
reg
))
for
(
RiscVBackend
.
Register
reg
:
calleeSavedUsageMap
.
keySet
())
{
if
(
calleeSavedUsageMap
.
put
(
reg
,
true
)
==
false
)
{
if
(!
registerToSaveAndRestoreInFunc
.
contains
(
reg
))
registerToSaveAndRestoreInFunc
.
add
(
reg
);
return
reg
;
}
...
...
@@ -271,7 +280,7 @@ public class CodeGenImpl extends CodeGenBase {
}
public
void
returnOne
(
RiscVBackend
.
Register
reg
)
{
if
(
calleeSavedUsageMap
.
containsKey
(
reg
))
if
(
calleeSavedUsageMap
.
containsKey
(
reg
))
assert
calleeSavedUsageMap
.
put
(
reg
,
false
);
else
assert
callerSavedUsageMap
.
put
(
reg
,
false
);
...
...
@@ -291,7 +300,9 @@ public class CodeGenImpl extends CodeGenBase {
*/
}
/** A code generator emitting instructions to BACKEND. */
/**
* A code generator emitting instructions to BACKEND.
*/
public
CodeGenImpl
(
RiscVBackend
backend
)
{
super
(
backend
);
betterBackend
=
new
BetterRsicVBackend
(
backend
);
...
...
@@ -299,21 +310,27 @@ public class CodeGenImpl extends CodeGenBase {
private
BetterRsicVBackend
betterBackend
;
/** Operation on None. */
/**
* Operation on None.
*/
private
final
Label
errorNone
=
new
Label
(
"error.None"
);
/** Division by zero. */
/**
* Division by zero.
*/
private
final
Label
errorDiv
=
new
Label
(
"error.Div"
);
/** Index out of bounds. */
/**
* Index out of bounds.
*/
private
final
Label
errorOob
=
new
Label
(
"error.OOB"
);
/**
* Emits the top level of the program.
*
*
<p>
* This method is invoked exactly once, and is surrounded
* by some boilerplate code that: (1) initializes the heap
* before the top-level begins and (2) exits after the top-level
* ends.
*
*
<p>
* You only need to generate code for statements.
*
* @param statements top level statements
...
...
@@ -321,12 +338,11 @@ public class CodeGenImpl extends CodeGenBase {
protected
void
emitTopLevel
(
List
<
Stmt
>
statements
)
{
StmtAnalyzer
stmtAnalyzer
=
new
StmtAnalyzer
(
null
);
backend
.
emitADDI
(
SP
,
SP
,
-
2
*
backend
.
getWordSize
(),
"Saved FP and saved RA (unused at top level)."
);
"Saved FP and saved RA (unused at top level)."
);
backend
.
emitSW
(
ZERO
,
SP
,
0
,
"Top saved FP is 0."
);
backend
.
emitSW
(
ZERO
,
SP
,
4
,
"Top saved RA is 0."
);
backend
.
emitADDI
(
FP
,
SP
,
2
*
backend
.
getWordSize
(),
"Set FP to previous SP."
);
"Set FP to previous SP."
);
for
(
Stmt
stmt
:
statements
)
{
stmt
.
dispatch
(
stmtAnalyzer
);
}
...
...
@@ -336,7 +352,7 @@ public class CodeGenImpl extends CodeGenBase {
/**
* Emits the code for a function described by FUNCINFO.
*
*
<p>
* This method is invoked once per function and method definition.
* At the code generation stage, nested functions are emitted as
* separate functions of their own. So if function `bar` is nested within
...
...
@@ -359,10 +375,14 @@ public class CodeGenImpl extends CodeGenBase {
backend
.
emitLocalLabel
(
stmtAnalyzer
.
epilogue
,
"Epilogue"
);
// FIXME: {... reset fp etc. ...}
backend
.
emitLW
(
RA
,
FP
,
0
,
"Restore RA"
);
backend
.
emitLW
(
FP
,
FP
,
4
,
"Restore old FP"
);
backend
.
emitJR
(
RA
,
"Return to caller"
);
}
/** An analyzer that encapsulates code generation for statments. */
/**
* An analyzer that encapsulates code generation for statments.
*/
private
class
StmtAnalyzer
extends
AbstractNodeAnalyzer
<
RiscVBackend
.
Register
>
{
/*
* The symbol table has all the info you need to determine
...
...
@@ -395,20 +415,26 @@ public class CodeGenImpl extends CodeGenBase {
* appropriate info for the var that is currently in scope.
*/
/** Symbol table for my statements. */
/**
* Symbol table for my statements.
*/
private
SymbolTable
<
SymbolInfo
>
sym
;
/** Label of code that exits from procedure. */
/**
* Label of code that exits from procedure.
*/
protected
Label
epilogue
;
/** The descriptor for the current function, or null at the top
* level. */
/**
* The descriptor for the current function, or null at the top
* level.
*/
private
FuncInfo
funcInfo
;
private
registerManager
regMgr
=
new
registerManager
();
/* This method allocates object on the heap using the prototype
* Return register containing address */
* Return register containing address */
private
RiscVBackend
.
Register
allocPrototype
(
SymbolType
typ
,
RiscVBackend
.
Register
objReg
)
{
RiscVBackend
.
Register
storeAddr
=
regMgr
.
borrowOneTmp
();
// Convention: if typ is INT_TYPE then objReg contains the literal value, not a pointer.
...
...
@@ -425,8 +451,10 @@ public class CodeGenImpl extends CodeGenBase {
return
null
;
}
/** An analyzer for the function described by FUNCINFO0, which is null
* for the top level. */
/**
* An analyzer for the function described by FUNCINFO0, which is null
* for the top level.
*/
StmtAnalyzer
(
FuncInfo
funcInfo0
)
{
funcInfo
=
funcInfo0
;
if
(
funcInfo
==
null
)
{
...
...
@@ -445,14 +473,35 @@ public class CodeGenImpl extends CodeGenBase {
// This is here just to demonstrate how to emit a
// RISC-V instruction.
RiscVBackend
.
Register
returnValReg
=
node
.
value
.
dispatch
(
this
);
if
(
returnValReg
==
null
)
if
(
returnValReg
==
null
)
return
null
;
backend
.
emitMV
(
A0
,
returnValReg
,
"put return value!"
);
regMgr
.
returnOne
(
returnValReg
);
return
null
;
// Statement always return null.
}
// FIXME: More, of course.
@Override
public
RiscVBackend
.
Register
analyze
(
BooleanLiteral
literal
)
{
/* Push boolean literal onto stack, incrementing stack pointer*/
RiscVBackend
.
Register
res
=
regMgr
.
borrowOneTmp
();
backend
.
emitLA
(
res
,
constants
.
getBoolConstant
(
literal
.
value
),
"Load boolean literal"
);
return
res
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
IntegerLiteral
literal
)
{
RiscVBackend
.
Register
res
=
regMgr
.
borrowOneTmp
();
backend
.
emitLA
(
res
,
constants
.
getIntConstant
(
literal
.
value
),
"Load boolean literal"
);
return
res
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
StringLiteral
literal
)
{
RiscVBackend
.
Register
res
=
regMgr
.
borrowOneTmp
();
backend
.
emitLA
(
res
,
constants
.
getStrConstant
(
literal
.
value
),
"Load string literal"
);
return
res
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
ExprStmt
node
)
{
node
.
expr
.
dispatch
(
this
);
...
...
@@ -462,30 +511,29 @@ public class CodeGenImpl extends CodeGenBase {
@Override
public
RiscVBackend
.
Register
analyze
(
CallExpr
node
)
{
SymbolInfo
called
=
sym
.
get
(
node
.
function
.
name
);
if
(
called
instanceof
FuncInfo
)
{
if
(
called
instanceof
FuncInfo
)
{
FuncInfo
func
=
(
FuncInfo
)
called
;
// TODO: Push the FUCKING arg0 (outter function frame ptr)
List
<
RiscVBackend
.
Register
>
args_reg
=
new
ArrayList
<>();
for
(
Expr
expr
:
node
.
args
)
{
for
(
Expr
expr
:
node
.
args
)
{
RiscVBackend
.
Register
result
=
expr
.
dispatch
(
this
);
if
(
result
==
null
)
{
if
(
result
==
null
)
{
throw
new
RuntimeException
(
"NotImplemented: Expression "
+
expr
.
getClass
().
getName
()
+
" returns null register."
);
}
args_reg
.
add
(
result
);
}
for
(
RiscVBackend
.
Register
reg
:
args_reg
)
{
for
(
RiscVBackend
.
Register
reg
:
args_reg
)
{
betterBackend
.
emitPush
(
reg
,
"Push function arguments."
);
regMgr
.
returnOne
(
reg
);
}
betterBackend
.
emitCall
(
func
.
getCodeLabel
(),
null
);
for
(
Object
reg
:
args_reg
)
for
(
Object
reg
:
args_reg
)
betterBackend
.
emitPop
(
null
,
"Pop function arguments."
);
return
A0
;
// Function return value is always in A0.
}
else
if
(
called
instanceof
ClassInfo
)
{
}
else
if
(
called
instanceof
ClassInfo
)
{
// TODO: Fuck the fucking framework.
}
return
null
;
...
...
@@ -494,18 +542,18 @@ public class CodeGenImpl extends CodeGenBase {
@Override
public
RiscVBackend
.
Register
analyze
(
BinaryExpr
node
)
{
RiscVBackend
.
Register
leftReturnReg
=
node
.
left
.
dispatch
(
this
);
if
(
leftReturnReg
==
null
)
return
null
;
if
(
leftReturnReg
==
null
)
return
null
;
RiscVBackend
.
Register
leftRes
=
regMgr
.
borrowOnePersist
();
backend
.
emitMV
(
leftRes
,
leftReturnReg
,
"Move left operand result to a callee saved register"
);
regMgr
.
returnOne
(
leftReturnReg
);
// because right operand may overwrite temp registers.
RiscVBackend
.
Register
rightReturnReg
=
node
.
right
.
dispatch
(
this
);
RiscVBackend
.
Register
rightRes
=
rightReturnReg
;
if
(
rightReturnReg
==
null
)
if
(
rightReturnReg
==
null
)
return
null
;
switch
(
node
.
operator
)
{
switch
(
node
.
operator
)
{
case
"+"
:
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
RiscVBackend
.
Register
savedLeftAddr
=
regMgr
.
borrowOneTmp
();
backend
.
emitMV
(
savedLeftAddr
,
leftRes
,
"Backup reg leftRes"
);
backend
.
emitLW
(
leftRes
,
leftRes
,
3
*
backend
.
getWordSize
(),
"Operator+ Fetch left int result"
);
...
...
@@ -516,16 +564,16 @@ public class CodeGenImpl extends CodeGenBase {
regMgr
.
returnOne
(
leftRes
);
return
savedLeftAddr
;
}
if
(
node
.
left
.
getInferredType
().
isListType
())
{
if
(
node
.
left
.
getInferredType
().
isListType
())
{
// TODO: Merge two list.
throw
new
RuntimeException
(
"NOTIMPLEMENTED: ListMerge"
);
}
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
STR_TYPE
))
{
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
STR_TYPE
))
{
// TODO: Merge two str.
throw
new
RuntimeException
(
"NOTIMPLEMENTED: StrMerge"
);
}
case
"-"
:
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
RiscVBackend
.
Register
savedLeftAddr
=
regMgr
.
borrowOneTmp
();
backend
.
emitMV
(
savedLeftAddr
,
leftRes
,
"Backup reg leftRes"
);
backend
.
emitLW
(
leftRes
,
leftRes
,
3
*
backend
.
getWordSize
(),
"Operator- Fetch left int result"
);
...
...
@@ -537,7 +585,7 @@ public class CodeGenImpl extends CodeGenBase {
return
savedLeftAddr
;
}
case
"*"
:
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
if
(
node
.
left
.
getInferredType
().
equals
(
SymbolType
.
INT_TYPE
))
{
RiscVBackend
.
Register
savedLeftAddr
=
regMgr
.
borrowOneTmp
();
backend
.
emitMV
(
savedLeftAddr
,
leftRes
,
"Backup reg leftRes"
);
backend
.
emitLW
(
leftRes
,
leftRes
,
3
*
backend
.
getWordSize
(),
"Operator* Fetch left int result"
);
...
...
@@ -558,10 +606,10 @@ public class CodeGenImpl extends CodeGenBase {
switch
(
node
.
operator
)
{
case
"-"
:
RiscVBackend
.
Register
savedOpAddr
=
regMgr
.
borrowOneTmp
();
RiscVBackend
.
Register
savedResult
=
regMgr
.
borrowOnePersist
();
backend
.
emitMV
(
savedOpAddr
,
operandReg
,
"Save operand addr in register"
);
// TODO FIXME NOOOOO! YOU"RE DOINT THINGS WRONGLY. I'll complete the merge and fix it later.
if
(
node
.
operand
instanceof
IntegerLiteral
)
{
backend
.
emitLW
(
operandReg
,
operandReg
,
3
*
backend
.
getWordSize
(),
"Load operand value"
);
}
else
if
(
node
.
operand
instanceof
Identifier
)
{
...
...
@@ -572,69 +620,46 @@ public class CodeGenImpl extends CodeGenBase {
regMgr
.
returnOne
(
operandReg
);
regMgr
.
returnOne
(
savedOpAddr
);
regMgr
.
returnOne
(
savedResult
);
return
heapObject
;
}
return
null
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
Identifier
node
)
{
SymbolInfo
id
=
sym
.
get
(
node
.
name
);
if
(
id
instanceof
GlobalVarInfo
)
{
if
(
id
instanceof
GlobalVarInfo
)
{
GlobalVarInfo
globalVarInfo
=
(
GlobalVarInfo
)
id
;
RiscVBackend
.
Register
tmpReg
=
regMgr
.
borrowOneTmp
();
backend
.
emitLA
(
tmpReg
,
globalVarInfo
.
getLabel
(),
"Load address of the global var."
);
return
tmpReg
;
return
tmpReg
;
// FIXME: The global var contains a bare int rather than a INT OBJECT>
}
// FIXME: not implemented
return
null
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
IntegerLiteral
node
)
{
// emitConstant(node, ValueType.INT_TYPE, "Set constant int literal.");
RiscVBackend
.
Register
tmpReg
=
regMgr
.
borrowOneTmp
();
betterBackend
.
emitPushIntVal
(
tmpReg
,
node
.
value
,
"Push int literal"
);
return
tmpReg
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
BooleanLiteral
node
)
{
RiscVBackend
.
Register
tmpReg
=
regMgr
.
borrowOneTmp
();
betterBackend
.
emitPushBoolVal
(
tmpReg
,
node
.
value
,
"Push bool literal"
);
return
tmpReg
;
}
@Override
public
RiscVBackend
.
Register
analyze
(
StringLiteral
node
)
{
RiscVBackend
.
Register
tmpReg
=
regMgr
.
borrowOneTmp
();
betterBackend
.
emitPushStrVal
(
tmpReg
,
node
.
value
,
"push string literal."
);
return
tmpReg
;
}
}
/**
* Emits custom code in the CODE segment.
*
*
<p>
* This method is called after emitting the top level and the
* function bodies for each function.
*
*
<p>
* You can use this method to emit anything you want outside of the
* top level or functions, e.g. custom routines that you may want to
* call from within your code to do common tasks. This is not strictly
* needed. You might not modify this at all and still complete
* the assignment.
*
*
<p>
* To start you off, here is an implementation of three routines that
* will be commonly needed from within the code you will generate
* for statements.
*
*
<p>
* The routines are error handlers for operations on None, index out
* of bounds, and division by zero. They never return to their caller.
* Just jump to one of these routines to throw an error and
* exit the program. For example, to throw an OOB error:
* backend.emitJ(errorOob, "Go to out-of-bounds error and abort");
*
* backend.emitJ(errorOob, "Go to out-of-bounds error and abort");
*/
protected
void
emitCustomCode
()
{
emitErrorFunc
(
errorNone
,
"Operation on None"
);
...
...
@@ -642,14 +667,16 @@ public class CodeGenImpl extends CodeGenBase {
emitErrorFunc
(
errorOob
,
"Index out of bounds"
);
}
/** Emit an error routine labeled ERRLABEL that aborts with message MSG. */
/**
* Emit an error routine labeled ERRLABEL that aborts with message MSG.
*/
private
void
emitErrorFunc
(
Label
errLabel
,
String
msg
)
{
backend
.
emitGlobalLabel
(
errLabel
);
backend
.
emitLI
(
A0
,
ERROR_NONE
,
"Exit code for: "
+
msg
);
backend
.
emitLA
(
A1
,
constants
.
getStrConstant
(
msg
),
"Load error message as str"
);
"Load error message as str"
);
backend
.
emitADDI
(
A1
,
A1
,
getAttrOffset
(
strClass
,
"__str__"
),
"Load address of attribute __str__"
);
"Load address of attribute __str__"
);
backend
.
emitJ
(
abortLabel
,
"Abort"
);
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment