131 |
(* FIXME: also need link register *) |
(* FIXME: also need link register *) |
132 |
(List.map C.GPReg [2, 11, 12]) @ argGPRs @ (List.map C.FPReg [0]) @ argFPRs |
(List.map C.GPReg [2, 11, 12]) @ argGPRs @ (List.map C.FPReg [0]) @ argFPRs |
133 |
|
|
134 |
|
(* the parameter area lies just above the linkage area in the caller's frame. |
135 |
|
* The linkage area is 24 bytes, so the first parameter is at 24(sp). |
136 |
|
*) |
137 |
|
val paramAreaOffset = 24 |
138 |
|
|
139 |
(* size and padding for integer types. Note that the padding is based on the |
(* size and padding for integer types. Note that the padding is based on the |
140 |
* parameter-passing description on p. 35 of the documentation. |
* parameter-passing description on p. 35 of the documentation. |
141 |
*) |
*) |
148 |
(* sizes of other C types *) |
(* sizes of other C types *) |
149 |
val sizeOfPtr = {sz = 4, pad = 0} |
val sizeOfPtr = {sz = 4, pad = 0} |
150 |
|
|
151 |
fun sizeOfStruct tys = ? |
fun sizeOfStruct tys = let |
152 |
|
(* |
153 |
|
fun sz CTy.C_void = error "unexpected void argument type" |
154 |
|
| sz CTy.C_float = 4 |
155 |
|
| sz CTy.C_double = 8 |
156 |
|
| sz CTy.C_long_double = 8 |
157 |
|
| sz CTy.C_unsigned isz = #sz(sizeOf isz) |
158 |
|
| sz CTy.C_signed isz = #sz(sizeOf isz) |
159 |
|
| sz CTy.C_PTR = 4 |
160 |
|
| sz (CTy.C_ARRAY tys) = let |
161 |
|
| sz (CTy.C_STRUCT s) = |
162 |
|
*) |
163 |
|
in |
164 |
|
raise Fail "FIXME" |
165 |
|
end |
166 |
|
|
167 |
(* compute the layout of a C call's arguments *) |
(* compute the layout of a C call's arguments *) |
168 |
fun layout {conv, retTy, paramTys} = let |
fun layout {conv, retTy, paramTys} = let |
170 |
of 8 => raise Fail "register pairs not yet supported" |
of 8 => raise Fail "register pairs not yet supported" |
171 |
| _ => SOME resGPR |
| _ => SOME resGPR |
172 |
(* end case *)) |
(* end case *)) |
173 |
val (resReg, availGPRs) = (case retTy |
val (resReg, availGPRs, structRet) = (case retTy |
174 |
of CTy.C_void => (NONE, availGPRs) |
of CTy.C_void => (NONE, availGPRs, NONE) |
175 |
| CTy.C_float => (SOME resFPR, availGPRs) |
| CTy.C_float => (SOME resFPR, availGPRs, NONE) |
176 |
| CTy.C_double => (SOME resFPR, availGPRs) |
| CTy.C_double => (SOME resFPR, availGPRs, NONE) |
177 |
| CTy.C_long_double => (SOME resFPR, availGPRs) |
| CTy.C_long_double => (SOME resFPR, availGPRs, NONE) |
178 |
| CTy.C_unsigned isz => (gprRes isz, availGPRs) |
| CTy.C_unsigned isz => (gprRes isz, availGPRs, NONE) |
179 |
| CTy.C_signed isz => (gprRes isz, availGPRs) |
| CTy.C_signed isz => (gprRes isz, availGPRs, NONE) |
180 |
| CTy.C_PTR => (SOME resGPR, availGPRs) |
| CTy.C_PTR => (SOME resGPR, availGPRs, NONE) |
181 |
| CTy.C_ARRAY _ => error "array return type" |
| CTy.C_ARRAY _ => error "array return type" |
182 |
| CTy.C_STRUCT s => let |
| CTy.C_STRUCT s => let |
183 |
val sz = sizeOfStruct s |
val sz = sizeOfStruct s |
186 |
* In Linux, GPR3/GPR4 are used to return composite values of 8 bytes. |
* In Linux, GPR3/GPR4 are used to return composite values of 8 bytes. |
187 |
*) |
*) |
188 |
if (sz > 4) |
if (sz > 4) |
189 |
then (SOME resGPR, List.tl availGPRs) |
then (SOME resGPR, List.tl availGPRs, SOME{szb=sz, align=4}) |
190 |
else (SOME resGPR, availGPRs) |
else (SOME resGPR, availGPRs, NONE) |
191 |
end |
end |
192 |
(* end case *)) |
(* end case *)) |
193 |
fun assign ([], offset, _, _, layout) = {sz = offset, layout = List.rev layout} |
fun assign ([], offset, _, _, layout) = {sz = offset, layout = List.rev layout} |
194 |
| assign (arg::args, offset, availGPRs, availFPRs, layout) = ( |
| assign (ty::tys, offset, availGPRs, availFPRs, layout) = ( |
195 |
case arg |
case ty |
196 |
of CTy.C_void => error "unexpected void argument type" |
of CTy.C_void => error "unexpected void tyument type" |
197 |
| CTy.C_float => (case (availGPRs, availFPRs) |
| CTy.C_float => (case (availGPRs, availFPRs) |
198 |
of (_:gprs, fpr::fprs) => |
of (_:gprs, fpr::fprs) => |
199 |
assign (args, offset+4, gprs, fprs, FReg(fltTy, fpr, SOME offset)::layout) |
assign (tys, offset+4, gprs, fprs, FReg(fltTy, fpr, SOME offset)::layout) |
200 |
| ([], fpr::fprs) => |
| ([], fpr::fprs) => |
201 |
assign (args, offset+4, [], fprs, FReg(fltTy, fpr, SOME offset)::layout) |
assign (tys, offset+4, [], fprs, FReg(fltTy, fpr, SOME offset)::layout) |
202 |
| ([], []) => |
| ([], []) => |
203 |
assign (args, offset+4, [], [], FStk(fltTy, offset)::layout) |
assign (tys, offset+4, [], [], FStk(fltTy, offset)::layout) |
204 |
(* end case *)) |
(* end case *)) |
205 |
| CTy.C_double => |
| CTy.C_double => |
206 |
|
assignFPR (tys, offset, availGPRs, availFPRs, layout) |
207 |
| CTy.C_long_double => |
| CTy.C_long_double => |
208 |
|
assignFPR (tys, offset, availGPRs, availFPRs, layout) |
209 |
| CTy.C_unsigned isz => |
| CTy.C_unsigned isz => |
210 |
assignGPR(sizeOf isz, args, offset, availGPRs, availFPRs, layout) |
assignGPR(sizeOf isz, tys, offset, availGPRs, availFPRs, layout) |
211 |
| CTy.C_signed isz => |
| CTy.C_signed isz => |
212 |
assignGPR(sizeOf isz, args, offset, availGPRs, availFPRs, layout) |
assignGPR(sizeOf isz, tys, offset, availGPRs, availFPRs, layout) |
213 |
| CTy.C_PTR => |
| CTy.C_PTR => |
214 |
assignGPR(sizeOfPtr, args, offset, availGPRs, availFPRs, layout) |
assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout) |
215 |
| CTy.C_ARRAY _ => |
| CTy.C_ARRAY _ => |
216 |
assignGPR(sizeOfPtr, args, offset, availGPRs, availFPRs, layout) |
assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout) |
217 |
| CTy.C_STRUCT tys => |
| CTy.C_STRUCT tys' => raise Fail "struct arguments not supported yet" |
218 |
(* end case *)) |
(* end case *)) |
219 |
(* assign a GP register and memory for an integer/pointer argument. *) |
(* assign a GP register and memory for an integer/pointer argument. *) |
220 |
and assignGPR ({sz, pad}, args, offset, availGPRs, availFPRs, layout) = let |
and assignGPR ({sz, pad}, args, offset, availGPRs, availFPRs, layout) = let |
242 |
in { |
in { |
243 |
argLocs = assign (paramTys, 0, argGPRs, argFPRs, []), |
argLocs = assign (paramTys, 0, argGPRs, argFPRs, []), |
244 |
resLoc = resReg, |
resLoc = resReg, |
245 |
structRet = ? |
structRet = structRet |
246 |
} end |
} end |
247 |
|
|
248 |
datatype c_arg |
datatype c_arg |
253 |
val memRg = T.Region.memory |
val memRg = T.Region.memory |
254 |
val stkRg = T.Region.memory |
val stkRg = T.Region.memory |
255 |
|
|
256 |
|
(* SP-based address of parameter at given offset *) |
257 |
|
fun paramAddr off = T.ADD(wordSz, spR, T.LI(off + IntInf.fromInt paramAreaOffset)) |
258 |
|
|
259 |
fun genCall { |
fun genCall { |
260 |
name, proto, paramAlloc, structRet, saveRestoreDedicated, |
name, proto, paramAlloc, structRet, saveRestoreDedicated, |
261 |
callComment, args |
callComment, args |
267 |
| assignArgs (Reg(ty, r, _) :: locs, ARG exp :: args, stms) = |
| assignArgs (Reg(ty, r, _) :: locs, ARG exp :: args, stms) = |
268 |
assignArgs (locs, args, T.MV(ty, r, exp) :: stms) |
assignArgs (locs, args, T.MV(ty, r, exp) :: stms) |
269 |
| assignArgs (Stk(ty, off) :: locs, ARG exp :: args, stms) = |
| assignArgs (Stk(ty, off) :: locs, ARG exp :: args, stms) = |
270 |
assignArgs (locs, args, T.STORE(ty, ?, exp, stkRg) :: stms) |
assignArgs (locs, args, T.STORE(ty, paramAddr off, exp, stkRg) :: stms) |
271 |
| assignArgs (FReg(ty, r, _) :: locs, FARG fexp :: args) = |
| assignArgs (FReg(ty, r, _) :: locs, FARG fexp :: args) = |
272 |
assignArgs (locs, args, T.FMV(ty, r, fexp) :: stms) |
assignArgs (locs, args, T.FMV(ty, r, fexp) :: stms) |
273 |
| assignArgs (FStk(ty, off) :: locs, FARG fexp :: args, stms) = |
| assignArgs (FStk(ty, off) :: locs, FARG fexp :: args, stms) = |
274 |
assignArgs (locs, args, T.FSTORE(ty, ?, fexp, stkRg) :: stms) |
assignArgs (locs, args, T.FSTORE(ty, paramAddr off, fexp, stkRg) :: stms) |
275 |
| assignArgs ((Args locs') :: locs, (ARGS args') :: args, stms) = |
| assignArgs ((Args locs') :: locs, (ARGS args') :: args, stms) = |
276 |
assignArgs (locs, args, assignArgs(locs', args', stms)) |
assignArgs (locs, args, assignArgs(locs', args', stms)) |
277 |
| assignArgs _ = error "argument/formal mismatch" |
| assignArgs _ = error "argument/formal mismatch" |
313 |
| SOME c => T.ANNOTATION(callStm, #create MLRiscAnnotations.COMMENT c) |
| SOME c => T.ANNOTATION(callStm, #create MLRiscAnnotations.COMMENT c) |
314 |
(* end case *)) |
(* end case *)) |
315 |
val callseq = List.concat [ |
val callseq = List.concat [ |
|
??, |
|
316 |
argSetupCode, |
argSetupCode, |
317 |
[callStm], |
[callStm] |
|
?? |
|
318 |
] |
] |
319 |
in |
in |
320 |
(* check calling convention *) |
(* check calling convention *) |