Ian Lance Taylor schrieb:
Georg-Johann Lay <avr@xxxxxxxx> 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
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
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