This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

S/390: Enable vcall thunks


Hello,

this patch adds support for the new TARGET_ASM_OUTPUT_MI_THUNK hook
for the s390 targets.

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.


ChangeLog:

      * config/s390/s390.c (s390_output_mi_vcall_thunk): New function.
      (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Define target hook.
      (s390_output_mi_thunk): Remove.
      (TARGET_ASM_OUTPUT_MI_THUNK): Remove.

Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.61
diff -c -p -r1.61 s390.c
*** gcc/config/s390/s390.c    20 Oct 2002 22:37:12 -0000    1.61
--- gcc/config/s390/s390.c    21 Oct 2002 13:08:41 -0000
*************** static int s390_adjust_priority PARAMS (
*** 54,60 ****
  static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx,
                                   unsigned HOST_WIDE_INT));
  static void s390_encode_section_info PARAMS ((tree, int));
! static void s390_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));

  #undef  TARGET_ASM_ALIGNED_HI_OP
  #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
--- 54,61 ----
  static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx,
                                   unsigned HOST_WIDE_INT));
  static void s390_encode_section_info PARAMS ((tree, int));
! static void s390_output_mi_vcall_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
!                                   HOST_WIDE_INT, tree));

  #undef  TARGET_ASM_ALIGNED_HI_OP
  #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
*************** static void s390_output_mi_thunk PARAMS
*** 81,88 ****
  #undef    TARGET_ENCODE_SECTION_INFO
  #define TARGET_ENCODE_SECTION_INFO s390_encode_section_info

! #undef TARGET_ASM_OUTPUT_MI_THUNK
! #define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk

  struct gcc_target targetm = TARGET_INITIALIZER;

--- 82,89 ----
  #undef    TARGET_ENCODE_SECTION_INFO
  #define TARGET_ENCODE_SECTION_INFO s390_encode_section_info

! #undef TARGET_ASM_OUTPUT_MI_VCALL_THUNK
! #define TARGET_ASM_OUTPUT_MI_VCALL_THUNK s390_output_mi_vcall_thunk

  struct gcc_target targetm = TARGET_INITIALIZER;

*************** s390_encode_section_info (decl, first)
*** 5587,5663 ****
      }
  }

  static void
! s390_output_mi_thunk (file, thunk, delta, function)
       FILE *file;
       tree thunk ATTRIBUTE_UNUSED;
       HOST_WIDE_INT delta;
       tree function;
  {
!   if (TARGET_64BIT)
!     {
!       if (flag_pic)
!         {
!           fprintf (file, "\tlarl  1,0f\n");
!           fprintf (file, "\tagf   %d,0(1)\n",
!                    aggregate_value_p (TREE_TYPE
!                                       (TREE_TYPE (function))) ? 3 :2 );
!           fprintf (file, "\tlarl  1,");
!           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
!           fprintf (file, "@GOTENT\n");
!           fprintf (file, "\tlg    1,0(1)\n");
!           fprintf (file, "\tbr    1\n");
!           fprintf (file, "0:\t.long  ");
!           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));
!           fprintf (file, "\n");
!         }
!       else
!         {
!           fprintf (file, "\tlarl  1,0f\n");
!           fprintf (file, "\tagf   %d,0(1)\n",
!           aggregate_value_p (TREE_TYPE
!                              (TREE_TYPE (function))) ? 3 :2 );
!           fprintf (file, "\tjg  ");
!           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
!           fprintf (file, "\n");
!           fprintf (file, "0:\t.long  ");
!           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));
!           fprintf (file, "\n");
!         }
!     }
!   else
!     {
!       if (flag_pic)
!         {
!           fprintf (file, "\tbras  1,0f\n");
!           fprintf (file, "\t.long _GLOBAL_OFFSET_TABLE_-.\n");
!           fprintf (file, "\t.long  ");
!           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
!           fprintf (file, "@GOT\n");
!           fprintf (file, "\t.long  ");
!           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));
!           fprintf (file, "\n");
!           fprintf (file, "0:\tal  %d,8(1)\n",
!                    aggregate_value_p (TREE_TYPE
!                                       (TREE_TYPE (function))) ? 3 : 2 );
!           fprintf (file, "\tl     0,4(1)\n");
!           fprintf (file, "\tal    1,0(1)\n");
!           fprintf (file, "\talr   1,0\n");
!           fprintf (file, "\tl     1,0(1)\n");
!           fprintf (file, "\tbr    1\n");
!         } else {
!           fprintf (file, "\tbras  1,0f\n");
!           fprintf (file, "\t.long  ");
!           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
!           fprintf (file, "-.\n");
!           fprintf (file, "\t.long  ");
!           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));
!           fprintf (file, "\n");
!           fprintf (file, "0:\tal  %d,4(1)\n",
!                    aggregate_value_p (TREE_TYPE
!                                       (TREE_TYPE (function))) ? 3 : 2 );
!           fprintf (file, "\tal    1,0(1)\n");
!           fprintf (file, "\tbr    1\n");
!        }
!     }
  }
--- 5588,5787 ----
      }
  }

+ /* Output thunk to FILE that implements a C++ virtual function call (with
+    multiple inheritance) to FUNCTION.  The thunk adjusts the this pointer
+    by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment
+    stored at VCALL_OFFSET in the vtable whose address is located at offset 0
+    relative to the resulting this pointer.  */
+
  static void
! s390_output_mi_vcall_thunk (file, thunk, delta, vcall_offset, function)
       FILE *file;
       tree thunk ATTRIBUTE_UNUSED;
       HOST_WIDE_INT delta;
