Semantics of Cmm `switch` statement?

Norman Ramsey nr at cs.tufts.edu
Wed Jan 12 00:02:29 UTC 2022


For testing purposes, I created the following Cmm program:

    myswitch (bits32 n) {
      switch [0 .. 4] n {
        case 0, 1: { foreign "C" A(); }
        case 2: { foreign "C" B(); }
        case 4: { foreign "C" C(); }
        default: { foreign "C" D(); }
      }
      return (666);
    }

In the original C-- specification, it's pretty clear that when, say,
the call to foreign function `A` terminates, the switch statement is
supposed to finish and function `myswitch` is supposed to return 666.
What actually happens in GHC is that this source code is parsed into a
control-flow graph in which execution loops forever, repeating the
call.  The relevant fragment of the prettyprinted CFG looks like this:

   {offset
     ca: // global
         _c1::I32 = %MO_XX_Conv_W64_W32(R1);
         //tick src<programs/panic.cmm:(1,21)-(9,1)>
         switch [0 .. 4] _c1::I32 {
             case 0, 1 : goto c5;
             case 2 : goto c7;
             case 4 : goto c9;
             default: {goto c3;}
         }
     ...
     c5: // global
         //tick src<programs/panic.cmm:3:16-35>
         _c4::I64 = A;
         call "ccall" arg hints:  []  result hints:  [] (_c4::I64)();
         goto c5;
     ...
   }

Surprising, at least to me.

Is this behavior a bug or a feature?  And if it is a feature, can
anyone explain it to me?


Norman


More information about the ghc-devs mailing list