1 (* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
9 functor x86 (S: X86_STRUCTS): X86 =
13 = fn s => Control.traceBatch (Control.Pass, s)
15 = fn s => fn f => (Control.trace (Control.Pass, s) f, fn () => ())
18 = fn s => Control.traceBatch (Control.Detail, s)
20 = fn s => fn f => (Control.trace (Control.Detail, s) f, fn () => ())
23 (* compensate for differences between
24 * C-escape sequences and ASM-escape sequences
26 val Char_escapeASM = fn #"\000" => "\\000"
32 fun String_escapeASM s = String.translate(s, Char_escapeASM)
39 if Relation.equals(ord, EQUAL)
52 if !Control.labelsHaveExtra_
53 then concat ["_", Label.toString l]
56 val layout = Layout.str o toString
61 datatype class = INT | FLT | FPI
82 val toString = Layout.toString o layout
84 val fromBytes : int -> t
88 | _ => Error.bug "x86.Size.fromBytes"
89 val toBytes : t -> int
101 datatype z = datatype CType.t
105 CPointer => Vector.new1 LONG
106 | Int8 => Vector.new1 BYTE
107 | Int16 => Vector.new1 WORD
108 | Int32 => Vector.new1 LONG
109 | Int64 => Vector.new2 (LONG, LONG)
110 | Objptr => Vector.new1 LONG
111 | Real32 => Vector.new1 SNGL
112 | Real64 => Vector.new1 DBLE
113 | Word8 => Vector.new1 BYTE
114 | Word16 => Vector.new1 WORD
115 | Word32 => Vector.new1 LONG
116 | Word64 => Vector.new2 (LONG, LONG)
136 | _ => Error.bug "x86.Size.toFPI"
138 val eq = fn (s1, s2) => s1 = s2
139 val lt = fn (s1, s2) => (toBytes s1) < (toBytes s2)
146 = EAX | EBX | ECX | EDX | EDI | ESI | EBP | ESP
147 val allReg = [EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP]
152 datatype t = T of {reg: reg, part: part}
154 fun size (T {part, ...})
161 fun layout (T {reg, part})
166 of E => {prefix = str "%e", suffix = str "x"}
167 | X => {prefix = str "%", suffix = str "x"}
168 | L => {prefix = str "%", suffix = str "l"}
169 | H => {prefix = str "%", suffix = str "h"}
172 of EAX => seq [prefix, str "a", suffix]
173 | EBX => seq [prefix, str "b", suffix]
174 | ECX => seq [prefix, str "c", suffix]
175 | EDX => seq [prefix, str "d", suffix]
176 | EDI => seq [prefix, str "di"]
177 | ESI => seq [prefix, str "si"]
178 | EBP => seq [prefix, str "bp"]
179 | ESP => seq [prefix, str "sp"]
181 val toString = Layout.toString o layout
183 fun eq(T r1, T r2) = r1 = r2
185 val eax = T {reg = EAX, part = E}
186 val ebx = T {reg = EBX, part = E}
187 val ecx = T {reg = ECX, part = E}
188 val edx = T {reg = EDX, part = E}
189 val ax = T {reg= EAX, part = X}
190 val al = T {reg = EAX, part = L}
191 val bl = T {reg = EBX, part = L}
192 val cl = T {reg = ECX, part = L}
193 val dl = T {reg = EDX, part = L}
194 val edi = T {reg = EDI, part = E}
195 val esi = T {reg = ESI, part = E}
196 val esp = T {reg = ESP, part = E}
197 val ebp = T {reg = EBP, part = E}
199 val byteRegisters = [T {reg = EAX, part = L},
200 T {reg = EAX, part = H},
201 T {reg = EBX, part = L},
202 T {reg = EBX, part = H},
203 T {reg = ECX, part = L},
204 T {reg = ECX, part = H},
205 T {reg = EDX, part = L},
206 T {reg = EDX, part = H}]
207 val byteRegisters = List.rev byteRegisters
209 val wordRegisters = [T {reg = EAX, part = X},
210 T {reg = EBX, part = X},
211 T {reg = ECX, part = X},
212 T {reg = EDX, part = X},
213 T {reg = EDI, part = X},
214 T {reg = ESI, part = X},
215 T {reg = EBP, part = X},
216 T {reg = ESP, part = X}]
217 val wordRegisters = List.rev wordRegisters
219 val longRegisters = [T {reg = EAX, part = E},
220 T {reg = EBX, part = E},
221 T {reg = ECX, part = E},
222 T {reg = EDX, part = E},
223 T {reg = EDI, part = E},
224 T {reg = ESI, part = E},
225 T {reg = EBP, part = E},
226 T {reg = ESP, part = E}]
227 val longRegisters = List.rev longRegisters
229 val all = List.concat [byteRegisters, wordRegisters, longRegisters]
231 fun valid r = List.contains(all, r, eq)
234 = fn (E, E) => true | (E, X) => true | (E, L) => true | (E, H) => true
235 | (X, X) => true | (X, L) => true | (X, H) => true
240 fun coincide (T {reg = reg1, part = part1},
241 T {reg = reg2, part = part2})
242 = reg1 = reg2 andalso (contains(part1,part2) orelse
243 contains(part2,part1))
246 = List.keepAllMap([E, X, L, H],
249 val register' = T {reg = reg, part = part}
251 if valid register' andalso
252 coincide(T {reg = reg, part = E}, register')
258 = fn Size.BYTE => byteRegisters
259 | Size.WORD => wordRegisters
260 | Size.LONG => longRegisters
261 | _ => Error.bug "x86.Register.registers"
263 val baseRegisters = longRegisters
264 val indexRegisters = [T {reg = EAX, part = E},
265 T {reg = EBX, part = E},
266 T {reg = ECX, part = E},
267 T {reg = EDX, part = E},
268 T {reg = EDI, part = E},
269 T {reg = ESI, part = E},
270 T {reg = EBP, part = E}]
272 val callerSaveRegisters = [T {reg = EAX, part = E},
273 T {reg = EAX, part = X},
274 T {reg = EAX, part = L},
275 T {reg = EAX, part = H},
276 T {reg = ECX, part = E},
277 T {reg = ECX, part = X},
278 T {reg = ECX, part = L},
279 T {reg = ECX, part = H},
280 T {reg = EDX, part = E},
281 T {reg = EDX, part = X},
282 T {reg = EDX, part = L},
283 T {reg = EDX, part = H}]
284 val calleeSaveRegisters = [T {reg = EBX, part = E},
285 T {reg = EBX, part = X},
286 T {reg = EBX, part = L},
287 T {reg = EBX, part = H},
288 T {reg = EDI, part = E},
289 T {reg = EDI, part = X},
290 T {reg = ESI, part = E},
291 T {reg = ESI, part = X}]
293 val withLowPart (* (fullsize,lowsize) *)
294 = fn (Size.WORD,Size.BYTE) => [T {reg = EAX, part = X},
295 T {reg = EBX, part = X},
296 T {reg = ECX, part = X},
297 T {reg = EDX, part = X}]
298 | (Size.LONG,Size.BYTE) => [T {reg = EAX, part = E},
299 T {reg = EBX, part = E},
300 T {reg = ECX, part = E},
301 T {reg = EDX, part = E}]
302 | (Size.LONG,Size.WORD) => longRegisters
303 | _ => Error.bug "x86.Register.withLowPart: fullsize,lowsize"
305 val lowPartOf (* (register,lowsize) *)
306 = fn (T {reg, part = L},Size.BYTE) => T {reg = reg, part = L}
307 | (T {reg, part = H},Size.BYTE) => T {reg = reg, part = H}
308 | (T {reg = EAX, ...}, Size.BYTE) => T {reg = EAX, part = L}
309 | (T {reg = EBX, ...}, Size.BYTE) => T {reg = EBX, part = L}
310 | (T {reg = ECX, ...}, Size.BYTE) => T {reg = ECX, part = L}
311 | (T {reg = EDX, ...}, Size.BYTE) => T {reg = EDX, part = L}
312 | (T {reg, part = X},Size.WORD) => T {reg = reg, part = X}
313 | (T {reg, ...}, Size.WORD) => T {reg = reg, part = X}
314 | _ => Error.bug "x86.Register.lowPartOf: register,lowsize"
317 structure FltRegister =
319 datatype t = T of int
326 else seq [str "%st", paren (Int.layout i)]
328 val toString = Layout.toString o layout
330 fun eq (T f1, T f2) = f1 = f2
332 fun push (T i) = T (i + 1)
333 fun pop (T i) = T (i - 1)
344 structure Immediate =
349 | LabelPlusWord of Label.t * WordX.t
351 = T of {immediate: u,
352 plist: PropertyList.t,
359 = fn Word w => WordX.layout w
360 | Label l => Label.layout l
361 | LabelPlusWord (l, w)
362 => paren (seq [Label.layout l, str "+", WordX.layout w])
364 = fn T {immediate, ...} => layoutU immediate
368 = fn (Word w1, Word w2) => WordX.equals (w1, w2)
369 | (Label l1, Label l2) => Label.equals(l1, l2)
370 | (LabelPlusWord (l1, w1), LabelPlusWord (l2,w2))
371 => Label.equals(l1,l2) andalso WordX.equals(w1, w2)
374 = fn (T {plist = plist1, ...},
375 T {plist = plist2, ...})
376 => PropertyList.equals(plist1, plist2)
382 = fn Word w => SOME w
384 | LabelPlusWord _ => NONE
386 = fn T {immediate, ...} => evalU immediate
389 val isZero = fn i => case eval i of SOME w => WordX.isZero w | _ => false
395 = fn Word w => WordX.hash w
396 | Label l => Label.hash l
397 | LabelPlusWord (l,w)
398 => Word.xorb(0wx5555 * (Label.hash l), WordX.hash w)
400 = fn T {hash, ...} => hash
404 val table: t HashSet.t ref = ref (HashSet.new {hash = hash})
409 val hash = hashU immediate
411 HashSet.lookupOrInsert
414 fn T {immediate = immediate', ...}
415 => eqU(immediate', immediate),
416 fn () => T {immediate = immediate,
418 plist = PropertyList.new ()})
422 = fn T {immediate, ...} => immediate
426 (!table, fn T {immediate, plist, ...} =>
428 PropertyList.clear plist;
431 | Label l => Label.clear l
432 | LabelPlusWord (l, _) => Label.clear l
436 val word = construct o Word
437 val label = construct o Label
438 val labelPlusWord = fn (l, w) =>
439 if WordSize.equals (WordX.size w, WordSize.word32)
440 then construct (LabelPlusWord (l, w))
441 else Error.bug "x86.Immediate.labelPlusWord"
443 val int' = fn (i, ws) => word (WordX.fromIntInf (IntInf.fromInt i, ws))
444 val int = fn i => int' (i, WordSize.word32)
447 val labelPlusInt = fn (l, i) =>
448 labelPlusWord (l, WordX.fromIntInf (IntInf.fromInt i, WordSize.word32))
451 = fn T {immediate = Label l, ...} => SOME l
458 = One | Two | Four | Eight
470 val fromBytes : int -> t
475 | _ => Error.bug "x86.Scale.fromBytes"
477 datatype z = datatype CType.t
495 fun eq(s1, s2) = s1 = s2
498 = fn One => WordX.fromIntInf (1, WordSize.word32)
499 | Two => WordX.fromIntInf (2, WordSize.word32)
500 | Four => WordX.fromIntInf (4, WordSize.word32)
501 | Eight => WordX.fromIntInf (8, WordSize.word32)
502 val toImmediate = Immediate.word o toWordX
507 datatype t = T of {disp: Immediate.t option,
508 base: Register.t option,
509 index: Register.t option,
510 scale: Scale.t option}
512 fun layout (T {disp, base, index, scale})
518 | SOME disp => Immediate.layout disp,
519 if (isSome base orelse isSome index)
524 => Register.layout base,
528 => seq [str ",", Register.layout index],
532 => seq [str ",", Scale.layout scale]])
536 fun eq(T {disp = disp, base = base, index = index, scale = scale},
537 T {disp = disp', base = base', index = index', scale = scale'})
538 = (case (disp, disp')
539 of (NONE, NONE) => true
540 | (SOME disp, SOME disp') => Immediate.eq(disp, disp')
541 | _ => false) andalso
543 index = index' andalso
551 val counter = Counter.new 0
552 datatype t = T of {counter: int,
555 fun layout (T {name, ...})
561 val toString = Layout.toString o layout
565 val class = T {counter = Counter.next counter,
572 = fn (T {counter = counter1, ...},
573 T {counter = counter2, ...})
574 => counter1 = counter2
576 = fn (T {counter = counter1, ...},
577 T {counter = counter2, ...})
578 => Int.compare (counter1, counter2)
580 = fn (T {counter, ...}) => counter
583 val Temp = new {name = "Temp"}
584 val StaticTemp = new {name = "StaticTemp"}
585 val CStack = new {name = "CStack"}
586 val Code = new {name = "Code"}
590 = U of {immBase: Immediate.t option,
592 immIndex: Immediate.t option,
600 plist: PropertyList.t,
608 = fn (NONE, NONE) => str "0"
609 | (SOME imm, NONE) => Immediate.layout imm
610 | (NONE, SOME mem) => layout mem
611 | (SOME imm, SOME mem) => seq [Immediate.layout imm,
615 and layoutImmMemScale
616 = fn (NONE, NONE, _) => str "0"
617 | (SOME imm, NONE, _) => Immediate.layout imm
618 | (NONE, SOME mem, scale) => seq [layout mem,
621 | (SOME imm, SOME mem, scale) => seq [Immediate.layout imm,
628 = fn U {immBase, memBase,
637 layoutImmMem (immBase, memBase),
639 layoutImmMemScale (immIndex, memIndex, scale),
642 = fn T {memloc, ...} => layoutU memloc
644 val toString = Layout.toString o layout
647 = fn (NONE, NONE) => 0wx55555555
648 | (SOME imm, NONE) => Immediate.hash imm
649 | (NONE, SOME mem) => hash mem
650 | (SOME imm, SOME mem)
651 => Word.xorb(0wx5555 * (Immediate.hash imm), hash mem)
653 = fn U {immBase, memBase, immIndex, memIndex, ...}
655 val hashBase = hashImmMem(immBase, memBase)
656 val hashIndex = hashImmMem(immIndex, memIndex)
658 Word.xorb(0wx5555 * hashBase, hashIndex)
661 = fn T {hash, ...} => hash
664 = fn (NONE, NONE) => true
665 | (SOME imm1, SOME imm2) => Immediate.eq(imm1, imm2)
668 = fn (NONE, NONE) => true
669 | (SOME mem1, SOME mem2) => eq(mem1, mem2)
672 = fn (U {immBase = immBase1, memBase = memBase1,
673 immIndex = immIndex1, memIndex = memIndex1,
674 scale = scale1, size = size1,
676 U {immBase = immBase2, memBase = memBase2,
677 immIndex = immIndex2, memIndex = memIndex2,
678 scale = scale2, size = size2,
680 => Class.eq(class1, class2) andalso
681 eqImm(immBase1, immBase2) andalso
682 eqMem(memBase1, memBase2) andalso
683 eqImm(immIndex1, immIndex2) andalso
684 eqMem(memIndex1, memIndex2) andalso
685 Scale.eq(scale1, scale2) andalso
686 Size.eq(size1, size2)
688 = fn (T {plist = plist1, ...},
689 T {plist = plist2, ...})
690 => PropertyList.equals(plist1, plist2)
694 | SOME m => m::(utilized m)
696 = fn U {memBase, memIndex, ...}
697 => (utilizedMem memBase) @ (utilizedMem memIndex)
699 = fn T {utilized, ...}
703 val counter = Counter.new 0
704 val table: t HashSet.t ref = ref (HashSet.new {hash = hash})
709 val hash = hashU memloc
711 HashSet.lookupOrInsert
714 fn T {memloc = memloc', ...} => eqU(memloc', memloc),
715 fn () => T {memloc = memloc,
717 plist = PropertyList.new (),
718 counter = Counter.next counter,
719 utilized = utilizedU memloc})
728 (!table, fn T {plist, ...} =>
730 PropertyList.clear plist
734 val rec mayAliasImmIndex
735 = fn ({immIndex = immIndex1, size = size1},
736 {immIndex = immIndex2, size = size2})
738 val size1 = IntInf.fromInt (Size.toBytes size1)
739 val size2 = IntInf.fromInt (Size.toBytes size2)
741 case (Immediate.eval (case immIndex1
742 of NONE => Immediate.zero
743 | SOME immIndex => immIndex),
744 Immediate.eval (case immIndex2
745 of NONE => Immediate.zero
746 | SOME immIndex => immIndex))
747 of (SOME pos1, SOME pos2)
749 val pos1 = WordX.toIntInfX pos1
750 val pos2 = WordX.toIntInfX pos2
753 then pos2 < (pos1 + size1)
754 else pos1 < (pos2 + size2)
756 handle Overflow => false)
760 = fn (U {immBase = SOME immBase1, memBase = NONE,
761 immIndex = immIndex1, memIndex = NONE,
763 U {immBase = SOME immBase2, memBase = NONE,
764 immIndex = immIndex2, memIndex = NONE,
766 => Immediate.eq(immBase1, immBase2)
768 mayAliasImmIndex ({immIndex = immIndex1,
770 {immIndex = immIndex2,
772 | (U {immBase = SOME immBase1, memBase = NONE,
773 immIndex = immIndex1, memIndex = SOME memIndex1,
775 U {immBase = SOME immBase2, memBase = NONE,
776 immIndex = immIndex2, memIndex = SOME memIndex2,
778 => not (Immediate.eq(immBase1, immBase2))
780 (not (eq(memIndex1, memIndex2))
782 mayAliasImmIndex ({immIndex = immIndex1,
784 {immIndex = immIndex2,
786 | (U {immBase = NONE, memBase = SOME memBase1,
787 immIndex = immIndex1, memIndex = NONE,
789 U {immBase = NONE, memBase = SOME memBase2,
790 immIndex = immIndex2, memIndex = NONE,
792 => not (eq(memBase1, memBase2))
794 mayAliasImmIndex ({immIndex = immIndex1,
796 {immIndex = immIndex2,
798 | (U {immBase = NONE, memBase = SOME memBase1,
799 immIndex = immIndex1, memIndex = SOME memIndex1,
801 U {immBase = NONE, memBase = SOME memBase2,
802 immIndex = immIndex2, memIndex = SOME memIndex2,
804 => not (eq(memBase1, memBase2))
806 not (eq(memIndex1, memIndex2))
808 mayAliasImmIndex ({immIndex = immIndex1,
810 {immIndex = immIndex2,
814 = fn (T {memloc = memloc1 as U {class = class1, ...}, ...},
815 T {memloc = memloc2 as U {class = class2, ...}, ...})
816 => Class.mayAlias(class1, class2) andalso
817 mayAliasU(memloc1, memloc2)
819 val rec mayAliasOrdImmIndex
820 = fn ({immIndex = immIndex1, size = size1},
821 {immIndex = immIndex2, size = size2})
823 val size1 = IntInf.fromInt (Size.toBytes size1)
824 val size2 = IntInf.fromInt (Size.toBytes size2)
826 case (Immediate.eval (case immIndex1
827 of NONE => Immediate.zero
828 | SOME immIndex => immIndex),
829 Immediate.eval (case immIndex2
830 of NONE => Immediate.zero
831 | SOME immIndex => immIndex))
832 of (SOME pos1, SOME pos2)
834 val pos1 = WordX.toIntInfX pos1
835 val pos2 = WordX.toIntInfX pos2
838 then if pos2 < (pos1 + size1)
841 else if pos1 < (pos2 + size2)
845 handle Overflow => NONE)
849 = fn (U {immBase = SOME immBase1, memBase = NONE,
850 immIndex = immIndex1, memIndex = NONE,
852 U {immBase = SOME immBase2, memBase = NONE,
853 immIndex = immIndex2, memIndex = NONE,
855 => if Immediate.eq(immBase1, immBase2)
856 then mayAliasOrdImmIndex ({immIndex = immIndex1,
858 {immIndex = immIndex2,
861 | (U {immBase = SOME immBase1, memBase = NONE,
862 immIndex = immIndex1, memIndex = SOME memIndex1,
864 U {immBase = SOME immBase2, memBase = NONE,
865 immIndex = immIndex2, memIndex = SOME memIndex2,
867 => if Immediate.eq(immBase1, immBase2)
868 then if not (eq(memIndex1, memIndex2))
870 else mayAliasOrdImmIndex ({immIndex = immIndex1,
872 {immIndex = immIndex2,
875 | (U {immBase = NONE, memBase = SOME memBase1,
876 immIndex = immIndex1, memIndex = NONE,
878 U {immBase = NONE, memBase = SOME memBase2,
879 immIndex = immIndex2, memIndex = NONE,
881 => if not (eq(memBase1, memBase2))
883 else mayAliasOrdImmIndex ({immIndex = immIndex1,
885 {immIndex = immIndex2,
887 | (U {immBase = NONE, memBase = SOME memBase1,
888 immIndex = immIndex1, memIndex = SOME memIndex1,
890 U {immBase = NONE, memBase = SOME memBase2,
891 immIndex = immIndex2, memIndex = SOME memIndex2,
893 => if (not (eq(memBase1, memBase2))
895 not (eq(memIndex1, memIndex2)))
897 else mayAliasOrdImmIndex ({immIndex = immIndex1,
899 {immIndex = immIndex2,
903 = fn (T {memloc = memloc1 as U {class = class1, ...}, ...},
904 T {memloc = memloc2 as U {class = class2, ...}, ...})
905 => if Class.mayAlias(class1, class2)
906 then mayAliasOrdU(memloc1, memloc2)
910 = fn (T {counter = counter1, ...},
911 T {counter = counter2, ...})
912 => Int.compare(counter1, counter2)
914 fun replaceMem replacer
916 | SOME mem => SOME (replace replacer mem)
917 and replaceU replacer
918 = fn memloc as T {memloc = U {immBase, memBase, immIndex, memIndex,
919 scale, size, class}, ...}
921 val memBase' = replaceMem replacer memBase
922 val memIndex' = replaceMem replacer memIndex
924 if eqMem(memBase, memBase') andalso eqMem(memIndex, memIndex')
926 else construct (U {immBase = immBase,
929 memIndex = memIndex',
937 val memloc' = replacer memloc
939 if eq(memloc', memloc)
940 then replaceU replacer memloc
944 val rec sizeU = fn U {size, ...} => size
945 and size = fn T {memloc, ...} => sizeU memloc
946 val rec classU = fn U {class, ...} => class
947 and class = fn T {memloc, ...} => classU memloc
949 fun scaleImmediate (imm, scale) =
950 case Immediate.destruct imm of
951 Immediate.Word w => Immediate.word (WordX.mul (w,
954 | _ => Error.bug "x86.MemLoc.scaleImmediate"
956 fun addImmediate (imm1, imm2) =
957 case (Immediate.destruct imm1, Immediate.destruct imm2) of
958 (Immediate.Word w1, Immediate.Word w2) => Immediate.word (WordX.add (w1, w2))
959 | _ => Error.bug "x86.MemLoc.scaleImmediate"
961 val imm = fn {base, index, scale, size, class}
962 => construct (U {immBase = SOME base,
964 immIndex = SOME (scaleImmediate (index, scale)),
969 val basic = fn {base, index, scale, size, class}
970 => construct (U {immBase = SOME base,
973 memIndex = SOME index,
977 val simple = fn {base, index, scale, size, class}
978 => construct (U {immBase = NONE,
980 immIndex = SOME (scaleImmediate (index, scale)),
986 val complex = fn {base, index, scale, size, class}
987 => construct (U {immBase = NONE,
990 memIndex = SOME index,
994 val shift = fn {origin, disp, scale, size}
996 val disp = scaleImmediate (disp, scale)
997 val U {immBase, memBase,
1002 construct (U {immBase = immBase,
1007 | SOME immIndex => SOME (addImmediate (immIndex, disp)),
1008 memIndex = memIndex,
1015 val num : int ref = ref 0
1017 val temp = fn {size} => (Int.inc num;
1018 imm {base = Immediate.zero,
1019 index = Immediate.int (!num),
1022 class = Class.Temp})
1026 * Static memory locations
1028 fun makeContents {base, size, class}
1030 index = Immediate.zero,
1036 datatype z = datatype CType.t
1037 datatype z = datatype Size.t
1039 fun cReturnTempContents sizes =
1042 (sizes, ([],0), fn (size, (contents, index)) =>
1043 ((cReturnTempContent (index, size))::contents,
1044 index + Size.toBytes size)))
1045 fun cReturnTempContent size =
1046 List.first(cReturnTempContents [size])
1047 val cReturnTempContents = fn size =>
1048 cReturnTempContents (
1050 Int s => let datatype z = datatype IntSize.t
1055 | I64 => [LONG, LONG]
1058 | Real s => let datatype z = datatype RealSize.t
1063 | Word s => let datatype z = datatype WordSize.t
1074 structure ClassElement =
1076 type t = MemLoc.Class.t
1077 val compare = MemLoc.Class.compare
1079 fun make f = fn (a, b) => f (MemLoc.Class.counter a, MemLoc.Class.counter b)
1081 val op < = make Int.<
1082 val op > = make Int.>
1083 val op >= = make Int.>=
1084 val op <= = make Int.<=
1086 val min = fn (a, b) => if Int.<(MemLoc.Class.counter a, MemLoc.Class.counter b)
1089 val max = fn (a, b) => min (b, a)
1090 val equals = MemLoc.Class.eq
1091 val layout = MemLoc.Class.layout
1094 structure ClassSet = OrderedUniqueSet(open ClassElement)
1097 structure MemLocElement =
1100 val equals = MemLoc.eq
1101 val layout = MemLoc.layout
1103 val compare = MemLoc.compare
1105 fun make f = fn (a, b) => f (MemLoc.counter a, MemLoc.counter b)
1107 val op < = make Int.<
1108 val op > = make Int.>
1109 val op >= = make Int.>=
1110 val op <= = make Int.<=
1112 val min = fn (a, b) => if Int.<(MemLoc.counter a, MemLoc.counter b)
1115 val max = fn (a, b) => min (b, a)
1116 val hash = MemLoc.hash
1120 structure MemLocSet = UnorderedSet(open MemLocElement)
1122 structure MemLocSet = OrderedUniqueSet(open MemLocElement)
1125 structure MemLocSet' = UnorderedSet(open MemLocElement)
1126 structure MemLocSet = HashedUniqueSet(structure Set = MemLocSet'
1127 structure Element = MemLocElement)
1134 = Register of Register.t
1135 | FltRegister of FltRegister.t
1136 | Immediate of Immediate.t
1138 | Address of Address.t
1139 | MemLoc of MemLoc.t
1142 = fn Register r => SOME (Register.size r)
1143 | FltRegister _ => SOME Size.EXTD
1144 | Immediate _ => NONE
1147 | MemLoc m => SOME (MemLoc.size m)
1153 fn Register r => Register.layout r
1154 | FltRegister f => FltRegister.layout f
1155 | Immediate i => seq [str "$", Immediate.layout i]
1156 | Label l => Label.layout l
1157 | Address a => Address.layout a
1158 | MemLoc m => MemLoc.layout m
1160 val toString = Layout.toString o layout
1163 = fn (Register r1, Register r2) => Register.eq(r1, r2)
1164 | (FltRegister f1, FltRegister f2) => FltRegister.eq(f1, f2)
1165 | (Immediate i1, Immediate i2) => Immediate.eq(i1, i2)
1166 | (Label l1, Label l2) => Label.equals(l1, l2)
1167 | (Address a1, Address a2) => Address.eq(a1, a2)
1168 | (MemLoc m1, MemLoc m2) => MemLoc.eq(m1, m2)
1172 = fn (Register r1, Register r2) => Register.eq(r1, r2)
1173 | (Register _, _) => false
1174 | (FltRegister f1, FltRegister f2) => FltRegister.eq(f1, f2)
1175 | (FltRegister _, _) => false
1176 | (Immediate i1, Immediate i2) => Immediate.eq(i1, i2)
1177 | (Immediate _, _) => false
1178 | (Label l1, Label l2) => Label.equals(l1, l2)
1179 | (Label _, _) => false
1180 | (Address _, Address _) => true
1181 | (Address _, MemLoc _) => true
1182 | (Address _, _) => false
1183 | (MemLoc m1, MemLoc m2) => MemLoc.mayAlias(m1, m2)
1184 | (MemLoc _, Address _) => true
1185 | (MemLoc _, _) => false
1187 val register = Register
1189 = fn Register x => SOME x
1191 val fltregister = FltRegister
1193 = fn FltRegister x => SOME x
1195 val immediate = Immediate
1197 = fn Immediate x => SOME x
1199 val immediate_word = immediate o Immediate.word
1200 val immediate_int' = immediate o Immediate.int'
1201 val immediate_int = immediate o Immediate.int
1202 val immediate_zero = immediate Immediate.zero
1203 val immediate_label = immediate o Immediate.label
1206 = fn Label x => SOME x
1208 val address = Address
1210 fun memloc_label l =
1211 memloc (MemLoc.makeContents { base = Immediate.label l,
1213 class = MemLoc.Class.Code })
1215 = fn MemLoc x => SOME x
1219 val cReturnTemp = Label.fromString "cReturnTemp"
1220 fun cReturnTempContent (index, size) =
1222 {base = Immediate.label cReturnTemp,
1223 index = Immediate.int index,
1226 class = MemLoc.Class.StaticTemp}
1227 datatype z = datatype CType.t
1228 datatype z = datatype Size.t
1230 fun cReturnTemps ty =
1231 if RepType.isUnit ty
1236 [{src = register r, dst = cReturnTempContent (0, s)}]
1237 val w8 = w (Register.al, BYTE)
1238 val w16 = w (Register.ax, WORD)
1239 val w32 = w (Register.eax, LONG)
1240 val w64 =[{src = register Register.eax,
1241 dst = cReturnTempContent (0, LONG)},
1242 {src = register Register.edx,
1243 dst = cReturnTempContent (4, LONG)}]
1245 case RepType.toCType ty of
1252 | Real32 => [{src = fltregister FltRegister.top,
1253 dst = cReturnTempContent (0, SNGL)}]
1254 | Real64 => [{src = fltregister FltRegister.top,
1255 dst = cReturnTempContent (0, DBLE)}]
1264 structure Instruction =
1266 (* Integer binary arithmetic(w/o mult & div)/logic instructions. *)
1268 = ADD (* signed/unsigned addition; p. 63 *)
1269 | ADC (* signed/unsigned addition with carry; p. 61 *)
1270 | SUB (* signed/unsigned subtraction; p. 713 *)
1271 | SBB (* signed/unsigned subtraction with borrow; p. 667 *)
1272 | AND (* logical and; p. 70 *)
1273 | OR (* logical or; p. 499 *)
1274 | XOR (* logical xor; p. 758 *)
1288 (* Integer multiplication and division. *)
1290 = IMUL (* signed multiplication (one operand form); p. 335 *)
1291 | MUL (* unsigned multiplication; p. 488 *)
1292 | IDIV (* signed division; p. 332 *)
1293 | DIV (* unsigned division; p. 188 *)
1294 | IMOD (* signed modulus; *)
1295 | MOD (* unsigned modulus; *)
1300 fn IMUL => str "imul"
1302 | IDIV => str "idiv"
1304 | IMOD => str "imod"
1308 (* Integer unary arithmetic/logic instructions. *)
1310 = INC (* increment by 1; p. 341 *)
1311 | DEC (* decrement by 1; p. 186 *)
1312 | NEG (* two's complement negation; p. 494 *)
1313 | NOT (* one's complement negation; p. 497 *)
1324 (* Integer shift/rotate arithmetic/logic instructions. *)
1326 = SAL (* shift arithmetic left; p. 662 *)
1327 | SHL (* shift logical left; p. 662 *)
1328 | SAR (* shift arithmetic right; p. 662 *)
1329 | SHR (* shift logical right; p. 662 *)
1330 | ROL (* rotate left; p. 631 *)
1331 | RCL (* rotate through carry left; p. 631 *)
1332 | ROR (* rotate right; p. 631 *)
1333 | RCR (* rotate through carry right; p. 631 *)
1348 (* Move with extention instructions. *)
1350 = MOVSX (* move with sign extention; p. 481 *)
1351 | MOVZX (* move with zero extention; p. 486 *)
1356 fn MOVSX => str "movs"
1357 | MOVZX => str "movz"
1360 (* Condition test field; p. 795 *)
1362 = O (* overflow *) | NO (* not overflow *)
1363 | B (* below *) | NB (* not below *)
1364 | AE (* above or equal *) | NAE (* not above or equal *)
1365 | C (* carry *) | NC (* not carry *)
1366 | E (* equal *) | NE (* not equal *)
1367 | Z (* zero *) | NZ (* not zero *)
1368 | BE (* below or equal *) | NBE (* not below or equal *)
1369 | A (* above *) | NA (* not above *)
1370 | S (* sign *) | NS (* not sign *)
1371 | P (* parity *) | NP (* not parity *)
1372 | PE (* parity even *) | PO (* parity odd *)
1374 | NL (* not less than *)
1375 | LE (* less than or equal *)
1376 | NLE (* not less than or equal *)
1377 | G (* greater than *)
1378 | NG (* not greater than *)
1379 | GE (* greater than or equal *)
1380 | NGE (* not greater than or equal *)
1382 val condition_negate
1383 = fn O => NO | NO => O
1385 | AE => NAE | NAE => AE
1389 | BE => NBE | NBE => BE
1393 | PE => PO | PO => PE
1395 | LE => NLE | NLE => LE
1397 | GE => NGE | NGE => GE
1399 val condition_reverse
1400 = fn B => A | NB => NA
1401 | AE => BE | NAE => NBE
1403 | BE => AE | NBE => NAE
1406 | LE => GE | NLE => NGE
1408 | GE => LE | NGE => NLE
1414 val rec condition_layout
1431 | c => seq [str "n", condition_layout (condition_negate c)]
1433 val condition_toString = Layout.toString o condition_layout
1435 (* Floating-point binary arithmetic instructions. *)
1437 = FADD (* addition; p. 205 *)
1438 | FSUB (* subtraction; p. 297 *)
1439 | FSUBR (* reversed subtraction; p. 301 *)
1440 | FMUL (* multiplication; p. 256 *)
1441 | FDIV (* division; p. 229 *)
1442 | FDIVR (* reversed division; p. 233 *)
1447 fn FADD => str "fadd"
1448 | FSUB => str "fsub"
1449 | FSUBR => str "fsubr"
1450 | FMUL => str "fmul"
1451 | FDIV => str "fdiv"
1452 | FDIVR => str "fdivr"
1462 (* Floating-point unary arithmetic instructions. *)
1464 = F2XM1 (* compute 2^x-1; p. 201 *)
1465 | FABS (* absolute value; p. 203 *)
1466 | FCHS (* change sign; p. 214 *)
1467 | FSQRT (* square root; p. 284 *)
1468 | FSIN (* sine; p. 280 *)
1469 | FCOS (* cosine; p. 226 *)
1470 | FRNDINT (* round to integer; p. 271 *)
1475 fn F2XM1 => str "f2xm1"
1476 | FABS => str "fabs"
1477 | FCHS => str "fchs"
1478 | FSQRT => str "fsqrt"
1479 | FSIN => str "fsin"
1480 | FCOS => str "fcos"
1481 | FRNDINT => str "frndint"
1484 (* Floating-point binary arithmetic stack instructions. *)
1486 = FSCALE (* scale; p. 278 *)
1487 | FPREM (* partial remainder; p. 263 *)
1488 | FPREM1 (* IEEE partial remainder; p. 266 *)
1493 fn FSCALE => str "fscale"
1494 | FPREM=> str "fprem"
1495 | FPREM1 => str "fprem1"
1498 (* floating point binary arithmetic stack pop instructions. *)
1500 = FYL2X (* compute y * log_2 x; p. 327 *)
1501 | FYL2XP1 (* compute y * log_2 (x + 1.0); p. 329 *)
1502 | FPATAN (* partial arctangent; p. 261 *)
1507 fn FYL2X => str "fyl2x"
1508 | FYL2XP1 => str "fyl2xp1"
1509 | FPATAN => str "fpatan"
1512 (* Floating-point constants. *)
1514 = ONE (* +1.0; p. 250 *)
1515 | ZERO (* +0.0; p. 250 *)
1516 | PI (* pi; p. 250 *)
1517 | L2E (* log_2 e; p. 250 *)
1518 | LN2 (* log_e 2; p. 250 *)
1519 | L2T (* log_2 10; p. 250 *)
1520 | LG2 (* log_10 2; p. 250 *)
1525 fn ONE => str "fld1"
1526 | ZERO => str "fldz"
1528 | L2E => str "fldl2e"
1529 | LN2 => str "fldln2"
1530 | L2T => str "fldl2t"
1531 | LG2 => str "fldlg2"
1534 (* x86 Instructions.
1535 * src operands are not changed by the instruction.
1536 * dst operands are changed by the instruction.
1543 (* Integer binary arithmetic(w/o mult & div)/logic instructions.
1545 | BinAL of {oper: binal,
1549 (* Psuedo integer multiplication and division.
1555 (* Integer multiplication and division.
1560 (* Integer signed/unsiged multiplication (two operand form); p. 335
1562 | IMUL2 of {src: Operand.t,
1565 (* Integer unary arithmetic/logic instructions.
1567 | UnAL of {oper: unal,
1570 (* Integer shift/rotate arithmetic/logic instructions.
1572 | SRAL of {oper: sral,
1576 (* Arithmetic compare.
1578 | CMP of {src1: Operand.t,
1583 | TEST of {src1: Operand.t,
1586 (* Set byte on condition.
1588 | SETcc of {condition: condition,
1593 | JMP of {target: Operand.t,
1595 (* Jump if condition is met.
1597 | Jcc of {condition: condition,
1601 | CALL of {target: Operand.t,
1603 (* Return from procedure.
1605 | RET of {src: Operand.t option}
1608 | MOV of {src: Operand.t,
1611 (* Conditional move.
1613 | CMOVcc of {condition: condition,
1617 (* Exchange register/memory with register.
1619 | XCHG of {src: Operand.t,
1622 (* Pseudo-push a value onto a stack.
1624 | pPUSH of {src: Operand.t,
1627 (* Pseudo-pop a value from a stack.
1629 | pPOP of {dst: Operand.t,
1632 (* Push a value onto the stack.
1634 | PUSH of {src: Operand.t,
1636 (* Pop a value from the stack.
1638 | POP of {dst: Operand.t,
1640 (* Convert X to 2X with sign extension.
1642 | CX of {size: Size.t}
1643 (* Move with extention.
1645 | MOVX of {oper: movx,
1650 (* Move with contraction.
1652 | XVOM of {src: Operand.t,
1656 (* Load effective address.
1658 | LEA of {src: Operand.t,
1661 (* Pseudo floating-point move.
1663 | pFMOV of {src: Operand.t,
1666 (* Pseudo floating-point move with extension.
1668 | pFMOVX of {src: Operand.t,
1672 (* Pseudo floating-point move with contraction.
1674 | pFXVOM of {src: Operand.t,
1678 (* Pseudo floating-point load constant.
1680 | pFLDC of {oper: fldc,
1683 (* Pseudo floating-point move from integer.
1685 | pFMOVFI of {src: Operand.t,
1689 (* Pseudo floating-point move to integer.
1691 | pFMOVTI of {src: Operand.t,
1695 (* Pseudo floating-point compare.
1697 | pFCOM of {src1: Operand.t,
1700 (* Pseudo floating-point unordered compare.
1702 | pFUCOM of {src1: Operand.t,
1705 (* Pseudo floating-point binary arithmetic instructions.
1707 | pFBinA of {oper: fbina,
1711 (* Pseudo floating-point unary arithmetic instructions.
1713 | pFUnA of {oper: funa,
1716 (* Pseudo floating-point partial tangent instruction.
1718 | pFPTAN of {dst: Operand.t,
1720 (* Pseudo floating-point binary arithmetic stack instructions.
1722 | pFBinAS of {oper: fbinas,
1726 (* Pseudo floating-point binary arithmetic stack pop instructions.
1728 | pFBinASP of {oper: fbinasp,
1732 (* Floating-point load real.
1734 | FLD of {src: Operand.t,
1736 (* Floating-point store real.
1738 | FST of {dst: Operand.t,
1741 (* Floating-point load integer.
1743 | FILD of {src: Operand.t,
1745 (* Floating-point store integer.
1747 | FIST of {dst: Operand.t,
1750 (* Floating-point exchange.
1752 | FXCH of {src: Operand.t}
1753 (* Floating-point load constant.
1755 | FLDC of {oper: fldc}
1756 (* Floating-point load control word.
1758 | FLDCW of {src: Operand.t}
1759 (* Floating-point store control word.
1761 | FSTCW of {dst: Operand.t,
1763 (* Floating-point store status word.
1765 | FSTSW of {dst: Operand.t,
1767 (* Floating-point compare.
1769 | FCOM of {src: Operand.t,
1773 (* Floating-point unordered compare.
1775 | FUCOM of {src: Operand.t,
1778 (* Floating-point binary arithmetic instructions.
1780 | FBinA of {oper: fbina,
1785 (* Floating-point unary arithmetic instructions.
1787 | FUnA of {oper: funa}
1788 (* Floating-point partial tangent instruction.
1791 (* Floating-point binary arithmetic stack instructions.
1793 | FBinAS of {oper: fbinas}
1794 (* Floating-point binary arithmetic stack pop instructions.
1796 | FBinASP of {oper: fbinasp}
1801 fun bin (oper, size, oper1, oper2)
1808 fun un (oper, size, oper1)
1818 | BinAL {oper, src, dst, size}
1819 => bin (binal_layout oper,
1823 | pMD {oper, src, dst, size}
1824 => bin (md_layout oper,
1828 | MD {oper, src, size}
1829 => un (md_layout oper,
1832 | IMUL2 {src, dst, size}
1837 | UnAL {oper, dst, size}
1838 => un (unal_layout oper,
1841 | SRAL {oper, count, dst, size}
1842 => bin (sral_layout oper,
1844 Operand.layout count,
1846 | CMP {src1, src2, size}
1849 Operand.layout src2,
1850 Operand.layout src1)
1851 | TEST {src1, src2, size}
1854 Operand.layout src2,
1855 Operand.layout src1)
1856 | SETcc {condition, dst, ...}
1858 condition_layout condition,
1861 | JMP {target, absolute}
1863 if absolute then str "*" else empty,
1864 Operand.layout target]
1865 | Jcc {condition, target}
1867 condition_layout condition,
1869 Operand.layout target]
1870 | CALL {target, absolute}
1871 => seq [str "call ",
1872 if absolute then str "*" else empty,
1873 Operand.layout target]
1878 | SOME src => seq [str " ", Operand.layout src]]
1879 | MOV {src, dst, size}
1884 | CMOVcc {condition, src, dst, size}
1886 condition_layout condition,
1892 | XCHG {src, dst, size}
1897 | pPUSH {src, base, size}
1898 => seq [str "ppush",
1901 Operand.layout base,
1904 | pPOP {dst, base, size}
1908 Operand.layout base,
1923 of Size.BYTE => str "cbtw"
1924 | Size.WORD => str "cwtd"
1925 | Size.LONG => str "cltd"
1926 | _ => Error.bug "x86.Instruction.layout: CX,unsupported conversion")
1927 | MOVX {oper, src, srcsize, dst, dstsize}
1928 => bin (movx_layout oper,
1929 seq [Size.layout srcsize,
1930 Size.layout dstsize],
1933 | XVOM {src, srcsize, dst, dstsize}
1935 seq [Size.layout srcsize,
1936 Size.layout dstsize],
1939 | LEA {src, dst, size}
1944 | pFMOV {src, dst, size}
1949 | pFMOVX {src, dst, srcsize, dstsize}
1950 => bin (str "fmovx",
1951 seq [Size.layout srcsize,
1952 Size.layout dstsize],
1955 | pFXVOM {src, dst, srcsize, dstsize}
1957 seq [Size.layout srcsize,
1958 Size.layout dstsize],
1961 | pFLDC {oper, dst, size}
1962 => un (fldc_layout oper,
1965 | pFMOVFI {src, dst, srcsize, dstsize}
1966 => bin (str "fmovfi",
1967 seq [Size.layout srcsize,
1968 Size.layout dstsize],
1971 | pFMOVTI {src, dst, srcsize, dstsize}
1972 => bin (str "fmovti",
1973 seq [Size.layout srcsize,
1974 Size.layout dstsize],
1977 | pFCOM {src1, src2, size}
1980 Operand.layout src1,
1981 Operand.layout src2)
1982 | pFUCOM {src1, src2, size}
1983 => bin (str "fucom",
1985 Operand.layout src1,
1986 Operand.layout src2)
1987 | pFBinA {oper, src, dst, size}
1988 => bin (fbina_layout oper,
1992 | pFUnA {oper, dst, size}
1993 => un (funa_layout oper,
1996 | pFPTAN {dst, size}
2000 | pFBinAS {oper, src, dst, size}
2001 => bin (fbinas_layout oper,
2005 | pFBinASP {oper, src, dst, size}
2006 => bin (fbinasp_layout oper,
2013 of Operand.FltRegister _ => empty
2014 | _ => Size.layout size,
2016 | FST {dst, size, pop}
2018 seq [if pop then str "p" else empty,
2020 of Operand.FltRegister _ => empty
2021 | _ => Size.layout size],
2027 | FIST {dst, size, pop}
2029 seq [if pop then str "p" else empty,
2033 => seq [str "fxch ",
2036 => seq [fldc_layout oper]
2038 => seq [str "fldcw ",
2040 | FSTCW {dst, check}
2041 => seq [if check then str "fstcw " else str "fnstcw ",
2043 | FSTSW {dst, check}
2044 => seq [if check then str "fstsw " else str "fnstsw ",
2046 | FCOM {src, size, pop, pop'}
2050 else seq [if pop then str "p" else empty,
2052 of Operand.FltRegister _
2054 | _ => Size.layout size,
2056 Operand.layout src]]
2057 | FUCOM {src, pop, pop'}
2058 => seq [str "fucom",
2061 else seq [if pop then str "p " else str " ",
2062 Operand.layout src]]
2063 | FBinA {oper, src, dst, size, pop}
2064 => seq [fbina_layout oper,
2066 of Operand.FltRegister _
2067 => seq [if pop then str "p " else str " ",
2072 => seq [Size.layout size,
2074 Operand.layout src]]
2076 => seq [funa_layout oper]
2078 => seq [str "fptan"]
2080 => seq [fbinas_layout oper]
2082 => seq [fbinasp_layout oper]
2084 val toString = Layout.toString o layout
2088 => {uses = [], defs = [], kills = []}
2090 => {uses = [], defs = [], kills = []}
2091 | BinAL {src, dst, ...}
2092 => {uses = [src, dst], defs = [dst], kills = []}
2093 | pMD {src, dst, ...}
2094 => {uses = [src, dst], defs = [dst], kills = []}
2095 | MD {oper, src, size}
2100 => (Register.T {reg = Register.EAX, part = Register.H},
2101 Register.T {reg = Register.EAX, part = Register.L})
2103 => (Register.T {reg = Register.EDX, part = Register.X},
2104 Register.T {reg = Register.EAX, part = Register.X})
2106 => (Register.T {reg = Register.EDX, part = Register.E},
2107 Register.T {reg = Register.EAX, part = Register.E})
2108 | _ => Error.bug "x86.Instruction.uses_defs: MD, size"
2110 if oper = IMUL orelse oper = MUL
2111 then {uses = [src, Operand.register lo],
2112 defs = [Operand.register hi, Operand.register lo],
2114 else {uses = [src, Operand.register hi, Operand.register lo],
2115 defs = [Operand.register hi, Operand.register lo],
2118 | IMUL2 {src, dst, ...}
2119 => {uses = [src, dst], defs = [dst], kills = []}
2121 => {uses = [dst], defs = [dst], kills = []}
2122 | SRAL {count, dst, size, ...}
2123 => if isSome (Operand.deMemloc count)
2128 => Register.T {reg = Register.ECX,
2131 => Register.T {reg = Register.ECX,
2134 => Register.T {reg = Register.ECX,
2136 | _ => Error.bug "x86.Instruction.uses_defs: SRAL, size"
2138 {uses = [count, dst, Operand.register reg],
2142 else {uses = [count, dst],
2145 | CMP {src1, src2, ...}
2146 => {uses = [src1, src2], defs = [], kills = []}
2147 | TEST {src1, src2, ...}
2148 => {uses = [src1, src2], defs = [], kills = []}
2150 => {uses = [], defs = [dst], kills = []}
2152 => {uses = [target], defs = [], kills = []}
2154 => {uses = [target], defs = [], kills = []}
2155 | CALL {target, ...}
2156 => {uses = [target], defs = [], kills = []}
2158 => {uses = case src of NONE => [] | SOME src => [src],
2161 | MOV {src, dst, ...}
2162 => {uses = [src], defs = [dst], kills = []}
2163 | CMOVcc {src, dst, ...}
2164 => {uses = [src], defs = [dst], kills = []}
2165 | XCHG {src, dst, ...}
2166 => {uses = [src,dst], defs = [src,dst], kills = []}
2167 | pPUSH {src, base, size, ...}
2168 => {uses = [src,base],
2171 of Operand.MemLoc base
2173 (MemLoc.simple {base = base,
2174 index = Immediate.zero,
2177 class = MemLoc.Class.CStack})]
2180 | pPOP {dst, base, size, ...}
2183 of Operand.MemLoc base
2185 (MemLoc.simple {base = base,
2186 index = Immediate.zero,
2189 class = MemLoc.Class.CStack})]
2194 => {uses = [src, Operand.register Register.esp],
2195 defs = [Operand.register Register.esp,
2196 Operand.address (Address.T {disp = NONE,
2197 base = SOME Register.esp,
2202 => {uses = [Operand.register Register.esp,
2203 Operand.address (Address.T {disp = NONE,
2204 base = SOME Register.esp,
2207 defs = [dst, Operand.register Register.esp],
2214 => (Register.T {reg = Register.EAX, part = Register.H},
2215 Register.T {reg = Register.EAX, part = Register.L})
2217 => (Register.T {reg = Register.EDX, part = Register.X},
2218 Register.T {reg = Register.EAX, part = Register.X})
2220 => (Register.T {reg = Register.EDX, part = Register.E},
2221 Register.T {reg = Register.EAX, part = Register.E})
2222 | _ => Error.bug "x86.Instruction.uses_defs: CX, size"
2224 {uses = [Operand.register lo],
2225 defs = [Operand.register hi, Operand.register lo],
2228 | MOVX {src, dst, ...}
2229 => {uses = [src], defs = [dst], kills = []}
2230 | XVOM {src, dst, ...}
2231 => {uses = [src], defs = [dst], kills = []}
2232 | LEA {src, dst, ...}
2233 => {uses = [src], defs = [dst], kills = []}
2234 | pFMOV {src, dst, ...}
2235 => {uses = [src], defs = [dst], kills = []}
2236 | pFMOVX {src, dst, ...}
2237 => {uses = [src], defs = [dst], kills = []}
2238 | pFXVOM {src, dst, ...}
2239 => {uses = [src], defs = [dst], kills = []}
2241 => {uses = [], defs = [dst], kills = []}
2242 | pFMOVFI {src, dst, ...}
2243 => {uses = [src], defs = [dst], kills = []}
2244 | pFMOVTI {src, dst, ...}
2245 => {uses = [src], defs = [dst], kills = []}
2246 | pFCOM {src1, src2, ...}
2247 => {uses = [src1, src2], defs = [], kills = []}
2248 | pFUCOM {src1, src2, ...}
2249 => {uses = [src1, src2], defs = [], kills = []}
2250 | pFBinA {src, dst, ...}
2251 => {uses = [src, dst], defs = [dst], kills = []}
2253 => {uses = [dst], defs = [dst], kills = []}
2255 => {uses = [dst], defs = [dst], kills = []}
2256 | pFBinAS {src, dst, ...}
2257 => {uses = [src, dst], defs = [dst], kills = []}
2258 | pFBinASP {src, dst, ...}
2259 => {uses = [src, dst],
2261 kills = if Operand.eq(src,dst)
2266 defs = [Operand.fltregister FltRegister.top],
2268 | FST {dst, pop, ...}
2269 => {uses = [Operand.fltregister FltRegister.top],
2272 then [Operand.fltregister FltRegister.top]
2276 defs = [Operand.fltregister FltRegister.top],
2278 | FIST {dst, pop, ...}
2279 => {uses = [Operand.fltregister FltRegister.top],
2282 then [Operand.fltregister FltRegister.top]
2285 => {uses = [src, Operand.fltregister FltRegister.top],
2286 defs = [src, Operand.fltregister FltRegister.top],
2290 defs = [Operand.fltregister FltRegister.top],
2293 => {uses = [src], defs = [], kills = []}
2295 => {uses = [], defs = [dst], kills = []}
2297 => {uses = [], defs = [dst], kills = []}
2298 | FCOM {src, pop, pop', ...}
2299 => {uses = [src, Operand.fltregister FltRegister.top],
2301 kills = if pop andalso pop'
2302 then [Operand.fltregister FltRegister.top, src]
2304 then [Operand.fltregister FltRegister.top]
2306 | FUCOM {src, pop, pop'}
2307 => {uses = [src, Operand.fltregister FltRegister.top],
2309 kills = if pop andalso pop'
2310 then [Operand.fltregister FltRegister.top, src]
2312 then [Operand.fltregister FltRegister.top]
2314 | FBinA {src, dst, pop, ...}
2315 => {uses = [src, dst],
2317 kills = if pop then [src] else []}
2319 => {uses = [Operand.fltregister FltRegister.top],
2320 defs = [Operand.fltregister FltRegister.top], kills = []}
2322 => {uses = [Operand.fltregister FltRegister.top],
2323 defs = [Operand.fltregister FltRegister.top], kills = []}
2325 => {uses = [Operand.fltregister FltRegister.top,
2326 Operand.fltregister FltRegister.one],
2327 defs = [Operand.fltregister FltRegister.top,
2328 Operand.fltregister FltRegister.one],
2331 => {uses = [Operand.fltregister FltRegister.top,
2332 Operand.fltregister FltRegister.one],
2333 defs = [Operand.fltregister FltRegister.one],
2334 kills = [Operand.fltregister FltRegister.top]}
2337 = fn pMD {dst, size, ...}
2342 => (Register.T {reg = Register.EAX, part = Register.H},
2343 Register.T {reg = Register.EAX, part = Register.L})
2345 => (Register.T {reg = Register.EDX, part = Register.X},
2346 Register.T {reg = Register.EAX, part = Register.X})
2348 => (Register.T {reg = Register.EDX, part = Register.E},
2349 Register.T {reg = Register.EAX, part = Register.E})
2350 | _ => Error.bug "x86.Instruction.hints: MD, size"
2352 val temp = MemLoc.temp {size = size}
2355 (case Operand.deMemloc dst
2356 of SOME memloc => (memloc, lo)
2357 | NONE => (temp, lo))]
2359 | MD {src, size, ...}
2364 => (Register.T {reg = Register.EAX, part = Register.H},
2365 Register.T {reg = Register.EAX, part = Register.L})
2367 => (Register.T {reg = Register.EDX, part = Register.X},
2368 Register.T {reg = Register.EAX, part = Register.X})
2370 => (Register.T {reg = Register.EDX, part = Register.E},
2371 Register.T {reg = Register.EAX, part = Register.E})
2372 | _ => Error.bug "x86.Instruction.hints: MD, size"
2374 val temp = MemLoc.temp {size = size}
2377 (case Operand.deMemloc src
2378 of SOME memloc => (memloc, lo)
2379 | NONE => (temp, lo))]
2381 | SRAL {count, size, ...}
2382 => (case Operand.deMemloc count
2388 => Register.T {reg = Register.ECX,
2391 => Register.T {reg = Register.ECX,
2394 => Register.T {reg = Register.ECX,
2396 | _ => Error.bug "x86.Instruction.hints: SRAL, size"
2402 => (case Operand.deMemloc base
2403 of SOME base => [(base,Register.esp)]
2406 => (case Operand.deMemloc base
2407 of SOME base => [(base,Register.esp)]
2411 val temp = MemLoc.temp {size = Size.LONG}
2413 [(temp,Register.esp)]
2417 val temp = MemLoc.temp {size = Size.LONG}
2419 [(temp,Register.esp)]
2425 => {srcs = NONE, dsts = NONE}
2427 => {srcs = NONE, dsts = NONE}
2428 | BinAL {src, dst, ...}
2429 => {srcs = SOME [src, dst], dsts = SOME [dst]}
2430 | pMD {src, dst, ...}
2431 => {srcs = SOME [src, dst], dsts = SOME [dst]}
2432 | MD {oper, src, size, ...}
2437 => (Register.T {reg = Register.EAX, part = Register.H},
2438 Register.T {reg = Register.EAX, part = Register.L})
2440 => (Register.T {reg = Register.EDX, part = Register.X},
2441 Register.T {reg = Register.EAX, part = Register.X})
2443 => (Register.T {reg = Register.EDX, part = Register.E},
2444 Register.T {reg = Register.EAX, part = Register.E})
2445 | _ => Error.bug "x86.Instruction.srcs_dsts: MD, size"
2447 if oper = IMUL orelse oper = MUL
2448 then {srcs = SOME [src,
2449 Operand.register lo],
2450 dsts = SOME [Operand.register hi,
2451 Operand.register lo]}
2452 else {srcs = SOME [src,
2453 Operand.register hi,
2454 Operand.register lo],
2455 dsts = SOME [Operand.register hi,
2456 Operand.register lo]}
2458 | IMUL2 {src, dst, ...}
2459 => {srcs = SOME [src, dst], dsts = SOME [dst]}
2461 => {srcs = SOME [dst], dsts = SOME [dst]}
2462 | SRAL {count, dst, size, ...}
2463 => if isSome (Operand.deMemloc count)
2468 => Register.T {reg = Register.ECX,
2471 => Register.T {reg = Register.ECX,
2474 => Register.T {reg = Register.ECX,
2476 | _ => Error.bug "x86.Instruction.srcs_dsts: SRAL, size"
2478 {srcs = SOME [count, dst, Operand.register reg],
2481 else {srcs = SOME [count, dst],
2483 | CMP {src1, src2, ...}
2484 => {srcs = SOME [src1, src2], dsts = NONE}
2485 | TEST {src1, src2, ...}
2486 => {srcs = SOME [src1, src2], dsts = NONE}
2488 => {srcs = NONE, dsts = SOME [dst]}
2490 => {srcs = SOME [target], dsts = NONE}
2492 => {srcs = SOME [target], dsts = NONE}
2493 | CALL {target, ...}
2494 => {srcs = SOME [target], dsts = NONE}
2496 => {srcs = case src of NONE => NONE | SOME src => SOME [src],
2498 | MOV {src, dst, ...}
2499 => {srcs = SOME [src], dsts = SOME [dst]}
2500 | CMOVcc {src, dst, ...}
2501 => {srcs = SOME [src], dsts = SOME [dst]}
2502 | XCHG {src, dst, ...}
2503 => {srcs = SOME [src,dst], dsts = SOME [src,dst]}
2504 | pPUSH {src, base, ...}
2505 => {srcs = SOME [src,base], dsts = SOME [base]}
2506 | pPOP {dst, base, ...}
2507 => {srcs = SOME [base], dsts = SOME [dst,base]}
2509 => {srcs = SOME [src, Operand.register Register.esp],
2510 dsts = SOME [Operand.register Register.esp]}
2512 => {srcs = SOME [Operand.register Register.esp],
2513 dsts = SOME [dst, Operand.register Register.esp]}
2519 => (Register.T {reg = Register.EAX, part = Register.H},
2520 Register.T {reg = Register.EAX, part = Register.L})
2522 => (Register.T {reg = Register.EDX, part = Register.X},
2523 Register.T {reg = Register.EAX, part = Register.X})
2525 => (Register.T {reg = Register.EDX, part = Register.E},
2526 Register.T {reg = Register.EAX, part = Register.E})
2527 | _ => Error.bug "x86.Instruction.srcs_dsts: CX, size"
2529 {srcs = SOME [Operand.register lo],
2530 dsts = SOME [Operand.register hi, Operand.register lo]}
2532 | MOVX {src, dst, ...}
2533 => {srcs = SOME [src], dsts = SOME [dst]}
2534 | XVOM {src, dst, ...}
2535 => {srcs = SOME [src], dsts = SOME [dst]}
2536 | LEA {src, dst, ...}
2537 => {srcs = SOME [src], dsts = SOME [dst]}
2538 | pFMOV {src, dst, ...}
2539 => {srcs = SOME [src], dsts = SOME [dst]}
2540 | pFMOVX {src, dst, ...}
2541 => {srcs = SOME [src], dsts = SOME [dst]}
2542 | pFXVOM {src, dst, ...}
2543 => {srcs = SOME [src], dsts = SOME [dst]}
2545 => {srcs = SOME [], dsts = SOME [dst]}
2546 | pFMOVFI {src, dst, ...}
2547 => {srcs = SOME [src], dsts = SOME [dst]}
2548 | pFMOVTI {src, dst, ...}
2549 => {srcs = SOME [src], dsts = SOME [dst]}
2550 | pFCOM {src1, src2, ...}
2551 => {srcs = SOME [src1, src2], dsts = NONE}
2552 | pFUCOM {src1, src2, ...}
2553 => {srcs = SOME [src1, src2], dsts = NONE}
2554 | pFBinA {src, dst, ...}
2555 => {srcs = SOME [src, dst], dsts = SOME [dst]}
2557 => {srcs = SOME [dst], dsts = SOME [dst]}
2559 => {srcs = SOME [dst], dsts = SOME [dst]}
2560 | pFBinAS {src, dst, ...}
2561 => {srcs = SOME [src, dst], dsts = SOME [dst]}
2562 | pFBinASP {src, dst, ...}
2563 => {srcs = SOME [src, dst],
2566 => {srcs = SOME [src],
2567 dsts = SOME [Operand.fltregister FltRegister.top]}
2569 => {srcs = SOME [Operand.fltregister FltRegister.top],
2572 => {srcs = SOME [src],
2573 dsts = SOME [Operand.fltregister FltRegister.top]}
2575 => {srcs = SOME [Operand.fltregister FltRegister.top],
2578 => {srcs = SOME [src, Operand.fltregister FltRegister.top],
2579 dsts = SOME [src, Operand.fltregister FltRegister.top]}
2582 dsts = SOME [Operand.fltregister FltRegister.top]}
2584 => {srcs = SOME [src], dsts = NONE}
2586 => {srcs = NONE, dsts = SOME [dst]}
2588 => {srcs = NONE, dsts = SOME [dst]}
2590 => {srcs = SOME [src, Operand.fltregister FltRegister.top],
2593 => {srcs = SOME [src, Operand.fltregister FltRegister.top],
2595 | FBinA {src, dst, ...}
2596 => {srcs = SOME [src, dst],
2599 => {srcs = SOME [Operand.fltregister FltRegister.top],
2600 dsts = SOME [Operand.fltregister FltRegister.top]}
2602 => {srcs = SOME [Operand.fltregister FltRegister.top],
2603 dsts = SOME [Operand.fltregister FltRegister.top]}
2605 => {srcs = SOME [Operand.fltregister FltRegister.top,
2606 Operand.fltregister FltRegister.one],
2607 dsts = SOME [Operand.fltregister FltRegister.top,
2608 Operand.fltregister FltRegister.one]}
2610 => {srcs = SOME [Operand.fltregister FltRegister.top,
2611 Operand.fltregister FltRegister.one],
2612 dsts = SOME [Operand.fltregister FltRegister.one]}
2614 fun replace replacer
2619 | BinAL {oper, src, dst, size}
2620 => BinAL {oper = oper,
2621 src = replacer {use = true, def = false} src,
2622 dst = replacer {use = true, def = true} dst,
2624 | pMD {oper, src, dst, size}
2625 => pMD {oper = oper,
2626 src = replacer {use = true, def = false} src,
2627 dst = replacer {use = true, def = true} dst,
2629 | MD {oper, src, size}
2631 src = replacer {use = true, def = false} src,
2633 | IMUL2 {src, dst, size}
2634 => IMUL2 {src = replacer {use = true, def = false} src,
2635 dst = replacer {use = true, def = true} dst,
2637 | UnAL {oper, dst, size}
2638 => UnAL {oper = oper,
2639 dst = replacer {use = true, def = true} dst,
2641 | SRAL {oper, count, dst, size}
2642 => SRAL {oper = oper,
2643 count = replacer {use = true, def = false} count,
2644 dst = replacer {use = true, def = true} dst,
2646 | CMP {src1, src2, size}
2647 => CMP {src1 = replacer {use = true, def = false} src1,
2648 src2 = replacer {use = true, def = false} src2,
2650 | TEST {src1, src2, size}
2651 => TEST {src1 = replacer {use = true, def = false} src1,
2652 src2 = replacer {use = true, def = false} src2,
2654 | SETcc {condition, dst, size}
2655 => SETcc {condition = condition,
2656 dst = replacer {use = false, def = true} dst,
2658 | JMP {target, absolute}
2659 => JMP {target = replacer {use = true, def = false} target,
2660 absolute = absolute}
2661 | Jcc {condition, target}
2662 => Jcc {condition = condition,
2663 target = replacer {use = true, def = false} target}
2664 | CALL {target, absolute}
2665 => CALL {target = replacer {use = true, def = false} target,
2666 absolute = absolute}
2669 of NONE => RET {src = NONE}
2671 => RET {src = SOME (replacer {use = true, def = false} src)})
2672 | MOV {src, dst, size}
2673 => MOV {src = replacer {use = true, def = false} src,
2674 dst = replacer {use = false, def = true} dst,
2676 | CMOVcc {condition, src, dst, size}
2677 => CMOVcc {condition = condition,
2678 src = replacer {use = true, def = false} src,
2679 dst = replacer {use = false, def = true} dst,
2681 | XCHG {src, dst, size}
2682 => XCHG {src = replacer {use = true, def = true} src,
2683 dst = replacer {use = true, def = true} dst,
2685 | pPUSH {src, base, size}
2686 => pPUSH {src = replacer {use = true, def = false} src,
2687 base = replacer {use = true, def = true} base,
2689 | pPOP {dst, base, size}
2690 => pPOP {dst = replacer {use = false, def = true} dst,
2691 base = replacer {use = true, def = true} base,
2694 => PUSH {src = replacer {use = true, def = false} src,
2697 => POP {dst = replacer {use = false, def = true} dst,
2701 | MOVX {oper, src, srcsize, dst, dstsize}
2702 => MOVX {oper = oper,
2703 src = replacer {use = true, def = false} src,
2705 dst = replacer {use = false, def = true} dst,
2707 | XVOM {src, srcsize, dst, dstsize}
2708 => XVOM {src = replacer {use = true, def = false} src,
2710 dst = replacer {use = false, def = true} dst,
2712 | LEA {src, dst, size}
2713 => LEA {src = replacer {use = true, def = false} src,
2714 dst = replacer {use = false, def = true} dst,
2716 | pFMOV {src, dst, size}
2717 => pFMOV {src = replacer {use = true, def = false} src,
2718 dst = replacer {use = false, def = true} dst,
2720 | pFMOVX {src, dst, srcsize, dstsize}
2721 => pFMOVX {src = replacer {use = true, def = false} src,
2722 dst = replacer {use = false, def = true} dst,
2723 srcsize = srcsize, dstsize = dstsize}
2724 | pFXVOM {src, dst, srcsize, dstsize}
2725 => pFXVOM {src = replacer {use = true, def = false} src,
2726 dst = replacer {use = false, def = true} dst,
2727 srcsize = srcsize, dstsize = dstsize}
2728 | pFLDC {oper, dst, size}
2729 => pFLDC {oper = oper,
2730 dst = replacer {use = false, def = true} dst,
2732 | pFMOVFI {src, srcsize, dst, dstsize}
2733 => pFMOVFI {src = replacer {use = true, def = false} src,
2735 dst = replacer {use = false, def = true} dst,
2737 | pFMOVTI {src, dst, srcsize, dstsize}
2738 => pFMOVTI {src = replacer {use = true, def = false} src,
2740 dst = replacer {use = false, def = true} dst,
2742 | pFCOM {src1, src2, size}
2743 => pFCOM {src1 = replacer {use = true, def = false} src1,
2744 src2 = replacer {use = true, def = false} src2,
2746 | pFUCOM {src1, src2, size}
2747 => pFUCOM {src1 = replacer {use = true, def = false} src1,
2748 src2 = replacer {use = true, def = false} src2,
2750 | pFBinA {oper, src, dst, size}
2751 => pFBinA {oper = oper,
2752 src = replacer {use = true, def = false} src,
2753 dst = replacer {use = true, def = true} dst,
2755 | pFUnA {oper, dst, size}
2756 => pFUnA {oper = oper,
2757 dst = replacer {use = true, def = true} dst,
2759 | pFPTAN {dst, size}
2760 => pFPTAN {dst = replacer {use = true, def = true} dst,
2762 | pFBinAS {oper, src, dst, size}
2763 => pFBinAS {oper = oper,
2764 src = replacer {use = true, def = false} src,
2765 dst = replacer {use = true, def = true} dst,
2767 | pFBinASP {oper, src, dst, size}
2768 => pFBinASP {oper = oper,
2769 src = replacer {use = true, def = true} src,
2770 dst = replacer {use = true, def = true} dst,
2773 => FLD {src = replacer {use = true, def = false} src,
2775 | FST {dst, size, pop}
2776 => FST {dst = replacer {use = false, def = true} dst,
2780 => FILD {src = replacer {use = true, def = false} src,
2782 | FIST {dst, size, pop}
2783 => FIST {dst = replacer {use = false, def = true} dst,
2787 => FXCH {src = replacer {use = true, def = true} src}
2789 => FLDC {oper = oper}
2791 => FLDCW {src = replacer {use = true, def = false} src}
2792 | FSTCW {dst, check}
2793 => FSTCW {dst = replacer {use = false, def = true} dst,
2795 | FSTSW {dst, check}
2796 => FSTSW {dst = replacer {use = false, def = true} dst,
2798 | FCOM {src, size, pop, pop'}
2799 => FCOM {src = replacer {use = true, def = false} src,
2803 | FUCOM {src, pop, pop'}
2804 => FUCOM {src = replacer {use = true, def = false} src,
2807 | FBinA {oper, src, dst, size, pop}
2808 => FBinA {oper = oper,
2809 src = replacer {use = true, def = false} src,
2810 dst = replacer {use = true, def = true} dst,
2814 => FUnA {oper = oper}
2818 => FBinAS {oper = oper}
2820 => FBinASP {oper = oper}
2822 val nop = fn () => NOP
2823 val hlt = fn () => HLT
2852 val pfmovfi = pFMOVFI
2853 val pfmovti = pFMOVTI
2859 val pfbinas = pFBinAS
2860 val pfbinasp = pFBinASP
2874 val fptan = fn () => FPTAN
2876 val fbinasp = FBinASP
2879 structure Directive =
2883 val num : int ref = ref 0
2884 datatype t = T of {num : int,
2885 plist: PropertyList.t}
2887 val id = T {num = !num,
2888 plist = PropertyList.new ()}
2893 val plist = fn T {plist, ...} => plist
2898 fn T {num, ...} => seq [str "RegAlloc", Int.layout num]
2900 val toString = Layout.toString o layout
2905 (* Assert that a memloc is in a register with properties;
2906 * used at top of basic blocks to establish passing convention.
2908 = Assume of {assumes: {register: Register.t,
2912 reserve: bool} list}
2913 | FltAssume of {assumes: {memloc: MemLoc.t,
2916 (* Ensure that memloc is in the register, possibly reserverd;
2917 * used at bot of basic blocks to establish passing convention,
2918 * also used before C calls to set-up %esp.
2920 | Cache of {caches: {register: Register.t,
2922 reserve: bool} list}
2923 | FltCache of {caches: {memloc: MemLoc.t} list}
2924 (* Reset the register allocation;
2925 * used at bot of basic blocks that fall-thru
2926 * to a block with multiple incoming paths of control.
2929 (* Ensure that memlocs are commited to memory;
2930 * used at bot of basic blocks to establish passing conventions
2932 | Force of {commit_memlocs: MemLocSet.t,
2933 commit_classes: ClassSet.t,
2934 remove_memlocs: MemLocSet.t,
2935 remove_classes: ClassSet.t,
2936 dead_memlocs: MemLocSet.t,
2937 dead_classes: ClassSet.t}
2939 (* Prepare for a C call; i.e., clear all caller save registers;
2940 * also, clear the flt. register stack;
2941 * used before C calls.
2944 (* Assert the return value;
2945 * used after C calls.
2947 | Return of {returns: {src: Operand.t, dst: MemLoc.t} list}
2949 (* Assert that the register is not free for the allocator;
2952 | Reserve of {registers: Register.t list}
2953 (* Assert that the register is free for the allocator;
2954 * used to free registers at fall-thru;
2955 * also used after C calls to free %esp.
2957 | Unreserve of {registers : Register.t list}
2958 (* Clear the floating point stack;
2959 * used at bot of basic blocks to establish passing convention
2962 (* Save the register allocation in id and
2963 * assert that live are used at this point;
2964 * used at bot of basic blocks to delay establishment
2965 * of passing convention to compensation block
2967 | SaveRegAlloc of {live: MemLocSet.t,
2969 (* Restore the register allocation from id and
2970 * remove anything tracked that is not live;
2971 * used at bot of basic blocks to delay establishment
2972 * of passing convention to compensation block
2974 | RestoreRegAlloc of {live: MemLocSet.t,
2978 = fn Assume {assumes}
2979 => concat["Assume: ",
2984 fn ({register, memloc, sync, reserve, ...}, s)
2985 => concat[MemLoc.toString memloc,
2986 " -> ", Register.toString register,
2987 if reserve then " (reserved)" else "",
2988 if sync then " (sync)" else "",
2991 | FltAssume {assumes}
2992 => concat["FltAssume: ",
2997 fn ({memloc, sync, ...}, s)
2998 => concat[MemLoc.toString memloc,
2999 if sync then " (sync)" else "",
3003 => concat["Cache: ",
3008 fn ({register, memloc, reserve}, s)
3009 => concat[MemLoc.toString memloc,
3010 " -> ", Register.toString register,
3011 if reserve then " (reserved)" else "",
3015 => concat["FltCache: ",
3021 => concat[MemLoc.toString memloc,
3024 | Force {commit_memlocs, commit_classes,
3025 remove_memlocs, remove_classes,
3026 dead_memlocs, dead_classes}
3027 => concat["Force: ",
3033 => concat[MemLoc.toString memloc, " ", s]),
3039 => concat[MemLoc.Class.toString class, " ", s]),
3045 => concat[MemLoc.toString memloc, " ", s]),
3051 => concat[MemLoc.Class.toString class, " ", s]),
3057 => concat[MemLoc.toString memloc, " ", s]),
3063 => concat[MemLoc.Class.toString class, " ", s])]
3069 => concat["Return: ", List.toString (fn {src,dst} =>
3070 concat ["(", Operand.toString src,
3071 ",", MemLoc.toString dst, ")"]) returns]
3072 | Reserve {registers}
3073 => concat["Reserve: ",
3075 List.fold(registers,
3078 => concat[Register.toString register, " ", s])]
3079 | Unreserve {registers}
3080 => concat["Unreserve: ",
3082 List.fold(registers,
3085 => concat[Register.toString register, " ", s])]
3087 => concat["ClearFlt"]
3088 | SaveRegAlloc {live, id}
3089 => concat["SaveRegAlloc: ",
3095 => concat[MemLoc.toString memloc, " ", s]),
3097 | RestoreRegAlloc {live, id}
3098 => concat["RestoreRegAlloc: ",
3104 => concat[MemLoc.toString memloc, " ", s]),
3106 val layout = Layout.str o toString
3109 = fn Assume {assumes}
3112 {uses = [], defs = [], kills = []},
3113 fn ({register, memloc, ...},
3115 => {uses = (Operand.memloc memloc)::uses,
3116 defs = (Operand.register register)::defs,
3118 | FltAssume {assumes}
3121 {uses = [], defs = [], kills = []},
3124 => {uses = (Operand.memloc memloc)::uses,
3130 {uses = [], defs = [], kills = []},
3131 fn ({register, memloc, ...},
3133 => {uses = (Operand.memloc memloc)::uses,
3134 defs = (Operand.register register)::defs,
3139 {uses = [], defs = [], kills = []},
3142 => {uses = (Operand.memloc memloc)::uses,
3145 | Reset => {uses = [], defs = [], kills = []}
3146 | Force {commit_memlocs, remove_memlocs, ...}
3147 => {uses = List.map(MemLocSet.toList commit_memlocs, Operand.memloc) @
3148 List.map(MemLocSet.toList remove_memlocs, Operand.memloc),
3151 | CCall => {uses = [], defs = [], kills = []}
3154 val uses = List.map(returns, fn {src, ...} => src)
3155 val defs = List.map(returns, fn {dst, ...} => Operand.memloc dst)
3157 {uses = uses, defs = defs, kills = []}
3159 | Reserve {...} => {uses = [], defs = [], kills = []}
3160 | Unreserve {...} => {uses = [], defs = [], kills = []}
3161 | ClearFlt => {uses = [], defs = [], kills = []}
3162 | SaveRegAlloc {live, ...}
3163 => {uses = List.map(MemLocSet.toList live, Operand.memloc),
3166 | RestoreRegAlloc {...}
3167 => {uses = [], defs = [], kills = []}
3173 fn {register, memloc, ...}
3174 => (memloc, register))
3177 fun replace replacer
3178 = fn Assume {assumes}
3182 fn {register, memloc, weight, sync, reserve}
3183 => {register = register,
3187 reserve = reserve})}
3188 | FltAssume {assumes}
3189 => FltAssume {assumes
3192 fn {memloc, weight, sync}
3193 => {memloc = memloc,
3200 fn {register, memloc, reserve}
3201 => {register = case replacer {use = false, def = true}
3202 (Operand.register register)
3203 of Operand.Register register => register
3204 | _ => Error.bug "x86.Directive.replace: Cache, register",
3205 memloc = case replacer {use = true, def = false}
3206 (Operand.memloc memloc)
3207 of Operand.MemLoc memloc => memloc
3208 | _ => Error.bug "x86.Directive.replace: Cache, memloc",
3209 reserve = reserve})}
3215 => {memloc = case replacer {use = true, def = false}
3216 (Operand.memloc memloc)
3217 of Operand.MemLoc memloc => memloc
3218 | _ => Error.bug "x86.Directive.replace: FltCache, memloc"})}
3220 | Force {commit_memlocs, commit_classes,
3221 remove_memlocs, remove_classes,
3222 dead_memlocs, dead_classes}
3223 => Force {commit_memlocs = MemLocSet.map
3227 {use = true, def = false}
3228 (Operand.memloc memloc)
3229 of Operand.MemLoc memloc => memloc
3230 | _ => Error.bug "x86.Directive.replace: Force, commit_memlocs"),
3231 commit_classes = commit_classes,
3232 remove_memlocs = MemLocSet.map
3236 {use = true, def = false}
3237 (Operand.memloc memloc)
3238 of Operand.MemLoc memloc => memloc
3239 | _ => Error.bug "x86.Directive.replace: Force, remove_memlocs"),
3240 remove_classes = remove_classes,
3241 dead_memlocs = MemLocSet.map
3245 {use = false, def = false}
3246 (Operand.memloc memloc)
3247 of Operand.MemLoc memloc => memloc
3248 | _ => Error.bug "x86.Directive.replace: Force, dead_memlocs"),
3249 dead_classes = dead_classes}
3252 => Return {returns = List.map
3253 (returns, fn {src,dst} =>
3256 case replacer {use = true, def = false}
3257 (Operand.memloc dst)
3258 of Operand.MemLoc memloc => memloc
3259 | _ => Error.bug "x86.Directive.replace: Return, returns"})}
3260 | Reserve {registers} => Reserve {registers = registers}
3261 | Unreserve {registers} => Unreserve {registers = registers}
3262 | ClearFlt => ClearFlt
3263 | SaveRegAlloc {live, id} => SaveRegAlloc {live = live, id = id}
3264 | RestoreRegAlloc {live, id} => RestoreRegAlloc {live = live, id = id}
3267 val fltassume = FltAssume
3269 val fltcache = FltCache
3270 val reset = fn () => Reset
3272 val ccall = fn () => CCall
3274 val reserve = Reserve
3275 val unreserve = Unreserve
3276 val saveregalloc = SaveRegAlloc
3277 val restoreregalloc = RestoreRegAlloc
3278 val clearflt = fn () => ClearFlt
3281 structure PseudoOp =
3287 | NonLazySymbolPointer
3288 | Balign of Immediate.t * Immediate.t option * Immediate.t option
3289 | P2align of Immediate.t * Immediate.t option * Immediate.t option
3290 | Space of Immediate.t * Immediate.t
3291 | Byte of Immediate.t list
3292 | Word of Immediate.t list
3293 | Long of Immediate.t list
3294 | String of string list
3297 | IndirectSymbol of Label.t
3299 | Comm of Label.t * Immediate.t * Immediate.t option
3305 fn Data => str ".data"
3306 | Text => str ".text"
3308 => str ".section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5"
3309 | NonLazySymbolPointer
3310 => str ".section __IMPORT,__pointers,non_lazy_symbol_pointers"
3311 | Balign (i,fill,max)
3312 => seq [str ".balign ",
3315 of (NONE, NONE) => empty
3316 | (SOME fill, NONE) => seq [str ",",
3317 Immediate.layout fill]
3318 | (NONE, SOME max) => seq [str ",,",
3319 Immediate.layout max]
3320 | (SOME fill, SOME max) => seq [str ",",
3321 Immediate.layout fill,
3323 Immediate.layout max]]
3324 | P2align (i,fill,max)
3325 => seq [str ".p2align ",
3328 of (NONE, NONE) => empty
3329 | (SOME fill, NONE) => seq [str ",",
3330 Immediate.layout fill]
3331 | (NONE, SOME max) => seq [str ",,",
3332 Immediate.layout max]
3333 | (SOME fill, SOME max) => seq [str ",",
3334 Immediate.layout fill,
3336 Immediate.layout max]]
3338 => seq [str ".space ",
3343 => seq [str ".byte ",
3344 seq (separate(List.map (bs, Immediate.layout), ","))]
3346 => seq [str ".word ",
3347 seq (separate(List.map (ws, Immediate.layout), ","))]
3349 => seq [str ".long ",
3350 seq (separate(List.map (ls, Immediate.layout), ","))]
3352 => seq [str ".ascii ",
3353 seq (separate(List.map
3355 fn s => seq [str "\"",
3356 str (String_escapeASM s),
3360 => seq [str ".globl ",
3363 => (* visibility directive depends on target object file *)
3365 val elf = seq [str ".hidden ", Label.layout l]
3366 val macho = seq [str ".private_extern ", Label.layout l]
3367 val coff = seq [str "/* ", str ".hidden ", Label.layout l, str " */"]
3369 case !Control.Target.os of
3370 MLton.Platform.OS.Cygwin => coff
3371 | MLton.Platform.OS.Darwin => macho
3372 | MLton.Platform.OS.MinGW => coff
3376 => seq [str ".indirect_symbol ",
3379 => seq [str ".local ",
3382 => seq [str ".comm ",
3386 case a of NONE => empty
3387 | SOME i => seq [str ",", Immediate.layout i]]
3389 val toString = Layout.toString o layout
3391 fun replace replacer
3395 => case Operand.deLabel
3396 (replacer {use = true, def = false}
3397 (Operand.label label))
3398 of SOME label => label
3399 | NONE => Error.bug "x86.PseudoOp.replace.replacerLabel"
3400 val replacerImmediate
3402 => case Operand.deImmediate
3403 (replacer {use = true, def = false}
3404 (Operand.immediate immediate))
3405 of SOME immediate => immediate
3406 | NONE => Error.bug "x86.PseudoOp.replace.replacerImmediate"
3410 | SymbolStub => SymbolStub
3411 | NonLazySymbolPointer => NonLazySymbolPointer
3412 | Balign (i,fill,max) => Balign (replacerImmediate i,
3413 Option.map(fill, replacerImmediate),
3414 Option.map(max, replacerImmediate))
3415 | P2align (i,fill,max) => P2align (replacerImmediate i,
3416 Option.map(fill, replacerImmediate),
3417 Option.map(max, replacerImmediate))
3418 | Space (i,f) => Space (replacerImmediate i, replacerImmediate f)
3419 | Byte bs => Byte (List.map(bs, replacerImmediate))
3420 | Word ws => Word (List.map(ws, replacerImmediate))
3421 | Long ls => Long (List.map(ls, replacerImmediate))
3422 | String ss => String ss
3423 | Global l => Global (replacerLabel l)
3424 | Hidden l => Hidden (replacerLabel l)
3425 | IndirectSymbol l => IndirectSymbol (replacerLabel l)
3426 | Local l => Local (replacerLabel l)
3427 | Comm (l, i, a) => Comm (replacerLabel l,
3428 replacerImmediate i,
3429 Option.map(a, replacerImmediate))
3432 val data = fn () => Data
3433 val text = fn () => Text
3434 val symbol_stub = fn () => SymbolStub
3435 val non_lazy_symbol_pointer = fn () => NonLazySymbolPointer
3437 val p2align = P2align
3445 val indirect_symbol = IndirectSymbol
3450 structure Assembly =
3454 | Directive of Directive.t
3455 | PseudoOp of PseudoOp.t
3457 | Instruction of Instruction.t
3463 fn Comment s => seq [str "/* ", str s, str " */"]
3464 | Directive d => seq [str "# directive: ", Directive.layout d]
3465 | PseudoOp p => seq [PseudoOp.layout p]
3466 | Label l => seq [Label.layout l, str ":"]
3467 | Instruction i => seq [str "\t", Instruction.layout i]
3469 val toString = Layout.toString o layout
3472 = fn Comment _ => {uses = [], defs = [], kills = []}
3473 | Directive d => Directive.uses_defs_kills d
3474 | PseudoOp _ => {uses = [], defs = [], kills = []}
3475 | Label _ => {uses = [], defs = [], kills = []}
3476 | Instruction i => Instruction.uses_defs_kills i
3479 = fn Comment _ => []
3480 | Directive d => Directive.hints d
3483 | Instruction i => Instruction.hints i
3485 fun replace replacer
3486 = fn Comment s => Comment s
3487 | Directive d => Directive (Directive.replace replacer d)
3488 | PseudoOp p => PseudoOp (PseudoOp.replace replacer p)
3489 | Label l => Label (case Operand.deLabel
3490 (replacer {use = false, def = true}
3493 | NONE => Error.bug "x86.Assembly.replace, Label")
3494 | Instruction i => Instruction (Instruction.replace replacer i)
3496 val comment = Comment
3497 val isComment = fn Comment _ => true | _ => false
3498 val directive = Directive
3499 val directive_assume = Directive o Directive.assume
3500 val directive_fltassume = Directive o Directive.fltassume
3501 val directive_cache = Directive o Directive.cache
3502 val directive_fltcache = Directive o Directive.fltcache
3503 val directive_reset = Directive o Directive.reset
3504 val directive_force = Directive o Directive.force
3505 val directive_ccall = Directive o Directive.ccall
3506 val directive_return = Directive o Directive.return
3507 val directive_reserve = Directive o Directive.reserve
3508 val directive_unreserve = Directive o Directive.unreserve
3509 val directive_saveregalloc = Directive o Directive.saveregalloc
3510 val directive_restoreregalloc = Directive o Directive.restoreregalloc
3511 val directive_clearflt = Directive o Directive.clearflt
3512 val pseudoop = PseudoOp
3513 val pseudoop_data = PseudoOp o PseudoOp.data
3514 val pseudoop_text = PseudoOp o PseudoOp.text
3515 val pseudoop_symbol_stub = PseudoOp o PseudoOp.symbol_stub
3516 val pseudoop_non_lazy_symbol_pointer =
3517 PseudoOp o PseudoOp.non_lazy_symbol_pointer
3518 val pseudoop_balign = PseudoOp o PseudoOp.balign
3519 val pseudoop_p2align = PseudoOp o PseudoOp.p2align
3520 val pseudoop_space = PseudoOp o PseudoOp.space
3521 val pseudoop_byte = PseudoOp o PseudoOp.byte
3522 val pseudoop_word = PseudoOp o PseudoOp.word
3523 val pseudoop_long = PseudoOp o PseudoOp.long
3524 val pseudoop_string = PseudoOp o PseudoOp.string
3525 val pseudoop_global = PseudoOp o PseudoOp.global
3526 val pseudoop_hidden = PseudoOp o PseudoOp.hidden
3527 val pseudoop_indirect_symbol = PseudoOp o PseudoOp.indirect_symbol
3528 val pseudoop_local = PseudoOp o PseudoOp.locall
3529 val pseudoop_comm = PseudoOp o PseudoOp.comm
3531 val instruction = Instruction
3532 val instruction_nop = Instruction o Instruction.nop
3533 val instruction_hlt = Instruction o Instruction.hlt
3534 val instruction_binal = Instruction o Instruction.binal
3535 val instruction_pmd = Instruction o Instruction.pmd
3536 val instruction_md = Instruction o Instruction.md
3537 val instruction_imul2 = Instruction o Instruction.imul2
3538 val instruction_unal = Instruction o Instruction.unal
3539 val instruction_sral = Instruction o Instruction.sral
3540 val instruction_cmp = Instruction o Instruction.cmp
3541 val instruction_test = Instruction o Instruction.test
3542 val instruction_setcc = Instruction o Instruction.setcc
3543 val instruction_jmp = Instruction o Instruction.jmp
3544 val instruction_jcc = Instruction o Instruction.jcc
3545 val instruction_call = Instruction o Instruction.call
3546 val instruction_ret = Instruction o Instruction.ret
3547 val instruction_mov = Instruction o Instruction.mov
3548 val instruction_cmovcc = Instruction o Instruction.cmovcc
3549 val instruction_xchg = Instruction o Instruction.xchg
3550 val instruction_ppush = Instruction o Instruction.ppush
3551 val instruction_ppop = Instruction o Instruction.ppop
3552 val instruction_push = Instruction o Instruction.push
3553 val instruction_pop = Instruction o Instruction.pop
3554 val instruction_cx = Instruction o Instruction.cx
3555 val instruction_movx = Instruction o Instruction.movx
3556 val instruction_xvom = Instruction o Instruction.xvom
3557 val instruction_lea = Instruction o Instruction.lea
3558 val instruction_pfmov = Instruction o Instruction.pfmov
3559 val instruction_pfmovx = Instruction o Instruction.pfmovx
3560 val instruction_pfxvom = Instruction o Instruction.pfxvom
3561 val instruction_pfldc = Instruction o Instruction.pfldc
3562 val instruction_pfmovfi = Instruction o Instruction.pfmovfi
3563 val instruction_pfmovti = Instruction o Instruction.pfmovti
3564 val instruction_pfcom = Instruction o Instruction.pfcom
3565 val instruction_pfucom = Instruction o Instruction.pfucom
3566 val instruction_pfbina = Instruction o Instruction.pfbina
3567 val instruction_pfuna = Instruction o Instruction.pfuna
3568 val instruction_pfptan = Instruction o Instruction.pfptan
3569 val instruction_pfbinas = Instruction o Instruction.pfbinas
3570 val instruction_pfbinasp = Instruction o Instruction.pfbinasp
3571 val instruction_fld = Instruction o Instruction.fld
3572 val instruction_fst = Instruction o Instruction.fst
3573 val instruction_fild = Instruction o Instruction.fild
3574 val instruction_fist = Instruction o Instruction.fist
3575 val instruction_fxch = Instruction o Instruction.fxch
3576 val instruction_fldc = Instruction o Instruction.fldc
3577 val instruction_fldcw = Instruction o Instruction.fldcw
3578 val instruction_fstcw = Instruction o Instruction.fstcw
3579 val instruction_fstsw = Instruction o Instruction.fstsw
3580 val instruction_fcom = Instruction o Instruction.fcom
3581 val instruction_fucom = Instruction o Instruction.fucom
3582 val instruction_fbina = Instruction o Instruction.fbina
3583 val instruction_funa = Instruction o Instruction.funa
3584 val instruction_fptan = Instruction o Instruction.fptan
3585 val instruction_fbinas = Instruction o Instruction.fbinas
3586 val instruction_fbinasp = Instruction o Instruction.fbinasp
3589 structure FrameInfo =
3591 datatype t = T of {size: int,
3592 frameLayoutsIndex: int}
3594 fun toString (T {size, frameLayoutsIndex})
3596 "size = ", Int.toString size, ", ",
3597 "frameLayoutsIndex = ",
3598 Int.toString frameLayoutsIndex, "}"]
3604 = Jump of {label: Label.t}
3605 | Func of {label: Label.t,
3607 | Cont of {label: Label.t,
3609 frameInfo: FrameInfo.t}
3610 | Handler of {frameInfo: FrameInfo.t,
3613 | CReturn of {dsts: (Operand.t * Size.t) vector,
3614 frameInfo: FrameInfo.t option,
3615 func: RepType.t CFunction.t,
3619 = fn Jump {label} => concat ["Jump::",
3620 Label.toString label]
3621 | Func {label, live}
3622 => concat ["Func::",
3623 Label.toString label,
3625 (concat o List.separate)
3629 fn (memloc, l) => (MemLoc.toString memloc)::l),
3632 | Cont {label, live, frameInfo}
3633 => concat ["Cont::",
3634 Label.toString label,
3636 (concat o List.separate)
3640 fn (memloc, l) => (MemLoc.toString memloc)::l),
3643 FrameInfo.toString frameInfo]
3644 | Handler {frameInfo, label, live}
3645 => concat ["Handler::",
3646 Label.toString label,
3648 (concat o List.separate)
3652 fn (memloc, l) => (MemLoc.toString memloc)::l),
3655 FrameInfo.toString frameInfo,
3657 | CReturn {dsts, frameInfo, func, label}
3658 => concat ["CReturn::",
3659 Label.toString label,
3661 Vector.toString (fn (dst,_) => Operand.toString dst) dsts,
3663 (CFunction.Target.toString o CFunction.target) func,
3667 | SOME f => FrameInfo.toString f]
3670 = fn CReturn {dsts, func, ...}
3673 List.map (Operand.cReturnTemps (CFunction.return func),
3674 fn {dst, ...} => Operand.memloc dst)
3677 defs = Vector.toListMap(dsts, fn (dst, _) => dst),
3680 | _ => {uses = [], defs = [], kills = []}
3683 = fn Jump {label, ...} => label
3684 | Func {label, ...} => label
3685 | Cont {label, ...} => label
3686 | Handler {label, ...} => label
3687 | CReturn {label, ...} => label
3690 = fn Func {live, ...} => live
3691 | Cont {live, ...} => live
3692 | Handler {live, ...} => live
3693 | _ => MemLocSet.empty
3697 val isFunc = fn Func _ => true | _ => false
3699 val handler = Handler
3700 val creturn = CReturn
3703 structure Transfer =
3707 datatype 'a t = Word of (WordX.t * 'a) list
3721 fun extract(cases,f)
3723 fun doit [(k,target)] = f (k, target)
3724 | doit _ = Error.bug "x86.Transfer.Cases.extract"
3727 of Word cases => doit cases
3732 fun doit [] = (0 : int)
3733 | doit ((_,target)::cases) = let
3742 of Word cases => doit cases
3745 fun keepAll(cases, p)
3747 fun doit l = List.keepAll(l, fn (k,target) => p (k,target))
3750 of Word cases => Word(doit cases)
3753 fun forall(cases, f)
3755 fun doit l = List.forall(l, fn (k, target) => f (k, target))
3758 of Word cases => doit cases
3761 fun foreach(cases, f)
3763 fun doit l = List.foreach(l, fn (k, target) => f (k, target))
3766 of Word cases => doit cases
3771 fun doit l = List.map(l, fn (k,target) => (k, f (k, target)))
3774 of Word cases => Word(doit cases)
3777 fun mapToList(cases, f)
3779 fun doit l = List.map(l, fn (k,target) => f (k, target))
3782 of Word cases => doit cases
3787 = Goto of {target: Label.t}
3788 | Iff of {condition: Instruction.condition,
3791 | Switch of {test: Operand.t,
3792 cases: Label.t Cases.t,
3794 | Tail of {target: Label.t,
3796 | NonTail of {target: Label.t,
3799 handler: Label.t option,
3801 | Return of {live: MemLocSet.t}
3802 | Raise of {live: MemLocSet.t}
3803 | CCall of {args: (Operand.t * Size.t) list,
3804 frameInfo: FrameInfo.t option,
3805 func: RepType.t CFunction.t,
3806 return: Label.t option}
3811 Label.toString target]
3812 | Iff {condition, truee, falsee}
3814 Instruction.condition_toString condition,
3816 Label.toString truee,
3818 Label.toString falsee]
3819 | Switch {test, cases, default}
3820 => (concat["SWITCH ",
3821 Operand.toString test]) ^
3822 (concat o Cases.mapToList)
3824 fn (w, target) => concat[" (",
3827 Label.toString target,
3830 Label.toString default])
3831 | Tail {target, live}
3833 Label.toString target,
3835 (concat o List.separate)
3839 fn (memloc, l) => (MemLoc.toString memloc)::l),
3842 | NonTail {target, live, return, handler, size}
3843 => concat ["NONTAIL ",
3844 Label.toString target,
3846 (concat o List.separate)
3850 fn (memloc, l) => (MemLoc.toString memloc)::l),
3853 Label.toString return,
3858 of SOME handler => Label.toString handler
3862 => concat ["RETURN",
3864 (concat o List.separate)
3868 fn (memloc, l) => (MemLoc.toString memloc)::l),
3874 (concat o List.separate)
3878 fn (memloc, l) => (MemLoc.toString memloc)::l),
3881 | CCall {args, func, return, ...}
3882 => concat ["CCALL ",
3883 (CFunction.Convention.toString o CFunction.convention) func,
3885 (CFunction.Target.toString o CFunction.target) func,
3887 (concat o List.separate)
3888 (List.map(args, fn (oper,_) => Operand.toString oper),
3891 Option.toString Label.toString return,
3895 = fn Switch {test, ...}
3896 => {uses = [test], defs = [], kills = []}
3897 | CCall {args, func, ...}
3900 List.map (Operand.cReturnTemps (CFunction.return func),
3901 fn {dst, ...} => Operand.memloc dst)
3903 {uses = List.map(args, fn (oper,_) => oper),
3904 defs = defs, kills = []}
3906 | _ => {uses = [], defs = [], kills = []}
3909 = fn Goto {target} => [target]
3910 | Iff {truee,falsee,...} => [truee,falsee]
3911 | Switch {cases,default,...}
3912 => default::(Cases.mapToList
3914 fn (_,target) => target))
3915 | NonTail {return,handler,...} => return::(case handler
3917 | SOME handler => [handler])
3918 | CCall {return, ...}
3925 = fn Tail {live,...} => live
3926 | NonTail {live,...} => live
3927 | Return {live,...} => live
3928 | Raise {live,...} => live
3929 | _ => MemLocSet.empty
3931 fun replace replacer
3932 = fn Switch {test, cases, default}
3933 => Switch {test = replacer {use = true, def = false} test,
3936 | CCall {args, frameInfo, func, return}
3937 => CCall {args = List.map(args,
3938 fn (oper,size) => (replacer {use = true,
3942 frameInfo = frameInfo,
3945 | transfer => transfer
3951 val nontail = NonTail
3957 structure ProfileLabel =
3963 val label = Label.fromString (toString pl)
3965 [Assembly.pseudoop_global label,
3966 Assembly.pseudoop_hidden label,
3967 Assembly.label label]
3969 fun toAssemblyOpt pl =
3972 | SOME pl => toAssembly pl
3977 datatype t' = T' of {entry: Entry.t option,
3978 profileLabel: ProfileLabel.t option,
3979 statements: Assembly.t list,
3980 transfer: Transfer.t option}
3981 fun mkBlock' {entry, statements, transfer} =
3983 profileLabel = NONE,
3984 statements = statements,
3985 transfer = transfer}
3986 fun mkProfileBlock' {profileLabel} =
3988 profileLabel = SOME profileLabel,
3992 datatype t = T of {entry: Entry.t,
3993 profileLabel: ProfileLabel.t option,
3994 statements: Assembly.t list,
3995 transfer: Transfer.t}
3997 fun printBlock (T {entry, profileLabel, statements, transfer, ...})
3998 = (print (Entry.toString entry);
4001 (profileLabel, fn profileLabel =>
4002 (print (ProfileLabel.toString profileLabel);
4005 (statements, fn asm =>
4006 (print (Assembly.toString asm);
4008 print (Transfer.toString transfer);
4011 fun printBlock' (T' {entry, profileLabel, statements, transfer, ...})
4012 = (print (if isSome entry
4013 then Entry.toString (valOf entry)
4017 (profileLabel, fn profileLabel =>
4018 (print (ProfileLabel.toString profileLabel);
4021 (statements, fn asm =>
4022 (print (Assembly.toString asm);
4024 print (if isSome transfer
4025 then Transfer.toString (valOf transfer)
4029 val compress': t' list -> t' list =
4033 fn (b' as T' {entry, profileLabel, statements, transfer}, ac) =>
4038 [] => Error.bug "x86.Block.compress': dangling transfer"
4041 val T' {entry = entry2,
4042 profileLabel = profileLabel2,
4043 statements = statements2,
4044 transfer = transfer2} = b2'
4048 Error.bug "x86.Block.compress': mismatched transfer"
4052 case (profileLabel, statements) of
4054 (profileLabel2, statements2)
4058 @ (ProfileLabel.toAssemblyOpt
4065 transfer = transfer2} :: ac
4069 val compress: t' list -> t list =
4072 (compress' l, fn T' {entry, profileLabel, statements, transfer} =>
4073 case (entry, transfer) of
4076 profileLabel = profileLabel,
4077 statements = statements,
4079 | _ => Error.bug "x86.Block.compress")
4084 datatype t = T of {data: Assembly.t list,
4085 blocks: Block.t list}