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

SCM Repository

[smlnj] Diff of /sml/trunk/src/MLRISC/ppc/c-calls/ppc-macosx.sml
ViewVC logotype

Diff of /sml/trunk/src/MLRISC/ppc/c-calls/ppc-macosx.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1549, Wed Jul 14 23:07:35 2004 UTC revision 1550, Thu Jul 15 18:17:27 2004 UTC
# Line 141  Line 141 
141     * padding is based on the parameter-passing description on p. 35 of the     * padding is based on the parameter-passing description on p. 35 of the
142     * documentation and the alignment is from p. 31.     * documentation and the alignment is from p. 31.
143     *)     *)
144      fun sizeOf CTy.I_char = {sz = 1, pad = 3, align = 1}      fun sizeOfInt CTy.I_char = {sz = 1, pad = 3, align = 1}
145        | sizeOf CTy.I_short = {sz = 2, pad = 2, align = 2}        | sizeOfInt CTy.I_short = {sz = 2, pad = 2, align = 2}
146        | sizeOf CTy.I_int = {sz = 4, pad = 0, align = 4}        | sizeOfInt CTy.I_int = {sz = 4, pad = 0, align = 4}
147        | sizeOf CTy.I_long = {sz = 4, pad = 0, align = 4}        | sizeOfInt CTy.I_long = {sz = 4, pad = 0, align = 4}
148        | sizeOf CTy.I_long_long = {sz = 8, pad = 0, align = 8}        | sizeOfInt CTy.I_long_long = {sz = 8, pad = 0, align = 8}
149    
150    (* sizes of other C types *)    (* sizes of other C types *)
151      val sizeOfPtr = {sz = 4, pad = 0, align = 4}      val sizeOfPtr = {sz = 4, pad = 0, align = 4}
152    
   (* compute the size and alignment information for fields of a struct  
    * or union; tys is the list  
    * of member types.  The alignment is what Apple calls the "embedding" alignment.  
    * The result has three parts:  
    *   sinfo = sz and align when fields are fields of a struct  
    *   uinfo = sz and align when fields are fields of a union  
    *   largest = the largest field  (relevant in case of a union)  
    * (This might be trimmed to just sinfo and largest since uinfo is  
    * currently used only internally within the implementation of  
    * fieldsInfo.)  
    *)  
     fun fieldsInfo tys = let  
153          (* align the address to the given alignment, which must be a power of 2 *)          (* align the address to the given alignment, which must be a power of 2 *)
154            fun alignAddr (addr, align) = let            fun alignAddr (addr, align) = let
155                  val mask = Word.fromInt(align-1)                  val mask = Word.fromInt(align-1)
156                  in                  in
157                    Word.toIntX(Word.andb(Word.fromInt addr + mask, Word.notb mask))                    Word.toIntX(Word.andb(Word.fromInt addr + mask, Word.notb mask))
158                  end                  end
159            fun sz CTy.C_void = error "unexpected void argument type"  
160              | sz CTy.C_float = {sz = 4, align = 4}    (* compute the size and alignment information for a struct; tys is the list
161              | sz CTy.C_double = {sz = 8, align = 8}     * of member types.  The alignment is what Apple calls the "embedding" alignment.
162              | sz CTy.C_long_double = {sz = 8, align = 8}     * The total size is padded to agree with the struct's alignment.
163              | sz (CTy.C_unsigned isz) = let     *)
164                  val {sz, align, ...} = sizeOf isz      fun sizeOfStruct tys = let
165              fun ssz [] = {sz = 0, align = 4}
166                | ssz (first::rest) = let
167                    fun f ([], maxAlign, offset) =
168                          {sz = alignAddr(offset, maxAlign), align = maxAlign}
169                      | f (ty::tys, maxAlign, offset) = let
170                            val {sz, align} = sizeOfTy ty
171                            val align = Int.min(align, 4)
172                            val offset = alignAddr(offset, align)
173                  in                  in
174                    {sz = sz, align = align}                            f (tys, Int.max(maxAlign, align), offset+sz)
175                  end                  end
176              | sz (CTy.C_signed isz) = let                  val {sz, align} = sizeOfTy first
                 val {sz, align, ...} = sizeOf isz  
