Category Archives: Tiny C Compiler

TCC – dynarray_add

This is very common function in TCC state.

here is main logical.

1
2
3
4
5
6
7
dynarray_add(void ***ptab, int *nb_ptr, void *data) 
{
...
pp= *ptab; nb=*nb_ptr;
pp[nb++] = data;
...
}

what dynarray_add do is simple. input array has just 3 parts that is double pointer, index and value.

then assign data to double pointer just like assign string to char array.

Here is sample call stack, it call to add pathname into library_paths.

1
2
3
dynarray_add(p_ary, p_nb_ary, str.data);
tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);

the define of library_paths is following

1
2
3
4
5
6
struct TCCState {
...
    char **library_paths;
    int nb_library_paths;
...
}

TCC – string index from char str[1] to str[len]

Check TokenSym declaration firstly, TokenSym is to store a single token info.

1
2
3
4
5
6
7
8
9
10
typedef struct TokenSym {
    struct TokenSym *hash_next;
    struct Sym *sym_define; /* direct pointer to define */
    struct Sym *sym_label; /* direct pointer to label */
    struct Sym *sym_struct; /* direct pointer to structure */
    struct Sym *sym_identifier; /* direct pointer to identifier */
    int tok; /* token number */
    int len;
    char str[1];
} TokenSym;

when malloc memory, it will alloc TokenSym+len.

1
ts = tcc_malloc(sizeof(TokenSym) + len);

the later on, memcpy copy str with len to str memory.
Of course, str[1] will be out of range, but extra len memory is appended.
therefore, str[1] is expanded to str[len].

This is very popular within TCC’s struct declaration.

1
2
memcpy(ts->str, str, len);
ts->str[len] = '\0';

TCC – struct CString for string process in compiler

struct CString is major struct for string process in TCC.
It also works some api such as cstr_reset(…),cstr_ccat(…).
Here is example on how to convert “char *” to s.data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  struct CString s;
 
  static char buf[STRING_MAX_SIZE + 1];
 
  char *p = "Test";
  char *p1 = p;
  char *p2 = p; 
 
  cstr_reset(&s);
 
  for(;;){
    if(*p2 != '\0')
      {
        p2++;
      }
    else
      break;
  }
 
  s.data = buf;  
 
  while (p1 < p2) {
    cstr_ccat(&s, *p1);
    p1++;
  }
 
  printf("%s",(char *)s.data);

TCC source code — define_stack and tcc_alloc

define_stack is good example of lots of stack using TCC. The following is example of print Define Stack.

1
2
3
4
5
6
7
8
9
10
11
void printDefineStack(){
  Sym *p = define_stack;
  for(;;){
    if(p == NULL){
      break;
    }
 
    printf("%d\n",p -> v);
    p = p -> prev; 
  }
}

tcc_alloc is function which is allocated tcc object, It is very simple and used everywhere in tcc. Here is example on how to use it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void tcc_alloc_test()
{
  int i = 0;
  int len =  3;
  char *str = "int";
  TokenSym *ts;  
  table_ident = tcc_malloc((TOK_ALLOC_INCR) * sizeof(TokenSym *));
 
  ts = tcc_malloc(sizeof(TokenSym) + len);
  table_ident[i] = ts;
 
  ts->sym_define = NULL;
  ts->sym_label = NULL;
  ts->sym_struct = NULL;
  ts->sym_identifier = NULL;
  ts->len = len;
  ts->hash_next = NULL;
  memcpy(ts->str, str, len);
  ts->str[len] = '\0';
 
}

Tcc source code – CONFIG_TCCDIR

In file config.h, it defined CONFIG_TCCDIR

# define CONFIG_TCCDIR “/usr/local/lib/tcc”

Then it executes

tcc_set_lib_path(s, CONFIG_TCCDIR);

[code]

LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
{
tcc_free(s->tcc_lib_path);
s->tcc_lib_path = tcc_strdup(path);
}

[/code]

Tcc 源码分析:第一步编译 (Tcc Source code analysis: First Step Compiling)

Tcc 源码分析:第一步编译
Tcc Source code analysis: First Step Compiling

Tiny C Compiler

  1. http://bellard.org/tcc/ 下载地址(download URL)
  2. 解压缩 tcc (decompress tcc)
  3. 像编译其他开源软件那样编译,tcc 规模较小 ( compiled as other open source, tcc is small size software)
  4. 复制编译好的libtcc1.a到/usr/local/lib/tcc/ (after compiling finished, copy libtcc1.a to /usr/local/lib/tcc)
    cp libtcc1.a /usr/local/lib/tcc

编译直接./configure && make (compile use command ./configure && make)

可以配置-g打开调试配置,以方便后续用gdb调试 (use -g to enable debug for gdb)

./tcc 1.c -o 1 来生成执行文件 (./tcc 1.c -o 1 to generate executable file)

[code]

#include <stdlib.h>

int main(int argc,char **argv)
{
int x = 0;
printf("%d",x);
return 0;
}

[/code]