Ejemplo n.º 1
0
void
run_tccode(void)
{
    char * ccode;
    size_t ccodelen;

    FILE * ofd;
    TCCState *s;
    int rv;
    void * memp;
#ifdef __STRICT_ANSI__
    void * iso_workaround;
#endif

    libtcc_specials = 1;

    ofd = open_memstream(&ccode, &ccodelen);
    if (ofd == NULL) { perror("open_memstream"); exit(7); }
    print_ccode(ofd);
    putc('\0', ofd);
    fclose(ofd);

    memp = map_hugeram();

    s = tcc_new();
    if (s == NULL) { perror("tcc_new()"); exit(7); }
    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);

    tcc_compile_string(s, ccode);

    tcc_add_symbol(s, "mem", memp);

    /* If our code was read from stdin it'll be done in standard mode,
     * the stdio stream is now modal (always a bad idea) so it's been switched
     * to standard mode, stupidly, it's now impossible to switch it back.
     *
     * So have the loaded C code use our getch and putch functions.
     *
     * The ugly casting is forced by the C99 standard as a (void*) is not a
     * valid cast for a function pointer.
     */

#ifdef __STRICT_ANSI__
    *(void_func*) &iso_workaround  = (void_func) &getch;
    tcc_add_symbol(s, "getch", iso_workaround);
    *(void_func*) &iso_workaround  = (void_func) &putch;
    tcc_add_symbol(s, "putch", iso_workaround);
#else
    tcc_add_symbol(s, "getch", &getch);
    tcc_add_symbol(s, "putch", &putch);

#if defined(__TCCLIB_VERSION) && __TCCLIB_VERSION == 0x000925
#define TCCDONE
    {
	int (*func)(void);
	int imagesize;
	void * image = 0;

	if (verbose)
	    fprintf(stderr, "Running C Code using libtcc 9.25.\n");

	imagesize = tcc_relocate(s, 0);
	if (imagesize <= 0) {
	    fprintf(stderr, "tcc_relocate failed to return code size.\n");
	    exit(1);
	}
	image = malloc(imagesize);
	rv = tcc_relocate(s, image);
	if (rv) {
	    fprintf(stderr, "tcc_relocate failed error=%d\n", rv);
	    exit(1);
	}

	/*
	 * The ugly casting is forced by the C99 standard as a (void*) is not a
	 * valid cast for a function pointer.
	 *
	*(void **) (&func) = tcc_get_symbol(s, "main");
	 */
	func = tcc_get_symbol(s, "main");

	if (!func) {
	    fprintf(stderr, "Could not find compiled code entry point\n");
	    exit(1);
	}
	tcc_delete(s);
	free(ccode);

	start_runclock();
	func();
	finish_runclock(&run_time, &io_time);
	free(image);
    }
#endif

#if defined(__TCCLIB_VERSION) && __TCCLIB_VERSION == 0x000926
#define TCCDONE
    {
	int (*func)(void);

	if (verbose)
	    fprintf(stderr, "Running C Code using libtcc 9.26.\n");

	rv = tcc_relocate(s);
	if (rv) {
	    perror("tcc_relocate()");
	    fprintf(stderr, "tcc_relocate failed return value=%d\n", rv);
	    exit(1);
	}

	/*
	 * The ugly casting is forced by the C99 standard as a (void*) is not a
	 * valid cast for a function pointer.
	*(void **) (&func) = tcc_get_symbol(s, "main");
	 */
	func = tcc_get_symbol(s, "main");

	if (!func) {
	    fprintf(stderr, "Could not find compiled code entry point\n");
	    exit(1);
	}
	start_runclock();
	func();
	finish_runclock(&run_time, &io_time);

	tcc_delete(s);
	free(ccode);
    }
#endif
#endif

#if !defined(TCCDONE)
    {
    static char arg0_tcclib[] = "tcclib";
    static char * args[] = {arg0_tcclib, 0};
    /*
	Hmm, I want to do the above without named initialisers ... so it looks
	like this ... but without the const problem.

    static char * args[] = {"tcclib", 0};
     */

	if (verbose)
	    fprintf(stderr, "Running C Code using libtcc tcc_run() to compile & run.\n");

	rv = tcc_run(s, 1, args);
	if (verbose && rv)
	    fprintf(stderr, "tcc_run returned %d\n", rv);
	tcc_delete(s);
	free(ccode);
    }
#endif
}
Ejemplo n.º 2
0
static void
compile_and_run(void)
{
    char cmdbuf[256];
    int ret;
    const char * cc = CC;
    const char * copt = "";
    const char * pic_cmd = "";
    if (opt_level >= 3)
	copt = " -O3";

    if (cc_cmd) cc = cc_cmd;

#ifdef DEFAULT_PIC
    if (pic_opt<0) pic_opt = DEFAULT_PIC;
#endif
    switch(pic_opt) {
    case 0: pic_cmd = ""; break;
    case 1: pic_cmd = " -fpic"; break;
    case 2: pic_cmd = " -fPIC"; break;
    }

    if (in_one) {
	if (verbose)
	    fprintf(stderr,
		"Running C Code using \"%s%s%s -shared\" and dlopen().\n",
		cc,pic_cmd,copt);

	sprintf(cmdbuf, "%s%s%s -shared -o %s %s",
		    cc, pic_cmd, copt, dl_name, ccode_name);
	ret = system(cmdbuf);
    } else {
	if (verbose)
	    fprintf(stderr,
		"Running C Code using \"%s%s%s\", link -shared and dlopen().\n",
		cc,pic_cmd,copt);

	/* Like this so that ccache has a good path and distinct compile. */
	sprintf(cmdbuf, "cd %s; %s%s%s -c -o %s %s",
		tmpdir, cc, pic_cmd, copt, BFBASE".o", BFBASE".c");
	ret = system(cmdbuf);

	if (ret != -1) {
	    sprintf(cmdbuf, "cd %s; %s%s -shared -o %s %s",
		    tmpdir, cc, pic_cmd, dl_name, BFBASE".o");
	    ret = system(cmdbuf);
	}
    }

    if (ret == -1) {
	perror("Calling C compiler failed");
	exit(1);
    }
    if (WIFEXITED(ret)) {
	if (WEXITSTATUS(ret)) {
	    fprintf(stderr, "Compile failed.\n");
	    exit(WEXITSTATUS(ret));
	}
    } else {
	if (WIFSIGNALED(ret)) {
	    if( WTERMSIG(ret) != SIGINT && WTERMSIG(ret) != SIGQUIT)
		fprintf(stderr, "Killed by SIGNAL %d.\n", WTERMSIG(ret));
	    exit(1);
	}
	perror("Abnormal exit");
	exit(1);
    }

    loaddll(dl_name);

    if (!leave_temps) {
	unlink(ccode_name);
	unlink(dl_name);
	unlink(obj_name);
	rmdir(tmpdir);
    }

#ifndef __STRICT_ANSI__
    if (verbose>1)
	fprintf(stderr, "Calling function loaded at address %p\n", (void*) runfunc);
#endif

    start_runclock();
    (*runfunc)();
    finish_runclock(&run_time, &io_time);

    dlclose(handle);
}
Ejemplo n.º 3
0
void
run_gnulightning(void)
{
    struct bfi * n = bfprog;
    int maxstack = 0, stackptr = 0;
    char *strbuf = 0;
    size_t maxstrlen = 0;
#ifdef GNULIGHTv1
    jit_insn** loopstack = 0;
    jit_insn *codeBuffer;
    void * startptr;
    int argp;
#endif
#ifdef GNULIGHTv2
    jit_node_t    *start, *end;	    /* For size of code */
    jit_node_t** loopstack = 0;
    jit_node_t    *argp;
#endif

    if (cell_size == 8) tape_step = 1; else
    tape_step = sizeof(int);

#ifdef GNULIGHTv1
    /* TODO: Use mmap for allocating memory, the x86 execute protection
     * bit is on the segment so Linux has to say thay everything below
     * a specific address is executable. If you ask mmap for executable
     * memory it can put it below the current value. The mprotect()
     * function can't do this.
     */
    if (total_nodes < 4096)
	codeBuffer = malloc(65536);
    else
	codeBuffer = malloc(16 * total_nodes);
    save_ptr_for_free(codeBuffer);

    codeptr = (codeptr_t) jit_set_ip(codeBuffer).vptr;
    startptr = jit_get_ip().ptr;
    /* Function call prolog */
    jit_prolog(1);
    /* Get the data area pointer */
    argp = jit_arg_p();
    jit_getarg_p(REG_P, argp);
#endif

#ifdef GNULIGHTv2
    init_jit(NULL); // argv[0]);
    _jit = jit_new_state();
    start = jit_note(__FILE__, __LINE__);
    jit_prolog();

    /* Get the data area pointer */
    argp = jit_arg();
    jit_getarg(REG_P, argp);
#endif

    while(n)
    {
	switch(n->type)
	{
	case T_MOV:
	    if (acc_loaded)
		acc_offset -= n->count;

	    jit_addi(REG_P, REG_P, n->count * tape_step);
	    break;

	case T_ADD:
	    load_acc_offset(n->offset);
	    set_acc_offset(n->offset);

	    jit_addi(REG_ACC, REG_ACC, n->count);
	    break;

	case T_SET:
	    set_acc_offset(n->offset);
	    if (acc_const && acc_const_val == n->count) {
		;
	    } else if (acc_const && acc_const_val+1 == n->count) {
		jit_addi(REG_ACC, REG_ACC, 1);
            } else if (acc_const && acc_const_val-1 == n->count) {
		jit_addi(REG_ACC, REG_ACC, -1);
            } else {
		jit_movi(REG_ACC, n->count);
            }
            acc_const = 1;
            acc_const_val = n->count;
            break;

	case T_CALC:
	    if (n->offset == n->offset2 && n->count2 == 1) {
		load_acc_offset(n->offset);
		set_acc_offset(n->offset);
		if (n->count)
		    jit_addi(REG_ACC, REG_ACC, n->count);
	    } else if (n->count2 != 0) {
		load_acc_offset(n->offset2);
		set_acc_offset(n->offset);
		if (n->count2 == -1)
		    jit_negr(REG_ACC, REG_ACC);
		else if (n->count2 != 1)
		    jit_muli(REG_ACC, REG_ACC, n->count2);
		if (n->count)
		    jit_addi(REG_ACC, REG_ACC, n->count);
	    } else {
		clean_acc();
		set_acc_offset(n->offset);

		jit_movi(REG_ACC, n->count);
		if (n->count2 != 0) {
		    if (tape_step > 1)
			jit_ldxi_i(REG_A1, REG_P, n->offset2 * tape_step);
		    else
			jit_ldxi_uc(REG_A1, REG_P, n->offset2);
		    if (n->count2 == -1)
			jit_negr(REG_A1, REG_A1);
		    else if (n->count2 != 1)
			jit_muli(REG_A1, REG_A1, n->count2);
		    jit_addr(REG_ACC, REG_ACC, REG_A1);
		}
	    }

	    if (n->count3 != 0) {
		if (tape_step > 1)
		    jit_ldxi_i(REG_A1, REG_P, n->offset3 * tape_step);
		else
		    jit_ldxi_uc(REG_A1, REG_P, n->offset3);
		if (n->count3 == -1)
		    jit_negr(REG_A1, REG_A1);
		else if (n->count3 != 1)
		    jit_muli(REG_A1, REG_A1, n->count3);
		jit_addr(REG_ACC, REG_ACC, REG_A1);
	    }
	    break;

	case T_IF: case T_MULT: case T_CMULT:
	case T_WHL:
	    load_acc_offset(n->offset);
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    if (stackptr >= maxstack) {
		loopstack = realloc(loopstack,
			    ((maxstack+=32)+2)*sizeof(*loopstack));
		if (loopstack == 0) {
		    perror("loop stack realloc failure");
		    exit(1);
		}
	    }

	    if (cell_mask > 0 && acc_hi_dirty) {
		if (cell_mask == 0xFF)
		    jit_extr_uc(REG_ACC,REG_ACC);
		else
		    jit_andi(REG_ACC, REG_ACC, cell_mask);
	    }

#ifdef GNULIGHTv1
	    loopstack[stackptr] = jit_beqi_i(jit_forward(), REG_ACC, 0);
	    loopstack[stackptr+1] = jit_get_label();
#endif
#ifdef GNULIGHTv2
	    loopstack[stackptr] = jit_beqi(REG_ACC, 0);
	    loopstack[stackptr+1] = jit_label();
#endif
	    stackptr += 2;
	    break;

	case T_END:
	    load_acc_offset(n->offset);
	    clean_acc();

	    stackptr -= 2;
	    if (stackptr < 0) {
		fprintf(stderr, "Code gen failure: Stack pointer negative.\n");
		exit(1);
	    }

	    if (cell_mask > 0 && acc_hi_dirty) {
		if (cell_mask == 0xFF)
		    jit_extr_uc(REG_ACC,REG_ACC);
		else
		    jit_andi(REG_ACC, REG_ACC, cell_mask);
	    }

#ifdef GNULIGHTv1
	    jit_bnei_i(loopstack[stackptr+1], REG_ACC, 0);
	    jit_patch(loopstack[stackptr]);
#endif
#ifdef GNULIGHTv2
	    {
		jit_node_t *ref;
		ref = jit_bnei(REG_ACC, 0);
		jit_patch_at(ref, loopstack[stackptr+1]);
		jit_patch(loopstack[stackptr]);
	    }
#endif
	    break;

	case T_ENDIF:
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    stackptr -= 2;
	    if (stackptr < 0) {
		fprintf(stderr, "Code gen failure: Stack pointer negative.\n");
		exit(1);
	    }
	    jit_patch(loopstack[stackptr]);
	    break;

	case T_PRT:
	    clean_acc();
	    load_acc_offset(n->offset);
	    acc_loaded = 0;

#ifdef GNULIGHTv1
	    jit_prepare_i(1);
	    jit_pusharg_i(REG_ACC);
	    jit_finish(putch);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_pushargr(REG_ACC);
	    jit_finishi(putch);
#endif
	    break;

	case T_CHR:
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    if (n->count <= 0 || (n->count >= 127 && iostyle == 1) ||
		    !n->next || n->next->type != T_CHR) {
		jit_movi(REG_ACC, n->count);
#ifdef GNULIGHTv1
		jit_prepare_i(1);
		jit_pusharg_i(REG_ACC);
		jit_finish(putch);
#endif
#ifdef GNULIGHTv2
		jit_prepare();
		jit_pushargr(REG_ACC);
		jit_finishi(putch);
#endif
	    } else {
		unsigned i = 0;
		struct bfi * v = n;
		char *s;
		while(v->next && v->next->type == T_CHR &&
			v->next->count > 0 &&
			    (v->next->count < 127 || iostyle != 1)) {

		    if (i+2 > maxstrlen) {
			if (maxstrlen) maxstrlen *= 2; else maxstrlen = 4096;
			strbuf = realloc(strbuf, maxstrlen);
			if (!strbuf) {
			    fprintf(stderr, "Reallocate of string buffer failed\n");
			    exit(42);
			}
		    }

		    strbuf[i++] = (char) /*GCC -Wconversion*/ v->count;
		    n = v;
		    v = v->next;
		}
		strbuf[i] = 0;
		s = strdup(strbuf);
		if (!s) {
		    fprintf(stderr, "Save of string failed\n");
		    exit(43);
		}
		save_ptr_for_free(s);

#ifdef GNULIGHTv1
		jit_movi_p(REG_ACC, s);
		jit_prepare_i(1);
		jit_pusharg_i(REG_ACC);
		jit_finish(puts_without_nl);
#endif
#ifdef GNULIGHTv2
		jit_prepare();
		jit_pushargi((jit_word_t) s);
		jit_finishi(puts_without_nl);
#endif
	    }
	    break;

	case T_INP:
	    load_acc_offset(n->offset);
	    set_acc_offset(n->offset);

#ifdef GNULIGHTv1
	    jit_prepare_i(1);
	    jit_pusharg_i(REG_ACC);
	    jit_finish(getch);
	    jit_retval_i(REG_ACC);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_pushargr(REG_ACC);
	    jit_finishi(getch);
	    jit_retval(REG_ACC);
#endif
	    break;

	case T_STOP:
#ifdef GNULIGHTv1
	    jit_prepare_i(0);
	    jit_finish(failout);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_finishi(failout);
#endif
	    break;

	case T_NOP:
	case T_DUMP:
	    fprintf(stderr, "Warning on code generation: "
		    "%s node: ptr+%d, cnt=%d, @(%d,%d).\n",
		    tokennames[n->type],
		    n->offset, n->count, n->line, n->col);
	    break;

	default:
	    fprintf(stderr, "Code gen error: "
		    "%s\t"
		    "%d:%d, %d:%d, %d:%d\n",
		    tokennames[n->type],
		    n->offset, n->count,
		    n->offset2, n->count2,
		    n->offset3, n->count3);
	    exit(1);
	}
	n=n->next;

#if 0 /*def GNULIGHTv2 */
	if(n && enable_trace) {
	    char *p, buf[250];
	    clean_acc();
	    acc_loaded = 0;

	    sprintf(buf, "@(%d,%d)\n", n->line, n->col);
	    p = strdup(buf);
	    save_ptr_for_free(p);

	    jit_prepare();
	    jit_pushargi((jit_word_t) p);
	    jit_finishi(puts_without_nl);
	}
#endif

#ifdef GNULIGHTv1
	/* TODO -- Check for codeBuffer overflow (add jmp to new) */
#endif
    }

    jit_ret();

    if (strbuf) { maxstrlen = 0; free(strbuf); strbuf = 0; }

    delete_tree();

#ifdef GNULIGHTv1
    jit_flush_code(startptr, jit_get_ip().ptr);

    if (verbose)
	fprintf(stderr, "Generated %d bytes of V1 GNU Lightning code, running\n",
		(int)(jit_get_ip().ptr - (char*)startptr));

    start_runclock();
    codeptr(map_hugeram());
    finish_runclock(&run_time, &io_time);
#endif

#ifdef GNULIGHTv2
    jit_epilog();
    end = jit_note(__FILE__, __LINE__);
    codeptr = jit_emit();

    if (verbose)
	fprintf(stderr, "Generated %d bytes of V2 GNU Lightning code, running\n",
	    (int)((char*)jit_address(end) - (char*)jit_address(start)));

    jit_clear_state();
    // jit_disassemble();

    start_runclock();
    codeptr(map_hugeram());
    finish_runclock(&run_time, &io_time);
#endif

#if 0
  /* This code writes the generated instructions to a file
   * so we can disassemble it using:  ndisasm -b 32/64 code.bin  */
    {
#ifdef GNULIGHTv1
	char   *p = startptr;
	int     s = jit_get_ip().ptr - p;
#endif
#ifdef GNULIGHTv2
	char   *p = (char*)jit_address(start);
	int     s = (char*)jit_address(end) - p;
#endif
	FILE   *fp = fopen("code.bin", "w");
	int     i;
	for (i = 0; i < s; ++i) {
	    fputc(p[i], fp);
	}
	fclose(fp);
    }
#endif

#ifdef GNULIGHTv2
    jit_destroy_state();
    finish_jit();
#endif

    codeptr = 0;
    if (loopstack) { free(loopstack); loopstack = 0; }
    free_saved_memory();
}