Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /MLRISC/trunk/amd64/staged-allocation/amd64-svid.sml
ViewVC logotype

Annotation of /MLRISC/trunk/amd64/staged-allocation/amd64-svid.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2992 - (view) (download)

1 : mrainey 2619 (* amd64-svid-fn.sml
2 :     *
3 :     * C calling conventions using staged allocation.
4 : mrainey 2986 *
5 : mrainey 2619 *)
6 :    
7 :     functor AMD64SVID (
8 :     structure T : MLTREE
9 :     val frameAlign : int
10 :     ) : C_CALL =
11 :     struct
12 :    
13 :     structure T = T
14 :     structure C = AMD64Cells
15 :     structure CB = CellsBasis
16 :     structure CTy = CTypes
17 :    
18 :     val wordTy = 64
19 :     val mem = T.Region.memory
20 :     fun gpr r = T.GPR (T.REG (wordTy, r))
21 :     fun fpr (ty, f) = T.FPR (T.FREG (ty, f))
22 :    
23 : mrainey 2986 (* general-purpose registers *)
24 : mrainey 2619 val [rax, rbx, rdi, rsi, rdx, rcx, r8, r9, r10, r11, r12, r13, r14, r15] =
25 : mrainey 2992 List.map (fn r => (wordTy, r))
26 : mrainey 2619 ([C.rax, C.rbx, C.rdi, C.rsi, C.rdx, C.rcx] @
27 :     C.Regs CB.GP {from=8, to=15, step=1})
28 : mrainey 2986 (* floating-point registers (SSE2) *)
29 : mrainey 2619 val sseFRegs as
30 :     [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10,
31 :     xmm11, xmm12, xmm13, xmm14, xmm15] =
32 : mrainey 2992 List.map (fn r => (64, r)) (C.Regs CB.FP {from=0, to=15, step=1})
33 :     val calleeSaveRegs = List.map #2 [rbx, r12, r13, r14, r15]
34 :     val callerSaveRegs = List.map #2 [rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11]
35 : mrainey 2619 val callerSaveFRegs = sseFRegs
36 :     val calleeSaveFRegs = []
37 : mrainey 2986 val spReg = T.REG (wordTy, C.rsp)
38 : mrainey 2619
39 :     datatype location_kind = K_GPR | K_FPR | K_MEM
40 : mrainey 2986 structure S = StagedAllocationFn (
41 : mrainey 2619 structure T = T
42 : mrainey 2986 structure TargetLang = struct
43 :     datatype location_kind = datatype location_kind
44 :     end
45 :     val memSize = 8
46 :     )
47 : mrainey 2619
48 : mrainey 2986 structure CCall = CCallStkFn (
49 :     structure C = AMD64Cells
50 :     structure T = T
51 :     val spReg = spReg
52 :     val wordTy = wordTy
53 :     )
54 :     datatype c_arg = datatype CCall.c_arg
55 :     datatype arg_location = datatype CCall.arg_location
56 :    
57 : mrainey 2619 (* This structure contains the automaton used in staged allocation. *)
58 :     structure SVIDConventions =
59 :     struct
60 :    
61 :     type reg = (int * CellsBasis.cell)
62 :     type slot = S.slot
63 :     type location_info = S.location_info
64 :     type automaton = {s0 : S.str, step : S.stepper_fn}
65 :    
66 :     val gprParams = [rdi, rsi, rdx, rcx, r8, r9]
67 :     val fprParams = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7]
68 :    
69 :     val maxAlign = 16
70 :    
71 :     (* parameter-passing conventions *)
72 :     fun call () = let
73 :     val cStack = S.freshCounter ()
74 :     val cInt = S.freshCounter ()
75 :     val cFloat = S.freshCounter ()
76 :     in
77 :     ( cStack, [cStack, cInt, cFloat],
78 :     [ S.CHOICE [
79 : mrainey 2986 (* pass in general-purpose register *)
80 : mrainey 2619 (fn (w, k, str) => k = K_GPR, S.SEQ [
81 :     S.WIDEN (fn w => Int.max (wordTy, w)),
82 :     S.BITCOUNTER cInt,
83 :     S.REGS_BY_BITS (cInt, gprParams)] ),
84 : mrainey 2986 (* pass in floating point register *)
85 : mrainey 2619 (fn (w, k, str) => k = K_FPR, S.SEQ [
86 :     S.WIDEN (fn w => Int.max (64, w)),
87 :     S.BITCOUNTER cFloat,
88 :     S.REGS_BY_BITS (cFloat, fprParams) ]),
89 : mrainey 2986 (* pass on the stack *)
90 : mrainey 2619 (fn (w, k, str) => k = K_MEM,
91 :     S.OVERFLOW {counter=cStack, blockDirection=S.UP, maxAlign=maxAlign}) ],
92 :     S.OVERFLOW {counter=cStack, blockDirection=S.UP, maxAlign=maxAlign}
93 :     ] )
94 :     end (* call *)
95 :    
96 :     val gprRets = [rax, rdx]
97 :     val fprRets = [xmm0, xmm1]
98 :    
99 :     (* value-returning conventions *)
100 :     fun return () = let
101 :     val (cFloat, ssFloat) = S.useRegs fprRets
102 :     val (cInt, ssGpr) = S.useRegs gprRets
103 :     in
104 :     ( [cFloat, cInt],
105 :     [ S.CHOICE [
106 : mrainey 2986 (* return in general-purpose register *)
107 : mrainey 2619 (fn (w, k, str) => k = K_GPR,
108 :     S.SEQ [S.WIDEN (fn w => Int.max (wordTy, w)), ssGpr]),
109 : mrainey 2986 (* return in floating-point register *)
110 : mrainey 2619 (fn (w, k, str) => k = K_FPR,
111 :     S.SEQ [S.WIDEN (fn w => Int.max (64, w)), ssFloat]),
112 : mrainey 2986 (* return in a memory location *)
113 : mrainey 2619 (fn (w, k, str) => k = K_MEM,
114 :     (* FIXME! *)
115 :     ssGpr) ]
116 :     ] )
117 :     end (* return *)
118 :    
119 : mrainey 2986 (* generate the finite automaton for the target machine's calling conventions *)
120 : mrainey 2619 fun genAutomaton () = let
121 :     val (stackCounter, callCounters, callStates) = call ()
122 :     val (retCounters, retStates) = return ()
123 :     fun finish str = S.find (str, stackCounter)
124 :     in
125 :     {call = {cS0=S.init callCounters,
126 :     cStep=S.mkStep callStates, finish=finish},
127 :     ret = {rS0=S.init retCounters, rStep=S.mkStep retStates}}
128 : mrainey 2986 end
129 : mrainey 2619
130 :     end (* SVIDConventions *)
131 :    
132 :     fun kindOfCTy (CTy.C_float | CTy.C_double | CTy.C_long_double) = K_FPR
133 :     | kindOfCTy (CTy.C_STRUCT _ | CTy.C_UNION _ | CTy.C_ARRAY _) = K_MEM
134 :     | kindOfCTy _ = K_GPR
135 :     fun szToLoc cty {sz, align} = (sz * 8, kindOfCTy cty, align)
136 :     fun cTyToLoc cty = szToLoc cty (CSizes.sizeOfTy cty)
137 : mrainey 2986 (* convert a C argument to a location for staged allocation *)
138 : mrainey 2619 fun argLoc _ (w, S.REG (_, r), K_GPR) = C_GPR (w, r)
139 :     | argLoc _ (w, S.REG (_, r), K_FPR) = C_FPR (w, r)
140 : mrainey 2992 | argLoc argOffset (w, S.BLOCK_OFFSET offB, K_GPR) = C_STK (w, T.I.fromInt (wordTy, offB+argOffset))
141 :     | argLoc argOffset (w, S.BLOCK_OFFSET offB, K_FPR) = C_STK (w, T.I.fromInt (wordTy, offB+argOffset))
142 :     | argLoc argOffset (w, S.NARROW (loc, w', k), _) = argLoc argOffset (w', loc, k)
143 : mrainey 2619 | argLoc _ (w, S.COMBINE _, _) = raise Fail "impossible"
144 :    
145 :     fun layout {conv, retTy, paramTys} = let
146 : mrainey 2926 val {call={cS0, cStep, finish}, ret={rS0, rStep}} = SVIDConventions.genAutomaton ()
147 : mrainey 2986 (* set up the return value of the call *)
148 :     fun setupReturn () = argLoc 0 (#2 (rStep (rS0, cTyToLoc retTy)))
149 : mrainey 2619 val (resLoc, structRetLoc, argOffset) = (case retTy
150 :     of CTy.C_void => (NONE, NONE, 0)
151 :     | CTy.C_UNION tys => raise Fail "todo"
152 :     | CTy.C_STRUCT tys => let
153 :     val {sz, align} = CSizes.sizeOfStruct tys
154 :     in
155 : mrainey 2986 (SOME (setupReturn ()), SOME {szb=sz, align=align}, 8)
156 : mrainey 2619 end
157 : mrainey 2986 | _ => (SOME (setupReturn ()), NONE, 0)
158 : mrainey 2888 (* end case *))
159 : mrainey 2986 (* set up the arguments for the call *)
160 :     fun setupArgs (str, [], locs) = (finish(str), List.rev locs)
161 :     | setupArgs (str, pTy :: pTys, locs) = let
162 : mrainey 2619 val (str', cLoc) = cStep (str, cTyToLoc pTy)
163 :     in
164 : mrainey 2986 setupArgs (str', pTys, argLoc argOffset cLoc :: locs)
165 :     end
166 :     val (frameSz, argLocs) = setupArgs (cS0, paramTys, [])
167 : mrainey 2926 val argMem = {szb=CSizes.alignAddr (frameSz, frameAlign), align=frameAlign}
168 : mrainey 2986 in
169 :     {argLocs=argLocs, argMem=argMem, resLoc=resLoc, structRetLoc=structRetLoc}
170 :     end
171 : mrainey 2619
172 : mrainey 2888 fun genCall {name, proto, paramAlloc, structRet, saveRestoreDedicated, callComment, args} = let
173 : mrainey 2986 val {argLocs, argMem, resLoc, structRetLoc} = layout(proto)
174 : mrainey 2619 val argAlloc = if ((#szb argMem = 0) orelse paramAlloc argMem)
175 :     then []
176 :     else [T.MV (wordTy, C.rsp, T.SUB (wordTy, spReg,
177 :     T.LI (T.I.fromInt (wordTy, #szb argMem))))]
178 : mrainey 2986 val (copyArgs, gprUses, fprUses) = CCall.copyArgs(args, argLocs)
179 : mrainey 2926 (* the defined registers of the call depend on the calling convention *)
180 : mrainey 2888 val defs = (case #conv proto
181 : mrainey 2926 of "ccall" => List.map gpr callerSaveRegs @ List.map fpr callerSaveFRegs
182 : mrainey 2888 | "ccall-bare" => []
183 :     | conv => raise Fail (concat [
184 :     "unknown calling convention \"", String.toString conv, "\""
185 :     ])
186 :     (* end case *))
187 : mrainey 2926 val uses = List.map gpr gprUses @ List.map fpr fprUses
188 :     val callStm = T.CALL {funct=name, targets=[], defs=defs, uses=uses, region=mem, pops=0}
189 : mrainey 2986 val (resultRegs, copyResult) = CCall.returnVals(resLoc)
190 : mrainey 2619 val callSeq = argAlloc @ copyArgs @ [callStm] @ copyResult
191 :     in
192 :     {callseq=callSeq, result=resultRegs}
193 :     end (* genCall *)
194 :    
195 : mrainey 2888 end (* AMD64SVID *)

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0