July 13, 2005
Hi,

the compiler seems to have some problems with inlining and opEquals in structs. The following 2 modules cause him to print some dubious error messages and crash if compiled with -inline (0.127 did not crash, but produced the same errors):

###########
module hash2;

private struct NodeType(Key, T)
{
  NodeType* next;
  uint hash;
  Key key;
}

private struct HeadNodeType(Key, T)
{
  alias NodeType!(Key, T) Node;

  Node* m_next;
  uint m_hash = 0;
  Key m_key;

  Node*[] m_table;
  uint m_bits = 0;
}

struct HashIterator(Key, T)
{
  alias NodeType!(Key, T) Node;
  alias HeadNodeType!(Key, T) HeadNode;

  Node* m_ptr;

  static HashIterator fromPtr(Node* ptr)
  {
    return *(cast(HashIterator*) &ptr);
  }

  int opEquals(HashIterator iter)
  {
    return (m_ptr == iter.m_ptr);
  }
}

struct Hash(Key, T)
{
  alias HashIterator!(Key, T) Iterator;
  alias NodeType!(Key, T) Node;
  alias HeadNodeType!(Key, T) HeadNode;

  HeadNode* m_data = null;

  Node* findNode(Key* key)
  {
    uint hash;
    Node* node = m_data.m_table[((hash >> m_data.m_bits) ^ hash) & ((1 << m_data.m_bits) - 1)];
    while (node != cast(Node*) m_data && (node.hash != hash || node.key != *key))
      node = node.next;

    return node;
  }

  Iterator end()
  {
    return Iterator.fromPtr(cast(Node*) m_data);
  }

  Iterator find(Key key)
  {
    return Iterator.fromPtr(findNode(&key));
  }
}

###########
module main;
private import hash2;

int main(char[][] args)
{
  Hash!(uint, uint) hash;
  hash.Iterator iter;

  if ((iter = hash.find(23)) == hash.end) // ERROR LINE
    printf("Nix");

  return 0;
}
############

If i remove HashIterator.opEquals(), everything works fine. These are the error messages i get:

######
main.d(9): iter = Hash *this = this = #hash;
 , uint key = key = 23;
 , NodeType *ptr = ptr = this.findNode(&key);
 , *(&ptr) is not an lvalue
./compilerelease.sh: line 4:  7418 Speicherzugriffsfehler  dmd -ofmain -odobj/ main.d indigo/*/*.d -L-ldl -L-lexpat -release -O -inline
######

Sorry that the code fragments are not much shorter... The if statement in the main function boils down to this call:

if (opEquals(iter = fromPtr(findNode(23)), end))

Ciao
uwe
July 21, 2005
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Uwe Salomon schrieb am Wed, 13 Jul 2005 09:59:02 +0200:
> Hi,
>
> the compiler seems to have some problems with inlining and opEquals in structs. The following 2 modules cause him to print some dubious error messages and crash if compiled with -inline (0.127 did not crash, but produced the same errors):
>
> ###########
> module hash2;
>
> private struct NodeType(Key, T)
> {
>    NodeType* next;
>    uint hash;
>    Key key;
> }
>
> private struct HeadNodeType(Key, T)
> {
>    alias NodeType!(Key, T) Node;
>
>    Node* m_next;
>    uint m_hash = 0;
>    Key m_key;
>
>    Node*[] m_table;
>    uint m_bits = 0;
> }
>
> struct HashIterator(Key, T)
> {
>    alias NodeType!(Key, T) Node;
>    alias HeadNodeType!(Key, T) HeadNode;
>
>    Node* m_ptr;
>
>    static HashIterator fromPtr(Node* ptr)
>    {
>      return *(cast(HashIterator*) &ptr);
>    }
>
>    int opEquals(HashIterator iter)
>    {
>      return (m_ptr == iter.m_ptr);
>    }
> }
>
> struct Hash(Key, T)
> {
>    alias HashIterator!(Key, T) Iterator;
>    alias NodeType!(Key, T) Node;
>    alias HeadNodeType!(Key, T) HeadNode;
>
>    HeadNode* m_data = null;
>
>    Node* findNode(Key* key)
>    {
>      uint hash;
>      Node* node = m_data.m_table[((hash >> m_data.m_bits) ^ hash) & ((1 <<
> m_data.m_bits) - 1)];
>      while (node != cast(Node*) m_data && (node.hash != hash || node.key !=
> *key))
>        node = node.next;
>
>      return node;
>    }
>
>    Iterator end()
>    {
>      return Iterator.fromPtr(cast(Node*) m_data);
>    }
>
>    Iterator find(Key key)
>    {
>      return Iterator.fromPtr(findNode(&key));
>    }
> }
>
> ###########
> module main;
> private import hash2;
>
> int main(char[][] args)
> {
>    Hash!(uint, uint) hash;
>    hash.Iterator iter;
>
>    if ((iter = hash.find(23)) == hash.end) // ERROR LINE
>      printf("Nix");
>
>    return 0;
> }
> ############
>
> If i remove HashIterator.opEquals(), everything works fine. These are the error messages i get:
>
> ######
> main.d(9): iter = Hash *this = this = #hash;
>   , uint key = key = 23;
>   , NodeType *ptr = ptr = this.findNode(&key);
>   , *(&ptr) is not an lvalue
> ./compilerelease.sh: line 4:  7418 Speicherzugriffsfehler  dmd -ofmain
> -odobj/ main.d indigo/*/*.d -L-ldl -L-lexpat -release -O -inline
> ######
>
> Sorry that the code fragments are not much shorter... The if statement in the main function boils down to this call:
>
> if (opEquals(iter = fromPtr(findNode(23)), end))

Added to DStress as http://dstress.kuehne.cn/run/i/inline_13_A.d http://dstress.kuehne.cn/run/i/inline_13_B.d

Thomas

-----BEGIN PGP SIGNATURE-----

iD8DBQFC380t3w+/yD4P9tIRAnlLAJ9qqKbrNWPR5gt747JGDLJlPCxpbgCglJKI
tI0rfsaNXOqU+ImlY2ksBSc=
=zaLC
-----END PGP SIGNATURE-----