Alien-TinyCCx

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

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;

src/elf.h  view on Meta::CPAN

#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 */

src/elf.h  view on Meta::CPAN

#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

src/elf.h  view on Meta::CPAN

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

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

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


/* Symbol tables.  */

src/elf.h  view on Meta::CPAN

} Elf32_RegInfo;

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

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

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

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

src/elf.h  view on Meta::CPAN

#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

src/elf.h  view on Meta::CPAN

#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:

src/tcc.c  view on Meta::CPAN

           "  -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

src/tcc.h  view on Meta::CPAN

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 */

src/tcc.h  view on Meta::CPAN

    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);

src/tcc.h  view on Meta::CPAN

    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);

src/tcc.h  view on Meta::CPAN


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

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

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

src/tccasm.c  view on Meta::CPAN

        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 = &section_header[i];
	tcc_sect = s1->sections[i];

src/tcccoff.c  view on Meta::CPAN


	tcc_free(Coff_str_table);
    }

    return 0;
}



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

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

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

    p = (Elf32_Sym *) symtab_section->data;

src/tccelf.c  view on Meta::CPAN

 * 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();
}



( run in 0.631 second using v1.01-cache-2.11-cpan-9b1e4054eb1 )