[gnu.gcc.bug] v1.28/386 inline-functions bug

james@bigtex.uucp (James Van Artsdalen) (09/22/88)

I have isolate a piece of code in which gcc handles incorrectly with
inline functions.  I am in the midst of changing jobs and can't
devote any more time to it, but this should be sufficient as an
example.  The compiler is an unmodified 1.28 with tm-i386v.h and
config-i386v.h.

The sample is a piece of Larry Wall's perl program.  The two functions
were moved from perly.c into their own file, bad.c.  When bad.c is
compiled with inline functions, perl dumps core, but without inline
functions, perl runs fine (output is deleted because it is large,
correct and not interesting).  Comparing the assembly from compiling
bad.c with and without inline functions hints that gcc may be losing
track of the number of pushes onto the stack, but this shouldn't cause
a core dump in these functions I would think.

/usr4/src/perl> gcc -c -O -finline-functions bad.c
/usr4/src/perl> make
gcc   perly.o arg.o array.o cmd.o dump.o eval.o form.o hash.o  regexp.o stab.o str.o toke.o util.o version.o yow.o bad.o perl.o -lm -o perl
touch all
/usr4/src/perl> ./perl t/op.stat
Memory fault - core dumped
(ERR:139)
/usr4/src/perl> gcc -c -O bad.c
/usr4/src/perl> make
gcc   perly.o arg.o array.o cmd.o dump.o eval.o form.o hash.o  regexp.o stab.o str.o toke.o util.o version.o yow.o bad.o perl.o -lm -o perl
touch all
/usr4/src/perl> ./perl t/op.stat
[ output deleted ]
/usr4/src/perl> 

Here is the file bad.c:
-----
extern char *memcpy();

typedef struct {
	int	_cnt;
	unsigned char	*_ptr;
	unsigned char	*_base;
	char	_flag;
	char	_file;
} FILE;

typedef struct arg ARG;
typedef struct cmd CMD;
typedef struct formcmd FCMD;
typedef struct scanpat SPAT;
typedef struct stab STAB;
typedef struct stio STIO;
typedef struct sub SUBR;
typedef struct string STR;
typedef struct atbl ARRAY;
typedef struct htbl HASH;
 
typedef unsigned short line_t;
 
char	*safemalloc();

struct stab {
    struct stab *stab_next;
    char	*stab_name;
    STR		*stab_val;
    struct stio *stab_io;
    FCMD	*stab_form;
    ARRAY	*stab_array;
    HASH	*stab_hash;
    SUBR	*stab_sub;
    char	stab_flags;
};

struct stio {
    FILE	*fp;
    long	lines;
    long	page;
    long	page_len;
    long	lines_left;
    char	*top_name;
    STAB	*top_stab;
    char	*fmt_name;
    STAB	*fmt_stab;
    short	subprocess;
    char	type;
    char	flags;
};

union argptr {
    ARG		*arg_arg;
    char	*arg_cval;
    STAB	*arg_stab;
    SPAT	*arg_spat;
    CMD		*arg_cmd;
    STR		*arg_str;
    double	arg_nval;
};

struct arg {
    union argptr arg_ptr;
    short	arg_len;
    unsigned char arg_type;
    unsigned char arg_flags;
};

struct acmd {
    STAB	*ac_stab;	 
    ARG		*ac_expr;	 
};
struct ccmd {
    CMD		*cc_true;	 
    CMD		*cc_alt;	 
};
struct cmd {
    CMD		*c_next;	 
    ARG		*c_expr;	 
    CMD		*c_head;	 
    STR		*c_short;	 
    STAB	*c_stab;	 
    SPAT	*c_spat;	 
    char	*c_label;	 
    union ucmd {
	struct acmd acmd;	 
	struct ccmd ccmd;	 
    } ucmd;
    short	c_slen;		 
    short	c_flags;	 
    char	*c_file;	 
    line_t      c_line;          
    char	c_type;		 
};

ARG *op_new();
ARG *make_op();

ARG *l();

extern  STAB *defstab  ;

void free_arg();

ARG *
stab2arg(atype,stab)
int atype;
register STAB *stab;
{
    register ARG *arg;
    arg = op_new(1);
    arg->arg_type = 1 ;
    arg[1].arg_type = atype;
    arg[1].arg_ptr.arg_stab = stab;
    return arg;
}

CMD *
wopt(cmd)
register CMD *cmd;
{
    register CMD *tail;
    register ARG *arg = cmd->c_expr;
    STAB *asgnstab;
    if (arg && arg->arg_type == 1  && arg[1].arg_type == 8 ) {
	cmd->c_flags &= ~077	;	 
	cmd->c_flags |= 6	;	 
	cmd->c_stab = arg[1].arg_ptr.arg_stab;
	if (arg[1].arg_ptr.arg_stab->stab_io->flags & 1	) {
	    cmd->c_expr = l(make_op(9 , 2,	 
	       stab2arg(4 ,defstab), arg, ((ARG*)0 )  ,1 ));
	}
	else {
	    free_arg(arg);
	    cmd->c_expr = ((ARG*)0 )  ;
	}
    }
    else if (arg && arg->arg_type == 1  && arg[1].arg_type == 16 ) {
	cmd->c_flags &= ~077	;	 
	cmd->c_flags |= 11	;	 
	cmd->c_stab = arg[1].arg_ptr.arg_stab;
	free_arg(arg);
	cmd->c_expr = ((ARG*)0 )  ;
    }
    else if (arg && arg->arg_type == 1  && arg[1].arg_type == 14 ) {
	if ((cmd->c_flags & 077	) == 10	)
	    asgnstab = cmd->c_stab;
	else
	    asgnstab = defstab;
	cmd->c_expr = l(make_op(9 , 2,	 
	   stab2arg(4 ,asgnstab), arg, ((ARG*)0 )  ,1 ));
	cmd->c_flags &= ~077	;	 
    }
    if (cmd->ucmd.ccmd.cc_true == ((CMD*)0 )  )
	return cmd;
    for (tail = cmd->ucmd.ccmd.cc_true; tail->c_next; tail = tail->c_next) ;
    if (cmd->ucmd.ccmd.cc_alt != ((CMD*)0 )  ) {
	tail->c_next = cmd->ucmd.ccmd.cc_alt;
	for ( ; tail->c_next; tail = tail->c_next) ;
    }
    tail->c_next = (CMD *) safemalloc(sizeof (CMD));
    tail = tail->c_next;
    if (!cmd->ucmd.ccmd.cc_alt)
	cmd->ucmd.ccmd.cc_alt = tail;	 
    memcpy( (char *)tail,(char *)cmd, sizeof(CMD)); ;
    tail->c_type = 3 ;
    tail->c_flags ^= 04000	;		 
    tail->c_next = tail->ucmd.ccmd.cc_true;	 
    tail->ucmd.acmd.ac_expr = make_op(67 ,0,((ARG*)0 )  ,((ARG*)0 )  ,((ARG*)0 )  ,0);
    tail->ucmd.acmd.ac_stab = ((STAB*)0 )  ;
    return cmd;
}
-- 
James R. Van Artsdalen    ...!uunet!utastro!bigtex!james     "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746