Byte Code; Direct Style 
Author Message
 Byte Code; Direct Style

   The following code sample is a GNU compliant byte-code run loop example.
Unfortunately I can't get the {*filter*}y thing to compile in VC.Net or VC++ 6.0.
How can I adapt this to work for VC.NET or preferably ANSI C++; the most
important part being getting the label addresses.

Note: I understand I can use a switch statement, but I really don't want nor
need a check to make sure it's within bounds.  If there's a way to define a
switch statement without the bounds checking I'm all ears.

#define NEXT goto **ip++
main()
{
  static void  *prog[] =
{&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
  void **ip=prog;
  int    count = 10000000;

 next:
  NEXT;
 loop:
  if (count>0) {
    count--;
    ip=prog;
    NEXT;
  }

Quote:
}

Off Subject:  Anyone know where I can get a nice Itanium/Hammer simulator,
if I can compile XP 64 while in 32-bit windows, and if XP 64 will support
the Hammer Architecture and if it does will VC.NET be able to compile 64-bit
code for it?  If so I have some benchmarks I'm working on that I'd love to
try and test on those 64-bit chips, specifically the Claw Hammer if it's
going to be as reasonably priced as we've been led to believe.

--Jonathan Ross, Mark Ross & Co., VB Programmer
// If you need to send me e-mail remove all numbers and capital letters from
the e-mail listed.



Sun, 01 Aug 2004 02:09:25 GMT  
 Byte Code; Direct Style
I don't know what language this is -- but it is not C or C++ as I know it.

There is no way in C or C++ to take the address of a label: the only way I
could think of doing this would be using assembler -- but that would not be
very protable.

--
Jonathan Caves
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Quote:
>    The following code sample is a GNU compliant byte-code run loop
example.
> Unfortunately I can't get the {*filter*}y thing to compile in VC.NET or VC++
6.0.
> How can I adapt this to work for VC.NET or preferably ANSI C++; the most
> important part being getting the label addresses.

> Note: I understand I can use a switch statement, but I really don't want
nor
> need a check to make sure it's within bounds.  If there's a way to define
a
> switch statement without the bounds checking I'm all ears.

> #define NEXT goto **ip++
> main()
> {
>   static void  *prog[] =
> {&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
>   void **ip=prog;
>   int    count = 10000000;

>  next:
>   NEXT;
>  loop:
>   if (count>0) {
>     count--;
>     ip=prog;
>     NEXT;
>   }
> }

> Off Subject:  Anyone know where I can get a nice Itanium/Hammer simulator,
> if I can compile XP 64 while in 32-bit windows, and if XP 64 will support
> the Hammer Architecture and if it does will VC.NET be able to compile
64-bit
> code for it?  If so I have some benchmarks I'm working on that I'd love to
> try and test on those 64-bit chips, specifically the Claw Hammer if it's
> going to be as reasonably priced as we've been led to believe.

> --Jonathan Ross, Mark Ross & Co., VB Programmer
> // If you need to send me e-mail remove all numbers and capital letters
from
> the e-mail listed.



Mon, 02 Aug 2004 08:29:40 GMT  
 Byte Code; Direct Style
   Actually GNU added that &&label bit a few years back.  I went ahead and
tried to compile the sample with gcc as a c file and it compiled without a
complaint; running it on the other hand was another matter.  However, to
simplify things here's an example I got to work in gcc as a c source file.
Are you sure there's no way to do this in VC++?

#include <stdio.h>

#define NEXT goto *ip++
main()
{
  static void  *prog[] = {&&cool,&&notcool};
  //void **ip=prog;
  //int    count = 1;

  goto *prog[0];
notcool:
  printf("Not Cool\n");
  exit(0);
cool:
  printf("Cool\n");
  exit(0);

Quote:
}

   The output when compiled and ran was, of course, "Cool".  The following
did however work in VC++

#include <iostream>

void main()
{
    __asm jmp mylabel;
    std::cout << "didn't work" << std::endl;
    return;
    mylabel:
    std::cout << "worked" << std::endl;
    return;

Quote:
}

   If I have to I'll just swap a definition depending on what platform I
have set for compile, not like my GUI stuff is all that ANSI anyway :)  But
I would prefer an ANSI solution if there is one, and that's what I was
wondering, if there was an ANSI solution.

--Jonathan Ross, Mark Ross & Co, Software R&D



Quote:
> I don't know what language this is -- but it is not C or C++ as I know it.

> There is no way in C or C++ to take the address of a label: the only way I
> could think of doing this would be using assembler -- but that would not
be
> very protable.

> --
> Jonathan Caves
> Microsoft Corporation

> This posting is provided "AS IS" with no warranties, and confers no

rights.


Mon, 02 Aug 2004 06:36:38 GMT  
 Byte Code; Direct Style
Errrr, ignore that second example of the jmp instruction.  <blinks>  I'm
going to blame it on programming for 18 straight hours [ minus a 15 minute
lunch break ].  Just stick to the part about is there an ANSI C or C++ way
to do the first example.


Quote:
>    Actually GNU added that &&label bit a few years back.  I went ahead and
> tried to compile the sample with gcc as a c file and it compiled without a
> complaint; running it on the other hand was another matter.  However, to
> simplify things here's an example I got to work in gcc as a c source file.
> Are you sure there's no way to do this in VC++?

> #include <stdio.h>

> #define NEXT goto *ip++
> main()
> {
>   static void  *prog[] = {&&cool,&&notcool};
>   //void **ip=prog;
>   //int    count = 1;

>   goto *prog[0];
> notcool:
>   printf("Not Cool\n");
>   exit(0);
> cool:
>   printf("Cool\n");
>   exit(0);
> }

>    The output when compiled and ran was, of course, "Cool".  The following
> did however work in VC++

> #include <iostream>

> void main()
> {
>     __asm jmp mylabel;
>     std::cout << "didn't work" << std::endl;
>     return;
>     mylabel:
>     std::cout << "worked" << std::endl;
>     return;
> }



Mon, 02 Aug 2004 06:43:29 GMT  
 Byte Code; Direct Style


Quote:


>>    The following code sample is a GNU compliant byte-code run loop
>example.
>> Unfortunately I can't get the {*filter*}y thing to compile in VC.NET or VC++
>6.0.
>> How can I adapt this to work for VC.NET or preferably ANSI C++; the most
>> important part being getting the label addresses.

>> Note: I understand I can use a switch statement, but I really don't want
>nor
>> need a check to make sure it's within bounds.  If there's a way to define
>a
>> switch statement without the bounds checking I'm all ears.

>> #define NEXT goto **ip++
>> main()
>> {
>>   static void  *prog[] =
>> {&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
>>   void **ip=prog;
>>   int    count = 10000000;

>>  next:
>>   NEXT;
>>  loop:
>>   if (count>0) {
>>     count--;
>>     ip=prog;
>>     NEXT;
>>   }
>> }

>I don't know what language this is -- but it is not C or C++ as I know it.

>There is no way in C or C++ to take the address of a label: the only way I
>could think of doing this would be using assembler -- but that would not be
>very protable.

Right, this is a gcc'ism.  With the 4.3 release of Comeau we'll support
this as an extension, along with 'goto *p;', but I agree one should
not expect this for portable code.  So to adapt it for Standard C++
you'll need to perhaps use pointers to function, or a switch statement
or something.
--
Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
Comeau C/C++ ONLINE ==>     http://www.*-*-*.com/
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?


Mon, 02 Aug 2004 23:20:29 GMT  
 Byte Code; Direct Style

Quote:





>>> #define NEXT goto **ip++
>>> main()
>>> {
>>>   static void  *prog[] =
>>> {&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
>>>   void **ip=prog;
>>>   int    count = 10000000;

>>>  next:
>>>   NEXT;
>>>  loop:
>>>   if (count>0) {
>>>     count--;
>>>     ip=prog;
>>>     NEXT;
>>>   }
>>> }

>>I don't know what language this is -- but it is not C or C++ as I know it.

>>There is no way in C or C++ to take the address of a label: the only way I
>>could think of doing this would be using assembler -- but that would not be
>>very protable.

>Right, this is a gcc'ism.  With the 4.3 release of Comeau we'll support
>this as an extension, along with 'goto *p;', but I agree one should
>not expect this for portable code.  So to adapt it for Standard C++
>you'll need to perhaps use pointers to function, or a switch statement
>or something.

BTW, if I'm not mistaken, your code seems equivalent to this:

int main()
{
  int count = 10000000;

  do {
    for (int next = 0; next < 9; next++)
      ;
  } while (count-- > 0);

  return 0;

Quote:
}

or for that matter just use 90000000L with one loop.
--
Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?


Tue, 03 Aug 2004 01:41:01 GMT  
 Byte Code; Direct Style
   When optimized down, yes, you're absolutely correct.  However, I was
simply trying to do some benchmarks to decide what form of byte code
interpreter run structure would work best on different platforms.  I may not
have made it clear but I'm trying to design a Direct Calling interpreter,
which may also be called a tail call interpreter (I'm not positive).

   Also, I tried to use the inline assembly of VC++ to load a label into a
register, it did not work.  At this point I'm concerned about my code being
compliable in both gcc and VC++, but I would be willing to define a few
assembly macros and switch them at compile time for the sake of speed.

   So with the goal of jumping to different areas in the function using an
index to an array of code positions as opcodes I have two choices.  The
first is using a switch statement, which I do not like since compilers
generally insert code to insure the variable is within bounds [ If I use an
unsigned value for the switch will VC++ only check to make sure the opcode
is <= the upper bound? ].  The second is the direct style which basically
means that instead of having a break at the end of an opcode's code there is
code that will move it directly to the next opcode in line.  Here's a simple
switch case example that I did get to work successfully in VC++.

void switch_type()
{
    static int prog[] = {0,0,0,0,0,0,0,0,0,1};
    int *ip=prog;
    int count = 10000000;
    unsigned int nop = 0;

    for (;;)
    {
        switch (*ip++)
        {
        case 0:
                nop++;
                break;
        case 1:
            if (--count)
            {
                ip=prog;
                break;
            }else
                return;
        }
    }

Quote:
}

    Remember that direct or tail style is different from switch style byte
code in that instead of returning to the beginning of the switch statement,
each opcode's native code goes straight to the next opcode in line instead
of going back to another position and then re-entering.  In other words,
there's no nesting.

   What I want to achieve is a direct calling example I can use in my
benchmark that will work in VC++ and GCC that has no bound checking.  While
I have no doubt that VC++ is an exceptionally smart compiler and may even
generate assembly that does do direct calling when all the optimizations for
speed are on (after all you're really just indexing an array for a switch
anyway, where you index it from isn't all that important) my worry is two
fold.  First off, gcc may not be this smart and I'd like my code to be as
static as possible.  And secondly, there's still a very high if not 100%
chance VC++ is still going to implement bound checking which is completely
unnecessary as the opcode generation will be handled by an assembler which
itself is used by a compiler in the finished product.

   As I said, I am not opposed to swapping a few macro definitions so long
as the general structure is the same for both ports of the code.  So my
question to anyone who can answer is how do I get the offset of a position
of code; the value of a label, and how do I then use that value, stored in
memory, to jump to the portion of the code I want?

   As for the using Comeau the idea is starting to look very attractive for
other reasons as well.  I had planned to use non-fixed length arrays as
masks for each code segment.  The idea was to have a structure with some
header, multi-threaded, etc. basic information in the front and an empty
array at the bottom.  I would then malloc whatever size code I need and use
one of these structures as the type of a pointer to that malloced area.
This would mean that the function wouldn't require an even deeper level
pointer to the code and would save sizeof(pointer) space in the function as
a bonus.  While that does compile in VC++, it only compiles while Microsoft
extensions are enabled (I'm writing my test code in VC++ 6.0, I'm waiting
for my recently purchased MSDN Developer CustomerID to kick in).

   My concerns however are that one of the biggest reasons I choose to
develop this project in Windows first instead of a Unix flavor or on a Mac
(although Unix/Linux/Solaris x86 is my main target) is that IDE for VC.NET
is just so extraordinary [ plus you just _HAVE_ to love the documentation
and help ].  It also doesn't hurt that VC++ is such a smart optimizer, but
that's just why I decided to actually compile the Windows final version in
VC++, not why I'm developing in it.  I looked at the Comeau site and I must
admit I didn't quite fully grasp the concept of what it is.  From my
understanding it's basically the top layer of a compiler, it compiles into
the middle code of another compiler, and then lets that compiler compile
native code from it's own middle language.  What concerns me is of course
that I noticed Comeau is text prompt based system, and I heard no mention of
it being an IDE.  To me this is extraordinarily important and why I choose
VC.NET in the first place.

   So my question to you is how could I leverage the IDE of VC.NET, the
compiler of Comeau, and the middle language to native code abilities of
VC.NET and GCC without making this project more difficult than it already
is?

--Jonathan Ross
// To send me e-mail remove all capital letters and numbers from my e-mail
address.


Quote:






> >>> #define NEXT goto **ip++
> >>> main()
> >>> {
> >>>   static void  *prog[] =

{&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
Quote:
> >>>   void **ip=prog;
> >>>   int    count = 10000000;

> >>>  next:
> >>>   NEXT;
> >>>  loop:
> >>>   if (count>0) {
> >>>     count--;
> >>>     ip=prog;
> >>>     NEXT;
> >>>   }
> >>> }

> >>I don't know what language this is -- but it is not C or C++ as I know
it.

> >>There is no way in C or C++ to take the address of a label: the only way
I
> >>could think of doing this would be using assembler -- but that would not
be
> >>very protable.

> >Right, this is a gcc'ism.  With the 4.3 release of Comeau we'll support
> >this as an extension, along with 'goto *p;', but I agree one should
> >not expect this for portable code.  So to adapt it for Standard C++
> >you'll need to perhaps use pointers to function, or a switch statement
> >or something.

> BTW, if I'm not mistaken, your code seems equivalent to this:

> int main()
> {
>   int count = 10000000;

>   do {
>     for (int next = 0; next < 9; next++)
>       ;
>   } while (count-- > 0);

>   return 0;
> }

> or for that matter just use 90000000L with one loop.
> --
> Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
> Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
> World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
> Comeau C/C++ with Dinkumware's Libraries... Have you tried it?



Mon, 02 Aug 2004 23:04:19 GMT  
 Byte Code; Direct Style
Jonathan: I not sure if I fully understand your concern about the Visual C++
compiler bounds-checking a switch statement. I do not believe that any C++
compiler will bounds check the expression in a switch-statement. If there is
not a case label that corresponds to the value of the expression then the
compiler will choose the default label, or if there is not a default label,
it will just skip the body of the switch-statement.

--
Jonathan Caves
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Quote:
>    When optimized down, yes, you're absolutely correct.  However, I was
> simply trying to do some benchmarks to decide what form of byte code
> interpreter run structure would work best on different platforms.  I may
not
> have made it clear but I'm trying to design a Direct Calling interpreter,
> which may also be called a tail call interpreter (I'm not positive).

>    Also, I tried to use the inline assembly of VC++ to load a label into a
> register, it did not work.  At this point I'm concerned about my code
being
> compliable in both gcc and VC++, but I would be willing to define a few
> assembly macros and switch them at compile time for the sake of speed.

>    So with the goal of jumping to different areas in the function using an
> index to an array of code positions as opcodes I have two choices.  The
> first is using a switch statement, which I do not like since compilers
> generally insert code to insure the variable is within bounds [ If I use
an
> unsigned value for the switch will VC++ only check to make sure the opcode
> is <= the upper bound? ].  The second is the direct style which basically
> means that instead of having a break at the end of an opcode's code there
is
> code that will move it directly to the next opcode in line.  Here's a
simple
> switch case example that I did get to work successfully in VC++.

> void switch_type()
> {
>     static int prog[] = {0,0,0,0,0,0,0,0,0,1};
>     int *ip=prog;
>     int count = 10000000;
>     unsigned int nop = 0;

>     for (;;)
>     {
>         switch (*ip++)
>         {
>         case 0:
>                 nop++;
>                 break;
>         case 1:
>             if (--count)
>             {
>                 ip=prog;
>                 break;
>             }else
>                 return;
>         }
>     }
> }

>     Remember that direct or tail style is different from switch style byte
> code in that instead of returning to the beginning of the switch
statement,
> each opcode's native code goes straight to the next opcode in line instead
> of going back to another position and then re-entering.  In other words,
> there's no nesting.

>    What I want to achieve is a direct calling example I can use in my
> benchmark that will work in VC++ and GCC that has no bound checking.
While
> I have no doubt that VC++ is an exceptionally smart compiler and may even
> generate assembly that does do direct calling when all the optimizations
for
> speed are on (after all you're really just indexing an array for a switch
> anyway, where you index it from isn't all that important) my worry is two
> fold.  First off, gcc may not be this smart and I'd like my code to be as
> static as possible.  And secondly, there's still a very high if not 100%
> chance VC++ is still going to implement bound checking which is completely
> unnecessary as the opcode generation will be handled by an assembler which
> itself is used by a compiler in the finished product.

>    As I said, I am not opposed to swapping a few macro definitions so long
> as the general structure is the same for both ports of the code.  So my
> question to anyone who can answer is how do I get the offset of a position
> of code; the value of a label, and how do I then use that value, stored in
> memory, to jump to the portion of the code I want?

>    As for the using Comeau the idea is starting to look very attractive
for
> other reasons as well.  I had planned to use non-fixed length arrays as
> masks for each code segment.  The idea was to have a structure with some
> header, multi-threaded, etc. basic information in the front and an empty
> array at the bottom.  I would then malloc whatever size code I need and
use
> one of these structures as the type of a pointer to that malloced area.
> This would mean that the function wouldn't require an even deeper level
> pointer to the code and would save sizeof(pointer) space in the function
as
> a bonus.  While that does compile in VC++, it only compiles while
Microsoft
> extensions are enabled (I'm writing my test code in VC++ 6.0, I'm waiting
> for my recently purchased MSDN Developer CustomerID to kick in).

>    My concerns however are that one of the biggest reasons I choose to
> develop this project in Windows first instead of a Unix flavor or on a Mac
> (although Unix/Linux/Solaris x86 is my main target) is that IDE for VC.NET
> is just so extraordinary [ plus you just _HAVE_ to love the documentation
> and help ].  It also doesn't hurt that VC++ is such a smart optimizer, but
> that's just why I decided to actually compile the Windows final version in
> VC++, not why I'm developing in it.  I looked at the Comeau site and I
must
> admit I didn't quite fully grasp the concept of what it is.  From my
> understanding it's basically the top layer of a compiler, it compiles into
> the middle code of another compiler, and then lets that compiler compile
> native code from it's own middle language.  What concerns me is of course
> that I noticed Comeau is text prompt based system, and I heard no mention
of
> it being an IDE.  To me this is extraordinarily important and why I choose
> VC.NET in the first place.

>    So my question to you is how could I leverage the IDE of VC.NET, the
> compiler of Comeau, and the middle language to native code abilities of
> VC.NET and GCC without making this project more difficult than it already
> is?

> --Jonathan Ross
> // To send me e-mail remove all capital letters and numbers from my e-mail
> address.









> > >>> #define NEXT goto **ip++
> > >>> main()
> > >>> {
> > >>>   static void  *prog[] =

> {&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&next,&&loop};
> > >>>   void **ip=prog;
> > >>>   int    count = 10000000;

> > >>>  next:
> > >>>   NEXT;
> > >>>  loop:
> > >>>   if (count>0) {
> > >>>     count--;
> > >>>     ip=prog;
> > >>>     NEXT;
> > >>>   }
> > >>> }

> > >>I don't know what language this is -- but it is not C or C++ as I know
> it.

> > >>There is no way in C or C++ to take the address of a label: the only
way
> I
> > >>could think of doing this would be using assembler -- but that would
not
> be
> > >>very protable.

> > >Right, this is a gcc'ism.  With the 4.3 release of Comeau we'll support
> > >this as an extension, along with 'goto *p;', but I agree one should
> > >not expect this for portable code.  So to adapt it for Standard C++
> > >you'll need to perhaps use pointers to function, or a switch statement
> > >or something.

> > BTW, if I'm not mistaken, your code seems equivalent to this:

> > int main()
> > {
> >   int count = 10000000;

> >   do {
> >     for (int next = 0; next < 9; next++)
> >       ;
> >   } while (count-- > 0);

> >   return 0;
> > }

> > or for that matter just use 90000000L with one loop.
> > --
> > Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
> > Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
> > World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
> > Comeau C/C++ with Dinkumware's Libraries... Have you tried it?



Tue, 03 Aug 2004 04:42:47 GMT  
 Byte Code; Direct Style

Quote:





>> >Right, this is a gcc'ism.  With the 4.3 release of Comeau we'll support
>> >this as an extension, along with 'goto *p;', but I agree one should
>> >not expect this for portable code.  So to adapt it for Standard C++
>> >you'll need to perhaps use pointers to function, or a switch statement
>> >or something.

>> BTW, if I'm not mistaken, your code seems equivalent to this:

>> int main()
>> {
>>   int count = 10000000;

>>   do {
>>     for (int next = 0; next < 9; next++)
>>       ;
>>   } while (count-- > 0);

>>   return 0;
>> }

>> or for that matter just use 90000000L with one loop.

>   When optimized down, yes, you're absolutely correct.  However, I was
>simply trying to do some benchmarks to decide what form of byte code
>interpreter run structure would work best on different platforms.  I may not
>have made it clear but I'm trying to design a Direct Calling interpreter,
>which may also be called a tail call interpreter (I'm not positive).

Ok, it wasn't clear if you were just trying to create a clever
delay, or some form of compute goto, or some sort of state machine
(w/o giving those details).

Quote:
>   Also, I tried to use the inline assembly of VC++ to load a label into a
>register, it did not work.  At this point I'm concerned about my code being
>compliable in both gcc and VC++, but I would be willing to define a few
>assembly macros and switch them at compile time for the sake of speed.

I'm not well versed in doing that, but I can't imagine why it's not
possible as a non-portable solution (just as the gcc version is).

Quote:
>   So with the goal of jumping to different areas in the function using an
>index to an array of code positions as opcodes I have two choices.

Ok.

Quote:
>The
>first is using a switch statement, which I do not like since compilers
>generally insert code to insure the variable is within bounds

No so many compilers do this, and those that do allow you to turn it off.

Quote:
> [ If I use an
>unsigned value for the switch will VC++ only check to make sure the opcode
>is <= the upper bound? ].

Isn't that what default: is for?

Quote:
>The second is the direct style which basically
>means that instead of having a break at the end of an opcode's code there is
>code that will move it directly to the next opcode in line.

Right.

- Show quoted text -

Quote:
>Here's a simple
>switch case example that I did get to work successfully in VC++.

>void switch_type()
>{
>    static int prog[] = {0,0,0,0,0,0,0,0,0,1};
>    int *ip=prog;
>    int count = 10000000;
>    unsigned int nop = 0;

>    for (;;)
>    {
>        switch (*ip++)
>        {
>        case 0:
>                nop++;
>                break;
>        case 1:
>            if (--count)
>            {
>                ip=prog;
>                break;
>            }else
>                return;
>        }
>    }
>}

>    Remember that direct or tail style is different from switch style byte
>code in that instead of returning to the beginning of the switch statement,
>each opcode's native code goes straight to the next opcode in line instead
>of going back to another position and then re-entering.  In other words,
>there's no nesting.

I'm still not complete clear what you want to do, but it sounds
like you want to make an enum with each "state" and then just use
the enumerators as the values for the case ?:'s above.  So instead
of 0 and 1 you might have enum states { next,  loop };
and then case next: and case loop:   And off the top of my head,
that should be reasonable efficient, probably not worse than the
gcc extension and perhaps seven better.

Quote:
>   What I want to achieve is a direct calling example I can use in my
>benchmark that will work in VC++ and GCC that has no bound checking.  While
>I have no doubt that VC++ is an exceptionally smart compiler and may even
>generate assembly that does do direct calling when all the optimizations for
>speed are on (after all you're really just indexing an array for a switch
>anyway, where you index it from isn't all that important) my worry is two
>fold.  First off, gcc may not be this smart and I'd like my code to be as
>static as possible.  And secondly, there's still a very high if not 100%
>chance VC++ is still going to implement bound checking which is completely
>unnecessary as the opcode generation will be handled by an assembler which
>itself is used by a compiler in the finished product.

Most compiler use many strategies for efficient switch tables,
especially if they are consecutive you should have it reasonable
with both compilers.

Quote:
>   As I said, I am not opposed to swapping a few macro definitions so long
>as the general structure is the same for both ports of the code.  So my
>question to anyone who can answer is how do I get the offset of a position
>of code; the value of a label, and how do I then use that value, stored in
>memory, to jump to the portion of the code I want?

I don't know but as per above, if I understand what you're asking
to do, it should be within reach.

Quote:
>   As for the using Comeau the idea is starting to look very attractive for
>other reasons as well.  I had planned to use non-fixed length arrays as
>masks for each code segment.  The idea was to have a structure with some
>header, multi-threaded, etc. basic information in the front and an empty
>array at the bottom.

Do you mean like C99's ''flexible arrays''?

Quote:
>I would then malloc whatever size code I need and use
>one of these structures as the type of a pointer to that malloced area.
>This would mean that the function wouldn't require an even deeper level
>pointer to the code and would save sizeof(pointer) space in the function as
>a bonus.  While that does compile in VC++, it only compiles while Microsoft
>extensions are enabled (I'm writing my test code in VC++ 6.0, I'm waiting
>for my recently purchased MSDN Developer CustomerID to kick in).

Right, MS has their own variation of this.

Quote:
>   My concerns however are that one of the biggest reasons I choose to
>develop this project in Windows first instead of a Unix flavor or on a Mac
>(although Unix/Linux/Solaris x86 is my main target) is that IDE for VC.NET
>is just so extraordinary [ plus you just _HAVE_ to love the documentation
>and help ].  It also doesn't hurt that VC++ is such a smart optimizer, but
>that's just why I decided to actually compile the Windows final version in
>VC++, not why I'm developing in it.

Ok.

Quote:
>I looked at the Comeau site and I must
>admit I didn't quite fully grasp the concept of what it is.  From my
>understanding it's basically the top layer of a compiler, it compiles into
>the middle code of another compiler, and then lets that compiler compile
>native code from it's own middle language.

That's right, and it happens transparently (for the compilers we support,
for those we don't a custom port would need to be done by us for you).
Currently, it used VC++ for Windows.

Quote:
>What concerns me is of course
>that I noticed Comeau is text prompt based system, and I heard no mention of
>it being an IDE.  To me this is extraordinarily important and why I choose
>VC.NET in the first place.

Right, Comeau doesn't come with an IDE, and currently does not
integrate into Visual Studio or .NET, but we're working on that.

Quote:
>   So my question to you is how could I leverage the IDE of VC.NET, the
>compiler of Comeau, and the middle language to native code abilities of
>VC.NET and GCC without making this project more difficult than it already
>is?

You can't leverage Comeau C++ off of the IDE yet, though it can be
used from the command line as a 3rd party tool of sorts to VC++.
--
Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?


Tue, 03 Aug 2004 05:23:21 GMT  
 Byte Code; Direct Style

Quote:

>Jonathan: I not sure if I fully understand your concern about the Visual C++
>compiler bounds-checking a switch statement. I do not believe that any C++
>compiler will bounds check the expression in a switch-statement. If there is
>not a case label that corresponds to the value of the expression then the
>compiler will choose the default label, or if there is not a default label,
>it will just skip the body of the switch-statement.

Maybe the worry was the set of instructions:

  cmp eax, 12 // 12 is just an example
  jg end_of_switch
  jmp jmp_table[eax*4]

?

It would slow down the code a bit (especially on the not too good
IA-32) compared to not generating those instructions and just doing

  jmp jmp_table[eax*4]

However, since we are talking about pretty deep stuff here, would the
VC specific __assume help the optimizer? Would something likt the
following perhaps help?

extern unsigned int iVal;
__assume(iVal < 2);
switch (iVal) {
        case 0: do_zero_stuff(); break;
        case 1: do_one_stuff(); break;

Quote:
}

Would the check still be made (if iVal < 2), or would that __assume
hint to the optimizer tell it that "these are the only two legal
values in this code and if you gimme something else it's your fault",
and not insert the extra "bounds"?

/Mike



Tue, 03 Aug 2004 05:22:35 GMT  
 Byte Code; Direct Style


Quote:

> However, since we are talking about pretty deep stuff here, would the
> VC specific __assume help the optimizer? Would something likt the
> following perhaps help?

> extern unsigned int iVal;
> __assume(iVal < 2);
> switch (iVal) {
> case 0: do_zero_stuff(); break;
> case 1: do_one_stuff(); break;
> }

> Would the check still be made (if iVal < 2), or would that __assume
> hint to the optimizer tell it that "these are the only two legal
> values in this code and if you gimme something else it's your fault",
> and not insert the extra "bounds"?

> /Mike

It's even simpler.  Try:

switch (iVal) {
case 0: do_zero_stuff(); break;
case 1: do_one_stuff(); break;
default: __assume(0);

Quote:
};

In our code, we have a macro UNREACHED which is an assertion in test builds,
and __assume(0) in retail builds.

Jason Shirk
VC++ Compiler Team



Tue, 03 Aug 2004 05:31:55 GMT  
 Byte Code; Direct Style
   Thanks Mike, that's what I was trying to say.  I was in the middle of
trying to figgure out how to keep gcc from optimizing a switch so I could
give a demo, thank god you answered since gcc's assembly is pretty ugly,
doesn't fit the intel standards.  Also, thanks to Mike and Jason for clueing
me into assume, that's fantastic.

   That leaves one final bit, if I nest my switch statment in an infinite
loop is VC++ smart enough to choose to tail call (as explained earlier); go
to the next case in the switch without going back to the begining and
reusing that code.  In otherwords, an inline switch at the end of every
case.  I realize that due to caching it may actually be optimial in some
cases to go to the begining and reuse the jump into the vector table [ as in
Mike's example: jmp jmp_table[eax*4] ].  So what I'm asking is, if having
that jump in the end of every case's code is more efficent in the specific
case, does VC++ put it there?

   I'm really sorry I'm being such a nit-picker, but speed really does
matter in this case.  Also if I were lazy enough to just take the first
thing that worked I'd probarbly still be writing code in VB like my
highschool taught me all so well [ teacher wouldn't let us use gotos, but
also wouldn't let use classes or modules since it would just complicate our
programs ].

--Jonathan Ross, thanks



Tue, 03 Aug 2004 01:19:23 GMT  
 Byte Code; Direct Style

Quote:
> Right, Comeau doesn't come with an IDE, and currently does not
> integrate into Visual Studio or .NET, but we're working on that.

Wow wow wooooooow.  Are you saying that Comeau will eventually let me write
C++ code in the VC.NET interface, write and debug Comeau code (maybe even
profile), etc., etc., compile into MSML, then get VS.NET to optimize the
heck out of it and after I'm done testing I can take the source, compile it
in a different platform's Comeau?

VS IDE (debugging, editing) + Comeau Code -> MSML     -> Optimized the heck
out of Win32/64 code
                     Comeau Code developed above -> Other ML -> Other Native
Code

   To think, I was actually starting to doubt my MSDN Developer
Subscription.  Granted, I may not have gotten that little flow perfectly but
if it's anything like that...  Sign me up for beta testing and let me buy
the first copy you sell :)

--Jonathan Ross, very very e{*filter*}d
PS:  Got a link to it describing it any further?  I think this is getting a
bit off thread here, just post the link so everyone can read it and we don't
clutter the boards anymore.  And I'm serious about beta testing, I tend to
break the unbreakable; as you can probably see why from this thread.



Tue, 03 Aug 2004 01:31:44 GMT  
 Byte Code; Direct Style

Quote:

>   Thanks Mike, that's what I was trying to say.  I was in the middle of
>trying to figgure out how to keep gcc from optimizing a switch so I could
>give a demo, thank god you answered since gcc's assembly is pretty ugly,

It's not GCC, it's the horrible AT&T version that GNU uses! :-)

Quote:
>doesn't fit the intel standards.  Also, thanks to Mike and Jason for clueing
>me into assume, that's fantastic.

I agree that you can get some pretty amazing results from __assume,
but also realize it's not perfect.

To display how some switch code without __assume is generated, try to
compile duffs device (just do a google search, you'll find it at e.g.
lysator.liu.se). It's actually quite interesting to see how some
compilers generate code, even when told to optimize for size (O1).
(I hope e.g. Jason will try this now, right? :->)

Quote:
>That leaves one final bit, if I nest my switch statment in an infinite
>loop is VC++ smart enough to choose to tail call (as explained earlier); go
>to the next case in the switch without going back to the begining and
>reusing that code.

I don't know about VC7, but IIRC the VC6 optimizer did no such thing.

I'm not completely sure what you're trying to do, but if you can use
C++ I can tell you that inlined function templates can sometimes be a
helluvalot more efficient than any "ordinary" code. I have f.e..
written a user-mode AlphaBlend that's on average ~10% faster than MS'
W2k version that runs in kernel-mode (!) using some carefully selected
template inlines (and I'm not cheating and using MMX or some such).

Quote:
> In otherwords, an inline switch at the end of every
>case.  I realize that due to caching it may actually be optimial in some
>cases to go to the begining and reuse the jump into the vector table [ as in
>Mike's example: jmp jmp_table[eax*4] ].  So what I'm asking is, if having
>that jump in the end of every case's code is more efficent in the specific
>case, does VC++ put it there?

Actually, that question is more-or-less impossible to answer without
knowing 1) what CPU you're targetting, 2) how the "pipes" are filled
at that point. Since you have MSVC I assume you have access to the crt
src. Have a look at e.g. memcpy.asm and look at the comments about U
and V. That are the two pipes in a Pentium processor. Running that
code on e.g a 486 would probably be slower than a simple repne (I'm
just guessing here), and I'd also assume that a PIII optimized version
would look nothing like it.
Just to display that the number of variables are quite large. :-)

Quote:
>I'm really sorry I'm being such a nit-picker, but speed really does
>matter in this case.

Then I'd suggest you drop by IAL (Intel Architecture Labs) and see
what they might have. Pipe bubbles are killers as you probably know,
and imagine something like the P4 getting a bubble in it's 20-stage
(or was it 16) pipe. :-<

Quote:
>Also if I were lazy enough to just take the first
>thing that worked I'd probarbly still be writing code in VB like my
>highschool taught me all so well [ teacher wouldn't let us use gotos, but
>also wouldn't let use classes or modules since it would just complicate our
>programs ].

Thank god there are still people that care about small size and high
performance! What if everyone just cared about dotnot? :-)

/Mike



Tue, 03 Aug 2004 08:54:24 GMT  
 Byte Code; Direct Style

Quote:

>> Right, Comeau doesn't come with an IDE, and currently does not
>> integrate into Visual Studio or .NET, but we're working on that.

>Wow wow wooooooow.  Are you saying that Comeau will eventually let me write
>C++ code in the VC.NET interface, write and debug Comeau code (maybe even
>profile), etc., etc., compile into MSML, then get VS.NET to optimize the
>heck out of it and after I'm done testing I can take the source, compile it
>in a different platform's Comeau?

That's the intent, whether it can actually occur is another situation.

Quote:
>VS IDE (debugging, editing) + Comeau Code -> MSML     -> Optimized the heck
>out of Win32/64 code
>                     Comeau Code developed above -> Other ML -> Other Native
>Code

>   To think, I was actually starting to doubt my MSDN Developer
>Subscription.  Granted, I may not have gotten that little flow perfectly but
>if it's anything like that...  Sign me up for beta testing and let me buy
>the first copy you sell :)

>--Jonathan Ross, very very e{*filter*}d
>PS:  Got a link to it describing it any further?  I think this is getting a
>bit off thread here, just post the link so everyone can read it and we don't
>clutter the boards anymore.  And I'm serious about beta testing, I tend to
>break the unbreakable; as you can probably see why from this thread.

There's no link to this yet.  It still needs work first.
And now that .NET is a reality, we need to revisit it.
Hopefully something will appear sooner than later...
--
Greg Comeau  GA BETA:4+ New Windows Backends  PLUS 'export' beta online!
Comeau C/C++ ONLINE ==>     http://www.*-*-*.com/
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?


Wed, 04 Aug 2004 00:27:17 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. argument list style (was: coding style)

2. 12 days of Christmas C code, top secret style of code writing

3. Directed graph source code?

4. source code for a directed graph

5. MethodRental and getting the code bytes from ILGenerator

6. Reverse byte order - my code

7. multi-byte char codes

8. Request the code for transfering a byte used C througth serial print

9. Embedded Systems: Estimate bytes/line of code

10. Estimate bytes/line of code?

11. bytes/octets (was Re: Writing portable C code

12. Byte me : ) (Was Re: Writing portable code)

 

 
Powered by phpBB® Forum Software