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 1545, Wed Jul 14 18:33:15 2004 UTC revision 1549, Wed Jul 14 23:07:35 2004 UTC
# Line 150  Line 150 
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    
153    (* compute the size and alignment information for a struct; tys is the list    (* compute the size and alignment information for fields of a struct
154       * or union; tys is the list
155     * of member types.  The alignment is what Apple calls the "embedding" alignment.     * of member types.  The alignment is what Apple calls the "embedding" alignment.
156       * The result has three parts:
157       *   sinfo = sz and align when fields are fields of a struct
158       *   uinfo = sz and align when fields are fields of a union
159       *   largest = the largest field  (relevant in case of a union)
160       * (This might be trimmed to just sinfo and largest since uinfo is
161       * currently used only internally within the implementation of
162       * fieldsInfo.)
163     *)     *)
164      fun sizeOfStruct tys = let      fun fieldsInfo tys = let
165          (* 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 *)
166            fun alignAddr (addr, align) = let            fun alignAddr (addr, align) = let
167                  val mask = Word.fromInt(align-1)                  val mask = Word.fromInt(align-1)
# Line 180  Line 188 
188                  in                  in
189                    {sz = n*sz, align = align}                    {sz = n*sz, align = align}
190                  end                  end
191              | sz (CTy.C_STRUCT tys) = ssz tys              | sz (CTy.C_STRUCT tys) = #sinfo (fsz tys)
192            and ssz [] = {sz = 0, align = 4}              | sz (CTy.C_UNION tys) = #uinfo (fsz tys)
193              | ssz (first::rest) = let            and fsz [] = {sinfo = {sz = 0, align = 4},
194                  fun f ([], maxAlign, offset) =                          uinfo = {sz = 0, align = 4},
195                        {sz = alignAddr(offset, maxAlign), align = maxAlign}                          largest = CTy.C_unsigned CTy.I_int }
196                    | f (ty::tys, maxAlign, offset) = let              | fsz (first::rest) = let
197                      fun f ([], maxAlign, offset, maxSize, largest) =
198                            {sinfo = {sz = alignAddr(offset, maxAlign),
199                                      align = maxAlign},
200                             uinfo = {sz = alignAddr(maxSize, maxAlign),
201                                      align = maxAlign},
202                             largest = largest}
203                        | f (ty::tys, maxAlign, offset, maxSize, largest) = let
204                          val {sz, align} = sz ty                          val {sz, align} = sz ty
205                          val align = Int.min(align, 4)                          val align = Int.min(align, 4)
206                          val offset = alignAddr(offset, align)                          val offset = alignAddr(offset, align)
207                          in                            val (largest', maxSize') =
208                            f (tys, Int.max(maxAlign, align), offset+sz)                                if sz > maxSize then (ty, sz)
209                                  else (largest, maxSize)
210                          in
211                              f (tys, Int.max(maxAlign, align),
212                                      offset+sz,
213                                      maxSize', largest')
214                          end                          end
215                  val {sz, align} = sz first                  val {sz, align} = sz first
216                  in                  in
217                    f (rest, align, sz)                    f (rest, align, sz, sz, first)
218                  end                  end
219            in            in
220              #sz(ssz tys)              fsz tys
221            end            end
222    
223        fun sizeOfStruct tys = #sz (#sinfo (fieldsInfo tys))
224    
225    (* compute the layout of a C call's arguments *)    (* compute the layout of a C call's arguments *)
226      fun layout {conv, retTy, paramTys} = let      fun layout {conv, retTy, paramTys} = let
227            fun gprRes isz = (case #sz(sizeOf isz)            fun gprRes isz = (case #sz(sizeOf isz)
228                   of 8 => raise Fail "register pairs not yet supported"                   of 8 => raise Fail "register pairs not yet supported"
229                    | _ => SOME resRegLoc                    | _ => SOME resRegLoc
230                  (* end case *))                  (* end case *))
231              fun do_struct s = let
232                 val sz = sizeOfStruct s
233                 in
234                  (* Note that this is a place where the MacOS X and Linux ABIs differ.
235                   * In Linux, GPR3/GPR4 are used to return composite values of 8 bytes.
236                   *)
237                    (* if (sz > 4)
238                    then *) (SOME resRegLoc, List.tl argGPRs, SOME{szb=sz, align=4})
239                    (* else (SOME resRegLoc, argGPRs, NONE) *)
240                 end
241            val (resLoc, argGPRs, structRet) = (case retTy            val (resLoc, argGPRs, structRet) = (case retTy
242                   of CTy.C_void => (NONE, argGPRs, NONE)                   of CTy.C_void => (NONE, argGPRs, NONE)
243                    | CTy.C_float => (SOME(FReg(fltTy, resFPR, NONE)), argGPRs, NONE)                    | CTy.C_float => (SOME(FReg(fltTy, resFPR, NONE)), argGPRs, NONE)
# Line 215  Line 247 
247                    | CTy.C_signed isz => (gprRes isz, argGPRs, NONE)                    | CTy.C_signed isz => (gprRes isz, argGPRs, NONE)
248                    | CTy.C_PTR => (SOME resRegLoc, argGPRs, NONE)                    | CTy.C_PTR => (SOME resRegLoc, argGPRs, NONE)
249                    | CTy.C_ARRAY _ => error "array return type"                    | CTy.C_ARRAY _ => error "array return type"
250                    | CTy.C_STRUCT s => let                    | CTy.C_STRUCT s => do_struct s
251                        val sz = sizeOfStruct s                    | CTy.C_UNION u =>
252                        in                        (* handle unions by pretending they are
253                        (* Note that this is a place where the MacOS X and Linux ABIs differ.                         * structures that contain a single field
254                         * In Linux, GPR3/GPR4 are used to return composite values of 8 bytes.                         * (i.e., the largest field of the union)
255                         *)                         *   -Matthias *)
256                          if (sz > 4)                        do_struct [#largest (fieldsInfo u)]
                           then (SOME resRegLoc, List.tl argGPRs, SOME{szb=sz, align=4})  
                           else (SOME resRegLoc, argGPRs, NONE)  
                       end  
257                  (* end case *))                  (* end case *))
258            fun assign ([], offset, _, _, layout) = (offset, List.rev layout)            fun assign ([], offset, _, _, layout) = (offset, List.rev layout)
259              | assign (ty::tys, offset, availGPRs, availFPRs, layout) = (              | assign (ty::tys, offset, availGPRs, availFPRs, layout) = let
260                      fun do_struct tys' = let
261                          val sz = IntInf.fromInt(sizeOfStruct tys')
262                          fun assignMem (relOffset, availGPRs, fields) =
263                                if (relOffset < sz)
264                                  then let
265                                    val (loc, availGPRs) = (case availGPRs
266                                           of [] => (Stk(wordTy, offset+relOffset), [])
267                                            | r1::rs => (Reg(wordTy, r1, SOME(offset+relOffset)), rs)
268                                          (* end case *))
269                                    in
270                                      assignMem (relOffset+4, availGPRs, loc::fields)
271                                    end
272                                  else assign (tys, offset+relOffset, availGPRs, availFPRs,
273                                      Args(List.rev fields) :: layout)
274                          in
275                            assignMem (0, availGPRs, [])
276                          end
277                    in
278                  case ty                  case ty
279                   of CTy.C_void => error "unexpected void argument type"                   of CTy.C_void => error "unexpected void argument type"
280                    | CTy.C_float => (case (availGPRs, availFPRs)                    | CTy.C_float => (case (availGPRs, availFPRs)
# Line 251  Line 298 
298                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)
299                    | CTy.C_ARRAY _ =>                    | CTy.C_ARRAY _ =>
300                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)                        assignGPR(sizeOfPtr, tys, offset, availGPRs, availFPRs, layout)
301                    | CTy.C_STRUCT tys' => let                    | CTy.C_STRUCT tys' => do_struct tys'
302                        val sz = IntInf.fromInt(sizeOfStruct tys')                    | CTy.C_UNION tys' =>
303                        fun assignMem (relOffset, availGPRs, fields) =                        (* Again, we treat a union as if it were a struct
304                              if (relOffset < sz)                         * with just a single field (the largest field of
305                                then let                         * the union).  Is this kosher?  -Matthias *)
306                                  val (loc, availGPRs) = (case availGPRs                        do_struct [#largest (fieldsInfo tys')]
                                        of [] => (Stk(wordTy, offset+relOffset), [])  
                                         | r1::rs => (Reg(wordTy, r1, SOME(offset+relOffset)), rs)  
                                       (* end case *))  
                                 in  
                                   assignMem (relOffset+4, availGPRs, loc::fields)  
307                                  end                                  end
                               else assign (tys, offset+relOffset, availGPRs, availFPRs,  
                                   Args(List.rev fields) :: layout)  
                       in  
                         assignMem (0, availGPRs, [])  
                       end  
                 (* end case *))  
308          (* assign a GP register and memory for an integer/pointer argument. *)          (* assign a GP register and memory for an integer/pointer argument. *)
309            and assignGPR ({sz, pad, ...}, args, offset, availGPRs, availFPRs, layout) = let            and assignGPR ({sz, pad, ...}, args, offset, availGPRs, availFPRs, layout) = let
310                  val (loc, availGPRs) = (case (sz, availGPRs)                  val (loc, availGPRs) = (case (sz, availGPRs)

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

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