[cfe-dev] the "computed goto" problem

De Azevedo Piovezan, Felipe via cfe-dev cfe-dev at lists.llvm.org
Thu Oct 3 05:48:15 PDT 2019


Hello cfe,

This year at CppCon (https://www.youtube.com/watch?v=9cPU1NdsgDQ), there was a funny talk about the use of what they called a "computed goto".
I was playing around with the idea, and there might be something incorrect about the code generated by clang when constexpr is involved (starting with 9.0).

The idea is this: the address of a bunch of labels are taken and stored into a table:

  enum bytecode : int8_t { add1, add2, halt };

  constexpr void* labels[] = {
    [bytecode::add1] = &&add1_label,
    [bytecode::add2] = &&add2_label,
    [bytecode::halt] = &&halt_label,
  };

  //labels defined here...

However, this is the IR generated with -O0 -emit-llvm:

  @labels = private unnamed_addr constant [3 x i8*] [i8* blockaddress(@"label1", <badref>), i8* blockaddress(@"label2", <badref>), i8* blockaddress(@"label3", <badref>)], align 16

Note the badrefs! Also, we generate a basic block with no predecessors:

  12: ; No predecessors!
  indirectbr i8* undef, [label <badref>, label <badref>, label <badref>]

As such, as soon as we start optimizing, the whole function is optimized away.
If we remove constexpr, however, everything seems sane. Godbolt link: https://godbolt.org/z/Anc9EI

Any insights on what might be happening here? I suspect a lot of people will play around with this construction just "for fun" and will encounter this.

--
Felipe




More information about the cfe-dev mailing list