[gnu.g++.bug] g++ 1.35.0 / i386g

jjc@UUNET.UU.NET (James Clark) (05/22/89)

I brought up g++ 1.35.0 on a 386 machine running SVR3.2 (386/ix
version 2.0.1) using COFF encapsulation (I used config.g++ i386g). I
had to make one small change to newld.c

*** newld.c.distrib	Sun May 21 17:02:18 1989
--- newld.c	Sun May 21 17:12:02 1989
***************
*** 255,261 ****
  #define INITIALIZE_HEADER outheader.a_machtype = HP9000S200_ID
  #endif
  #if defined(i386) && !defined(sequent)
! #define INITIALIZE_HEADER outheader.a_machtype = M_386
  #endif
  
  #ifdef is68k
--- 255,261 ----
  #define INITIALIZE_HEADER outheader.a_machtype = HP9000S200_ID
  #endif
  #if defined(i386) && !defined(sequent)
! #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_386)
  #endif
  
  #ifdef is68k

(This is how the current version of ld.c in binutils defines it).

There seems to be a register allocation problem.  I compiled this using just -g.

class symbol {
  static const char **table;
  static int table_used;
  static int table_size;
  static char *block;
  static int block_size;
  const char *s;
public:
  symbol(const char *p, int how = 0);
  symbol();
  unsigned hash();
  operator ==(symbol);
  operator !=(symbol);
};

inline symbol::symbol() : s(0)
{
}

inline symbol::operator==(symbol p)
{
  return s == p.s;
}

inline symbol::operator!=(symbol p)
{
  return s != p.s;
}

inline unsigned symbol::hash()
{
  return unsigned(s);
}

struct association {
  symbol s;
  void *v;
  association() :  v(0) {}
};

class dictionary {
  int size;
  int used;
  double threshold;
  double factor;
  association *table;
  void rehash(int);
public:
  dictionary(int);
  void *lookup(symbol s, void *v=0); // returns value associated with key
};

static int is_good_size(int p);

void *dictionary::lookup(symbol s, void *v = 0)
{
  for (int i = s.hash() % size; 
       table[i].v != 0;
       i == 0 ? i = size - 1: --i)
    if (s == table[i].s) {
      if (v != 0) {
	void *temp = table[i].v;
	table[i].v = v;
	return temp;
      }
      else
	return table[i].v;
    }
  ++used;
  table[i].v = v;
  table[i].s = s;
  if ((double)used/(double)size >= threshold || used + 1 >= size) {
    int old_size = size;
    size = int(size*factor);
    while (!is_good_size(size))
      ++size;
    association *old_table = table;
    table = new association[size];
    used = 0;
    for (i = 0; i < old_size; i++)
      if (old_table[i].v != 0)
	(void)lookup(old_table[i].s, old_table[i].v);
  }
  return 0;
}

It generates incorrect assembler code for line 74:

    size = int(size*factor);

Here's the assembler code that's incorrect:

	.stabd 68,0,73
	movl 8(%ebp),%eax
	movl (%eax),%edx
	movl %edx,-16(%ebp)
	.stabd 68,0,74
	fildl (%eax)
	fstpl -88(%ebp)
	fldl -88(%ebp)
	fmull 16(%eax)
	fstpl -88(%ebp)
	pushl -84(%ebp)
	pushl -88(%ebp)
	call ___fixdfsi
	leal 8(%esp),%esp
	movl 8(%ebp),%eax  <--- eax isn't available here: it holds the return value
	movl %eax,(%eax)
	.stabd 68,0,75

If you need the rest of the assembler code, I can easily send it.

James Clark
jjc@jclark.uucp