Showing posts with label gcc. Show all posts
Showing posts with label gcc. Show all posts

Saturday, September 29, 2012

GCC Bug 53812

I was [un]lucky enough to stumble upon a gcc bug recently. I was working on an interpreter for a simple calculator language and in building the jump table for the instructions I was using a construct similar to:


struct Processor {
    bool initialized_;
    std::map< std::string, void* > jump_table;
    Processor () : initialized_(false) {}
    long execute (Program& prog) {
        if (! initialized_) {

            jump_table["+"] = &&block_add;
            jump_table["-"] = &&block_sub;
            jump_table["*"] = &&block_mul;
            jump_table["/"] = &&block_div;
            jump_table[";"] = &&block_end;
            initialized_ = true;
            return execute (prog);
        }
block_add:
        prog.value (prog.arg (0) + prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_sub:
        prog.value (prog.arg (0) - prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_div:
        prog.value (prog.arg (0) / prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_mul:
        prog.value (prog.arg (0) * prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_end:
        return prog.result ();
    }
};


Trying to compile that with g++ 4.6.3 leads to the following error:


calc.cc: In member function 'long int Processor::execute(Program&)';
calc.cc:75:1: internal compiler error: in lower_stmt, at gimple-low.c:432


This bug also manifests itself in 4.7.0 and 4.7.1 but in a another location (verify_gimple_stmt). The oldest copy of gcc I have is 4.3.2 and the bug is not evident in that version.

Granted I was using non-standard constructs in my code but it still felt pretty cool to uncover a bug in such a well-known piece of software.

You can find the bug report (and current status) here

Saturday, July 21, 2012

gcc constructor attribute

It is sometimes helpful to provide a way to 'initialize the system' when you are writing a library. Many times, this manifests itself in the form of a lib_init() call. Similarly, any convenience cleanup would be provided via lib_close(). For a concrete example look at ncurses which provides initscr() and endwin() for this use.

In the case when these routines are required (as they are in ncurses) there is an easier way to provide the proper setup without placing the onus to call these methods on the developer. GCC provides __attribute__((constructor)) and __attribute__((destructor)) which allow for calling methods when a library is loaded and unloaded respectively. These calls happen outside the scope of main. For example,

#include <stdio.h>

__attribute__((constructor)) void init() {
    fprintf (stderr, "constructor\n");
}

int main () {
    return fprintf(stderr, "main\n");
}

This program will output the following:

constructor
main


In the case of a library such as ncurses this is a perfect place to invoke the necessary initialization and cleanup routines. A simplified example library:

__attribute__((constructor))
static void setup() { do_some ("setup"); }

__attribute__((destructor))
static void breakdown() { do_some ("breakdown"); }

void mylib_method (const char * thing) { do_some (thing); }

Now, if a developer links against your library setup() is called when your library is loaded and breakdown() is called when it is unloaded. A nicety of this approach is that it provides the same functionality if the library is pulled in when the executable is loaded or at some later point (via dlopen/dlsym, for example) thus always ensuring a consistent environment for your code.

This is obviously not a fit for all libraries. Only those with setup and cleanup that can be self-contained and are always required would benefit from such an approach. In those cases, however, I prefer this method to the alternative of burdening the developer with requirements of my library.

Sunday, March 13, 2011

Disappearing Ink

This is something I've been wanting to post about for a while now. There was thread on a forum I used to frequent (under a different handle). You can follow the link for details, but the main concept was that in a transition to a GUI environment the developers needed to intercept printf and fprintf calls and do something GUI-related when the GUI was running and leave the software as-is when the GUI was not running. The approach to handle this was to define their own version of the functions and handle the context there. Something like:

extern "C" int fprintf (FILE *__restrict __stream,
       __const char *__restrict __format, ...)
{
   va_list args;
   int return_status = 0;

   va_start(args,__format);

   if (is_gui && (__stream == stdout || __stream == stderr)) {
       return_status = showMessageInGui(NULL, __format, args);
   }
   else {
       return_status = vfprintf(__stream, __format, args);
   }

   va_end(args);
   return return_status;
}

Which only worked part of the time. Complicating matters was the behavior was different across multiple compiler versions: gcc4.2.4 exhibited the problem while gcc3.4.2 did not.

I did some digging around and found out that the newer version of gcc was actually implementing a level of optimization that undermined the approach of redefining printf. Basically, any argument to printf that did not contain a format string (%) to be filled in resulted in a translation by later versions of gcc to a call to fwrite (or puts). For example:

#include <stdio.h>
int main () {
    printf ("With args %d\n", 10);
    printf ("Without\n");
    return 0;
}

Translates to

.LC0:
    .string "With args %d\n"
.LC1:
    .string "Without"
    .text
    ...
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    $.LC1, %edi
    call    puts
    movl    $0, %eax

Notice the puts call for the second call to printf. So regardless of what definition was provided for printf the code would never be executed. Try it with the following:

#include <stdio.h>

int printf (const char * fmt, ...) { return 1/0; }

int main () {
    printf ("w00t\n");
    return 0;
}

You'll see that a warning is presented (for division by zero) but the code runs without issue.

There were several solutions presented in the thread but the OP eventually chose to use gcc flags to prevent this behavior. Using -fno-builtin-fprintf and -fno-builtin-printf allowed compilation without the translation and the redefinition of printf worked as expected.

Saturday, February 5, 2011

Goto Hell

There was a recent stackoverflow challenge question where users were asked to present code that prints the numbers 1 through 1000 without using loops or conditionals. A major theme for answers to the thread was recursion - both compile time and run time. There were a mix of other entries including consecutive function calls to iterate through 1000 increment/print operations, shelling-out to a program such as seq, and several other approaches to the problem. My first opinion was that the only correct solution (according to the spec) was the one that used constructors. I say correct because, technically, recursion is looping.

I posted my own solution for fun which aimed to solve the problem in a way not currently presented. This is both an abuse of compiler extensions and language constructs and is nothing more than me having some fun. Really, don't write code like this. Ever.

#include <stdio.h>

int main () {
    void * label[1001] = { [0 ... 999] = &&again };
    label[1000] = &&done;
    int i = 0;
again:
    printf ("%d\n", i + 1);
    goto *label[++i];
done:
    return 0;
}

I knew that if I considered recursion a loop that my code was also a loop construct. The point of my post, however, was to have a solution that was entirely distinct from what had already been posted and not necessarily to solve the puzzle exactly. This got me thinking though; how close is state machine looping, and recursion, and compile-time recursion to an actual coded loop?

I coded up and compiled three implementations with the intent of determining what the code looked like after the compiler was finished with it. The solutions I chose were: compile time recursion, run time recursion, and my goto looping. Each of these was compared to a basic for loop. Because of template stack depth issues I've only printed up to 10 in these examples. All files were compiled by g++ -O0 (except my solution, see below). In all assembly output the comments are my own.

Compile Time Template Recursion

template< int N > void fun () {
    fun< N-1 >();
    std::cout << N << '\n';
}

As asm

...

_Z3funILi1EEvv:                 ; fun< 1 >
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $1, %esi
    movl    $_ZSt4cout, %edi
    call    _ZNSolsEi
    movq    %rax, %rdi
    movl    $10, %esi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
    leave
    ret
...

_Z3funILi2EEvv:                 ; fun< 2 >
    pushq   %rbp
    movq    %rsp, %rbp
    call    _Z3funILi1EEvv      ; fun< 1 >()
...

_Z3funILi3EEvv:                 ; fun< 3 >
    pushq   %rbp
    movq    %rsp, %rbp
    call    _Z3funILi2EEvv      ; fun< 2 >()
...

main:
    pushq   %rbp
    movq    %rsp, %rbp
    call    _Z3funILi10EEvv     ; fun< 10 >()
    movl    $0, %eax
    leave
    ret

This was a big surprise to me. I assumed that since the compiler was dealing with constant values and there was no class involved that this would actually be generated as a recursive expression. Instead, as you can see, the compiler actually generates all 10 function calls and arranges them to call each other in order where main calls _Z3funILi10EEvv which calls _Z3funILi9EEvv which, in turn, calls _Z3funILi8EEvv and so on - each printing a value after invoking the next function. The process bottoms out at _Z3funILi1EEvv where no function is called and only a value is printed. So this is essentially the same as creating a function for each value to be printed and calling them in order with the exception that the calls are actually nested instead of sequential. This is not recursion.

Run Time Recursion

void fun(int n) {
    n && (fun (n-1), std::cout << n << '\n');
}

As asm

_Z3funi:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    cmpl    $0, -4(%rbp)    ; hidden conditional ;)
    je  .L9
    movl    -4(%rbp), %eax
    leal    -1(%rax), %edi
    call    _Z3funi         ; the recursion
    movl    -4(%rbp), %esi
    movl    $_ZSt4cout, %edi

    ; print setup stuff here

.L9:
    leave
    ret
...

main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $10, %edi
    call    _Z3funi         ; start recursive call
    movl    $0, %eax
    leave
    ret

It is interesting to note that there is a hidden conditional in there. It applies to the short-circuit operation used to terminate the recursion. Other than that, there is nothing unexpected here. The only thing that might have changed this up a bit is if we could have done tail recursion; the compiler might have turned it into a loop. Requiring the print call to be the final executed statement of the function spoils any chance of that.

Goto State Table
 As a side note, I was not able to compile my submission as C++ code. In order to make the comparisons I've just used gcc instead - I don't imagine the result would be any different had g++ been willing to accept the code.

main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $8048, %rsp
    leaq    -8016(%rbp), %rax
    movq    %rax, -8024(%rbp)
    movq    $0, -8032(%rbp)
    movl    $8008, %eax
    cmpl    $8, %eax        ; part of initialization, not my code
    jb  .L2
    movq    $1001, -8040(%rbp)
    movq    -8024(%rbp), %rdi
    movq    -8040(%rbp), %rcx
    movq    -8032(%rbp), %rax
    rep stosq
.L2:
    movq    $.L3, -8016(%rbp) ; again label

    ; lots of lines initializing jump table

    movq    $.L3, -24(%rbp)   ; again label
    movq    $.L4, -16(%rbp)   ; end lable
    movl    $0, -4(%rbp)
.L3:
    movl    -4(%rbp), %eax
    leal    1(%rax), %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    addl    $1, -4(%rbp)
    movl    -4(%rbp), %eax
    cltq
    movq    -8016(%rbp,%rax,8), %rax
    jmp *%rax       ; non-conditional jump
.L4:
    movl    $0, %eax
    leave
    ret

And, for completeness, the for loop

main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    $1, -4(%rbp)
    jmp .L7
.L8:
    movl    -4(%rbp), %esi
    movl    $_ZSt4cout, %edi
    call    _ZNSolsEi
    movq    %rax, %rdi
    movl    $10, %esi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
    addl    $1, -4(%rbp)
.L7:
    cmpl    $1000, -4(%rbp)     ; conditional
    jle .L8
    movl    $0, %eax
    leave
    ret

The really surprising thing to me was the result of C++ template recursion and that the generated code is not recursive. So, in addition to the constructor submission it seems that compile time recursion satisfies both requirements of the problem: no conditionals and no looping.

 As expected, there were conditionals in the resulting assembly for the run time recursion - they are necessary to ensure an exit condition. This is where I believe that I have a leg up on the recursive solutions: the goto approach does not rely on a condition to terminate. In both the run time recursion and straight for loop implementation the resulting [assembly] code boiled down to basically a check for continuation (the conditional) and a jump to a previous location (the loop). Neither are present in the template recursion or the constructor solution. My code sits somewhere in between. Though, I likely lose major points for style.