Re: Doing without GCC's statement-blocks-as-expressions extension

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Nicholas Sherlock <n.sherlock@xxxxxxxxx> writes:

> I'm developing a translator which converts code from a language I'm
> designing (which is an object-oriented language similar to Java) into
> C. At the moment, I'm making heavy use of GCC's GNU99
> statement-blocks-as-expressions extension. This means that the code I
> generate can't be used by my friends who use VC++ or other
> compilers. I would like to generate code much closer to standard C99.
>
> At the moment I am using this extension to call virtual methods in my
> language. For a virtual call on an object instance "objectexpression",
> with a signature like "int square(int)", with "5" as the argument, I
> generate this expression:
>
> ({ struct object_header * temp=objectexpression; ((int(*)(struct
> object_header *, int))(temp->vmt[VMTINDEX_MyObject_square]))(temp,
> 5);})
>
> "struct object_header" is the struct that all of my object types begin
> with. "object_header.vmt" is a void** - an array of function pointers
> for the VMT of my object. "VMTINDEX_MyObject_square" is the index of
> the method I want to call in the VMT. The first argument to the called
> function is the address of the object instance being used.
>
> The problem is that I cannot figure out a good way of writing this
> without using this GCC-specific extension. "objectexpression" can have
> side effects, so I cannot evaluate it more than once. And yet I need
> to use it at least twice: firstly to look up the entry in the object's
> VMT, and secondly to provide the evaluated expression as the "this"
> argument for the method.

Since you are generating C code, you control the horizontal and the
vertical.  Count the number of virtual calls you have, and emit 
    struct object_header *__my_private_temp_1;
    struct object_header *__my_private_temp_2;
    ...
at the start of the C function.   Then for each virtual call do
    (__my_private_temp_N = objectexpression,
     ((int(*)(struct object_header *, int))
      (temp->vmt[VMTINDEX_MyObject_square))(__my_private_temp_N, 5)))
replacing N with the index of the call.

Ian

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux