GHC's internal confusion about Ints and Words

Moritz Angermann moritz.angermann at
Tue Oct 20 01:50:41 UTC 2020

Hi there!

So there is a procedure calling convention that for reasons I did not fully
understand, but seem to be historically grown, uses packed arguments for
those that are spilled onto the stack. On top of that, CInt is 32bit, Word
is 64bits. This provides the following spectacle:

While we know in STG that the CInt is 32bits wide, when lowered into Cmm,
it's represented as I64 in the arguments to the C function.  Thus packing
based on the format of the Cmm type would yield 8 bytes. And now, all
further packed arguments have the wrong offset (by four).

Specifically in GHC.Cmm.Utils we find:

primRepCmmType :: Platform -> PrimRep -> CmmType
primRepCmmType platform IntRep = bWord platform

mkIntCLit :: Platform -> Int -> CmmLit
mkIntCLit platform i = CmmInt (toInteger i) (wordWidth platform)

The naive idea to just fix this and make them return cIntWidth instead,
seemingly produces the correct Cmm expressions at a local level, but
produces a broken compiler.

A second approach could be to extend the Hints into providing sizes, and
using those during the foreign call generation to pack spilled arguments.
This however appears to be more of a patching up of some fundamental
underlying issue, instead of rectifying it properly.

Maybe I'll have to go down the Hint path, it does however break current Eq
assumptions, as they are sized now, and what was equal before, is only
equal now if they represent the same size.

>From a cursory glance at the issues with naively fixing the width for Int,
it seems that GHC internally assumes sizeof(Int) = sizeof(Word).  Maybe
there is a whole level of HsInt vs CInt discrimination missing?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the ghc-devs mailing list