177                  in                  in
178                    {sz = sz, align = align}                    f (rest, align, sz)
179                  end                  end
             | sz CTy.C_PTR = {sz = 4, align = 4}  
             | sz (CTy.C_ARRAY(ty, n)) = let  
                 val {sz, align} = sz ty  
180                  in                  in
181                    {sz = n*sz, align = align}              ssz tys
182                  end                  end
183              | sz (CTy.C_STRUCT tys) = #sinfo (fsz tys)  
184              | sz (CTy.C_UNION tys) = #uinfo (fsz tys)    (* the size alignment of a union type is the maximum of the sizes and alignments of the
185            and fsz [] = {sinfo = {sz = 0, align = 4},     * members.  The final size is padded to agree with the alignment.
186                          uinfo = {sz = 0, align = 4},     *)
187                          largest = CTy.C_unsigned CTy.I_int }      and sizeOfUnion tys = let
188              | fsz (first::rest) = let            fun usz [] = {sz = 0, align = 4}
189                    fun f ([], maxAlign, offset, maxSize, largest) =              | usz (first::rest) = let
190                          {sinfo = {sz = alignAddr(offset, maxAlign),                  fun f ([], maxAlign, maxSz) =
191                                    align = maxAlign},                        {sz = alignAddr(maxSz, maxAlign), align = maxAlign}
192                           uinfo = {sz = alignAddr(maxSize, maxAlign),                    | f (ty::tys, maxAlign, maxSz) = let
193                                    align = maxAlign},                          val {sz, align} = sizeOfTy ty
                          largest = largest}  
                     | f (ty::tys, maxAlign, offset, maxSize, largest) = let  
                           val {sz, align} = sz ty  
                           val align = Int.min(align, 4)  
                           val offset = alignAddr(offset, align)  
                           val (largest', maxSize') =  
                               if sz > maxSize then (ty, sz)  
                               else (largest, maxSize)  
194                        in                        in
195                            f (tys, Int.max(maxAlign, align),                            f (tys, Int.max(maxAlign, align), Int.max(align, maxAlign))
                                   offset+sz,  
                                   maxSize', largest')  
196                        end                        end
197                    val {sz, align} = sz first                  val {sz, align} = sizeOfTy first
198                in                in
199                    f (rest, align, sz, sz, first)                    f (rest, align, sz)
200                end                end
201            in            in
202              fsz tys              usz tys
203            end            end
204    
205      fun sizeOfStruct tys = #sz (#sinfo (fieldsInfo tys))      and sizeOfTy CTy.C_void = error "unexpected void argument type"
206          | sizeOfTy CTy.C_float = {sz = 4, align = 4}
207          | sizeOfTy CTy.C_double = {sz = 8, align = 8}
208          | sizeOfTy CTy.C_long_double = {sz = 8, align = 8}
209          | sizeOfTy (CTy.C_unsigned isz) = let
210              val {sz, align, ...} = sizeOfInt isz
211              in
212                {sz = sz, align = align}
213              end
214          | sizeOfTy (CTy.C_signed isz) = let
215              val {sz, align, ...} = sizeOfInt isz
216              in
217                {sz = sz, align = align}
218              end
219          | sizeOfTy CTy.C_PTR = {sz = 4, align = 4}
220          | sizeOfTy (CTy.C_ARRAY(ty, n)) = let
221              val {sz, align} = sizeOfTy ty
222              in
223                {sz = n*sz, align = align}
224              end
225          | sizeOfTy (CTy.C_STRUCT tys) = sizeOfStruct tys
226          | sizeOfTy (CTy.C_UNION tys) = sizeOfUnion tys
227    
228    (* compute the layout of a C call's arguments *)    (* compute the layout of a C call's arguments *)
229      fun layout {conv, retTy, paramTys} = let      fun layout {conv, retTy, paramTys} = let
230            fun gprRes isz = (case #sz(sizeOf isz)            fun gprRes isz = (case #sz(sizeOfInt isz)
231                   of 8 => raise Fail "register pairs not yet supported"                   of 8 => raise Fail "register pairs not yet supported"
232                    | _ => SOME resRegLoc                    | _ => SOME resRegLoc
233                  (* end case *))                  (* end case *))
           fun do_struct s = let  
              val sz = sizeOfStruct s  
              in  
               (* Note that this is a place where the MacOS X and Linux ABIs differ.  
                * In Linux, GPR3/GPR4 are used to return composite values of 8 bytes.  
                *)  
                 (* if (sz > 4)  
                 then *) (SOME resRegLoc, List.tl argGPRs, SOME{szb=sz, align=4})  
                 (* else (SOME resRegLoc, argGPRs, NONE) *)  
              end  
234            val (resLoc, argGPRs, structRet) = (case retTy            val (resLoc, argGPRs, structRet) = (case retTy
235                   of CTy.C_void => (NONE, argGPRs, NONE)                   of CTy.C_void => (NONE, argGPRs, NONE)
236                    | CTy.C_float => (SOME(FReg(fltTy, resFPR, NONE)), argGPRs, NONE)                    | CTy.C_float => (SOME(FReg(fltTy, resFPR, NONE)), argGPRs, NONE)
# Line 247  Line 240 
240                    | CTy.C_signed isz => (gprRes isz, argGPRs, NONE)                    | CTy.C_signed isz => (gprRes isz, argGPRs, NONE)
241                    | CTy.C_PTR => (SOME resRegLoc, argGPRs, NONE)                    | CTy.C_PTR => (SOME resRegLoc, argGPRs, NONE)
242                    | CTy.C_ARRAY _ => error "array return type"                    | CTy.C_ARRAY _ => error "array return type"
243                    | CTy.C_STRUCT s => do_struct s                    | CTy.C_STRUCT s => let
244                    | CTy.C_UNION u =>                        val sz = #sz(sizeOfStruct s)
                       (* handle unions by pretending they are  
                        * structures that contain a single field  
                        * (i.e., the largest field of the union)  
                        *   -Matthias *)  
                       do_struct [#largest (fieldsInfo u)]  
                 (* end case *))  
           fun assign ([], offset, _, _, layout) = (offset, List.rev layout)  
             | assign (ty::tys, offset, availGPRs, availFPRs, layout) = let  
                   fun do_struct tys' = let  
                       val sz = IntInf.fromInt(sizeOfStruct tys')  
                       fun assignMem (relOffset, availGPRs, fields) =  
                             if (relOffset < sz)  
                               then let  
                                 val (loc, availGPRs) = (case availGPRs  
                                        of [] => (Stk(wordTy, offset+relOffset), [])  
                                         | r1::rs => (Reg(wordTy, r1, SOME(offset+relOffset)), rs)  
                                       (* end case *))  
245                                  in                                  in
246                                    assignMem (relOffset+4, availGPRs, loc::fields)                        (* Note that this is a place where the MacOS X and Linux ABIs differ.
247                           * In Linux, GPR3/GPR4 are used to return composite values of 8 bytes.
248                           *)
249                            (SOME resRegLoc, List.tl argGPRs, SOME{szb=sz, align=4})
250                                  end                                  end
251                                else assign (tys, offset+relOffset, availGPRs, availFPRs,                    | CTy.C_UNION u => let
252                                    Args(List.rev fields) :: layout)                        val sz = #sz(sizeOfUnion u)
253                        in                        in
254                          assignMem (0, availGPRs, [])                          (SOME resRegLoc, List.tl argGPRs, SOME{szb=sz, align=4})
255                        end                        end
256                  in                  (* end case *))
257              fun assign ([], offset, _, _, layout) = (offset, List.rev layout)
258                | assign (ty::tys, offset, availGPRs, availFPRs, layout) = (
259                  case ty                  case ty
260                   of CTy.C_void => error "unexpected void argument type"                   of CTy.C_void => error "unexpected void argument type"
261                    | CTy.C_float => (case (availGPRs, availFPRs)                    | CTy.C_float => (case (availGPRs, availFPRs)
# Line 291  Line 272 
272                    | CTy.C_long_double =>                    | CTy.C_long_double =>
273                        assignFPR (tys, offset, availGPRs, availFPRs, layout)                        assignFPR (tys, offset, availGPRs, availFPRs, layout)
274                    | CTy.C_unsigned isz =>                    | CTy.C_unsigned isz =>
275                        assignGPR(sizeOf isz, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfInt isz, tys, offset, availGPRs, availFPRs, layout)
276                    | CTy.C_signed isz =>                    | CTy.C_signed isz =>
277                        assignGPR(sizeOf isz, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfInt isz, tys, offset, availGPRs, availFPRs, layout)
278                    | CTy.C_PTR =>                    | CTy.C_PTR =>
279                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)
280                    | CTy.C_ARRAY _ =>                    | CTy.C_ARRAY _ =>
281                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)
282                    | CTy.C_STRUCT tys' => do_struct tys'                    | CTy.C_STRUCT tys' =>
283                          assignMem(sizeOfStruct tys', tys, offset, availGPRs, availFPRs, layout)
284                    | CTy.C_UNION tys' =>                    | CTy.C_UNION tys' =>
285                        (* Again, we treat a union as if it were a struct                        assignMem(sizeOfUnion tys', tys, offset, availGPRs, availFPRs, layout)
286                         * with just a single field (the largest field of                  (* end case *))
                        * the union).  Is this kosher?  -Matthias *)  
                       do_struct [#largest (fieldsInfo tys')]  
                 end  
287          (* assign a GP register and memory for an integer/pointer argument. *)          (* assign a GP register and memory for an integer/pointer argument. *)
288            and assignGPR ({sz, pad, ...}, args, offset, availGPRs, availFPRs, layout) = let            and assignGPR ({sz, pad, ...}, args, offset, availGPRs, availFPRs, layout) = let
289                  val (loc, availGPRs) = (case (sz, availGPRs)                  val (loc, availGPRs) = (case (sz, availGPRs)
# Line 329  Line 308 
308                      | _ => error "FPRs exhausted before GPRs"                      | _ => error "FPRs exhausted before GPRs"
309                    (* end case *)                    (* end case *)
310                  end                  end
311            (* assign a argument locations to pass a composite argument (struct or union) *)
312              and assignMem ({sz, ...}, args, offset, availGPRs, availFPRs, layout) = let
313                    val sz = IntInf.fromInt sz
314                    fun assignMem (relOffset, availGPRs, fields) =
315                          if (relOffset < sz)
316                            then let
317                              val (loc, availGPRs) = (case availGPRs
318                                     of [] => (Stk(wordTy, offset+relOffset), [])
319                                      | r1::rs => (Reg(wordTy, r1, SOME(offset+relOffset)), rs)
320                                    (* end case *))
321                              in
322                                assignMem (relOffset+4, availGPRs, loc::fields)
323                              end
324                            else assign (args, offset+relOffset, availGPRs, availFPRs,
325                                Args(List.rev fields) :: layout)
326                    in
327                      assignMem (0, availGPRs, [])
328                    end
329            val (sz, argLocs) = assign (paramTys, 0, argGPRs, argFPRs, [])            val (sz, argLocs) = assign (paramTys, 0, argGPRs, argFPRs, [])
330            in {            in {
331              argLocs = argLocs,              argLocs = argLocs,

Legend:
Removed from v.1549  
changed lines
  Added in v.1550

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