Re: [ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-08-30 Thread Kyrill Tkachov



On 8/29/19 4:36 PM, Christophe Lyon wrote:

On 31/07/2019 16:44, Christophe Lyon wrote:

On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov
 wrote:



On 7/16/19 12:18 PM, Kyrill Tkachov wrote:

Hi Christophe

On 5/15/19 1:39 PM, Christophe Lyon wrote:

In FDPIC mode, the trampoline generated to support pointers to nested
functions looks like:

    .word trampoline address
    .word trampoline GOT address
    ldr    r12, [pc, #8]
    ldr    r9, [pc, #8]
    ldr   pc, [pc, #8]
    .word static chain value
    .word GOT address
    .word function's address

because in FDPIC function pointers are actually pointers to function
descriptors, we have to actually generate a function descriptor for
the trampoline.

2019-XX-XX  Christophe Lyon 
 Mickaël Guêné 

 gcc/
 * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
 support.
 (arm_trampoline_init): Likewise.
 (arm_trampoline_init): Likewise.
 * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.

Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 40e3f3b..99d13bf 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
 .word static chain value
 .word function's address
 XXX FIXME: When the trampoline returns, r8 will be 
clobbered.  */

+/* In FDPIC mode, the trampoline looks like:
+  .word trampoline address
+  .word trampoline GOT address
+  ldr    r12, [pc, #8] ; #4 for Thumb2
+  ldr    r9,  [pc, #8] ; #4 for Thumb2
+  ldr   pc,  [pc, #8] ; #4 for Thumb2
+  .word static chain value
+  .word GOT address
+  .word function's address
+*/



I think this comment is not right for Thumb2.

These load instructionshave 32-bit encodings, even in Thumb2 (they use
high registers).


Andre and Wilco pointed out to me offline that the offset should be #4
for Arm mode.

The Arm ARM at E1.2.3 says:

PC, the program counter

* When executing an A32 instruction, PC reads as the address of the
current instruction plus 8.

* When executing a T32 instruction, PC reads as the address of the
current instruction plus 4.



Yes, it looks like the code is right, and the comment is wrong:
- offset 8 for thumb2 mode
- offset 4 for arm mode


Here is the updated version

Ok with a fixed ChangeLog (it currently mentions arm_trampoline_init 
twice but doesn't mention arm_trampoline_adjust_address)


Thanks,

Kyrill



Thanks,

Christophe


Thanks,

Kyrill




Also, please merge this comment with the one above (no separate /**/)



  static void
  arm_asm_trampoline_template (FILE *f)
  {
    fprintf (f, "\t.syntax unified\n");

-  if (TARGET_ARM)
+  if (TARGET_FDPIC)
+    {
+  /* The first two words are a function descriptor pointing 
to the

+    trampoline code just below.  */
+  if (TARGET_ARM)
+   fprintf (f, "\t.arm\n");
+  else if (TARGET_THUMB2)
+   fprintf (f, "\t.thumb\n");
+  else
+   /* Only ARM and Thumb-2 are supported.  */
+   gcc_unreachable ();
+
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  /* Trampoline code which sets the static chain register but 
also

+    PIC register before jumping into real code. */
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  STATIC_CHAIN_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PC_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);



As above, I think the offset should be 8 for both Arm and Thumb2.

Thanks,

Kyrill



+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+    }
+  else if (TARGET_ARM)
  {
    fprintf (f, "\t.arm\n");
    asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM,
PC_REGNUM);
@@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree 
fndecl,

rtx chain_value)
    emit_block_move (m_tramp, assemble_trampoline_template (),
 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
-  emit_move_insn (mem, chain_value);
+  if (TARGET_FDPIC)
+    {
+  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
+  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode,
funcdesc, 4));
+  /* The function start address is at offset 8, but in Thumb 
mode

+    we want bit 0 set to 1 to indicate Thumb-ness, hence 9
+    below.  */
+  rtx trampoline_code_start
+   = plus_constant (Pmode, XEXP 

Re: [ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-08-29 Thread Christophe Lyon

On 31/07/2019 16:44, Christophe Lyon wrote:

On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov
 wrote:



On 7/16/19 12:18 PM, Kyrill Tkachov wrote:

Hi Christophe

On 5/15/19 1:39 PM, Christophe Lyon wrote:

In FDPIC mode, the trampoline generated to support pointers to nested
functions looks like:

.word trampoline address
.word trampoline GOT address
ldrr12, [pc, #8]
ldrr9, [pc, #8]
ldr   pc, [pc, #8]
.word static chain value
.word GOT address
.word function's address

because in FDPIC function pointers are actually pointers to function
descriptors, we have to actually generate a function descriptor for
the trampoline.

2019-XX-XX  Christophe Lyon 
 Mickaël Guêné 

 gcc/
 * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
 support.
 (arm_trampoline_init): Likewise.
 (arm_trampoline_init): Likewise.
 * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.

Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 40e3f3b..99d13bf 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
 .word static chain value
 .word function's address
 XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
+/* In FDPIC mode, the trampoline looks like:
+  .word trampoline address
+  .word trampoline GOT address
+  ldrr12, [pc, #8] ; #4 for Thumb2
+  ldrr9,  [pc, #8] ; #4 for Thumb2
+  ldr   pc,  [pc, #8] ; #4 for Thumb2
+  .word static chain value
+  .word GOT address
+  .word function's address
+*/



I think this comment is not right for Thumb2.

These load instructionshave 32-bit encodings, even in Thumb2 (they use
high registers).


Andre and Wilco pointed out to me offline that the offset should be #4
for Arm mode.

The Arm ARM at E1.2.3 says:

PC, the program counter

* When executing an A32 instruction, PC reads as the address of the
current instruction plus 8.

* When executing a T32 instruction, PC reads as the address of the
current instruction plus 4.



Yes, it looks like the code is right, and the comment is wrong:
- offset 8 for thumb2 mode
- offset 4 for arm mode


Here is the updated version


Thanks,

Christophe


Thanks,

Kyrill




Also, please merge this comment with the one above (no separate /**/)



  static void
  arm_asm_trampoline_template (FILE *f)
  {
fprintf (f, "\t.syntax unified\n");

-  if (TARGET_ARM)
+  if (TARGET_FDPIC)
+{
+  /* The first two words are a function descriptor pointing to the
+trampoline code just below.  */
+  if (TARGET_ARM)
+   fprintf (f, "\t.arm\n");
+  else if (TARGET_THUMB2)
+   fprintf (f, "\t.thumb\n");
+  else
+   /* Only ARM and Thumb-2 are supported.  */
+   gcc_unreachable ();
+
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  /* Trampoline code which sets the static chain register but also
+PIC register before jumping into real code. */
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  STATIC_CHAIN_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PC_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);



As above, I think the offset should be 8 for both Arm and Thumb2.

Thanks,

Kyrill



+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+}
+  else if (TARGET_ARM)
  {
fprintf (f, "\t.arm\n");
asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM,
PC_REGNUM);
@@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree fndecl,
rtx chain_value)
emit_block_move (m_tramp, assemble_trampoline_template (),
 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
-  emit_move_insn (mem, chain_value);
+  if (TARGET_FDPIC)
+{
+  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
+  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode,
funcdesc, 4));
+  /* The function start address is at offset 8, but in Thumb mode
+we want bit 0 set to 1 to indicate Thumb-ness, hence 9
+below.  */
+  rtx trampoline_code_start
+   = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9

: 8);

+
+  /* Write initial funcdesc which points to the trampoline.  */
+  mem = adjust_address (m_tramp, SImode, 0);
+  emit_move_insn (mem, 

Re: [ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-07-31 Thread Christophe Lyon
On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov
 wrote:
>
>
> On 7/16/19 12:18 PM, Kyrill Tkachov wrote:
> > Hi Christophe
> >
> > On 5/15/19 1:39 PM, Christophe Lyon wrote:
> > > In FDPIC mode, the trampoline generated to support pointers to nested
> > > functions looks like:
> > >
> > >.word trampoline address
> > >.word trampoline GOT address
> > >ldrr12, [pc, #8]
> > >ldrr9, [pc, #8]
> > >ldr   pc, [pc, #8]
> > >.word static chain value
> > >.word GOT address
> > >.word function's address
> > >
> > > because in FDPIC function pointers are actually pointers to function
> > > descriptors, we have to actually generate a function descriptor for
> > > the trampoline.
> > >
> > > 2019-XX-XX  Christophe Lyon 
> > > Mickaël Guêné 
> > >
> > > gcc/
> > > * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
> > > support.
> > > (arm_trampoline_init): Likewise.
> > > (arm_trampoline_init): Likewise.
> > > * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.
> > >
> > > Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144
> > >
> > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> > > index 40e3f3b..99d13bf 100644
> > > --- a/gcc/config/arm/arm.c
> > > +++ b/gcc/config/arm/arm.c
> > > @@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
> > > .word static chain value
> > > .word function's address
> > > XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
> > > +/* In FDPIC mode, the trampoline looks like:
> > > +  .word trampoline address
> > > +  .word trampoline GOT address
> > > +  ldrr12, [pc, #8] ; #4 for Thumb2
> > > +  ldrr9,  [pc, #8] ; #4 for Thumb2
> > > +  ldr   pc,  [pc, #8] ; #4 for Thumb2
> > > +  .word static chain value
> > > +  .word GOT address
> > > +  .word function's address
> > > +*/
> >
> >
> > I think this comment is not right for Thumb2.
> >
> > These load instructionshave 32-bit encodings, even in Thumb2 (they use
> > high registers).
>
> Andre and Wilco pointed out to me offline that the offset should be #4
> for Arm mode.
>
> The Arm ARM at E1.2.3 says:
>
> PC, the program counter
>
> * When executing an A32 instruction, PC reads as the address of the
> current instruction plus 8.
>
> * When executing a T32 instruction, PC reads as the address of the
> current instruction plus 4.
>

Yes, it looks like the code is right, and the comment is wrong:
- offset 8 for thumb2 mode
- offset 4 for arm mode

Thanks,

Christophe

> Thanks,
>
> Kyrill
>
>
> >
> > Also, please merge this comment with the one above (no separate /**/)
> >
> > >
> > >  static void
> > >  arm_asm_trampoline_template (FILE *f)
> > >  {
> > >fprintf (f, "\t.syntax unified\n");
> > >
> > > -  if (TARGET_ARM)
> > > +  if (TARGET_FDPIC)
> > > +{
> > > +  /* The first two words are a function descriptor pointing to the
> > > +trampoline code just below.  */
> > > +  if (TARGET_ARM)
> > > +   fprintf (f, "\t.arm\n");
> > > +  else if (TARGET_THUMB2)
> > > +   fprintf (f, "\t.thumb\n");
> > > +  else
> > > +   /* Only ARM and Thumb-2 are supported.  */
> > > +   gcc_unreachable ();
> > > +
> > > +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> > > +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> > > +  /* Trampoline code which sets the static chain register but also
> > > +PIC register before jumping into real code. */
> > > +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> > > +  STATIC_CHAIN_REGNUM, PC_REGNUM,
> > > +  TARGET_THUMB2 ? 8 : 4);
> > > +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> > > +  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
> > > +  TARGET_THUMB2 ? 8 : 4);
> > > +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> > > +  PC_REGNUM, PC_REGNUM,
> > > +  TARGET_THUMB2 ? 8 : 4);
> >
> >
> > As above, I think the offset should be 8 for both Arm and Thumb2.
> >
> > Thanks,
> >
> > Kyrill
> >
> >
> > > +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> > > +}
> > > +  else if (TARGET_ARM)
> > >  {
> > >fprintf (f, "\t.arm\n");
> > >asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM,
> > > PC_REGNUM);
> > > @@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree fndecl,
> > > rtx chain_value)
> > >emit_block_move (m_tramp, assemble_trampoline_template (),
> > > GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
> > >
> > > -  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
> > > -  emit_move_insn (mem, chain_value);
> > > +  if (TARGET_FDPIC)
> > > +{
> > > +  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
> > > +

Re: [ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-07-16 Thread Kyrill Tkachov



On 7/16/19 12:18 PM, Kyrill Tkachov wrote:

Hi Christophe

On 5/15/19 1:39 PM, Christophe Lyon wrote:
> In FDPIC mode, the trampoline generated to support pointers to nested
> functions looks like:
>
>    .word trampoline address
>    .word trampoline GOT address
>    ldr    r12, [pc, #8]
>    ldr    r9, [pc, #8]
>    ldr   pc, [pc, #8]
>    .word static chain value
>    .word GOT address
>    .word function's address
>
> because in FDPIC function pointers are actually pointers to function
> descriptors, we have to actually generate a function descriptor for
> the trampoline.
>
> 2019-XX-XX  Christophe Lyon 
>     Mickaël Guêné 
>
>     gcc/
>     * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
>     support.
>     (arm_trampoline_init): Likewise.
>     (arm_trampoline_init): Likewise.
>     * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.
>
> Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144
>
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 40e3f3b..99d13bf 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
>     .word static chain value
>     .word function's address
>     XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
> +/* In FDPIC mode, the trampoline looks like:
> +  .word trampoline address
> +  .word trampoline GOT address
> +  ldr    r12, [pc, #8] ; #4 for Thumb2
> +  ldr    r9,  [pc, #8] ; #4 for Thumb2
> +  ldr   pc,  [pc, #8] ; #4 for Thumb2
> +  .word static chain value
> +  .word GOT address
> +  .word function's address
> +*/


I think this comment is not right for Thumb2.

These load instructionshave 32-bit encodings, even in Thumb2 (they use
high registers).


Andre and Wilco pointed out to me offline that the offset should be #4 
for Arm mode.


The Arm ARM at E1.2.3 says:

PC, the program counter

* When executing an A32 instruction, PC reads as the address of the 
current instruction plus 8.


* When executing a T32 instruction, PC reads as the address of the 
current instruction plus 4.


Thanks,

Kyrill




Also, please merge this comment with the one above (no separate /**/)

>
>  static void
>  arm_asm_trampoline_template (FILE *f)
>  {
>    fprintf (f, "\t.syntax unified\n");
>
> -  if (TARGET_ARM)
> +  if (TARGET_FDPIC)
> +    {
> +  /* The first two words are a function descriptor pointing to the
> +    trampoline code just below.  */
> +  if (TARGET_ARM)
> +   fprintf (f, "\t.arm\n");
> +  else if (TARGET_THUMB2)
> +   fprintf (f, "\t.thumb\n");
> +  else
> +   /* Only ARM and Thumb-2 are supported.  */
> +   gcc_unreachable ();
> +
> +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> +  /* Trampoline code which sets the static chain register but also
> +    PIC register before jumping into real code. */
> +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> +  STATIC_CHAIN_REGNUM, PC_REGNUM,
> +  TARGET_THUMB2 ? 8 : 4);
> +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> +  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
> +  TARGET_THUMB2 ? 8 : 4);
> +  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
> +  PC_REGNUM, PC_REGNUM,
> +  TARGET_THUMB2 ? 8 : 4);


As above, I think the offset should be 8 for both Arm and Thumb2.

Thanks,

Kyrill


> +  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
> +    }
> +  else if (TARGET_ARM)
>  {
>    fprintf (f, "\t.arm\n");
>    asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM,
> PC_REGNUM);
> @@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree fndecl,
> rtx chain_value)
>    emit_block_move (m_tramp, assemble_trampoline_template (),
>     GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
>
> -  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
> -  emit_move_insn (mem, chain_value);
> +  if (TARGET_FDPIC)
> +    {
> +  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
> +  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
> +  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode,
> funcdesc, 4));
> +  /* The function start address is at offset 8, but in Thumb mode
> +    we want bit 0 set to 1 to indicate Thumb-ness, hence 9
> +    below.  */
> +  rtx trampoline_code_start
> +   = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 
: 8);

> +
> +  /* Write initial funcdesc which points to the trampoline.  */
> +  mem = adjust_address (m_tramp, SImode, 0);
> +  emit_move_insn (mem, trampoline_code_start);
> +  mem = adjust_address (m_tramp, SImode, 4);
> +  emit_move_insn (mem, 

Re: [ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-07-16 Thread Kyrill Tkachov

Hi Christophe

On 5/15/19 1:39 PM, Christophe Lyon wrote:

In FDPIC mode, the trampoline generated to support pointers to nested
functions looks like:

   .word trampoline address
   .word trampoline GOT address
   ldr    r12, [pc, #8]
   ldr    r9, [pc, #8]
   ldr   pc, [pc, #8]
   .word static chain value
   .word GOT address
   .word function's address

because in FDPIC function pointers are actually pointers to function
descriptors, we have to actually generate a function descriptor for
the trampoline.

2019-XX-XX  Christophe Lyon  
    Mickaël Guêné 

    gcc/
    * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
    support.
    (arm_trampoline_init): Likewise.
    (arm_trampoline_init): Likewise.
    * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.

Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 40e3f3b..99d13bf 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
    .word static chain value
    .word function's address
    XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
+/* In FDPIC mode, the trampoline looks like:
+  .word trampoline address
+  .word trampoline GOT address
+  ldr    r12, [pc, #8] ; #4 for Thumb2
+  ldr    r9,  [pc, #8] ; #4 for Thumb2
+  ldr   pc,  [pc, #8] ; #4 for Thumb2
+  .word static chain value
+  .word GOT address
+  .word function's address
+*/



I think this comment is not right for Thumb2.

These load instructionshave 32-bit encodings, even in Thumb2 (they use 
high registers).


Also, please merge this comment with the one above (no separate /**/)



 static void
 arm_asm_trampoline_template (FILE *f)
 {
   fprintf (f, "\t.syntax unified\n");

-  if (TARGET_ARM)
+  if (TARGET_FDPIC)
+    {
+  /* The first two words are a function descriptor pointing to the
+    trampoline code just below.  */
+  if (TARGET_ARM)
+   fprintf (f, "\t.arm\n");
+  else if (TARGET_THUMB2)
+   fprintf (f, "\t.thumb\n");
+  else
+   /* Only ARM and Thumb-2 are supported.  */
+   gcc_unreachable ();
+
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  /* Trampoline code which sets the static chain register but also
+    PIC register before jumping into real code.  */
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  STATIC_CHAIN_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PC_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);



As above, I think the offset should be 8 for both Arm and Thumb2.

Thanks,

Kyrill



+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+    }
+  else if (TARGET_ARM)
 {
   fprintf (f, "\t.arm\n");
   asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, 
PC_REGNUM);
@@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree fndecl, 
rtx chain_value)

   emit_block_move (m_tramp, assemble_trampoline_template (),
    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
-  emit_move_insn (mem, chain_value);
+  if (TARGET_FDPIC)
+    {
+  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
+  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode, 
funcdesc, 4));

+  /* The function start address is at offset 8, but in Thumb mode
+    we want bit 0 set to 1 to indicate Thumb-ness, hence 9
+    below.  */
+  rtx trampoline_code_start
+   = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8);
+
+  /* Write initial funcdesc which points to the trampoline.  */
+  mem = adjust_address (m_tramp, SImode, 0);
+  emit_move_insn (mem, trampoline_code_start);
+  mem = adjust_address (m_tramp, SImode, 4);
+  emit_move_insn (mem, gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
+  /* Setup static chain.  */
+  mem = adjust_address (m_tramp, SImode, 20);
+  emit_move_insn (mem, chain_value);
+  /* GOT + real function entry point.  */
+  mem = adjust_address (m_tramp, SImode, 24);
+  emit_move_insn (mem, gotaddr);
+  mem = adjust_address (m_tramp, SImode, 28);
+  emit_move_insn (mem, fnaddr);
+    }
+  else
+    {
+  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
+  emit_move_insn (mem, chain_value);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
-  

[ARM/FDPIC v5 09/21] [ARM] FDPIC: Add support for taking address of nested function

2019-05-15 Thread Christophe Lyon
In FDPIC mode, the trampoline generated to support pointers to nested
functions looks like:

   .wordtrampoline address
   .wordtrampoline GOT address
   ldr  r12, [pc, #8]
   ldr  r9, [pc, #8]
   ldr  pc, [pc, #8]
   .wordstatic chain value
   .wordGOT address
   .wordfunction's address

because in FDPIC function pointers are actually pointers to function
descriptors, we have to actually generate a function descriptor for
the trampoline.

2019-XX-XX  Christophe Lyon  
Mickaël Guêné 

gcc/
* config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
support.
(arm_trampoline_init): Likewise.
(arm_trampoline_init): Likewise.
* config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.

Change-Id: Idc4d5f629ae4f8d79bdf9623517481d524a0c144

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 40e3f3b..99d13bf 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3976,13 +3976,50 @@ arm_warn_func_return (tree decl)
   .wordstatic chain value
   .wordfunction's address
XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
+/* In FDPIC mode, the trampoline looks like:
+  .wordtrampoline address
+  .wordtrampoline GOT address
+  ldr  r12, [pc, #8] ; #4 for Thumb2
+  ldr  r9,  [pc, #8] ; #4 for Thumb2
+  ldr  pc,  [pc, #8] ; #4 for Thumb2
+  .wordstatic chain value
+  .wordGOT address
+  .wordfunction's address
+*/
 
 static void
 arm_asm_trampoline_template (FILE *f)
 {
   fprintf (f, "\t.syntax unified\n");
 
-  if (TARGET_ARM)
+  if (TARGET_FDPIC)
+{
+  /* The first two words are a function descriptor pointing to the
+trampoline code just below.  */
+  if (TARGET_ARM)
+   fprintf (f, "\t.arm\n");
+  else if (TARGET_THUMB2)
+   fprintf (f, "\t.thumb\n");
+  else
+   /* Only ARM and Thumb-2 are supported.  */
+   gcc_unreachable ();
+
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+  /* Trampoline code which sets the static chain register but also
+PIC register before jumping into real code.  */
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  STATIC_CHAIN_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+  PC_REGNUM, PC_REGNUM,
+  TARGET_THUMB2 ? 8 : 4);
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+}
+  else if (TARGET_ARM)
 {
   fprintf (f, "\t.arm\n");
   asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, PC_REGNUM);
@@ -4023,12 +4060,40 @@ arm_trampoline_init (rtx m_tramp, tree fndecl, rtx 
chain_value)
   emit_block_move (m_tramp, assemble_trampoline_template (),
   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
 
-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
-  emit_move_insn (mem, chain_value);
+  if (TARGET_FDPIC)
+{
+  rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
+  rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+  rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode, funcdesc, 4));
+  /* The function start address is at offset 8, but in Thumb mode
+we want bit 0 set to 1 to indicate Thumb-ness, hence 9
+below.  */
+  rtx trampoline_code_start
+   = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8);
+
+  /* Write initial funcdesc which points to the trampoline.  */
+  mem = adjust_address (m_tramp, SImode, 0);
+  emit_move_insn (mem, trampoline_code_start);
+  mem = adjust_address (m_tramp, SImode, 4);
+  emit_move_insn (mem, gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
+  /* Setup static chain.  */
+  mem = adjust_address (m_tramp, SImode, 20);
+  emit_move_insn (mem, chain_value);
+  /* GOT + real function entry point.  */
+  mem = adjust_address (m_tramp, SImode, 24);
+  emit_move_insn (mem, gotaddr);
+  mem = adjust_address (m_tramp, SImode, 28);
+  emit_move_insn (mem, fnaddr);
+}
+  else
+{
+  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
+  emit_move_insn (mem, chain_value);
 
-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
-  fnaddr = XEXP (DECL_RTL (fndecl), 0);
-  emit_move_insn (mem, fnaddr);
+  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
+  fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  emit_move_insn (mem, fnaddr);
+}
 
   a_tramp = XEXP (m_tramp, 0);
   emit_library_call