Compilation 2015
Instruction Selection for Tiger
Aslan Askarov aslan@cs.au.dk Based on slides by E. Ernst
Instruction Selection for Tiger Aslan Askarov aslan@cs.au.dk Based - - PowerPoint PPT Presentation
Compilation 2015 Instruction Selection for Tiger Aslan Askarov aslan@cs.au.dk Based on slides by E. Ernst Instruction Selection for Tiger The algorithms, e.g., Maximal Munch, did not show which registers were used to carry
Aslan Askarov aslan@cs.au.dk Based on slides by E. Ernst
which registers were used to carry results
(needed during static analysis)
+ CONST e c MEM EBX
FP
assembly instructions
in assem: a string
backquote marks “parameters”
source number i, destination i, jump i, in fields src, dst, jump (NONE: fall through, SOME _: all targets)
datatype instr = OPER of { assem:string , dst: temp list , src: temp list , jump: label list
| LABEL of { assem: string , lab: label} | MOVE of { assem: string , dst: temp , src: temp}
OPER { assem = "LOAD `d0 <- M[`s0+8]" , dst = [Temp.newtemp()] , src = [Frame.FP] , jump = NONE}
MEM + TEMP FP CONST 8
assem dst src "ADDI `d0 <- `s0+3" t908 t87 "LOAD `d0 <- M[`s0+0]" t909 t92 "MUL `d0 <- `s0*`s1" t910 t908,t909
* + TEMP t87 CONST 3 MEM TEMP t92
assem dst src "ADD `d0,`s1" t1 t1,t2
MOVE + TEMP t1 TEMP t2 TEMP t1
ADD t1 ⃪ t1 + t2 ADD t1,t2
munchStm: Tree.stm -> unit
fun munchStm (SEQ(a,b)) = (munchStm a; munchStm b) | munchStm (MOVE(MEM(BINOP(PLUS,e1,CONST i)),e2)) = emit (A.OPER{ assem = "STORE M[`s0+" ^ int i ^ "] <- `s1\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} | munchStm (MOVE(MEM(BINOP(PLUS,CONST i,e1)),e2)) = emit (A.OPER{ assem = "STORE M[`s0+" ^ int i ^ "] <- `s1\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} | munchStm (MOVE(MEM e1,MEM e2)) = emit (A.OPER{ assem = "MOVE M[`s0] <- M[`s1]\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} ... | munchStm (LABEL lab) = emit (A.LABEL {assem = lab ^ ":\n", lab = lab}) ...
depends on parameter passing mechanism (arguments, static link, frame pointer, …)
... | munchStm (EXP(CALL(e,args))) = emit (A.OPER{ assem = "CALL `s0\n" , src = munchExp e :: munchArgs (0,args) , dst = calldefs , jump = NONE} ...
and munchExp (MEM(BINOP(PLUS,e1,CONST i))) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[`s0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} | munchExp (MEM(BINOP(PLUS,CONST i,e1))) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[`s0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} | munchExp (MEM(CONST i)) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[r0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} ... | munchExp (BINOP(PLUS,e1,e2)) = result (fn r => emit (A.OPER { assem = "ADD `d0 <-`s0+`s1\n" , src = [munchExp e1, munchExp e2] , dst = [r], jump = NONE} | munchExp (TEMP t) = t
Note the use of result
fun codegen frame (stm: Tree.stm): Assem.instr list = let val ilist = ref (nil: instr list) fun emit x = (ilist := x::ilist) fun result gen = let val t = newtemp() in gen t; t end fun munchStm ... fun munchExp ... in munchStm stm; rev (!ilist) end
Note definition of result and use of side-effects
mentioned explicitly (!)
... | munchExp (BINOP(MUL,e1,e2)) = result (fn r => ... emit (A.OPER{ assem = "IMUL `s1" , src = [F.EAX, r] , dst = [F.EAX, F.EDX] , jump = NONE}) ...
High bits used for 32*32->64 bit computation, rarely Common view: it “trashes” EDX
... emit (A.OPER { assem = "CALL " ^S.name lab^ "\n" (* result: EAX *) , src = munchArgs args , dst = F.calldefs , jump = NONE}); emit (... (* clean up stack *)); emit (A.OPER { assem = "STORE M[`s0+0] <- `s1\n" , src = [munchExp e1, F.EAX] (* overwrite EAX! *) , dst = [] , jump = NONE}) ...
Problem: generated code destroys fixed register
... val t = newtemp() ... emit (A.OPER { assem = "CALL " ^S.name lab^ "\n" (* result: EAX *) , src = munchArgs args , dst = F.calldefs , jump = NONE}); emit (... (* clean up stack *)); emit (A.MOVE { assem = "MOVE `d0 <- `s0\n" (* result: t *) , src = F.EAX , dst = t}); emit (A.OPER { assem = "STORE M[`s0+0] <- `s1\n" , src = [munchExp e1, t] (* no overwrite *) , dst = [] , jump = NONE}) ...
Trick: fresh temp protects value
cost