Alien-TinyCCx
view release on metacpan
or search on metacpan
MANIFEST
view on Meta::CPAN
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 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
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | if (not $self ->notes( 'build_state' )) {
chdir 'src\\win32' ;
system ( 'build-tcc.bat' );
chdir '..\\..' ;
$ENV {ERRORLEVEL} and die 'build-tcc.bat failed' ;
File::Copy::Recursive::rcopy_glob( 'src\\win32\\*' => 'share\\' );
$self ->notes( 'build_state' , 'built' );
}
$self ->SUPER::ACTION_code;
}
sub my_clean {}
|
src/Changelog
view on Meta::CPAN
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | - 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
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | 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
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | 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
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 | 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
2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 | } else if ((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) {
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
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 | else if (r2 == VT_LDOUBLE)
func=TOK___fixxfdi;
else if (r2 == VT_DOUBLE)
else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE)
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
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 | 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),
o(0xf9400800 | r1 | r0 << 5); // ldr x(r1),[x(r0),
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
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 | 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,
o(0x1a9f07e0 | (uint32_t)cond << 12); // cset w0,(cond)
}
|
src/arm64-gen.c
view on Meta::CPAN
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 | 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
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 | 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
1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 | 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
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 | 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
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 | } 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
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | int _CRT_glob = 0;
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;
|
src/elf.h
view on Meta::CPAN
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | /* Legal values for vd_flags (version information flags). */
/* Versym symbol index values . */
/* Auxialiary version information. */
typedef struct
{
Elf32_Word vda_name; /* Version or dependency names */
Elf32_Word vda_next; /* Offset in bytes to next verdaux
entry */
|
src/elf.h
view on Meta::CPAN
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 | /* Pointer to the global system page used for system calls and other
nice things. */
/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
log2 of line size; mask those to get cache size. */
|
src/elf.h
view on Meta::CPAN
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 | /* Legal values for sh_flags field of Elf32_Shdr. */
/* Symbol tables. */
|
src/elf.h
view on Meta::CPAN
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | } 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. */
|
src/elf.h
view on Meta::CPAN
2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 | thread local data */
thread local data */
block */
static TLS block offset */
TLS block */
|
src/elf.h
view on Meta::CPAN
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 | offset. */
offset. */
block. */
|
src/i386-gen.c
view on Meta::CPAN
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | 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
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | 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;
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;
}
/* convert from one floating point type to another */
ST_FUNC void gen_cvt_ftof( int t)
|
src/i386-gen.c
view on Meta::CPAN
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | 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));
}
/* 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
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | /* 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) {
/* 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);
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
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | } 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
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | 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
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | } 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
1 2 3 4 5 6 7 8 9 10 11 | .text
.align 2
.global alloca
.type alloca, %function
alloca:
rsb sp, r0, sp
bic sp, sp,
mov r0, sp
mov pc, lr
.size alloca, .-alloca
.section .note.GNU-stack, "" , %progbits
|
src/lib/alloca86-bt.S
view on Meta::CPAN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ---------------------------------------------- */
/* alloca86-bt.S */
.globl __bound_alloca
__bound_alloca:
pop %edx
pop %eax
mov %eax , %ecx
add $3, %eax
and $-4, %eax
jz p6
|
src/lib/alloca86.S
view on Meta::CPAN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ---------------------------------------------- */
/* alloca86.S */
.globl alloca
alloca:
pop %edx
pop %eax
add $3, %eax
and $-4, %eax
jz p3
p1:
|
src/lib/alloca86_64-bt.S
view on Meta::CPAN
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ---------------------------------------------- */
/* alloca86_64.S */
.globl __bound_alloca
__bound_alloca:
pop %rdx
mov %rcx , %rax
add $15, %rax
and $-16, %rax
jz p3
|
src/lib/alloca86_64.S
view on Meta::CPAN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ---------------------------------------------- */
/* alloca86_64.S */
.globl alloca
alloca:
pop %rdx
mov %rcx , %rax
mov %rdi , %rax
add $15, %rax
and $-16, %rax
|
src/libtcc.c
view on Meta::CPAN
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | * 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
*/
/********************************************************/
/* global variables */
/* use GNU C extensions */ ST_DATA int gnu_ext = 1;
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
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | /********************************************************/
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" );
}
/********************************************************/
ST_FUNC char *normalize_slashes (char *path )
{
char *p ;
|
src/libtcc.c
view on Meta::CPAN
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | 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);
}
/*
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;
}
/*
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
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | 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
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | @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
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 | @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
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 | @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
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | @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
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | 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 {
@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
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | " -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"
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
src/tcc.h
view on Meta::CPAN
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 | 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: */
|
src/tcc.h
view on Meta::CPAN
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | return (c >= 'a' && c <= 'z' ) ? c - 'a' + 'A' : c;
}
/* ------------ tccgen.c ------------ */
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 ;
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);
ST_FUNC int get_reg_ex( int rc, int rc2);
ST_FUNC void lexpand_nr(void);
ST_FUNC void vpushv(SValue *v );
ST_FUNC void save_reg( int r);
ST_FUNC void save_reg_upstack( int r, int n);
|
src/tcc.h
view on Meta::CPAN
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | 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 */
ST_DATA Section *last_text_section ; /* to handle .previous asm directive */
/* 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 );
/* 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 );
|
src/tcc.h
view on Meta::CPAN
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | /* ------------ tcccoff.c ------------ */
ST_FUNC int tcc_output_coff(TCCState *s1 , FILE *f );
ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
/* ------------ tccasm.c ------------ */
ST_FUNC void asm_instr(void);
ST_FUNC void asm_global_instr(void);
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
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 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
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | 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
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 | 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
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 | /* 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( "';'" );
printf ( "asm_global: \"%s\"\n" , (char *)astr.data);
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
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | // 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
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 | 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
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Define this to get some debug output during relocation processing. */
/********************************************************/
/* 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 */
ST_DATA Section *last_text_section ; /* to handle .previous asm directive */
/* bound check related sections */
ST_DATA Section *bounds_section ; /* contains global data bound description */
ST_DATA Section *lbounds_section ; /* contains local data bound description */
/* 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
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | 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
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | {
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
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | } 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
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | put_stabs(NULL, type, other, desc, 0);
}
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
using variable <elem> */
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
2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 | 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
2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 | 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
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | 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
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | 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
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | 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
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | /* 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
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | * 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
*/
/********************************************************/
/* 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
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 | if (local_stack)
ps = &local_stack ;
else {
/*
/* 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));
// }
/*
ps = &global_stack ;
}
/*
v &= ~SYM_EXTENDED;
/*
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
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | 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 */
/*
if ((v & ~SYM_EXTENDED) < SYM_FIRST_ANOM) {
ps = &table_ident [(v & ~SYM_EXTENDED) - TOK_IDENT]->sym_identifier;
/*
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;
}
/*
if (v & SYM_EXTENDED) {
tcc_warning( "pushing global identifier with name from extended symbol table '%s'" ,
get_tok_str(v, 0));
}
/*
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
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | 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
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 | /* 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
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | goto gen_mod_func;
case TOK_UMOD:
func = TOK___umoddi3;
gen_mod_func:
reg_iret = TREG_R2;
reg_lret = TREG_R3;
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
2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 | /* generic itof for unsigned long long case */
static void gen_cvt_itof1( int t)
{
gen_cvt_itof(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);
else if (t == VT_LDOUBLE)
vpush_global_sym( &func_old_type , TOK___floatundixf);
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);
}
}
|
src/tccgen.c
view on Meta::CPAN
2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 | {
gen_cvt_ftoi(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);
else if (st == VT_LDOUBLE)
vpush_global_sym( &func_old_type , TOK___fixunsxfdi);
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
2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 | size = type_size( &vtop ->type, &align );
/* destination */
vswap();
vtop->type.t = VT_PTR;
gaddrof();
/* address of memcpy() */
if (!(align & 7))
vpush_global_sym( &func_old_type , TOK_memcpy8);
else if (!(align & 3))
vpush_global_sym( &func_old_type , TOK_memcpy4);
else
/* 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
4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 | 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
4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 | skip( ')' );
vpushi(classify_x86_64_va_arg( &type ));
}
break;
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
4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 | 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
4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 | /* for simple function calls, we tolerate undeclared
external reference to int () function */
if (tcc_state->warn_implicit_function_declaration
/* people must be warned about using undeclared WINAPI functions
(which usually start with uppercase letter) */
|| (name[0] >= 'A' && name[0] <= 'Z' )
)
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
5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 | /* 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
5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 | 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
5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 | dst += elem_size;
memcpy(dst, src, elem_size);
}
}
}
/* 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
5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 | 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);
vpushs(size);
vpushi(0);
vpushi(0);
vpushs(size);
gfunc_call(3);
}
|
src/tccgen.c
view on Meta::CPAN
6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 | 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
6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 | 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
6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 | 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
6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 | /* 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
6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 | 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;
/* add padding if bound check */
if (tcc_state->do_bounds_check)
data_offset++;
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
6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 | 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);
/* 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;
}
}
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
6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 | 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
6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 | 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
6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 | 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
6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 | /* 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
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | * 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
*/
/********************************************************/
/* 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
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 | ST_FUNC Sym *label_push (Sym * *ptop , int v, int flags)
{
Sym *s , * *ps ;
/*
v &= ~SYM_EXTENDED;
/*
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
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | 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
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | call 0x1000
call L4
call * %eax
call * %rax
call *0x1000
call func1
.global L5,L6
L5:
L6:
lcall $0x100, $0x1000
lcall *0x100
lcall *( %rax )
|
src/tests/exsymtab/60-two-contexts-globals.c
view on Meta::CPAN
1 2 3 4 5 6 7 8 9 10 11 12 | /*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
//
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
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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
1 2 3 4 5 6 7 8 9 10 11 12 | /*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
//
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
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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
1 2 3 4 5 6 7 8 9 10 11 12 | /*
* Declare a global variable in one context and access it in another context.
*/
/* uncomment to enable diagnostic output */
//
/* 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
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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();
}
|