+      HOST_WIDE_INT vcall_offset;
       tree function;
  {
!   rtx op[9];
!
!   /* Operand 0 is the target function.  */
!   op[0] = XEXP (DECL_RTL (function), 0);
!   if (flag_pic && !SYMBOL_REF_FLAG (op[0]))
!     {
!       op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]), 113);
!       op[0] = gen_rtx_CONST (Pmode, op[0]);
!     }
!
!   /* Operand 1 is the 'this' pointer.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
!     op[1] = gen_rtx_REG (Pmode, 3);
!   else
!     op[1] = gen_rtx_REG (Pmode, 2);
!
!   /* Operand 2 is the delta.  */
!   op[2] = GEN_INT (delta);
!
!   /* Operand 3 is the vcall_offset.  */
!   op[3] = GEN_INT (vcall_offset);
!
!   /* Operand 4 is the temporary register.  */
!   op[4] = gen_rtx_REG (Pmode, 1);
!
!   /* Operands 5 to 8 can be used as labels.  */
!   op[5] = NULL_RTX;
!   op[6] = NULL_RTX;
!   op[7] = NULL_RTX;
!   op[8] = NULL_RTX;
!
!   /* Generate code.  */
!   if (TARGET_64BIT)
!     {
!       /* Setup literal pool pointer if required.  */
!       if (!CONST_OK_FOR_LETTER_P (delta, 'K')
!       || !CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
!     {
!       op[5] = gen_label_rtx ();
!       output_asm_insn ("larl\t%4,%5", op);
!     }
!
!       /* Add DELTA to this pointer.  */
!       if (delta)
!     {
!       if (CONST_OK_FOR_LETTER_P (delta, 'J'))
!         output_asm_insn ("la\t%1,%2(%1)", op);
!       else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
!         output_asm_insn ("aghi\t%1,%2", op);
!       else
!         {
!           op[6] = gen_label_rtx ();
!           output_asm_insn ("agf\t%1,%6-%5(%4)", op);
!         }
!     }
!
!       /* Perform vcall adjustment.  */
!       if (vcall_offset)
!     {
!       if (CONST_OK_FOR_LETTER_P (vcall_offset, 'J'))
!         {
!           output_asm_insn ("lg\t%4,0(%1)", op);
!           output_asm_insn ("ag\t%1,%3(%4)", op);
!         }
!       else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
!         {
!           output_asm_insn ("lghi\t%4,%3", op);
!           output_asm_insn ("ag\t%4,0(%1)", op);
!           output_asm_insn ("ag\t%1,0(%4)", op);
!         }
!       else
!         {
!           op[7] = gen_label_rtx ();
!           output_asm_insn ("llgf\t%4,%7-%5(%4)", op);
!           output_asm_insn ("ag\t%4,0(%1)", op);
!           output_asm_insn ("ag\t%1,0(%4)", op);
!         }
!     }
!
!       /* Jump to target.  */
!       output_asm_insn ("jg\t%0", op);
!
!       /* Output literal pool if required.  */
!       if (op[5])
!     {
!       output_asm_insn (".align\t4", op);
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
!     }
!       if (op[6])
!     {
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
!       output_asm_insn (".long\t%2", op);
!     }
!       if (op[7])
!     {
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[7]));
!       output_asm_insn (".long\t%3", op);
!     }
!     }
!   else
!     {
!       /* Setup base pointer if required.  */
!       if (!vcall_offset
!       || !CONST_OK_FOR_LETTER_P (delta, 'K')
!       || !CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
!     {
!       op[5] = gen_label_rtx ();
!       output_asm_insn ("basr\t%4,0", op);
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
!     }
!
!       /* Add DELTA to this pointer.  */
!       if (delta)
!     {
!       if (CONST_OK_FOR_LETTER_P (delta, 'J'))
!         output_asm_insn ("la\t%1,%2(%1)", op);
!       else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
!         output_asm_insn ("ahi\t%1,%2", op);
!       else
!         {
!           op[6] = gen_label_rtx ();
!           output_asm_insn ("a\t%1,%6-%5(%4)", op);
!         }
!     }
!
!       /* Perform vcall adjustment.  */
!       if (vcall_offset)
!         {
!       if (CONST_OK_FOR_LETTER_P (vcall_offset, 'J'))
!         {
!           output_asm_insn ("lg\t%4,0(%1)", op);
!           output_asm_insn ("a\t%1,%3(%4)", op);
!         }
!       else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
!         {
!           output_asm_insn ("lhi\t%4,%3", op);
!           output_asm_insn ("a\t%4,0(%1)", op);
!           output_asm_insn ("a\t%1,0(%4)", op);
!         }
!       else
!         {
!           op[7] = gen_label_rtx ();
!           output_asm_insn ("l\t%4,%7-%5(%4)", op);
!           output_asm_insn ("a\t%4,0(%1)", op);
!           output_asm_insn ("a\t%1,0(%4)", op);
!         }
!
!       /* We had to clobber the base pointer register.
!          Re-setup the base pointer (with a different base).  */
!       op[5] = gen_label_rtx ();
!       output_asm_insn ("basr\t%4,0", op);
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
!     }
!
!       /* Jump to target.  */
!       op[8] = gen_label_rtx ();
!       if (!flag_pic)
!     output_asm_insn ("l\t%4,%8-%5(%4)", op);
!       else
!     output_asm_insn ("a\t%4,%8-%5(%4)", op);
!       output_asm_insn ("br\t%4", op);
!
!       /* Output literal pool.  */
!       output_asm_insn (".align\t4", op);
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[8]));
!       if (!flag_pic)
!     output_asm_insn (".long\t%0", op);
!       else
!     output_asm_insn (".long\t%0-%5", op);
!
!       if (op[6])
!     {
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
!       output_asm_insn (".long\t%2", op);
!     }
!       if (op[7])
!     {
!       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[7]));
!       output_asm_insn (".long\t%3", op);
!     }
!     }
  }
+

Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]