Re: Semantics of Cmm `switch` statement?

2022-01-11 Thread Andreas Klebinger

Hi Norman,

I vaguely remember that we "finish" such unterminated code blocks by
jumping to the block again.

That is for code like this:

    myswitch2 (bits32 n) {
  foreign "C" D();
    }

We produce code like this:

    {
  cg: call "ccall" arg hints:  []  result hints:  [] D();
  goto cg;
    }

Instead of blowing up the compiler at compile time or the program at
runtime.

For switch statements I think blocks are just syntactic sugar. E.g. if
you write

case n: {  }

it's treated as if you wrote

case n: jmp codeBlock;
...

codeBlock:
    

And since your blocks don't terminate we get the behaviour you are seeing.
But I haven't looked at any of the code related to this so it's possible
I got it wrong.

Cheers
Andreas


Am 12/01/2022 um 01:02 schrieb Norman Ramsey:

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
  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
  _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
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Semantics of Cmm `switch` statement?

2022-01-11 Thread Norman Ramsey
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
 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
 _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
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs