GHC creates untagged closure references in strict field of static closures.
Pretty
defines a handful of shorthands of the form: lparen = char '('
These get compiled to static closures as expected:
STG:
Pretty.lparen1 :: Pretty.TextDetails
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] =
CCS_DONT_CARE Pretty.Chr! ['('#];
Pretty.lparen :: Pretty.Doc
[GblId, Caf=NoCafRefs, Str=m3, Unf=OtherCon []] =
CCS_DONT_CARE Pretty.TextBeside! [Pretty.lparen1 1# Pretty.Empty];
==================== Asm code ====================
2019-04-08 21:17:52.2702151 UTC
.section .data
.align 8
.align 1
.globl Pretty.lparen1_closure
Pretty.lparen1_closure:
.quad Pretty.Chr_con_info
.quad 40
==================== Asm code ====================
2019-04-08 21:17:52.2891641 UTC
.section .data
.align 8
.align 1
.globl Pretty.lparen_closure
Pretty.lparen_closure:
.quad Pretty.TextBeside_con_info
.quad Pretty.lparen1_closure+1
.quad Pretty.Empty_closure+1
.quad 1
.quad 3
So far so good, however in the X86 pretty printer we have this code
which is essentially a redefinition of lparen:
stg
lvl67_rvZv :: Pretty.Doc
[GblId, Caf=NoCafRefs, Str=m3, Unf=OtherCon []] =
CCS_DONT_CARE Pretty.TextBeside! [Pretty.lparen1 1# Pretty.Empty];
==================== Asm code ====================
2019-04-08 23:28:52.8210512 UTC
.section .data
.align 8
.align 1
lvl67_rvZv_closure:
.quad Pretty.TextBeside_con_info
.quad Pretty.lparen1_closure
.quad Pretty.Empty_closure+1
.quad 1
.quad 3
Where lparen doesn't get tagged. It seems related to #15155 (closed) however there is no casting going on in this case.
This happens with all the char docs as far as I can tell.
So far I wasn't able to reproduce the issue outside of GHC. But I'Ve reproduced it on both Linux and Windows with HEAD.
Sidenote: It also seems we inline all the lparens, rparens, ...
bindings just to then then float them out again, which causes them to be duplicated. Once in the pretty module, once in Ppr. Maybe also something we could avoid.