Alien-TinyCC

 view release on metacpan or  search on metacpan

inc/My/Build/Windows.pm  view on Meta::CPAN

	if (not $self->notes('build_state')) {
		# move into the source directory and invoke the custom Windows build
		chdir 'src\\win32';
		system('build-tcc.bat');
		chdir '..\\..';
		
		# check if there was a mishap:
		$ENV{ERRORLEVEL} and die 'build-tcc.bat failed';
		
		# Copy the files to the distribution's share dir
		File::Copy::Recursive::rcopy_glob('src\\win32\\*' => 'share\\');
		
		# Note that we've built it.
		$self->notes('build_state', 'built');
	}
	
	$self->SUPER::ACTION_code;
}

sub my_clean {}

src/Changelog  view on Meta::CPAN

  469: Fix symbol visibility problems in the linker (Vincent Pit)
  468: Allow && and || involving pointer arguments (Rob Landley)
  455: Optimize case labels with no code in between (Zdenek Pavlas)
  450: Implement alloca for x86 (grischka)
  415: Parse unicode escape sequences (Axel Liljencrantz)
  407: Add a simple va_copy() in stdarg.h (Hasso Tepper)
  400: Allow typedef names as symbols (Dave Dodge)

- Import some changesets from Rob Landley's fork (part 1):
  462: Use LGPL with bcheck.c and il-gen.c
  458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
  456: Use return code from tcc_output_file in main() (Michael Somos)
  442: Fix indirections with function pointers (***fn)() (grischka)
  441: Fix LL left shift in libtcc1.c:__shldi3 (grischka)
  440: Pass structures and function ptrs through ?: (grischka)
  439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka)
  438: Degrade nonportable pointer assignment to warning (grischka)
  437: Call 'saveregs()' before jumping with logical and/or/not (grischka)
  435: Put local static variables into global memory (grischka)
  432/434: Cast double and ptr to bool (grischka)
  420: Zero pad x87 tenbyte long doubles (Felix Nawothnig)
  417: Make 'sizeof' unsigned (Rob Landley)
  397: Fix save_reg for longlongs (Daniel Glöckner)
  396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer)

- ignore AS_NEEDED ld command
- mark executable sections as executable when running in memory
- added support for win32 wchar_t (Filip Navara)
- segment override prefix support (Filip Navara)

src/Changelog  view on Meta::CPAN


version 0.9.19:

- "alacarte" linking (Dave Long)
- simpler function call
- more strict type checks
- added 'const' and 'volatile' support and associated warnings
- added -Werror, -Wunsupported, -Wwrite-strings, -Wall.
- added __builtin_types_compatible_p() and __builtin_constant_p()
- chars support in assembler (Dave Long)
- .string, .globl, .section, .text, .data and .bss asm directive
  support (Dave Long)
- man page generated from tcc-doc.texi
- fixed macro argument substitution
- fixed zero argument macro parsing
- changed license to LGPL
- added -rdynamic option support

version 0.9.18:

- header fix (time.h)

src/arm-gen.c  view on Meta::CPAN

	c = vtop->c.i & 0x1f;
	o(opc|(c<<7)|(fr<<12));
      } else {
        fr=intr(gv(RC_INT));
	c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
	o(opc|(c<<12)|(fr<<8)|0x10);
      }
      vtop--;
      break;
    case 3:
      vpush_global_sym(&func_old_type, func);
      vrott(3);
      gfunc_call(2);
      vpushi(0);
      vtop->r = retreg;
      break;
    default:
      tcc_error("gen_opi %i unimplemented!",op);
  }
}

src/arm-gen.c  view on Meta::CPAN

#else
    } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
#endif
      func_type = &func_double_type;
      if(vtop->type.t & VT_UNSIGNED)
        func=TOK___floatundidf;
      else
        func=TOK___floatdidf;
    }
    if(func_type) {
      vpush_global_sym(func_type, func);
      vswap();
      gfunc_call(1);
      vpushi(0);
      vtop->r=TREG_F0;
      return;
    }
  }
  tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t);
}

src/arm-gen.c  view on Meta::CPAN

#if LDOUBLE_SIZE != 8
    else if(r2 == VT_LDOUBLE)
      func=TOK___fixxfdi;
    else if(r2 == VT_DOUBLE)
#else
    else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
#endif
      func=TOK___fixdfdi;
  }
  if(func) {
    vpush_global_sym(&func_old_type, func);
    vswap();
    gfunc_call(1);
    vpushi(0);
    if(t == VT_LLONG)
      vtop->r2 = REG_LRET;
    vtop->r = REG_IRET;
    return;
  }
  tcc_error("unimplemented gen_cvt_ftoi!");
}

src/c67-gen.c  view on Meta::CPAN

	fr = vtop[0].r;
	vtop--;
	C67_SHR(fr, r);		// arithmetic shift
	break;

    case '/':
	t = TOK__divi;
      call_func:
	vswap();
	/* call generic idiv function */
	vpush_global_sym(&func_old_type, t);
	vrott(3);
	gfunc_call(2);
	vpushi(0);
	vtop->r = REG_IRET;
	vtop->r2 = VT_CONST;
	break;
    case TOK_UDIV:
    case TOK_PDIV:
	t = TOK__divu;
	goto call_func;

src/c67-gen.c  view on Meta::CPAN

	    } else {
		C67_MPYSP(r, fr);	// MPY  fr,r,fr
		C67_NOP(3);
	    }
	    vtop--;
	} else if (op == '/') {
	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
		// must call intrinsic DP floating point divide
		vswap();
		/* call generic idiv function */
		vpush_global_sym(&func_old_type, TOK__divd);
		vrott(3);
		gfunc_call(2);
		vpushi(0);
		vtop->r = REG_FRET;
		vtop->r2 = REG_LRET;

	    } else {
		// must call intrinsic SP floating point divide
		vswap();
		/* call generic idiv function */
		vpush_global_sym(&func_old_type, TOK__divf);
		vrott(3);
		gfunc_call(2);
		vpushi(0);
		vtop->r = REG_FRET;
		vtop->r2 = VT_CONST;
	    }
	} else
	    ALWAYS_ASSERT(FALSE);


src/elf.h  view on Meta::CPAN

#define SHT_MIPS_PIXIE         0x70000023
#define SHT_MIPS_XLATE         0x70000024
#define SHT_MIPS_XLATE_DEBUG   0x70000025
#define SHT_MIPS_WHIRL         0x70000026
#define SHT_MIPS_EH_REGION     0x70000027
#define SHT_MIPS_XLATE_OLD     0x70000028
#define SHT_MIPS_PDR_EXCEPTION 0x70000029

/* Legal values for sh_flags field of Elf32_Shdr.  */

#define SHF_MIPS_GPREL   0x10000000     /* Must be part of global data area */
#define SHF_MIPS_MERGE   0x20000000
#define SHF_MIPS_ADDR    0x40000000
#define SHF_MIPS_STRINGS 0x80000000
#define SHF_MIPS_NOSTRIP 0x08000000
#define SHF_MIPS_LOCAL   0x04000000
#define SHF_MIPS_NAMES   0x02000000
#define SHF_MIPS_NODUPE  0x01000000


/* Symbol tables.  */

src/elf.h  view on Meta::CPAN

} Elf32_RegInfo;

/* Entries found in sections of type SHT_MIPS_OPTIONS.  */

typedef struct
{
  unsigned char kind;           /* Determines interpretation of the
                                   variable part of descriptor.  */
  unsigned char size;           /* Size of descriptor, including header.  */
  Elf32_Section section;        /* Section header index of section affected,
                                   0 for global options.  */
  Elf32_Word info;              /* Kind-specific information.  */
} Elf_Options;

/* Values for `kind' field in Elf_Options.  */

#define ODK_NULL        0       /* Undefined.  */
#define ODK_REGINFO     1       /* Register usage information.  */
#define ODK_EXCEPTIONS  2       /* Exception processing options.  */
#define ODK_PAD         3       /* Section padding options.  */
#define ODK_HWPATCH     4       /* Hardware workarounds performed */

src/elf.h  view on Meta::CPAN

                                0x020b  PA-RISC 1.0 big-endian
                                0x0210  PA-RISC 1.1 big-endian
                                0x028b  PA-RISC 1.0 little-endian
                                0x0290  PA-RISC 1.1 little-endian
*/

/* Legal values for sh_type field of Elf32_Shdr.  */

#define SHT_PARISC_GOT          0x70000000 /* GOT for external data.  */
#define SHT_PARISC_ARCH         0x70000001 /* Architecture extensions.  */
#define SHT_PARISC_GLOBAL       0x70000002 /* Definition of $global$.  */
#define SHT_PARISC_MILLI        0x70000003 /* Millicode routines.  */
#define SHT_PARISC_UNWIND       0x70000004 /* Unwind information.  */
#define SHT_PARISC_PLT          0x70000005 /* Procedure linkage table.  */
#define SHT_PARISC_SDATA        0x70000006 /* Short initialized data.  */
#define SHT_PARISC_SBSS         0x70000007 /* Short uninitialized data.  */
#define SHT_PARISC_SYMEXTN      0x70000008 /* Argument/relocation info.  */
#define SHT_PARISC_STUBS        0x70000009 /* Linker stubs.  */

/* Legal values for sh_flags field of Elf32_Shdr.  */

src/i386-gen.c  view on Meta::CPAN

        g(val);
    } else {
        oad(0xc481, val); /* add $xxx, %esp */
    }
}

static void gen_static_call(int v)
{
    Sym *sym;

    sym = external_global_sym(v, &func_old_type, 0);
    oad(0xe8, -4);
    greloc(cur_text_section, sym, ind-4, R_386_PC32);
}

/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
    int r;
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
        /* constant case */

src/i386-gen.c  view on Meta::CPAN

    case 16: func = TOK___bound_ptr_indir16; break;
    default:
        tcc_error("unhandled size when dereferencing bounded pointer");
        func = 0;
        break;
    }

    /* patch relocation */
    /* XXX: find a better solution ? */
    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
    sym = external_global_sym(func, &func_old_type, 0);
    if (!sym->c)
        put_extern_sym(sym, NULL, 0, 0);
    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
}
#endif

/* Save the stack pointer onto the stack */
ST_FUNC void gen_vla_sp_save(int addr) {
    /* mov %esp,addr(%ebp)*/
    o(0x89);

src/i386-gen.c  view on Meta::CPAN

/* Restore the SP from a location on the stack */
ST_FUNC void gen_vla_sp_restore(int addr) {
    o(0x8b);
    gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
}

/* Subtract from the stack pointer, and push the resulting value onto the stack */
ST_FUNC void gen_vla_alloc(CType *type, int align) {
#ifdef TCC_TARGET_PE
    /* alloca does more than just adjust %rsp on Windows */
    vpush_global_sym(&func_old_type, TOK_alloca);
    vswap(); /* Move alloca ref past allocation size */
    gfunc_call(1);
    vset(type, REG_IRET, 0);
#else
    int r;
    r = gv(RC_INT); /* allocation size */
    /* sub r,%rsp */
    o(0x2b);
    o(0xe0 | r);
    /* We align to 16 bytes rather than align */

src/il-gen.c  view on Meta::CPAN

            } else {
                if (fc >= 0 && fc <= 4) {
                    out_op(IL_OP_LDLOC_0 + fc);
                } else if (fc <= 0xff) {
                    out_opb(IL_OP_LDLOC_S, fc);
                } else {
                    out_opi(IL_OP_LDLOC, fc);
                }
            }
        } else if (v == VT_CONST) {
                /* XXX: handle globals */
                out_opi(IL_OP_LDSFLD, 0);
        } else {
            if ((ft & VT_BTYPE) == VT_FLOAT) {
                out_op(IL_OP_LDIND_R4);
            } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
                out_op(IL_OP_LDIND_R8);
            } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
                out_op(IL_OP_LDIND_R8);
            } else if ((ft & VT_TYPE) == VT_BYTE)
                out_op(IL_OP_LDIND_I1);

src/il-gen.c  view on Meta::CPAN

                out_op(IL_OP_LDIND_U1);
            else if ((ft & VT_TYPE) == VT_SHORT)
                out_op(IL_OP_LDIND_I2);
            else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
                out_op(IL_OP_LDIND_U2);
            else
                out_op(IL_OP_LDIND_I4);
        } 
    } else {
        if (v == VT_CONST) {
            /* XXX: handle globals */
            if (fc >= -1 && fc <= 8) {
                out_op(IL_OP_LDC_I4_M1 + fc + 1); 
            } else {
                out_opi(IL_OP_LDC_I4, fc);
            }
        } else if (v == VT_LOCAL) {
            if (fc >= ARG_BASE) {
                fc -= ARG_BASE;
                if (fc <= 0xff) {
                    out_opb(IL_OP_LDARGA_S, fc);

src/il-gen.c  view on Meta::CPAN

        } else {
            if (fc >= 0 && fc <= 4) {
                out_op(IL_OP_STLOC_0 + fc);
            } else if (fc <= 0xff) {
                out_opb(IL_OP_STLOC_S, fc);
            } else {
                out_opi(IL_OP_STLOC, fc);
            }
        }
    } else if (v == VT_CONST) {
        /* XXX: handle globals */
        out_opi(IL_OP_STSFLD, 0);
    } else {
        if ((ft & VT_BTYPE) == VT_FLOAT)
            out_op(IL_OP_STIND_R4);
        else if ((ft & VT_BTYPE) == VT_DOUBLE)
            out_op(IL_OP_STIND_R8);
        else if ((ft & VT_BTYPE) == VT_LDOUBLE)
            out_op(IL_OP_STIND_R8);
        else if ((ft & VT_BTYPE) == VT_BYTE)
            out_op(IL_OP_STIND_I1);

src/lib/alloca86-bt.S  view on Meta::CPAN

/* ---------------------------------------------- */
/* alloca86-bt.S */

.globl __bound_alloca

__bound_alloca:
    pop     %edx
    pop     %eax
    mov     %eax, %ecx
    add     $3,%eax
    and     $-4,%eax
    jz      p6

#ifdef TCC_TARGET_PE

src/lib/alloca86.S  view on Meta::CPAN

/* ---------------------------------------------- */
/* alloca86.S */

.globl alloca

alloca:
    pop     %edx
    pop     %eax
    add     $3,%eax
    and     $-4,%eax
    jz      p3

#ifdef TCC_TARGET_PE
p1:

src/lib/alloca86_64.S  view on Meta::CPAN

/* ---------------------------------------------- */
/* alloca86_64.S */

.globl alloca

alloca:
    pop     %rdx
#ifdef TCC_TARGET_PE
    mov     %rcx,%rax
#else
    mov     %rdi,%rax
#endif
    add     $15,%rax
    and     $-16,%rax

src/libtcc.c  view on Meta::CPAN

 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "tcc.h"

/********************************************************/
/* global variables */

/* use GNU C extensions */
ST_DATA int gnu_ext = 1;

/* use TinyCC extensions */
ST_DATA int tcc_ext = 1;

/* XXX: get rid of this ASAP */
ST_DATA struct TCCState *tcc_state;

src/libtcc.c  view on Meta::CPAN

#include "tccpe.c"
#endif
#endif /* ONE_SOURCE */

/********************************************************/
#ifndef CONFIG_TCC_ASM
ST_FUNC void asm_instr(void)
{
    tcc_error("inline asm() not supported");
}
ST_FUNC void asm_global_instr(void)
{
    tcc_error("inline asm() not supported");
}
#endif

/********************************************************/
#ifdef _WIN32
static char *normalize_slashes(char *path)
{
    char *p;

src/libtcc.c  view on Meta::CPAN

    }

    s1->error_set_jmp_enabled = 0;

    /* reset define stack, but leave -Dsymbols (may be incorrect if
       they are undefined) */
    free_defines(define_start); 

    gen_inline_functions();

    sym_pop(&global_stack, NULL);
    sym_pop(&local_stack, NULL);

    return s1->nb_errors != 0 ? -1 : 0;
}

LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
{
    int len, ret;
    len = strlen(str);

src/tcc-doc.texi  view on Meta::CPAN

Generate a shared library instead of an executable.

@item -soname name
set name for shared library to be used at runtime

@item -static
Generate a statically linked executable (default is a shared linked
executable).

@item -rdynamic
Export global symbols to the dynamic linker. It is useful when a library
opened with @code{dlopen()} needs to access executable symbols.

@item -r
Generate an object file combining all input files.

@item -Wl,-rpath=path
Put custom seatch path for dynamic libraries into executable.

@item -Wl,--oformat=fmt
Use @var{fmt} as output format. The supported output formats are:

src/tcc-doc.texi  view on Meta::CPAN

@cindex directives, assembler
@cindex align directive
@cindex skip directive
@cindex space directive
@cindex byte directive
@cindex word directive
@cindex short directive
@cindex int directive
@cindex long directive
@cindex quad directive
@cindex globl directive
@cindex global directive
@cindex section directive
@cindex text directive
@cindex data directive
@cindex bss directive
@cindex fill directive
@cindex org directive
@cindex previous directive
@cindex string directive
@cindex asciz directive
@cindex ascii directive

src/tcc-doc.texi  view on Meta::CPAN

@itemize
@item .align n[,value]
@item .skip n[,value]
@item .space n[,value]
@item .byte value1[,...]
@item .word value1[,...]
@item .short value1[,...]
@item .int value1[,...]
@item .long value1[,...]
@item .quad immediate_value1[,...]
@item .globl symbol
@item .global symbol
@item .section section
@item .text
@item .data
@item .bss
@item .fill repeat[,size[,value]]
@item .org n
@item .previous
@item .string string[,...]
@item .asciz string[,...]
@item .ascii string[,...]

src/tcc-doc.texi  view on Meta::CPAN

@table @asis

@item Invalid range with standard string function:
@example
@{
    char tab[10];
    memset(tab, 0, 11);
@}
@end example

@item Out of bounds-error in global or local arrays:
@example
@{
    int tab[10];
    for(i=0;i<11;i++) @{
        sum += tab[i];
    @}
@}
@end example

@item Out of bounds-error in malloc'ed data:

src/tcc-doc.texi  view on Meta::CPAN

@node Libtcc
@chapter The @code{libtcc} library

The @code{libtcc} library enables you to use TCC as a backend for
dynamic code generation. 

Read the @file{libtcc.h} to have an overview of the API. Read
@file{libtcc_test.c} to have a very simple example.

The idea consists in giving a C string containing the program you want
to compile directly to @code{libtcc}. Then you can access to any global
symbol (function or variable) defined.

@node devel
@chapter Developer's guide

This chapter gives some hints to understand how TCC works. You can skip
it if you do not intend to modify the TCC code.

@section File reading

src/tcc-doc.texi  view on Meta::CPAN

Variable length array types use @code{Sym.c} as a location on the stack
which holds the runtime sizeof for the type.

Four main symbol stacks are defined:

@table @code

@item define_stack
for the macros (@code{#define}s).

@item global_stack
for the global variables, functions and types.

@item local_stack
for the local variables, functions and types.

@item global_label_stack
for the local labels (for @code{goto}).

@item label_stack
for GCC block local labels (see the @code{__label__} keyword).

@end table

@code{sym_push()} is used to add a new symbol in the local symbol
stack. If no local symbol stack is active, it is added in the global
symbol stack.

@code{sym_pop(st,b)} pops symbols from the symbol stack @var{st} until
the symbol @var{b} is on the top of stack. If @var{b} is NULL, the stack
is emptied.

@code{sym_find(v)} return the symbol associated to the identifier
@var{v}. The local stack is searched first from top to bottom, then the
global stack.

@section Sections

The generated code and datas are written in sections. The structure
@code{Section} contains all the necessary information for a given
section. @code{new_section()} creates a new section. ELF file semantics
is assumed for each section.

The following sections are predefined:

src/tcc.c  view on Meta::CPAN

           "Preprocessor options:\n"
           "  -E          preprocess only\n"
           "  -Idir       add include path 'dir'\n"
           "  -Dsym[=val] define 'sym' with value 'val'\n"
           "  -Usym       undefine 'sym'\n"
           "Linker options:\n"
           "  -Ldir       add library path 'dir'\n"
           "  -llib       link with dynamic or static library 'lib'\n"
           "  -pthread    link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
           "  -r          generate (relocatable) object file\n"
           "  -rdynamic   export all global symbols to dynamic linker\n"
           "  -shared     generate a shared library\n"
           "  -soname     set name for shared library to be used at runtime\n"
           "  -static     static linking\n"
           "  -Wl,-opt[=val]  set linker option (see manual)\n"
           "Debugger options:\n"
           "  -g          generate runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
#endif
#ifdef CONFIG_TCC_BACKTRACE

src/tcc.h  view on Meta::CPAN

ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);

ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c);
ST_FUNC Sym *sym_find2(Sym *s, int v);
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b);
ST_INLN Sym *struct_find(int v);
ST_INLN Sym *sym_find(int v);
ST_FUNC Sym *global_identifier_push(int v, int t, int c);

ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
ST_FUNC void tcc_close(void);

ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);

PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time);

src/tcc.h  view on Meta::CPAN

/* ------------ tccgen.c ------------ */

ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */
ST_DATA Section *cur_text_section; /* current section where function code is generated */
#ifdef CONFIG_TCC_ASM
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
#endif
#ifdef CONFIG_TCC_BCHECK
/* bound check related sections */
ST_DATA Section *bounds_section; /* contains global data bound description */
ST_DATA Section *lbounds_section; /* contains local data bound description */
#endif
/* symbol sections */
ST_DATA Section *symtab_section, *strtab_section;
/* debug sections */
ST_DATA Section *stab_section, *stabstr_section;

#define SYM_POOL_NB (8192 / sizeof(Sym))
ST_DATA Sym *sym_free_first;
ST_DATA void **sym_pools;
ST_DATA int nb_sym_pools;

ST_DATA Sym *global_stack;
ST_DATA Sym *local_stack;
ST_DATA Sym *local_label_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *define_stack;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop;
#define vstack  (__vstack + 1)
ST_DATA int rsym, anon_sym, ind, loc;

ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
ST_DATA int global_expr;  /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;

ST_INLN int is_float(int t);
ST_FUNC int ieee_finite(double d);
ST_FUNC void test_lvalue(void);
ST_FUNC void swap(int *p, int *q);
ST_FUNC void vpushi(int v);
ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vswap(void);
ST_FUNC void vpush_global_sym(CType *type, int v);
ST_FUNC void vrote(SValue *e, int n);
ST_FUNC void vrott(int n);
ST_FUNC void vrotb(int n);
#ifdef TCC_TARGET_ARM
ST_FUNC int get_reg_ex(int rc, int rc2);
ST_FUNC void lexpand_nr(void);
#endif
ST_FUNC void vpushv(SValue *v);
ST_FUNC void save_reg(int r);
ST_FUNC int get_reg(int rc);

src/tcc.h  view on Meta::CPAN


/* ------------ tcccoff.c ------------ */

#ifdef TCC_TARGET_COFF
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f);
ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
#endif

/* ------------ tccasm.c ------------ */
ST_FUNC void asm_instr(void);
ST_FUNC void asm_global_instr(void);
#ifdef CONFIG_TCC_ASM
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
ST_FUNC int asm_int_expr(TCCState *s1);
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
/* ------------ i386-asm.c ------------ */
ST_FUNC void gen_expr32(ExprValue *pe);
ST_FUNC void asm_opcode(TCCState *s1, int opcode);
ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);

src/tccasm.c  view on Meta::CPAN

        next();
        asm_expr(s1, pe);
        skip(')');
        break;
    default:
        if (tok >= TOK_IDENT) {
            /* label case : if the label was not found, add one */
            sym = label_find(tok);
            if (!sym) {
                sym = label_push(&s1->asm_labels, tok, 0);
                /* NOTE: by default, the symbol is global */
                sym->type.t = VT_VOID;
            }
            if (sym->r == SHN_ABS) {
                /* if absolute symbol, no need to put a symbol value */
                pe->v = sym->jnext;
                pe->sym = NULL;
            } else {
                pe->v = 0;
                pe->sym = sym;
            }

src/tccasm.c  view on Meta::CPAN

            next();
            /* XXX: handle section symbols too */
            n = asm_int_expr(s1);
            if (n < ind)
                tcc_error("attempt to .org backwards");
            v = 0;
            size = n - ind;
            goto zero_pad;
        }
        break;
    case TOK_ASM_globl:
    case TOK_ASM_global:
    case TOK_ASM_weak:
    tok1 = tok;
	do { 
            Sym *sym;

            next();
            sym = label_find(tok);
            if (!sym) {
                sym = label_push(&s1->asm_labels, tok, 0);
                sym->type.t = VT_VOID;

src/tccasm.c  view on Meta::CPAN

    /* free everything */
    for(i=0;i<nb_operands;i++) {
        ASMOperand *op;
        op = &operands[i];
        tcc_free(op->constraint);
        vpop();
    }
    cstr_free(&astr1);
}

ST_FUNC void asm_global_instr(void)
{
    CString astr;

    next();
    parse_asm_str(&astr);
    skip(')');
    /* NOTE: we do not eat the ';' so that we can restore the current
       token after the assembler parsing */
    if (tok != ';')
        expect("';'");
    
#ifdef ASM_DEBUG
    printf("asm_global: \"%s\"\n", (char *)astr.data);
#endif
    cur_text_section = text_section;
    ind = cur_text_section->data_offset;

    /* assemble the string with tcc internal assembler */
    tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
    
    cur_text_section->data_offset = ind;

    /* restore the current C token */

src/tcccoff.c  view on Meta::CPAN

	    // put relocations data
	    if (coff_sec->s_nreloc > 0) {
		fwrite(tcc_sect->reloc,
		       coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
	    }
	}
    }


    // group the symbols in order of filename, func1, func2, etc
    // finally global symbols

    if (s1->do_debug)
	SortSymbolTable();

    // write line no data

    for (i = 1; i < s1->nb_sections; i++) {
	coff_sec = &section_header[i];
	tcc_sect = s1->sections[i];

src/tcccoff.c  view on Meta::CPAN


	tcc_free(Coff_str_table);
    }

    return 0;
}



// group the symbols in order of filename, func1, func2, etc
// finally global symbols

void SortSymbolTable(void)
{
    int i, j, k, n = 0;
    Elf32_Sym *p, *p2, *NewTable;
    char *name, *name2;

    NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));

    p = (Elf32_Sym *) symtab_section->data;

src/tccelf.c  view on Meta::CPAN

    sym->st_size = size;
    sym->st_info = info;
    sym->st_other = other;
    sym->st_shndx = shndx;
    sym_index = sym - (ElfW(Sym) *)s->data;
    hs = s->hash;
    if (hs) {
        int *ptr, *base;
        ptr = section_ptr_add(hs, sizeof(int));
        base = (int *)hs->data;
        /* only add global or weak symbols */
        if (ELFW(ST_BIND)(info) != STB_LOCAL) {
            /* add another hashing entry */
            nbuckets = base[0];
            h = elf_hash(name) % nbuckets;
            *ptr = base[2 + h];
            base[2 + h] = sym_index;
            base[1]++;
            /* we resize the hash table */
            hs->nb_hashed_syms++;
            if (hs->nb_hashed_syms > 2 * nbuckets) {
                rebuild_hash(s, 2 * nbuckets);
            }
        } else {
            *ptr = 0;
            base[1]++;
        }
    }
    return sym_index;
}

/* find global ELF symbol 'name' and return its index. Return 0 if not
   found. */
ST_FUNC int find_elf_sym(Section *s, const char *name)
{
    ElfW(Sym) *sym;
    Section *hs;
    int nbuckets, sym_index, h;
    const char *name1;
    
    hs = s->hash;
    if (!hs)

src/tccelf.c  view on Meta::CPAN

{
    ElfW(Sym) *esym;
    int sym_bind, sym_index, sym_type, esym_bind;
    unsigned char sym_vis, esym_vis, new_vis;

    sym_bind = ELFW(ST_BIND)(info);
    sym_type = ELFW(ST_TYPE)(info);
    sym_vis = ELFW(ST_VISIBILITY)(other);
        
    if (sym_bind != STB_LOCAL) {
        /* we search global or weak symbols */
        sym_index = find_elf_sym(s, name);
        if (!sym_index)
            goto do_def;
        esym = &((ElfW(Sym) *)s->data)[sym_index];
        if (esym->st_shndx != SHN_UNDEF) {
            esym_bind = ELFW(ST_BIND)(esym->st_info);
            /* propagate the most constraining visibility */
            /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
            esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
            if (esym_vis == STV_DEFAULT) {

src/tccelf.c  view on Meta::CPAN

            } else {
                new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
            }
            esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
                             | new_vis;
            other = esym->st_other; /* in case we have to patch esym */
            if (sh_num == SHN_UNDEF) {
                /* ignore adding of undefined symbol if the
                   corresponding symbol is already defined */
            } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
                /* global overrides weak, so patch */
                goto do_patch;
            } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
                /* weak is ignored if already global */
            } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
                /* keep first-found weak definition, ignore subsequents */
            } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
                /* ignore hidden symbols after */
            } else if (esym->st_shndx == SHN_COMMON
                    && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
                /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
                   No idea if this is the correct solution ... */
                goto do_patch;
            } else if (s == tcc_state->dynsymtab_section) {

src/tccelf.c  view on Meta::CPAN

{
    put_stabs(NULL, type, other, desc, value);
}

ST_FUNC void put_stabd(int type, int other, int desc)
{
    put_stabs(NULL, type, other, desc, 0);
}

/* In an ELF file symbol table, the local symbols must appear below
   the global and weak ones. Since TCC cannot sort it while generating
   the code, we must do it after. All the relocation tables are also
   modified to take into account the symbol table sorting */
static void sort_syms(TCCState *s1, Section *s)
{
    int *old_to_new_syms;
    ElfW(Sym) *new_syms;
    int nb_syms, i;
    ElfW(Sym) *p, *q;
    ElfW_Rel *rel, *rel_end;
    Section *sr;

src/tccelf.c  view on Meta::CPAN

                            if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
                                /* weak symbols can stay undefined */
                            } else {
                                tcc_warning("undefined dynamic symbol '%s'", name);
                            }
                        }
                    }
                }
            } else {
                int nb_syms;
                /* shared library case : we simply export all the global symbols */
                nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
                s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
                for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
                    sym < sym_end;
                    sym++) {
                    if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
                        if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
                            ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
                            && sym->st_shndx == SHN_UNDEF) {

src/tccgen.c  view on Meta::CPAN

 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "tcc.h"

/********************************************************/
/* global variables */

/* loc : local variable index
   ind : output code index
   rsym: return symbol
   anon_sym: anonymous symbol index
*/
ST_DATA int rsym, anon_sym, ind, loc;

ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
ST_DATA Section *cur_text_section; /* current section where function code is generated */
#ifdef CONFIG_TCC_ASM
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
#endif
#ifdef CONFIG_TCC_BCHECK
/* bound check related sections */
ST_DATA Section *bounds_section; /* contains global data bound description */
ST_DATA Section *lbounds_section; /* contains local data bound description */
#endif
/* symbol sections */
ST_DATA Section *symtab_section, *strtab_section;
/* debug sections */
ST_DATA Section *stab_section, *stabstr_section;
ST_DATA Sym *sym_free_first;
ST_DATA void **sym_pools;
ST_DATA int nb_sym_pools;

ST_DATA Sym *global_stack;
ST_DATA Sym *local_stack;
ST_DATA Sym *scope_stack_bottom;
ST_DATA Sym *define_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *local_label_stack;

ST_DATA int vla_sp_loc_tmp; /* vla_sp_loc is set to this when the value won't be needed later */
ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
ST_DATA int *vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
ST_DATA int vla_flags; /* VLA_* flags */

ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop;

ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
ST_DATA int global_expr;  /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;

ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;

/* ------------------------------------------------------------------------- */
static void gen_cast(CType *type);
static inline CType *pointed_type(CType *type);

src/tccgen.c  view on Meta::CPAN


/* push a given symbol on the symbol stack */
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
{
    Sym *s, **ps;
    TokenSym *ts;

    if (local_stack)
        ps = &local_stack;
    else
        ps = &global_stack;
    s = sym_push2(ps, v, type->t, c);
    s->type.ref = type->ref;
    s->r = r;
    /* don't record fields or anonymous symbols */
    /* XXX: simplify */
    if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
        /* record symbol in token array */
        ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
        if (v & SYM_STRUCT)
            ps = &ts->sym_struct;
        else
            ps = &ts->sym_identifier;
        s->prev_tok = *ps;
        *ps = s;
    }
    return s;
}

