/* Sun-$Revision: 23.5 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
   See the LICENSE file for license information. */
# pragma interface
// sparc frame layout:
/*
                                 prev frame
  %fp-> ----------------------------------------------
    %fp - offset: space for automatic arrays, aggregates, and addressable
                  scalar automatics.
                  (Self compiled frames alloc extras here for
                  frame chains and currentPCs)
                  -------------------------------
                  space dynamically allocated via alloca(), if any
    alloca()-> ----------------------------
                  space if needed for compiler temps and saved floating
    %sp + offset  -point registers
               ----------------------------
    %sp + offset  outgoing params past the sixth, if any
               -----------------------------
    %sp + offset  6 words into which callee may store reg args
               -----------------------------
    %sp + offset  one-word hidden param (addr where callee should store
                    aggregate return value)
               -----------------------------
    %sp + offset  16 words in which to save register window (in and locals)
  %sp-> ------------------------------------------------
                              next frame
*/
class sparc_fp;
class sparc_sp;
class frame;
class sparc_fp {
  friend frame;
  friend FrameIterator;
  friend sparc_sp;
  sparc_fp()            { ShouldNotCallThis(); }
  sparc_fp(sparc_fp &s) { ShouldNotCallThis(); }
  
  // coercions
  
  oop*      as_oops()       { return (oop*)     this; }
  sparc_sp* as_callers_sp() { return (sparc_sp*)this; }
  // nmethod frame chain operations:
  //  this is a word allocated by the Self compiler to allow
  //   frames that use an nmethod to be linked
  
  frame** nmethod_frame_chain_addr() {
    return &((frame**) this)[nmethod_frame_chain_offset]; }
  char**     currentPC_addr() {
    return &((char**    ) this)[current_pc_offset]; }
};
class Conversion;
class Recompilation;
class sparc_sp {
  friend sparc_fp;
  friend frame;
  friend FrameIterator;
  friend Conversion; // this is sparc-specific for now
  friend Recompilation; // this is sparc-specific for now
  
  sparc_sp()            { ShouldNotCallThis(); }
  sparc_sp(sparc_sp &s) { ShouldNotCallThis(); }
  // coercions
  sparc_fp* as_callees_fp() { return (sparc_fp*)this; }
  frame*    as_callers_frame() { return (frame*)this; }
  oop*      as_oops() { return (oop*)this; }
  // what is stored here:
  // link is a low-level machine-dependent concept about how
  //  frames are stiched together (senders are high-level)
  
  // could use location_addr but this is faster:
  sparc_fp**       link_addr() { return &((sparc_fp**) this)[frame_offset]; }
  sparc_fp*        link() { return *link_addr(); }
  void         set_link(sparc_fp* x) { *link_addr() = x; }
  void      adjust_link(int32 delta) { *(char**)link_addr() += delta; }
  // return address, no patch/real distinction here
  char**        return_addr_addr() { return &((char**) this)[pc_offset]; }
  char*         return_addr() { return *return_addr_addr(); }
  void      set_return_addr(char* x) { *return_addr_addr() = x; }
  
  void** location_addr(Location r);
 public:
  sparc_sp* push_new_sp( char* pc,
                         fint size_in_oops = 0,
                         bool zapAlways = false);
};