1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
signature C_CALL =
sig
structure T : MLTREE
structure Gen : C_CALL_GEN
(* where T = T *)
where type T.Basis.cond = T.Basis.cond
and type T.Basis.div_rounding_mode = T.Basis.div_rounding_mode
and type T.Basis.ext = T.Basis.ext
and type T.Basis.fcond = T.Basis.fcond
and type T.Basis.rounding_mode = T.Basis.rounding_mode
and type T.Constant.const = T.Constant.const
and type ('s,'r,'f,'c) T.Extension.ccx = ('s,'r,'f,'c) T.Extension.ccx
and type ('s,'r,'f,'c) T.Extension.fx = ('s,'r,'f,'c) T.Extension.fx
and type ('s,'r,'f,'c) T.Extension.rx = ('s,'r,'f,'c) T.Extension.rx
and type ('s,'r,'f,'c) T.Extension.sx = ('s,'r,'f,'c) T.Extension.sx
and type T.I.div_rounding_mode = T.I.div_rounding_mode
and type T.Region.region = T.Region.region
and type T.ccexp = T.ccexp
and type T.fexp = T.fexp
(* and type T.labexp = T.labexp *)
and type T.mlrisc = T.mlrisc
and type T.oper = T.oper
and type T.rep = T.rep
and type T.rexp = T.rexp
and type T.stm = T.stm
datatype c_arg = datatype Gen.c_arg
val layout : CType.c_proto -> {
argLocs : Gen.SA.loc list list, (* argument/parameter assignment; nested lists are for passing structs *)
argMem : {szb : int, align : int}, (* memory requirements for stack-allocated *)
(* arguments; this value can be passed to *)
(* the paramAlloc callback. *)
resLocs : Gen.SA.loc list, (* result location *)
structRetLoc : {szb : int, align : int} option
}
(* translate a C function call with the given argument list into
* a MLRISC statement list. The arguments are as follows:
*
* name -- an expression that speficies the function.
* proto -- the function's prototype
* paramAlloc -- this callback takes the size and alignment
* constraints on the parameter-passing area
* in the stack. If it returns true, then the
* space for the parameters is allocated by
* client; otherwise genCall allocates the space.
* structRet -- this callback takes the size and alignment
* of space required for returning a struct
* value. It returns the address of the
* reserved space.
* saveRestoreDedicated -- this callback takes a list of registers
* that the call kills and should return an
* instruction sequence to save/restore any
* registers that the client run-time model
* expects to be preserved (e.g., allocation
* pointers).
* callComment -- if present, the comment string is attached
* the CALL instruction as a COMMENT annotation.
* args -- the arguments to the call. The assumption is
* that any required sign or zero extension has
* already been done.
*
* The result of genCall is a mlrisc list specifying where the result
* is and the MLRisc statements that implement the calling sequence.
* Functions with void return type have no result, most others have
* one result, but some conventions may flatten larger arguments into
* multiple registers (e.g., a register pair for long long results).
*
* The implementation of genCall will return a statement sequence with the
* following order:
*
* <argument area allocation>
* <setup arguments>
* <save dedicated registers>
* <call C function>
* <restore dedicated registers>
* <free argument area>
* <copy result into fresh registers>
*
* WARNING: if the client's implementation of structRet uses the stack
* pointer to address the struct-return area, then paramAlloc should always
* handle allocating space for the parameter area (i.e., return true).
*)
val genCall : {
name : Gen.T.rexp,
proto : CType.c_proto,
paramAlloc : {szb : int, align : int} -> bool,
structRet : {szb : int, align : int} -> Gen.T.rexp,
saveRestoreDedicated :
Gen.T.mlrisc list -> {save: Gen.T.stm list, restore: Gen.T.stm list},
callComment : string option,
args : Gen.c_arg list
} -> {
callseq : Gen.T.stm list,
result: Gen.T.mlrisc list
}
(* Callee-save registers as defined in the C calling convention. Note that
* these do not include special registers (e.g., stack and frame-pointers)
* that are preserved across calls.
*)
val calleeSaveRegs : Gen.T.reg list (* C callee-save registers *)
val calleeSaveFRegs : Gen.T.reg list (* C callee-save floating-point registers *)
val callerSaveRegs : Gen.T.reg list (* C caller-save registers *)
val callerSaveFRegs : Gen.T.reg list (* C caller-save floating-point registers *)
end (* C_CALL *)
|