Vincent Lefevre | 21 May 19:04 2015
Picon

shared libraries and run-time path issues

I've reported the following problem for libtool 2.4.6:

  http://debbugs.gnu.org/cgi/bugreport.cgi?bug=20622

but I wonder whether something can be improved on the tcc side
(except by using static linking, which works).

When I build GNU MPFR with CC=tcc LD=tcc and do "make check",
I get things like:

  libtool: link: tcc -O2 -o tzeta_ui tzeta_ui.o  -L../src/.libs ./.libs/libfrtests.a -lm
../src/.libs/libmpfr.so -lgmp

The problem is that the MPFR library used at run time is not
../src/.libs/libmpfr.so but the one installed on the system.

--

-- 
Vincent Lefèvre <vincent@...> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

Thomas Preud'homme | 18 May 13:46 2015
Picon

No lazy PLTGOT relocation for TinyCC generated executables

Hi all,

I'm currently working on distention, cleaning up and refactoring tccelf.c. The process already
uncovered some bugs and one of them is that PLT0 is broken for ARM [1]. Since binaries are working, I
investigated and found that the lazy relocation of PLTGOT entries is not in effect. When _start is run,
PLTGOT entries already hold their final values.

I tries comparing the output of readelf -a for an hello world program but there are too many differences and I
didn't spot anything obvious. So I'm turning to you dear TinyCC community[2] for some explanation. Why
does ld.so behave as if RTLD_BIND_NOW was set when running TinyCC generated executables?

[1] it lacks an extra 4 bytes to hold offset to GOT and code in relocate_plt to write the offset in that space.
[2] Michael, I'm asking you explicitly since you are one of the author of the System V ABI for x86_64 and thus
probably know a fair amount on the subject.

Sergey Korshunoff | 18 May 11:25 2015
Picon

tips? define asm symbol as global if it is extern in C

Hello all!
tcc fails to compile the following program
extern void vide(void);
#ifndef TCC_OK
__asm__(".align 4\nvide: ret"); // tcc: error: undefined symbol 'vide'
#else
__asm__(".align 4\n.globl vide\nvide: ret");
#endif
int main (void) { vide(); }

What the problem with tcc? Why tcc need ".globl vide" in asm code and
gcc can compile w/o this declaration?

Joey Payne | 13 May 03:33 2015
Picon

TinyCC REPL

Hi,

I was wondering if there was a way to implement a REPL without having to recompile a long string of code every time using tcc_compile_string. I modified some of the source code to somewhat allow for this, but the symbols from previous code seem to need to be updated, since calling one results in a segfault. That's where I need some help. I'd like to be able to overwrite symbols from the REPL, as well as keep the old ones and use them where appropriate.

I'm using tcc 0.9.26 and my modification to the library is this:

tccelf.c (from line 247):

                //tcc_error_noabort("'%s' defined twice", name);
                sym_index = put_elf_sym(s, value, size,
                                ELFW(ST_INFO)(sym_bind, sym_type), other,
                                sh_num, name);
                esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
                esym->st_shndx = sh_num;
                new_undef_sym = 1;
                esym->st_value = value;
                esym->st_size = size;
                esym->st_other = other;



My c code that I want to work is here:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "libtcc.h"

char my_program[] =
"int sub(int a, int b){return a-b;}\n"
"int foo(int n)\n"
"{\n"
"    printf(\"Hello World!\\n\");\n"
"    printf(\"sub(%d, %d) = %d\\n\", 2*n, n, sub(2*n, n));\n"
"    return 0;\n"
"}\n";

char program_mod_foo[] =
"int foo(int n){\n"
"    printf(\"Hello world!\n\");\n"
"    printf(\"%d\", sub(15,10));\n"
"}\n";

