Skip to content

Commit fdd37c1

Browse files
committed
Added asm for callout, final asm for program
1 parent 97cd63a commit fdd37c1

File tree

3 files changed

+103
-16
lines changed

3 files changed

+103
-16
lines changed

src/main/kotlin/deep/decaf/low/amd64/IRToLow.kt

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package deep.decaf.low.amd64
22

33
import deep.decaf.ir.*
4+
import java.lang.IllegalArgumentException
45
import java.lang.IllegalStateException
56

67
class AsmProgramInfo {
@@ -14,6 +15,7 @@ class AsmProgramInfo {
1415
private val globalArrays = mutableMapOf<String, Int>() // name -> size
1516
private val variableStacks = mutableListOf<MutableMap<String, MemLoc>>()
1617
private val methodFormalParamsStack = mutableListOf<Map<String, Location>>()
18+
val globalText = mutableMapOf<String, String>()
1719

1820
fun addGlobalVariable(name: String, type: Type) {
1921
globalVariables[name] = type
@@ -53,7 +55,7 @@ class AsmProgramInfo {
5355
if (name in methodFormalParamsStack.last()) {
5456
return methodFormalParamsStack.last()[name]!! as MemLoc
5557
}
56-
if (name in globalVariables) {
58+
if (name in globalVariables) {
5759
return MemLoc(
5860
Register.instructionPointer(),
5961
StringOffset(name)
@@ -77,6 +79,12 @@ class AsmProgramInfo {
7779
fun popMethodArgs() {
7880
methodFormalParamsStack.removeAt(methodFormalParamsStack.size - 1)
7981
}
82+
83+
fun addGlobalString(value: String): String {
84+
val label = "LOC${globalText.size}"
85+
globalText[label] = value
86+
return label
87+
}
8088
}
8189

8290
fun irExprToLow(expr: IRExpr, info: AsmProgramInfo): List<Instruction> {
@@ -114,7 +122,46 @@ fun irExprToLow(expr: IRExpr, info: AsmProgramInfo): List<Instruction> {
114122
instructions.add(MoveInstruction(Register.returnRegister(), tmp))
115123
tmp
116124
}
117-
is IRCallOutExpr -> TODO()
125+
is IRCallOutExpr -> {
126+
for ((i, arg) in expr.argList.withIndex()) {
127+
val register = when (i) {
128+
0 -> Register("rdi")
129+
1 -> Register("rsi")
130+
2 -> Register("rdx")
131+
3 -> Register("rcx")
132+
4 -> Register("r8")
133+
5 -> Register("r9")
134+
else -> throw IllegalArgumentException("too many arguments to callout expression")
135+
}
136+
when (arg) {
137+
is StringCallOutArg -> {
138+
val loc = info.addGlobalString(arg.arg)
139+
instructions.add(
140+
MoveInstruction(
141+
MemLoc(Register.basePointer(), StringOffset(loc)),
142+
register
143+
)
144+
)
145+
}
146+
is ExprCallOutArg -> {
147+
val loc = traverse(arg.arg)
148+
instructions.add(MoveInstruction(loc, register))
149+
}
150+
}
151+
}
152+
val mustPush = info.stackSize % 2 == 1
153+
if (mustPush) {
154+
instructions.add(PushInstruction(Register.r10()))
155+
}
156+
instructions.add(CallInstruction(expr.name))
157+
if (mustPush) {
158+
instructions.add(PopInstruction(Register.r10()))
159+
}
160+
val tmp = info.addVariable(getUUID())
161+
instructions.add(PushInstruction(ImmediateVal(0)))
162+
instructions.add(MoveInstruction(Register.returnRegister(), tmp))
163+
tmp
164+
}
118165
is IRBinOpExpr -> {
119166
val leftLocation = traverse(expr.left)
120167
val rightLocation = traverse(expr.right)
@@ -467,5 +514,21 @@ fun irMethodToLow(method: IRMethodDeclaration, info: AsmProgramInfo): Method {
467514
convert(method.block, blocks[0])
468515
info.popMethodArgs()
469516

470-
return Method(argMap, blocks)
517+
return Method(argMap, blocks, method.name)
518+
}
519+
520+
fun irProgramToLow(program: IRProgram): Program {
521+
val info = AsmProgramInfo()
522+
program.fieldDeclarations.forEach {
523+
when (it) {
524+
is IRRegularFieldDeclaration -> info.addGlobalVariable(it.name, it.type)
525+
is IRArrayFieldDeclaration -> info.addGlobalArray(it.name, it.size)
526+
}
527+
}
528+
val methods = program.methodDeclarations.map { irMethodToLow(it, info) }
529+
val globalVariables = program.fieldDeclarations.filterIsInstance<IRRegularFieldDeclaration>().map { it.name }
530+
val globalArrays = mutableMapOf<String, Int>()
531+
program.fieldDeclarations.filterIsInstance<IRArrayFieldDeclaration>().forEach { globalArrays[it.name] = it.size }
532+
533+
return Program(globalVariables, globalArrays, info.globalText, methods)
471534
}

src/main/kotlin/deep/decaf/low/amd64/Low.kt

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ data class Block(val label: String?, val instructions: MutableList<Instruction>)
241241
data class Method(
242242
val formalParams: Map<String, Location>,
243243
val blocks: List<Block>,
244+
val name: String
244245
) {
245246
init {
246247
blocks[0].instructions.add(0, EnterInstruction(0))
@@ -257,7 +258,37 @@ data class Method(
257258
}
258259

259260
data class Program(
260-
var globalVars: List<String>,
261-
var globalArrays: List<String>,
262-
var methods: List<Method>
263-
)
261+
val globalVars: List<String>,
262+
val globalArrays: Map<String, Int>,
263+
val globalText: Map<String, String>,
264+
val methods: List<Method>
265+
) {
266+
override fun toString(): String {
267+
val stringBuilder = StringBuilder()
268+
stringBuilder.append(".section .rodata").append("\n")
269+
for (text in globalText.keys) {
270+
stringBuilder.append("${globalText[text]}:").append("\n")
271+
stringBuilder.append("\t").append(".string \"$text\"").append("\n")
272+
}
273+
274+
stringBuilder.append(".section .text").append("\n")
275+
stringBuilder.append("\t").append(".global main").append("\n")
276+
for (method in methods) {
277+
if (method.name == "main") {
278+
stringBuilder.append(method.toString())
279+
}
280+
}
281+
for (method in methods) {
282+
if (method.name != "main") {
283+
stringBuilder.append(method.toString())
284+
}
285+
}
286+
globalVars.forEach {
287+
stringBuilder.append(".comm $it, 8, 8").append("\n")
288+
}
289+
globalArrays.keys.forEach {
290+
stringBuilder.append(".comm $it, 8*${globalArrays[it]}, 8")
291+
}
292+
return stringBuilder.toString()
293+
}
294+
}

src/main/kotlin/deep/decaf/tester/LowMethodTester.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,7 @@ fun main() {
1616
val errors = checkSemantics(irTree)
1717
if (errors.isNotEmpty())
1818
throw RuntimeException("Invalid program")
19-
for (method in irTree.methodDeclarations) {
20-
if (method.name == "main") {
21-
val info = AsmProgramInfo()
22-
val methodAsm = irMethodToLow(method, info)
23-
println(file.absolutePath)
24-
println(methodAsm)
25-
println()
26-
}
27-
}
19+
val program = irProgramToLow(irTree)
20+
println(program)
2821
}
2922
}

0 commit comments

Comments
 (0)