This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
S/390: Enable vcall thunks
- From: "Ulrich Weigand" <Ulrich dot Weigand at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 21 Oct 2002 17:30:39 +0200
- Subject: S/390: Enable vcall thunks
- Sensitivity:
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