int main(int argc, char **argv)
{
    TCCState *s;
    int (*func)(int);

    s = tcc_new();
    if (!s) {
        fprintf(stderr, "Could not create tcc state\n");
        exit(1);
    }

    /* if tcclib.h and libtcc1.a are not installed, where can we find them */
    if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
        tcc_set_lib_path(s, argv[1]+9);

    /* MUST BE CALLED before any compilation */
    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);

    if (tcc_compile_string(s, my_program) == -1)
        return 1;

    /* relocate the code */
    if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
        return 1;

    /* run the code */
    func(32);

    if (tcc_compile_string(s, program_mod_foo) == -1)
        return 1;

    /* relocate the code */
    if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
        return 1;

    /* get entry symbol */
    func = tcc_get_symbol(s, "foo");

    // should print "Hello World" then 5
    func(32); // segfaults here due to calling sub() again.

    /* delete the state */
    tcc_delete(s);

    return 0;
}

Any help or pointers in the right direction would be of great value to me :)

Thanks!
<div><div dir="ltr">
<span>Hi,</span><div><br></div>
<div>I was wondering if there was a way to implement a REPL without having to recompile a long string of code every time using tcc_compile_string. I modified some of the source code to somewhat allow for this, but the symbols from previous code seem to need to be updated, since calling one results in a segfault. That's where I need some help. I'd like to be able to overwrite symbols from the REPL, as well as keep the old ones and use them where appropriate.</div>
<div><br></div>
<div>I'm using tcc 0.9.26 and my modification to the library is this:</div>
<div><br></div>
<div>tccelf.c (from line 247):<br><br>
</div>
<div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //tcc_error_noabort("'%s' defined twice", name);</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sym_index = put_elf_sym(s, value, size,</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELFW(ST_INFO)(sym_bind, sym_type), other,</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sh_num, name);</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esym-&gt;st_info = ELFW(ST_INFO)(sym_bind, sym_type);</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esym-&gt;st_shndx = sh_num;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new_undef_sym = 1;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esym-&gt;st_value = value;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esym-&gt;st_size = size;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; esym-&gt;st_other = other;</div>
</div>
<div><br></div>
<div><br></div>
<div><br></div>
<div>My c code that I want to work is here:</div>
<div><br></div>
<div>
<div>#include &lt;stdlib.h&gt;</div>
<div>#include &lt;stdio.h&gt;</div>
<div>#include &lt;string.h&gt;</div>
<div><br></div>
<div>#include "libtcc.h"</div>
<div><br></div>
<div>char my_program[] =</div>
<div>"int sub(int a, int b){return a-b;}\n"</div>
<div>"int foo(int n)\n"</div>
<div>"{\n"</div>
<div>" &nbsp; &nbsp;printf(\"Hello World!\\n\");\n"</div>
<div>" &nbsp; &nbsp;printf(\"sub(%d, %d) = %d\\n\", 2*n, n, sub(2*n, n));\n"</div>
<div>" &nbsp; &nbsp;return 0;\n"</div>
<div>"}\n";</div>
<div><br></div>
<div>char program_mod_foo[] =</div>
<div>"int foo(int n){\n"</div>
<div>" &nbsp; &nbsp;printf(\"Hello world!\n\");\n"</div>
<div>" &nbsp; &nbsp;printf(\"%d\", sub(15,10));\n"</div>
<div>"}\n";</div>
<div><br></div>
<div>int main(int argc, char **argv)</div>
<div>{</div>
<div>&nbsp; &nbsp; TCCState *s;</div>
<div>&nbsp; &nbsp; int (*func)(int);</div>
<div><br></div>
<div>&nbsp; &nbsp; s = tcc_new();</div>
<div>&nbsp; &nbsp; if (!s) {</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; fprintf(stderr, "Could not create tcc state\n");</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; exit(1);</div>
<div>&nbsp; &nbsp; }</div>
<div><br></div>
<div>&nbsp; &nbsp; /* if tcclib.h and libtcc1.a are not installed, where can we find them */</div>
<div>&nbsp; &nbsp; if (argc == 2 &amp;&amp; !memcmp(argv[1], "lib_path=",9))</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; tcc_set_lib_path(s, argv[1]+9);</div>
<div><br></div>
<div>&nbsp; &nbsp; /* MUST BE CALLED before any compilation */</div>
<div>&nbsp; &nbsp; tcc_set_output_type(s, TCC_OUTPUT_MEMORY);</div>
<div><br></div>
<div>&nbsp; &nbsp; if (tcc_compile_string(s, my_program) == -1)</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; return 1;</div>
<div><br></div>
<div>&nbsp; &nbsp; /* relocate the code */</div>
<div>&nbsp; &nbsp; if (tcc_relocate(s, TCC_RELOCATE_AUTO) &lt; 0)</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; return 1;</div>
</div>
<div><br></div>
<div>
<div>&nbsp; &nbsp; /* run the code */</div>
<div>&nbsp; &nbsp; func(32);</div>
<div><br></div>
<div>&nbsp; &nbsp; if (tcc_compile_string(s, program_mod_foo) == -1)</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; return 1;</div>
<div><br></div>
<div>&nbsp; &nbsp; /* relocate the code */</div>
<div>&nbsp; &nbsp; if (tcc_relocate(s, TCC_RELOCATE_AUTO) &lt; 0)</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; return 1;</div>
<div><br></div>
<div>&nbsp; &nbsp; /* get entry symbol */</div>
<div>&nbsp; &nbsp; func = tcc_get_symbol(s, "foo");</div>
<div><br></div>
<div>&nbsp; &nbsp; // should print "Hello World" then 5</div>
<div>&nbsp; &nbsp; func(32); // segfaults here due to calling sub() again.</div>
<div><br></div>
<div>&nbsp; &nbsp; /* delete the state */</div>
<div>&nbsp; &nbsp; tcc_delete(s);</div>
<div><br></div>
<div>&nbsp; &nbsp; return 0;</div>
<div>}</div>
</div>
<div><br></div>
<div>Any help or pointers in the right direction would be of great value to me :)</div>
<div><br></div>
<div>Thanks!</div>
</div></div>
grischka | 30 Apr 19:49 2015
Picon
Picon

