switches in GCC JIT?

David Malcolm dmalcolm@redhat.com
Thu Jan 1 00:00:00 GMT 2015


On Tue, 2015-06-23 at 21:01 +0100, Dibyendu Majumdar wrote:
> On 23 June 2015 at 01:25, David Malcolm <dmalcolm@redhat.com> wrote:
> > As it happens, none of the bytecode languages I've implemented so far
> > have switch-like constructs.
> >
> 
> Often bytecodes in dynamic languages when translated do not exactly
> map to C constructs, so this is not surprising I think.
> 
> > But I see now that the JVM has opcodes "lookupswitch" and "tableswitch";
> > those alone make a compelling case for libgccjit supporting switches.
> >
> > I'm working on it now; the API I'm thinking of looks like this:
> >
> > extern void
> > gcc_jit_block_end_with_switch (gcc_jit_block *block,
> >                                   gcc_jit_location *loc,
> >                                   gcc_jit_rvalue *expr,
> >                                   gcc_jit_block *default_block,
> >                                   int num_cases,
> >                                   gcc_jit_rvalue **case_min_values,
> >                                   gcc_jit_rvalue **case_max_values,
> >                                   gcc_jit_block **case_blocks);
> >
> >
> > thus supporting ranged cases, whilst also allowing individual values, by
> > simply passing in the same table for both case_min_values and
> > case_max_values.
> >

(fwiw I have it mostly working)

> The API looks ok to me but would it be more user friendly if you
> created a struct to hold the case values and blocks together? That is:
> 
> struct case {
>   gcc_jit_rvalue *min_value;
>   gcc_jit_rvalue *max_value;
>   gcc_jit_block *block;
> };
> 
> Then the last three parameters could be replaced by 'struct case *'.

Is is actually easier that way?

If so, it would probably need to be "struct gcc_jit_case", both for the
sake of namespacing, and because "case" is a reserved word.

That said, it would be the first non-opaque struct in the API, which
makes me nervous; I guess we could make it opaque like this:

extern gcc_jit_case *
gcc_jit_context_new_case (gcc_jit_context *ctxt,
  	                   gcc_jit_rvalue *min_value,
                          gcc_jit_rvalue *max_value,
                          gcc_jit_block *block);

though I don't know if that's better.

I prefer the original API, fwiw (with 3 arrays), as it doesn't introduce
a new type.

> >> BTW, if we don't have switches, we should at least have indirect jumps,
> >> and the ability to retrieve, as a label, the starting address of any
> >> basic block. (i.e. the equivalent of goto *ptr; and of &&label in C). If
> >> that is possible today, we need more documentation about that (at least
> >> saying that switch statements could be translated that way)
> >>
> 
> It would also be useful to have the indirect jump capability - LLVM
> offers this and I used it in Ravi to help with performance (although
> in the particular use case I did not really see much benefit).

This isn't yet supported by libgccjit.  Maybe the API might look
something like this:

extern gcc_jit_rvalue *
gcc_jit_block_get_address (gcc_jit_block *block);

giving an rvalue of type void *, and:

extern void
gcc_jit_block_end_with_indirect_jump (gcc_jit_block *block,
                                      gcc_jit_rvalue *expr);

where "expr" must be of type void *, obtained via
gcc_jit_block_get_address.

That said, what use-cases are you thinking of?   The one I'm familiar
with is threaded dispatch of the big switch statement typically seen in
an interpreter, but presumably anyone using libgccjit is unrolling the
switch statement into code.

Dave



More information about the Jit mailing list