/* push a global identifier */
ST_FUNC Sym *global_identifier_push(int v, int t, int c)
{
    Sym *s, **ps;
    s = sym_push2(&global_stack, v, t, c);
    /* don't record anonymous symbol */
    if (v < SYM_FIRST_ANOM) {
        ps = &table_ident[v - TOK_IDENT]->sym_identifier;
        /* modify the top most local identifier, so that
           sym_identifier will point to 's' when popped */
        while (*ps != NULL)
            ps = &(*ps)->prev_tok;
        s->prev_tok = NULL;
        *ps = s;
    }

src/tccgen.c  view on Meta::CPAN

    vpush64(VT_LLONG, v);
}

/* Return a static symbol pointing to a section */
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
{
    int v;
    Sym *sym;

    v = anon_sym++;
    sym = global_identifier_push(v, type->t | VT_STATIC, 0);
    sym->type.ref = type->ref;
    sym->r = VT_CONST | VT_SYM;
    put_extern_sym(sym, sec, offset, size);
    return sym;
}

/* push a reference to a section offset by adding a dummy symbol */
static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
{
    CValue cval;

    cval.ul = 0;
    vsetc(type, VT_CONST | VT_SYM, &cval);
    vtop->sym = get_sym_ref(type, sec, offset, size);
}

/* define a new external reference to a symbol 'v' of type 'u' */
ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
{
    Sym *s;

    s = sym_find(v);
    if (!s) {
        /* push forward reference */
        s = global_identifier_push(v, type->t | VT_EXTERN, 0);
        s->type.ref = type->ref;
        s->r = r | VT_CONST | VT_SYM;
    }
    return s;
}

/* define a new external reference to a symbol 'v' with alternate asm
   name 'asm_label' of type 'u'. 'asm_label' is equal to NULL if there
   is no alternate name (most cases) */
static Sym *external_sym(int v, CType *type, int r, char *asm_label)

src/tccgen.c  view on Meta::CPAN

        s->type.ref = type->ref;
        s->r = r | VT_CONST | VT_SYM;
        s->type.t |= VT_EXTERN;
    } else if (!is_compatible_types(&s->type, type)) {
        tcc_error("incompatible types for redefinition of '%s'", 
              get_tok_str(v, NULL));
    }
    return s;
}

/* push a reference to global symbol v */
ST_FUNC void vpush_global_sym(CType *type, int v)
{
    Sym *sym;
    CValue cval;

    sym = external_global_sym(v, type, 0);
    cval.ul = 0;
    vsetc(type, VT_CONST | VT_SYM, &cval);
    vtop->sym = sym;
}

ST_FUNC void vset(CType *type, int r, int v)
{
    CValue cval;

    cval.i = v;

src/tccgen.c  view on Meta::CPAN

        goto gen_mod_func;
    case TOK_UMOD:
        func = TOK___umoddi3;
    gen_mod_func:
#ifdef TCC_ARM_EABI
        reg_iret = TREG_R2;
        reg_lret = TREG_R3;
#endif
    gen_func:
        /* call generic long long function */
        vpush_global_sym(&func_old_type, func);
        vrott(3);
        gfunc_call(2);
        vpushi(0);
        vtop->r = reg_iret;
        vtop->r2 = reg_lret;
        break;
    case '^':
    case '&':
    case '|':
    case '*':

src/tccgen.c  view on Meta::CPAN

}

#ifndef TCC_TARGET_ARM
/* generic itof for unsigned long long case */
static void gen_cvt_itof1(int t)
{
    if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == 
        (VT_LLONG | VT_UNSIGNED)) {

        if (t == VT_FLOAT)
            vpush_global_sym(&func_old_type, TOK___floatundisf);
#if LDOUBLE_SIZE != 8
        else if (t == VT_LDOUBLE)
            vpush_global_sym(&func_old_type, TOK___floatundixf);
#endif
        else
            vpush_global_sym(&func_old_type, TOK___floatundidf);
        vrott(2);
        gfunc_call(1);
        vpushi(0);
        vtop->r = reg_fret(t);
    } else {
        gen_cvt_itof(t);
    }
}
#endif

/* generic ftoi for unsigned long long case */
static void gen_cvt_ftoi1(int t)
{
    int st;

    if (t == (VT_LLONG | VT_UNSIGNED)) {
        /* not handled natively */
        st = vtop->type.t & VT_BTYPE;
        if (st == VT_FLOAT)
            vpush_global_sym(&func_old_type, TOK___fixunssfdi);
#if LDOUBLE_SIZE != 8
        else if (st == VT_LDOUBLE)
            vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
#endif
        else
            vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
        vrott(2);
        gfunc_call(1);
        vpushi(0);
        vtop->r = REG_IRET;
        vtop->r2 = REG_LRET;
    } else {
        gen_cvt_ftoi(t);
    }
}

src/tccgen.c  view on Meta::CPAN

            size = type_size(&vtop->type, &align);

            /* destination */
            vswap();
            vtop->type.t = VT_PTR;
            gaddrof();

            /* address of memcpy() */
#ifdef TCC_ARM_EABI
            if(!(align & 7))
                vpush_global_sym(&func_old_type, TOK_memcpy8);
            else if(!(align & 3))
                vpush_global_sym(&func_old_type, TOK_memcpy4);
            else