pp bug

$ tcc bug1.c
bug1.c:109: warning: implicit declaration of function 'AB'
bug1.c:109: error: 'C' undeclared

thanks,

-- gr

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

#define A(X) A ## X
#define AB(X) X ## _FOO
#define C_FOO 77

int main(int argc, char **argv)
{
    return A(B)(C);
}

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

#define A(X) A ## X
#define AB(X) X ## _FOO
#define C_FOO 77

int main(int argc, char **argv)
{
    return A(B)(C);
}

sylware | 28 Apr 18:57 2015
Picon

modern c++ compiler written in C

Hi,

Since version 4.8, gcc is now c++. clang is c++. Furthermore, the c++
standardization body is going bersek in complexity (c++11->c++14...).

I'm worried about compiling an "everyday use" c++ compiler from a C compiler on
on a medium term timeframe. Some critical "user level" applications are written
in the latest c++ dialect, and this dialect will soon be compilable only with
c++ written c++ compiler, hence shutting down for good any C compiler.

I did not say I like c++, quite the opposite actually: I would rather port to
C89/99 any "critical" c++ components.

What are you thoughts about this issue?

regards,

--

-- 
Sylvain

Emmanuel Deloget | 28 Apr 02:21 2015
Picon

cross-compilation of tcc fails

Hello, 

I'm cross-compiling tcc to create a native ARM compiler for an ARM platform 
and noticed that this is just not possible with the current build scripts. 

$ ./configure --cpu=armv7a --cross-prefix=arm-openwrt-linux-muslgnueabi-

