public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes  problems.
@ 2009-04-29 14:34 Georg-Johann Lay
  2009-04-29 15:57 ` Ian Lance Taylor
  0 siblings, 1 reply; 7+ messages in thread
From: Georg-Johann Lay @ 2009-04-29 14:34 UTC (permalink / raw)
  To: gcc-help

Hi, I am working on a GCC 4.3.3 port for a 32-bit architecture.

The machine has dedicated data (D) resp. address (A) registers.

A function shall pass addresses in A-registers and other stuff in 
D-registers, Pmode = SImode.

Everything works fine except that for libcalls the target macros 
FUNCTION_ARG, FUNCTION_ARG_ADVANCE, TARGET_PASS_BY_REFERENCE et al. are 
called with TYPE=NULL_TREE, so that is is not possible to destinguish 
between pointers and non-pointers.

If the call of memmove is done explicitely from the C source, then there 
is a prototype and TYPE!=NULL_TREE so that I can provide correct 
behaviour for the target hooks mentioned above.

But, if memmove is called implicitely to copy function args like large 
structs that are passed in memory, then TYPE==NULL_TREE and the hooks 
have no information about what they have to do. Neigher choosing an 
A-reg not choosing a D-reg will yield a consistend calling conventions 
in every case.

Did I miss something? Is there a way to retrieve the necessary 
information without hacking calls.c, function.c, etc?

Why is this essential information cancelled in calls.c?
Obviously, calls.c has that information but hides it from the backend.

I do not consider to introduce Pmode = PSImode because that would result 
in an exact clone of the SImode support in the backend.

Thanks for any hints,

Georg-Johann

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes  problems.
  2009-04-29 14:34 [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes problems Georg-Johann Lay
@ 2009-04-29 15:57 ` Ian Lance Taylor
  2009-04-29 17:20   ` Georg-Johann Lay
  2009-04-30  9:29   ` Richard Earnshaw
  0 siblings, 2 replies; 7+ messages in thread
From: Ian Lance Taylor @ 2009-04-29 15:57 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc-help

Georg-Johann Lay <avr@gjlay.de> writes:

> A function shall pass addresses in A-registers and other stuff in
> D-registers, Pmode = SImode.

How do varargs functions work?


> Everything works fine except that for libcalls the target macros
> FUNCTION_ARG, FUNCTION_ARG_ADVANCE, TARGET_PASS_BY_REFERENCE et
> al. are called with TYPE=NULL_TREE, so that is is not possible to
> destinguish between pointers and non-pointers.
>
> If the call of memmove is done explicitely from the C source, then
> there is a prototype and TYPE!=NULL_TREE so that I can provide correct
> behaviour for the target hooks mentioned above.
>
> But, if memmove is called implicitely to copy function args like large
> structs that are passed in memory, then TYPE==NULL_TREE and the hooks
> have no information about what they have to do. Neigher choosing an
> A-reg not choosing a D-reg will yield a consistend calling conventions
> in every case.
>
> Did I miss something? Is there a way to retrieve the necessary
> information without hacking calls.c, function.c, etc?
>
> Why is this essential information cancelled in calls.c?
> Obviously, calls.c has that information but hides it from the backend.

Yours is the first processor I have heard of which uses this sort of
calling convention.  Differentiating on the basis of integer
vs. floating point is common, on the basis of integer vs. pointer is
not.  I can see that you have a problem, but I'm not surprised that gcc
does not already address it.  You are going to have to figure out what
is required to make it work.  Modifying libcalls to be more like
ordinary functions sounds like a good approach; it is one that gcc has
been following, very slowly, for many years.

Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes   problems.
  2009-04-29 15:57 ` Ian Lance Taylor
@ 2009-04-29 17:20   ` Georg-Johann Lay
  2009-04-29 17:31     ` Ian Lance Taylor
  2009-04-30  9:29   ` Richard Earnshaw
  1 sibling, 1 reply; 7+ messages in thread
From: Georg-Johann Lay @ 2009-04-29 17:20 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help