#endif
            vpush_global_sym(&func_old_type, TOK_memcpy);

            vswap();
            /* source */
            vpushv(vtop - 2);
            vtop->type.t = VT_PTR;
            gaddrof();
            /* type size */
            vpushi(size);
            gfunc_call(3);
        } else {

src/tccgen.c  view on Meta::CPAN

        break;
    case '(':
        next();
        /* cast ? */
        if (parse_btype(&type, &ad)) {
            type_decl(&type, &ad, &n, TYPE_ABSTRACT);
            skip(')');
            /* check ISOC99 compound literal */
            if (tok == '{') {
                    /* data is allocated locally by default */
                if (global_expr)
                    r = VT_CONST;
                else
                    r = VT_LOCAL;
                /* all except arrays are lvalues */
                if (!(type.t & VT_ARRAY))
                    r |= lvalue_type(type.t);
                memset(&ad, 0, sizeof(AttributeDef));
                decl_initializer_alloc(&type, &ad, r, 1, 0, NULL, 0);
            } else {
                if (sizeof_caller) {

src/tccgen.c  view on Meta::CPAN

        break;
    case TOK_LAND:
        if (!gnu_ext)
            goto tok_identifier;
        next();
        /* allow to take the address of a label */
        if (tok < TOK_UIDENT)
            expect("label identifier");
        s = label_find(tok);
        if (!s) {
            s = label_push(&global_label_stack, tok, LABEL_FORWARD);
        } else {
            if (s->r == LABEL_DECLARED)
                s->r = LABEL_FORWARD;
        }
        if (!s->type.t) {
            s->type.t = VT_VOID;
            mk_pointer(&s->type);
            s->type.t |= VT_STATIC;
        }
        vset(&s->type, VT_CONST | VT_SYM, 0);

src/tccgen.c  view on Meta::CPAN

            expect("identifier");
        s = sym_find(t);
        if (!s) {
            if (tok != '(')
                tcc_error("'%s' undeclared", get_tok_str(t, NULL));
            /* for simple function calls, we tolerate undeclared
               external reference to int() function */
            if (tcc_state->warn_implicit_function_declaration)
                tcc_warning("implicit declaration of function '%s'",
                        get_tok_str(t, NULL));
            s = external_global_sym(t, &func_old_type, 0); 
        }
        if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
            (VT_STATIC | VT_INLINE | VT_FUNC)) {
            /* if referencing an inline function, then we generate a
               symbol to it if not already done. It will have the
               effect to generate code for it at the end of the
               compilation unit. Inline function as always
               generated in the text section. */
            if (!s->c)
                put_extern_sym(s, text_section, 0, 0);

src/tccgen.c  view on Meta::CPAN

            /* computed goto */
            next();
            gexpr();
            if ((vtop->type.t & VT_BTYPE) != VT_PTR)
                expect("pointer");
            ggoto();
        } else if (tok >= TOK_UIDENT) {
            s = label_find(tok);
            /* put forward definition if needed */
            if (!s) {
                s = label_push(&global_label_stack, tok, LABEL_FORWARD);
            } else {
                if (s->r == LABEL_DECLARED)
                    s->r = LABEL_FORWARD;
            }
            /* label already defined */
            if (vla_flags & VLA_IN_SCOPE) {
                /* If VLAs are in use, save the current stack pointer and
                   reset the stack pointer to what it was at function entry
                   (label will restore stack pointer in inner scopes) */
                vla_sp_save();

src/tccgen.c  view on Meta::CPAN

                   after the label unless we arrive via goto */
                vla_sp_save();
            }
            s = label_find(b);
            if (s) {
                if (s->r == LABEL_DEFINED)
                    tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL));
                gsym(s->jnext);
                s->r = LABEL_DEFINED;
            } else {
                s = label_push(&global_label_stack, b, LABEL_DEFINED);
            }
            s->jnext = ind;
            if (vla_flags & VLA_IN_SCOPE) {
                gen_vla_sp_restore(*vla_sp_loc);
                vla_flags |= VLA_NEED_NEW_FRAME;
            }
            /* we accept this, but it is a mistake */
        block_after_label:
            if (tok == '}') {
                tcc_warning("deprecated use of label at end of compound statement");

src/tccgen.c  view on Meta::CPAN

            dst += elem_size;
            memcpy(dst, src, elem_size);
        }
    }
}

#define EXPR_VAL   0
#define EXPR_CONST 1
#define EXPR_ANY   2

/* store a value or an expression directly in global data or in local array */
static void init_putv(CType *type, Section *sec, unsigned long c, 
                      int v, int expr_type)
{
    int saved_global_expr, bt, bit_pos, bit_size;
    void *ptr;
    unsigned long long bit_mask;
    CType dtype;

    switch(expr_type) {
    case EXPR_VAL:
        vpushi(v);
        break;
    case EXPR_CONST:
        /* compound literals must be allocated globally in this case */
        saved_global_expr = global_expr;
        global_expr = 1;
        expr_const1();
        global_expr = saved_global_expr;
        /* NOTE: symbols are accepted */
        if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
            tcc_error("initializer element is not constant");
        break;
    case EXPR_ANY:
        expr_eq();
        break;
    }
    
    dtype = *type;

src/tccgen.c  view on Meta::CPAN

        vswap();
        vstore();
        vpop();
    }
}

/* put zeros for variable based init */
static void init_putz(CType *t, Section *sec, unsigned long c, int size)
{
    if (sec) {
        /* nothing to do because globals are already set to zero */
    } else {
        vpush_global_sym(&func_old_type, TOK_memset);
        vseti(VT_LOCAL, c);
        vpushi(0);
        vpushs(size);
        gfunc_call(3);
    }
}

/* 't' contains the type and storage info. 'c' is the offset of the
   object in section 'sec'. If 'sec' is NULL, it means stack based
   allocation. 'first' is true if array '{' must be read (multi

src/tccgen.c  view on Meta::CPAN

                else
                    cstr_len = cstr->size / sizeof(nwchar_t);
                cstr_len--;
                nb = cstr_len;
                if (n >= 0 && nb > (n - array_length))
                    nb = n - array_length;
                if (!size_only) {
                    if (cstr_len > nb)
                        tcc_warning("initializer-string for array is too long");
                    /* in order to go faster for common case (char
                       string in global variable, we handle it
                       specifically */
                    if (sec && tok == TOK_STR && size1 == 1) {
                        memcpy(sec->data + c + array_length, cstr->data, nb);
                    } else {
                        for(i=0;i<nb;i++) {
                            if (tok == TOK_STR)
                                ch = ((unsigned char *)cstr->data)[i];
                            else
                                ch = ((nwchar_t *)cstr->data)[i];
                            init_putv(t1, sec, c + (array_length + i) * size1,

src/tccgen.c  view on Meta::CPAN

                parlevel++;
            else if (tok == ')')
                parlevel--;
	    else if (tok == '{')
		parlevel1++;
	    else if (tok == '}')
		parlevel1--;
            next();
        }
    } else {
        /* currently, we always use constant expression for globals
           (may change for scripting case) */
        expr_type = EXPR_CONST;
        if (!sec)
            expr_type = EXPR_ANY;
        init_putv(type, sec, c, 0, expr_type);
    }
}

