11package deep.decaf.low.amd64
22
33import deep.decaf.ir.*
4+ import java.lang.IllegalArgumentException
45import java.lang.IllegalStateException
56
67class 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
8290fun 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}
0 commit comments