[-- Attachment #1: Type: text/plain, Size: 3021 bytes --]

Ian Lance Taylor schrieb:

> Georg-Johann Lay <avr@gjlay.de> writes:
> 
>> A function shall pass addresses in A-registers and other stuff in
>> D-registers, Pmode = SImode.
> 
> How do varargs functions work?

Named arguments are passed as explained, and the unnamed ... portion 
will be passed in memory. Perhapy everything will be passed via memory. 
The ABI is in the flow as is the ISA, because there is no silicon 
available yet.

For every function that is called from source level there must ba a 
prototype. If there is no prototype for a called function, the behaviour 
is unspecified.

>> Everything works fine except that for libcalls the target macros
>> FUNCTION_ARG, FUNCTION_ARG_ADVANCE, TARGET_PASS_BY_REFERENCE et
>> al. are called with TYPE=NULL_TREE, so that is is not possible to
>> destinguish between pointers and non-pointers.
>>
>> If the call of memmove is done explicitely from the C source, then
>> there is a prototype and TYPE!=NULL_TREE so that I can provide correct
>> behaviour for the target hooks mentioned above.
>>
>> But, if memmove is called implicitely to copy function args like large
>> structs that are passed in memory, then TYPE==NULL_TREE and the hooks
>> have no information about what they have to do. Neigher choosing an
>> A-reg not choosing a D-reg will yield a consistend calling conventions
>> in every case.
>>
>> Did I miss something? Is there a way to retrieve the necessary
>> information without hacking calls.c, function.c, etc?
>>
>> Why is this essential information cancelled in calls.c?
>> Obviously, calls.c has that information but hides it from the backend.
> 
> Yours is the first processor I have heard of which uses this sort of
> calling convention.  Differentiating on the basis of integer
> vs. floating point is common, on the basis of integer vs. pointer is
> not.  I can see that you have a problem, but I'm not surprised that gcc
> does not already address it.  You are going to have to figure out what
> is required to make it work.  Modifying libcalls to be more like
> ordinary functions sounds like a good approach; it is one that gcc has
> been following, very slowly, for many years.

Several years ago -- before my time -- my company made a port for 
Infineon TriCore. It works and is about to be SIL sertified. It uses a 
similar ABI. I attached the patches. That are not very much changes, but 
I don't like this kind of hacks and would prefer very much to keep the 
frontend/middleend clean of backend issues.

Unfortunately, the TriCore is not an official port (not my decision) and 
will never be a part of the official GCC because it contains many 
non-standard hacks some customers payed for (bad idea, but it is/was not 
my decision to implement hacks-for-money). Moreover, we simply don't 
have the manpower to consider going into such a direction (again, not my 
decision)...

At what place would you recommend to make such changes?

I intend to keep all of the port in the backend, in the place where it 
belongs.

Georg-Johann

[-- Attachment #2: function.c-diff-1.1-1.2 --]
[-- Type: text/plain, Size: 1091 bytes --]

Index: function.c
===================================================================
RCS file: /data/CVS_Archive/gnu/gcc-3.4.5/gcc/function.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- function.c	13 Dec 2005 09:17:00 -0000	1.1
+++ function.c	9 Jan 2006 14:06:11 -0000	1.2
@@ -6831,11 +6831,11 @@
       else
 	abort ();
       emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode,
-			 2, fun, Pmode,
+			 2, fun, Pmode, ptr_type_node, 
 			 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
 						     0,
 						     hard_frame_pointer_rtx),
-			 Pmode);
+			 Pmode, ptr_type_node);
     }
 
   if (current_function_profile)
@@ -7111,11 +7111,11 @@
       else
 	abort ();
       emit_library_call (profile_function_exit_libfunc, LCT_NORMAL, VOIDmode,
-			 2, fun, Pmode,
+			 2, fun, Pmode, ptr_type_node,
 			 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
 						     0,
 						     hard_frame_pointer_rtx),
-			 Pmode);
+			 Pmode, ptr_type_node);
     }
 
   /* Let except.c know where it should emit the call to unregister

[-- Attachment #3: calls.c-diff-1.1-1.2 --]
[-- Type: text/plain, Size: 2791 bytes --]

Index: calls.c
===================================================================
RCS file: /data/CVS_Archive/gnu/gcc-3.4.5/gcc/calls.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- calls.c	13 Dec 2005 09:17:03 -0000	1.1
+++ calls.c	9 Jan 2006 14:06:15 -0000	1.2
@@ -3856,9 +3856,9 @@
       argvec[count].mode = Pmode;
       argvec[count].partial = 0;
 
-      argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, NULL_TREE, 1);
+      argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, /*NULL_TREE*/ptr_type_node, 1);
 #ifdef FUNCTION_ARG_PARTIAL_NREGS
-      if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, Pmode, NULL_TREE, 1))
+      if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, Pmode, /*NULL_TREE*/ptr_type_node, 1))
 	abort ();
 #endif
 
@@ -3883,6 +3883,7 @@
     {
       rtx val = va_arg (p, rtx);
       enum machine_mode mode = va_arg (p, enum machine_mode);
+	  tree arg_type = va_arg(p,tree);
 
       /* We cannot convert the arg value to the mode the library wants here;
 	 must do it earlier where we know the signedness of the arg.  */
@@ -3899,13 +3900,13 @@
 	val = force_operand (val, NULL_RTX);
 
 #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
-      if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1))
+      if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, /*NULL_TREE*/arg_type, 1))
 	{
 	  rtx slot;
 	  int must_copy = 1
 #ifdef FUNCTION_ARG_CALLEE_COPIES
 	    && ! FUNCTION_ARG_CALLEE_COPIES (args_so_far, mode,
-					     NULL_TREE, 1)
+					     /*NULL_TREE*/arg_type, 1)
 #endif
 	    ;
 
@@ -3964,23 +3965,23 @@
       argvec[count].value = val;
       argvec[count].mode = mode;
 
-      argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
+      argvec[count].reg = FUNCTION_ARG (args_so_far, mode, /*NULL_TREE*/arg_type, 1);
 
 #ifdef FUNCTION_ARG_PARTIAL_NREGS
       argvec[count].partial
-	= FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1);
+	= FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, /*NULL_TREE*/arg_type, 1);
 #else
       argvec[count].partial = 0;
 #endif
 
-      locate_and_pad_parm (mode, NULL_TREE,
+      locate_and_pad_parm (mode, /*NULL_TREE*/arg_type,
 #ifdef STACK_PARMS_IN_REG_PARM_AREA
 			   1,
 #else
 			   argvec[count].reg != 0,
 #endif
 			   argvec[count].partial,
-			   NULL_TREE, &args_size, &argvec[count].locate);
+			   /*NULL_TREE*/arg_type, &args_size, &argvec[count].locate);
 
       if (argvec[count].locate.size.var)
 	abort ();
@@ -3989,7 +3990,7 @@
 	  || reg_parm_stack_space > 0)
 	args_size.constant += argvec[count].locate.size.constant;
 
