www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Inlining problems

reply "Uwe Salomon" <post uwesalomon.de> writes:
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
Jul 13 2005
parent Thomas Kuehne <thomas-dloop kuehne.this-is-spam.cn> writes:
-----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-----
Jul 21 2005