Sunday, February 21, 2010

Trust your tools...

For my current work I need to show how efficient the generated code is. Fortunately the binutils include a tool called size which "lists the section sizes of an object or archive file".
In order to have representative results I should compile for a platform which is typical for the WSN community. I have chosen the MSP430 because there is a package of a GCC cross compiler for that target in the TinyOS Ubuntu repository.
At first, the numbers looked promising. But at a closer look something was wrong. Investigating the problem emerges something weird.
The function ec_sub6_collect_run from the generated application is defined as:
static void ec_sub6_collect_run()
{
    ec_struct_collect_run*const ec_p_collect_run =
      ec_map_collect_run();
    ec_p_collect_run->ec_continuation();
}

It is merely an artifact of the code generation and will most probably be target of optimization soon. Nevertheless the generated assembler code should not harm too much. But here is the surprise. In the assembler code this function consists of 196 bytes of code! How can this be?
Disassembling the binary reveals this:
00000436 :
 436:   92 12 00 00  call    &0x0000  ;
 43a:   30 41        ret
 43c:   2f 74        subc    @r4,    r15  ;
 43e:   6d 70        subc.b  @r0,    r13  ;
 440:   2f 74        subc    @r4,    r15  ;
 442:   63 2f        jc      $-312        ;abs 0x30a
 444:   72 65        addc.b  @r5+,   r2   ;
 446:   63 65        .word   0x6563; ????
 448:   69 76        subc.b  @r6,    r9   ;
 44a:   65 2e        jc      $-820        ;abs 0x116
 44c:   73 6f        .word   0x6f73; ????
 44e:   63 6b        .word   0x6b63; ????
 450:   00 2f        jc      $-510        ;abs 0x252
 452:   74 6d        addc.b  @r13+,  r4   ;
 454:   70 2f        jc      $-286        ;abs 0x336
 456:   74 63        addc.b  #-1,    r4   ;r3 As==11
 458:   2f 73        subc    #2,     r15  ;r3 As==10
 45a:   65 6e        addc.b  @r14,   r5   ;
[...]
 4f2:   73 69        .word   0x6973; ????
 4f4:   6e 6b        addc.b  @r11,   r14  ;
 4f6:   2e 73        subc    #2,     r14  ;r3 As==10
 4f8:   6f 63        addc.b  #2,     r15  ;r3 As==10
 4fa:   6b 00        .word   0x006b; ????

WTF?!? The second command is a ret. This ends the function. There is no jump before that. So everything below is unreachable code. And anyways, it does not seem to do something meaningful. As long as I haven't completely misunderstood something, I think this is a bug.

If I would not have had a closer look I would have trusted the output of the tools and used it as an argument for or against my hypothesis. Because, as we all know, you can trust your tools. Ouch!

Well, could be a known issue and maybe its even fixed. So I checked the compiler version. Turns out, it's GCC version 3.2.3! According to the GCC release documentation this release is from October 2003. It is over six years old. Double-checking other distribution channels makes clear, that this is really what the TinyOS community uses.

I mean, maybe we should use recent tools before we complain that deploying motes is hard. Maybe it's due to compiler bugs that motes tend to inexplicably reboot now and then.

How can I measure the properties of the generated code now anyway? Do I really have to build a cross compiler from source? So much for unexpected problems...

No comments:

Post a Comment