question about coercions between primitive types in STG level

Ömer Sinan Ağacan omeragacan at gmail.com
Mon Dec 7 16:21:59 UTC 2015


Thanks Simon, primops worked fine, but not I'm getting assembler errors(even
though -dcore-lint, -dstg-lint and -dcmm-lint are all passing).

The error is caused by this STG expression:

    case (#,#) [ds_gX8 ds_gX9] of _ {
      (#,#) tag_gWR ubx_gWS ->
          case tag_gWR of tag_gWR {
            __DEFAULT -> GHC.Err.undefined;
            1# ->
                let {
                  sat_sWD :: [GHC.Types.Char] =
                      \u srt:SRT:[roK :-> GHC.Show.$fShowInt] []
                          let { sat_sWC :: GHC.Types.Int = NO_CCS
GHC.Types.I#! [ubx_gWS];
                          } in  GHC.Show.show GHC.Show.$fShowInt sat_sWC; } in
                let {
                  sat_sWB :: [GHC.Types.Char] =
                      \u srt:SRT:[0k :-> GHC.CString.unpackCString#] []
                          GHC.CString.unpackCString# "Left "#;
                } in  GHC.Base.++ sat_sWB sat_sWD;
            2# ->
                let {
                  co_gWT :: GHC.Prim.Float# =
                      sat-only \s [] int2Float# [ubx_gWS]; } in
                let {
                  sat_sWH :: [GHC.Types.Char] =
                      \u srt:SRT:[rd2 :-> GHC.Float.$fShowFloat] []
                          let { sat_sWG :: GHC.Types.Float = NO_CCS
GHC.Types.F#! [co_gWT];
                          } in  GHC.Show.show GHC.Float.$fShowFloat
sat_sWG; } in
                let {
                  sat_sWF :: [GHC.Types.Char] =
                      \u srt:SRT:[0k :-> GHC.CString.unpackCString#] []
                          GHC.CString.unpackCString# "Right "#;
                } in  GHC.Base.++ sat_sWF sat_sWH;
          };
    };

In the first case(when the tag is 1#) I'm not doing any coercions, second
argument of the tuple is directly used. In the second case(when the tag is 2#),
I'm generating this let-binding:

    let {
      co_gWT :: GHC.Prim.Float# =
          sat-only \s [] int2Float# [ubx_gWS]; }

And then in the RHS of case alternative I'm using co_gWT instead of ubx_gWS,
but for some reason GHC is generating invalid assembly for this expression:

    /tmp/ghc2889_0/ghc_2.s: Assembler messages:

    /tmp/ghc2889_0/ghc_2.s:125:0: error:
         Error: `16(%xmm1)' is not a valid base/index expression
    `gcc' failed in phase `Assembler'. (Exit code: 1)

The assembly seems to be:

    ==================== Asm code ====================
    .section .text
    .align 8
    .quad 4294967296
    .quad 18
    co_gWT_info:
    _cY7:
    _cY9:
    movq 16(%xmm1),%rax
    cvtsi2ssq %rax,%xmm0
    movss %xmm0,%xmm1
    jmp *(%rbp)
    .size co_gWT_info, .-co_gWT_info

Do you have any ideas why this may be happening?

2015-12-07 7:23 GMT-05:00 Simon Peyton Jones <simonpj at microsoft.com>:
> If memory serves, there are primops for converting between unboxed values of different widths.
>
> Certainly converting between a float and a non-float will require an instruction on some architectures, since they use different register sets.
>
> Re (2) I have no idea.  You'll need to get more information... pprTrace or something.
>
> Simon
>
> |  -----Original Message-----
> |  From: ghc-devs [mailto:ghc-devs-bounces at haskell.org] On Behalf Of Ömer
> |  Sinan Agacan
> |  Sent: 06 December 2015 18:25
> |  To: ghc-devs <ghc-devs at haskell.org>
> |  Subject: question about coercions between primitive types in STG level
> |
> |  Hi all,
> |
> |  In my compiler pass(D1559, see ElimUbxSums.hs) I'm doing some unsafe
> |  coercions at the STG level. It works fine for lifted types, but for
> |  unlifted ones I'm having some problems. What I'm trying to do is given
> |  a number of primitive types I'm finding the one with biggest size, and
> |  then generating a constructor that takes this biggest primitive type
> |  as argument.
> |
> |  The problem is that this is not working very well - GHC is generating
> |  illegal instructions that try to load a F32 value to a register
> |  allocated for I64, using movss instruction.
> |
> |  CoreLint is catching this error and printing this:
> |
> |      Cmm lint error:
> |        in basic block c1hF
> |          in assignment:
> |            _g16W::I64 = 4.5 :: W32;   // CmmAssign
> |            Reg ty: I64
> |            Rhs ty: F32
> |
> |  So I have two questions about this:
> |
> |  1. Is there a way to safely do this? What are my options here? What
> |  I'm trying
> |     to do is to use a single data constructor field for different
> |  primitive
> |     types.  The field is guaranteed to be as big as necessary.
> |
> |  2. In the Cmm code shown above, the type annotation is showing `W32`
> |  but in the
> |     error message it says `F32`. I'm confused about this, is this error
> |  message
> |     given because the sizes don't match? (64bits vs 32bits) Why the
> |  type
> |     annotation says W32 while the value has type F32?
> |
> |  Thanks..
> |  _______________________________________________
> |  ghc-devs mailing list
> |  ghc-devs at haskell.org
> |  https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.h
> |  askell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
> |  devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7ced6a1fbfa6254e5
> |  2a7d808d2fe6a9a63%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7j3fQs4
> |  ox67SZbA4jv4uPVVdvp5X5yUUuMaqp4sh%2fpg%3d


More information about the ghc-devs mailing list