Sergey Korshunoff | 2 May 14:24 2016

tcc bug: big exe in 1 step

It looks like tcc have some bug when compiling a big exectutable in one step.
This is a tccboot kernel. When I added some additional files to
compile (PCI bus and ethernet)
then compiled kernel hags if compiled w/o specific option
-fnocode-if-false. This option is not needed for 2 steps (compile +
link) or 3 steps (preprocess + compile + link) builds.

-fnocode-if-false skips code generation for the BLOCK in
  if(0) {BLOCK}

This looks like a problem with tcc compiling a big code in one step.
This option was not needed with a smaller source base (before PCI
addition). What parms/limits can be changed to find a problem?
VSTACK_SIZE? What else?

May be there is limit on the resulting code? If we skip some code with
-fnocode-if-false then bug not exposed.

PS: There is no output from the kernel at all. VirtualBox window is
closed on start.

Sergey Korshunoff | 2 May 06:08 2016

bug #47379: Compare bug

bug #47379: Compare bug
Please test/confirm on x86-64 (no bug on x86 Linux)

include <stdio.h>
#include <stdint.h>
int main(int argc, char* argv[]) {
printf("%d\n", -2147483648);
printf("%ld\n", -2147483648LL);
printf("%d\n", (1LL) < (-2147483648LL));
return 0;

tcc output:

gcc output:

Sergey Korshunoff | 1 May 21:29 2016

TOK_PPNUM for asm

Proposed patch: handle 0x1e+1 as 0x1e +1 if (parse_flags & PARSE_FLAG_ASM_FILE)
This helps to compile asm code like:
__asm("mov $0x1e" "-1");
(a code from linux kernel)

Sergey Korshunoff | 1 May 20:58 2016

lcall invalid hex code


diff --git a/i386-asm.h b/i386-asm.h
index 486cffe..637568b 100644
--- a/i386-asm.h
+++ b/i386-asm.h
 <at>  <at>  -213,7 +213,7  <at>  <at>  ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW))
 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
-ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
+ALT(DEF_ASM_OP1(lcall, 0xff1f, 3, 0, OPT_EA))
 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))

grischka | 29 Apr 19:06 2016

Re: X(X(1)) (nested macro substitution)

Sergey Korshunoff wrote: ---
>> And currently output is identical for the case #define A B+1
> correction for X(X(X(X(X(1)))))
> I think a patch is quite usefull. It adds a right replacement for the
> nested macro calls and don't break any other cases for macro calls.
> But any additional cases when new algo don't work are welcom.

A useful patch that does not add lines:

-- gr

Sergey Korshunoff | 29 Apr 18:24 2016

tcc build on OSX

Just started travis-CI builds with OSX configuration.
After adding a linker options
-Wl,-flat_namespace,-warning,unsupported, I faced with the following

1. abitest-tcc is compiled w/o -run option and crt1.o crti.o are not found
2. /usr/include/sys/cdefs.h:81: warning: #warning "Unsupported compiler"
  ../tccpp.c:3413: warning: implicit declaration of function 'snprintf'
  ../tccelf.c:2500: warning: implicit declaration of function 'fdopen'
  ../tccrun.c:429: error: invalid type

Sergey Korshunoff | 27 Apr 06:17 2016

parsing 0x1e+1 as 0x1e +1

A problem solved (as someone suggested on the list) by teaching tcc to
recognize right exponent chars in next_nomacro1().(no any space chars
after macro expansion). This is like pcc do. A test prgram:

extern int printf(const char *format, ...);
int array[NUM_NS_TYPES];
#define n 0xe
int main() {
    printf("n+1 = %d\n", n+1);

prints 15
And preprocessor output is
    printf("n+1 = %d\n", 0x1e+1);.

Sergey Korshunoff | 26 Apr 12:32 2016

X(X(1)) (nested macro substitution)

#define Y(x) Z(x)
#define X Y

If comment out in tccpp.c the following lines
/* if nested substitution, do nothing */
if ( (!s->next)
    && sym_find2(*nested_list, t))
    /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */
    tok_str_add2(tok_str, TOK_NOSUBST, NULL);
    goto no_subst;
then we get the right result  Z(Z(1) (but tcc loops in other macro
substiturion cases).
Currently we get Z(Y(1)), i.e. Y() is added to the nosubst_list affter
first substitution.

Sergey Korshunoff | 24 Apr 17:37 2016

how to name a switch

I need some switch to allow tcc behave like gcc/pcc in the code:
  void vide(void); __asm__("vide: ret");
  void vide(void); __asm__("globl vide\nvide: ret");

When the right solution is to ask developers to write asm code correctly,
there is many such code in linux kernels. How to name this switch?

Sergey Korshunoff | 24 Apr 17:09 2016

gcc/tcc nested macros difference

A test file:
#define __le16_to_cpu(x) ((__u16)(x))
#define le16_to_cpu __le16_to_cpu
static void pcnet32_load_multicast (struct net_device *dev)
    mcast_table [crc >> 4] = le16_to_cpu(le16_to_cpu(mcast_table [crc
>> 4]) | (1 << (crc & 0xf)));

GCC -E output:
    mcast_table [crc >> 4] = ((__u16)(((__u16)(mcast_table [crc >>
4])) | (1 << (crc & 0xf))));

TCC -E output:
    mcast_table [crc >> 4] = ((__u16)(__le16_to_cpu(mcast_table [crc
>> 4]) | (1 << (crc & 0xf))))

Look at the __ie16_to_cpu presence in the tcc output: nested macro was
not expanded.

Sergey Korshunoff | 24 Apr 10:13 2016

precompiled headers

> David Mertens wrote:
> If there is an argument to be made for including exsymtab, it would probably be based on these results. It is
plausible to use symbol table caching and serializing/deserializing to avoid loading and parsing
standard header files. This could potentially reduce compilation times. If you (we?) could show
measurable performance gains with such a modification, then it might get broader support for being
included with tcc.

As I see this today. For example, I prefer to speed up tccboot kernel
A current command to compile is like
  tcc -o vmlinux linux/kernel/init.c linux/arch/kernel/head.c ...

With -cheaders[=dDIR] option tcc will precompile headers in each *.c
before  the first C token is seen and create files
[DIR]linux/kernel/init.tch, [DIR]linux/arch/kernel/head.tch,...  or
use these files if they already present. I think this is better and
don't need a special tuning.