<p dir="ltr">GCC has a non-standard extension to do this, I've used it to get great performance wins writing emulators. I love this feature, love to see it in D!</p>
<div class="gmail_quote">On 1 Jun 2013 15:30, "Alex Rønne Petersen" <<a href="mailto:alex@lycus.org">alex@lycus.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
<br>
I'm sure this has been brought up before, but I feel I need to bring it up again (because I'm going to be writing a threaded-code interpreter): <a href="http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html" target="_blank">http://gcc.gnu.org/onlinedocs/<u></u>gcc/Labels-as-Values.html</a><br>

<br>
This is an incredibly important extension. The final switch statement is not a replacement because it doesn't allow the programmer to store a label address directly into a code stream, which is what's essential to write a threaded-code interpreter.<br>

<br>
The Erlang folks went through hell just to use this feature; see the 5th Q at: <a href="http://www.erlang.org/doc/installation_guide/INSTALL-WIN32.html#Frequently-Asked-Questions" target="_blank">http://www.erlang.org/doc/<u></u>installation_guide/INSTALL-<u></u>WIN32.html#Frequently-Asked-<u></u>Questions</a><br>

<br>
The idea is to be able to write code like this:<br>
<br>
----<br>
<br>
import std.algorithm;<br>
<br>
enum Op : ubyte<br>
{<br>
    imm,<br>
    add,<br>
    sub,<br>
    // ...<br>
    ret,<br>
}<br>
<br>
final class Insn<br>
{<br>
    Op op;<br>
    size_t[] args;<br>
    void* lbl;<br>
    Insn next;<br>
}<br>
<br>
final class State<br>
{<br>
    Insn pc;<br>
    size_t[64] regs;<br>
}<br>
<br>
size_t interp(Insn[] code)<br>
{<br>
    // Set up the instruction stream with label addresses<br>
    // the first time that it is executed. Label addresses<br>
    // are stable, so we only do this once.<br>
<br>
    foreach (insn; code.filter!(x => !x.lbl)())<br>
    {<br>
        void* lbl;<br>
<br>
        with (Op)<br>
        {<br>
            final switch (insn.op)<br>
            {<br>
                case imm: lbl = &&handle_imm; break;<br>
                case add: lbl = &&handle_add; break;<br>
                case sub: lbl = &&handle_sub; break;<br>
                // ...<br>
                case ret: lbl = &&handle_ret; break;<br>
            }<br>
        }<br>
<br>
        insn.lbl = lbl;<br>
    }<br>
<br>
    // Start interpreting the entry instruction.<br>
<br>
    auto state = new State;<br>
    state.pc = code[0];<br>
    goto *state.pc.lbl;<br>
<br>
    // Interpreter logic follows...<br>
<br>
    // The whole point is to avoid unnecessary function<br>
    // calls, so we use a mixin template for this stuff.<br>
    enum advance = "state.pc = state.pc.next;" ~<br>
                   "goto *state.pc.lbl;";<br>
<br>
    handle_imm:<br>
    {<br>
        state.regs[state.pc.args[0]] = state.pc.args[1];<br>
        mixin(advance);<br>
    }<br>
<br>
    handle_add:<br>
    {<br>
        state.regs[state.pc.args[0]] = state.regs[state.pc.args[1]] + state.regs[state.pc.args[2]];<br>
        mixin(advance);<br>
    }<br>
<br>
    handle_sub:<br>
    {<br>
        state.regs[state.pc.args[0]] = state.regs[state.pc.args[1]] - state.regs[state.pc.args[2]];<br>
        mixin(advance);<br>
    }<br>
<br>
    // ...<br>
<br>
    handle_ret:<br>
    {<br>
        return state.regs[state.pc.args[0]];<br>
    }<br>
<br>
    assert(false);<br>
}<br>
<br>
----<br>
<br>
Notice that there are no function calls going on. Just plain jumps all the way through. This is a technique that many real world interpreters use to get significant speedups, and I for one think we desperately need it.<br>

<br>
Implementing it should be trivial as both LLVM and GCC support taking the address of a block. I'm sure the DMD back end could be extended to support it too.<br>
<br>
-- <br>
Alex Rønne Petersen<br>
<a href="mailto:alex@alexrp.com" target="_blank">alex@alexrp.com</a> / <a href="mailto:alex@lycus.org" target="_blank">alex@lycus.org</a><br>
<a href="http://alexrp.com" target="_blank">http://alexrp.com</a> / <a href="http://lycus.org" target="_blank">http://lycus.org</a><br>
</blockquote></div>