-      FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
+      FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) /*NULL_TREE*/arg_type, 1);
     }
 
 #ifdef FINAL_REG_PARM_STACK_SPACE

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes problems.
  2009-04-29 17:20   ` Georg-Johann Lay
@ 2009-04-29 17:31     ` Ian Lance Taylor
  2009-04-30 11:05       ` Georg-Johann Lay
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Lance Taylor @ 2009-04-29 17:31 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc-help

Georg-Johann Lay <avr@gjlay.de> writes:

> Several years ago -- before my time -- my company made a port for
> Infineon TriCore. It works and is about to be SIL sertified. It uses a
> similar ABI. I attached the patches. That are not very much changes,
> but I don't like this kind of hacks and would prefer very much to keep
> the frontend/middleend clean of backend issues.

That is an admirable goal, but in this case I think you are going to
have to change the middle-end to make your port work.  I recommend that
you contribute the patches back to gcc mainline for the benefit of other
users.  Of course this will require a copyright assignment or
disclaimer.

The small patch you sent looks quite reasonable.

Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE  causes  problems.
  2009-04-29 15:57 ` Ian Lance Taylor
  2009-04-29 17:20   ` Georg-Johann Lay
@ 2009-04-30  9:29   ` Richard Earnshaw
  2009-04-30 11:38     ` Georg-Johann Lay
  1 sibling, 1 reply; 7+ messages in thread
From: Richard Earnshaw @ 2009-04-30  9:29 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Georg-Johann Lay, gcc-help

On Wed, 2009-04-29 at 08:57 -0700, Ian Lance Taylor wrote:
> > Everything works fine except that for libcalls the target macros
> > FUNCTION_ARG, FUNCTION_ARG_ADVANCE, TARGET_PASS_BY_REFERENCE et
> > al. are called with TYPE=NULL_TREE, so that is is not possible to
> > destinguish between pointers and non-pointers.
> >
> > If the call of memmove is done explicitely from the C source, then
> > there is a prototype and TYPE!=NULL_TREE so that I can provide correct
> > behaviour for the target hooks mentioned above.
> >
> > But, if memmove is called implicitely to copy function args like large
> > structs that are passed in memory, then TYPE==NULL_TREE and the hooks
> > have no information about what they have to do. Neigher choosing an
> > A-reg not choosing a D-reg will yield a consistend calling conventions
> > in every case.
> >
> > Did I miss something? Is there a way to retrieve the necessary
> > information without hacking calls.c, function.c, etc?
> >
> > Why is this essential information cancelled in calls.c?
> > Obviously, calls.c has that information but hides it from the backend.
> 
> Yours is the first processor I have heard of which uses this sort of
> calling convention.  Differentiating on the basis of integer
> vs. floating point is common, on the basis of integer vs. pointer is
> not.  I can see that you have a problem, but I'm not surprised that gcc
> does not already address it.  You are going to have to figure out what
> is required to make it work.  Modifying libcalls to be more like
> ordinary functions sounds like a good approach; it is one that gcc has
> been following, very slowly, for many years.

Hmm, the ARM port has something similar, which only comes to be
significant when the hard-float calling convention is implemented; in
this case, the calling convention for the ABI-specified support
functions remains unchanged even though the calling convention for
normal user calls can be different.  The trick is that you have to find
out exactly which libcall is being used, essentially by name matching.
You can look at what I've done for this on the ARM/hard_vfp_4_4_branch
in the GCC SVN repository.

It's unfortunate that GCC doesn't synthesise a type node for libcalls;
that would probably make things much simpler...

R.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes  problems.
  2009-04-29 17:31     ` Ian Lance Taylor
@ 2009-04-30 11:05       ` Georg-Johann Lay
  0 siblings, 0 replies; 7+ messages in thread
From: Georg-Johann Lay @ 2009-04-30 11:05 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help

Ian Lance Taylor schrieb:
> Georg-Johann Lay <avr@gjlay.de> writes:
> 
>> Several years ago -- before my time -- my company made a port for
>> Infineon TriCore. It works and is about to be SIL sertified. It uses a
>> similar ABI. I attached the patches. That are not very much changes,
>> but I don't like this kind of hacks and would prefer very much to keep
>> the frontend/middleend clean of backend issues.
> 
> That is an admirable goal, but in this case I think you are going to
> have to change the middle-end to make your port work.  I recommend that
> you contribute the patches back to gcc mainline for the benefit of other
> users.  Of course this will require a copyright assignment or
> disclaimer.
> 
> The small patch you sent looks quite reasonable.

I must admit that I don't like this bulk of micro-patches. They do not 
solve the very problem (no prototypes for support functions), may 
confuse some backends because TYPE is no more NULL_TREE for libfunc in 
FUNCTION_ARG et al., are beyond the backend's sandbox, and I am not sure 
if it fixes all combinations of target hooks/makros one can think of.

I am still waiting for my copyright assignment, maybe one day I will get 
  one... who knows.

For now I am simply using INIT_CUMULATIVE_ARGS 
(INIT_CUMULATIVE_LIBCALL_ARGS would do as well) and reconstruct the 
prototype from the function's name in libname rtx. As far as I can 
depict from libfuncs.h, only "memmove", "memcpy", "memset" and "memcmp" 
need to be reconstructed, maybe some parts of the non-local-goto/eh 
stuff, too.

The implementation is redundant as is recreates information which is 
present in some corner of the universe, but at least I need not touch 
the middle-end to get working code :-)

What I do not know is wether or not some optimizations use the return 
value of some support function in the case it is a pointer. What I can 
say is that TARGET_FUNCTION_VALUE is not called for the suppot functions 
I saw so far.

Georg-Johann

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [target.h] FUNCTION_ARG et al. called with type=NULL_TREE  causes   problems.
  2009-04-30  9:29   ` Richard Earnshaw
