www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - a case where static foreach dosn't work "correctly"

reply BCS <BCS pathilink.com> writes:
If a static foreach is given a tuple of const ints, the ints don't 
behave like consts inside of the foreach body. I havent checked other 
cases but you can't use them for array indexes in ASM operations:


voif fn(V...)()
{
  const int i = 0
  int[3] array;

  foreach(j, V)
  {
   asm
   {
    mov EAX, array[i]; // works
    mov EAX, array[j]; // fails
   }
  }
}


Why does this matter you ask? It would allow this to work:


/***** unsigned big int with "size" words of precision */

template BigNum(uint size)
{
   static if(size == 0)
     static assert(false, "BigNum!(1) is not valid");
   else static if(size == 1)
     static assert(false, "BigNum!(1) is not implemented");
   else static if(size == 2)
     alias use!(1, 1) start;
   else
     alias build!(size, size-2, size-1) start;
}

template build(uint size, uint i, V...)
{
   static if(i==1)
     alias use!(size, 1, V) build;
   else
     alias build!(size, i-1, i, V) build;
}

template use(uint size, V...)
{
   struct use
   {
     uint[size] valuse;
     use!(size, V).use opAdd(use!(size, V).use to)
     {
       uint[size] mine, other;
       mine[] = valuse;
       other[] = to.valuse[];
       asm
       {
         mov EAX, mine[0];
         add other[0], EAX;
       }
       foreach(i; V)
       {
         asm
         {
           mov EAX, mine[i];	// this fails
           adc other[i], EAX;
         }
       }
       use!(size, V).use ret;
       ret.valuse[] = other;
       return ret;
     }
   }
}


DMD 0.174
Dec 06 2006
parent reply Alexander Panek <a.panek brainsware.org> writes:
Have you tried to do the same with DMD 0.176 ?
Maybe the bug is already solved in one of the two big massacres!

BCS wrote:
 If a static foreach is given a tuple of const ints, the ints don't 
 behave like consts inside of the foreach body. I havent checked other 
 cases but you can't use them for array indexes in ASM operations:
 
 
 voif fn(V...)()
 {
  const int i = 0
  int[3] array;
 
  foreach(j, V)
  {
   asm
   {
    mov EAX, array[i]; // works
    mov EAX, array[j]; // fails
   }
  }
 }
 
 
 Why does this matter you ask? It would allow this to work:
 
 
 /***** unsigned big int with "size" words of precision */
 
 template BigNum(uint size)
 {
   static if(size == 0)
     static assert(false, "BigNum!(1) is not valid");
   else static if(size == 1)
     static assert(false, "BigNum!(1) is not implemented");
   else static if(size == 2)
     alias use!(1, 1) start;
   else
     alias build!(size, size-2, size-1) start;
 }
 
 template build(uint size, uint i, V...)
 {
   static if(i==1)
     alias use!(size, 1, V) build;
   else
     alias build!(size, i-1, i, V) build;
 }
 
 template use(uint size, V...)
 {
   struct use
   {
     uint[size] valuse;
     use!(size, V).use opAdd(use!(size, V).use to)
     {
       uint[size] mine, other;
       mine[] = valuse;
       other[] = to.valuse[];
       asm
       {
         mov EAX, mine[0];
         add other[0], EAX;
       }
       foreach(i; V)
       {
         asm
         {
           mov EAX, mine[i];    // this fails
           adc other[i], EAX;
         }
       }
       use!(size, V).use ret;
       ret.valuse[] = other;
       return ret;
     }
   }
 }
 
 
 DMD 0.174
Dec 06 2006
parent BCS <BCS pathlink.com> writes:
Alexander Panek wrote:
 Have you tried to do the same with DMD 0.176 ?
 Maybe the bug is already solved in one of the two big massacres!
 
It wasn't, but I fond a work around (and a few typos), here's the latest: /***** unsigned big int with "size" words of precision */ alias BigNum(4) uCent; template BigNum(uint size) { static if(size == 0) static assert(false, "BigNum!(1) is not valid"); else static if(size == 1) static assert(false, "BigNum!(1) is not implemented"); else static if(size == 2) alias use!(1, 1) BigNum; else alias build!(size, size-2, size-1) BigNum; } template build(uint size, uint i, V...) { static if(i==1) alias use!(size, 1, V) build; else alias build!(size, i-1, i, V) build; } template use(uint size, V...) { struct use { uint[size] valuse; use!(size, V) opAdd(use!(size, V) to) { uint[size] mine, other; mine[] = valuse; other[] = to.valuse[]; asm { mov EAX, mine[0]; add other[0], EAX; } foreach(j,i; V) { const uint off = V[j]; // this is a work-around asm { mov EAX, mine[off]; adc other[off], EAX; } } use!(size, V) ret; ret.valuse[] = other; return ret; } use!(size, V) opSub(use!(size, V) to) { uint[size] mine, other; mine[] = valuse; other[] = to.valuse[]; asm { mov EAX, mine[0]; sub other[0], EAX; } foreach(j,i; V) { const uint off = V[j]; asm { mov EAX, mine[off]; sbb other[off], EAX; } } use!(size, V) ret; ret.valuse[] = other; return ret; } } }
 BCS wrote:
 
 If a static foreach is given a tuple of const ints, the ints don't 
 behave like consts inside of the foreach body. I havent checked other 
 cases but you can't use them for array indexes in ASM operations:
[...]
 Why does this matter you ask? It would allow this to work:
Dec 07 2006