Article View: gnu.gcc.bug
Article #443GCC 1.39 bug report and suggestions
From: Andrew Cadach
Date: Thu, 16 Apr 1992 17:43
Date: Thu, 16 Apr 1992 17:43
351 lines
12291 bytes
12291 bytes
Dear sir!
Please, take my apologies wasting your time.
I'm trying to install GCC version 1.39 at Atari Mega ST2
computer with MC68000 CPU. I had some problems concerning such
fact that GCC itself is written in non-ANSI way.
The matter is that Turbo C compiler I used passes parameters
in registers and looks at type they have: `int', `char', etc.
are passed in d0-d2, pointers are passed in a0-a1. Sure you
know what could happen if compiler doesn't know the functions
prototypes. By the way I believe that pass to function wrong
number of parameters or unite in single array pointers to
functions with different kind and/or number of parameters in
hope that all parameters are passed by stack and there will no
any problems is not the best style of programming. In my case
it could just produce wrong code!
Another problem was following: compiler assumed `int' as
16-bits, and I've found several places where suggestion about
32-bits `int' was important. By the way, would you be so kind
and let me to put you some questions:
1. Why in functions, such as 'gen_rtx', 'gen_rtvec',
'emit_library_call', etc. which are need to be declared
as variable number of parameters functions, authers
supposed that all pushes at the stack will be right
aligned (i.e. 32-bits)?
2. Why authers of 'emit-rtl' supposed that 1st 32 bits of
`rtx' structure will contain ALL the flags (function
`rtx_alloc', which clears it), code and mode fields?
Some compilers could think otherwise...
And now about the bug itself.
When I've changed calling convention in GCC it starts to
produce wrong code. Compiling flags was following:
-O
-fdefer-pop
-fstrength-reduce
-fcombine-regs
-fforce-mem
-fforce-addr
-fomit-frame-pointer
-ffunction-cse
-fno-inline-functions
When I ran GCC with `-fno-function-cse' option, it produced
needed instruction (other's flags are the same as above).
Full source program and GCC output listed below.
---------------------------------------------------------
typedef int ar1[52];
typedef ar1 ar2[52];
void test(ar2 p, int n)
{
while ( ++p[n][n] );
}
---------------------------------------------------------
test:
movem.l D3-D4,-(SP)
move.l A0,D3
move.l D0,D4
asl.l #2,D4
move.l #208,D1
jsr (A0) ; suppose __mulsi3!!! a0 is undefined!!!
move.l D3,A0
add.l D0,A0
L2:
move.l (A0,D4.l),D0
move.l D0,D2
addq.l #1,D2
move.l D2,(A0,D4.l)
addq.l #1,D0
bne L2
movem.l (SP)+,D3-D4
rts
---------------------------------------------------------
I've changed following:
----------------------
/* file tm-m68k.h */
#define DEBUG_REGS 0x307 /* d0-d2/a0-a1 */
#define DEBUG_DREGS 3
#define DEBUG_AREGS 10 /* 8+2 */
#define CALL_USED_REGISTERS \
{1, 1, 1, 0, 0, 0, 0, 0, /* d0-d3 */ \
1, 1, 0, 0, 0, 0, 0, 1, /* a0-a1 */ \
1, 1, 0, 0, 0, 0, 0, 0, \
/* FPA registers. */ \
1, 1, 1, 1, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, }
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 8)
#define FUNCTION_ARG_REGNO_P(N) (DEBUG_REGS&(1<<(N))
void *fnc_value (void *type, void *func);
#define FUNCTION_VALUE(VALTYPE, FUNC)\
(fnc_value (VALTYPE, FUNC))
typedef struct
{
short
areg, /* how much address registers already occupied */
dreg, /* how much data registers already occupied */
cntp, /* incoming parameter counter */
parm; /* total number of named parameters or */
/* -1 for undeclared and library functions. */
/* We'll try to pass parameters according to */
/* their type for this functions anyway. */
/* For declared functions only named parameters*/
/* are passed in registers; extra parameters */
/* will be passed in stack slots */
}
CUMULATIVE_ARGS;
typedef void fnc_fnc_type (
CUMULATIVE_ARGS *cum, int mode, void *type, int named);
void fnc_init (CUMULATIVE_ARGS *cum, void *fntype);
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
(fnc_init (&(CUM),FNTYPE))
extern fnc_fnc_type fnc_advance;
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
(fnc_advance (&(CUM), MODE, TYPE, NAMED))
extern fnc_fnc_type fnc_arg;
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
(fnc_arg (&(CUM), MODE, TYPE, NAMED))
extern fnc_fnc_type fnc_arg_partial;
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
(fnc_arg_partial (&(CUM), MODE, TYPE, NAMED))
/* my own file */
#define VARG(x) ((long)(x))
void
fnc_init (cum, decl)
CUMULATIVE_ARGS *cum; /* argument info to initialize */
void *decl; /* tree ptr for function decl */
{
short parm;
cum->dreg = 0;
cum->areg = 8;
cum->cntp = 0;
parm = -1;
if (decl != 0)
{
tree arg;
arg = TYPE_ARG_TYPES (((tree)decl));
if (arg != 0) /* we have named parameters */
{
tree type;
parm = 0;
/* arg == 0 if `func (type1 p1,..,typeN pN, ... )' */
/* arg == void if `func (type1 p1,..,typeN pN, void)' */
while (arg != 0 && (type = TREE_VALUE (arg)) != void_type_node)
{
++parm;
arg = TREE_CHAIN (arg);
}
}
}
cum->parm = parm;
if (TARGET_DEBUGE_MODE)
fprintf (stderr, "fnc_init: total named parameters = %ld\n", VARG (parm));
}
void
fnc_advance (cum, mode, type, named)
CUMULATIVE_ARGS *cum; /* current arg information */
int mode; /* current arg mode */
void *type; /* type of the argument or 0 if lib support */
int named;
{
named = cum->cntp < cum->parm || cum->parm < 0;
/* suppose unnamed if and only if it is really unnamed */
++cum->cntp;
if (!named) return;
switch (mode)
{
default:
error ("Illegal mode given to fnc_advance");
case VOIDmode:
case BLKmode:
break;
case DImode:
case DFmode:
cum->dreg += 2;
break;
case QImode:
case HImode:
case SImode:
case SFmode:
if (type != 0 && TREE_CODE (((tree)type)) == POINTER_TYPE)
++cum->areg;
else
++cum->dreg;
}
}
void *
fnc_arg (cum, mode, type, named)
CUMULATIVE_ARGS *cum; /* current arg information */
int mode; /* current arg mode */
void *type; /* type of the argument or 0 if lib support */
int named; /* != 0 for normal args, == 0 for ... args */
{
named = cum->cntp < cum->parm || cum->parm < 0;
/* suppose unnamed if and only if it is really unnamed */
if (!named) return (0);
switch (mode)
{
default:
error ("Illegal mode given to fnc_arg");
case VOIDmode:
case BLKmode:
break;
case DImode:
case DFmode:
if (cum->dreg < DEBUG_DREGS)
return (gen_rtx (REG, mode, VARG (cum->dreg)));
case SFmode:
case QImode:
case HImode:
case SImode:
if (type != 0 && TREE_CODE (((tree)type)) == POINTER_TYPE)
{
if (cum->areg < DEBUG_AREGS )
return (gen_rtx (REG, mode, VARG (cum->areg)));
}
else
{
if (cum->dreg < DEBUG_DREGS )
return (gen_rtx (REG, mode, VARG (cum->dreg)));
}
}
return (0);
}
int
fnc_arg_partial(cum, mode, type, named)
CUMULATIVE_ARGS *cum; /* current arg information */
int mode; /* current arg mode */
void *type; /* type of the argument or 0 if lib support */
int named; /* != 0 for normal args, == 0 for ... args */
{
named = cum->cntp < cum->parm || cum->parm < 0;
/* suppose unnamed if and only if it is really unnamed */
if (named
&& (mode == DImode || mode == DFmode)
&& cum->dreg == DEBUG_DREGS-1) return (1);
return (0);
}
void *
fnc_value (type, func)
void *type, *func;
{
if (TREE_CODE (((tree)type)) == POINTER_TYPE)
return gen_rtx (REG, TYPE_MODE (((tree)type)), VARG (8));
return gen_rtx (REG, TYPE_MODE (((tree)type)), VARG (0));
}
-------------------------------------------------------------
Several notes now. The matter is that parameter `named' is
wrong for functions with variable number of parameters (about
always zero, regardless of function prototype), therefore we're
need to count number of really named parameters ourselves.
Please note, that current function epilogue/prologue generators
freely uses a0 - this could cause an error, but this stupid
register parameter allocator is enough for this test.
There is more clever parameter allocating procedures which
is able to use data or address registers if there's too many
pointer parameters and little number of data parameters and
vise versa. I believe there's anyway better to pass parameters
in registers than in stack slots, because soon of all callee
will move it's parameters from stack into registers.
Register-register move at MC68000 is 3 times quicklier than
memory-register, and code becomes shorter and much more
prettier.
Another way to improve code for MC68000 is to exchange `link
a6' and `movem ...' instructions. We'll need correct offset to
`FP' or `SP', but restoreing of registers will be much simplier
and willn't need to use `a0' . Another way is to use `a1'
instead of `a0', because `a1' will never be used for parameter
returning.
Third improvment is use frame pointer if and only if we
really need it: when current function calls 'alloca'.
Forth is to use instruction `move.l A0, D0', for examle, to
implement `tstsi' instruction to test `a0', if `d0' is free
register. There's need to change `m68k.md' file.
Fifth is following: if current function does't contain any
calls (to library functions as well), there's no need to save
it's parameters, which were in registers, in pseudo-registers.
Sometimes such saving produce suboptimal code and unrequired.
It doesn't concern `inline' functions because of side effects.
I think if you'll try such calling convention you'll notice
code shortage yourself. May be difference in speed for MC68040
is not so noticable but for MC68000 and MC68020 it's still
important.
It will be possible to use stack-passing functions in
libraries produced by other compilers, declaring all the
functions as `int foo (...);' to have the compiler to pass
parameters in stack and receive result from `d0', but GCC
reports an error for such a function declaration, for great
sorry.
May be in latest version of GCC such improvements are
already present and there's no this bug. I'm sorry very much if
so. May be some days later I'll find the bug myself, but I hope
last suggestion I did may be interesting for you. And I believe
you may be already knew about this bug and able to help.
I hope my terrible English didn't shoke you.
Sencirely yours,
Andrew Cadach,
Novosibirsk State University student.
Information Systems Institute,
Lavrentiev avenue, 6 room 489,
Akademgorodok,
Novosibirsk,
Russia.
Zip: 630090.
E-mail: kadach@isi.itfs.nsk.su
Technical Details
Message-ID:
<ABFjZxfmX5@isi.itfs.nsk.su>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!isi.ITfs.nsk.SU!kadachShow Full Headers
Complete Article Headers
Newsgroups: gnu.gcc.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!isi.ITfs.nsk.SU!kadach From: kadach@isi.ITfs.nsk.SU (Andrew Cadach) Subject: GCC 1.39 bug report and suggestions Message-ID: <ABFjZxfmX5@isi.itfs.nsk.su> Sender: gnulists@ai.mit.edu Organization: Institute of Informatics Systems Distribution: gnu Date: Thu, 16 Apr 1992 17:43:27 GMT Approved: bug-gcc@prep.ai.mit.edu Lines: 353