(root)/
gcc-13.2.0/
libgcc/
config/
alpha/
vms-gcc_shell_handler.c
       1  /* Static condition handler for Alpha/VMS.
       2     Copyright (C) 2005-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of GCC.
       5  
       6     GCC is free software; you can redistribute it and/or modify it
       7     under the terms of the GNU General Public License as published
       8     by the Free Software Foundation; either version 3, or (at your
       9     option) any later version.
      10  
      11     GCC is distributed in the hope that it will be useful, but WITHOUT
      12     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14     License for more details.
      15  
      16     Under Section 7 of GPL version 3, you are granted additional
      17     permissions described in the GCC Runtime Library Exception, version
      18     3.1, as published by the Free Software Foundation.
      19  
      20     You should have received a copy of the GNU General Public License and
      21     a copy of the GCC Runtime Library Exception along with this program;
      22     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23     <http://www.gnu.org/licenses/>.  */
      24  
      25  /* This file implements __gcc_shell_handler, the static VMS condition handler
      26     used as the indirection wrapper around user level handlers installed with
      27     establish_vms_condition_handler GCC builtin.
      28  
      29     [ABI] in comments refers to the "HP OpenVMS calling standard" document
      30     dated January 2005.  */
      31  
      32  #include <vms/chfdef.h>
      33  #include <vms/pdscdef.h>
      34  #include <vms/ssdef.h>
      35  
      36  typedef void * ADDR;
      37  typedef unsigned long long REG;
      38  
      39  #define REG_AT(addr) (*(REG *)(addr))
      40  
      41  /* Compute pointer to procedure descriptor (Procedure Value) from Frame
      42     Pointer FP, according to the rules in [ABI-3.5.1 Current Procedure].  */
      43  #define PV_FOR(FP) \
      44    (((FP) != 0) \
      45      ? (((REG_AT (FP) & 0x7) == 0) ? *(PDSCDEF **)(FP) : (PDSCDEF *)(FP)) : 0)
      46  
      47  long
      48  __gcc_shell_handler (struct chf$signal_array *sig_arr,
      49  		     struct chf$mech_array *mech_arr);
      50  
      51  /* Helper for __gcc_shell_handler.  Fetch the pointer to procedure currently
      52     registered as the VMS condition handler for the live function with a frame
      53     pointer FP.  */
      54  
      55  static ADDR
      56  get_dyn_handler_pointer (REG fp)
      57  {
      58    /* From the frame pointer we find the procedure descriptor, and fetch
      59       the handler_data field from there.  This field contains the offset
      60       from FP at which the address of the currently installed handler is
      61       to be found.  */
      62    
      63    PDSCDEF * pd = PV_FOR (fp);
      64    /* Procedure descriptor pointer for the live subprogram with FP as the frame
      65       pointer, and to which _gcc_shell_handler is attached as a condition
      66       handler.  */
      67  
      68    REG handler_slot_offset;
      69    /* Offset from FP at which the address of the currently established real
      70       condition handler is to be found.  This offset is available from the
      71       handler_data field of the procedure descriptor.  */
      72  
      73    REG handler_data_offset;
      74    /* The handler_data field position in the procedure descriptor, which
      75       depends on the kind of procedure at hand.  */
      76  
      77    switch (pd->pdsc$w_flags & 0xf)
      78      {
      79      case PDSC$K_KIND_FP_STACK:    /* [3.4.2 PD for stack frame procedures]  */
      80        handler_data_offset = 40;
      81        break;
      82  	
      83      case PDSC$K_KIND_FP_REGISTER: /* [3.4.5 PD for reg frame procedures]  */
      84        handler_data_offset = 32;
      85        break;
      86        
      87      default:
      88        handler_data_offset = 0;
      89        break;
      90      }
      91  
      92    /* If we couldn't determine the handler_data field position, give up.  */
      93    if (handler_data_offset == 0)
      94      return 0;
      95  
      96    /* Otherwise, fetch the fp offset at which the real handler address is to be
      97       found, then fetch and return the latter in turn.  */
      98       
      99    handler_slot_offset = REG_AT ((REG)pd + handler_data_offset);
     100  
     101    return (ADDR) REG_AT (fp + handler_slot_offset);
     102  }
     103  
     104  /* The static VMS condition handler for GCC code.  Fetch the address of the
     105     currently established condition handler, then resignal if there is none or
     106     call the handler with the VMS condition arguments.  */
     107  
     108  long
     109  __gcc_shell_handler (struct chf$signal_array *sig_arr,
     110  		     struct chf$mech_array *mech_arr)
     111  {
     112    long ret;
     113    long (*user_handler) (struct chf$signal_array *, struct chf$mech_array *);
     114  
     115    user_handler = get_dyn_handler_pointer (mech_arr->chf$q_mch_frame);
     116    if (!user_handler)
     117      ret = SS$_RESIGNAL;
     118    else
     119      ret = user_handler (sig_arr, mech_arr);
     120  
     121    return ret;
     122  }
     123