@ 2009-04-30 11:38     ` Georg-Johann Lay
  0 siblings, 0 replies; 7+ messages in thread
From: Georg-Johann Lay @ 2009-04-30 11:38 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Ian Lance Taylor, gcc-help

Richard Earnshaw schrieb:
> On Wed, 2009-04-29 at 08:57 -0700, Ian Lance Taylor wrote:
>>> Everything works fine except that for libcalls the target macros
>>> FUNCTION_ARG, FUNCTION_ARG_ADVANCE, TARGET_PASS_BY_REFERENCE et
>>> al. are called with TYPE=NULL_TREE, so that is is not possible to
>>> destinguish between pointers and non-pointers.
>>>
>>> If the call of memmove is done explicitely from the C source, then
>>> there is a prototype and TYPE!=NULL_TREE so that I can provide correct
>>> behaviour for the target hooks mentioned above.
>>>
>>> But, if memmove is called implicitely to copy function args like large
>>> structs that are passed in memory, then TYPE==NULL_TREE and the hooks
>>> have no information about what they have to do. Neigher choosing an
>>> A-reg not choosing a D-reg will yield a consistend calling conventions
>>> in every case.
>>>
>>> Did I miss something? Is there a way to retrieve the necessary
>>> information without hacking calls.c, function.c, etc?
>>>
>>> Why is this essential information cancelled in calls.c?
>>> Obviously, calls.c has that information but hides it from the backend.
>> Yours is the first processor I have heard of which uses this sort of
>> calling convention.  Differentiating on the basis of integer
>> vs. floating point is common, on the basis of integer vs. pointer is
>> not.  I can see that you have a problem, but I'm not surprised that gcc
>> does not already address it.  You are going to have to figure out what
>> is required to make it work.  Modifying libcalls to be more like
>> ordinary functions sounds like a good approach; it is one that gcc has
>> been following, very slowly, for many years.
> 
> Hmm, the ARM port has something similar, which only comes to be
> significant when the hard-float calling convention is implemented; in
> this case, the calling convention for the ABI-specified support
> functions remains unchanged even though the calling convention for
> normal user calls can be different.  The trick is that you have to find
> out exactly which libcall is being used, essentially by name matching.
> You can look at what I've done for this on the ARM/hard_vfp_4_4_branch
> in the GCC SVN repository.
> 
> It's unfortunate that GCC doesn't synthesise a type node for libcalls;
> that would probably make things much simpler...

Yes, definitely.
But optabs.c::init_one_libfunc() does not investigate in building a 
proper SYMBOL_REF_DECL. It just creates a dummy tree to set some flags 
like DECL_ARTIFICIAL and nullifies it afterwards. As a result, 
SYMBOL_REF_DECL(LIBNAME) is NULL_TREE in FUNCTION_ARG et al.

What I do not understand is how the ABI can be different, because the 
callee will expect the arguments in dedicated registers, regardless of 
who calls it and of wether or not the caller issues a user call or a 
support call.

As I read in
 
http://gcc.gnu.org/viewvc/branches/ARM/hard_vfp_4_4_branch/gcc/doc/tm.texi?r1=142586&r2=142592&diff_format=h
you solved the shortcomings of LIBCALL_VALUE, which are basically the 
same as these of FUNCTION_ARG* if the target has ptr_mode=word_mode :-)

Will this get into the next official 4.3.x release? I hope so!

Georg-Johann


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-04-30 11:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-29 14:34 [target.h] FUNCTION_ARG et al. called with type=NULL_TREE causes problems Georg-Johann Lay
2009-04-29 15:57 ` Ian Lance Taylor
2009-04-29 17:20   ` Georg-Johann Lay
2009-04-29 17:31     ` Ian Lance Taylor
2009-04-30 11:05       ` Georg-Johann Lay
2009-04-30  9:29   ` Richard Earnshaw
2009-04-30 11:38     ` Georg-Johann Lay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).