/* parse an initializer for type 't' if 'has_init' is non zero, and
   allocate space in local or global data space ('r' is either
   VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
   variable 'v' with an associated name represented by 'asm_label' of
   scope 'scope' is declared before initializers are parsed. If 'v' is
   zero, then a reference to the new object is put in the value stack.
   If 'has_init' is 2, a special parsing is done to handle string
   constants. */
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, 
                                   int has_init, int v, char *asm_label,
                                   int scope)
{

src/tccgen.c  view on Meta::CPAN

            while (field->next)
                field = field->next;
            if (field->type.t & VT_ARRAY && field->type.ref->c < 0)
                flexible_array = field;
        }
    }

    size = type_size(type, &align);
    /* If unknown size, we must evaluate it before
       evaluating initializers because
       initializers can generate global data too
       (e.g. string pointers or ISOC99 compound
       literals). It also simplifies local
       initializers handling */
    tok_str_new(&init_str);
    if (size < 0 || (flexible_array && has_init)) {
        if (!has_init) 
            tcc_error("unknown type size");
        /* get all init string */
        if (has_init == 2) {
            /* only get strings */

src/tccgen.c  view on Meta::CPAN

                    /* if the variable is extern, it was not allocated */
                    sym->type.t &= ~VT_EXTERN;
                    /* set array size if it was ommited in extern
                       declaration */
                    if ((sym->type.t & VT_ARRAY) && 
                        sym->type.ref->c < 0 &&
                        type->ref->c >= 0)
                        sym->type.ref->c = type->ref->c;
                } else {
                    /* we accept several definitions of the same
                       global variable. this is tricky, because we
                       must play with the SHN_COMMON type of the symbol */
                    /* XXX: should check if the variable was already
                       initialized. It is incorrect to initialized it
                       twice */
                    /* no init data, we won't add more to the symbol */
                    if (!has_init)
                        goto no_alloc;
                }
            }
        }

src/tccgen.c  view on Meta::CPAN

        if (!sec) {
            if (has_init)
                sec = data_section;
            else if (tcc_state->nocommon)
                sec = bss_section;
        }
        if (sec) {
            data_offset = sec->data_offset;
            data_offset = (data_offset + align - 1) & -align;
            addr = data_offset;
            /* very important to increment global pointer at this time
               because initializers themselves can create new initializers */
            data_offset += size;
#ifdef CONFIG_TCC_BCHECK
            /* add padding if bound check */
            if (tcc_state->do_bounds_check)
                data_offset++;
#endif
            sec->data_offset = data_offset;
            /* allocate section space to put the data */
            if (sec->sh_type != SHT_NOBITS && 

src/tccgen.c  view on Meta::CPAN

                ElfW(Sym) *esym;
                /* put a common area */
                put_extern_sym(sym, NULL, align, size);
                /* XXX: find a nicer way */
                esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
                esym->st_shndx = SHN_COMMON;
            }
        } else {
            CValue cval;

            /* push global reference */
            sym = get_sym_ref(type, sec, addr, size);
            cval.ul = 0;
            vsetc(type, VT_CONST | VT_SYM, &cval);
            vtop->sym = sym;
        }
        /* patch symbol weakness */
        if (type->t & VT_WEAK)
            weaken_symbol(sym);
#ifdef CONFIG_TCC_BCHECK
        /* handles bounds now because the symbol must be defined
           before for the relocation */
        if (tcc_state->do_bounds_check) {
            unsigned long *bounds_ptr;

            greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR);
            /* then add global bound info */
            bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
            bounds_ptr[0] = 0; /* relocated */
            bounds_ptr[1] = size;
        }
