diff options
author | Vladimir Azarov <avm@intermediate-node.net> | 2025-08-10 19:47:28 +0200 |
---|---|---|
committer | Vladimir Azarov <avm@intermediate-node.net> | 2025-08-10 19:47:28 +0200 |
commit | 413136926c66e97b4dd137b354665e5ae4ebb89e (patch) | |
tree | 812f116a140cc12fb7ae400f24dd3e27598e1b22 /emit.fun | |
parent | 9edb2b8dbd99636cf2d98d3253a0316f74720894 (diff) |
Instruction selection finish
Diffstat (limited to 'emit.fun')
-rw-r--r-- | emit.fun | 545 |
1 files changed, 442 insertions, 103 deletions
@@ -34,14 +34,15 @@ functor Emit(I: IL) = struct (R14, 10), (R15, 11), - (Rax, 12), - (Rdx, 13), + (Rdx, 12), + + (Rax, 13), (Rsp, 14), (Rbp, 15) ] val callerSavedRegs = 7 - val usedRegNum = 12 + val usedRegNum = 12 (* rdx is not counted *) fun reg2idx reg = case List.find (fn (r, _) => r = reg) regs of @@ -148,10 +149,31 @@ functor Emit(I: IL) = struct fun handleStrlits strlits = let - fun f id = fprint `".S" I id `":\tdb " `(PP.?? id) `", 0\n" % + fun emitStrlit id = + let + val () = fprint `".S" I id `":\t" % + val symbols = PP.T.strlit2charList (PP.?? id) + + fun pc c out = + if Char.isPrint c andalso not (Char.isSpace c) then + Printf out `"'" C c `"'" % + else + Printf out I (ord c) % + + fun outputStrlit (c :: []) = fprint A1 pc c % + | outputStrlit [] = raise Unreachable + | outputStrlit (c :: cs) = ( + fprint A1 pc c `", " %; + outputStrlit cs + ) + + in + fprint `"db " %; + outputStrlit symbols + end in fprint `"\n" %; - List.app f strlits + List.app emitStrlit strlits end fun handleLocalIniLayouts () = @@ -304,16 +326,8 @@ functor Emit(I: IL) = struct | I.IrAnd t => tr t | I.IrOr t => tr t | I.IrXor t => tr t - | I.IrEq t => tr t - | I.IrNeq t => tr t - | I.IrCmpul t => tr t - | I.IrCmpug t => tr t - | I.IrCmpule t => tr t - | I.IrCmpuge t => tr t - | I.IrCmpsl t => tr t - | I.IrCmpsg t => tr t - | I.IrCmpsle t => tr t - | I.IrCmpsge t => tr t + + | I.IrCmp (_, _, _, _) => IaNone | I.IrExtZero _ | I.IrExtSign _ | I.IrLoad _ | I.IrStore _ | I.IrJmp _ @@ -510,11 +524,12 @@ functor Emit(I: IL) = struct FRU.makeUpdate5 (from, from, to) i end z - fun returnToPool pool reg = + fun returnToPool (_, rdxRef) Rdx = rdxRef := NONE + | returnToPool (arr, _) reg = let val idx = reg2idx reg in - Array.update (pool, idx, NONE) + Array.update (arr, idx, NONE) end fun expireOne { rinfo, active, pool, ... } (_, start, _) = @@ -563,21 +578,29 @@ functor Emit(I: IL) = struct Array.update (arr, idx, (aff, reg)) end + fun getUser (_, rdxRef) Rdx = !rdxRef + | getUser (arr, _) r = Array.sub (arr, reg2idx r) + + fun setUser (_, rdxRef) u Rdx: unit = rdxRef := SOME u + | setUser (arr, _) u r = Array.update(arr, reg2idx r, SOME u) + fun assignFirstReg poff { rinfo, pool, ... } vr = let + val regArr = #1 pool + fun loop idx = - if idx = Array.length pool then + if idx = Array.length regArr then raise Unreachable else let - val user = Array.sub (pool, idx) + val user = Array.sub (regArr, idx) in case user of SOME _ => loop (idx + 1) | NONE => let - val () = Array.update (pool, idx, SOME vr); val reg = idx2reg idx + val () = setUser pool vr reg val () = printfn R poff `"assigned (first) reg " Preg reg `" to %" ip vr % @@ -589,7 +612,7 @@ functor Emit(I: IL) = struct loop 0 end - fun freeRegList pool = + fun freeRegList (pool, _) = let fun loop idx acc = if idx = Array.length pool then @@ -633,7 +656,7 @@ functor Emit(I: IL) = struct intersection l1 l2 end - fun assignSoftReg poff affs (I as { rinfo, pool, ... }) vr = + fun assignSoftReg poff affs (I as { rinfo, pool, ... }) vr = let val () = printfn R poff `"trying to assign register (by affinity) to %" ip vr % @@ -658,7 +681,8 @@ functor Emit(I: IL) = struct let in updReg rinfo vr (VtReg reg); - Array.update (pool, reg2idx reg, SOME vr); + setUser pool vr reg; + printfn R (poff + 1) `"assigned (by affinity) reg " Preg reg `" to %" ip vr %; printfn R (poff + 1) @@ -681,14 +705,13 @@ functor Emit(I: IL) = struct val () = printfn R poff `"trying to assign hard reg " A1 preg reg `" to %" ip vr % - val regIdx = reg2idx reg - val user = Array.sub (pool, regIdx) + val user = getUser pool reg fun setOurReg () = let val () = printfn R (poff + 1) `"reg assigned" % in - Array.update (pool, regIdx, SOME vr); + setUser pool vr reg; updReg rinfo vr (VtReg reg) end in @@ -696,6 +719,8 @@ functor Emit(I: IL) = struct NONE => setOurReg () | SOME u => let + val () = if reg = Rdx then raise Unreachable else () + val () = printfn R (poff + 1) `"reg is taken by %" ip u % val (aff, _) = Array.sub (rinfo, u) in @@ -718,7 +743,8 @@ functor Emit(I: IL) = struct | AfHard reg => assignHardReg 0 I vr reg end - fun getPool () = Array.array (usedRegNum, NONE) + (* Ref is for Rdx *) + fun getPool () = (Array.array (usedRegNum, NONE), ref NONE) fun changeInActive active newInt oldVr = let @@ -728,10 +754,13 @@ functor Emit(I: IL) = struct active := addToActive newInt a end - fun expropriateReg (I as { rinfo, pool, active, ... }) int reg = + fun expropriateReg (I as { rinfo, pool = (pool, _), active, ... }) + int reg = let val vr = #1 int + val () = if reg = Rdx then raise Unreachable else () + val regIdx = reg2idx reg val u = valOf $ Array.sub (pool, regIdx) @@ -748,13 +777,19 @@ functor Emit(I: IL) = struct changeInActive active int u end - fun userIdx pool vr = + fun userIdx (arr, rdxRef) vr = let + val () = + if !rdxRef = SOME vr then + raise Unreachable + else + () + fun loop idx = - if idx = Array.length pool then + if idx = Array.length arr then raise Unreachable else - case Array.sub (pool, idx) of + case Array.sub (arr, idx) of SOME u => if u = vr then idx @@ -788,9 +823,10 @@ functor Emit(I: IL) = struct let val idx = userIdx pool (#1 spill) val () = printfn `"spilling!!!" % + val reg = idx2reg idx in - Array.update (pool, idx, SOME vr); - updReg rinfo vr (VtReg $ idx2reg idx); + setUser pool vr reg; + updReg rinfo vr (VtReg reg); putToStack 1 I (#1 spill); changeInActive active int (#1 spill) end @@ -798,6 +834,23 @@ functor Emit(I: IL) = struct putToStack 0 I vr end + fun haveRoomForVR { rinfo, active, pool = (_, rdxRef), ... } vr = + if length (!active) < usedRegNum then + true + else + let + val (aff, _) = Array.sub (rinfo, vr) + in + case aff of + AfHard Rdx => + if isSome (!rdxRef) then + raise Unreachable + else + true + | _ => false + end + + fun linearscan rinfo ints stackOff = let fun incStart ((_, start1, _), (_, start2, _)) = start1 <= start2 @@ -814,14 +867,14 @@ functor Emit(I: IL) = struct val () = expireOld I int val () = - if length (!active) = usedRegNum then - spillAtInterval I int - else + if haveRoomForVR I (#1 int) then let val () = assignReg I int in active := addToActive int (!active) end + else + spillAtInterval I int in loop I ints end @@ -841,6 +894,37 @@ functor Emit(I: IL) = struct | VtConst _ | VtUnk => raise Unreachable end + fun pr is8 reg out = + let + fun old s = + let + val s = if is8 then s else "e" ^ String.extract (s, 1, NONE) + in + Printf out `s % + end + + fun new s = Printf out `(if is8 then s else s ^ "d") % + in + case reg of + Rcx => old "rcx" + | Rsi => old "rsi" + | Rdi => old "rdi" + | R8 => new "r8" + | R9 => new "r9" + | R10 => new "r10" + | R11 => new "r11" + + | Rbx => old "rbx" + | R12 => new "r12" + | R13 => new "r13" + | R14 => new "r14" + | R15 => new "r15" + + | Rax => old "rax" + | Rdx => old "rdx" + | Rsp => old "rsp" + | Rbp => old "rbp" + end fun printAlloced rinfo toAlloc = let val () = printfn `"\nallocated:\n" % @@ -850,7 +934,7 @@ functor Emit(I: IL) = struct fun getUsedRegs rinfo = let - val regs = Array.array (usedRegNum, false) + val regs = Array.array (usedRegNum + 1, false) fun loop idx = if idx = Array.length rinfo then @@ -860,7 +944,10 @@ functor Emit(I: IL) = struct val (_, vt) = Array.sub (rinfo, idx) in case vt of - VtReg reg => Array.update (regs, reg2idx reg, true) + VtReg reg => ( + printfn `"reg: " A2 pr true reg %; + Array.update (regs, reg2idx reg, true) + ) | _ => (); loop (idx + 1) end @@ -971,7 +1058,10 @@ functor Emit(I: IL) = struct let val () = printfn `"alloca size: " W size % val () = - if Word.mod (size, 0w8) <> 0w0 then raise Unreachable else () + if Word.mod (size, 0w8) <> 0w0 then + raise Unreachable + else + () val stackOffset = stackOffset - Word.toInt size val negOffset = ~stackOffset @@ -1009,64 +1099,31 @@ functor Emit(I: IL) = struct rinfo = regInfo, vregs } end - fun emitPushReg reg = fprinttn `"push " Preg reg % + fun emitPushPopReg op' reg = fprinttn `op' `" " Preg reg % fun emitPrologue ({ stackOffset, regsToSave, ... }) name = let val () = fprint PP.? name `":\n" % in + List.app (emitPushPopReg "push") regsToSave; if stackOffset <> 0 then ( fprinttn `"push rbp" %; fprinttn `"mov rbp, rsp" %; fprinttn `"sub rsp, " I (~ stackOffset) % ) else - (); - List.app emitPushReg regsToSave + () end - fun emitEpilogue { regsToSave, stackOffset, ... } = - let - val () = List.app emitPushReg (rev regsToSave) - in + fun emitEpilogue { regsToSave, stackOffset, ... } = ( if stackOffset <> 0 then ( fprinttn `"mov rsp, rbp" %; fprinttn `"pop rbp" % ) else (); + List.app (emitPushPopReg "pop") (rev regsToSave); fprinttn `"ret" % - end - - fun pr is8 reg out = - let - fun old s = - let - val s = if is8 then s else "e" ^ String.extract (s, 1, NONE) - in - Printf out `s % - end - - fun new s = Printf out `(if is8 then s else s ^ "d") % - in - case reg of - Rcx => old "rcx" - | Rsi => old "rsi" - | Rdi => old "rdi" - | R8 => new "r8" - | R9 => new "r9" - | R10 => new "r10" - | R11 => new "r11" - - | Rbx => old "rbx" - | R12 => new "r12" - | R13 => new "r13" - | R14 => new "r14" - | R15 => new "r15" + ) - | Rax => old "rax" - | Rdx => old "rdx" - | Rsp => old "rsp" - | Rbp => old "rbp" - end fun pm is8 off out = Printf out `(if is8 then "qword" else "dword") `" [rbp-" I off `"]"% @@ -1111,8 +1168,21 @@ functor Emit(I: IL) = struct if is8 then Printf out W w % else - Printf out W (P.extz w 0w32) % - | VAddrConst (id, w) => Printf out PP.? id I.Pwc I.VR8 w % + Printf out W (P.extz w 0w4) % + | VAddrConst (id, w) => + let + val repr = PP.?? id + val repr = + if String.sub (repr, 0) = #"\"" then + ".S" ^ Int.toString id + else + repr + in + if w = 0w0 then + Printf out `repr % + else + Printf out `repr I.Pwc I.VR8 w % + end fun wordFitsInNsx N w = let @@ -1309,7 +1379,7 @@ functor Emit(I: IL) = struct [ movRV Rax c, opRR r Rax ] end - fun truncConst (VConst w) N = VConst $ P.extz w (Word.fromInt N) + fun truncConst (VConst w) N = VConst $ P.extz w N | truncConst (C as (VAddrConst _)) _ = C fun emitShift I op' triple = @@ -1325,9 +1395,9 @@ functor Emit(I: IL) = struct sprintf `op' `"x " Pr r1 `", " Pr r2 `", " Pr r3 % fun shift3m r1 off r2 = - sprintf `op' `" x" Pr r1 `", " A2 pm is8 off `", " Pr r2 % + sprintf `op' `"x " Pr r1 `", " A2 pm is8 off `", " Pr r2 % - fun t v = truncConst v 8 + fun t v = truncConst v 0w1 in case tmp of RRR (r1, r2, r3) => [shift3 r1 r2 r3] @@ -1336,7 +1406,7 @@ functor Emit(I: IL) = struct | RMR (r1, off, r2) => [shift3m r1 off r2] | RMM (r1, off1, off2) => [movRM Rax off1, movRM Rdx off2, shift3 r1 Rax Rdx] - | RMV (r, off, v) => [movRM r off, opRV r (truncConst v 8)] + | RMV (r, off, v) => [movRM r off, opRV r (t v)] | RVR (r1, v, r2) => [movRV Rax v, shift3 r1 Rax r2] | RVM (r, v, off) => [movRV Rax v, movRM Rdx off, shift3 r Rax Rdx] | MRR (off, r1, r2) => [shift3 Rax r1 r2, movMR off Rax] @@ -1401,10 +1471,10 @@ functor Emit(I: IL) = struct else [movRM r1 off, movRV Rax v, opRR r1 Rax] | RVR (r1, v, r2) => - (printfn `"HERE" %; if r1 = r2 andalso isZeroConst v then - [sprintf `"neg " A2 pr is8 r1 %] - else - [movRV r1 v, opRR r1 r2]) + if r1 = r2 andalso isZeroConst v then + [sprintf `"neg " A2 pr is8 r1 %] + else + [movRV r1 v, opRR r1 r2] | RVM (r, v, off) => [movRV r v, opRM r off] | MRR (off, r1, r2) => [movRR Rax r1, opRR Rax r2, movMR off Rax] | MRM (off1, r, off2) => [opRM r off2, movMR off1 r] @@ -1463,7 +1533,7 @@ functor Emit(I: IL) = struct else () - fun emitGenConstraint I (rd, rs1, rs2) op' resInReg = + fun emitDivMod I (rd, rs1, rs2) op' resInReg signExtend = let val (is81, t1) = getType I rd val (is82, t2) = getType I rs1 @@ -1478,12 +1548,22 @@ functor Emit(I: IL) = struct | (_, _) => raise Unreachable in [ + if signExtend then + if is81 then "cqo" else "cdq" + else + "xor edx, edx", mov is81 (VtReg Rax) first, sprintf `op' `" " A2 prm is81 second %, mov is81 t1 (VtReg resInReg) ] end + fun moveBackIfNeeded is8 dest vt = + if dest = Rax then + [mov is8 vt (VtReg Rax)] + else + [] + fun emitIMul I (vd, vs1, vs2) = let val (is81, t1) = getType I vd @@ -1499,12 +1579,6 @@ functor Emit(I: IL) = struct VtReg r => r | _ => Rax - fun moveBackIfNeeded dest = - if dest = Rax then - [mov is81 t1 (VtReg Rax)] - else - [] - fun op2 () = let val form = @@ -1525,7 +1599,7 @@ functor Emit(I: IL) = struct sprintf `"imul " A2 pr is81 dest `", " A2 prm is81 rs2 % ] in - main @ moveBackIfNeeded dest + main @ moveBackIfNeeded is81 dest t1 end fun op3 rs1 c = @@ -1537,7 +1611,7 @@ functor Emit(I: IL) = struct [sprintf `"imul " A2 pr is81 dest `", " A2 prm is81 rs1 `", " A2 pc is81 c %] in - main @ moveBackIfNeeded dest + main @ moveBackIfNeeded is81 dest t1 end else op2 () @@ -1548,6 +1622,183 @@ functor Emit(I: IL) = struct | _ => op2 () end + fun regByAc ac r = + let + fun get16bitName r = + let + val repr = sprintf A2 pr false r % + in + if String.sub (repr, 0) = #"r" then + repr ^ "w" + else + String.extract (repr, 1, NONE) + end + + fun get8bitName r = + let + val repr = sprintf A2 pr false r % + in + if String.sub (repr, 0) = #"r" then + let + val len = size repr + in + String.substring (repr, 0, len - 1) ^ "b" + end + else + case r of + Rbx => "bl" + | Rcx => "cl" + | Rsi => "sil" + | Rdi => "dil" + | R8 | R9 | R10 | R11 | R12 | R13 | R14 | R15 + | Rbp | Rsp | Rax | Rdx => raise Unreachable + end + in + case ac of + I.AC8 => sprintf A2 pr true r % + | I.AC4 => sprintf A2 pr false r % + | I.AC2 => get16bitName r + | I.AC1 => get8bitName r + end + + fun pByAc ac vt out = + case vt of + VtReg r => Printf out `(regByAc ac r) % + | VtStack off => Printf out I.Pac ac `" [rbp-" I off `"]" % + | _ => raise Unreachable + + fun emitLoad I (vd, vs, ac) = + let + val (_, tl) = getType I vd + val (_, tr) = getType I vs + + val (pre, src) = + case tr of + VtReg r => ([], r) + | _ => ([mov true (VtReg Rdx) tr], Rdx) + + val dest = + case tl of + VtReg r => r + | _ => Rax + + val main = + [ + sprintf `"mov " `(regByAc ac dest) `", " + I.Pac ac `" [" A2 pr true src `"]" % + ] + in + pre @ main @ moveBackIfNeeded true dest tl + end + + fun emitStore I (vd, vs, ac) = + let + val (_, tl) = getType I vd + val (_, tr) = getType I vs + val (pre, src) = + case tr of + VtReg r => ([], VtReg r) + | VtConst c => + if fitsInNsx 32 c then + ([], VtConst c) + else + ([mov true (VtReg Rdx) tr], VtReg Rdx) + | _ => ([mov true (VtReg Rdx) tr], VtReg Rdx) + + + val (mid, dest) = + case tl of + VtReg r => ([], r) + | _ => ([mov true (VtReg Rax) tl], Rax) + + fun p vt out = + case vt of + VtReg reg => Printf out `(regByAc ac reg) % + | VtConst c => Printf out A2 pc true c % + | _ => raise Unreachable + + val main = + [ sprintf `"mov " I.Pac ac `" [" A2 pr true dest `"], " A1 p src % ] + in + pre @ mid @ main + end + + fun emitCmp E (cmpop, rd, rs1, rs2) = + let + val (_, td) = getType E rd + val (is82, ts1) = getType E rs1 + val (is83, ts2) = getType E rs2 + + val () = if is82 <> is83 then raise Unreachable else () + + fun RMwithImm vt c = + sprintf `"cmp " A2 prm is82 vt `", " A2 pc is82 c % + + fun RMwithR vt r = + sprintf `"cmp " A2 prm is82 vt `", " A2 pr is82 r % + + fun RwithRM r vt = sprintf `"cmp " A2 pr is82 r `", " A2 prm is82 vt % + + val zeroing = sprintf `"xor " A2 pr false Rax `", " A2 pr false Rax % + + val (pre, main) = + case (ts1, ts2) of + (VtReg _ | VtStack _, VtConst c) => + if fitsInNsx 32 c then + ([], RMwithImm ts1 c) + else + ([movRV is82 Rax c], RMwithR ts1 Rax) + | (VtReg _ | VtStack _, VtReg r) => ([], RMwithR ts1 r) + | (VtReg r, VtStack _) => ([], RwithRM r ts2) + + | (VtConst c, _) => ([movRV is82 Rax c], RwithRM Rax ts2) + | (VtStack off, VtStack _) => ([movRM is82 Rax off], RwithRM Rax ts2) + | (VtUnk, _) | (_, VtUnk) => raise Unreachable + + val flags = + case cmpop of + I.Cmpeq => "e" + | I.Cmpneq => "ne" + | I.Cmpul => "b" + | I.Cmpug => "a" + | I.Cmpule => "be" + | I.Cmpuge => "ae" + | I.Cmpsl => "l" + | I.Cmpsg => "g" + | I.Cmpsle => "le" + | I.Cmpsge => "ge" + + val setPart = sprintf `"set" `flags `" al" % + in + [zeroing] @ pre @ [main] @ [setPart] @ [mov true td (VtReg Rax)] + end + + fun emitExt E (vd, vs, from) op' = + let + val (is81, td) = getType E vd + val (_, ts) = getType E vs + + val to = if is81 then I.AC8 else I.AC4 + val dest = + case td of + VtReg r => r + | _ => Rax + + fun ext () = + sprintf `op' `" " A2 pr is81 dest `", " A2 pByAc from ts % + val main = + case (to, from) of + (I.AC4, I.AC1) | (I.AC4, I.AC2) => ext () + | (I.AC8, I.AC1) | (I.AC8, I.AC2) | (I.AC8, I.AC4) => ext () + + | (I.AC4, I.AC4) | (I.AC4, I.AC8) => raise Unreachable + | (I.AC8, I.AC8) => raise Unreachable + + | (I.AC1, _) | (I.AC2, _) => raise Unreachable + in + [main] @ moveBackIfNeeded is81 dest td + end + fun emitSet I (vrd, I.SaVReg vrs) = let val (is81, t1) = getType I vrd @@ -1563,7 +1814,7 @@ functor Emit(I: IL) = struct [movRR true r1 r2] | (true, VtReg r1, false, VtReg r2) => [movRR false r1 r2] - | (_, VtReg r1, _, VtConst c) => [movRV true r1 c] + | (_, VtReg r1, _, VtConst c) => [movRV true r1 c] | (_, VtReg r1, _, VtStack off) => [movRM true r1 off] | (_, VtStack off, _, VtReg r) => [movMR true off r] | (_, VtStack off1, _, VtStack off2) => @@ -1686,6 +1937,84 @@ functor Emit(I: IL) = struct | VtUnk => raise Unreachable end + fun getRegsWeSave map idx = + let + val row = Array.sub (map, idx) + + fun loop j acc = + if j = callerSavedRegs then + rev acc + else + case Array.sub (row, j) of + NONE => loop (j + 1) acc + | SOME _ => loop (j + 1) (idx2reg j :: acc) + in + loop 0 [] + end + + fun prepFuncPrologue ({ stackOffset, regsToSave, regMap, ... }) idx = + let + val offFromCall = 8 + 8 * length regsToSave + val offFromCall = + if (stackOffset <> 0) then + offFromCall + 8 (* push rbp *) + else + offFromCall + val offFromCall = offFromCall + ~ stackOffset + + fun pushRegs regs = map (fn r => sprintf `"push " A2 pr true r %) regs + val regsWeSave = getRegsWeSave regMap idx + + val registerPush: string list = pushRegs regsWeSave + val offFromCall = offFromCall + 8 * length regsWeSave + + val tail = + if offFromCall mod 16 <> 0 then + [sprintf `"sub rsp, 8" %] + else + [] + in + (not $ null tail, regsWeSave, registerPush @ tail) + end + + fun emitFcall E (rd, rf, _) idx = + let + val (shouldAdd, regsToRestore, prologueSeq) = prepFuncPrologue E idx + val (_, tf) = getType E rf + + val fcall = + case tf of + VtConst (C as VAddrConst _) => [sprintf `"call " A2 pc true C %] + | VtConst (VConst _) => [mov true (VtReg Rax) tf, sprintf `"call rax" %] + | VtReg _ | VtStack _ => [sprintf `"call " A2 prm true tf %] + | VtUnk => raise Unreachable + + val regRestoration = + let + val pre = + if shouldAdd then + [sprintf `"add rsp, 8" %] + else + [] + val restoration = + map (fn r => sprintf `"pop " A2 pr true r %) (rev regsToRestore) + + in + pre @ restoration + end + val assignRes = + if rd = ~1 then + [] + else + let + val (is8, t) = getType E rd + in + [mov is8 t (VtReg Rax)] + end + in + prologueSeq @ fcall @ regRestoration @ assignRes + end + fun emitOpStrList ins E idx = case ins of I.IrSet p => emitSet E p @@ -1702,15 +2031,25 @@ functor Emit(I: IL) = struct | I.IrMul t => emitIMul E t | I.IrIMul t => emitIMul E t - | I.IrDiv t => emitGenConstraint E t "div" Rax - | I.IrIDiv t => emitGenConstraint E t "idiv" Rax - | I.IrMod t => emitGenConstraint E t "div" Rdx - | I.IrIMod t => emitGenConstraint E t "idiv" Rdx + | I.IrDiv t => emitDivMod E t "div" Rax false + | I.IrIDiv t => emitDivMod E t "idiv" Rax true + | I.IrMod t => emitDivMod E t "div" Rdx false + | I.IrIMod t => emitDivMod E t "idiv" Rdx true + + | I.IrCmp q => emitCmp E q + + | I.IrLoad t => emitLoad E t + | I.IrStore t => emitStore E t + + | I.IrExtZero t => emitExt E t "movzx" + | I.IrExtSign t => emitExt E t "movsx" + + | I.IrFcall t => emitFcall E t idx | I.IrAlloc t => emitAlloc E t | I.IrRet vr => emitRet E vr idx | I.IrCopy t => emitCopy E t - | I.IrNopLabel lid => [ sprintf `".L" I lid % ] + | I.IrNopLabel lid => [ sprintf `".L" I lid `":" % ] | I.IrJmp lid => [ jmp lid ] | I.IrJz p => emitJz E p true | I.IrJnz p => emitJz E p false |