The problem happens when the system tries to compile a native library:

  make -C lib native
  make[1]: Entering directory '/home/me/tcc-2015-04-28/lib'
  mkdir -p arm
  ../tcc -B.. -c libtcc1.c -o arm/libtcc1.o -I..  -fPIC -DTCC_TARGET_ARM
  ../tcc: 1: ../tcc: Syntax error: word unexpected (expecting ")")

(I spare you tons of lines ; I'm integrating tcc as an openwrt package as I 
don't want to build my own toolchain).

Now, the error is perfectly logical, as tcc is: 

  $ file tcc
  tcc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, 
  interpreter /lib/ld-musl-arm.so.1, not stripped

it's not going to run. 

I'm more or less stick here: either I create cross-compilers and the library is built using the cross compilers (but that don't help much, as the cross-compiler will not run on my target host) or I build a cross-compiled native tcc but then I cannot compile the library. 

Unfortunately, I cannot build tcc for arm and rebuild it (with its native library) on the target host.

So, question: what would be a good way to remove that deadly lock ? 

A) when cross-compiling, build the corresponding cross-compiler to build the library? That ould require to either have more configure switch or to detect the target arch from the cross-prefix (this is not always possible). 

B) use the cross-compiler to built the target library? it should not be difficult but I'm not sure that a good thing. 

C) something I haven't said yet?

Best regards, 

-- Emmanuel Deloget

<div><div dir="ltr">
<div class="gmail_default">Hello,&nbsp;</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">I'm cross-compiling tcc to create a native ARM compiler for an ARM platform&nbsp;</div>
<div class="gmail_default">and noticed that this is just not possible with the current build scripts.&nbsp;</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">$ ./configure --cpu=armv7a --cross-prefix=arm-openwrt-linux-muslgnueabi-≤br>
</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">The problem happens when the system tries to compile a native library:</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">
<div class="gmail_default">&nbsp; make -C lib native</div>
<div class="gmail_default">&nbsp; make[1]: Entering directory '/home/me/tcc-2015-04-28/lib'</div>
<div class="gmail_default">&nbsp; mkdir -p arm</div>
<div class="gmail_default">&nbsp; ../tcc -B.. -c libtcc1.c -o arm/libtcc1.o -I.. &nbsp;-fPIC -DTCC_TARGET_ARM</div>
<div class="gmail_default">&nbsp; ../tcc: 1: ../tcc: Syntax error: word unexpected (expecting ")")</div>
<div><br></div>
<div>(I spare you tons of lines ; I'm integrating tcc as an openwrt package as I&nbsp;</div>
<div>don't want to build my own toolchain).</div>
<div><br></div>
<div>Now, the error is perfectly logical, as tcc is:&nbsp;</div>
<div><br></div>
<div>&nbsp; $ file tcc</div>
<div>&nbsp; tcc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked,&nbsp;</div>
<div>&nbsp; interpreter /lib/ld-musl-arm.so.1, not stripped<br>
</div>
<div><br></div>
<div>it's not going to run.&nbsp;</div>
<div><br></div>
<div>I'm more or less stick here: either I create cross-compilers and the library is built using the cross compilers (but that don't help much, as the cross-compiler will not run on my target host) or I build a cross-compiled native tcc but then I cannot compile the library.&nbsp;</div>
<div><br></div>
<div>Unfortunately, I cannot build tcc for arm and rebuild it (with its native library) on the target host.</div>
<div><br></div>
<div>So, question: what would be a good way to remove that deadly lock ?&nbsp;</div>
<div><br></div>
<div>A) when cross-compiling, build the corresponding cross-compiler to build the library? That ould require to either have more configure switch or to detect the target arch from the cross-prefix (this is not always possible).&nbsp;</div>
<div><br></div>
<div>B) use the cross-compiler to built the target library? it should not be difficult but I'm not sure that a good thing.&nbsp;</div>
<div><br></div>
<div>C) something I haven't said yet?</div>
<div><br></div>
<div>Best regards,&nbsp;</div>
<div><br></div>
<div>-- Emmanuel Deloget</div>
<div><br></div>
</div>
</div></div>
Sergey Korshunoff | 26 Apr 04:48 2015
Picon