#endif
    }
    if (has_init || (type->t & VT_VLA)) {
        decl_initializer(type, sec, addr, 1, 0);
        /* restore parse state if needed */
        if (init_str.str) {

src/tccgen.c  view on Meta::CPAN

    if (tcc_state->do_debug)
        put_func_debug(sym);
    /* push a dummy symbol to enable local sym storage */
    sym_push2(&local_stack, SYM_FIELD, 0, 0);
    gfunc_prolog(&sym->type);
    rsym = 0;
    block(NULL, NULL, NULL, NULL, 0, 0);
    gsym(rsym);
    gfunc_epilog();
    cur_text_section->data_offset = ind;
    label_pop(&global_label_stack, NULL);
    /* reset local stack */
    scope_stack_bottom = NULL;
    sym_pop(&local_stack, NULL);
    /* end of function */
    /* patch symbol size */
    ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = 
        ind - func_ind;
    /* patch symbol weakness (this definition overrules any prototype) */
    if (sym->type.t & VT_WEAK)
        weaken_symbol(sym);

src/tccgen.c  view on Meta::CPAN

            if (is_for_loop_init)
                return 0;
            /* skip redundant ';' */
            /* XXX: find more elegant solution */
            if (tok == ';') {
                next();
                continue;
            }
            if (l == VT_CONST &&
                (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
                /* global asm block */
                asm_global_instr();
                continue;
            }
            /* special test for old K&R protos without explicit int
               type. Only accepted when defining global data */
            if (l == VT_LOCAL || tok < TOK_DEFINE)
                break;
            btype.t = VT_INT;
        }
        if (((btype.t & VT_BTYPE) == VT_ENUM ||
             (btype.t & VT_BTYPE) == VT_STRUCT) && 
            tok == ';') {
            /* we accept no variable after */
            next();
            continue;

src/tccgen.c  view on Meta::CPAN

                    if (!is_compatible_types(&sym->type, &type)) {
                    func_error1:
                        tcc_error("incompatible types for redefinition of '%s'", 
                              get_tok_str(v, NULL));
                    }
                    FUNC_PROTO(type.ref->r) = 0;
                    /* if symbol is already defined, then put complete type */
                    sym->type = type;
                } else {
                    /* put function symbol */
                    sym = global_identifier_push(v, type.t, 0);
                    sym->type.ref = type.ref;
                }

                /* static inline functions are just recorded as a kind
                   of macro. Their code will be emitted at the end of
                   the compilation unit only if they are used */
                if ((type.t & (VT_INLINE | VT_STATIC)) == 
                    (VT_INLINE | VT_STATIC)) {
                    TokenString func_str;
                    int block_level;

src/tccgen.c  view on Meta::CPAN

                        /* not lvalue if array */
                        r |= lvalue_type(type.t);
                    }
                    has_init = (tok == '=');
                    if (has_init && (type.t & VT_VLA))
                        tcc_error("Variable length array cannot be initialized");
                    if ((btype.t & VT_EXTERN) || ((type.t & VT_BTYPE) == VT_FUNC) ||
                        ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
                         !has_init && l == VT_CONST && type.ref->c < 0)) {
                        /* external variable or function */
                        /* NOTE: as GCC, uninitialized global static
                           arrays of null size are considered as
                           extern */
                        sym = external_sym(v, &type, r, asm_label);

                        if (type.t & VT_WEAK)
                            weaken_symbol(sym);

                        if (ad.alias_target) {
                            Section tsec;
                            Elf32_Sym *esym;

src/tccpp.c  view on Meta::CPAN

 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "tcc.h"

/********************************************************/
/* global variables */

ST_DATA int tok_flags;
/* additional informations about token */
#define TOK_FLAG_BOL   0x0001 /* beginning of line before */
#define TOK_FLAG_BOF   0x0002 /* beginning of file before */
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
#define TOK_FLAG_EOF   0x0008 /* end of file */

ST_DATA int parse_flags;
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */

src/tccpp.c  view on Meta::CPAN

        return NULL;
    return table_ident[v]->sym_label;
}

ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
{
    Sym *s, **ps;
    s = sym_push2(ptop, v, 0, 0);
    s->r = flags;
    ps = &table_ident[v - TOK_IDENT]->sym_label;
    if (ptop == &global_label_stack) {
        /* modify the top most local identifier, so that
           sym_identifier will point to 's' when popped */
        while (*ps != NULL)
            ps = &(*ps)->prev_tok;
    }
    s->prev_tok = *ps;
    *ps = s;
    return s;
}

src/tcctok.h  view on Meta::CPAN

/* Tiny Assembler */
 DEF_ASM(byte)
 DEF_ASM(word)
 DEF_ASM(align)
 DEF_ASM(skip)
 DEF_ASM(space)
 DEF_ASM(string)
 DEF_ASM(asciz)
 DEF_ASM(ascii)
 DEF_ASM(file)
 DEF_ASM(globl)
 DEF_ASM(global)
 DEF_ASM(ident)
 DEF_ASM(size)
 DEF_ASM(type)
 DEF_ASM(text)
 DEF_ASM(data)
 DEF_ASM(bss)
 DEF_ASM(previous)
 DEF_ASM(fill)
 DEF_ASM(org)
 DEF_ASM(quad)

src/tests/tests2/46_grep.c  view on Meta::CPAN


/*** Display usage summary *****************************/
void usage(char *s)
{
   fprintf(stderr, "?GREP-E-%s\n", s);
   fprintf(stderr,
         "Usage: grep [-cfnv] pattern [file ...].  grep ? for help\n");
   exit(1);
}

/*** Compile the pattern into global pbuf[] ************/
void compile(char *source)
{
   char  *s;         /* Source string pointer     */
   char  *lp;        /* Last pattern pointer      */
   int   c;          /* Current character         */
   int            o;          /* Temp                      */
   char           *spp;       /* Save beginning of pattern */

   s = source;
   if (debug)

src/win32/include/ctype.h  view on Meta::CPAN

#endif
#endif
#endif

  /* CRT stuff */
#if 1
  extern const unsigned char __newclmap[];
  extern const unsigned char __newcumap[];
  extern pthreadlocinfo __ptlocinfo;
  extern pthreadmbcinfo __ptmbcinfo;
  extern int __globallocalestatus;
  extern int __locale_changed;
  extern struct threadlocaleinfostruct __initiallocinfo;
  extern _locale_tstruct __initiallocalestructinfo;
  pthreadlocinfo __cdecl __updatetlocinfo(void);
  pthreadmbcinfo __cdecl __updatetmbcinfo(void);
#endif

#define _UPPER 0x1
#define _LOWER 0x2
#define _DIGIT 0x4

src/win32/lib/chkstk.S  view on Meta::CPAN

/* ---------------------------------------------- */
/* chkstk86.s */

/* ---------------------------------------------- */
#ifndef TCC_TARGET_X86_64
/* ---------------------------------------------- */

.globl __chkstk

__chkstk:
    xchg    (%esp),%ebp     /* store ebp, get ret.addr */
    push    %ebp            /* push ret.addr */
    lea     4(%esp),%ebp    /* setup frame ptr */
    push    %ecx            /* save ecx */
    mov     %ebp,%ecx
P0:
    sub     $4096,%ecx
    test    %eax,(%ecx)

src/win32/lib/chkstk.S  view on Meta::CPAN


    mov     %esp,%eax
    mov     %ecx,%esp
    mov     (%eax),%ecx     /* restore ecx */
    jmp     *4(%eax)

/* ---------------------------------------------- */
#else
/* ---------------------------------------------- */

.globl __chkstk

__chkstk:
    xchg    (%rsp),%rbp     /* store ebp, get ret.addr */
    push    %rbp            /* push ret.addr */
    lea     8(%rsp),%rbp    /* setup frame ptr */
    push    %rcx            /* save ecx */
    mov     %rbp,%rcx
    movslq  %eax,%rax
P0:
    sub     $4096,%rcx

src/win32/lib/chkstk.S  view on Meta::CPAN

    test    %rax,(%rcx)

    mov     %rsp,%rax
    mov     %rcx,%rsp
    mov     (%rax),%rcx     /* restore ecx */
    jmp     *8(%rax)

/* ---------------------------------------------- */
/* setjmp/longjmp support */

.globl tinyc_getbp
tinyc_getbp:
    mov %rbp,%rax
    ret

/* ---------------------------------------------- */
#endif
/* ---------------------------------------------- */


/* ---------------------------------------------- */

src/win32/lib/chkstk.S  view on Meta::CPAN

    __try
    {
         // ...
    }
    __except (_XcptFilter(GetExceptionCode(), GetExceptionInformation()))
    {
         exit(GetExceptionCode());
    }
*/

.globl _exception_info
_exception_info:
    mov 1*4-24(%ebp),%eax
    ret

.globl _exception_code
_exception_code:
    call _exception_info
    mov (%eax),%eax
    mov (%eax),%eax
    ret

seh_filter:
    call _exception_info
    push %eax
    call _exception_code

src/win32/lib/chkstk.S  view on Meta::CPAN

// msvcrt wants scopetables aligned and in read-only segment (using .text)
.align 4
seh_scopetable:
    .long -1
    .long seh_filter
    .long seh_except

seh_handler:
    jmp _except_handler3

.globl ___try__
___try__:
.globl __try__
__try__:
    push %ebp
    mov 8(%esp),%ebp

//    void *esp;
    lea 12(%esp),%eax
    mov %eax,0*4(%ebp)

//    void *exception_pointers;
    xor %eax,%eax

src/win32/lib/crt1.c  view on Meta::CPAN

#define __CONSOLE_APP    1
#define __GUI_APP        2
void __set_app_type(int);
void _controlfp(unsigned a, unsigned b);

typedef struct
{
    int newmode;
} _startupinfo;

void __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
int main(int argc, char **argv, char **env);

int _start(void)
{
    __TRY__
    int argc; char **argv; char **env; int ret;
    _startupinfo start_info = {0};

    _controlfp(0x10000, 0x30000);
    __set_app_type(__CONSOLE_APP);

src/win32/lib/msvcrt.def  view on Meta::CPAN

_getdrive
_getdrives
_getmaxstdio
_getmbcp
_getpid
_getsystime
_getw
_getwch
_getwche
_getws
_global_unwind2
_gmtime32
_gmtime32_s
_gmtime64
_gmtime64_s
_heapadd
_heapchk
_heapmin
_heapset
_heapused
_heapwalk

src/x86_64-gen.c  view on Meta::CPAN

        g(func_ret_sub);
        g(func_ret_sub >> 8);
    }

    saved_ind = ind;
    ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
    /* align local size to word & save local variables */
    v = (func_scratch + -loc + 15) & -16;

    if (v >= 4096) {
        Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
        oad(0xb8, v); /* mov stacksize, %eax */
        oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
        greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
        o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
    } else {
        o(0xe5894855);  /* push %rbp, mov %rsp, %rbp */
        o(0xec8148);  /* sub rsp, stacksize */
        gen_le32(v);
    }

src/x86_64-gen.c  view on Meta::CPAN


/* Restore the SP from a location on the stack */
ST_FUNC void gen_vla_sp_restore(int addr) {
    gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr);
}

/* Subtract from the stack pointer, and push the resulting value onto the stack */
ST_FUNC void gen_vla_alloc(CType *type, int align) {
#ifdef TCC_TARGET_PE
    /* alloca does more than just adjust %rsp on Windows */
    vpush_global_sym(&func_old_type, TOK_alloca);
    vswap(); /* Move alloca ref past allocation size */
    gfunc_call(1);
    vset(type, REG_IRET, 0);
#else
    int r;
    r = gv(RC_INT); /* allocation size */
    /* sub r,%rsp */
    o(0x2b48);
    o(0xe0 | REG_VALUE(r));
    /* We align to 16 bytes rather than align */

t/30-tcc-test-suite.t  view on Meta::CPAN

use Test::More;

use Alien::TinyCC;

# Needed for quick patching
use inc::My::Build;

# These test files don't work, according to tcc's own test suite Makefile
my @test_files = grep {
	not (m/30_hanoi/ or m/34_array_assignment/ or m/46_grep/)
} glob 'src/tests/tests2/*.c';

# Tabulate known failure points
my (@expected_to_fail, $todo_message);
if ($^O =~ /darwin/) {
	$todo_message = 'Known to fail on Mac';
	push @expected_to_fail, qr/40_stdio/, qr/32_led/;
}
if ($^O =~ /MSWin/) {
	$todo_message = 'Known to fail on Windows';
	push @expected_to_fail, qr/24_math_library/, qr/28_strings/



( run in 1.172 second using v1.01-cache-2.11-cpan-49f99fa48dc )