aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard>2002-05-13 23:00:17 +0000
committerbellard <bellard>2002-05-13 23:00:17 +0000
commit8f64c13c40b8967b6579e8fb865ce828e53aab84 (patch)
tree60409ca9cd4f574a49165e0fe24c258af1b3e1e7
parent1e14c90c7ab78e9669733c82c1cee280efab1a3b (diff)
downloadtinycc-8f64c13c40b8967b6579e8fb865ce828e53aab84.tar.gz
tinycc-8f64c13c40b8967b6579e8fb865ce828e53aab84.tar.bz2
added libtcc - fixed spill reg bugs
-rw-r--r--tcc.c247
1 files changed, 173 insertions, 74 deletions
diff --git a/tcc.c b/tcc.c
index 7ed803f..67e8fc0 100644
--- a/tcc.c
+++ b/tcc.c
@@ -38,6 +38,8 @@
#include <dlfcn.h>
#endif
+#include "libtcc.h"
+
//#define DEBUG
/* preprocessor debug */
//#define PP_DEBUG
@@ -245,6 +247,10 @@ int gnu_ext = 1;
/* use Tiny C extensions */
int tcc_ext = 1;
+struct TCCState {
+ int dummy;
+};
+
/* The current value can be: */
#define VT_VALMASK 0x00ff
#define VT_CONST 0x00f0 /* constant in vc
@@ -491,7 +497,7 @@ int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
int gv(int rc);
void gv2(int rc1, int rc2);
void move_reg(int r, int s);
-void save_regs(void);
+void save_regs(int n);
void save_reg(int r);
void vpop(void);
void vswap(void);
@@ -2450,7 +2456,7 @@ void save_reg(int r)
}
#endif
/* special long long case */
- if ((p->t & VT_BTYPE) == VT_LLONG) {
+ if ((t & VT_BTYPE) == VT_LLONG) {
sv.c.ul += 4;
store(p->r2, &sv);
}
@@ -2501,12 +2507,13 @@ int get_reg(int rc)
return r;
}
-void save_regs(void)
+/* save registers up to (vtop - n) stack entry */
+void save_regs(int n)
{
int r;
- SValue *p;
-
- for(p=vstack;p<=vtop;p++) {
+ SValue *p, *p1;
+ p1 = vtop - n;
+ for(p = vstack;p <= p1; p++) {
r = p->r & VT_VALMASK;
if (r < VT_CONST) {
save_reg(r);
@@ -3810,7 +3817,7 @@ void vstore(void)
gaddrof();
gfunc_param(&gf);
- save_regs();
+ save_regs(0);
vpushi((int)&memcpy);
gfunc_call(&gf);
/* leave source on stack */
@@ -4660,7 +4667,7 @@ void unary(void)
}
/* get return type */
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
- save_regs(); /* save used temporary registers */
+ save_regs(0); /* save used temporary registers */
gfunc_start(&gf, s->r);
next();
sa = s->next; /* first parameter */
@@ -4879,6 +4886,8 @@ void expr_eq(void)
eor();
if (tok == '?') {
next();
+ save_regs(1); /* we need to save all registers here except
+ at the top because it is a branch point */
t = gtst(1, 0);
gexpr();
/* XXX: long long handling ? */
@@ -5832,17 +5841,13 @@ void resolve_global_syms(void)
}
}
-/* compile a C file. Return non zero if errors. */
-int tcc_compile_file(const char *filename1)
+/* compile the C file opened in 'file'. Return non zero if errors. */
+int tcc_compile(TCCState *s)
{
Sym *define_start;
char buf[512];
funcname = "";
-
- file = tcc_open(filename1);
- if (!file)
- error("file '%s' not found", filename1);
include_stack_ptr = include_stack;
ifdef_stack_ptr = ifdef_stack;
@@ -5868,7 +5873,6 @@ int tcc_compile_file(const char *filename1)
decl(VT_CONST);
if (tok != -1)
expect("declaration");
- tcc_close(file);
/* end of translation unit info */
if (do_debug) {
@@ -5886,23 +5890,48 @@ int tcc_compile_file(const char *filename1)
return 0;
}
+int tcc_compile_file(TCCState *s, const char *filename1)
+{
+ int ret;
+ file = tcc_open(filename1);
+ if (!file)
+ error("file '%s' not found", filename1);
+ ret = tcc_compile(s);
+ tcc_close(file);
+ return ret;
+}
+
+int tcc_compile_string(TCCState *s, const char *str)
+{
+ BufferedFile bf1, *bf = &bf1;
+ int ret;
+
+ /* init file structure */
+ bf->fd = -1;
+ bf->buf_ptr = (char *)str;
+ bf->buf_end = (char *)str + strlen(bf->buffer);
+ pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
+ bf->line_num = 1;
+ file = bf;
+
+ ret = tcc_compile(s);
+
+ /* currently, no need to close */
+ return ret;
+}
+
/* define a symbol. A value can also be provided with the '=' operator */
-/* XXX: currently only handles integers and string defines. should use
- tcc parser, but would need a custom 'FILE *' */
-void define_symbol(const char *sym)
+void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
{
- char *p;
BufferedFile bf1, *bf = &bf1;
pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
- p = strchr(bf->buffer, '=');
- if (!p) {
- /* default value */
- pstrcat(bf->buffer, IO_BUF_SIZE, " 1");
- } else {
- *p = ' ';
- }
-
+ pstrcat(bf->buffer, IO_BUF_SIZE, " ");
+ /* default value */
+ if (!value)
+ value = "1";
+ pstrcat(bf->buffer, IO_BUF_SIZE, value);
+
/* init file structure */
bf->fd = -1;
bf->buf_ptr = bf->buffer;
@@ -5921,7 +5950,7 @@ void define_symbol(const char *sym)
file = NULL;
}
-void undef_symbol(const char *sym)
+void tcc_undefine_symbol(TCCState *s1, const char *sym)
{
TokenSym *ts;
Sym *s;
@@ -5934,15 +5963,39 @@ void undef_symbol(const char *sym)
/* open a dynamic library so that its symbol are available for
compiled programs */
-void open_dll(char *libname)
+/* XXX: open the lib only to actually run the program */
+int tcc_add_dll(TCCState *s, const char *library_name)
{
- char buf[1024];
void *h;
- snprintf(buf, sizeof(buf), "lib%s.so", libname);
- h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
+ h = dlopen(library_name, RTLD_GLOBAL | RTLD_LAZY);
if (!h)
error((char *)dlerror());
+ return 0;
+}
+
+/* If the symbol already exists, then it is redefined */
+int tcc_add_symbol(TCCState *s, const char *name, void *value)
+{
+ TokenSym *ts;
+ Sym *ext_sym;
+ int v;
+
+ ts = tok_alloc(name, 0);
+ v = ts->tok;
+ ext_sym = sym_find1(&extern_stack, v);
+ if (ext_sym) {
+ if (ext_sym->r & VT_FORWARD) {
+ greloc_patch(ext_sym, (long)value);
+ } else {
+ /* redefine symbol */
+ ext_sym->c = (long)value;
+ }
+ } else {
+ ext_sym = sym_push1(&extern_stack, v, VT_INT, (long)value);
+ ext_sym->r = VT_CONST;
+ }
+ return 0;
}
static void *resolve_sym(const char *sym)
@@ -6059,7 +6112,7 @@ static void put_stabd(int type, int other, int desc)
/* XXX: generate startup code */
/* XXX: better program header generation */
/* XXX: handle realloc'ed sections (instead of mmaping them) */
-void build_exe(char *filename)
+int tcc_output_file(TCCState *s, const char *filename, int file_type)
{
Elf32_Ehdr ehdr;
FILE *f;
@@ -6188,6 +6241,7 @@ void build_exe(char *filename)
}
fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
fclose(f);
+ return 0;
}
/* print the position in the source file of PC value 'pc' by reading
@@ -6337,11 +6391,13 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
#endif
/* launch the compiled program with the given arguments */
-int launch_exe(int argc, char **argv)
+int tcc_run(TCCState *s1, int argc, char **argv)
{
Sym *s;
int (*t)();
+ resolve_extern_syms();
+
s = sym_find1(&extern_stack, TOK_MAIN);
if (!s || (s->r & VT_FORWARD))
error("main() not defined");
@@ -6382,34 +6438,20 @@ int launch_exe(int argc, char **argv)
return (*t)(argc, argv);
}
-
-void help(void)
+TCCState *tcc_new(void)
{
- printf("tcc version 0.9.6 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
- "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
- " [-i infile] infile [infile_args...]\n"
- "\n"
- "-Idir : add include path 'dir'\n"
- "-Dsym[=val] : define 'sym' with value 'val'\n"
- "-Usym : undefine 'sym'\n"
- "-llib : link with dynamic library 'lib'\n"
- "-g : generate runtime debug info\n"
-#ifdef CONFIG_TCC_BCHECK
- "-b : compile with built-in memory and bounds checker (implies -g)\n"
-#endif
- "-i infile : compile infile\n"
- );
-}
+ char *p, *r;
+ TCCState *s;
-int main(int argc, char **argv)
-{
- char *p, *r, *outfile;
- int optind;
+ s = malloc(sizeof(TCCState));
+ if (!s)
+ return NULL;
- include_paths[0] = "/usr/include";
- include_paths[1] = "/usr/lib/tcc";
- include_paths[2] = "/usr/local/lib/tcc";
- nb_include_paths = 3;
+ /* default include paths */
+ nb_include_paths = 0;
+ tcc_add_include_path(s, "/usr/include");
+ tcc_add_include_path(s, "/usr/lib/tcc");
+ tcc_add_include_path(s, "/usr/local/lib/tcc");
/* add all tokens */
tok_ident = TOK_IDENT;
@@ -6422,12 +6464,12 @@ int main(int argc, char **argv)
}
/* standard defines */
- define_symbol("__STDC__");
+ tcc_define_symbol(s, "__STDC__", NULL);
#ifdef __i386__
- define_symbol("__i386__");
+ tcc_define_symbol(s, "__i386__", NULL);
#endif
/* tiny C specific defines */
- define_symbol("__TINYC__");
+ tcc_define_symbol(s, "__TINYC__", NULL);
/* create standard sections */
text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
@@ -6435,6 +6477,55 @@ int main(int argc, char **argv)
/* XXX: should change type to SHT_NOBITS */
bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+ return s;
+}
+
+void tcc_delete(TCCState *s)
+{
+ free(s);
+}
+
+int tcc_add_include_path(TCCState *s, const char *pathname)
+{
+ char *pathname1;
+
+ if (nb_include_paths >= INCLUDE_PATHS_MAX)
+ return -1;
+ pathname1 = strdup(pathname);
+ if (!pathname1)
+ return -1;
+ include_paths[nb_include_paths++] = pathname1;
+ return 0;
+}
+
+#if !defined(LIBTCC)
+
+void help(void)
+{
+ printf("tcc version 0.9.7 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
+ "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
+ " [-i infile] infile [infile_args...]\n"
+ "\n"
+ "-Idir : add include path 'dir'\n"
+ "-Dsym[=val] : define 'sym' with value 'val'\n"
+ "-Usym : undefine 'sym'\n"
+ "-llib : link with dynamic library 'lib'\n"
+ "-g : generate runtime debug info\n"
+#ifdef CONFIG_TCC_BCHECK
+ "-b : compile with built-in memory and bounds checker (implies -g)\n"
+#endif
+ "-i infile : compile infile\n"
+ );
+}
+
+int main(int argc, char **argv)
+{
+ char *r, *outfile;
+ int optind;
+ TCCState *s;
+
+ s = tcc_new();
+
optind = 1;
outfile = NULL;
while (1) {
@@ -6448,19 +6539,27 @@ int main(int argc, char **argv)
break;
optind++;
if (r[1] == 'I') {
- if (nb_include_paths >= INCLUDE_PATHS_MAX)
+ if (tcc_add_include_path(s, r + 2) < 0)
error("too many include paths");
- include_paths[nb_include_paths++] = r + 2;
} else if (r[1] == 'D') {
- define_symbol(r + 2);
+ char *sym, *value;
+ sym = r + 2;
+ value = strchr(sym, '=');
+ if (value) {
+ *value = '\0';
+ value++;
+ }
+ tcc_define_symbol(s, sym, value);
} else if (r[1] == 'U') {
- undef_symbol(r + 2);
+ tcc_undefine_symbol(s, r + 2);
} else if (r[1] == 'l') {
- open_dll(r + 2);
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "lib%s.so", r + 2);
+ tcc_add_dll(s, buf);
} else if (r[1] == 'i') {
if (optind >= argc)
goto show_help;
- tcc_compile_file(argv[optind++]);
+ tcc_compile_file(s, argv[optind++]);
} else if (!strcmp(r + 1, "bench")) {
do_bench = 1;
#ifdef CONFIG_TCC_BCHECK
@@ -6468,7 +6567,7 @@ int main(int argc, char **argv)
if (!do_bounds_check) {
do_bounds_check = 1;
/* define symbol */
- define_symbol("__BOUNDS_CHECKING_ON");
+ tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
/* create bounds sections */
bounds_section = new_section(".bounds",
SHT_PROGBITS, SHF_ALLOC);
@@ -6512,19 +6611,19 @@ int main(int argc, char **argv)
}
}
- tcc_compile_file(argv[optind]);
+ tcc_compile_file(s, argv[optind]);
if (do_bench) {
printf("total: %d idents, %d lines, %d bytes\n",
tok_ident - TOK_IDENT, total_lines, total_bytes);
}
- resolve_extern_syms();
-
if (outfile) {
- build_exe(outfile);
+ tcc_output_file(s, outfile, TCC_FILE_EXE);
return 0;
} else {
- return launch_exe(argc - optind, argv + optind);
+ return tcc_run(s, argc - optind, argv + optind);
}
}
+
+#endif