tcc-kernel-2.4.26.tar.bz2

An archive contains scripts to build a linux kernel  2.4.26 with the
current tcc.
Attachment (tcc-kernel-2.4.26.tar.bz2): application/x-bzip2, 67 KiB
An archive contains scripts to build a linux kernel  2.4.26 with the
current tcc.
Pip Cet | 25 Apr 21:09 2015
Picon

x86_64 ABI: mixed structs

I've just committed two tests for the x86_64 ELF ABI which currently
fail, because we don't deal properly with mixed structures along the
lines of

struct {
    double x;
    long y;
};

Such structs should be split and passed in an SSE register plus an
integer register, which the current approach, assigning VT_QFLOAT or
VT_QLONG as structure type, fails to deal with.

I think I've got most of what's needed for a fix here, but the change
involves rewriting a little of the x86_64 code; a less intrusive fix
would be preferred, I think.

I'll try isolating this from my other changes and coming up with a patch.

Pip Cet | 24 Apr 11:07 2015
Picon

VLAs broken on mob branch

Hi,
as far as I can tell, VLAs are currently broken. If you apply this
patch to the source code (adding a useless VLA to the TCC code
itself), make test dies with a segmentation fault (on x86-64, Linux):

diff --git a/x86_64-gen.c b/x86_64-gen.c
index d837a1d..593dd91 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
 <at>  <at>  -1186,6 +1186,7  <at>  <at>  void gfunc_call(int nb_args)
     int size, align, r, args_size, stack_adjust, run_start, run_end,
i, reg_count;
     int nb_reg_args = 0;
     int nb_sse_args = 0;
+    int offsets[nb_args*nb_args+1];
     int sse_reg, gen_reg;

     /* calculate the number of integer/float register arguments */

I've tried fixing it. So far all I have is a patch that appears to
make the problem go away, but that I don't fully understand. If anyone
who actually understands the VLA code could have a look, that would be
very much appreciated. I include the patch mostly for reasons of
completeness, since it's probably very different from any actual fix:

diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags,
*orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ?
&vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags
& VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type,
Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();

Attachment tcc-break-vlas.diff is the change that causes the segfault;
attachment tcc-notafix.diff is the half-understood patch that "fixes"
things.
diff --git a/x86_64-gen.c b/x86_64-gen.c
index d837a1d..593dd91 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
 <at>  <at>  -1186,6 +1186,7  <at>  <at>  void gfunc_call(int nb_args)
     int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
     int nb_reg_args = 0;
     int nb_sse_args = 0;
+    int offsets[nb_args*nb_args+1];
     int sse_reg, gen_reg;

     /* calculate the number of integer/float register arguments */
diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ? &vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type, Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();
diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ? &vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type, Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();
Ramsay Jones | 20 Apr 13:19 2015
Picon
Picon

Missing test for -fdollar-in-identifiers commit

Hi Sergey, Daniel,

I just pushed a quick fix for the missing test files to the mob branch.

Also, I noticed a slight difference between Daniel's patch and commit
5ce2154, which amounts to:

  diff --git a/tccasm.c b/tccasm.c
  index 3fa6f07..8f71846 100644
  --- a/tccasm.c
  +++ b/tccasm.c
   <at>  <at>  -853,6 +853,7  <at>  <at>  static void tcc_assemble_inline(TCCState *s1, char *str, int len)
       memcpy(file->buffer, str, len);

       macro_ptr = NULL;
  +    parse_flags |= PARSE_FLAG_ASM_FILE;
       tcc_assemble_internal(s1, 0);
       tcc_close();

  $ 

I don't have time to investigate further, so I will leave the issue
of the above difference for you to investigate.

Thanks!

ATB,
Ramsay Jones


Gmane