1 (* Copyright (C) 2010 Matthew Fluet.
2 * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
10 functor x86AllocateRegisters(S: X86_ALLOCATE_REGISTERS_STRUCTS) : X86_ALLOCATE_REGISTERS =
16 val tracer = x86.tracer
17 val tracerTop = x86.tracerTop
20 (* When outputing position-independent-code (PIC), we need to keep
21 * one register pointing at a known local address. Addresses are
22 * then computed relative to this register.
25 datatype z = datatype Control.Format.t
26 datatype z = datatype MLton.Platform.OS.t
28 (* If the ELF symbol is external, we already setup an indirect
29 * mov to load the address. Don't munge the symbol more.
32 case Label.toString l of s =>
33 if String.hasSuffix (s, { suffix = "@GOT" }) then l else
34 Label.fromString (s ^ "@GOTOFF")
36 (* !!! PIC on darwin not done yet !!! *)
37 (* It will work using %esp -> MLtonLocalBaseSymbol *)
38 fun mungeLabelDarwin l =
39 Label.fromString (Label.toString l ^ "-MLtonLocalBaseSymbol")
41 case (!Control.Target.os, !Control.positionIndependent) of
42 (* Only darwin and ELF might be using PIC *)
43 (Darwin, true) => (mungeLabelDarwin, SOME Register.esp)
44 | (_, true) => (mungeLabelELF, SOME Register.ebx)
45 | (_, false) => (fn l => l, NONE)
48 fun track memloc = let
50 = ClassSet.add(ClassSet.+
51 (!x86MLton.Classes.livenessClasses,
52 !x86MLton.Classes.holdClasses),
53 x86MLton.Classes.StaticNonTemp)
55 ClassSet.contains(trackClasses, MemLoc.class memloc)
57 fun volatile memloc = let
59 = !x86MLton.Classes.volatileClasses
61 ClassSet.contains(volatileClasses, MemLoc.class memloc)
71 | P::PS => if List.exists(P,fn x => p(h, x))
73 else P::(partition'' PS)
75 partition'(t,partition'' PS)
81 fun totalOrder (l, plt)
88 => case List.splitPrefix
90 of (nil,t) => lt@[h]@t
91 | (lt',t) => split(lt@lt',t)
93 totalOrder'(t,split([],l))
100 = fn (false, true) => true
104 = fn (true, false) => true
108 = fn (SOME x, SOME y) => lt (x,y)
109 | (NONE, SOME _) => true
115 datatype futureMemlocTag = FLIVE
116 | FCOMMIT | FREMOVE | FDEAD
117 | FUSE | FUSEDEF | FDEF
119 val futureMemlocTag_toString
120 = fn FLIVE => "FLIVE"
121 | FCOMMIT => "FCOMMIT"
122 | FREMOVE => "FREMOVE"
125 | FUSEDEF => "FUSEDEF"
128 type futureMemloc = futureMemlocTag * MemLoc.t
130 datatype futureMemlocPredTag = FCOMMITP | FREMOVEP | FDEADP
131 | FMCOMMITP | FMREMOVEP
133 val futureMemlocPredTag_toString
134 = fn FCOMMITP => "FCOMMITP"
135 | FREMOVEP => "FREMOVEP"
137 | FMCOMMITP => "FMCOMMITP"
138 | FMREMOVEP => "FMREMOVEP"
140 type futureMemlocPred = futureMemlocPredTag * (MemLoc.t -> bool)
142 datatype future = M of futureMemloc | MP of futureMemlocPred
145 = fn (M (tag, memloc))
146 => concat [futureMemlocTag_toString tag, " ", MemLoc.toString memloc]
148 => concat [futureMemlocPredTag_toString tag]
151 type hint = Register.t * MemLoc.t list * MemLocSet.t
154 = fn (register, memlocs, _)
159 fn (memloc, s) => s ^ (MemLoc.toString memloc) ^ " "),
161 Register.toString register]
163 type t = {dead: MemLocSet.t,
166 futures: {pre: future list,
171 fun toString {dead, commit, remove, futures = {pre, post}, hint}
173 fun doit (name, l, toString, s)
176 => concat [name, toString x, "\n", s])
177 fun doit' (name, l, toString, s)
178 = MemLocSet.fold(l, s,
180 => concat [name, toString x, "\n", s])
182 doit'("dead: ", dead, MemLoc.toString,
183 doit'("commit: ", commit, MemLoc.toString,
184 doit'("remove: ", remove, MemLoc.toString,
185 doit("future (pre): ", List.rev pre, future_toString,
186 doit("future (post): ", List.rev post, future_toString,
187 doit("hint: ", hint, hint_toString, ""))))))
191 fun toComments {dead, commit, remove, futures = {pre, post}, hint}
193 fun doit (name, l, toString, ac)
196 => (Assembly.comment (concat [name, toString x]))::
198 fun doit' (name, l, toString, ac)
199 = MemLocSet.fold(l, ac,
201 => (Assembly.comment (concat [name, toString x]))::
204 doit'("dead: ", dead, MemLoc.toString,
205 doit'("commit: ", commit, MemLoc.toString,
206 doit'("remove: ", remove, MemLoc.toString,
207 doit("future (pre): ", List.rev pre, future_toString,
208 doit("future (post): ", List.rev post, future_toString,
209 doit("hint: ", hint, hint_toString, []))))))
213 datatype commit = NO | COMMIT | REMOVE | DEAD
215 fun predict(future, memloc)
218 = fn [] => if track memloc then DEAD else REMOVE
219 | (M (tag',memloc'))::future
220 => if MemLoc.eq(memloc, memloc')
223 | FCOMMIT => sawCommit future
224 | FREMOVE => sawRemove future
226 | FUSE => sawUse future
229 else if ((tag' = FUSEDEF) orelse (tag' = FDEF))
232 (MemLoc.utilized memloc,
233 fn memloc'' => MemLoc.mayAlias(memloc'', memloc'))
235 else if MemLoc.mayAlias(memloc, memloc')
237 of FUSE => sawCommit future
240 | _ => sawNothing future
241 else sawNothing future
242 | (MP (tag',pred'))::future
245 of FCOMMITP => sawCommit future
246 | FREMOVEP => sawRemove future
248 | FMCOMMITP => sawCommit future
249 | FMREMOVEP => sawRemove future
250 else sawNothing future
253 | (M (tag',memloc'))::future
254 => if MemLoc.eq(memloc, memloc')
257 | FCOMMIT => sawCommit future
263 else if MemLoc.mayAlias(memloc, memloc')
265 of FUSE => sawCommit future
268 | _ => sawCommit future
269 else sawCommit future
270 | (MP (tag',pred'))::future
273 of FCOMMITP => sawCommit future
276 | FMCOMMITP => sawCommit future
277 | FMREMOVEP => REMOVE
278 else sawCommit future
281 | (M (tag',memloc'))::future
282 => if MemLoc.eq(memloc, memloc')
286 | FREMOVE => sawRemove future
291 else if MemLoc.mayAlias(memloc, memloc')
296 | _ => sawRemove future
297 else sawRemove future
298 | (MP (tag',pred'))::future
301 of FCOMMITP => REMOVE
304 | FMCOMMITP => REMOVE
305 | FMREMOVEP => sawRemove future
306 else sawRemove future
308 = fn [] => if track memloc then NO else COMMIT
309 | (M (tag',memloc'))::future
310 => if MemLoc.eq(memloc, memloc')
313 | FCOMMIT => sawUseCommit future
316 | FUSE => sawUse future
319 else if MemLoc.mayAlias(memloc, memloc')
321 of FUSE => sawUseCommit future
326 | (MP (tag',pred'))::future
329 of FCOMMITP => sawUseCommit future
332 | FMCOMMITP => sawUseCommit future
336 = fn [] => if track memloc then NO else COMMIT
337 | (M (tag',memloc'))::future
338 => if MemLoc.eq(memloc, memloc')
341 | FCOMMIT => sawUseCommit future
347 else if MemLoc.mayAlias(memloc, memloc')
349 of FUSE => sawUseCommit future
352 | _ => sawUseCommit future
353 else sawUseCommit future
354 | (MP (tag',pred'))::future
357 of FCOMMITP => sawUseCommit future
360 | FMCOMMITP => sawUseCommit future
362 else sawUseCommit future
366 (MemLoc.utilized memloc,
367 fn memloc' => case predict (future, memloc')
374 val default = case sawNothing future
377 | commit => check commit
386 (MemLocSet.empty,MemLocSet.empty,MemLocSet.empty,MemLocSet.empty),
387 fn (memloc, (no, commit, remove, dead))
389 val add = fn set => MemLocSet.add(set, memloc)
392 of NO => (add no, commit, remove, dead)
393 | COMMIT => (no, add commit, remove, dead)
394 | REMOVE => (no, commit, add remove, dead)
395 | DEAD => (no, commit, remove, add dead)
398 fun liveness {uses: MemLocSet.t,
400 future: future list} :
407 fun doit' (memlocs, set)
413 (set, MemLocSet.fromList (MemLoc.utilized memloc)))
424 = MemLocSet.+(allUses, allDefs)
426 = MemLocSet.intersect(allUses, allDefs)
428 = MemLocSet.-(allUses, current_usedef)
430 = MemLocSet.-(allDefs, current_usedef)
432 val (_,commit,remove,dead)
433 = split(current, fn memloc => predict(future, memloc))
437 fun doit(memlocs, tag, future)
442 => (M (tag, memloc))::future)
444 doit(current_use, FUSE,
445 doit(current_usedef, FUSEDEF,
446 doit(current_def, FDEF,
459 fun livenessInstruction {instruction: Instruction.t,
462 val future_post = future
464 val {uses, defs, ...} = Instruction.uses_defs_kills instruction
470 fn (operand, memlocs)
471 => case Operand.deMemloc operand
472 of SOME memloc => MemLocSet.add(memlocs, memloc)
479 val {dead,commit,remove,future}
480 = liveness {uses = uses,
482 future = future_post}
483 val future_pre = future
485 val info = {dead = dead,
488 futures = {pre = future_pre, post = future_post}}
494 fun livenessDirective {directive: Directive.t,
497 val future_post = future
499 fun addLive (memlocsX, f)
503 fn (X, future) => (M (FLIVE, f X))::future)
504 fun addLive' (memlocs)
508 fn (memloc, future) => (M (FLIVE, memloc))::future)
514 | Directive.Cache {caches, ...}
515 => addLive(caches, fn {memloc, ...} => memloc)
516 | Directive.FltCache {caches, ...}
517 => addLive(caches, fn {memloc, ...} => memloc)
518 | Directive.Force {commit_memlocs,
533 => ClassSet.contains(commit_classes,
534 MemLoc.class memloc)))::
537 => ClassSet.contains(remove_classes,
538 MemLoc.class memloc)))::
541 => ClassSet.contains(dead_classes,
542 MemLoc.class memloc)))::
544 fn (memloc,future) => (M (FDEAD, memloc))::future),
545 fn (memloc,future) => (M (FREMOVE, memloc))::future),
546 fn (memloc,future) => (M (FCOMMIT, memloc))::future)
551 (MemLoc.class memloc,
552 MemLoc.Class.CStack)))::
555 => (not (MemLoc.Class.eq
556 (MemLoc.class memloc,
557 MemLoc.Class.CStack)))
559 (Size.class (MemLoc.size memloc) <> Size.INT)))::
561 | Directive.Return {returns}
562 => (List.map(returns, fn {dst, ...} => M (FDEF, dst))) @ future
566 => (Size.class (MemLoc.size memloc) <> Size.INT)))::
568 | Directive.SaveRegAlloc {live, ...}
572 val info = {dead = MemLocSet.empty,
573 commit = MemLocSet.empty,
574 remove = MemLocSet.empty,
575 futures = {pre = future_pre, post = future_post}}
580 fun livenessAssembly {assembly: Assembly.t,
584 fun default () = {dead = MemLocSet.empty,
585 commit = MemLocSet.empty,
586 remove = MemLocSet.empty,
587 futures = {pre = future, post = future}}
588 val {dead, commit, remove, futures}
590 of Assembly.Comment _ => default ()
591 | Assembly.Directive d
592 => livenessDirective {directive = d,
594 | Assembly.Instruction i
595 => livenessInstruction {instruction = i,
597 | Assembly.Label _ => default ()
598 | Assembly.PseudoOp _ => default ()
600 val hint' = Assembly.hints assembly
604 of Assembly.Directive Directive.Reset => []
608 fn (memloc, register)
609 => (register, [memloc], MemLocSet.empty)),
610 fn ((hint_register,hint_memlocs,hint_ignore),hint)
613 fn (hint_register',_,_) => Register.coincide(hint_register,
617 val hint_memloc = hd hint_memlocs
622 fn ((_,hint_memlocs',_),b)
623 => b orelse List.contains
630 MemLocSet.union(dead, hint_ignore))::hint
634 of (Assembly.Instruction (Instruction.MOV
635 {src = Operand.MemLoc src',
636 dst = Operand.MemLoc dst',
640 fn (hint_register,hint_memlocs,hint_ignore)
641 => if List.contains(hint_memlocs, dst', MemLoc.eq)
645 else (hint_register,hint_memlocs,hint_ignore))
648 val info = {dead = dead,
657 fun toLiveness (assembly: Assembly.t list) : ((Assembly.t * t) list)
662 {assembly = [], future = [], hint = []},
663 fn (asm, {assembly,future,hint})
665 val info as {futures = {pre, ...}, hint, ...}
666 = livenessAssembly {assembly = asm,
670 {assembly = (asm,info)::assembly,
678 val (toLiveness,toLiveness_msg)
683 fun toNoLiveness (assembly: Assembly.t list) : ((Assembly.t * t) list)
684 = List.map(assembly, fn asm => (asm,{dead = MemLocSet.empty,
685 commit = MemLocSet.empty,
686 remove = MemLocSet.empty,
687 futures = {pre = [], post = []},
690 val (toNoLiveness,toNoLiveness_msg)
696 structure RegisterAllocation =
699 val spill : Int.t ref = ref 0
700 val spillLabel = Label.fromString "spill"
701 val depth : Int.t ref = ref 0
712 | COMMIT i => "COMMIT " ^ (Int.toString i)
713 | REMOVE i => "REMOVE " ^ (Int.toString i)
714 | TRYCOMMIT i => "TRYCOMMIT " ^ (Int.toString i)
715 | TRYREMOVE i => "TRYREMOVE " ^ (Int.toString i)
717 type value = {register: Register.t,
723 fun value_toString {register, memloc, weight, sync, commit}
724 = concat [Register.toString register, " ",
725 MemLoc.toString memloc, " ",
726 Int.toString weight, " ",
727 Bool.toString sync, " ",
728 commit_toString commit]
730 type fltvalue = {fltregister: FltRegister.t,
736 fun fltvalue_toString {fltregister, memloc, weight, sync, commit}
737 = concat [FltRegister.toString fltregister, " ",
738 MemLoc.toString memloc, " ",
739 Int.toString weight, " ",
740 Bool.toString sync, " ",
741 commit_toString commit]
743 type t = {entries: value list,
744 reserved: Register.t list,
745 fltstack: fltvalue list}
748 fun unique ({entries, fltstack, ...}: t)
750 fun check_entries (entries: value list, res) =
753 | ({register, memloc, ...})::entries =>
758 fn ({register = register',
759 memloc = memloc', ...}, res) =>
761 andalso (not (Register.coincide (register, register')))
762 andalso (not (MemLoc.eq (memloc, memloc')))))
763 fun check_fltstack (fltstack: fltvalue list, res) =
766 | ({fltregister, memloc, ...})::fltstack =>
771 fn ({fltregister = fltregister',
772 memloc = memloc', ...}, res) =>
774 andalso (not (FltRegister.eq (fltregister, fltregister')))
775 andalso (not (MemLoc.eq (memloc, memloc')))))
777 check_entries(entries, true)
779 check_fltstack(fltstack, true)
783 fun toString ({entries, reserved, fltstack}: t)
785 fun doit (name, l, toString, ac)
789 => (toString x) ^ "\n" ^ ac))
791 doit("entries:", entries, value_toString,
792 doit("reserved:", reserved, Register.toString,
793 doit("fltstack:", fltstack, fltvalue_toString,
797 fun toComments ({entries, reserved, fltstack}: t)
799 fun doit (name, l, toString, ac)
800 = (Assembly.comment name)::
803 => (Assembly.comment (toString x))::
807 (doit("entries:", entries, value_toString,
808 doit("reserved:", reserved, Register.toString,
809 doit("fltstack:", fltstack, fltvalue_toString,
813 val {get = getRA : Directive.Id.t -> {registerAllocation: t},
815 = Property.getSetOnce
817 Property.initRaise ("getRA", fn _ => Layout.empty))
824 fun reserve' {register: Register.t,
825 registerAllocation = {entries, reserved, fltstack}: t}
826 = {assembly = AppendList.empty,
827 registerAllocation = {entries = entries,
828 reserved = register::reserved,
829 fltstack = fltstack}}
831 fun reserve {registers: Register.t list,
832 registerAllocation = {entries, reserved, fltstack}: t}
833 = {assembly = AppendList.empty,
834 registerAllocation = {entries = entries,
835 reserved = registers @ reserved,
836 fltstack = fltstack}}
838 fun unreserve' {register: Register.t,
839 registerAllocation = {entries, reserved, fltstack}: t}
840 = {assembly = AppendList.empty,
841 registerAllocation = {entries = entries,
842 reserved = List.revRemoveAll
848 fltstack = fltstack}}
850 fun unreserve {registers: Register.t list,
851 registerAllocation = {entries, reserved, fltstack}: t}
852 = {assembly = AppendList.empty,
853 registerAllocation = {entries = entries,
854 reserved = List.revRemoveAll
861 fltstack = fltstack}}
864 registerAllocation = {entries,
867 = {entries = List.revMap(entries, map),
871 fun valueFilter {filter,
872 registerAllocation = {entries,
874 = List.revKeepAll(entries, filter)
876 fun valueRegister {register,
878 = case valueFilter {filter = fn {register = register', ...}
879 => Register.eq(register, register'),
880 registerAllocation = registerAllocation}
882 | [value] => SOME value
883 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.valueRegister"
885 fun valuesRegister {register = Register.T {reg, ...},
886 registerAllocation = {entries,
888 = List.revKeepAll(entries,
890 = Register.T {reg = reg',
895 fun fltvalueMap {map,
896 registerAllocation = {entries,
899 = {entries = entries,
901 fltstack = List.map(fltstack, map)}
903 fun fltvalueFilter {filter,
904 registerAllocation = {fltstack,
906 = List.keepAll(fltstack, filter)
908 fun update {value as {register,...},
909 registerAllocation = {entries, reserved, fltstack}: t}
912 = List.revRemoveAll(entries,
913 fn {register = register',...}
914 => Register.eq(register,register'))
921 fun fltupdate {value as {fltregister, ...},
922 registerAllocation = {entries, reserved, fltstack}: t}
923 = {entries = entries,
927 = fn [] => Error.bug "x86AllocateRegisters.RegisterAllocation.fltupdate"
928 | (value' as {fltregister = fltregister', ...})::l
929 => if FltRegister.eq(fltregister, fltregister')
931 else value'::(fltupdate' l)
936 fun delete {register,
937 registerAllocation = {entries, reserved, fltstack}: t}
938 = {entries = List.revRemoveAll(entries,
939 fn {register = register',...}
940 => Register.eq(register, register')),
943 fun deletes {registers, registerAllocation: t}
944 = List.fold(registers,
946 fn (register, registerAllocation)
947 => delete {register = register,
948 registerAllocation = registerAllocation})
951 registerAllocation = {entries, reserved, fltstack}: t}
952 = {fltrename = FltRegister.push,
954 = {entries = entries,
956 fltstack = case #fltregister value
958 => value::(List.map(fltstack,
966 FltRegister.T (i + 1),
971 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.fltpush"}}
973 fun fltpop {registerAllocation = {entries, reserved, fltstack}: t}
974 = {fltrename = FltRegister.pop,
976 = {entries = entries,
978 fltstack = case fltstack
979 of [] => Error.bug "x86AllocateRegisters.RegisterAllocation.fltpop"
981 => List.map(fltstack,
982 fn {fltregister = FltRegister.T i,
988 = FltRegister.T (i - 1),
994 fun fltxch' {fltregister: FltRegister.t,
995 registerAllocation = {entries, reserved, fltstack}: t}
998 = fn (_ : fltvalue list, []) => Error.bug "x86AllocateRegisters.RegisterAllocation.fltxch'.split"
999 | (fltstack_pre,value::fltstack_post)
1000 => if FltRegister.eq(fltregister, #fltregister value)
1001 then (List.rev fltstack_pre, value, fltstack_post)
1002 else split (value::fltstack_pre, fltstack_post)
1005 {fltregister = fltregister',
1010 fltstack_post) = split ([], fltstack)
1012 {fltrename = fn fltregister
1013 => if FltRegister.eq(fltregister,
1015 then FltRegister.top
1016 else if FltRegister.eq(fltregister,
1021 = {entries = entries,
1022 reserved = reserved,
1023 fltstack = case fltstack_pre
1024 of [] => Error.bug "x86AllocateRegisters.RegisterAllocation.fltxch'"
1029 commit})::fltstack_pre
1030 => ({fltregister = fltregister,
1034 commit = commit'})::
1037 ({fltregister = fltregister',
1045 fun fltxch {value: fltvalue, registerAllocation: t}
1046 = fltxch' {fltregister = #fltregister value,
1047 registerAllocation = registerAllocation}
1049 fun fltxch1 {registerAllocation: t}
1050 = fltxch' {fltregister = FltRegister.one,
1051 registerAllocation = registerAllocation}
1053 fun allocated {memloc,
1054 registerAllocation: t}
1055 = case valueFilter {filter = fn {memloc = memloc',...}
1056 => MemLoc.eq(memloc,memloc'),
1057 registerAllocation = registerAllocation}
1059 | [value] => SOME value
1060 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.allocated"
1062 fun fltallocated {memloc,
1063 registerAllocation: t}
1064 = case fltvalueFilter {filter = fn {memloc = memloc',...}
1065 => MemLoc.eq(memloc,memloc'),
1066 registerAllocation = registerAllocation}
1068 | [value] => SOME value
1069 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.fltallocated"
1072 registerAllocation: t}
1073 = case allocated {memloc = memloc,
1074 registerAllocation = registerAllocation}
1075 of SOME {register, ...}
1076 => delete {register = register,
1077 registerAllocation = registerAllocation}
1078 | NONE => registerAllocation
1079 fun removes {memlocs,
1080 registerAllocation: t}
1081 = List.fold(memlocs,
1083 fn (memloc,registerAllocation)
1084 => remove {memloc = memloc,
1085 registerAllocation = registerAllocation})
1090 | COMMIT i => COMMIT (i + 1)
1091 | REMOVE i => REMOVE (i + 1)
1092 | TRYCOMMIT i => TRYCOMMIT (i + 1)
1093 | TRYREMOVE i => TRYREMOVE (i + 1)
1097 | COMMIT i => COMMIT (i - 1)
1098 | REMOVE i => REMOVE (i - 1)
1099 | TRYCOMMIT i => TRYCOMMIT (i - 1)
1100 | TRYREMOVE i => TRYREMOVE (i - 1)
1102 fun commitPush {registerAllocation: t}
1103 = valueMap {map = fn {register,memloc,weight,sync,commit}
1104 => {register = register,
1108 commit = commitPush' commit},
1109 registerAllocation = registerAllocation}
1111 fun commitPop {registerAllocation: t}
1112 = valueMap {map = fn {register,memloc,weight,sync,commit}
1113 => {register = register,
1117 commit = commitPop' commit},
1118 registerAllocation = registerAllocation}
1121 fun savedRegisters {saves: Operand.t list,
1122 registerAllocation: t} :
1127 => (case allocated {memloc = m,
1128 registerAllocation = registerAllocation}
1129 of SOME {register, ...} => [register]
1131 | Operand.Register r => [r]
1132 | Operand.Address (Address.T {base, index, ...})
1133 => (case (base, index)
1134 of (NONE, NONE ) => []
1135 | (SOME rb, NONE ) => [rb]
1136 | (NONE, SOME ro) => [ro]
1137 | (SOME rb, SOME ro) => [rb,ro])
1140 fun supportedRegisters {supports: Operand.t list,
1141 registerAllocation: t} :
1144 fun supportedRegisters' memloc
1145 = case (allocated {memloc = memloc,
1146 registerAllocation = registerAllocation},
1147 fltallocated {memloc = memloc,
1148 registerAllocation = registerAllocation})
1149 of (SOME {register, ...}, _) => [register]
1151 | (NONE, NONE) => List.concatMap(MemLoc.utilized memloc,
1152 supportedRegisters')
1156 fn Operand.MemLoc m => supportedRegisters' m
1160 fun supportedMemLocs {supports: Operand.t list,
1161 registerAllocation: t} :
1164 fun supportedMemLocs' memloc
1165 = case (allocated {memloc = memloc,
1166 registerAllocation = registerAllocation},
1167 fltallocated {memloc = memloc,
1168 registerAllocation = registerAllocation})
1169 of (SOME _, _) => [memloc]
1170 | (_, SOME _) => [memloc]
1171 | (NONE, NONE) => List.concatMap(MemLoc.utilized memloc,
1176 fn Operand.MemLoc m => supportedMemLocs' m
1180 fun fltsavedMemLocs {saves: Operand.t list,
1181 registerAllocation: t} :
1183 = List.revKeepAllMap
1186 => (case fltallocated {memloc = m,
1187 registerAllocation = registerAllocation}
1192 fun fltsupportedMemLocs {supports: Operand.t list,
1193 registerAllocation: t} :
1195 = List.revKeepAllMap
1198 => (case fltallocated {memloc = m,
1199 registerAllocation = registerAllocation}
1204 fun 'a spillAndReissue {info: Liveness.t,
1205 supports: Operand.t list,
1206 saves: Operand.t list,
1207 registerAllocation: t,
1208 spiller : {info: Liveness.t,
1209 supports: Operand.t list,
1210 saves: Operand.t list,
1211 registerAllocation: t} ->
1212 {assembly: Assembly.t AppendList.t,
1213 registerAllocation: t},
1215 reissue : {assembly: Assembly.t AppendList.t,
1216 registerAllocation: t} -> 'a} : 'a
1220 val _ = Int.inc depth
1221 val {assembly, registerAllocation}
1224 supports = supports,
1226 registerAllocation = registerAllocation}
1228 = reissue {assembly = assembly,
1229 registerAllocation = registerAllocation}
1231 => (Error.bug (concat [msg, ":reSpill"]))
1232 val _ = Int.dec depth
1238 fun potentialRegisters ({size, force, ...}:
1240 saves: Operand.t list,
1241 force: Register.t list,
1242 registerAllocation: t}):
1245 of [] => Register.registers size
1246 | registers => List.revKeepAll(Register.registers size,
1248 => List.contains(registers,
1252 fun chooseRegister {info = {futures = {pre = future, ...},
1253 hint,...}: Liveness.t,
1254 memloc: MemLoc.t option,
1256 supports: Operand.t list,
1257 saves: Operand.t list,
1258 force: Register.t list,
1259 registerAllocation as {reserved,...}: t} :
1260 {register: Register.t,
1261 coincide_values: value list}
1263 val registers = potentialRegisters {size = size,
1267 = registerAllocation}
1270 = savedRegisters {saves = saves,
1271 registerAllocation = registerAllocation}
1275 fun doit(registers, preserved)
1279 fn (register,preserved)
1280 => if List.contains(preserved,
1284 else register::preserved)
1298 => Register.coincide(register',register'')))
1300 val supported = supportedRegisters {supports = supports,
1302 = registerAllocation}
1304 val values = valueFilter {filter = fn _ => true,
1305 registerAllocation = registerAllocation}
1306 val memlocs = List.revMap(values, #memloc)
1317 fn ((hint_register,hint_memlocs,hint_ignore),
1319 => if Register.eq(register',
1323 => (case (List.contains
1330 of (true, _) => hint_cost + 5
1331 | (false, true) => hint_cost
1332 | (false, false) => hint_cost - 5)
1333 | NONE => hint_cost - 5
1334 else if Register.coincide(register',
1339 val values = valuesRegister {register = register',
1341 = registerAllocation}
1350 (false,false,NONE,0,true,0),
1351 fn ({register,memloc,weight,sync,commit,...},
1352 cost as (support_cost,
1358 => if Register.coincide(register,register')
1361 = List.contains(supported,
1367 of TRYREMOVE _ => false
1374 fn Liveness.M (tag, memloc')
1376 val eq = MemLoc.eq(memloc, memloc')
1379 of Liveness.FLIVE => eq
1380 | Liveness.FUSE => eq
1381 | Liveness.FUSEDEF => eq
1392 (MemLoc.utilized memloc',
1401 val sync_cost' = sync
1403 val weight_cost' = weight
1405 (support_cost orelse support_cost',
1406 commit_cost orelse commit_cost',
1407 case (future_cost,future_cost')
1408 of (_, NONE) => future_cost
1409 | (NONE, _) => future_cost'
1411 => SOME (Int.min(f,f')),
1412 utilized_cost + utilized_cost',
1413 sync_cost andalso sync_cost',
1414 weight_cost + weight_cost')
1428 val registers_costs_sorted
1429 = List.insertionSort
1445 => bool_lt(support_c1,support_c2) orelse
1446 (support_c1 = support_c2 andalso
1447 (bool_lt(commit_c1,commit_c2) orelse
1448 (commit_c1 = commit_c2 andalso
1449 (option_lt (op >) (future_c1, future_c2) orelse
1450 (future_c1 = future_c2 andalso
1451 (hint_c1 > hint_c2 orelse
1452 (hint_c1 = hint_c2 andalso
1453 (utilized_c1 < utilized_c2 orelse
1454 (utilized_c1 = utilized_c2 andalso
1455 (bool_gt(sync_c1,sync_c2) orelse
1456 (sync_c1 = sync_c2 andalso
1457 weight_c1 < weight_c2))))))))))))
1460 = List.map(registers_costs_sorted, #1)
1469 fun listToString(ss: string list): string
1470 = "[" ^ (concat(List.separate(ss, ", "))) ^ "]"
1472 val size = Size.toString size
1474 = listToString(List.map(supports,Operand.toString))
1476 = listToString(List.map(saves,Operand.toString))
1478 = listToString(List.map(force,Register.toString))
1480 = listToString(List.map(reserved,Register.toString))
1482 val msg = concat["\n",
1483 "chooseRegister:\n",
1484 (toString registerAllocation),
1485 "size = ", size, "\n",
1486 "supports = ", supports, "\n",
1487 "saves = ", saves, "\n",
1488 "force = ", force, "\n",
1489 "reserved = ", reserved, "\n",
1490 "depth = ", Int.toString (!depth), "\n"]
1494 print "Raising Spill in chooseRegister\n";
1497 | register::_ => register
1499 val values = valuesRegister {register = register,
1501 = registerAllocation}
1503 = List.revKeepAll(values,
1504 fn {register = register',...}
1505 => Register.coincide(register',register))
1507 {register = register,
1508 coincide_values = coincide_values}
1511 fun freeRegister ({info: Liveness.t,
1512 memloc: MemLoc.t option,
1514 supports: Operand.t list,
1515 saves: Operand.t list,
1516 force: Register.t list,
1517 registerAllocation: t}) :
1518 {register: Register.t,
1519 assembly: Assembly.t AppendList.t,
1520 registerAllocation: t}
1522 val _ = Int.inc depth
1524 val {register = final_register,
1526 = chooseRegister {info = info,
1529 supports = supports,
1532 registerAllocation = registerAllocation}
1534 val supported = supportedMemLocs {supports = supports,
1536 = registerAllocation}
1538 fun supportRemove memloc
1540 fun supportRemove' memlocs
1544 => if MemLoc.eq(memloc,memloc')
1546 else supportRemove' (MemLoc.utilized memloc'))
1551 fn (Operand.MemLoc memloc', supports)
1552 => List.concat [(supportRemove' [memloc']), supports]
1553 | (_, supports) => supports)
1556 val {assembly = assembly_support,
1560 {assembly = AppendList.empty,
1561 registerAllocation = registerAllocation},
1564 registerAllocation})
1565 => if List.contains(supported,
1569 val supports = supportRemove memloc
1573 (Register.registers (MemLoc.size memloc),
1575 => Register.coincide(final_register,
1578 val {assembly = assembly_register,
1584 size = MemLoc.size memloc,
1586 supports = supports,
1587 saves = (Operand.register
1588 final_register)::saves,
1590 registerAllocation = registerAllocation}
1592 {assembly = AppendList.append (assembly,
1594 registerAllocation = registerAllocation}
1596 else {assembly = assembly,
1597 registerAllocation = registerAllocation})
1599 val registerAllocation
1601 {map = fn value as {register,
1606 => if Register.coincide(register,
1608 then {register = register,
1614 registerAllocation = registerAllocation}
1616 val {assembly = assembly_commit,
1618 = commitRegisters {info = info,
1619 supports = supports,
1621 registerAllocation = registerAllocation}
1623 val _ = Int.dec depth
1625 {register = final_register,
1626 assembly = AppendList.appends [assembly_support,
1628 registerAllocation = registerAllocation}
1633 supports = supports,
1635 registerAllocation = registerAllocation,
1636 spiller = spillRegisters,
1637 msg = "freeRegister",
1638 reissue = fn {assembly = assembly_spill,
1641 val {register, assembly, registerAllocation}
1646 supports = supports,
1649 registerAllocation = registerAllocation}
1651 {register = register,
1652 assembly = AppendList.append (assembly_spill,
1654 registerAllocation = registerAllocation}
1657 and freeFltRegister {info: Liveness.t,
1659 supports: Operand.t list,
1660 saves: Operand.t list,
1661 registerAllocation: t} :
1662 {assembly: Assembly.t AppendList.t,
1663 fltrename: FltRegister.t -> FltRegister.t,
1664 registerAllocation: t}
1666 val info as {futures = {pre = future, ...},...} = info
1668 = fltvalueFilter {filter = fn _ => true,
1669 registerAllocation = registerAllocation}
1671 if List.length values >= FltRegister.total
1673 val saved = fltsavedMemLocs {saves = saves,
1675 = registerAllocation}
1677 val supported = fltsupportedMemLocs {supports = supports,
1679 = registerAllocation}
1682 = List.revRemoveAll(values,
1684 => List.contains(saved,
1691 fn value as {memloc,weight,sync,commit,...}
1694 = List.contains(supported,
1700 of TRYREMOVE _ => false
1707 fn Liveness.M (tag, memloc')
1709 val eq = MemLoc.eq(memloc, memloc')
1712 of Liveness.FLIVE => eq
1713 | Liveness.FUSE => eq
1714 | Liveness.FUSEDEF => eq
1719 val sync_cost = sync
1721 val weight_cost = weight
1731 val values_costs_sorted
1732 = List.insertionSort
1744 => bool_lt(support_c1,support_c2) orelse
1745 (support_c1 = support_c2 andalso
1746 (bool_lt(commit_c1,commit_c2) orelse
1747 (commit_c1 = commit_c2 andalso
1749 (future_c1, future_c2) orelse
1750 (future_c1 = future_c2 andalso
1751 (bool_gt(sync_c1,sync_c2) orelse
1752 (sync_c1 = sync_c2 andalso
1753 weight_c1 < weight_c2))))))))
1755 val values = List.map(values_costs_sorted, #1)
1758 of [] => Error.bug "x86AllocateRegisters.RegisterAllocation.freeFltRegister"
1765 val registerAllocation
1766 = fltupdate {value = {fltregister = fltregister,
1772 = registerAllocation}
1774 val {assembly = assembly_commit,
1775 fltrename = fltrename_commit,
1777 = commitFltRegisters {info = info,
1778 supports = supports,
1781 = registerAllocation}
1783 {assembly = assembly_commit,
1784 fltrename = fltrename_commit,
1785 registerAllocation = registerAllocation}
1788 else {assembly = AppendList.empty,
1789 fltrename = FltRegister.id,
1790 registerAllocation = registerAllocation}
1795 supports = supports,
1797 registerAllocation = registerAllocation,
1798 spiller = spillRegisters,
1799 msg = "freeFltRegisters",
1800 reissue = fn {assembly = assembly_spill,
1803 val {assembly, fltrename, registerAllocation}
1807 supports = supports,
1809 registerAllocation = registerAllocation}
1811 {assembly = AppendList.append (assembly_spill,
1813 fltrename = fltrename,
1814 registerAllocation = registerAllocation}
1817 and commitRegisters {info: Liveness.t,
1818 supports: Operand.t list,
1819 saves: Operand.t list,
1820 registerAllocation as {reserved,...}: t} :
1821 {assembly: Assembly.t AppendList.t,
1822 registerAllocation: t}
1824 val _ = Int.inc depth
1826 = valueFilter {filter = fn {commit = COMMIT 0, ...} => true
1827 | {commit = REMOVE 0, ...} => true
1828 | {commit = TRYCOMMIT 0, ...} => true
1829 | {commit = TRYREMOVE 0, ...} => true
1831 registerAllocation = registerAllocation}
1833 val commit_memlocs = List.revMap(commit_values, #memloc)
1838 fn (memloc1,memloc2)
1839 => List.contains(MemLoc.utilized memloc1,
1843 val {assembly = assembly_commit,
1847 {assembly = AppendList.empty,
1848 registerAllocation = registerAllocation},
1851 registerAllocation})
1852 => (case allocated {memloc = memloc,
1854 = registerAllocation}
1855 of NONE => {assembly = assembly,
1856 registerAllocation = registerAllocation}
1863 fun doCommitFalse ()
1865 val registerAllocation
1866 = update {value = {register = register,
1872 = registerAllocation}
1874 val registerAllocation
1875 = commitPush {registerAllocation
1876 = registerAllocation}
1879 = List.removeDuplicates
1880 ((Operand.register register)::saves,
1883 val size = Register.size register
1885 assembly = assembly_address,
1887 = toAddressMemLoc {memloc = memloc,
1890 supports = supports,
1891 saves = commit_saves,
1893 = registerAllocation}
1895 val registerAllocation
1896 = commitPop {registerAllocation
1897 = registerAllocation}
1900 = AppendList.appends
1904 (Assembly.instruction_mov
1905 {dst = Operand.Address address,
1906 src = Operand.Register register,
1908 registerAllocation = registerAllocation}
1913 val registerAllocation
1914 = update {value = {register = register,
1920 = registerAllocation}
1922 {assembly = assembly,
1923 registerAllocation = registerAllocation}
1926 fun doRemoveFalse ()
1928 val registerAllocation
1929 = update {value = {register = register,
1935 = registerAllocation}
1937 val registerAllocation
1938 = commitPush {registerAllocation
1939 = registerAllocation}
1942 = List.removeDuplicates
1943 ((Operand.register register)::saves,
1946 val size = Register.size register
1948 assembly = assembly_address,
1950 = toAddressMemLoc {memloc = memloc,
1953 supports = supports,
1954 saves = commit_saves,
1956 = registerAllocation}
1958 val registerAllocation
1959 = commitPop {registerAllocation
1960 = registerAllocation}
1962 val registerAllocation
1967 then registerAllocation
1968 else remove {memloc = memloc,
1970 = registerAllocation}
1973 = AppendList.appends
1977 (Assembly.instruction_mov
1978 {dst = Operand.Address address,
1979 src = Operand.Register register,
1981 registerAllocation = registerAllocation}
1986 val registerAllocation
1987 = update {value = {register = register,
1993 = registerAllocation}
1995 val registerAllocation
2000 then registerAllocation
2001 else remove {memloc = memloc,
2003 = registerAllocation}
2005 {assembly = assembly,
2006 registerAllocation = registerAllocation}
2010 of (COMMIT 0, false) => doCommitFalse ()
2011 | (COMMIT 0, true) => doCommitTrue ()
2012 | (REMOVE 0, false) => doRemoveFalse ()
2013 | (REMOVE 0, true) => doRemoveTrue ()
2014 | (TRYCOMMIT 0, false) => doCommitFalse ()
2015 | (TRYCOMMIT 0, true) => doCommitTrue ()
2016 | (TRYREMOVE 0, false) => doRemoveFalse ()
2017 | (TRYREMOVE 0, true) => doRemoveTrue ()
2019 => Error.bug "x86AllocateRegisters.RegisterAllocation.commitRegisters"
2021 val _ = Int.dec depth
2023 {assembly = assembly_commit,
2024 registerAllocation = registerAllocation}
2029 supports = supports,
2031 registerAllocation = registerAllocation,
2032 spiller = spillRegisters,
2033 msg = "commitRegisters",
2034 reissue = fn {assembly = assembly_spill,
2037 val {assembly, registerAllocation}
2040 supports = supports,
2042 registerAllocation = registerAllocation}
2044 {assembly = AppendList.append (assembly_spill,
2046 registerAllocation = registerAllocation}
2049 and commitFltRegisters {info: Liveness.t,
2050 supports: Operand.t list,
2051 saves: Operand.t list,
2052 registerAllocation: t} :
2053 {assembly: Assembly.t AppendList.t,
2054 fltrename: FltRegister.t -> FltRegister.t,
2055 registerAllocation: t}
2057 val _ = Int.inc depth
2059 = fltvalueFilter {filter
2060 = fn {commit = COMMIT 0, ...} => true
2061 | {commit = REMOVE 0, ...} => true
2062 | {commit = TRYCOMMIT 0, ...} => true
2063 | {commit = TRYREMOVE 0, ...} => true
2065 registerAllocation = registerAllocation}
2067 val {assembly = assembly_commit,
2068 fltrename = fltrename_commit,
2072 {assembly = AppendList.empty,
2073 fltrename = FltRegister.id,
2074 registerAllocation = registerAllocation},
2080 {assembly, fltrename, registerAllocation})
2082 fun doCommitFalse ()
2084 val fltregister = fltrename fltregister
2085 val {assembly = assembly_xch,
2086 fltrename = fltrename_xch,
2088 = if FltRegister.eq(fltregister,
2090 then {assembly = AppendList.empty,
2091 fltrename = FltRegister.id,
2093 = registerAllocation}
2095 val {fltrename = fltrename_xch,
2098 {fltregister = fltregister,
2100 = registerAllocation}
2104 (Assembly.instruction_fxch
2105 {src = Operand.fltregister
2107 fltrename = fltrename_xch,
2109 = registerAllocation}
2112 val size = MemLoc.size memloc
2115 assembly = assembly_address,
2117 = toAddressMemLoc {memloc = memloc,
2120 supports = supports,
2123 = registerAllocation}
2125 val registerAllocation
2127 = {fltregister = FltRegister.top,
2133 = registerAllocation}
2136 = AppendList.appends
2140 case Size.class size
2142 => AppendList.single
2143 (Assembly.instruction_fst
2144 {dst = Operand.Address address,
2148 => AppendList.single
2149 (Assembly.instruction_fist
2150 {dst = Operand.Address address,
2153 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.commitFltRegisters"],
2155 = fltrename_xch o fltrename,
2156 registerAllocation = registerAllocation}
2161 val fltregister = fltrename fltregister
2162 val registerAllocation
2164 {value = {fltregister = fltregister,
2169 registerAllocation = registerAllocation}
2171 {assembly = assembly,
2172 fltrename = fltrename,
2173 registerAllocation = registerAllocation}
2176 fun doRemoveFalse ()
2178 val fltregister = fltrename fltregister
2179 val {assembly = assembly_xch,
2180 fltrename = fltrename_xch,
2182 = if FltRegister.eq(fltregister,
2184 then {assembly = AppendList.empty,
2185 fltrename = FltRegister.id,
2187 = registerAllocation}
2189 val {fltrename = fltrename_xch,
2192 {fltregister = fltregister,
2194 = registerAllocation}
2198 (Assembly.instruction_fxch
2199 {src = Operand.fltregister
2201 fltrename = fltrename_xch,
2203 = registerAllocation}
2206 val size = MemLoc.size memloc
2209 assembly = assembly_address,
2211 = toAddressMemLoc {memloc = memloc,
2214 supports = supports,
2217 = registerAllocation}
2219 val {fltrename = fltrename_pop,
2222 {registerAllocation = registerAllocation}
2225 = AppendList.appends
2229 case Size.class size
2231 => AppendList.single
2232 (Assembly.instruction_fst
2233 {dst = Operand.Address address,
2237 => AppendList.single
2238 (Assembly.instruction_fist
2239 {dst = Operand.Address address,
2242 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.commitFltRegisters"],
2244 = fltrename_pop o fltrename_xch o fltrename,
2245 registerAllocation = registerAllocation}
2250 val fltregister = fltrename fltregister
2251 val {assembly = assembly_xch,
2252 fltrename = fltrename_xch,
2254 = if FltRegister.eq(fltregister,
2256 then {assembly = AppendList.empty,
2257 fltrename = FltRegister.id,
2259 = registerAllocation}
2261 val {fltrename = fltrename_xch,
2264 {fltregister = fltregister,
2266 = registerAllocation}
2270 (Assembly.instruction_fxch
2271 {src = Operand.fltregister
2273 fltrename = fltrename_xch,
2275 = registerAllocation}
2278 val {fltrename = fltrename_pop,
2280 = fltpop {registerAllocation
2281 = registerAllocation}
2283 val size = MemLoc.size memloc
2286 = AppendList.appends
2289 case Size.class size
2291 => AppendList.single
2292 (Assembly.instruction_fst
2293 {dst = Operand.fltregister
2298 => AppendList.single
2299 (Assembly.instruction_fst
2300 {dst = Operand.fltregister
2304 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.commitFltRegisters"],
2305 fltrename = fltrename_pop o fltrename_xch o fltrename,
2306 registerAllocation = registerAllocation}
2310 = {assembly = assembly,
2311 fltrename = fltrename,
2312 registerAllocation = registerAllocation}
2315 of (COMMIT 0, false) => doCommitFalse ()
2316 | (COMMIT 0, true) => doCommitTrue ()
2317 | (REMOVE 0, false) => doRemoveFalse ()
2318 | (REMOVE 0, true) => doRemoveTrue ()
2319 | (TRYCOMMIT 0, false)
2320 => if FltRegister.eq(fltrename fltregister,
2322 then doCommitFalse ()
2324 | (TRYCOMMIT 0, true)
2325 => if FltRegister.eq(fltrename fltregister,
2327 then doCommitTrue ()
2329 | (TRYREMOVE 0, false)
2330 => if FltRegister.eq(fltrename fltregister,
2332 then doRemoveFalse ()
2334 | (TRYREMOVE 0, true)
2335 => if FltRegister.eq(fltrename fltregister,
2337 then doRemoveTrue ()
2339 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.commitFltRegisters"
2342 val _ = Int.dec depth
2344 {assembly = assembly_commit,
2345 fltrename = fltrename_commit,
2346 registerAllocation = registerAllocation}
2351 supports = supports,
2353 registerAllocation = registerAllocation,
2354 spiller = spillRegisters,
2355 msg = "commitFltRegisters",
2356 reissue = fn {assembly = assembly_spill,
2359 val {assembly, fltrename, registerAllocation}
2360 = commitFltRegisters
2362 supports = supports,
2364 registerAllocation = registerAllocation}
2366 {assembly = AppendList.append (assembly_spill,
2368 fltrename = fltrename,
2369 registerAllocation = registerAllocation}
2372 and spillRegisters {info: Liveness.t,
2373 supports: Operand.t list,
2374 saves: Operand.t list,
2375 registerAllocation} :
2376 {assembly: Assembly.t AppendList.t,
2377 registerAllocation: t}
2379 val _ = Int.inc depth
2380 val spillStart = !spill
2382 val {reserved, ...} = registerAllocation
2383 val {assembly = assembly_unreserve,
2387 {assembly = AppendList.empty,
2388 registerAllocation = registerAllocation},
2390 {assembly, registerAllocation})
2392 val {assembly = assembly_unreserve,
2395 {register = register,
2396 registerAllocation = registerAllocation}
2398 {assembly = AppendList.append (assembly,
2399 assembly_unreserve),
2400 registerAllocation = registerAllocation}
2403 val saved = savedRegisters {saves = saves,
2404 registerAllocation = registerAllocation}
2406 val saved = List.fold
2410 => if List.contains(saved,register,Register.eq)
2412 else register::saved)
2414 val saves = valueFilter
2415 {filter = fn {register, ...}
2416 => List.contains(saved,
2419 registerAllocation = registerAllocation}
2421 val all = valueFilter
2422 {filter = fn _ => true,
2423 registerAllocation = registerAllocation}
2425 (* partition the values in the register file
2426 * by their base register.
2428 val groups = partition (all,
2429 fn ({register = Register.T {reg = reg1, ...},...},
2430 {register = Register.T {reg = reg2, ...},...})
2433 (* order the groups by number of registers used
2436 = List.insertionSort
2438 fn (g1,g2) => (List.length g1) < (List.length g2))
2440 (* choose four registers to spill
2444 of g1::g2::g3::g4::_ => List.concat [g1,g2,g3,g4]
2445 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.spillRegisters"
2447 (* totally order the spills by utilization
2452 fn ({memloc = memloc1, ...},
2453 {memloc = memloc2, ...})
2454 => List.contains(MemLoc.utilized memloc2,
2458 fun mkReplacer (spillMap : (value * MemLoc.t) list)
2460 => case List.peek(spillMap, fn ({memloc,...},_)
2461 => MemLoc.eq(memloc,memloc'))
2462 of SOME (_,spillMemloc) => spillMemloc
2465 (* associate each spilled value with a spill slot
2467 val (spillMap, spillEnd)
2471 fn (value as {memloc, ...},
2472 (spillMap, spillEnd))
2475 = MemLoc.imm {base = Immediate.label spillLabel,
2476 index = Immediate.int spillEnd,
2477 scale = x86MLton.wordScale,
2478 size = MemLoc.size memloc,
2479 class = x86MLton.Classes.Temp}
2481 ((value,spillMemLoc)::spillMap,
2485 val replacer = mkReplacer spillMap
2487 (* commit everything in the register file;
2488 * also replace all memlocs that are spilled with their spill slot
2490 val registerAllocation
2491 = valueMap {map = fn {register, memloc, weight, sync, commit}
2494 fn ({memloc = memloc',...},_)
2495 => MemLoc.eq(memloc,memloc'))
2496 then {register = register,
2497 memloc = MemLoc.replace replacer memloc,
2501 else {register = register,
2502 memloc = MemLoc.replace replacer memloc,
2505 commit = case commit
2507 | COMMIT _ => COMMIT 0
2508 | TRYCOMMIT _ => COMMIT 0
2509 | REMOVE _ => REMOVE 0
2510 | TRYREMOVE _ => REMOVE 0},
2511 registerAllocation = registerAllocation}
2513 (* update next available spill slot for cascading spills *)
2514 val _ = spill := spillEnd
2515 (* commit everything;
2516 * since the spilt memlocs look like they are spill slots,
2517 * they can all be committed to memory without any additional
2520 val {assembly = assembly_commit1,
2521 registerAllocation = registerAllocation}
2526 registerAllocation = registerAllocation}
2528 (* unspill; as we pull values in, we update the memloc to what it
2529 * looks under the pending unspills, and then replace any occurences
2530 * of the spill slot with the updated memloc;
2531 * by the time we are done, everything should be mapped back to
2532 * its original form.
2534 val {assembly = assembly_unspill,
2535 registerAllocation = registerAllocation}
2538 = fn ([],{assembly,registerAllocation})
2539 => {assembly = assembly,
2540 registerAllocation = registerAllocation}
2541 | (({memloc, weight, sync, commit, ...},
2542 spillMemLoc)::spillMap,
2543 {assembly, registerAllocation})
2545 val replacer = mkReplacer spillMap
2546 val memloc' = MemLoc.replace replacer memloc
2549 assembly = assembly_unspill,
2552 {memloc = spillMemLoc,
2554 size = MemLoc.size memloc,
2559 registerAllocation = registerAllocation}
2560 val registerAllocation
2561 = update {value = {register = register,
2568 | COMMIT _ => COMMIT 0
2569 | TRYCOMMIT _ => COMMIT 0
2570 | REMOVE _ => REMOVE 0
2571 | TRYREMOVE _ => REMOVE 0},
2572 registerAllocation = registerAllocation}
2574 val registerAllocation
2576 {map = fn {register,
2581 => {register = register,
2582 memloc = MemLoc.replace
2583 (fn memloc'' => if MemLoc.eq
2592 registerAllocation = registerAllocation}
2596 {assembly = AppendList.append (assembly,
2598 registerAllocation = registerAllocation})
2602 {assembly = AppendList.empty,
2603 registerAllocation = registerAllocation})
2605 (* everything is unspilled *)
2606 val _ = spill := spillStart
2608 (* commit all the memlocs that got spilled.
2610 val {assembly = assembly_commit2,
2611 registerAllocation = registerAllocation}
2616 registerAllocation = registerAllocation}
2617 val _ = spill := spillStart
2619 (* restore the saved operands to their previous locations.
2621 val {assembly = assembly_restore,
2625 {assembly = AppendList.empty,
2626 registerAllocation = registerAllocation},
2627 fn ({register, memloc, weight, commit, ...},
2628 {assembly, registerAllocation})
2630 val {assembly = assembly_register,
2636 size = Register.size register,
2638 supports = supports,
2641 registerAllocation = registerAllocation}
2642 val registerAllocation
2643 = update {value = {register = register,
2648 registerAllocation = registerAllocation}
2649 val {assembly = assembly_reserve,
2651 = reserve' {register = register,
2652 registerAllocation = registerAllocation}
2654 {assembly = AppendList.appends [assembly,
2657 registerAllocation = registerAllocation}
2659 val {assembly = assembly_unreserve',
2663 {assembly = AppendList.empty,
2664 registerAllocation = registerAllocation},
2666 {assembly, registerAllocation})
2668 val {assembly = assembly_unreserve',
2671 {register = register,
2672 registerAllocation = registerAllocation}
2674 {assembly = AppendList.append (assembly,
2675 assembly_unreserve'),
2676 registerAllocation = registerAllocation}
2678 val {assembly = assembly_reserve,
2682 {assembly = AppendList.empty,
2683 registerAllocation = registerAllocation},
2685 {assembly, registerAllocation})
2687 val {assembly = assembly_reserve,
2690 {register = register,
2691 registerAllocation = registerAllocation}
2693 {assembly = AppendList.append (assembly,
2695 registerAllocation = registerAllocation}
2698 val _ = Int.dec depth
2700 {assembly = AppendList.appends [assembly_unreserve,
2705 assembly_unreserve',
2707 registerAllocation = registerAllocation}
2710 and toRegisterMemLoc {memloc: MemLoc.t,
2714 supports: Operand.t list,
2715 saves: Operand.t list,
2716 force: Register.t list,
2717 registerAllocation: t} :
2718 {register: Register.t,
2719 assembly: Assembly.t AppendList.t,
2720 registerAllocation: t}
2722 (case allocated {memloc = memloc,
2723 registerAllocation = registerAllocation}
2724 of SOME {register,memloc,weight,sync,commit}
2727 = potentialRegisters {size = size,
2731 = registerAllocation}
2733 if List.contains(registers, register, Register.eq)
2734 then {register = register,
2735 assembly = AppendList.empty,
2736 registerAllocation = registerAllocation}
2738 val {register = final_register,
2742 memloc = SOME memloc,
2744 supports = supports,
2745 saves = (Operand.register register)::saves,
2747 registerAllocation = registerAllocation}
2752 = if List.contains(saves,
2753 Operand.register final_register,
2756 List.contains(saves,
2757 Operand.memloc memloc,
2761 {base = Immediate.label
2762 (Label.fromString "BUG"),
2763 index = Immediate.zero,
2765 size = MemLoc.size memloc,
2766 class = MemLoc.Class.Temp},
2769 = registerAllocation}
2770 else {memloc = memloc,
2773 = delete {register = register,
2775 = registerAllocation}}
2777 case coincide_values
2781 val registerAllocation
2790 = registerAllocation}
2792 {register = final_register,
2795 (Assembly.instruction_mov
2796 {src = Operand.register register,
2797 dst = Operand.register
2801 = registerAllocation}
2804 val registerAllocation
2813 = registerAllocation}
2815 {register = final_register,
2816 assembly = AppendList.empty,
2818 = registerAllocation}
2820 | [{register = register',
2825 => if Register.eq(register',final_register)
2827 val registerAllocation
2831 = registerAllocation}
2832 val registerAllocation
2841 = registerAllocation}
2845 val registerAllocation
2855 = registerAllocation}
2857 {register = final_register,
2860 (Assembly.instruction_xchg
2861 {src = Operand.register
2863 dst = Operand.register
2867 = registerAllocation}
2870 val registerAllocation
2880 = registerAllocation}
2882 {register = final_register,
2885 (Assembly.instruction_mov
2886 {src = Operand.register
2888 dst = Operand.register
2892 = registerAllocation}
2896 val {register = final_register,
2897 assembly = assembly_register,
2901 memloc = SOME memloc,
2903 supports = supports,
2904 saves = (Operand.register
2908 = registerAllocation}
2909 val registerAllocation
2913 = registerAllocation}
2917 val registerAllocation
2927 = registerAllocation}
2929 {register = final_register,
2931 = AppendList.appends
2934 (Assembly.instruction_mov
2935 {src = Operand.register
2937 dst = Operand.register
2941 = registerAllocation}
2944 val registerAllocation
2954 = registerAllocation}
2956 {register = final_register,
2958 = assembly_register,
2960 = registerAllocation}
2965 val {register = final_register,
2966 assembly = assembly_register,
2968 = freeRegister {info = info,
2969 memloc = SOME memloc,
2971 supports = supports,
2972 saves = (Operand.register
2976 = registerAllocation}
2977 val registerAllocation
2978 = remove {memloc = memloc,
2980 = registerAllocation}
2984 val registerAllocation
2993 = registerAllocation}
2995 {register = final_register,
2997 = AppendList.appends
3000 (Assembly.instruction_mov
3001 {src = Operand.register
3003 dst = Operand.register
3007 = registerAllocation}
3010 val registerAllocation
3019 = registerAllocation}
3021 {register = final_register,
3023 = assembly_register,
3025 = registerAllocation}
3033 then case MemLoc.size memloc
3036 val {register = register',
3037 assembly = assembly_register,
3041 memloc = SOME memloc,
3043 supports = (Operand.memloc memloc)::
3048 = registerAllocation}
3051 assembly = assembly_address,
3057 supports = supports,
3058 saves = (Operand.register register')::
3060 registerAllocation = registerAllocation}
3063 val registerAllocation
3066 registerAllocation = registerAllocation}
3068 val registerAllocation
3070 {value = {register = register',
3075 registerAllocation = registerAllocation}
3078 assembly = assembly_force,
3085 supports = supports,
3088 registerAllocation = registerAllocation}
3091 {register = register,
3093 = AppendList.appends
3097 (Assembly.instruction_mov
3098 {dst = Operand.register register',
3099 src = Operand.address address,
3102 registerAllocation = registerAllocation}
3107 assembly = assembly_address,
3113 supports = supports,
3115 registerAllocation = registerAllocation}
3119 of Address.T {base = SOME base',
3120 index = SOME index',
3122 => (Operand.register base')::
3123 (Operand.register index')::saves
3124 | Address.T {base = SOME base',
3126 => (Operand.register base')::saves
3127 | Address.T {index = SOME index',
3129 => (Operand.register index')::saves
3132 val {register = register',
3133 assembly = assembly_register,
3137 memloc = SOME memloc,
3139 supports = supports,
3142 registerAllocation = registerAllocation}
3144 val registerAllocation
3147 registerAllocation = registerAllocation}
3149 val registerAllocation
3151 {value = {register = register',
3156 registerAllocation = registerAllocation}
3159 assembly = assembly_force,
3166 supports = supports,
3169 registerAllocation = registerAllocation}
3172 {register = register,
3174 = AppendList.appends
3178 (Assembly.instruction_mov
3179 {dst = Operand.register register',
3180 src = Operand.address address,
3183 registerAllocation = registerAllocation}
3187 assembly = assembly_register,
3189 = freeRegister {info = info,
3190 memloc = SOME memloc,
3192 supports = supports,
3196 = registerAllocation}
3197 val registerAllocation
3198 = remove {memloc = memloc,
3199 registerAllocation = registerAllocation}
3201 val registerAllocation
3202 = update {value = {register = register,
3207 registerAllocation = registerAllocation}
3209 {register = register,
3210 assembly = assembly_register,
3211 registerAllocation = registerAllocation}
3213 before (Int.dec depth))
3217 supports = supports,
3219 registerAllocation = registerAllocation,
3220 spiller = spillRegisters,
3221 msg = "toRegisterMemLoc",
3222 reissue = fn {assembly = assembly_spill,
3225 val {register, assembly, registerAllocation}
3231 supports = supports,
3234 registerAllocation = registerAllocation}
3236 {register = register,
3237 assembly = AppendList.append (assembly_spill,
3239 registerAllocation = registerAllocation}
3242 and toFltRegisterMemLoc {memloc: MemLoc.t,
3246 supports: Operand.t list,
3247 saves: Operand.t list,
3249 registerAllocation: t} :
3250 {fltregister: FltRegister.t,
3251 assembly: Assembly.t AppendList.t,
3252 fltrename : FltRegister.t -> FltRegister.t,
3253 registerAllocation: t}
3255 (case fltallocated {memloc = memloc,
3256 registerAllocation = registerAllocation}
3257 of SOME (value as {fltregister,memloc,weight,sync,commit})
3258 => (case (FltRegister.eq(fltregister, FltRegister.top),
3262 val {fltrename = fltrename_pop,
3264 = fltpop {registerAllocation
3265 = registerAllocation}
3268 (Assembly.instruction_fst
3269 {dst = Operand.fltregister FltRegister.top,
3273 val {registerAllocation,
3275 = fltpush {value = {fltregister = FltRegister.top,
3280 registerAllocation = registerAllocation}
3282 {fltregister = FltRegister.top,
3283 assembly = assembly_pop,
3284 fltrename = fltrename_pop,
3285 registerAllocation = registerAllocation}
3289 val {fltrename = fltrename_xch,
3291 = fltxch {value = value,
3293 = registerAllocation}
3296 (Assembly.instruction_fxch
3297 {src = Operand.fltregister fltregister})
3299 val {fltrename = fltrename_pop,
3301 = fltpop {registerAllocation
3302 = registerAllocation}
3305 (Assembly.instruction_fst
3306 {dst = Operand.fltregister FltRegister.top,
3310 val {registerAllocation,
3312 = fltpush {value = {fltregister = FltRegister.top,
3317 registerAllocation = registerAllocation}
3319 {fltregister = FltRegister.top,
3320 assembly = AppendList.append (assembly_xch,
3322 fltrename = fltrename_pop o fltrename_xch,
3323 registerAllocation = registerAllocation}
3325 | (false, SOME true)
3327 val {fltrename = fltrename_xch,
3329 = fltxch {value = value,
3331 = registerAllocation}
3334 (Assembly.instruction_fxch
3335 {src = Operand.fltregister fltregister})
3337 {fltregister = FltRegister.top,
3338 assembly = assembly_xch,
3339 fltrename = fltrename_xch,
3340 registerAllocation = registerAllocation}
3343 => {fltregister = fltregister,
3344 assembly = AppendList.empty,
3345 fltrename = FltRegister.id,
3346 registerAllocation = registerAllocation})
3348 => (case (top, move)
3351 val {assembly = assembly_free,
3352 fltrename = fltrename_free,
3354 = registerAllocation}
3355 = freeFltRegister {info = info,
3357 supports = supports,
3360 = registerAllocation}
3362 val {registerAllocation,
3364 = fltpush {value = {fltregister = FltRegister.top,
3369 registerAllocation = registerAllocation}
3371 {fltregister = FltRegister.top,
3372 assembly = assembly_free,
3373 fltrename = fltrename_free,
3374 registerAllocation = registerAllocation}
3378 val {assembly = assembly_free,
3379 fltrename = fltrename_free,
3381 = registerAllocation}
3382 = freeFltRegister {info = info,
3384 supports = supports,
3387 = registerAllocation}
3390 assembly = assembly_address,
3392 = toAddressMemLoc {memloc = memloc,
3395 supports = supports,
3398 = registerAllocation}
3400 val {fltrename = fltrename_push,
3402 = fltpush {value = {fltregister = FltRegister.top,
3407 registerAllocation = registerAllocation}
3410 = case Size.class size
3412 => AppendList.single
3413 (Assembly.instruction_fld
3414 {src = Operand.address address,
3417 => AppendList.single
3418 (Assembly.instruction_fild
3419 {src = Operand.address address,
3422 => Error.bug "x86AllocateRegisters.RegisterAllocation.toFltRegisterMemLoc: size"
3424 {fltregister = FltRegister.top,
3425 assembly = AppendList.appends
3429 fltrename = fltrename_push o fltrename_free,
3430 registerAllocation = registerAllocation}
3433 => Error.bug "x86AllocateRegisters.RegisterAllocation.toFltRegisterMemLoc: (top, move)"))
3434 before (Int.dec depth))
3438 supports = supports,
3440 registerAllocation = registerAllocation,
3441 spiller = spillRegisters,
3442 msg = "toFltRegisterMemLoc",
3443 reissue = fn {assembly = assembly_spill,
3446 val {fltregister, assembly,
3447 fltrename, registerAllocation}
3448 = toFltRegisterMemLoc
3453 supports = supports,
3456 registerAllocation = registerAllocation}
3458 {fltregister = fltregister,
3459 assembly = AppendList.append (assembly_spill,
3461 fltrename = fltrename,
3462 registerAllocation = registerAllocation}
3465 and toAddressMemLoc {memloc: MemLoc.t,
3468 supports: Operand.t list,
3469 saves: Operand.t list,
3470 registerAllocation: t} :
3471 {address: Address.t,
3472 assembly: Assembly.t AppendList.t,
3473 registerAllocation: t}
3476 val MemLoc.U {immBase, memBase, immIndex, memIndex, scale, ...}
3477 = MemLoc.destruct memloc
3479 (* If PIC, find labels with RBX-relative addressing.
3480 * It's bigger and slower, so only use it if we must.
3482 val (mungeLabel, base) = picRelative ()
3485 = case (immBase, immIndex) of
3486 (NONE, NONE) => Immediate.zero
3487 | (SOME immBase, NONE)
3488 => (case Immediate.destruct immBase of
3489 Immediate.Word _ => immBase
3490 | Immediate.Label l =>
3491 Immediate.label (mungeLabel l)
3492 | Immediate.LabelPlusWord (l, w) =>
3493 Immediate.labelPlusWord (mungeLabel l, w))
3494 | (NONE, SOME immIndex)
3495 => (case Immediate.destruct immIndex of
3496 Immediate.Word _ => immIndex
3497 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.toAddressMemLoc:indexLabel")
3498 | (SOME immBase, SOME immIndex)
3499 => (case (Immediate.destruct immBase, Immediate.destruct immIndex) of
3500 (Immediate.Label l1, Immediate.Word w2) =>
3501 Immediate.labelPlusWord (mungeLabel l1, w2)
3502 | (Immediate.LabelPlusWord (l1, w1), Immediate.Word w2) =>
3503 Immediate.labelPlusWord (mungeLabel l1, WordX.add (w1, w2))
3504 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.toAddressMemLoc:disp")
3506 val {register = register_base,
3507 assembly = assembly_base,
3509 = case (Immediate.destruct disp, memBase) of
3510 (Immediate.Word _, NONE)
3511 => {register = NONE,
3512 assembly = AppendList.empty,
3513 registerAllocation = registerAllocation}
3514 | (Immediate.Word _, SOME memBase) (* no label, no PIC *)
3516 val {register, assembly, registerAllocation}
3520 size = MemLoc.size memBase,
3526 => (Operand.memloc memIndex)::
3529 force = Register.baseRegisters,
3530 registerAllocation = registerAllocation}
3532 {register = SOME register,
3533 assembly = assembly,
3534 registerAllocation = registerAllocation}
3536 | (_, SOME _) (* label & memBase? bad input *)
3537 => Error.bug "x86AllocateRegisters.RegisterAllocation.toAddressMemLoc:base*2"
3538 | (_, NONE) (* label only -> use PIC if needed *)
3539 => {register = base,
3540 assembly = AppendList.empty,
3541 registerAllocation = registerAllocation}
3543 val {register = register_index,
3544 assembly = assembly_index,
3547 of NONE => {register = NONE,
3548 assembly = AppendList.empty,
3549 registerAllocation = registerAllocation}
3552 val {register, assembly, registerAllocation}
3556 size = MemLoc.size memIndex,
3558 supports = supports,
3560 = case (memBase, register_base)
3561 of (NONE, _) => saves
3562 | (SOME memBase, SOME register_base)
3563 => (Operand.memloc memBase)::
3564 (Operand.register register_base)::
3566 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.toAddressMemLoc",
3567 force = Register.indexRegisters,
3568 registerAllocation = registerAllocation}
3570 {register = SOME register,
3571 assembly = assembly,
3572 registerAllocation = registerAllocation}
3575 {address = Address.T {disp = SOME disp,
3576 base = register_base,
3577 index = register_index,
3578 scale = case memIndex
3579 of SOME _ => SOME scale
3581 assembly = AppendList.append (assembly_base,
3583 registerAllocation = registerAllocation}
3587 (case MemLoc.destruct memloc
3588 of MemLoc.U {base = MemLoc.Imm base, index = MemLoc.Imm index,
3592 = if Immediate.eq(index, Immediate.const_int 0)
3594 else SOME (Immediate.binexp
3595 {oper = Immediate.Multiplication,
3597 exp2 = Scale.toImmediate scale})
3600 of NONE => SOME base
3601 | SOME disp' => SOME (Immediate.binexp
3602 {oper = Immediate.Addition,
3606 {address = Address.T {disp = disp,
3610 assembly = AppendList.empty,
3611 registerAllocation = registerAllocation}
3613 | MemLoc.U {base = MemLoc.Imm base, index = MemLoc.Mem index,
3616 val disp = SOME base
3618 val {register = register_index,
3619 assembly = assembly_index,
3621 = toRegisterMemLoc {memloc = index,
3623 size = MemLoc.size index,
3625 supports = supports,
3627 force = Register.indexRegisters,
3629 = registerAllocation}
3631 {address = Address.T {disp = disp,
3633 index = SOME register_index,
3634 scale = SOME scale},
3635 assembly = assembly_index,
3636 registerAllocation = registerAllocation}
3638 | MemLoc.U {base = MemLoc.Mem base, index = MemLoc.Imm index,
3642 = if Immediate.eq(index, Immediate.const_int 0)
3644 else SOME (Immediate.binexp
3645 {oper = Immediate.Multiplication,
3647 exp2 = Scale.toImmediate scale})
3649 val {register = register_base,
3650 assembly = assembly_base,
3652 = toRegisterMemLoc {memloc = base,
3654 size = MemLoc.size base,
3656 supports = supports,
3658 force = Register.baseRegisters,
3660 = registerAllocation}
3662 {address = Address.T {disp = disp,
3663 base = SOME register_base,
3666 assembly = assembly_base,
3667 registerAllocation = registerAllocation}
3669 | MemLoc.U {base = MemLoc.Mem base, index = MemLoc.Mem index,
3672 val {register = register_base,
3673 assembly = assembly_base,
3675 = toRegisterMemLoc {memloc = base,
3677 size = MemLoc.size base,
3680 = (Operand.memloc index)::supports,
3682 force = Register.baseRegisters,
3684 = registerAllocation}
3686 val {register = register_index,
3687 assembly = assembly_index,
3689 = toRegisterMemLoc {memloc = index,
3691 size = MemLoc.size index,
3693 supports = supports,
3694 saves = (Operand.memloc base)::
3698 force = Register.indexRegisters,
3700 = registerAllocation}
3702 {address = Address.T {disp = NONE,
3703 base = SOME register_base,
3704 index = SOME register_index,
3705 scale = SOME scale},
3706 assembly = AppendList.append (assembly_base,
3708 registerAllocation = registerAllocation}
3711 before (Int.dec depth))
3715 supports = supports,
3717 registerAllocation = registerAllocation,
3718 spiller = spillRegisters,
3719 msg = "toAddressMemLoc",
3720 reissue = fn {assembly = assembly_spill,
3723 val {address, assembly, registerAllocation}
3728 supports = supports,
3730 registerAllocation = registerAllocation}
3733 assembly = AppendList.append (assembly_spill,
3735 registerAllocation = registerAllocation}
3738 and toRegisterImmediate {immediate: Immediate.t,
3741 supports: Operand.t list,
3742 saves: Operand.t list,
3743 force: Register.t list,
3744 registerAllocation: t} :
3745 {register: Register.t,
3746 assembly: Assembly.t AppendList.t,
3747 registerAllocation: t}
3749 val _ = Int.inc depth
3750 val {register = final_register, assembly, registerAllocation}
3751 = freeRegister {info = info,
3754 supports = supports,
3757 registerAllocation = registerAllocation}
3758 val _ = Int.dec depth
3759 val (mungeLabel, base) = picRelative ()
3761 = case Immediate.destruct immediate of
3763 Assembly.instruction_mov
3764 {dst = Operand.Register final_register,
3765 src = Operand.Immediate immediate,
3767 | Immediate.Label l =>
3768 Assembly.instruction_lea
3769 {dst = Operand.Register final_register,
3770 src = Operand.Address
3771 (Address.T { disp = SOME (Immediate.label
3774 index = NONE, scale = NONE }),
3776 | Immediate.LabelPlusWord (l, w) =>
3777 Assembly.instruction_lea
3778 {dst = Operand.Register final_register,
3779 src = Operand.Address
3780 (Address.T { disp = SOME (Immediate.labelPlusWord
3783 index = NONE, scale = NONE }),
3786 {register = final_register,
3787 assembly = AppendList.appends
3789 AppendList.single instruction],
3790 registerAllocation = registerAllocation}
3795 supports = supports,
3797 registerAllocation = registerAllocation,
3798 spiller = spillRegisters,
3799 msg = "toRegisterImmediate",
3800 reissue = fn {assembly = assembly_spill,
3803 val {register, assembly, registerAllocation}
3804 = toRegisterImmediate
3805 {immediate = immediate,
3808 supports = supports,
3811 registerAllocation = registerAllocation}
3813 {register = register,
3814 assembly = AppendList.append (assembly_spill,
3816 registerAllocation = registerAllocation}
3819 fun pre {uses: Operand.t list,
3820 defs: Operand.t list,
3821 kills: Operand.t list,
3825 registerAllocation: t} :
3826 {assembly: Assembly.t AppendList.t,
3827 registerAllocation: t}
3829 val ra = registerAllocation
3831 val dead_memlocs = dead
3832 val remove_memlocs = remove
3834 val (allUses, allDefs, allKills)
3841 => case Operand.deMemloc operand
3843 => MemLocSet.add(set, memloc)
3846 val uses = doit uses
3847 val defs = doit defs
3848 val kills = doit kills
3850 fun doit' (memlocs, set)
3857 MemLocSet.fromList (MemLoc.utilized memloc)))
3863 val allKills = kills
3865 (allUses, allDefs, allKills)
3868 val allDest = MemLocSet.unions
3869 [allDefs, allKills, dead_memlocs, remove_memlocs]
3870 val allKeep = MemLocSet.unions
3871 [allUses, allDefs, allKills]
3873 val registerAllocation
3875 {map = fn {fltregister,
3885 => not (MemLoc.eq(memloc', memloc))
3886 andalso (MemLoc.mayAlias(memloc', memloc))))
3891 => not (MemLoc.eq(memloc', memloc))
3892 andalso (MemLoc.mayAlias(memloc', memloc))))
3895 (MemLoc.utilized memloc,
3897 => MemLocSet.contains (allDest, memloc)))
3899 = (MemLocSet.contains
3900 (MemLocSet.-(allKills, dead_memlocs), memloc))
3902 = if volatile memloc
3906 = if volatile memloc
3908 else if must_commit3
3910 else if must_commit2
3911 then if MemLocSet.contains
3915 else if must_commit1 orelse must_commit0
3917 of TRYREMOVE _ => REMOVE 0
3918 | REMOVE _ => REMOVE 0
3922 {fltregister = fltregister,
3928 registerAllocation = registerAllocation}
3930 val {assembly = assembly_commit_fltregisters,
3933 = commitFltRegisters {info = info,
3936 registerAllocation = registerAllocation}
3938 val registerAllocation
3940 {map = fn {register,
3950 => not (MemLoc.eq(memloc', memloc))
3951 andalso (MemLoc.mayAlias(memloc', memloc))))
3956 => not (MemLoc.eq(memloc', memloc))
3957 andalso (MemLoc.mayAlias(memloc', memloc))))
3960 (MemLoc.utilized memloc,
3962 => MemLocSet.contains (allDest, memloc)))
3964 = (MemLocSet.contains
3965 (MemLocSet.-(allKills, dead_memlocs), memloc))
3967 = if volatile memloc
3971 = if volatile memloc
3973 else if MemLocSet.contains(allDefs, memloc)
3974 then if must_commit1 orelse must_commit0
3976 of TRYREMOVE _ => REMOVE 0
3977 | REMOVE _ => REMOVE 0
3980 else if must_commit3
3982 else if must_commit2
3983 then if MemLocSet.contains
3987 else if must_commit1 orelse must_commit0
3989 of TRYREMOVE _ => REMOVE 0
3990 | REMOVE _ => REMOVE 0
3994 {register = register,
4000 registerAllocation = registerAllocation}
4002 val {assembly = assembly_commit_registers,
4004 = commitRegisters {info = info,
4007 registerAllocation = registerAllocation}
4009 {assembly = AppendList.appends
4010 [if !Control.Native.commented > 3
4011 then AppendList.cons
4012 ((Assembly.comment "pre begin:"),
4014 else AppendList.empty,
4015 assembly_commit_fltregisters,
4016 assembly_commit_registers,
4017 if !Control.Native.commented > 3
4018 then AppendList.cons
4019 ((Assembly.comment "pre end:"),
4020 (toComments registerAllocation))
4021 else AppendList.empty],
4022 registerAllocation = registerAllocation}
4030 fun post {uses: Operand.t list,
4031 final_uses: Operand.t list,
4032 defs: Operand.t list,
4033 final_defs: Operand.t list,
4034 kills: Operand.t list,
4039 registerAllocation: t} :
4040 {assembly: Assembly.t AppendList.t,
4041 registerAllocation: t}
4043 val ra = registerAllocation
4045 val (final_uses_registers,
4046 final_defs_registers,
4047 final_uses_fltregisters,
4048 final_defs_fltregisters)
4050 fun doit(operands, (final_registers, final_fltregisters))
4053 (final_registers, final_fltregisters),
4054 fn (operand, (final_registers, final_fltregisters))
4055 => case (Operand.deRegister operand,
4056 Operand.deFltregister operand)
4057 of (SOME register, _)
4058 => if List.contains(final_registers,
4061 then (final_registers,
4063 else (register::final_registers,
4065 | (_, SOME fltregister)
4066 => if List.contains(final_fltregisters,
4069 then (final_registers,
4071 else (final_registers,
4072 fltregister::final_fltregisters)
4073 | _ => (final_registers, final_fltregisters))
4074 val (final_uses_registers, final_uses_fltregisters)
4075 = doit(final_uses, ([], []))
4076 val (final_defs_registers, final_defs_fltregisters)
4077 = doit(final_defs, ([], []))
4079 (final_uses_registers,
4080 final_defs_registers,
4081 final_uses_fltregisters,
4082 final_defs_fltregisters)
4085 val dead_memlocs = dead
4086 val commit_memlocs = commit
4087 val remove_memlocs = remove
4089 val (_, allDefs, allKills)
4096 => case Operand.deMemloc operand
4098 => MemLocSet.add(set, memloc)
4101 val uses = doit uses
4102 val defs = doit defs
4103 val kills = doit kills
4105 fun doit' (memlocs, set)
4112 MemLocSet.fromList (MemLoc.utilized memloc)))
4118 val allKills = kills
4120 (allUses, allDefs, allKills)
4123 val allDest = MemLocSet.unions
4124 [allDefs, allKills, dead_memlocs, remove_memlocs]
4126 val registerAllocation
4128 {map = fn {fltregister,
4133 => if volatile memloc
4137 (final_defs_fltregisters,
4142 {fltregister = fltregister,
4144 sync = sync andalso (not isDef),
4145 weight = weight - 500,
4148 else if MemLocSet.contains
4149 (dead_memlocs, memloc)
4150 then {fltregister = fltregister,
4153 weight = weight - 500,
4154 commit = TRYREMOVE 0}
4158 (final_uses_fltregisters,
4164 (final_defs_fltregisters,
4170 {fltregister = fltregister,
4179 sync = sync andalso (not isDef),
4180 commit = if !Control.Native.IEEEFP
4182 not (sync andalso (not isDef))
4185 (MemLoc.utilized memloc,
4187 => MemLocSet.contains
4190 else if MemLocSet.contains
4194 else if MemLocSet.contains
4200 registerAllocation = registerAllocation}
4202 val {assembly = assembly_commit_fltregisters,
4205 = commitFltRegisters {info = info,
4208 registerAllocation = registerAllocation}
4210 val registerAllocation
4212 {map = fn value as {register,
4217 => if volatile memloc
4221 (final_defs_registers,
4226 {register = register,
4228 sync = sync andalso (not isDef),
4229 weight = weight - 500,
4232 else if MemLocSet.contains
4233 (dead_memlocs, memloc)
4238 (final_uses_registers,
4244 (final_defs_registers,
4250 {register = register,
4259 sync = sync andalso (not isDef),
4260 commit = if List.exists
4261 (MemLoc.utilized memloc,
4263 => MemLocSet.contains
4266 else if MemLocSet.contains
4270 else if MemLocSet.contains
4276 registerAllocation = registerAllocation}
4278 val {assembly = assembly_commit_registers,
4280 = commitRegisters {info = info,
4283 registerAllocation = registerAllocation}
4285 val registerAllocation
4287 {map = fn value as {register,
4291 => if MemLocSet.contains
4292 (dead_memlocs, memloc)
4293 then {register = register,
4299 registerAllocation = registerAllocation}
4301 val {assembly = assembly_dead_registers,
4303 = commitRegisters {info = info,
4306 registerAllocation = registerAllocation}
4308 {assembly = AppendList.appends
4309 [if !Control.Native.commented > 3
4310 then AppendList.cons
4311 ((Assembly.comment "post begin:"),
4313 else AppendList.empty,
4314 assembly_commit_fltregisters,
4315 assembly_commit_registers,
4316 assembly_dead_registers,
4317 if !Control.Native.commented > 3
4318 then AppendList.cons
4319 ((Assembly.comment "post end:"),
4320 (toComments registerAllocation))
4321 else AppendList.empty],
4322 registerAllocation = registerAllocation}
4325 val (post, post_msg)
4330 fun allocateOperand {operand: Operand.t,
4331 options = {register: bool,
4340 supports: Operand.t list,
4341 saves: Operand.t list,
4342 force: Register.t list,
4343 registerAllocation: t} :
4344 {operand: Operand.t,
4345 assembly: Assembly.t AppendList.t,
4346 registerAllocation: t}
4348 of Operand.Immediate i
4349 => if immediate andalso
4351 val (_, picBase) = picRelative ()
4352 val pic = picBase <> NONE
4354 case Immediate.destruct i of
4355 Immediate.Word _ => false
4358 not (pic andalso hasLabel)
4360 then {operand = operand,
4361 assembly = AppendList.empty,
4362 registerAllocation = registerAllocation}
4368 = toRegisterImmediate {immediate = i,
4371 supports = supports,
4375 = registerAllocation}
4377 {operand = Operand.register register,
4378 assembly = assembly,
4379 registerAllocation = registerAllocation}
4383 val (mungeLabel, picBase) = picRelative ()
4384 val label = mungeLabel (Label.fromString "raTemp1")
4387 {disp = SOME (Immediate.label label),
4392 {operand = Operand.address address,
4393 assembly = AppendList.single
4394 (Assembly.instruction_mov
4395 {src = Operand.immediate i,
4396 dst = Operand.address address,
4398 registerAllocation = registerAllocation}
4400 else Error.bug "x86AllocateRegisters.RegisterAllocation.allocateOperand: operand:Immediate"
4403 then {operand = operand,
4404 assembly = AppendList.empty,
4405 registerAllocation = registerAllocation}
4407 then {operand = Operand.immediate_label l,
4408 assembly = AppendList.empty,
4409 registerAllocation = registerAllocation}
4415 = toRegisterImmediate {immediate
4416 = Immediate.label l,
4419 supports = supports,
4423 = registerAllocation}
4425 {operand = Operand.register register,
4426 assembly = assembly,
4427 registerAllocation = registerAllocation}
4429 else Error.bug "x86AllocateRegisters.RegisterAllocation.allocateOperand: operand:Label"
4432 fun toRegisterMemLoc' ()
4442 supports = supports,
4445 registerAllocation = registerAllocation}
4447 {operand = Operand.Register register,
4448 assembly = assembly,
4449 registerAllocation = registerAllocation}
4451 fun toAddressMemLoc' ()
4460 supports = supports,
4463 = registerAllocation}
4465 {operand = Operand.Address address,
4466 assembly = assembly,
4467 registerAllocation = registerAllocation}
4469 fun toAddressMemLocRemove' ()
4471 val registerAllocation
4473 = fn value as {register,
4478 => if MemLoc.eq(memloc, m)
4479 then {register = register,
4485 registerAllocation = registerAllocation}
4487 val {assembly = assembly_commit,
4489 = commitRegisters {info = info,
4490 supports = supports,
4493 = registerAllocation}
4495 val {address, assembly, registerAllocation}
4496 = toAddressMemLoc {memloc = m,
4499 supports = supports,
4502 = registerAllocation}
4504 {operand = Operand.Address address,
4505 assembly = AppendList.append (assembly_commit,
4507 registerAllocation = registerAllocation}
4510 if register andalso address
4511 then case allocated {memloc = m,
4513 = registerAllocation}
4515 => if MemLocSet.contains(dead, m)
4517 MemLocSet.contains(remove, m)
4518 then toAddressMemLoc' ()
4519 else toRegisterMemLoc' ()
4521 => toRegisterMemLoc' ()
4523 then toRegisterMemLoc' ()
4525 then toAddressMemLocRemove' ()
4526 else Error.bug "x86AllocateRegisters.RegisterAllocation.allocateOperand: operand:MemLoc"
4528 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.allocateOperand: operand"
4530 val (allocateOperand, allocateOperand_msg)
4535 fun allocateFltOperand {operand: Operand.t,
4536 options = {fltregister: bool,
4543 supports: Operand.t list,
4544 saves: Operand.t list,
4546 registerAllocation: t} :
4547 {operand: Operand.t,
4548 assembly: Assembly.t AppendList.t,
4549 fltrename: FltRegister.t -> FltRegister.t,
4550 registerAllocation: t}
4553 => if fltregister andalso address
4554 then case fltallocated {memloc = m,
4556 = registerAllocation}
4558 => if MemLocSet.contains(dead, m)
4560 MemLocSet.contains(remove, m)
4569 supports = supports,
4572 = registerAllocation}
4574 {operand = Operand.Address address,
4575 assembly = assembly,
4576 fltrename = FltRegister.id,
4577 registerAllocation = registerAllocation}
4584 = toFltRegisterMemLoc
4589 supports = supports,
4593 = registerAllocation}
4596 = Operand.FltRegister fltregister,
4597 assembly = assembly,
4598 fltrename = fltrename,
4599 registerAllocation = registerAllocation}
4607 = toFltRegisterMemLoc {memloc = m,
4611 supports = supports,
4615 = registerAllocation}
4617 {operand = Operand.FltRegister fltregister,
4618 assembly = assembly,
4619 fltrename = fltrename,
4620 registerAllocation = registerAllocation}
4628 = toFltRegisterMemLoc {memloc = m,
4632 supports = supports,
4636 = registerAllocation}
4638 {operand = Operand.FltRegister fltregister,
4639 assembly = assembly,
4640 fltrename = fltrename,
4641 registerAllocation = registerAllocation}
4645 val registerAllocation
4647 = fn value as {fltregister,
4652 => if MemLoc.eq(memloc, m)
4661 = registerAllocation}
4663 val {assembly = assembly_commit,
4664 fltrename = fltrename_commit,
4666 = commitFltRegisters {info = info,
4667 supports = supports,
4670 = registerAllocation}
4673 assembly = assembly_address,
4675 = toAddressMemLoc {memloc = m,
4678 supports = supports,
4681 = registerAllocation}
4683 {operand = Operand.Address address,
4684 assembly = AppendList.append (assembly_commit,
4686 fltrename = fltrename_commit,
4687 registerAllocation = registerAllocation}
4689 else Error.bug "x86AllocateRegisters.RegisterAllocation.allocateFltOperand: operand:MemLoc"
4690 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.allocateFltOperand: operand"
4692 val (allocateFltOperand, allocateFltOperand_msg)
4694 "allocateFltOperand"
4698 fun allocateFltStackOperands' {fltregister_top: FltRegister.t,
4699 fltregister_one: FltRegister.t,
4700 registerAllocation: t} :
4701 {assembly: Assembly.t AppendList.t,
4702 fltrename: FltRegister.t -> FltRegister.t,
4703 registerAllocation: t}
4704 = case (fltregister_top, fltregister_one)
4705 of (FltRegister.T 0, FltRegister.T 1)
4706 => {assembly = AppendList.empty,
4707 fltrename = FltRegister.id,
4708 registerAllocation = registerAllocation}
4709 | (FltRegister.T 1, FltRegister.T 0)
4711 val {fltrename = fltrename,
4713 = fltxch1 {registerAllocation = registerAllocation}
4715 {assembly = AppendList.single
4716 (Assembly.instruction_fxch
4717 {src = Operand.fltregister
4718 (FltRegister.T 1)}),
4719 fltrename = fltrename,
4720 registerAllocation = registerAllocation}
4722 | (FltRegister.T 0, FltRegister.T j)
4724 val {fltrename = fltrename,
4726 = fltxch1 {registerAllocation = registerAllocation}
4728 val {fltrename = fltrename',
4730 = fltxch' {fltregister = FltRegister.T j,
4731 registerAllocation = registerAllocation}
4733 val {fltrename = fltrename'',
4735 = fltxch1 {registerAllocation = registerAllocation}
4737 {assembly = AppendList.fromList
4738 [Assembly.instruction_fxch
4739 {src = Operand.fltregister
4741 Assembly.instruction_fxch
4742 {src = Operand.fltregister
4744 Assembly.instruction_fxch
4745 {src = Operand.fltregister
4746 (FltRegister.T 1)}],
4747 fltrename = fltrename'' o fltrename' o fltrename,
4748 registerAllocation = registerAllocation}
4750 | (FltRegister.T 1, FltRegister.T j)
4752 val {fltrename = fltrename,
4754 = fltxch' {fltregister = FltRegister.T j,
4755 registerAllocation = registerAllocation}
4757 val {fltrename = fltrename',
4759 = fltxch1 {registerAllocation = registerAllocation}
4761 {assembly = AppendList.fromList
4762 [Assembly.instruction_fxch
4763 {src = Operand.fltregister
4765 Assembly.instruction_fxch
4766 {src = Operand.fltregister
4767 (FltRegister.T 1)}],
4768 fltrename = fltrename' o fltrename,
4769 registerAllocation = registerAllocation}
4771 | (FltRegister.T i, FltRegister.T 1)
4773 val {fltrename = fltrename,
4775 = fltxch' {fltregister = FltRegister.T i,
4776 registerAllocation = registerAllocation}
4778 {assembly = AppendList.single
4779 (Assembly.instruction_fxch
4780 {src = Operand.fltregister
4781 (FltRegister.T i)}),
4782 fltrename = fltrename,
4783 registerAllocation = registerAllocation}
4785 | (FltRegister.T i, FltRegister.T 0)
4787 val {fltrename = fltrename,
4789 = fltxch1 {registerAllocation = registerAllocation}
4791 val {fltrename = fltrename',
4793 = fltxch' {fltregister = FltRegister.T i,
4794 registerAllocation = registerAllocation}
4796 {assembly = AppendList.fromList
4797 [Assembly.instruction_fxch
4798 {src = Operand.fltregister
4800 Assembly.instruction_fxch
4801 {src = Operand.fltregister
4802 (FltRegister.T i)}],
4803 fltrename = fltrename' o fltrename,
4804 registerAllocation = registerAllocation}
4806 | (FltRegister.T i, FltRegister.T j)
4808 val {fltrename = fltrename,
4810 = fltxch' {fltregister = FltRegister.T j,
4811 registerAllocation = registerAllocation}
4813 val {fltrename = fltrename',
4815 = fltxch1 {registerAllocation = registerAllocation}
4817 val {fltrename = fltrename'',
4819 = fltxch' {fltregister = FltRegister.T i,
4820 registerAllocation = registerAllocation}
4822 {assembly = AppendList.fromList
4823 [Assembly.instruction_fxch
4824 {src = Operand.fltregister
4826 Assembly.instruction_fxch
4827 {src = Operand.fltregister
4829 Assembly.instruction_fxch
4830 {src = Operand.fltregister
4831 (FltRegister.T i)}],
4832 fltrename = fltrename'' o fltrename' o fltrename,
4833 registerAllocation = registerAllocation}
4836 fun allocateFltStackOperands {operand_top: Operand.t,
4839 operand_one: Operand.t,
4843 supports: Operand.t list,
4844 saves: Operand.t list,
4845 registerAllocation: t} :
4846 {operand_top: Operand.t,
4847 operand_one: Operand.t,
4848 assembly: Assembly.t AppendList.t,
4849 fltrename: FltRegister.t -> FltRegister.t,
4850 registerAllocation: t}
4851 = if Operand.eq(operand_top, operand_one)
4853 val {assembly = assembly_free,
4854 fltrename = fltrename_free,
4856 = freeFltRegister {info = info,
4858 supports = operand_top::supports,
4861 = registerAllocation}
4863 val {assembly = assembly_allocate_top_one,
4864 fltrename = fltrename_allocate_top_one,
4867 = allocateFltOperand
4868 {operand = operand_top,
4869 options = {fltregister = true,
4874 supports = supports,
4878 = registerAllocation}
4882 {base = Immediate.label (Label.fromString "raTemp2"),
4883 index = Immediate.zero,
4884 scale = Scale.Eight,
4886 class = MemLoc.Class.Temp}
4888 val {fltrename = fltrename_push,
4890 = fltpush {value = {fltregister = FltRegister.top,
4895 registerAllocation = registerAllocation}
4897 {operand_top = Operand.FltRegister FltRegister.top,
4898 operand_one = Operand.FltRegister FltRegister.one,
4899 assembly = AppendList.appends
4901 assembly_allocate_top_one,
4903 (Assembly.instruction_fld
4904 {src = Operand.FltRegister FltRegister.top,
4906 fltrename = fltrename_push o
4907 fltrename_allocate_top_one o
4909 registerAllocation = registerAllocation}
4912 val {operand = operand_allocate_one,
4913 assembly = assembly_allocate_one,
4914 fltrename = fltrename_allocate_one,
4917 of (Operand.MemLoc memloc_one)
4918 => (case fltallocated {memloc = memloc_one,
4920 = registerAllocation}
4922 => {operand = Operand.FltRegister
4923 (#fltregister value_one),
4924 assembly = AppendList.empty,
4925 fltrename = FltRegister.id,
4927 = registerAllocation}
4929 => allocateFltOperand
4930 {operand = operand_one,
4931 options = {fltregister = true,
4936 supports = supports,
4937 saves = operand_top::saves,
4940 = registerAllocation})
4941 | _ => allocateFltOperand
4942 {operand = operand_one,
4943 options = {fltregister = true,
4948 supports = supports,
4949 saves = operand_top::saves,
4951 registerAllocation = registerAllocation}
4953 val {operand = operand_allocate_top,
4954 assembly = assembly_allocate_top,
4955 fltrename = fltrename_allocate_top,
4958 of (Operand.MemLoc memloc_top)
4959 => (case fltallocated {memloc = memloc_top,
4961 = registerAllocation}
4963 => {operand = Operand.FltRegister
4964 (#fltregister value_top),
4965 assembly = AppendList.empty,
4966 fltrename = FltRegister.id,
4968 = registerAllocation}
4970 => allocateFltOperand
4971 {operand = operand_top,
4972 options = {fltregister = true,
4977 supports = supports,
4978 saves = operand_top::saves,
4981 = registerAllocation})
4982 | _ => allocateFltOperand
4983 {operand = operand_top,
4984 options = {fltregister = true,
4989 supports = supports,
4990 saves = operand_top::saves,
4992 registerAllocation = registerAllocation}
4995 = case operand_allocate_one
4996 of Operand.FltRegister f => f
4997 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.allocateFltStackOperand: one"
4998 val fltregister_one = fltrename_allocate_top fltregister_one
5001 = case operand_allocate_top
5002 of Operand.FltRegister f => f
5003 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.allocateFltStackOperand: top"
5008 = allocateFltStackOperands'
5009 {fltregister_top = fltregister_top,
5010 fltregister_one = fltregister_one,
5011 registerAllocation = registerAllocation}
5013 {operand_top = Operand.FltRegister FltRegister.top,
5014 operand_one = Operand.FltRegister FltRegister.one,
5015 assembly = AppendList.appends
5016 [assembly_allocate_one,
5017 assembly_allocate_top,
5019 fltrename = fltrename o
5020 fltrename_allocate_top o
5021 fltrename_allocate_one,
5022 registerAllocation = registerAllocation}
5026 val (allocateFltStackOperands, allocateFltStackOperands_msg)
5028 "allocateFltStackOperands"
5029 allocateFltStackOperands
5031 fun fltrenameLift fltrename
5032 = fn Operand.FltRegister f
5033 => Operand.FltRegister (fltrename f)
5034 | operand => operand
5036 (* Implementation of directives. *)
5038 fun assume {assumes : {register: Register.t,
5042 reserve: bool} list,
5050 {assembly = AppendList.empty,
5051 registerAllocation = registerAllocation},
5057 {assembly, registerAllocation})
5059 val registerAllocation
5061 {value = {register = register,
5066 registerAllocation = registerAllocation}
5068 val {assembly = assembly_reserve,
5071 then reserve' {register = register,
5072 registerAllocation = registerAllocation}
5073 else unreserve' {register = register,
5074 registerAllocation = registerAllocation}
5076 {assembly = AppendList.append (assembly,
5078 registerAllocation = registerAllocation}
5081 {assembly = assembly,
5082 registerAllocation = registerAllocation}
5085 fun fltassume {assumes : {memloc: MemLoc.t,
5089 registerAllocation = {entries,
5093 val registerAllocation
5094 = {entries = entries,
5095 reserved = reserved,
5102 {assembly = AppendList.empty,
5103 registerAllocation = registerAllocation},
5107 {assembly, registerAllocation})
5109 val {registerAllocation, ...}
5110 = fltpush {value = {fltregister = FltRegister.top,
5115 registerAllocation = registerAllocation}
5117 {assembly = assembly,
5118 registerAllocation = registerAllocation}
5121 {assembly = assembly,
5122 registerAllocation = registerAllocation}
5125 fun cache {caches: {register: Register.t,
5127 reserve: bool} list,
5134 fn {memloc, ...} => Operand.memloc memloc)
5136 datatype u = None | Reg of Register.t | Mem of MemLoc.t
5138 fun computeEdges' {reg,
5141 (Register.coincident' reg,
5148 => Register.eq(register, register'))
5149 of NONE => (None, NONE)
5150 | SOME {memloc, ...}
5151 => (case allocated {memloc = memloc,
5153 = registerAllocation}
5155 => (Mem memloc, SOME memloc)
5156 | SOME {register, ...}
5157 => (Reg register, SOME memloc))
5160 = case valueRegister
5161 {register = register',
5162 registerAllocation = registerAllocation}
5164 | SOME {memloc = memloc', ...}
5168 => MemLoc.eq(memloc, memloc'))
5170 | SOME {register, ...} => Reg register)
5172 (from, m, register', to)
5175 fun computeEdges {registerAllocation}
5179 => (reg, computeEdges' {reg = reg,
5180 registerAllocation = registerAllocation}))
5182 fun doitSelf {edges,
5187 val {yes = self, no = edges}
5193 fn (Reg rf, _, r, Reg rt)
5194 => Register.eq(rf, r) andalso
5198 if not (List.isEmpty self)
5204 fn ((_, edges'), saves)
5208 fn ((_,_,r,_), saves)
5209 => (Operand.register r)::saves))
5211 doit {edges = edges,
5212 saves = saves_self @ saves,
5213 assembly = assembly,
5214 registerAllocation = registerAllocation}
5216 else doitEasy {edges = edges,
5218 assembly = assembly,
5219 registerAllocation = registerAllocation}
5222 and doitEasy {edges,
5231 fn ((_, edges'), {easy = NONE})
5237 fn ((Reg _, SOME m, r, None),
5239 => {easy = SOME (m, r)}
5251 val {assembly = assembly_register,
5257 size = MemLoc.size m,
5259 supports = supports,
5262 registerAllocation = registerAllocation}
5264 val edges = computeEdges
5265 {registerAllocation = registerAllocation}
5267 doit {edges = edges,
5269 assembly = AppendList.append
5270 (assembly, assembly_register),
5271 registerAllocation = registerAllocation}
5273 | NONE => doitHard {edges = edges,
5275 assembly = assembly,
5276 registerAllocation = registerAllocation}
5279 and doitHard {edges,
5288 fn ((_, edges'), {hard = NONE})
5294 fn ((Mem _, SOME m, r, None),
5296 => {hard = SOME (m, r)}
5308 val {assembly = assembly_register,
5314 size = MemLoc.size m,
5316 supports = supports,
5319 registerAllocation = registerAllocation}
5321 val edges = computeEdges
5322 {registerAllocation = registerAllocation}
5324 doit {edges = edges,
5326 assembly = AppendList.append
5327 (assembly, assembly_register),
5328 registerAllocation = registerAllocation}
5330 | NONE => doitCycle {edges = edges,
5332 assembly = assembly,
5333 registerAllocation = registerAllocation}
5336 and doitCycle {edges,
5339 registerAllocation = registerAllocation}
5345 fn ((_, edges'), {cycle = NONE})
5351 fn ((Reg _, SOME m, r, Reg _),
5353 => {cycle = SOME (m, r)}
5365 val {assembly = assembly_register,
5371 size = MemLoc.size m,
5373 supports = supports,
5376 registerAllocation = registerAllocation}
5378 val edges = computeEdges
5379 {registerAllocation = registerAllocation}
5381 doit {edges = edges,
5383 assembly = AppendList.append
5384 (assembly, assembly_register),
5385 registerAllocation = registerAllocation}
5387 | NONE => doitCycle {edges = edges,
5389 assembly = assembly,
5390 registerAllocation = registerAllocation}
5402 fn ((reg, edges'), edges)
5407 fn (None, _, _, None) => true
5410 if List.isEmpty edges'
5412 else (reg, edges')::edges
5415 if List.isEmpty edges
5416 then {assembly = assembly,
5417 registerAllocation = registerAllocation}
5418 else doitSelf {edges = edges,
5420 assembly = assembly,
5421 registerAllocation = registerAllocation}
5424 val {assembly = assembly_force,
5426 = doit {edges = computeEdges {registerAllocation = registerAllocation},
5428 assembly = AppendList.empty,
5429 registerAllocation = registerAllocation}
5431 val {assembly = assembly_reserve,
5433 = reserve {registers = List.revKeepAllMap
5435 fn {register, reserve, ...}
5439 registerAllocation = registerAllocation}
5442 {assembly = AppendList.append(assembly_force, assembly_reserve),
5443 registerAllocation = registerAllocation}
5447 fun cache {caches : {register: Register.t,
5449 reserve: bool} list,
5456 fn {memloc, ...} => Operand.memloc memloc)
5463 {assembly = AppendList.empty,
5464 registerAllocation = registerAllocation,
5466 fn (cache as {register,
5474 assembly = assembly_register,
5479 size = MemLoc.size memloc,
5481 supports = supports,
5484 registerAllocation = registerAllocation}
5486 val {assembly = assembly_reserve,
5489 then reserve' {register = register,
5490 registerAllocation = registerAllocation}
5491 else {assembly = AppendList.empty,
5492 registerAllocation = registerAllocation}
5494 {assembly = AppendList.appends [assembly,
5497 registerAllocation = registerAllocation,
5498 saves = (Operand.memloc memloc)::saves}
5501 {assembly = assembly,
5502 registerAllocation = registerAllocation}
5506 fun fltcache {caches : {memloc: MemLoc.t} list,
5513 fn {memloc, ...} => Operand.memloc memloc)
5515 val {assembly = assembly_load,
5520 {assembly = AppendList.empty,
5521 registerAllocation = registerAllocation,
5523 fn ({memloc: MemLoc.t},
5528 val {assembly = assembly_fltregister,
5531 = toFltRegisterMemLoc
5534 size = MemLoc.size memloc,
5536 supports = supports,
5539 registerAllocation = registerAllocation}
5541 {assembly = AppendList.append (assembly,
5542 assembly_fltregister),
5543 registerAllocation = registerAllocation,
5544 saves = (Operand.memloc memloc)::saves}
5553 (num_caches, dest_caches))
5556 fltregister = FltRegister.T num_caches}::dest_caches))
5558 fun check {assembly, registerAllocation}
5560 val {fltstack, ...} = registerAllocation
5561 val disp = (List.length fltstack) - num_caches
5564 = fn (FltRegister.T i) => FltRegister.T (i + disp)
5567 = fn [] => {assembly = assembly,
5568 registerAllocation = registerAllocation}
5571 ...}: fltvalue)::fltstack
5574 fn {memloc = memloc', ...}
5575 => MemLoc.eq(memloc, memloc'))
5576 of SOME {fltregister = fltregister', ...}
5578 val fltregister' = dest fltregister'
5583 then check' fltstack
5592 val {registerAllocation,
5595 {fltregister = fltregister'',
5597 = registerAllocation}
5601 (Assembly.instruction_fxch
5602 {src = Operand.fltregister
5607 = AppendList.append (assembly,
5609 registerAllocation = registerAllocation}
5614 val registerAllocation
5616 {map = fn value as {fltregister,
5621 => if FltRegister.eq
5624 then {fltregister = fltregister,
5630 registerAllocation = registerAllocation}
5632 val {assembly = assembly_commit,
5635 = commitFltRegisters
5637 supports = supports,
5640 = registerAllocation}
5643 = AppendList.append (assembly,
5645 registerAllocation = registerAllocation}
5651 val {assembly = assembly_shuffle,
5653 = check {assembly = AppendList.empty,
5654 registerAllocation = registerAllocation}
5656 {assembly = AppendList.appends [assembly_load,
5658 registerAllocation = registerAllocation}
5662 fun reset ({...}: {registerAllocation: t})
5663 = {assembly = AppendList.empty,
5664 registerAllocation = empty ()}
5666 fun force {commit_memlocs: MemLocSet.t,
5667 commit_classes: ClassSet.t,
5668 remove_memlocs: MemLocSet.t,
5669 remove_classes: ClassSet.t,
5670 dead_memlocs: MemLocSet.t,
5671 dead_classes: ClassSet.t,
5673 registerAllocation: t}
5676 = fn TRYREMOVE _ => REMOVE 0
5677 | REMOVE _ => REMOVE 0
5683 = fn memloc => (MemLocSet.contains(commit_memlocs,
5686 ClassSet.contains(commit_classes,
5687 MemLoc.class memloc))
5689 = fn memloc => (MemLocSet.contains(remove_memlocs,
5692 ClassSet.contains(remove_classes,
5693 MemLoc.class memloc))
5695 = fn memloc => (MemLocSet.contains(dead_memlocs,
5698 ClassSet.contains(dead_classes,
5699 MemLoc.class memloc))
5701 val registerAllocation
5703 = fn value as {fltregister,
5708 => case (shouldCommit memloc,
5709 shouldRemove memloc,
5711 of (true,false,false)
5712 => {fltregister = fltregister,
5716 commit = toCommit commit}
5717 | (false,true,false)
5718 => {fltregister = fltregister,
5722 commit = toRemove commit}
5723 | (false,false,true)
5724 => {fltregister = fltregister,
5728 commit = toRemove commit}
5729 | (false,false,false)
5731 (MemLoc.utilized memloc,
5732 fn memloc' => shouldDead memloc')
5733 then {fltregister = fltregister,
5737 commit = toRemove commit}
5739 (MemLoc.utilized memloc,
5740 fn memloc' => shouldRemove memloc')
5741 then {fltregister = fltregister,
5745 commit = toCommit commit}
5747 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.force",
5748 registerAllocation = registerAllocation}
5750 val {assembly = assembly_commit_fltregisters,
5753 = commitFltRegisters {info = info,
5757 = registerAllocation}
5759 val registerAllocation
5761 = fn value as {register,
5766 => case (shouldCommit memloc,
5767 shouldRemove memloc,
5769 of (true,false,false)
5770 => {register = register,
5774 commit = toCommit commit}
5775 | (false,true,false)
5776 => {register = register,
5780 commit = toRemove commit}
5781 | (false,false,true)
5783 | (false,false,false)
5785 (MemLoc.utilized memloc,
5786 fn memloc' => shouldDead memloc')
5787 then {register = register,
5791 commit = toRemove commit}
5793 (MemLoc.utilized memloc,
5794 fn memloc' => shouldRemove memloc')
5795 then {register = register,
5799 commit = toCommit commit}
5801 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.force",
5802 registerAllocation = registerAllocation}
5804 val {assembly = assembly_commit_registers,
5806 = commitRegisters {info = info,
5810 = registerAllocation}
5812 val registerAllocation
5814 = fn value as {register,
5819 => if shouldDead memloc
5820 then {register = register,
5824 commit = toRemove commit}
5826 registerAllocation = registerAllocation}
5828 val {assembly = assembly_dead_registers,
5830 = commitRegisters {info = info,
5834 = registerAllocation}
5836 {assembly = AppendList.appends
5837 [assembly_commit_fltregisters,
5838 assembly_commit_registers,
5839 assembly_dead_registers],
5840 registerAllocation = registerAllocation}
5843 fun ccall {info: Liveness.t,
5844 registerAllocation: t}
5846 val cstaticClasses = !x86MLton.Classes.cstaticClasses
5848 val {reserved = reservedStart, ...} = registerAllocation
5850 val {assembly = assembly_reserve,
5853 (Register.callerSaveRegisters,
5854 {assembly = AppendList.empty,
5855 registerAllocation = registerAllocation},
5856 fn (register, {assembly, registerAllocation})
5858 val {assembly = assembly_reserve,
5860 = reserve' {register = register,
5861 registerAllocation = registerAllocation}
5863 {assembly = AppendList.append (assembly,
5865 registerAllocation = registerAllocation}
5868 val availCalleeSaveRegisters =
5870 (Register.calleeSaveRegisters,
5873 (#reserved registerAllocation,
5875 not (Register.coincide (reservedReg, calleeSaveReg))))
5877 val {assembly = assembly_shuffle,
5878 registerAllocation, ...}
5879 = if !Control.Native.shuffle then
5881 (valueFilter {filter = fn {register, ...}
5883 (Register.callerSaveRegisters,
5888 (availCalleeSaveRegisters,
5890 Size.eq (Register.size register,
5891 Register.size calleeSaveReg)),
5892 registerAllocation = registerAllocation},
5893 {assembly = AppendList.empty,
5894 registerAllocation = registerAllocation},
5895 fn ({memloc, ...}, {assembly, registerAllocation})
5897 val {assembly = assembly_shuffle,
5898 registerAllocation, ...}
5899 = allocateOperand {operand = Operand.memloc memloc,
5900 options = {register = true,
5905 size = MemLoc.size memloc,
5909 force = Register.calleeSaveRegisters,
5911 = registerAllocation}
5913 {assembly = AppendList.append (assembly,
5915 registerAllocation = registerAllocation}
5917 else {assembly = AppendList.empty,
5918 registerAllocation = registerAllocation}
5920 val registerAllocation
5921 = valueMap {map = fn value as {register,
5927 (Register.callerSaveRegisters,
5933 MemLoc.class memloc)
5934 then {register = register,
5940 registerAllocation = registerAllocation}
5942 val registerAllocation
5943 = fltvalueMap {map = fn {fltregister,
5948 => {fltregister = fltregister,
5953 registerAllocation = registerAllocation}
5955 val {assembly = assembly_commit_fltregisters,
5956 registerAllocation, ...}
5957 = commitFltRegisters {info = info,
5960 registerAllocation = registerAllocation}
5962 val {assembly = assembly_commit_registers,
5964 = commitRegisters {info = info,
5967 registerAllocation = registerAllocation}
5969 val {assembly = assembly_unreserve,
5973 (Register.callerSaveRegisters,
5974 fn register => List.contains(reservedStart, register, Register.eq)),
5975 {assembly = AppendList.empty,
5976 registerAllocation = registerAllocation},
5977 fn (register, {assembly, registerAllocation})
5979 val {assembly = assembly_unreserve,
5981 = unreserve' {register = register,
5982 registerAllocation = registerAllocation}
5984 {assembly = AppendList.append (assembly,
5985 assembly_unreserve),
5986 registerAllocation = registerAllocation}
5989 val registerAllocation
5990 = deletes {registers = Register.callerSaveRegisters,
5991 registerAllocation = registerAllocation}
5993 {assembly = AppendList.appends
5996 assembly_commit_fltregisters,
5997 assembly_commit_registers,
5998 assembly_unreserve],
5999 registerAllocation = registerAllocation}
6002 fun return {returns: {src: Operand.t, dst: MemLoc.t} list,
6004 registerAllocation: t} =
6007 valueFilter {filter = fn {memloc, ...} =>
6009 (returns, fn {dst = return_memloc, ...} =>
6010 List.exists(MemLoc.utilized memloc,
6012 MemLoc.eq(memloc', return_memloc))
6014 MemLoc.mayAlias(return_memloc, memloc)),
6015 registerAllocation = registerAllocation}
6016 val killed_memlocs = List.revMap(killed_values, #memloc)
6018 val registerAllocation =
6019 removes {memlocs = killed_memlocs,
6020 registerAllocation = registerAllocation}
6022 val registerAllocation =
6024 (returns, registerAllocation, fn ({src = operand,
6025 dst = return_memloc}, registerAllocation) =>
6027 Operand.Register return_register =>
6028 update {value = {register = return_register,
6029 memloc = return_memloc,
6033 registerAllocation = registerAllocation}
6034 | Operand.FltRegister return_register =>
6036 (fltpush {value = {fltregister = return_register,
6037 memloc = return_memloc,
6041 registerAllocation = registerAllocation})
6042 | _ => Error.bug "x86AllocateRegisters.RegisterAllocation.return")
6044 val (final_defs, defs) =
6046 (returns, ([],[]), fn ({src,dst},(final_defs,defs)) =>
6047 (src::final_defs,(Operand.memloc dst)::defs))
6048 val {assembly = assembly_post,
6053 final_defs = final_defs,
6056 registerAllocation = registerAllocation}
6058 {assembly = assembly_post,
6059 registerAllocation = registerAllocation}
6063 fun return {memloc = return_memloc,
6065 registerAllocation: t}
6068 = valueFilter {filter = fn value as {memloc,...}
6070 (MemLoc.utilized memloc,
6072 => MemLoc.eq(memloc',
6075 MemLoc.mayAlias(return_memloc,
6077 registerAllocation = registerAllocation}
6078 val killed_memlocs = List.revMap(killed_values, #memloc)
6080 val registerAllocation
6081 = removes {memlocs = killed_memlocs,
6082 registerAllocation = registerAllocation}
6084 val return_register = Register.return (MemLoc.size return_memloc)
6085 val registerAllocation
6087 {value = {register = return_register,
6088 memloc = return_memloc,
6092 registerAllocation = registerAllocation}
6094 val {assembly = assembly_post,
6098 defs = [Operand.memloc return_memloc],
6099 final_defs = [Operand.register return_register],
6102 registerAllocation = registerAllocation}
6104 {assembly = assembly_post,
6105 registerAllocation = registerAllocation}
6108 fun fltreturn {memloc = return_memloc,
6110 registerAllocation: t}
6112 val return_register = FltRegister.return
6114 val {fltrename = fltrename_push,
6117 {value = {fltregister = return_register,
6118 memloc = return_memloc,
6122 registerAllocation = registerAllocation}
6124 val {assembly = assembly_post,
6128 defs = [Operand.memloc return_memloc],
6129 final_defs = [Operand.fltregister return_register],
6132 registerAllocation = registerAllocation}
6135 {assembly = assembly_post,
6136 registerAllocation = registerAllocation}
6140 fun clearflt {info: Liveness.t,
6141 registerAllocation: t}
6143 val registerAllocation
6144 = fltvalueMap {map = fn {fltregister,
6149 => {fltregister = fltregister,
6154 registerAllocation = registerAllocation}
6156 val {assembly = assembly_commit_fltregisters,
6159 = commitFltRegisters {info = info,
6162 registerAllocation = registerAllocation}
6164 {assembly = assembly_commit_fltregisters,
6165 registerAllocation = registerAllocation}
6168 fun saveregalloc ({id, registerAllocation, ...}:
6172 registerAllocation: t})
6174 val _ = setRA(id, {registerAllocation = registerAllocation})
6176 {assembly = if !Control.Native.commented > 2
6177 then (toComments registerAllocation)
6178 else AppendList.empty,
6179 registerAllocation = registerAllocation}
6182 fun restoreregalloc ({live, id, info, ...}:
6186 registerAllocation: t})
6188 val {registerAllocation} = getRA id
6191 = (track memloc) andalso
6192 not (MemLocSet.contains(live,memloc))
6194 val registerAllocation
6196 {map = fn value as {fltregister,
6202 then {fltregister = fltregister,
6206 commit = TRYREMOVE 0}
6207 else if List.exists(MemLoc.utilized memloc, dump)
6208 then {fltregister = fltregister,
6212 commit = TRYREMOVE 0}
6214 registerAllocation = registerAllocation}
6216 val {assembly = assembly_commit_fltregisters,
6219 = commitFltRegisters {info = info,
6222 registerAllocation = registerAllocation}
6224 val registerAllocation
6226 {map = fn value as {register,
6232 then {register = register,
6236 commit = TRYREMOVE 0}
6237 else if List.exists(MemLoc.utilized memloc, dump)
6238 then {register = register,
6242 commit = TRYREMOVE 0}
6244 registerAllocation = registerAllocation}
6246 val {assembly = assembly_commit_registers,
6249 = commitRegisters {info = info,
6252 registerAllocation = registerAllocation}
6254 {assembly = AppendList.append (assembly_commit_fltregisters,
6255 assembly_commit_registers),
6256 registerAllocation = registerAllocation}
6260 structure Instruction =
6262 structure RA = RegisterAllocation
6266 * Require src/dst operands as follows:
6275 fun allocateSrcDst {src: Operand.t,
6279 info as {dead, remove, ...}: Liveness.t,
6280 registerAllocation: RegisterAllocation.t}
6281 = if Operand.eq(src, dst)
6283 val {operand = final_src_dst,
6284 assembly = assembly_src_dst,
6286 = RA.allocateOperand
6288 options = {register = true,
6299 = registerAllocation}
6301 {final_src = final_src_dst,
6302 final_dst = final_src_dst,
6303 assembly_src_dst = assembly_src_dst,
6304 registerAllocation = registerAllocation}
6306 else case (src, dst)
6307 of (Operand.MemLoc _,
6308 Operand.MemLoc memloc_dst)
6309 => if MemLocSet.contains(dead,
6312 MemLocSet.contains(remove,
6315 val {operand = final_dst,
6316 assembly = assembly_dst,
6318 = RA.allocateOperand
6320 options = {register = true,
6331 = registerAllocation}
6335 of Operand.Register _
6336 => {register = true,
6341 => {register = true,
6346 val {operand = final_src,
6347 assembly = assembly_src,
6349 = RA.allocateOperand
6351 options = options_src,
6356 saves = [dst,final_dst],
6359 = registerAllocation}
6361 {final_src = final_src,
6362 final_dst = final_dst,
6364 = AppendList.appends
6367 registerAllocation = registerAllocation}
6370 val {operand = final_src,
6371 assembly = assembly_src,
6373 = RA.allocateOperand
6375 options = {register = true,
6386 = registerAllocation}
6388 val {operand = final_dst,
6389 assembly = assembly_dst,
6391 = RA.allocateOperand
6393 options = {register = true,
6401 saves = [src,final_src],
6404 = registerAllocation}
6406 {final_src = final_src,
6407 final_dst = final_dst,
6409 = AppendList.appends
6412 registerAllocation = registerAllocation}
6415 Operand.MemLoc memloc_dst)
6417 val {operand = final_src,
6418 assembly = assembly_src,
6420 = RA.allocateOperand
6422 options = {register = true,
6433 = registerAllocation}
6436 = RA.allocateOperand
6438 options = {register = true,
6446 saves = [src,final_src],
6449 = registerAllocation}
6451 val {operand = final_dst,
6452 assembly = assembly_dst,
6454 = if MemLocSet.contains(dead,
6457 MemLocSet.contains(remove,
6459 then case RA.allocated
6460 {memloc = memloc_dst,
6461 registerAllocation = registerAllocation}
6462 of SOME {register, sync, ...}
6465 val registerAllocation
6467 {register = register,
6469 = registerAllocation}
6473 options = {register = false,
6481 saves = [src,final_src],
6484 = registerAllocation}
6487 | NONE => default ()
6490 {final_src = final_src,
6491 final_dst = final_dst,
6493 = AppendList.appends
6496 registerAllocation = registerAllocation}
6498 | _ => Error.bug "x86AllocateRegisters.Instruction.allocateSrcDst"
6501 * Require src1/src2 operands as follows:
6510 fun allocateSrc1Src2 {src1: Operand.t,
6514 registerAllocation: RegisterAllocation.t}
6515 = if Operand.eq(src1, src2)
6517 val {operand = final_src1_src2,
6518 assembly = assembly_src1_src2,
6520 = RA.allocateOperand
6522 options = {register = true,
6533 = registerAllocation}
6535 {final_src1 = final_src1_src2,
6536 final_src2 = final_src1_src2,
6537 assembly_src1_src2 = assembly_src1_src2,
6538 registerAllocation = registerAllocation}
6541 val {operand = final_src1,
6542 assembly = assembly_src1,
6544 = RA.allocateOperand
6546 options = {register = true,
6557 = registerAllocation}
6561 of Operand.Register _
6562 => {register = true,
6567 => {register = true,
6572 val {operand = final_src2,
6573 assembly = assembly_src2,
6575 = RA.allocateOperand
6577 options = options_src2,
6582 saves = [src1,final_src1],
6585 = registerAllocation}
6587 {final_src1 = final_src1,
6588 final_src2 = final_src2,
6590 = AppendList.appends
6593 registerAllocation = registerAllocation}
6596 fun pfmov {instruction, info as {dead, remove, ...},
6598 src, dst, srcsize, dstsize} =
6602 val {uses,defs,kills}
6603 = Instruction.uses_defs_kills instruction
6604 val {assembly = assembly_pre,
6606 = RA.pre {uses = uses,
6610 registerAllocation = registerAllocation}
6612 val {operand = final_src,
6613 assembly = assembly_src,
6616 = RA.allocateFltOperand
6618 options = {fltregister = true,
6627 = registerAllocation}
6629 val {assembly = assembly_dst,
6630 fltrename = fltrename_dst,
6633 = RA.allocateFltOperand
6635 options = {fltregister = true,
6641 saves = [src,final_src],
6644 = registerAllocation}
6646 val final_src = (RA.fltrenameLift fltrename_dst) final_src
6653 val {uses = final_uses,
6656 = Instruction.uses_defs_kills instruction
6658 val {assembly = assembly_post,
6660 = RA.post {uses = uses,
6661 final_uses = final_uses,
6663 final_defs = final_defs,
6666 registerAllocation = registerAllocation}
6669 = AppendList.appends
6674 (Assembly.instruction instruction),
6676 registerAllocation = registerAllocation}
6681 val {uses,defs,kills}
6682 = Instruction.uses_defs_kills instruction
6683 val {assembly = assembly_pre,
6685 = RA.pre {uses = uses,
6689 registerAllocation = registerAllocation}
6691 val {operand = final_src,
6692 assembly = assembly_src,
6695 = RA.allocateFltOperand
6697 options = {fltregister = true,
6705 registerAllocation = registerAllocation}
6707 val {operand = final_dst,
6708 assembly = assembly_dst,
6711 = RA.allocateFltOperand
6713 options = {fltregister = false,
6719 saves = [src,final_src],
6721 registerAllocation = registerAllocation}
6729 val {fltrename = fltrename_pop,
6731 = RA.fltpop {registerAllocation = registerAllocation}
6733 val {uses = final_uses,
6736 = Instruction.uses_defs_kills instruction
6739 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
6741 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
6743 val {assembly = assembly_post,
6745 = RA.post {uses = uses,
6746 final_uses = final_uses,
6748 final_defs = final_defs,
6751 registerAllocation = registerAllocation}
6754 = AppendList.appends
6759 (Assembly.instruction instruction),
6761 registerAllocation = registerAllocation}
6765 of (Operand.MemLoc memloc_src,
6766 Operand.MemLoc memloc_dst)
6767 => (case (RA.fltallocated {memloc = memloc_src,
6769 = registerAllocation},
6770 RA.fltallocated {memloc = memloc_dst,
6772 = registerAllocation})
6773 of (SOME {fltregister = fltregister_src,
6775 commit = commit_src,
6778 => if MemLocSet.contains(dead,memloc_src)
6780 (MemLocSet.contains(remove,memloc_src)
6783 then if MemLocSet.contains(remove,
6787 val registerAllocation
6789 {value = {fltregister
6798 = registerAllocation}
6800 val {uses,defs,kills}
6801 = Instruction.uses_defs_kills
6803 val {assembly = assembly_pre,
6811 = registerAllocation}
6815 = [Operand.fltregister
6818 val {assembly = assembly_post,
6822 final_uses = final_uses,
6824 final_defs = final_defs,
6828 = registerAllocation}
6831 = AppendList.appends
6835 = registerAllocation}
6843 fun removable {memloc,
6844 info = {dead, remove, ...}: Liveness.t,
6846 = MemLocSet.contains(dead,
6849 (MemLocSet.contains(remove,
6852 (case RA.fltallocated {memloc = memloc,
6853 registerAllocation = registerAllocation}
6854 of SOME {sync,...} => sync
6857 fun allocateRegisters {instruction: t,
6858 info as {dead, remove, ...}: Liveness.t,
6859 registerAllocation: RegisterAllocation.t}
6862 (* No operation; p. 496 *)
6864 val {uses,defs,kills}
6865 = Instruction.uses_defs_kills instruction
6866 val {assembly = assembly_pre,
6868 = RA.pre {uses = uses,
6872 registerAllocation = registerAllocation}
6877 val {uses = final_uses,
6880 = Instruction.uses_defs_kills instruction
6882 val {assembly = assembly_post,
6884 = RA.post {uses = uses,
6885 final_uses = final_uses,
6887 final_defs = final_defs,
6890 registerAllocation = registerAllocation}
6893 = AppendList.appends
6895 AppendList.single (Assembly.instruction instruction),
6897 registerAllocation = registerAllocation}
6902 val {uses,defs,kills}
6903 = Instruction.uses_defs_kills instruction
6904 val {assembly = assembly_pre,
6906 = RA.pre {uses = uses,
6910 registerAllocation = registerAllocation}
6915 val {uses = final_uses,
6918 = Instruction.uses_defs_kills instruction
6920 val {assembly = assembly_post,
6922 = RA.post {uses = uses,
6923 final_uses = final_uses,
6925 final_defs = final_defs,
6928 registerAllocation = registerAllocation}
6931 = AppendList.appends
6933 AppendList.single (Assembly.instruction instruction),
6935 registerAllocation = registerAllocation}
6937 | BinAL {oper, src, dst, size}
6938 (* Integer binary arithmetic(w/o mult & div)/logic instructions.
6939 * Require src/dst operands as follows:
6949 val {uses,defs,kills}
6950 = Instruction.uses_defs_kills instruction
6951 val {assembly = assembly_pre,
6953 = RA.pre {uses = uses,
6957 registerAllocation = registerAllocation}
6965 = allocateSrcDst {src = src,
6970 registerAllocation = registerAllocation}
6979 val {uses = final_uses,
6982 = Instruction.uses_defs_kills instruction
6984 val {assembly = assembly_post,
6986 = RA.post {uses = uses,
6987 final_uses = final_uses,
6989 final_defs = final_defs,
6992 registerAllocation = registerAllocation}
6995 = AppendList.appends
6999 (Assembly.instruction instruction),
7001 registerAllocation = registerAllocation}
7006 | pMD {oper, dst, src, size}
7007 (* Integer multiplication and division.
7008 * Require src operand as follows:
7015 val {uses,defs,kills}
7016 = Instruction.uses_defs_kills instruction
7017 val {assembly = assembly_pre,
7019 = RA.pre {uses = uses,
7023 registerAllocation = registerAllocation}
7028 => (Register.T {reg = Register.EAX, part = Register.H},
7029 Register.T {reg = Register.EAX, part = Register.L})
7031 => (Register.T {reg = Register.EDX, part = Register.X},
7032 Register.T {reg = Register.EAX, part = Register.X})
7034 => (Register.T {reg = Register.EDX, part = Register.E},
7035 Register.T {reg = Register.EAX, part = Register.E})
7036 | _ => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: pMD, size"
7038 val {assembly = assembly_clear,
7045 supports = [src,dst],
7048 registerAllocation = registerAllocation}
7050 val registerAllocation
7051 = RA.delete {register = hi,
7052 registerAllocation = registerAllocation}
7058 = if Operand.eq(src, dst)
7060 val {operand = final_src_dst,
7061 assembly = assembly_src_dst,
7062 registerAllocation = registerAllocation}
7063 = RA.allocateOperand
7065 options = {register = true,
7073 saves = [Operand.register hi],
7076 = registerAllocation}
7078 {final_src = final_src_dst,
7079 final_dst = final_src_dst,
7080 assembly_src_dst = assembly_src_dst,
7081 registerAllocation = registerAllocation}
7084 val {operand = final_dst,
7085 assembly = assembly_dst,
7086 registerAllocation = registerAllocation}
7087 = RA.allocateOperand
7089 options = {register = true,
7097 saves = [Operand.register hi],
7100 = registerAllocation}
7104 (Register.registers size,
7105 fn r => not (Register.eq(r, hi) orelse
7106 Register.eq(r, lo)))
7108 val {operand = final_src,
7109 assembly = assembly_src,
7111 = RA.allocateOperand
7113 options = {register = true,
7121 saves = [Operand.register hi,
7125 = registerAllocation}
7127 {final_src = final_src,
7128 final_dst = final_dst,
7130 = AppendList.appends
7133 registerAllocation = registerAllocation}
7138 of Instruction.IMUL => Instruction.IMUL
7139 | Instruction.MUL => Instruction.MUL
7140 | Instruction.IDIV => Instruction.IDIV
7141 | Instruction.DIV => Instruction.DIV
7142 | Instruction.IMOD => Instruction.IDIV
7143 | Instruction.MOD => Instruction.DIV
7145 val registerAllocation
7146 = if oper = Instruction.IMOD orelse
7147 oper = Instruction.MOD
7148 then case RA.valuesRegister {register = lo,
7150 = registerAllocation}
7157 val registerAllocation
7158 = RA.delete {register = lo,
7160 = registerAllocation}
7162 val registerAllocation
7163 = RA.update {value = {register = hi,
7169 = registerAllocation}
7173 | _ => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: pMD, lo"
7174 else registerAllocation
7182 val {uses = final_uses,
7185 = Instruction.uses_defs_kills instruction
7187 val {assembly = assembly_post,
7189 = RA.post {uses = uses,
7190 final_uses = final_uses,
7192 final_defs = final_defs,
7195 registerAllocation = registerAllocation}
7198 = AppendList.appends
7202 (if oper = Instruction.IDIV orelse
7203 oper = Instruction.IMOD
7204 then AppendList.single
7205 (Assembly.instruction_cx
7207 else if oper = Instruction.DIV orelse
7208 oper = Instruction.MOD
7209 then AppendList.single
7210 (Assembly.instruction_binal
7211 {oper = Instruction.XOR,
7212 dst = Operand.register hi,
7213 src = Operand.register hi,
7215 else AppendList.empty),
7217 (Assembly.instruction instruction),
7219 registerAllocation = registerAllocation}
7221 | IMUL2 {src, dst, size}
7222 (* Integer signed/unsigned multiplication (two operand form).
7223 * Require src/dst operands as follows:
7233 val {uses,defs,kills}
7234 = Instruction.uses_defs_kills instruction
7235 val {assembly = assembly_pre,
7237 = RA.pre {uses = uses,
7241 registerAllocation = registerAllocation}
7247 = if Operand.eq(src, dst)
7249 val {operand = final_src_dst,
7250 assembly = assembly_src_dst,
7252 = RA.allocateOperand
7254 options = {register = true,
7265 = registerAllocation}
7267 {final_src = final_src_dst,
7268 final_dst = final_src_dst,
7269 assembly_src_dst = assembly_src_dst,
7270 registerAllocation = registerAllocation}
7273 val {operand = final_dst,
7274 assembly = assembly_dst,
7276 = RA.allocateOperand
7278 options = {register = true,
7289 = registerAllocation}
7291 val {operand = final_src,
7292 assembly = assembly_src,
7294 = RA.allocateOperand
7296 options = {register = true,
7304 saves = [dst,final_dst],
7307 = registerAllocation}
7309 {final_src = final_src,
7310 final_dst = final_dst,
7312 = AppendList.appends
7315 registerAllocation = registerAllocation}
7324 val {uses = final_uses,
7327 = Instruction.uses_defs_kills instruction
7329 val {assembly = assembly_post,
7331 = RA.post {uses = uses,
7332 final_uses = final_uses,
7334 final_defs = final_defs,
7337 registerAllocation = registerAllocation}
7340 = AppendList.appends
7344 (Assembly.instruction instruction),
7346 registerAllocation = registerAllocation}
7348 | UnAL {oper, dst, size}
7349 (* Integer unary arithmetic/logic instructions.
7350 * Require dst operand as follows:
7357 val {uses,defs,kills}
7358 = Instruction.uses_defs_kills instruction
7359 val {assembly = assembly_pre,
7361 = RA.pre {uses = uses,
7365 registerAllocation = registerAllocation}
7367 val {operand = final_dst,
7368 assembly = assembly_dst,
7369 registerAllocation = registerAllocation}
7370 = RA.allocateOperand {operand = dst,
7371 options = {register = true,
7382 = registerAllocation}
7390 val {uses = final_uses,
7393 = Instruction.uses_defs_kills instruction
7395 val {assembly = assembly_post,
7397 = RA.post {uses = uses,
7398 final_uses = final_uses,
7400 final_defs = final_defs,
7403 registerAllocation = registerAllocation}
7406 = AppendList.appends
7410 (Assembly.instruction instruction),
7412 registerAllocation = registerAllocation}
7414 | SRAL {oper, count, dst, size}
7415 (* Integer shift/rotate arithmetic/logic instructions.
7416 * Require count operand as follows:
7421 * * only register %cl
7423 * Require dst operand as follows:
7430 val {uses,defs,kills}
7431 = Instruction.uses_defs_kills instruction
7432 val {assembly = assembly_pre,
7434 = RA.pre {uses = uses,
7438 registerAllocation = registerAllocation}
7445 = if Operand.eq(count,dst)
7447 val {operand = final_count,
7448 assembly = assembly_count,
7450 = RA.allocateOperand
7452 options = {register = true,
7462 = [Register.T {reg = Register.ECX,
7464 Register.T {reg = Register.ECX,
7466 Register.T {reg = Register.ECX,
7467 part = Register.E}],
7469 = registerAllocation}
7471 val final_dst = final_count
7472 val assembly_dst = AppendList.empty
7474 {final_count = final_count,
7475 assembly_count = assembly_count,
7476 final_dst = final_dst,
7477 assembly_dst = assembly_dst,
7478 registerAllocation = registerAllocation}
7481 val count_size = case Operand.size count
7482 of NONE => Size.BYTE
7485 val {operand = final_count,
7486 assembly = assembly_count,
7488 = RA.allocateOperand
7490 options = {register = true,
7500 = [Register.T {reg = Register.ECX,
7502 Register.T {reg = Register.ECX,
7504 Register.T {reg = Register.ECX,
7505 part = Register.E}],
7507 = registerAllocation}
7509 val {operand = final_dst,
7510 assembly = assembly_dst,
7511 registerAllocation = registerAllocation}
7512 = RA.allocateOperand
7514 options = {register = true,
7522 saves = [count,final_count],
7525 = registerAllocation}
7527 {final_count = final_count,
7528 assembly_count = assembly_count,
7529 final_dst = final_dst,
7530 assembly_dst = assembly_dst,
7531 registerAllocation = registerAllocation}
7536 of Operand.Register _
7538 (Register.T {reg = Register.ECX,
7545 count = final_count,
7549 val {uses = final_uses,
7552 = Instruction.uses_defs_kills instruction
7554 val {assembly = assembly_post,
7556 = RA.post {uses = uses,
7557 final_uses = final_uses,
7559 final_defs = final_defs,
7562 registerAllocation = registerAllocation}
7565 = AppendList.appends
7570 (Assembly.instruction instruction),
7572 registerAllocation = registerAllocation}
7574 | CMP {src2, src1, size}
7575 (* Arithmetic compare; p. 116
7576 * Require src1/src2 operands as follows:
7586 val {uses,defs,kills}
7587 = Instruction.uses_defs_kills instruction
7588 val {assembly = assembly_pre,
7590 = RA.pre {uses = uses,
7594 registerAllocation = registerAllocation}
7605 registerAllocation = registerAllocation}
7613 val {uses = final_uses,
7616 = Instruction.uses_defs_kills instruction
7618 val {assembly = assembly_post,
7620 = RA.post {uses = uses,
7621 final_uses = final_uses,
7623 final_defs = final_defs,
7626 registerAllocation = registerAllocation}
7629 = AppendList.appends
7633 (Assembly.instruction instruction),
7635 registerAllocation = registerAllocation}
7637 | TEST {src2, src1, size}
7638 (* Logical compare; p. 728
7639 * Require src1/src2 operands as follows:
7649 val {uses,defs,kills}
7650 = Instruction.uses_defs_kills instruction
7651 val {assembly = assembly_pre,
7653 = RA.pre {uses = uses,
7657 registerAllocation = registerAllocation}
7668 registerAllocation = registerAllocation}
7676 val {uses = final_uses,
7679 = Instruction.uses_defs_kills instruction
7681 val {assembly = assembly_post,
7683 = RA.post {uses = uses,
7684 final_uses = final_uses,
7686 final_defs = final_defs,
7689 registerAllocation = registerAllocation}
7692 = AppendList.appends
7696 (Assembly.instruction instruction),
7698 registerAllocation = registerAllocation}
7700 | SETcc {condition, dst, size}
7701 (* Set byte on condition; p. 672
7702 * Require dst operand as follows:
7707 * * only byte registers
7710 val {uses,defs,kills}
7711 = Instruction.uses_defs_kills instruction
7712 val {assembly = assembly_pre,
7714 = RA.pre {uses = uses,
7718 registerAllocation = registerAllocation}
7720 val {operand = final_dst,
7721 assembly = assembly_dst,
7722 registerAllocation = registerAllocation}
7723 = RA.allocateOperand
7725 options = {register = true,
7734 force = Register.withLowPart (size, Size.BYTE),
7735 registerAllocation = registerAllocation}
7739 of Operand.Register r
7742 = Register.lowPartOf (r, Size.BYTE)
7744 Operand.register register
7746 | _ => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: SETcc, temp_reg"
7748 val {uses = final_uses,
7751 = Instruction.uses_defs_kills
7752 (Instruction.SETcc {condition = condition,
7756 val {assembly = assembly_post,
7758 = RA.post {uses = uses,
7759 final_uses = final_uses,
7761 final_defs = final_defs,
7764 registerAllocation = registerAllocation}
7767 = AppendList.appends
7771 (Assembly.instruction_setcc
7772 {condition = condition,
7776 then if Operand.eq (final_dst, temp_dst)
7777 then AppendList.empty
7778 else AppendList.single
7779 (Assembly.instruction_mov
7783 else AppendList.single
7784 (Assembly.instruction_movx
7785 {oper = Instruction.MOVZX,
7789 srcsize = Size.BYTE}),
7791 registerAllocation = registerAllocation}
7793 | JMP {target, absolute}
7795 * Require target operand as follows:
7802 val {uses,defs,kills}
7803 = Instruction.uses_defs_kills instruction
7804 val {assembly = assembly_pre,
7806 = RA.pre {uses = uses,
7810 registerAllocation = registerAllocation}
7812 val {operand = final_target,
7813 assembly = assembly_target,
7814 registerAllocation = registerAllocation}
7815 = RA.allocateOperand {operand = target,
7816 options = {register = false,
7827 = registerAllocation}
7831 {target = final_target,
7832 absolute = absolute}
7834 val {uses = final_uses,
7837 = Instruction.uses_defs_kills instruction
7839 val {assembly = assembly_post,
7841 = RA.post {uses = uses,
7842 final_uses = final_uses,
7844 final_defs = final_defs,
7847 registerAllocation = registerAllocation}
7850 = AppendList.appends
7854 (Assembly.instruction instruction),
7856 registerAllocation = registerAllocation}
7858 | Jcc {condition, target}
7859 (* Jump if condition is met; p. 369
7860 * Require target operand as follows:
7867 val {uses,defs,kills}
7868 = Instruction.uses_defs_kills instruction
7869 val {assembly = assembly_pre,
7871 = RA.pre {uses = uses,
7875 registerAllocation = registerAllocation}
7877 val {operand = final_target,
7878 assembly = assembly_target,
7879 registerAllocation = registerAllocation}
7880 = RA.allocateOperand {operand = target,
7881 options = {register = false,
7892 = registerAllocation}
7896 {condition = condition,
7897 target = final_target}
7899 val {uses = final_uses,
7902 = Instruction.uses_defs_kills instruction
7904 val {assembly = assembly_post,
7906 = RA.post {uses = uses,
7907 final_uses = final_uses,
7909 final_defs = final_defs,
7912 registerAllocation = registerAllocation}
7915 = AppendList.appends
7919 (Assembly.instruction instruction),
7921 registerAllocation = registerAllocation}
7923 | CALL {target, absolute}
7924 (* Call procedure; p. 93
7925 * Require target operand as follows:
7932 val {uses,defs,kills}
7933 = Instruction.uses_defs_kills instruction
7934 val {assembly = assembly_pre,
7936 = RA.pre {uses = uses,
7940 registerAllocation = registerAllocation}
7942 val {operand = final_target,
7943 assembly = assembly_target,
7944 registerAllocation = registerAllocation}
7945 = RA.allocateOperand {operand = target,
7946 options = {register = true,
7957 = registerAllocation}
7961 {target = final_target,
7962 absolute = absolute}
7964 val {uses = final_uses,
7967 = Instruction.uses_defs_kills instruction
7969 val {assembly = assembly_post,
7971 = RA.post {uses = uses,
7972 final_uses = final_uses,
7974 final_defs = final_defs,
7977 registerAllocation = registerAllocation}
7980 = AppendList.appends
7984 (Assembly.instruction instruction),
7986 registerAllocation = registerAllocation}
7988 | RET {src = SOME src}
7989 (* Return from procedure; p. 648
7990 * Require optional src operand as follows:
7997 val {uses,defs,kills}
7998 = Instruction.uses_defs_kills instruction
7999 val {assembly = assembly_pre,
8001 = RA.pre {uses = uses,
8005 registerAllocation = registerAllocation}
8007 val {operand = final_src,
8008 assembly = assembly_src,
8009 registerAllocation = registerAllocation}
8010 = RA.allocateOperand {operand = src,
8011 options = {register = false,
8022 = registerAllocation}
8026 {src = SOME final_src}
8028 val {uses = final_uses,
8031 = Instruction.uses_defs_kills instruction
8033 val {assembly = assembly_post,
8035 = RA.post {uses = uses,
8036 final_uses = final_uses,
8038 final_defs = final_defs,
8041 registerAllocation = registerAllocation}
8044 = AppendList.appends
8048 (Assembly.instruction instruction),
8050 registerAllocation = registerAllocation}
8054 val {uses,defs,kills}
8055 = Instruction.uses_defs_kills instruction
8056 val {assembly = assembly_pre,
8058 = RA.pre {uses = uses,
8062 registerAllocation = registerAllocation}
8068 val {uses = final_uses,
8071 = Instruction.uses_defs_kills instruction
8073 val {assembly = assembly_post,
8075 = RA.post {uses = uses,
8076 final_uses = final_uses,
8078 final_defs = final_defs,
8081 registerAllocation = registerAllocation}
8084 = AppendList.appends
8087 (Assembly.instruction instruction),
8089 registerAllocation = registerAllocation}
8091 | MOV {src, dst, size}
8093 * Require src/dst operands as follows:
8103 val {uses,defs,kills}
8104 = Instruction.uses_defs_kills instruction
8105 val {assembly = assembly_pre,
8107 = RA.pre {uses = uses,
8111 registerAllocation = registerAllocation}
8125 registerAllocation = registerAllocation}
8127 val isConst0 = Immediate.isZero
8129 (* special case moving 0 to a register
8132 = case (final_src, final_dst)
8133 of (Operand.Immediate immediate,
8135 => if isConst0 immediate
8136 then Instruction.BinAL
8141 else Instruction.MOV
8145 | _ => Instruction.MOV
8150 val {uses = final_uses,
8153 = Instruction.uses_defs_kills instruction
8155 val {assembly = assembly_post,
8157 = RA.post {uses = uses,
8158 final_uses = final_uses,
8160 final_defs = final_defs,
8163 registerAllocation = registerAllocation}
8166 = AppendList.appends
8170 (Assembly.instruction instruction),
8172 registerAllocation = registerAllocation}
8175 fun default' ({register = register_src,
8176 commit = commit_src,
8177 ...} : RegisterAllocation.value,
8180 val registerAllocation
8182 {memloc = memloc_dst,
8183 registerAllocation = registerAllocation}
8185 val registerAllocation
8187 {value = {register = register_src,
8188 memloc = memloc_dst,
8191 commit = commit_src},
8192 registerAllocation = registerAllocation}
8196 = [Operand.register register_src]
8198 val {assembly = assembly_post,
8200 = RA.post {uses = uses,
8201 final_uses = final_uses,
8203 final_defs = final_defs,
8206 registerAllocation = registerAllocation}
8209 = AppendList.appends [assembly_pre,
8211 registerAllocation = registerAllocation}
8214 fun default'' (memloc_dst)
8216 val registerAllocation
8218 {memloc = memloc_dst,
8219 registerAllocation = registerAllocation}
8231 registerAllocation = registerAllocation}
8239 val {uses = final_uses,
8242 = Instruction.uses_defs_kills instruction
8244 val {assembly = assembly_post,
8246 = RA.post {uses = uses,
8247 final_uses = final_uses,
8249 final_defs = final_defs,
8252 registerAllocation = registerAllocation}
8255 = AppendList.appends
8259 (Assembly.instruction instruction),
8261 registerAllocation = registerAllocation}
8264 val memloc_src = Operand.deMemloc src
8269 => RA.allocated {memloc = memloc_src,
8271 = registerAllocation}
8272 val memloc_dst = Operand.deMemloc dst
8276 => if MemLocSet.contains(remove,memloc_dst)
8277 then (case memloc_src
8280 (memloc_src::(MemLoc.utilized memloc_src),
8284 else default'' memloc_dst
8285 | NONE => default'' memloc_dst)
8286 else (case value_src
8287 of SOME (value_src as {memloc = memloc_src,
8288 sync = sync_src, ...})
8289 => if MemLocSet.contains(dead,memloc_src)
8291 (MemLocSet.contains(remove,memloc_src)
8294 then default' (value_src, memloc_dst)
8296 | NONE => default ())
8297 | NONE => default ()
8299 | CMOVcc {condition, src, dst, size}
8300 (* Conditional move; p. 112
8301 * Require src/dst operands as follows:
8311 val {uses,defs,kills}
8312 = Instruction.uses_defs_kills instruction
8313 val {assembly = assembly_pre,
8315 = RA.pre {uses = uses,
8319 registerAllocation = registerAllocation}
8321 val {operand = final_src,
8322 assembly = assembly_src,
8324 = RA.allocateOperand {operand = src,
8325 options = {register = true,
8336 = registerAllocation}
8338 val {operand = final_dst,
8339 assembly = assembly_dst,
8340 registerAllocation = registerAllocation}
8341 = RA.allocateOperand {operand = dst,
8342 options = {register = true,
8350 saves = [src,final_src],
8353 = registerAllocation}
8356 = Instruction.CMOVcc
8357 {condition = condition,
8362 val {uses = final_uses,
8365 = Instruction.uses_defs_kills instruction
8367 val {assembly = assembly_post,
8369 = RA.post {uses = uses,
8370 final_uses = final_uses,
8372 final_defs = final_defs,
8375 registerAllocation = registerAllocation}
8378 = AppendList.appends
8383 (Assembly.instruction instruction),
8385 registerAllocation = registerAllocation}
8387 | XCHG {src, dst, size}
8388 (* Exchange register/memory with register; p. 754
8389 * Require src/dst operands as follows:
8399 val {uses,defs,kills}
8400 = Instruction.uses_defs_kills instruction
8401 val {assembly = assembly_pre,
8403 = RA.pre {uses = uses,
8407 registerAllocation = registerAllocation}
8413 = allocateSrcDst {src = src,
8418 registerAllocation = registerAllocation}
8426 val {uses = final_uses,
8429 = Instruction.uses_defs_kills instruction
8431 val {assembly = assembly_post,
8433 = RA.post {uses = uses,
8434 final_uses = final_uses,
8436 final_defs = final_defs,
8439 registerAllocation = registerAllocation}
8442 = AppendList.appends
8446 (Assembly.instruction instruction),
8448 registerAllocation = registerAllocation}
8450 | pPUSH {src, base, size}
8451 (* Pseudo push a value onto the stack; p. 621
8452 * Require src operand as follows:
8457 * * only word or long registers
8465 val {uses,defs,kills}
8466 = Instruction.uses_defs_kills instruction
8467 val {assembly = assembly_pre,
8469 = RA.pre {uses = uses,
8473 registerAllocation = registerAllocation}
8475 val {assembly = assembly_base,
8478 = RA.allocateOperand {operand = base,
8479 options = {register = true,
8488 force = [Register.esp],
8490 = registerAllocation}
8495 => {register = true,
8500 => {register = true,
8505 => {register = false,
8510 val {operand = final_src,
8511 assembly = assembly_src,
8513 = RA.allocateOperand {operand = src,
8522 = registerAllocation}
8529 val {uses = final_uses,
8532 = Instruction.uses_defs_kills instruction
8534 val {assembly = assembly_post,
8536 = RA.post {uses = uses,
8537 final_uses = final_uses,
8539 final_defs = final_defs,
8542 registerAllocation = registerAllocation}
8545 = AppendList.appends
8550 (Assembly.instruction instruction),
8552 registerAllocation = registerAllocation}
8554 | pPOP {dst, base, size}
8555 (* Pseudo pop a value from the stack; p. 571
8556 * Require dst operand as follows:
8561 * * only word or long registers
8568 val {uses,defs,kills}
8569 = Instruction.uses_defs_kills instruction
8570 val {assembly = assembly_pre,
8572 = RA.pre {uses = uses,
8576 registerAllocation = registerAllocation}
8578 val {assembly = assembly_base,
8581 = RA.allocateOperand {operand = base,
8582 options = {register = true,
8591 force = [Register.esp],
8593 = registerAllocation}
8598 => {register = true,
8603 => {register = true,
8608 => {register = false,
8613 val {operand = final_dst,
8614 assembly = assembly_dst,
8616 = RA.allocateOperand {operand = dst,
8625 = registerAllocation}
8632 val {uses = final_uses,
8635 = Instruction.uses_defs_kills instruction
8637 val {assembly = assembly_post,
8639 = RA.post {uses = uses,
8640 final_uses = final_uses,
8642 final_defs = final_defs,
8645 registerAllocation = registerAllocation}
8648 = AppendList.appends
8653 (Assembly.instruction instruction),
8655 registerAllocation = registerAllocation}
8657 | MOVX {oper, src, dst, srcsize, dstsize}
8658 (* Move with extention.
8659 * Require src/dst operands as follows:
8669 val {uses,defs,kills}
8670 = Instruction.uses_defs_kills instruction
8671 val {assembly = assembly_pre,
8673 = RA.pre {uses = uses,
8677 registerAllocation = registerAllocation}
8679 val {operand = final_src,
8680 assembly = assembly_src,
8682 = RA.allocateOperand {operand = src,
8683 options = {register = true,
8694 = registerAllocation}
8696 val {operand = final_dst,
8697 assembly = assembly_dst,
8698 registerAllocation = registerAllocation}
8699 = RA.allocateOperand {operand = dst,
8700 options = {register = true,
8708 saves = [src,final_src],
8711 = registerAllocation}
8721 val {uses = final_uses,
8724 = Instruction.uses_defs_kills instruction
8726 val {assembly = assembly_post,
8728 = RA.post {uses = uses,
8729 final_uses = final_uses,
8731 final_defs = final_defs,
8734 registerAllocation = registerAllocation}
8737 = AppendList.appends
8742 (Assembly.instruction instruction),
8744 registerAllocation = registerAllocation}
8746 | XVOM {src, dst, srcsize, dstsize}
8747 (* Move with contraction.
8748 * Require src/dst operands as follows:
8758 val {uses,defs,kills}
8759 = Instruction.uses_defs_kills instruction
8760 val {assembly = assembly_pre,
8762 = RA.pre {uses = uses,
8766 registerAllocation = registerAllocation}
8768 val {operand = final_src,
8769 assembly = assembly_src,
8771 = RA.allocateOperand {operand = src,
8772 options = {register = true,
8782 = Register.withLowPart (srcsize,
8785 = registerAllocation}
8787 val {operand = final_dst,
8788 assembly = assembly_dst,
8789 registerAllocation = registerAllocation}
8790 = RA.allocateOperand {operand = dst,
8791 options = {register = true,
8799 saves = [src,final_src],
8802 = registerAllocation}
8804 val {uses = final_uses,
8807 = Instruction.uses_defs_kills
8816 of Operand.Register r
8817 => Register.lowPartOf (r, dstsize)
8819 => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: XVOM, temp_reg"
8823 {src = Operand.register temp_reg,
8827 val {assembly = assembly_post,
8829 = RA.post {uses = uses,
8830 final_uses = final_uses,
8832 final_defs = final_defs,
8835 registerAllocation = registerAllocation}
8838 = AppendList.appends
8843 (Assembly.instruction instruction),
8845 registerAllocation = registerAllocation}
8847 | LEA {src, dst, size}
8848 (* Load effective address; p. 393
8849 * Require src/dst operands as follows:
8859 val {uses,defs,kills}
8860 = Instruction.uses_defs_kills instruction
8861 val {assembly = assembly_pre,
8863 = RA.pre {uses = uses,
8867 registerAllocation = registerAllocation}
8869 val {operand = final_src,
8870 assembly = assembly_src,
8872 = RA.allocateOperand {operand = src,
8873 options = {register = false,
8884 = registerAllocation}
8886 val {operand = final_dst,
8887 assembly = assembly_dst,
8888 registerAllocation = registerAllocation}
8889 = RA.allocateOperand {operand = dst,
8890 options = {register = true,
8898 saves = [src,final_src],
8901 = registerAllocation}
8909 val {uses = final_uses,
8912 = Instruction.uses_defs_kills instruction
8914 val {assembly = assembly_post,
8916 = RA.post {uses = uses,
8917 final_uses = final_uses,
8919 final_defs = final_defs,
8922 registerAllocation = registerAllocation}
8925 = AppendList.appends
8930 (Assembly.instruction instruction),
8932 registerAllocation = registerAllocation}
8934 | pFMOV {src, dst, size} => pfmov {instruction = instruction, info = info,
8935 registerAllocation = registerAllocation,
8936 src = src, dst = dst,
8937 srcsize = size, dstsize = size}
8938 | pFMOVX {src, dst, srcsize, dstsize} => pfmov {instruction = instruction, info = info,
8939 registerAllocation = registerAllocation,
8940 src = src, dst = dst,
8941 srcsize = srcsize, dstsize = dstsize}
8942 | pFXVOM {src, dst, srcsize, dstsize} => pfmov {instruction = instruction, info = info,
8943 registerAllocation = registerAllocation,
8944 src = src, dst = dst,
8945 srcsize = srcsize, dstsize = dstsize}
8946 | pFLDC {oper, dst, size}
8947 (* Pseudo floating-point load constant.
8950 val {uses,defs,kills}
8951 = Instruction.uses_defs_kills instruction
8952 val {assembly = assembly_pre,
8954 = RA.pre {uses = uses,
8958 registerAllocation = registerAllocation}
8960 val {assembly = assembly_dst,
8963 = RA.allocateFltOperand {operand = dst,
8964 options = {fltregister = true,
8973 = registerAllocation}
8979 val {uses = final_uses,
8982 = Instruction.uses_defs_kills instruction
8984 val {assembly = assembly_post,
8986 = RA.post {uses = uses,
8987 final_uses = final_uses,
8989 final_defs = final_defs,
8992 registerAllocation = registerAllocation}
8995 = AppendList.appends
8999 (Assembly.instruction instruction),
9001 registerAllocation = registerAllocation}
9003 | pFMOVFI {src, dst, srcsize, dstsize}
9004 (* Pseudo floating-point from integer.
9007 val {uses,defs,kills}
9008 = Instruction.uses_defs_kills instruction
9009 val {assembly = assembly_pre,
9011 = RA.pre {uses = uses,
9015 registerAllocation = registerAllocation}
9017 val {operand = final_src,
9018 assembly = assembly_src,
9020 = RA.allocateOperand {operand = src,
9021 options = {register = false,
9032 = registerAllocation}
9034 val {assembly = assembly_dst,
9037 = RA.allocateFltOperand {operand = dst,
9038 options = {fltregister = true,
9044 saves = [src,final_src],
9047 = registerAllocation}
9052 size = Size.toFPI srcsize}
9054 val {uses = final_uses,
9057 = Instruction.uses_defs_kills instruction
9059 val {assembly = assembly_post,
9061 = RA.post {uses = uses,
9062 final_uses = final_uses,
9064 final_defs = final_defs,
9067 registerAllocation = registerAllocation}
9070 = AppendList.appends
9075 (Assembly.instruction instruction),
9077 registerAllocation = registerAllocation}
9079 | pFMOVTI {src, dst, srcsize, dstsize}
9080 (* Pseudo floating-point to integer.
9083 val {uses,defs,kills}
9084 = Instruction.uses_defs_kills instruction
9085 val {assembly = assembly_pre,
9087 = RA.pre {uses = uses,
9091 registerAllocation = registerAllocation}
9095 val {operand = final_src,
9096 assembly = assembly_src,
9099 = RA.allocateFltOperand
9101 options = {fltregister = true,
9109 registerAllocation = registerAllocation}
9111 val {operand = final_dst,
9112 assembly = assembly_dst,
9114 = RA.allocateOperand
9116 options = {register = false,
9124 saves = [src,final_src],
9126 registerAllocation = registerAllocation}
9131 size = Size.toFPI dstsize,
9134 val {uses = final_uses,
9137 = Instruction.uses_defs_kills instruction
9139 val {assembly = assembly_post,
9141 = RA.post {uses = uses,
9142 final_uses = final_uses,
9144 final_defs = final_defs,
9147 registerAllocation = registerAllocation}
9150 = AppendList.appends
9155 (Assembly.instruction instruction),
9157 registerAllocation = registerAllocation}
9162 val {operand = final_src,
9163 assembly = assembly_src,
9166 = RA.allocateFltOperand
9168 options = {fltregister = true,
9176 registerAllocation = registerAllocation}
9178 val {operand = final_dst,
9179 assembly = assembly_dst,
9182 = RA.allocateFltOperand
9184 options = {fltregister = false,
9190 saves = [src,final_src],
9192 registerAllocation = registerAllocation}
9197 size = Size.toFPI dstsize,
9200 val {fltrename = fltrename_pop,
9202 = RA.fltpop {registerAllocation = registerAllocation}
9204 val {uses = final_uses,
9207 = Instruction.uses_defs_kills instruction
9210 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
9212 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
9214 val {assembly = assembly_post,
9216 = RA.post {uses = uses,
9217 final_uses = final_uses,
9219 final_defs = final_defs,
9223 = registerAllocation}
9226 = AppendList.appends
9231 (Assembly.instruction instruction),
9233 registerAllocation = registerAllocation}
9237 of Operand.MemLoc memloc_src
9238 => if removable {memloc = memloc_src,
9241 = registerAllocation}
9246 | pFCOM {src1, src2, size}
9247 (* Floating-point compare real; p. 220
9248 * Require src operand as follows:
9253 * * only st(1) if pop and pop'
9255 * Require size modifier class as follows: FLT(SNGL,DBLE)
9258 val {uses,defs,kills}
9259 = Instruction.uses_defs_kills instruction
9260 val {assembly = assembly_pre,
9262 = RA.pre {uses = uses,
9266 registerAllocation = registerAllocation}
9274 = if Operand.eq(src1,src2)
9278 val {operand = final_src1_src2,
9279 assembly = assembly_src1_src2,
9280 fltrename = fltrename_src1_src2,
9282 = RA.allocateFltOperand
9284 options = {fltregister = true,
9293 = registerAllocation}
9295 {final_src1 = final_src1_src2,
9296 final_src2 = final_src1_src2,
9297 assembly_src1_src2 = assembly_src1_src2,
9298 fltrename_src1_src2 = fltrename_src1_src2,
9301 registerAllocation = registerAllocation}
9305 of Operand.MemLoc memloc_src1
9306 => if removable {memloc = memloc_src1,
9309 = registerAllocation}
9312 | _ => default false
9317 val {operand = final_src2,
9318 assembly = assembly_src2,
9319 fltrename = fltrename_src2,
9321 = RA.allocateFltOperand
9323 options = {fltregister = true,
9332 = registerAllocation}
9334 val {operand = final_src1,
9335 assembly = assembly_src1,
9336 fltrename = fltrename_src1,
9338 = RA.allocateFltOperand
9340 options = {fltregister = true,
9346 saves = [src2,final_src2],
9349 = registerAllocation}
9352 = (RA.fltrenameLift fltrename_src1) final_src2
9354 {final_src1 = final_src1,
9355 final_src2 = final_src2,
9357 = AppendList.appends
9360 fltrename_src1_src2 = fltrename_src1 o
9364 registerAllocation = registerAllocation}
9369 val {operand_top = final_src1,
9370 operand_one = final_src2,
9371 assembly = assembly_src1_src2,
9372 fltrename = fltrename_src1_src2,
9374 = RA.allocateFltStackOperands
9375 {operand_top = src1,
9385 = registerAllocation}
9387 {final_src1 = final_src1,
9388 final_src2 = final_src2,
9389 assembly_src1_src2 = assembly_src1_src2,
9390 fltrename_src1_src2 = fltrename_src1_src2,
9393 registerAllocation = registerAllocation}
9397 of (Operand.MemLoc memloc_src1,
9398 Operand.MemLoc memloc_src2)
9399 => if removable {memloc = memloc_src1,
9402 = registerAllocation}
9404 {memloc = memloc_src2,
9407 = registerAllocation}
9411 | (Operand.MemLoc memloc_src1, _)
9412 => if removable {memloc = memloc_src1,
9415 = registerAllocation}
9418 | _ => default false
9428 val {fltrename = fltrename_pop,
9433 val {fltrename = fltrename_pop,
9435 = RA.fltpop {registerAllocation
9436 = registerAllocation}
9437 val {fltrename = fltrename_pop',
9439 = RA.fltpop {registerAllocation
9440 = registerAllocation}
9442 {fltrename = fltrename_pop' o fltrename_pop,
9443 registerAllocation= registerAllocation}
9446 val {fltrename = fltrename_pop,
9448 = RA.fltpop {registerAllocation
9449 = registerAllocation}
9451 {fltrename = fltrename_pop,
9452 registerAllocation = registerAllocation}
9454 else {fltrename = FltRegister.id,
9455 registerAllocation = registerAllocation}
9457 val {uses = final_uses,
9460 = Instruction.uses_defs_kills instruction
9463 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
9465 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
9467 val {assembly = assembly_post,
9469 = RA.post {uses = uses,
9470 final_uses = final_uses,
9472 final_defs = final_defs,
9475 registerAllocation = registerAllocation}
9478 = AppendList.appends
9482 (Assembly.instruction instruction),
9484 registerAllocation = registerAllocation}
9486 | pFUCOM {src1, src2, size}
9487 (* Floating-point unordered compare real; p. 307
9488 * Require src operand as follows:
9493 * * only st(1) if pop and pop'
9496 val {uses,defs,kills}
9497 = Instruction.uses_defs_kills instruction
9498 val {assembly = assembly_pre,
9500 = RA.pre {uses = uses,
9504 registerAllocation = registerAllocation}
9512 = if Operand.eq(src1,src2)
9516 val {operand = final_src1_src2,
9517 assembly = assembly_src1_src2,
9518 fltrename = fltrename_src1_src2,
9520 = RA.allocateFltOperand
9522 options = {fltregister = true,
9531 = registerAllocation}
9533 {final_src1 = final_src1_src2,
9534 final_src2 = final_src1_src2,
9535 assembly_src1_src2 = assembly_src1_src2,
9536 fltrename_src1_src2 = fltrename_src1_src2,
9539 registerAllocation = registerAllocation}
9543 of Operand.MemLoc memloc_src1
9544 => if removable {memloc = memloc_src1,
9547 = registerAllocation}
9550 | _ => default false
9555 val {operand = final_src2,
9556 assembly = assembly_src2,
9557 fltrename = fltrename_src2,
9559 = RA.allocateFltOperand
9561 options = {fltregister = true,
9570 = registerAllocation}
9572 val {operand = final_src1,
9573 assembly = assembly_src1,
9574 fltrename = fltrename_src1,
9576 = RA.allocateFltOperand
9578 options = {fltregister = true,
9584 saves = [src2,final_src2],
9587 = registerAllocation}
9590 = (RA.fltrenameLift fltrename_src1) final_src2
9592 {final_src1 = final_src1,
9593 final_src2 = final_src2,
9595 = AppendList.appends
9598 fltrename_src1_src2 = fltrename_src1 o
9602 registerAllocation = registerAllocation}
9606 of (Operand.MemLoc memloc_src1,
9607 Operand.MemLoc memloc_src2)
9610 = case RA.fltallocated
9611 {memloc = memloc_src2,
9613 = registerAllocation}
9621 = assembly_src1_src2,
9623 = fltrename_src1_src2,
9625 = RA.allocateFltStackOperands
9626 {operand_top = src1,
9636 = registerAllocation}
9638 {final_src1 = final_src1,
9639 final_src2 = final_src2,
9641 = assembly_src1_src2,
9643 = fltrename_src1_src2,
9647 = registerAllocation}
9653 {memloc = memloc_src1,
9656 = registerAllocation}
9658 {memloc = memloc_src2,
9661 = registerAllocation}
9666 | (Operand.MemLoc memloc_src1, _)
9667 => if removable {memloc = memloc_src1,
9670 = registerAllocation}
9673 | _ => default false
9682 val {fltrename = fltrename_pop,
9687 val {fltrename = fltrename_pop,
9689 = RA.fltpop {registerAllocation
9690 = registerAllocation}
9691 val {fltrename = fltrename_pop',
9693 = RA.fltpop {registerAllocation
9694 = registerAllocation}
9696 {fltrename = fltrename_pop' o fltrename_pop,
9697 registerAllocation= registerAllocation}
9700 val {fltrename = fltrename_pop,
9702 = RA.fltpop {registerAllocation
9703 = registerAllocation}
9705 {fltrename = fltrename_pop,
9706 registerAllocation = registerAllocation}
9708 else {fltrename = FltRegister.id,
9709 registerAllocation = registerAllocation}
9711 val {uses = final_uses,
9714 = Instruction.uses_defs_kills instruction
9717 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
9719 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
9721 val {assembly = assembly_post,
9723 = RA.post {uses = uses,
9724 final_uses = final_uses,
9726 final_defs = final_defs,
9729 registerAllocation = registerAllocation}
9732 = AppendList.appends
9736 (Assembly.instruction instruction),
9738 registerAllocation = registerAllocation}
9740 | pFBinA {oper, src, dst, size}
9741 (* Floating-point binary arithmetic instructions.
9742 * Require src operand as follows:
9747 * * only st(0) if pop
9749 * Require dst operand as follows:
9754 * * only st(0) if src add
9756 * * one of src,dst must be st(0)
9758 * Require size modifier class as follows: FLT
9761 val {uses,defs,kills}
9762 = Instruction.uses_defs_kills instruction
9763 val {assembly = assembly_pre,
9765 = RA.pre {uses = uses,
9769 registerAllocation = registerAllocation}
9778 = if Operand.eq(src,dst)
9780 val {operand = final_src_dst,
9781 assembly = assembly_src_dst,
9782 fltrename = fltrename_src_dst,
9784 = RA.allocateFltOperand
9786 options = {fltregister = true,
9795 = registerAllocation}
9797 {final_src = final_src_dst,
9798 final_dst = final_src_dst,
9799 assembly_src_dst = assembly_src_dst,
9800 fltrename_src_dst = fltrename_src_dst,
9803 registerAllocation = registerAllocation}
9808 val {operand = final_src,
9809 assembly = assembly_src,
9810 fltrename = fltrename_src,
9812 = RA.allocateFltOperand
9814 options = {fltregister = true,
9823 = registerAllocation}
9825 val {operand = final_dst,
9826 assembly = assembly_dst,
9827 fltrename = fltrename_dst,
9830 of Operand.Address _
9831 => RA.allocateFltOperand
9833 options = {fltregister = true,
9839 saves = [src,final_src],
9842 = registerAllocation}
9843 | Operand.FltRegister f
9844 => if FltRegister.eq
9845 (f, FltRegister.top)
9846 then RA.allocateFltOperand
9849 = {fltregister = true,
9855 saves = [src,final_src],
9858 = registerAllocation}
9859 else RA.allocateFltOperand
9862 = {fltregister = true,
9868 saves = [src,final_src],
9871 = registerAllocation}
9874 "x86AllocateRegisters.Instruction.allocateRegisters: pFBinA, final_src"
9877 = (RA.fltrenameLift fltrename_dst) final_src
9879 {final_src = final_src,
9880 final_dst = final_dst,
9882 = AppendList.appends
9885 fltrename_src_dst = fltrename_dst o
9889 registerAllocation = registerAllocation}
9894 val {operand = final_dst,
9895 assembly = assembly_dst,
9896 fltrename = fltrename_dst,
9898 = RA.allocateFltOperand
9900 options = {fltregister = true,
9909 = registerAllocation}
9911 val {operand = final_src,
9912 assembly = assembly_src,
9913 fltrename = fltrename_src,
9915 = RA.allocateFltOperand
9917 options = {fltregister = true,
9923 saves = [dst,final_dst],
9926 = registerAllocation}
9929 = (RA.fltrenameLift fltrename_src) final_dst
9931 {final_src = final_src,
9932 final_dst = final_dst,
9934 = AppendList.appends
9937 fltrename_src_dst = fltrename_src o
9941 registerAllocation = registerAllocation}
9944 fun default'' value_dst
9946 val {operand = final_dst,
9947 assembly = assembly_dst,
9948 fltrename = fltrename_dst,
9950 = RA.allocateFltOperand
9952 options = {fltregister = true,
9961 = registerAllocation}
9963 val {operand = final_src,
9964 assembly = assembly_src,
9965 fltrename = fltrename_src,
9967 = RA.allocateFltOperand
9969 options = {fltregister = true,
9975 saves = [dst,final_dst],
9978 = registerAllocation}
9981 = (RA.fltrenameLift fltrename_src) final_dst
9983 val {memloc = memloc_dst,
9984 weight = weight_dst,
9986 commit = commit_dst,
9987 ...} : RegisterAllocation.fltvalue
9991 = case Operand.deFltregister final_src
9992 of SOME fltregister => fltregister
9994 => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: pFBinA, final_src"
9996 val registerAllocation
9999 = {fltregister = fltregister_src,
10000 memloc = memloc_dst,
10001 weight = weight_dst,
10003 commit = commit_dst},
10005 = registerAllocation}
10007 {final_src = final_dst,
10008 final_dst = final_src,
10010 = AppendList.appends
10013 fltrename_src_dst = fltrename_src o
10015 oper = Instruction.fbina_reverse oper,
10017 registerAllocation = registerAllocation}
10020 fun default''' memloc_dst
10022 val {operand = final_dst,
10023 assembly = assembly_dst,
10024 fltrename = fltrename_dst,
10025 registerAllocation}
10026 = RA.allocateFltOperand
10028 options = {fltregister = false,
10037 = registerAllocation}
10039 val {operand = final_src,
10040 assembly = assembly_src,
10041 fltrename = fltrename_src,
10042 registerAllocation}
10043 = RA.allocateFltOperand
10045 options = {fltregister = true,
10051 saves = [dst,final_dst],
10054 = registerAllocation}
10057 = (RA.fltrenameLift fltrename_src) final_dst
10059 val {fltrename = fltrename_pop,
10060 registerAllocation}
10062 {registerAllocation
10063 = registerAllocation}
10065 val {fltrename = fltrename_push,
10066 registerAllocation}
10069 = {fltregister = FltRegister.top,
10070 memloc = memloc_dst,
10075 = registerAllocation}
10077 {final_src = final_dst,
10078 final_dst = final_src,
10080 = AppendList.appends
10083 fltrename_src_dst = fltrename_push o
10087 oper = Instruction.fbina_reverse oper,
10089 registerAllocation = registerAllocation}
10093 of (Operand.MemLoc memloc_src,
10094 Operand.MemLoc memloc_dst)
10095 => (case (RA.fltallocated
10096 {memloc = memloc_src,
10098 = registerAllocation},
10100 {memloc = memloc_dst,
10102 = registerAllocation})
10103 of (SOME ({sync = sync_src,
10109 => if MemLocSet.contains(dead,
10112 (MemLocSet.contains(remove,
10116 then if FltRegister.eq
10119 then default'' value_dst
10122 | (SOME {sync = sync_src,...},
10124 => if MemLocSet.contains(dead,
10127 (MemLocSet.contains(remove,
10131 then default''' memloc_dst
10134 | (Operand.MemLoc memloc_src, _)
10135 => (case RA.fltallocated
10136 {memloc = memloc_src,
10138 = registerAllocation}
10139 of SOME {sync = sync_src,...}
10140 => if MemLocSet.contains(dead,
10143 (MemLocSet.contains(remove,
10154 = if Operand.eq(final_src,
10155 Operand.fltregister FltRegister.top)
10156 andalso isSome (Operand.deFltregister final_dst)
10157 then fbina_reverse oper
10161 = Instruction.FBinA
10168 val {fltrename = fltrename_pop,
10169 registerAllocation}
10172 val {fltrename = fltrename_pop,
10173 registerAllocation}
10174 = RA.fltpop {registerAllocation
10175 = registerAllocation}
10177 {fltrename = fltrename_pop,
10178 registerAllocation = registerAllocation}
10180 else {fltrename = FltRegister.id,
10181 registerAllocation = registerAllocation}
10183 val {uses = final_uses,
10186 = Instruction.uses_defs_kills instruction
10189 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
10191 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
10193 val {assembly = assembly_post,
10194 registerAllocation}
10195 = RA.post {uses = uses,
10196 final_uses = final_uses,
10198 final_defs = final_defs,
10201 registerAllocation = registerAllocation}
10205 = AppendList.appends
10209 (Assembly.instruction instruction),
10211 registerAllocation = registerAllocation}
10213 | pFUnA {oper, dst, size}
10214 (* Floating-point unary arithmetic instructions.
10215 * Require src operand as follows:
10222 * Require size modifier class as follows: FLT
10225 val {uses,defs,kills}
10226 = Instruction.uses_defs_kills instruction
10227 val {assembly = assembly_pre,
10228 registerAllocation}
10229 = RA.pre {uses = uses,
10233 registerAllocation = registerAllocation}
10235 val {assembly = assembly_dst,
10236 registerAllocation,
10238 = RA.allocateFltOperand {operand = dst,
10239 options = {fltregister = true,
10248 = registerAllocation}
10254 val {uses = final_uses,
10257 = Instruction.uses_defs_kills instruction
10259 val {assembly = assembly_post,
10260 registerAllocation}
10261 = RA.post {uses = uses,
10262 final_uses = final_uses,
10264 final_defs = final_defs,
10267 registerAllocation = registerAllocation}
10270 = AppendList.appends
10274 (Assembly.instruction instruction),
10276 registerAllocation = registerAllocation}
10278 | pFPTAN {dst, size}
10279 (* Floating-point partial tangent instruction.
10280 * Require src operand as follows:
10287 * Require size modifier class as follows: FLT
10288 * Automatically pushes 1.0 onto stack.
10291 val {uses,defs,kills}
10292 = Instruction.uses_defs_kills instruction
10293 val {assembly = assembly_pre,
10294 registerAllocation}
10295 = RA.pre {uses = uses,
10299 registerAllocation = registerAllocation}
10301 val {assembly = assembly_free,
10302 registerAllocation,
10304 = RA.freeFltRegister
10309 registerAllocation = registerAllocation}
10311 val {assembly = assembly_dst,
10312 registerAllocation,
10314 = RA.allocateFltOperand {operand = dst,
10315 options = {fltregister = true,
10324 = registerAllocation}
10327 = Instruction.FPTAN
10329 val {uses = final_uses,
10332 = Instruction.uses_defs_kills instruction
10334 val {assembly = assembly_post,
10335 registerAllocation}
10336 = RA.post {uses = uses,
10337 final_uses = final_uses,
10339 final_defs = final_defs,
10342 registerAllocation = registerAllocation}
10345 = AppendList.appends
10350 (Assembly.instruction instruction),
10352 (Assembly.instruction_fst
10353 {dst = Operand.fltregister FltRegister.top,
10357 registerAllocation = registerAllocation}
10359 | pFBinAS {oper, src, dst, size}
10360 (* Floating-point binary arithmetic stack instructions.
10361 * Require src operand as follows:
10368 * Require dst operand as follows:
10375 * Require size modifier class as follows: FLT
10378 val {uses,defs,kills}
10379 = Instruction.uses_defs_kills instruction
10380 val {assembly = assembly_pre,
10381 registerAllocation}
10382 = RA.pre {uses = uses,
10386 registerAllocation = registerAllocation}
10388 val {assembly = assembly_dst_src,
10389 registerAllocation,
10391 = RA.allocateFltStackOperands
10392 {operand_top = dst,
10401 registerAllocation = registerAllocation}
10404 = Instruction.FBinAS
10407 val {uses = final_uses,
10410 = Instruction.uses_defs_kills instruction
10412 val {assembly = assembly_post,
10413 registerAllocation}
10414 = RA.post {uses = uses,
10415 final_uses = final_uses,
10417 final_defs = final_defs,
10420 registerAllocation = registerAllocation}
10423 = AppendList.appends
10427 (Assembly.instruction instruction),
10429 registerAllocation = registerAllocation}
10431 | pFBinASP {oper, src, dst, size}
10432 (* Floating-point binary arithmetic stack pop instructions.
10433 * Require src operand as follows:
10440 * Require dst operand as follows:
10447 * Require size modifier class as follows: FLT
10450 val {uses,defs,kills}
10451 = Instruction.uses_defs_kills instruction
10452 val {assembly = assembly_pre,
10453 registerAllocation}
10454 = RA.pre {uses = uses,
10458 registerAllocation = registerAllocation}
10460 val {assembly = assembly_src_dst,
10461 registerAllocation, ...}
10462 = RA.allocateFltStackOperands
10463 {operand_top = src,
10472 registerAllocation = registerAllocation}
10475 = Instruction.FBinASP
10478 val {fltrename = fltrename_pop,
10479 registerAllocation}
10480 = RA.fltpop {registerAllocation = registerAllocation}
10482 val {uses = final_uses,
10485 = Instruction.uses_defs_kills instruction
10488 = List.revMap(final_uses, RA.fltrenameLift fltrename_pop)
10490 = List.revMap(final_defs, RA.fltrenameLift fltrename_pop)
10492 val {assembly = assembly_post,
10493 registerAllocation}
10494 = RA.post {uses = uses,
10495 final_uses = final_uses,
10497 final_defs = final_defs,
10500 registerAllocation = registerAllocation}
10503 = AppendList.appends
10507 (Assembly.instruction instruction),
10509 registerAllocation = registerAllocation}
10512 (* Floating-point load control word; p. 252
10513 * Require src operand as follows:
10520 val {uses,defs,kills}
10521 = Instruction.uses_defs_kills instruction
10522 val {assembly = assembly_pre,
10523 registerAllocation}
10524 = RA.pre {uses = uses,
10528 registerAllocation = registerAllocation}
10530 val {operand = final_src,
10531 assembly = assembly_src,
10532 registerAllocation}
10533 = RA.allocateOperand {operand = src,
10534 options = {register = false,
10545 = registerAllocation}
10548 = Instruction.FLDCW
10551 val {uses = final_uses,
10554 = Instruction.uses_defs_kills instruction
10556 val {assembly = assembly_post,
10557 registerAllocation}
10558 = RA.post {uses = uses,
10559 final_uses = final_uses,
10561 final_defs = final_defs,
10564 registerAllocation = registerAllocation}
10567 = AppendList.appends
10571 (Assembly.instruction instruction),
10573 registerAllocation = registerAllocation}
10575 | FSTCW {dst, check}
10576 (* Floating-point store control word; p. 289
10577 * Require dst operand as follows:
10584 val {uses,defs,kills}
10585 = Instruction.uses_defs_kills instruction
10586 val {assembly = assembly_pre,
10587 registerAllocation}
10588 = RA.pre {uses = uses,
10592 registerAllocation = registerAllocation}
10594 val {operand = final_dst,
10595 assembly = assembly_dst,
10596 registerAllocation}
10597 = RA.allocateOperand {operand = dst,
10598 options = {register = false,
10609 = registerAllocation}
10612 = Instruction.FSTCW
10616 val {uses = final_uses,
10619 = Instruction.uses_defs_kills instruction
10621 val {assembly = assembly_post,
10622 registerAllocation}
10623 = RA.post {uses = uses,
10624 final_uses = final_uses,
10626 final_defs = final_defs,
10629 registerAllocation = registerAllocation}
10632 = AppendList.appends
10636 (Assembly.instruction instruction),
10638 registerAllocation = registerAllocation}
10640 | FSTSW {dst, check}
10641 (* Floating-point store status word; p. 294
10642 * Require dst operand as follows:
10647 * * only register %ax
10650 val {uses,defs,kills}
10651 = Instruction.uses_defs_kills instruction
10652 val {assembly = assembly_pre,
10653 registerAllocation}
10654 = RA.pre {uses = uses,
10658 registerAllocation = registerAllocation}
10660 val {operand = final_dst,
10661 assembly = assembly_dst,
10662 registerAllocation}
10663 = RA.allocateOperand {operand = dst,
10664 options = {register = true,
10673 force = [Register.T
10674 {reg = Register.EAX,
10675 part = Register.X}],
10677 = registerAllocation}
10680 = Instruction.FSTSW
10684 val {uses = final_uses,
10687 = Instruction.uses_defs_kills instruction
10689 val {assembly = assembly_post,
10690 registerAllocation}
10691 = RA.post {uses = uses,
10692 final_uses = final_uses,
10694 final_defs = final_defs,
10697 registerAllocation = registerAllocation}
10700 = AppendList.appends
10704 (Assembly.instruction instruction),
10706 registerAllocation = registerAllocation}
10708 | _ => Error.bug "x86AllocateRegisters.Instruction.allocateRegisters: unimplemented"
10710 val (allocateRegisters, allocateRegisters_msg)
10712 "Instruction.allocateRegisters"
10716 structure Directive =
10720 fun allocateRegisters {directive, info, registerAllocation}
10722 val {assembly, registerAllocation}
10724 of Assume {assumes}
10725 => RegisterAllocation.assume
10726 {assumes = assumes,
10728 registerAllocation = registerAllocation}
10729 | FltAssume {assumes}
10730 => RegisterAllocation.fltassume
10731 {assumes = assumes,
10733 registerAllocation = registerAllocation}
10735 => RegisterAllocation.cache
10738 registerAllocation = registerAllocation}
10739 | FltCache {caches}
10740 => RegisterAllocation.fltcache
10743 registerAllocation = registerAllocation}
10745 => RegisterAllocation.reset
10746 {registerAllocation = registerAllocation}
10747 | Force {commit_memlocs, commit_classes,
10748 remove_memlocs, remove_classes,
10749 dead_memlocs, dead_classes}
10750 => RegisterAllocation.force
10751 {commit_memlocs = commit_memlocs,
10752 commit_classes = commit_classes,
10753 remove_memlocs = remove_memlocs,
10754 remove_classes = remove_classes,
10755 dead_memlocs = dead_memlocs,
10756 dead_classes = dead_classes,
10758 registerAllocation = registerAllocation}
10760 => RegisterAllocation.ccall
10762 registerAllocation = registerAllocation}
10764 => RegisterAllocation.return
10765 {returns = returns,
10767 registerAllocation = registerAllocation}
10768 | Reserve {registers}
10769 => RegisterAllocation.reserve
10770 {registers = registers,
10771 registerAllocation = registerAllocation}
10772 | Unreserve {registers}
10773 => RegisterAllocation.unreserve
10774 {registers = registers,
10775 registerAllocation = registerAllocation}
10777 => RegisterAllocation.clearflt
10779 registerAllocation = registerAllocation}
10780 | SaveRegAlloc {live, id}
10781 => RegisterAllocation.saveregalloc
10785 registerAllocation = registerAllocation}
10786 | RestoreRegAlloc {live, id}
10787 => RegisterAllocation.restoreregalloc
10791 registerAllocation = registerAllocation}
10793 {assembly = assembly,
10794 registerAllocation = registerAllocation}
10797 val (allocateRegisters, allocateRegisters_msg)
10799 "Directive.allocateRegisters"
10803 structure Assembly =
10807 fun allocateRegisters {assembly: (t * Liveness.t) list,
10808 registerAllocation: RegisterAllocation.t}
10810 val {assembly, registerAllocation}
10813 {assembly = AppendList.empty,
10814 registerAllocation = registerAllocation},
10815 fn ((Comment s,_), {assembly, registerAllocation})
10816 => {assembly = AppendList.snoc
10819 registerAllocation = registerAllocation}
10820 | ((Directive d,info), {assembly, registerAllocation})
10822 val {assembly = assembly',
10823 registerAllocation}
10824 = Directive.allocateRegisters
10827 registerAllocation = registerAllocation}
10830 = AppendList.appends
10831 [if !Control.Native.commented > 1
10832 then AppendList.fromList
10834 (String.make (60, #"*")),
10836 (Directive.toString d))]
10837 else AppendList.empty,
10838 if !Control.Native.commented > 4
10839 then AppendList.fromList
10840 (Liveness.toComments info)
10841 else AppendList.empty,
10843 if !Control.Native.commented > 5
10844 then (RegisterAllocation.toComments
10845 registerAllocation)
10846 else AppendList.empty]
10848 {assembly = AppendList.append
10851 registerAllocation = registerAllocation}
10853 | ((PseudoOp p,_), {assembly, registerAllocation})
10854 => {assembly = AppendList.snoc
10857 registerAllocation = registerAllocation}
10858 | ((Label l,_), {assembly, registerAllocation})
10859 => {assembly = AppendList.snoc
10862 registerAllocation = registerAllocation}
10863 | ((Instruction i,info), {assembly, registerAllocation})
10865 val {assembly = assembly',
10866 registerAllocation}
10867 = Instruction.allocateRegisters
10870 registerAllocation = registerAllocation}
10873 = AppendList.appends
10874 [if !Control.Native.commented > 1
10875 then AppendList.fromList
10877 (String.make (60, #"*")),
10879 (Instruction.toString i))]
10880 else AppendList.empty,
10881 if !Control.Native.commented > 4
10882 then AppendList.fromList
10883 (Liveness.toComments info)
10884 else AppendList.empty,
10886 if !Control.Native.commented > 5
10887 then (RegisterAllocation.toComments
10888 registerAllocation)
10889 else AppendList.empty]
10891 {assembly = AppendList.append
10894 registerAllocation = registerAllocation}
10897 val assembly = AppendList.toList assembly
10898 val assembly = if !Control.Native.commented > 1
10899 then (Assembly.comment
10900 (String.make (60, #"&"))::
10902 (String.make (60, #"&"))::
10906 {assembly = assembly,
10907 registerAllocation = registerAllocation}
10910 val (allocateRegisters, allocateRegisters_msg)
10912 "Assembly.allocateRegisters"
10916 fun allocateRegisters {assembly : Assembly.t list list,
10918 Assembly.t list list
10920 val {get = getInfo : Label.t -> Label.t option,
10921 set = setInfo, ...}
10922 = Property.getSetOnce
10924 Property.initConst NONE)
10927 = case getInfo label
10929 | SOME label' => unroll label'
10935 fn (assembly,assembly')
10939 then Liveness.toLiveness assembly
10940 else Liveness.toNoLiveness assembly
10942 val {assembly, ...}
10943 = Assembly.allocateRegisters
10944 {assembly = assembly,
10946 = RegisterAllocation.empty ()}
10949 = fn (Assembly.Comment _)::assembly
10951 | (Assembly.PseudoOp (PseudoOp.P2align _))::assembly
10952 => doit' (assembly, [])
10955 = fn ((Assembly.Comment _)::assembly, labels)
10956 => doit' (assembly, labels)
10957 | ((Assembly.PseudoOp (PseudoOp.Local _))::assembly, labels)
10958 => doit' (assembly, labels)
10959 | ((Assembly.Label l)::assembly, labels)
10960 => doit' (assembly, l::labels)
10961 | (assembly, labels) => doit'' (assembly, labels)
10963 = fn ((Assembly.Comment _)::assembly, labels)
10964 => doit'' (assembly, labels)
10965 | ((Assembly.Instruction
10967 {target = Operand.Label label,
10968 absolute = false}))::assembly, labels)
10969 => doit''' (assembly, labels, label)
10972 = fn ([], labels, label)
10974 val label' = unroll label
10976 if List.contains(labels, label', Label.equals)
10980 fn label'' => setInfo(label'', SOME label'));
10983 | ((Assembly.Comment _)::assembly, labels, label)
10984 => doit''' (assembly, labels, label)
10989 else assembly::assembly'
10992 fun replacer _ oper
10993 = (case (Operand.deImmediate oper, Operand.deLabel oper)
10994 of (SOME immediate, _)
10995 => (case Immediate.deLabel immediate
10996 of SOME label => Operand.immediate_label (unroll label)
10998 | (_, SOME label) => Operand.label (unroll label)
11005 fn (assembly,assembly')
11006 => (List.map(assembly, Assembly.replace replacer))::assembly')
11011 val (allocateRegisters, allocateRegisters_msg)
11013 "allocateRegisters"
11016 fun allocateRegisters_totals ()
11017 = (allocateRegisters_msg ();
11019 Liveness.toLiveness_msg ();
11020 Liveness.toNoLiveness_msg ();
11021 Assembly.allocateRegisters_msg ();
11023 Instruction.allocateRegisters_msg ();
11025 RegisterAllocation.pre_msg ();
11026 RegisterAllocation.post_msg ();
11027 RegisterAllocation.allocateOperand_msg ();
11028 RegisterAllocation.allocateFltOperand_msg ();
11029 RegisterAllocation.allocateFltStackOperands_msg ();
11030 Control.unindent ();
11031 Directive.allocateRegisters_msg ();
11032 Control.unindent ();
11033 Control.unindent())