Using CPP in Cmm

Johan Tibell johan.tibell at
Thu Jun 9 15:44:43 CEST 2011


I'm trying to write a test case to make sure memset gets unrolled
correctly by the backend. Unrolling only happens when the alignment
and size is statically known so writing a simple Cmm loop that calls
memset won't work as the sizes won't be statically known. I want to
test memset with a large (e.g. 10-20) different variations of
alignments and sizes and I don't want to cut-n-paste large chunks of
code so I tried the following (best viewed with a fixed-width font):

#define TEST_MEMSET(ALIGN,SIZE)                                        \
    W_ size, src, dst, off, alignV, set;                               \
    bits8 set8;                                                        \
    // Need two versions as memset takes a word for historical reasons \
    // but really its a bits8. We check that setting has ben done      \
    // correctly at the bits8 level, so need bits8 version for         \
    // checking.                                                       \
    set = 4;                                                           \
    set8 = 4::bits8;                                                   \
    size = SIZE;                                                       \
    alignV = ALIGN;                                                    \
    ("ptr" src) = foreign "C" malloc(size);                            \
    ("ptr" dst) = foreign "C" malloc(size);                            \
    prim %memset(src "ptr", set, size, alignV) [];                     \
    // Check memset worked                                             \
    off = 0;                                                           \
while1:                                                                \
    if (off == size) {                                                 \
        goto while1_end;                                               \
    }                                                                  \
    if (bits8[src + off] != set8) {                                    \
        foreign "C" printf(memsetErr "ptr") [];                        \
        goto while1_end;                                               \
    }                                                                  \
    off = off + 1;                                                     \
    goto while1;                                                       \
while1_end:                                                            \
    foreign "C" free(src);                                             \
    foreign "C" free(dst);

    // Test many different combinations here.

    jump %ENTRY_CODE(Sp(0));

This seems to work (i.e. the test passes) but it shouldn't! I'd expect
the fact that we generate several labels (and temp registers) with the
same name to lead to problems, but it doesn't seem to. I initially
tried to use the CPP ## string concatenation operator to create unique
names (tedious, but works) but GHC runs CPP in traditional mode so
that doesn't work. I also tried to introduce local {} blocks in the
Cmm to deal with the scoping of identifiers (like you would in C) but
that's not supported.

Any idea of how I can generate the same piece of Cmm code (that
contains labels and locally defined identifiers) multiple times
without name capturing?


More information about the Glasgow-haskell-users mailing list