view release on metacpan or search on metacpan
src/tests/exsymtab/36-two-contexts-typedef-share.c
src/tests/exsymtab/40-two-contexts-func-decl-share.c
src/tests/exsymtab/41-two-contexts-inline-func-share.c
src/tests/exsymtab/42-three-contexts-func-share.c
src/tests/exsymtab/43-three-contexts-inline-func-share.c
src/tests/exsymtab/47-many-consuming-contexts-func-share.c
src/tests/exsymtab/48-many-consuming-contexts-delete.c
src/tests/exsymtab/49-many-consuming-contexts-early-delete.c
src/tests/exsymtab/50-two-contexts-mixup.c
src/tests/exsymtab/51-many-consuming-contexts-with-constants-early-delete.c
src/tests/exsymtab/60-two-contexts-globals.c
src/tests/exsymtab/61-two-contexts-const-globals.c
src/tests/exsymtab/62-two-contexts-static-globals.c
src/tests/exsymtab/63-two-contexts-enum.c
src/tests/exsymtab/70-symtab-use-check.c
src/tests/exsymtab/80-cache-defines.c
src/tests/exsymtab/81-cache-struct.c
src/tests/exsymtab/82-cache-func-decl.c
src/tests/exsymtab/83-cache-func-decl-with-args.c
src/tests/exsymtab/84-cache-func-decl-with-pointer-args.c
src/tests/exsymtab/85-cache-inline-func.c
src/tests/exsymtab/dump-elf-syms.c
src/tests/exsymtab/mytest.pl
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
- add va_* macro implementation for ARM (Thomas Preud'homme)
- define __ARM_EABI__, __ARMEL__ and __ARM_PCS_VFP (Thomas Preud'homme)
- provide a runtime library for ARM (Thomas Preud'homme)
- vastly improved support for ARM hard float calling convention
(Thomas Preud'homme, Daniel Glöckner)
- tcc can uses libtcc1 on ARM (Thomas Preud'homme)
- use __fixdfdi for all float to integer conversion (grischka)
- simplify startup code for unix platforms (grischka)
- improve ELF generated on ARM (Thomas Preud'homme)
- add support for thumb to ARM relocation (Thomas Preud'homme)
- fix globbing to match MSVC on Windows (Thomas Preud'homme)
- deprecate FPA and OABI support for ARM (Thomas Preud'homme)
- warn about softfloat not being supported on ARM (Thomas Preud'homme)
Bug fixes:
- many code clean up (Urs Janssen, grischka)
- fixes of other's patches (grischka, Ramsay Jones, Michael Matz)
- fix documentation about __TINYC__ (Urs Janssen)
- improve build of documentation (Urs Janssen)
- improve build instructions (Jov)
- switch from texi2html to makeinfo --html to build tcc-doc.html (James Lyon)
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/arm64-gen.c view on Meta::CPAN
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
b2 = ind; o(0x14000000); // b lab2
// lab1:
write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3);
o(0xb9001c00 | r1 | r0 << 5); // str w(r1),[x(r0),#28] // __vr_offs
o(0xf9400800 | r1 | r0 << 5); // ldr x(r1),[x(r0),#16] // __vr_top
if (hfa == 1 || fsize == 16)
o(0x8b3ec000 | r1 | r1 << 5); // add x(r1),x(r1),w30,sxtw
else {
// We need to change the layout of this HFA.
// Get some space on the stack using global variable "loc":
loc = (loc - size) & -(uint32_t)align;
o(0x8b3ec000 | 30 | r1 << 5); // add x30,x(r1),w30,sxtw
arm64_movimm(r1, loc);
o(0x8b0003a0 | r1 | r1 << 16); // add x(r1),x29,x(r1)
o(0x4c402bdc | (uint32_t)fsize << 7 |
(uint32_t)(hfa == 2) << 15 |
(uint32_t)(hfa == 3) << 14); // ld1 {v28.(4s|2d),...},[x30]
o(0x0d00801c | r1 << 5 | (fsize == 8) << 10 |
(uint32_t)(hfa != 2) << 13 |
(uint32_t)(hfa != 3) << 21); // st(hfa) {v28.(s|d),...}[0],[x(r1)]
src/arm64-gen.c view on Meta::CPAN
case '-': func = TOK___subtf3; break;
case '/': func = TOK___divtf3; break;
case TOK_EQ: func = TOK___eqtf2; cond = 1; break;
case TOK_NE: func = TOK___netf2; cond = 0; break;
case TOK_LT: func = TOK___lttf2; cond = 10; break;
case TOK_GE: func = TOK___getf2; cond = 11; break;
case TOK_LE: func = TOK___letf2; cond = 12; break;
case TOK_GT: func = TOK___gttf2; cond = 13; break;
default: assert(0); break;
}
vpush_global_sym(&func_old_type, func);
vrott(3);
gfunc_call(2);
vpushi(0);
vtop->r = cond < 0 ? REG_FRET : REG_IRET;
if (cond < 0)
vtop->type = type;
else {
o(0x7100001f); // cmp w0,#0
o(0x1a9f07e0 | (uint32_t)cond << 12); // cset w0,(cond)
}
src/arm64-gen.c view on Meta::CPAN
o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)
}
ST_FUNC void gen_cvt_itof(int t)
{
if (t == VT_LDOUBLE) {
int f = vtop->type.t;
int func = (f & VT_BTYPE) == VT_LLONG ?
(f & VT_UNSIGNED ? TOK___floatunditf : TOK___floatditf) :
(f & VT_UNSIGNED ? TOK___floatunsitf : TOK___floatsitf);
vpush_global_sym(&func_old_type, func);
vrott(2);
gfunc_call(1);
vpushi(0);
vtop->type.t = t;
vtop->r = REG_FRET;
return;
}
else {
int d, n = intr(gv(RC_INT));
int s = !(vtop->type.t & VT_UNSIGNED);
src/arm64-gen.c view on Meta::CPAN
l << 31 | n << 5); // [us]cvtf [sd](d),[wx](n)
}
}
ST_FUNC void gen_cvt_ftoi(int t)
{
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
int func = (t & VT_BTYPE) == VT_LLONG ?
(t & VT_UNSIGNED ? TOK___fixunstfdi : TOK___fixtfdi) :
(t & VT_UNSIGNED ? TOK___fixunstfsi : TOK___fixtfsi);
vpush_global_sym(&func_old_type, func);
vrott(2);
gfunc_call(1);
vpushi(0);
vtop->type.t = t;
vtop->r = REG_IRET;
return;
}
else {
int d, n = fltr(gv(RC_FLOAT));
uint32_t l = ((vtop->type.t & VT_BTYPE) != VT_FLOAT);
src/arm64-gen.c view on Meta::CPAN
int f = vtop[0].type.t;
assert(t == VT_FLOAT || t == VT_DOUBLE || t == VT_LDOUBLE);
assert(f == VT_FLOAT || f == VT_DOUBLE || f == VT_LDOUBLE);
if (t == f)
return;
if (t == VT_LDOUBLE || f == VT_LDOUBLE) {
int func = (t == VT_LDOUBLE) ?
(f == VT_FLOAT ? TOK___extendsftf2 : TOK___extenddftf2) :
(t == VT_FLOAT ? TOK___trunctfsf2 : TOK___trunctfdf2);
vpush_global_sym(&func_old_type, func);
vrott(2);
gfunc_call(1);
vpushi(0);
vtop->type.t = t;
vtop->r = REG_FRET;
}
else {
int x, a;
gv(RC_FLOAT);
assert(vtop[0].r < VT_CONST);
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/conftest.c view on Meta::CPAN
# define TRIPLET_ABI "gnu"
#endif
#ifdef __GNU__
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
#else
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
#endif
#if defined(_WIN32)
int _CRT_glob = 0;
#endif
int main(int argc, char *argv[])
{
switch(argc == 2 ? argv[1][0] : 0) {
case 'b':
{
volatile unsigned foo = 0x01234567;
puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes");
break;
#define VER_DEF_NONE 0 /* No version */
#define VER_DEF_CURRENT 1 /* Current version */
#define VER_DEF_NUM 2 /* Given version number */
/* Legal values for vd_flags (version information flags). */
#define VER_FLG_BASE 0x1 /* Version definition of file itself */
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
/* Versym symbol index values. */
#define VER_NDX_LOCAL 0 /* Symbol is local. */
#define VER_NDX_GLOBAL 1 /* Symbol is global. */
#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
/* Auxialiary version information. */
typedef struct
{
Elf32_Word vda_name; /* Version or dependency names */
Elf32_Word vda_next; /* Offset in bytes to next verdaux
entry */
#define AT_IGNOREPPC 22 /* Entry should be ignored. */
#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/
#define AT_RANDOM 25 /* Address of 16 random bytes. */
#define AT_EXECFN 31 /* Filename of executable. */
/* Pointer to the global system page used for system calls and other
nice things. */
#define AT_SYSINFO 32
#define AT_SYSINFO_EHDR 33
/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
log2 of line size; mask those to get cache size. */
#define AT_L1I_CACHESHAPE 34
#define AT_L1D_CACHESHAPE 35
#define AT_L2_CACHESHAPE 36
#define AT_L3_CACHESHAPE 37
#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. */
} 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 */
#define R_ARM_THM_MOVW_ABS_NC 47
#define R_ARM_THM_MOVT_ABS 48
#define R_ARM_TLS_GOTDESC 90
#define R_ARM_TLS_CALL 91
#define R_ARM_TLS_DESCSEQ 92
#define R_ARM_THM_TLS_CALL 93
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
#define R_ARM_THM_PC9 103 /* thumb conditional branch */
#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic
thread local data */
#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic
thread local data */
#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS
block */
#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of
static TLS block offset */
#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static
TLS block */
#define R_ARM_THM_TLS_DESCSEQ 129
#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
#define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */
#define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */
#define R_MN10300_TLS_LDO 26 /* Module-relative offset. */
#define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block
offset. */
#define R_MN10300_TLS_IE 28 /* GOT address for static TLS block
offset. */
#define R_MN10300_TLS_LE 29 /* Offset relative to static TLS
block. */
#define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */
#define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */
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) {
int rt;
src/i386-gen.c view on Meta::CPAN
gv(RC_FLOAT);
save_reg(TREG_EAX);
save_reg(TREG_EDX);
gen_static_call(TOK___tcc_cvt_ftol);
vtop->r = TREG_EAX; /* mark reg as used */
if (t == VT_LLONG)
vtop->r2 = TREG_EDX;
#else
int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixsfdi);
else if (bt == VT_LDOUBLE)
vpush_global_sym(&func_old_type, TOK___fixxfdi);
else
vpush_global_sym(&func_old_type, TOK___fixdfdi);
vswap();
gfunc_call(1);
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = REG_LRET;
#endif
}
/* convert from one floating point type to another */
ST_FUNC void gen_cvt_ftof(int t)
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.i);
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);
#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 */
/* and ~15, %esp */
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/alloca-arm.S view on Meta::CPAN
.text
.align 2
.global alloca
.type alloca, %function
alloca:
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
mov pc, lr
.size alloca, .-alloca
.section .note.GNU-stack,"",%progbits
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-bt.S view on Meta::CPAN
/* ---------------------------------------------- */
/* alloca86_64.S */
.globl __bound_alloca
__bound_alloca:
#ifdef TCC_TARGET_PE
# bound checking is not implemented
pop %rdx
mov %rcx,%rax
add $15,%rax
and $-16,%rax
jz p3
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
ST_FUNC char *normalize_slashes(char *path)
{
char *p;
src/libtcc.c view on Meta::CPAN
tcc_serialize_extended_symtab(s1->exsymtab, s1->symtab_serialize_outfile);
/* Output the symbol names */
if (s1->dump_identifier_names_outfile)
tcc_dump_identifier_names(s1->exsymtab, s1->dump_identifier_names_outfile);
}
/* #endif */
free_inline_functions(s1);
/* reset define stack, but keep -D and built-ins */
free_defines(define_start);
sym_pop(&global_stack, NULL);
sym_pop(&local_stack, NULL);
return s1->nb_errors != 0 ? -1 : 0;
}
/* #ifdef CONFIG_TCC_EXSYMTAB */
LIBTCCAPI int tcc_compile_string_ex(TCCState *s, const char *str, int len, const char * filename, int line_num)
{
int ret;
/* Open the buffer and copy the contents */
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 search 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:
" -Dsym[=val] define 'sym' with value 'val'\n"
" -Usym undefine 'sym'\n"
" -E preprocess only\n"
" -P[1] no / alternative #line output with -E\n"
" -dD -dM output #define directives with -E\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
ST_FUNC void cstr_free(CString *cstr);
ST_FUNC void cstr_reset(CString *cstr);
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);
/* flags: */
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
#define AFF_PREPROCESS 0x40 /* preprocess file */
return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
}
/* ------------ tccgen.c ------------ */
#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, *pvtop;
#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_var; /* true if current function is variadic */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA const char *funcname;
ST_FUNC void tccgen_start(TCCState *s1);
ST_FUNC void tccgen_end(TCCState *s1);
ST_FUNC void free_inline_functions(TCCState *s);
ST_FUNC void check_vstack(void);
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 void save_reg_upstack(int r, int n);
unsigned int n_value; /* value of symbol */
} Stab_Sym;
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 */
ST_FUNC void tccelf_bounds_new(TCCState *s);
#endif
/* symbol sections */
ST_DATA Section *symtab_section, *strtab_section;
/* debug sections */
ST_DATA Section *stab_section, *stabstr_section;
ST_FUNC void tccelf_new(TCCState *s);
ST_FUNC void tccelf_delete(TCCState *s);
/* ------------ 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
sym_dot.r = cur_text_section->sh_num;
sym_dot.jnext = ind;
next();
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_ASMDIR_globl:
case TOK_ASMDIR_global:
case TOK_ASMDIR_weak:
case TOK_ASMDIR_hidden:
tok1 = tok;
do {
Sym *sym;
next();
sym = label_find(tok);
if (!sym) {
sym = label_push(&s1->asm_labels, tok, 0);
src/tccasm.c view on Meta::CPAN
asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
next();
skip(':');
goto redo;
} else if (tok >= TOK_IDENT) {
/* instruction or label */
opcode = tok;
next();
if (tok == ':') {
/* handle "extern void vide(void); __asm__("vide: ret");" as
"__asm__("globl vide\nvide: ret");" */
Sym *sym = sym_find(opcode);
if (sym && (sym->type.t & VT_EXTERN) && nocode_wanted) {
sym = label_find(opcode);
if (!sym) {
sym = label_push(&s1->asm_labels, opcode, 0);
sym->type.t = VT_VOID;
}
}
/* new label */
asm_new_label(s1, opcode, 0);
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 = §ion_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
* 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"
/* Define this to get some debug output during relocation processing. */
#undef DEBUG_RELOC
/********************************************************/
/* global variables */
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;
/* XXX: avoid static variable */
static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
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((unsigned char *) 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
|| esym->st_shndx == bss_section->sh_num)
&& (sh_num < SHN_LORESERVE
&& sh_num != bss_section->sh_num)) {
/* data symbol gets precedence over common/bss */
goto do_patch;
src/tccelf.c view on Meta::CPAN
put_stabs(NULL, type, other, desc, 0);
}
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
using variable <elem> */
#define for_each_elem(sec, startoff, elem, type) \
for (elem = (type *) sec->data + startoff; \
elem < (type *) (sec->data + sec->data_offset); elem++)
/* 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;
Section *sr;
src/tccelf.c view on Meta::CPAN
sym->st_info, 0, sym->st_shndx, name);
} else if (esym->st_shndx == SHN_UNDEF) {
/* weak symbols can stay undefined */
if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
tcc_warning("undefined dynamic symbol '%s'", name);
}
}
}
/* Export all non local symbols (for shared libraries) */
static void export_global_syms(TCCState *s1)
{
int nb_syms, dynindex, index;
const char *name;
ElfW(Sym) *sym;
nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
name = (char *) symtab_section->link->data + sym->st_name;
src/tccelf.c view on Meta::CPAN
if (file_type == TCC_OUTPUT_EXE) {
bind_exe_dynsyms(s1);
if (s1->nb_errors) {
ret = -1;
goto the_end;
}
bind_libs_dynsyms(s1);
} else /* shared library case: simply export all global symbols */
export_global_syms(s1);
build_got_entries(s1);
/* add a list of needed dlls */
for(i = 0; i < s1->nb_loaded_dlls; i++) {
DLLReference *dllref = s1->loaded_dlls[i];
if (dllref->level == 0)
put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
}
src/tccexsymtab.c view on Meta::CPAN
if (curr_sym->type.t & VT_CONSTANT) fprintf(out_fh, "constant ");
/* type */
btype = curr_sym->type.t & VT_BTYPE;
fprintf(out_fh, "%s\n", type_lookup_table[btype]);
}
fclose(out_fh);
}
/* tcc_get_next_extended_symbol_name: a simple mechanism for getting the names
* of all of the global symbols known to the extended symbol table. */
char * tcc_get_next_extended_symbol_name(extended_symtab * symtab, int * poffset)
{
/* Increment the counter to get to the next TokenSym */
for ((*poffset)++; symtab->tokenSym_list + *poffset < symtab->tokenSym_last; (*poffset)++)
{
TokenSym * ts = symtab->tokenSym_list[*poffset];
if (ts->sym_identifier) return ts->str;
}
src/tccexsymtab.c view on Meta::CPAN
Sym * get_new_symtab_pointer (Sym * old, ram_hash * rh)
{
void ** Sym_ref;
Sym * to_return;
int btype;
/* Handle the null case up-front */
if (old == NULL) return NULL;
/* Check the global symbol stack. */
Sym_ref = ram_hash_get_ref(rh, old);
to_return = *Sym_ref;
if (NULL != to_return) return to_return;
/* Create new sym. Note that mallocz sets lots of things to null
* for me. :-) */
to_return = *Sym_ref = tcc_mallocz(sizeof(Sym));
/* See tcc.h around line 425 for descriptions of some of the fields.
* See also tccgen.c line 5987 to see what needs to happen for function
src/tccexsymtab.c view on Meta::CPAN
to_return->r = old->r;
/* Set the type. Judging by the constants in tcc.h and code that
* uses this field, I'm pretty sure that the low bits in the .t field
* tells tcc how to load the data into a register. The high bits seem to
* indicate storage details, such as VT_EXTERN. Since that is not
* something that can be extended at runtime, I should be able to copy
* the value as-is and add an extern flag for variables and functions. */
to_return->type.t = old->type.t;
/* After compilation, functions and global variables point to hard
* locations in memory. Consuming contexts should think of these as
* having external storage, which is reflected in the VT_EXTERN bit of
* the type.t field. */
btype = old->type.t & VT_BTYPE;
if (btype == VT_FUNC || to_return->r & (VT_SYM | VT_LVAL))
to_return->type.t |= VT_EXTERN;
/* Remove static indicator from functions */
if ((btype == VT_FUNC) && (old->type.t & VT_STATIC))
to_return->type.t &= ~VT_STATIC;
src/tccexsymtab.c view on Meta::CPAN
/* Copy the c field, the "associated number." According to tcc-doc.texi
* as well as the comments just above the definition of put_extern_sym2,
* the c field will (for some Syms) point to an external symbol in an
* associated section. But this is not true for all Syms. For structs,
* this is the size (in bytes), and for struct members it is the byte
* offset of the member, according to the end of struct_decl(). For
* variable length arrays, this is "the location on the stack that holds
* the runtime sizeof for the type." For functions, I believe this is
* one of FUNC_NEW, FUNC_OLD, or FUNC_ELLIPSIS. At any rate, everything
* seems to work if I simply set it to zero for functions and global
* variables and copy it otherwise, so I'm going with that. This probably
* needs to be more nuanced. */
if (btype == VT_FUNC || to_return->r & (VT_SYM | VT_LVAL))
to_return->c = 0;
else
to_return->c = old->c;
/* Copy the next symbol field. Labels and gotos are tracked in a
* separate stack, so for these Symbols we focus on next, not
* jnext. The next field (I seem to recall) is used in storing
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 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 *define_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *local_label_stack;
static int local_scope;
static int in_sizeof;
static int section_sym;
ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
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 SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop;
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_var; /* true if current function is variadic (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 const char *funcname;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
ST_DATA struct switch_t {
struct case_t {
src/tccgen.c view on Meta::CPAN
if (local_stack)
ps = &local_stack;
else {
/* #ifdef CONFIG_TCC_EXSYMTAB */
/* Global symbol stack. This is OK for the local symbol stack, but don't allow
* this for symbols that are in the extended symbol stack. There seem to be
* some issues associated with copying *all* TokenSyms, so this needs to be
* ironed out. For now, I'm removing the check. */
//
// if (v & SYM_EXTENDED) {
// tcc_error("Cannot use name '%s' as a global variable, it is already in the "
// "extended symbol table.", get_tok_str(v, 0));
// }
/* #endif */
ps = &global_stack;
}
/* #ifdef CONFIG_TCC_EXSYMTAB */
v &= ~SYM_EXTENDED;
/* #endif */
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) {
src/tccgen.c view on Meta::CPAN
s->prev_tok = *ps;
*ps = s;
s->scope = local_scope;
if (s->prev_tok && s->prev_tok->scope == s->scope)
tcc_error("redeclaration of '%s'",
get_tok_str(v & ~SYM_STRUCT, NULL));
}
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 */
/* #ifdef CONFIG_TCC_EXSYMTAB */
if ((v & ~SYM_EXTENDED) < SYM_FIRST_ANOM) {
ps = &table_ident[(v & ~SYM_EXTENDED) - TOK_IDENT]->sym_identifier;
/* #else
if (v < SYM_FIRST_ANOM) {
ps = &table_ident[v - TOK_IDENT]->sym_identifier;
#endif */
/* 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;
}
/* #ifdef CONFIG_TCC_EXSYMTAB */
if (v & SYM_EXTENDED) {
tcc_warning("pushing global identifier with name from extended symbol table '%s'",
get_tok_str(v, 0));
}
/* #endif */
return s;
}
/* pop symbols until top reaches 'b' */
ST_FUNC void sym_pop(Sym **ptop, Sym *b)
{
Sym *s, *ss, **ps;
src/tccgen.c view on Meta::CPAN
vtop->sym = sym;
}
/* 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)
{
vpushsym(type, 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' */
static Sym *external_sym(int v, CType *type, int r)
{
Sym *s;
src/tccgen.c view on Meta::CPAN
/* Merge some storage attributes. */
if (type->t & VT_WEAK)
weaken_symbol(s);
if (type->t & VT_VIS_MASK)
apply_visibility(s, type);
return s;
}
/* push a reference to global symbol v */
ST_FUNC void vpush_global_sym(CType *type, int v)
{
vpushsym(type, external_global_sym(v, type, 0));
}
ST_FUNC void vset(CType *type, int r, int v)
{
CValue cval;
cval.i = v;
vsetc(type, r, &cval);
}
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
/* generic itof for unsigned long long case */
static void gen_cvt_itof1(int t)
{
#ifdef TCC_TARGET_ARM64
gen_cvt_itof(t);
#else
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
}
#endif
src/tccgen.c view on Meta::CPAN
{
#ifdef TCC_TARGET_ARM64
gen_cvt_ftoi(t);
#else
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);
}
#endif
}
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
/* Use memmove, rather than memcpy, as dest and src may be same: */
vpush_global_sym(&func_old_type, TOK_memmove);
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, 0);
} else {
if (sizeof_caller) {
src/tccgen.c view on Meta::CPAN
skip(')');
vpushi(classify_x86_64_va_arg(&type));
}
break;
#endif
#endif
#ifdef TCC_TARGET_ARM64
case TOK___va_start: {
if (nocode_wanted)
tcc_error("statement in global scope");
next();
skip('(');
expr_eq();
skip(',');
expr_eq();
skip(')');
//xx check types
gen_va_start();
vpushi(0);
vtop->type.t = VT_VOID;
break;
}
case TOK___va_arg: {
CType type;
if (nocode_wanted)
tcc_error("statement in global scope");
next();
skip('(');
expr_eq();
skip(',');
parse_type(&type);
skip(')');
//xx check types
gen_va_arg(&type);
vtop->type = type;
break;
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;
}
vpushsym(&s->type, s);
src/tccgen.c view on Meta::CPAN
/* for simple function calls, we tolerate undeclared
external reference to int() function */
if (tcc_state->warn_implicit_function_declaration
#ifdef TCC_TARGET_PE
/* people must be warned about using undeclared WINAPI functions
(which usually start with uppercase letter) */
|| (name[0] >= 'A' && name[0] <= 'Z')
#endif
)
tcc_warning("implicit declaration of function '%s'", name);
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;
}
vla_sp_restore_root();
if (s->r & LABEL_FORWARD)
s->jnext = gjmp(s->jnext);
else
gjmp_addr(s->jnext);
next();
src/tccgen.c view on Meta::CPAN
b = is_label();
if (b) {
/* label case */
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;
vla_sp_restore();
/* we accept this, but it is a mistake */
block_after_label:
if (tok == '}') {
tcc_warning("deprecated use of label at end of compound statement");
} else {
if (is_expr)
vpop();
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);
#ifdef TCC_TARGET_ARM
vpushs(size);
vpushi(0);
#else
vpushi(0);
vpushs(size);
#endif
gfunc_call(3);
}
src/tccgen.c view on Meta::CPAN
else
cstr_len = tokc.str.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, tokc.str.data, nb);
} else {
for(i=0;i<nb;i++) {
if (tok == TOK_STR)
ch = ((unsigned char *)tokc.str.data)[i];
else
ch = ((nwchar_t *)tokc.str.data)[i];
init_putv(t1, sec, c + (array_length + i) * size1,
src/tccgen.c view on Meta::CPAN
else if (tok == '{')
parlevel1++;
else if (tok == '}') {
if (parlevel == 0 && parlevel1 == 0)
break;
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' 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, int scope)
{
int size, align, addr, data_offset;
int level;
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 */
if (size < 0 || (flexible_array && has_init)) {
if (!has_init)
tcc_error("unknown type size");
/* get all init string */
init_str = tok_str_alloc();
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 omitted 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
put_extern_sym(sym, sec, addr, size);
} else {
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 {
/* push global reference */
sym = get_sym_ref(type, sec, addr, size);
vpushsym(type, sym);
}
/* patch symbol weakness */
if (type->t & VT_WEAK)
weaken_symbol(sym);
apply_visibility(sym, type);
#ifdef CONFIG_TCC_BCHECK
/* handles bounds now because the symbol must be defined
before for the relocation */
if (tcc_state->do_bounds_check) {
addr_t *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(addr_t));
bounds_ptr[0] = 0; /* relocated */
bounds_ptr[1] = size;
}
#endif
}
if (has_init || (type->t & VT_VLA)) {
decl_initializer(type, sec, addr, 1, 0);
/* patch flexible array member size back to -1, */
/* for possible subsequent similar declarations */
src/tccgen.c view on Meta::CPAN
sym_push2(&local_stack, SYM_FIELD, 0, 0);
local_scope = 1; /* for function parameters */
gfunc_prolog(&sym->type);
local_scope = 0;
rsym = 0;
block(NULL, NULL, 0);
gsym(rsym);
gfunc_epilog();
cur_text_section->data_offset = ind;
label_pop(&global_label_stack, NULL);
/* reset local stack */
local_scope = 0;
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_UIDENT)
break;
btype.t = VT_INT;
}
if (((btype.t & VT_BTYPE) == VT_ENUM ||
(btype.t & VT_BTYPE) == VT_STRUCT) &&
tok == ';') {
if ((btype.t & VT_BTYPE) == VT_STRUCT) {
int v = btype.ref->v;
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
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));
}
type.ref->a.func_proto = 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)) {
int block_level;
struct InlineFunc *fn;
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);
sym->asm_label = ad.asm_label;
if (ad.alias_target) {
Section tsec;
Elf32_Sym *esym;
Sym *alias_target;
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;
ST_DATA int parse_flags;
ST_DATA struct BufferedFile *file;
ST_DATA int ch, tok;
ST_DATA CValue tokc;
ST_DATA const int *macro_ptr;
ST_DATA CString tokcstr; /* current parsed string, if any */
src/tccpp.c view on Meta::CPAN
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
{
Sym *s, **ps;
/* #ifdef CONFIG_TCC_EXSYMTAB */
v &= ~SYM_EXTENDED;
/* #endif */
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
DEF_ASMDIR(byte) /* must be first directive */
DEF_ASMDIR(word)
DEF_ASMDIR(align)
DEF_ASMDIR(p2align)
DEF_ASMDIR(skip)
DEF_ASMDIR(space)
DEF_ASMDIR(string)
DEF_ASMDIR(asciz)
DEF_ASMDIR(ascii)
DEF_ASMDIR(file)
DEF_ASMDIR(globl)
DEF_ASMDIR(global)
DEF_ASMDIR(weak)
DEF_ASMDIR(hidden)
DEF_ASMDIR(ident)
DEF_ASMDIR(size)
DEF_ASMDIR(type)
DEF_ASMDIR(text)
DEF_ASMDIR(data)
DEF_ASMDIR(bss)
DEF_ASMDIR(previous)
DEF_ASMDIR(fill)
src/tests/asmtest.S view on Meta::CPAN
call 0x1000
call L4
#ifdef __i386__
call *%eax
#else
call *%rax
#endif
call *0x1000
call func1
.global L5,L6
L5:
L6:
#ifdef __i386__
lcall $0x100, $0x1000
#else
lcall *0x100
lcall *(%rax)
#endif
src/tests/exsymtab/60-two-contexts-globals.c view on Meta::CPAN
/*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
// #define DIAG(...) diag(__VA_ARGS__)
#include "test_setup.h"
char first_code[] =
"unsigned int test_var;\n"
"unsigned int get_test_var () {\n"
src/tests/exsymtab/60-two-contexts-globals.c view on Meta::CPAN
int main(int argc, char **argv)
{
/* ---- Compile the first code string and setup the callback data ---- */
TCCState *s1 = tcc_new();
extended_symtab_p my_symtab;
setup_and_compile_s1(my_symtab, first_code);
SETUP_SECOND_CALLBACK_DATA();
/* ---- Make sure the getter and setter actually modify global state ---- */
unsigned int (*first_get)() = tcc_get_symbol(s1, "get_test_var");
void (*first_set)(unsigned int) = tcc_get_symbol(s1, "set_test_var");
first_set(42);
is_i(first_get(), 42, "first_set/first_get work");
first_set(439);
is_i(first_get(), 439, "first_set/first_get really work");
/* ---- Compile code string that depends on the function and global variable ---- */
TCCState *s2 = tcc_new();
setup_and_compile_second_state(s2, second_code);
relocate_second_state(s2);
/* ---- Check indirect getter and setter ---- */
unsigned int (*indirect_get)() = tcc_get_symbol(s2, "indirect_get");
void (*indirect_set)(unsigned int) = tcc_get_symbol(s2, "indirect_set");
is_i(indirect_get(), 439, "indirect_get seems to work");
indirect_set(276);
src/tests/exsymtab/61-two-contexts-const-globals.c view on Meta::CPAN
/*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
// #define DIAG(...) diag(__VA_ARGS__)
#include "test_setup.h"
char first_code[] =
"const unsigned int test_var = 42;\n"
"unsigned int get_test_var () {\n"
src/tests/exsymtab/61-two-contexts-const-globals.c view on Meta::CPAN
int main(int argc, char **argv)
{
/* ---- Compile the first code string and setup the callback data ---- */
TCCState *s1 = tcc_new();
extended_symtab_p my_symtab;
setup_and_compile_s1(my_symtab, first_code);
SETUP_SECOND_CALLBACK_DATA();
/* ---- Make sure the getter and setter actually modify global state ---- */
unsigned int (*first_get)() = tcc_get_symbol(s1, "get_test_var");
is_i(first_get(), 42, "first_set/first_get work");
/* ---- Compile code string that depends on the function and global variable ---- */
TCCState *s2 = tcc_new();
setup_and_compile_second_state(s2, second_code);
relocate_second_state(s2);
/* ---- Check indirect getter and setter ---- */
unsigned int (*indirect_get)() = tcc_get_symbol(s2, "indirect_get");
is_i(indirect_get(), 42, "indirect_get seems to work");
/* ---- Check direct getter and setter ---- */
src/tests/exsymtab/62-two-contexts-static-globals.c view on Meta::CPAN
/*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
// #define DIAG(...) diag(__VA_ARGS__)
#include "test_setup.h"
#include <string.h>
/* Create a custom error handler that merely tracks that the correct
* error was thrown. */
src/tests/exsymtab/62-two-contexts-static-globals.c view on Meta::CPAN
int main(int argc, char **argv)
{
/* ---- Compile the first code string and setup the callback data ---- */
TCCState *s1 = tcc_new();
extended_symtab_p my_symtab;
setup_and_compile_s1(my_symtab, first_code);
SETUP_SECOND_CALLBACK_DATA();
/* ---- Make sure the getter and setter actually modify global state ---- */
unsigned int (*first_get)() = tcc_get_symbol(s1, "get_test_var");
is_i(first_get(), 42, "first_set/first_get work");
/* ---- Check for errors during dependent compilation ---- */
TCCState *s2 = tcc_new();
if (!s2) return 1;
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
tcc_set_lib_path(s2, argv[1]+9);
else
tcc_set_lib_path(s2, "../..");
tcc_set_output_type(s2, TCC_OUTPUT_MEMORY);
tcc_set_error_func(s2, my_error_func, my_error_func);
callback_data.second_context = s2;
tcc_set_extended_symtab_callbacks(s2, &lookup_by_name, &sym_used, &prep_table, &callback_data);
tcc_compile_string(s2, second_code);
tcc_relocate(s2, TCC_RELOCATE_AUTO);
/* See if the error was thrown */
is_i(error_thrown, 1, "Static global variables do not bleed scope");
/* ---- clean up the memory ---- */
tcc_delete_extended_symbol_table(my_symtab);
tcc_delete(s1);
tcc_delete(s2);
pass("cleanup");
return done_testing();
}