void as_3_function::compile_stack_resize( int count )
	{
#ifdef __GAMESWF_ENABLE_JIT__
		jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
		jit_this_call( m_compiled_code, &array<as_value>::size );
		jit_subi( m_compiled_code, jit_eax, count );
		jit_pusharg( m_compiled_code, jit_eax );
		jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
		jit_this_call( m_compiled_code,  &array<as_value>::resize );
		jit_popargs( m_compiled_code, 1 );
#endif
	}
	void as_3_function::compile()
	{
#define var_stack jit_getarg( 1 )
#define var_scope jit_getarg( 2 )

#ifdef __GAMESWF_ENABLE_JIT__
		int ip = 0;
		jit_prologue( m_compiled_code );

		if( m_code.size() == 0 ) return;
		do
		{
			Uint8 opcode = m_code[ip++];
			switch (opcode)
			{
				case 0x24:	// pushbyte
				{
					int byte_value;
					ip += read_vu30(byte_value, &m_code[ip]);

					//stack.push_back(byte_value);
					jit_pushargi( m_compiled_code, byte_value );
					jit_load( m_compiled_code, jit_eax, jit_getarg( 1 ) );
					jit_pusharg( m_compiled_code, jit_eax );
					jit_call( m_compiled_code, stack_int_function(stack_push_back_value) );
					jit_popargs( m_compiled_code, 2 );

					//IF_VERBOSE_ACTION(log_msg("EX: pushbyte\t %d\n", byte_value));

					break;
				}

				case 0x2D:	// pushint
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					int val = m_abc->get_integer(index);

					//stack.push_back(val);
					jit_pushargi( m_compiled_code, val );
					jit_load( m_compiled_code, jit_eax, jit_getarg( 1 ) );
					jit_pusharg( m_compiled_code, jit_eax );
					jit_call( m_compiled_code, stack_int_function(stack_push_back_value) );
					jit_popargs( m_compiled_code, 2 );

					//IF_VERBOSE_ACTION(log_msg("EX: pushint\t %d\n", val));

					break;
				}

				case 0x2C:	// pushstring
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* val = m_abc->get_string(index);

					//stack.push_back(val);
					jit_pushargi( m_compiled_code, val );
					jit_load( m_compiled_code, jit_eax, jit_getarg( 1 ) );
					jit_pusharg( m_compiled_code, jit_eax );
					jit_call( m_compiled_code, stack_charp_function( &stack_push_back_value ) );
					jit_popargs( m_compiled_code, 2 );

					//IF_VERBOSE_ACTION(log_msg("EX: pushstring\t '%s'\n", val));

					break;
				}

				case 0x2F:	// pushdouble
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					double val = m_abc->get_double(index);
					
					jit_pushargi( m_compiled_code, val );
					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_pusharg( m_compiled_code, jit_esi );
					jit_call( m_compiled_code, &(stack_push_back_value<double>) );
					jit_popargs( m_compiled_code, 3 ); //double counts for 2;
					//stack.push_back(val);

					//IF_VERBOSE_ACTION(log_msg("EX: pushdouble\t %f\n", val));

					break;
				}

				case 0x30:	// pushscope
				{
					//as_value& val = stack.back();
					typedef as_value& ( array<as_value>::*back_function )();
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
					jit_this_call( m_compiled_code, (back_function)&array<as_value>::back );

					jit_load( m_compiled_code, jit_this_pointer, var_scope );
					jit_push( m_compiled_code, jit_result );
					jit_call( m_compiled_code, (push_value_function)&array<as_value>::push_back );
					jit_popargs( m_compiled_code, 1 );


					//IF_VERBOSE_ACTION(log_msg("EX: pushscope\t %s\n", val.to_xstring()));
					//TODO: Ecx is caller-saved, copy it to esi or edi before calling to prevent reload from memory
					//stack.resize(stack.size() - 1); 
					compile_stack_resize( 1 );

					break;
				}

				case 0x47:	// returnvoid
				{
					//IF_VERBOSE_ACTION(log_msg("EX: returnvoid\t\n"));

					//result->set_undefined();
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 3 ) );
					jit_this_call( m_compiled_code, &as_value::set_undefined );

					break;
				}

				case 0x49:	// constructsuper
				{
					// stack: object, arg1, arg2, ..., argn
					int arg_count;
					ip += read_vu30(arg_count, &m_code[ip]);

					struct constructsuper
					{
					
						static void call( array<as_value> & stack, int arg_count )
						{
							as_object* obj = stack.back().to_object();
							stack.resize(stack.size() - 1);
							for (int i = 0; i < arg_count; i++)
							{
								as_value& val = stack.back();
								stack.resize(stack.size() - 1);
							}

							//TODO: construct super of obj

							IF_VERBOSE_ACTION(log_msg("EX: constructsuper\t 0x%p(args:%d)\n", obj, arg_count));
						}
					};

					jit_pushi( m_compiled_code, arg_count );
					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_push( m_compiled_code, jit_esi );
					jit_call( m_compiled_code, &constructsuper::call );
					jit_popargs( m_compiled_code, 2 );

					break;
				}

				case 0x4F:	// callpropvoid, Call a property, discarding the return value.
				// Stack: …, obj, [ns], [name], arg1,...,argn => …
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* name = m_abc->get_multiname(index);

					int arg_count;
					ip += read_vu30(arg_count, &m_code[ip]);

					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_pusharg( m_compiled_code, jit_esi );
					jit_pushargi( m_compiled_code, arg_count );
					jit_pushargi( m_compiled_code, name );
					jit_pushargi( m_compiled_code, this );
					jit_call( m_compiled_code, &callpropvoid::call );
					jit_popargs( m_compiled_code, 4 );

					/*
					struct local
					{
						static void construct_env( as_environment *env, player * player )
						{
							new( env ) as_environment( player );
						}

						static void destruct_env( as_environment *env )
						{
							env->~as_environment();
						}
					};

					//as_environment env(get_player());
					int env_offset = jit_allocate_stack_object_memory( m_compiled_code, sizeof( as_environment ) );
					//Do we query it each it or it won't change? I decided it won't change
					jit_mov( m_compiled_code, jit_edi, jit_stack_pointer );
					jit_pushi( m_compiled_code, (uint32)get_player() );
					jit_push( m_compiled_code, jit_edi );
					jit_call( m_compiled_code, &local::construct_env );
					jit_popargs( m_compiled_code, 2 );

					//as_value* val = stack.back();
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
					typedef as_value& ( array<as_value>::*back_function )();
					jit_this_call( m_compiled_code, (back_function)&array<as_value>::back );
					jit_mov( m_compiled_code, jit_esi, jit_result );

					for (int i = 0; i < arg_count; i++)
					{
					 //env.push( *val);
					 jit_mov( m_compiled_code, jit_this_pointer, jit_edi );
					 jit_push( m_compiled_code, jit_esi );
					 jit_this_call( m_compiled_code, & as_environment::push<as_value&> );
					 
					 //val--;
					 jit_subi( m_compiled_code, jit_esi, sizeof( as_value ) );
					}

					//stack.resize(stack.size() - arg_count);
					compile_stack_resize( arg_count );

					//as_object* obj = stack.back().to_object();
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
					typedef as_value& ( array<as_value>::*back_function )();
					jit_this_call( m_compiled_code, (back_function)&array<as_value>::back );
					jit_mov( m_compiled_code, jit_this_pointer, jit_result );
					jit_this_call( m_compiled_code, &as_value::to_object );
					jit_mov( m_compiled_code, jit_esi, jit_result );

					 //stack.resize(stack.size() - 1);
					compile_stack_resize( 1 );


					//as_value func;
					//if (obj && obj->get_member(name, &func))
					//{
					//	call_method(func, &env, obj,	arg_count, env.get_top_index());
					//}

					// Destruct env
					jit_getaddress( m_compiled_code, jit_result, jit_stack_pointer, env_offset );
					jit_push( m_compiled_code ,jit_result );
					jit_call( m_compiled_code, &local::destruct_env );
					jit_popargs( m_compiled_code, 1 );

 
					//IF_VERBOSE_ACTION(log_msg("EX: callpropvoid\t 0x%p.%s(args:%d)\n", obj, name, arg_count));
					*/
					break;
				}

				case 0x5D:	// findpropstrict
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* name = m_abc->get_multiname(index);

					// search property in scope
					
					// TODO: inline
					struct findpropstrict
					{
						static as_object * call( char* name, array<as_value> & scope )
						{
							for (int i = scope.size() - 1; i >= 0; i--)
							{
								as_value val;
								if (scope[i].find_property(name, &val))
								{
									return scope[i].to_object();
								}
							}

							return NULL;
						}
					};

					jit_load( m_compiled_code, jit_esi, var_scope );
					jit_push( m_compiled_code, jit_esi );
					jit_pushi( m_compiled_code, name);
					jit_call( m_compiled_code, &findpropstrict::call );
					jit_popargs( m_compiled_code, 2 );

					//IF_VERBOSE_ACTION(log_msg("EX: findpropstrict\t %s, obj=0x%p\n", name, obj));

					//stack.push_back(obj);
					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_push( m_compiled_code, jit_result );
					jit_push( m_compiled_code, jit_esi );
					jit_call( m_compiled_code, &stack_push_back_value<as_object*> );
					jit_popargs( m_compiled_code, 2 );

					break;
				}

				case 0x5E:	// findproperty, Search the scope stack for a property
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* name = m_abc->get_multiname(index);

					struct findproperty
					{
						static void call( const char* name, array<as_value> & scope, array<as_value> & stack )
						{
							as_object* obj = NULL;
							for (int i = scope.size() - 1; i >= 0; i--)
							{
								as_value val;
								if (scope[i].find_property(name, &val))
								{
									obj = scope[i].to_object();
									break;
								}
							}

							IF_VERBOSE_ACTION(log_msg("EX: findproperty\t %s, obj=0x%p\n", name, obj));

							stack.push_back(obj);
						}
					};

					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_push( m_compiled_code, jit_esi );
					jit_load( m_compiled_code, jit_esi, var_scope );
					jit_push( m_compiled_code, jit_esi );
					jit_pushi( m_compiled_code, name );
					jit_call( m_compiled_code, &findproperty::call );
					jit_popargs( m_compiled_code, 3 );

					break;

				}

				case 0x60:	// getlex, Find and get a property.
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* name = m_abc->get_multiname(index);

					struct getlex
					{
						static void call( const char* name, array<as_value> & scope, array<as_value> &stack )
						{
							// search property in scope
							as_value val;
							for (int i = scope.size() - 1; i >= 0; i--)
							{
								if (scope[i].find_property(name, &val))
								{
									break;
								}
							}

							IF_VERBOSE_ACTION(log_msg("EX: getlex\t %s, value=%s\n", name, val.to_xstring()));

							stack.push_back(val);
						}
					};

					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_push( m_compiled_code, jit_esi );
					jit_load( m_compiled_code, jit_esi, var_scope );
					jit_push( m_compiled_code, jit_esi );
					jit_pushi( m_compiled_code, name );
					jit_call( m_compiled_code, &getlex::call );
					jit_popargs( m_compiled_code, 2 );
					break;
				}

				case 0x66:	// getproperty
				{
					//					 int index;
					//					 ip += read_vu30(index, &m_code[ip]);
					//					 const char* name = m_abc->get_multiname(index);
					// 
					//					 as_object* obj = stack.back().to_object();
					//					 if (obj)
					//					 {
					//						 obj->get_member(name, &stack.back());
					//					 }
					//					 else
					//					 {
					//						 stack.back().set_undefined();
					//					 }
					// 
					//					 IF_VERBOSE_ACTION(log_msg("EX: getproperty\t %s, value=%s\n", name, stack.back().to_xstring()));
					// 
					break;
				}

				case 0x68:	// initproperty, Initialize a property.
				{
					int index;
					ip += read_vu30(index, &m_code[ip]);
					const char* name = m_abc->get_multiname(index);

					struct initproperty
					{
						static void call( const char * name, array<as_value> & stack )
						{
							as_value& val = stack[stack.size() - 1];
							as_object* obj = stack[stack.size() - 2].to_object();
							if (obj)
							{
								obj->set_member(name, val);
							}

							IF_VERBOSE_ACTION(log_msg("EX: initproperty\t 0x%p.%s=%s\n", obj, name, val.to_xstring()));

							stack.resize(stack.size() - 2);
						}
					};

					jit_load( m_compiled_code, jit_esi, var_stack );
					jit_push( m_compiled_code, jit_esi );
					jit_pushi( m_compiled_code, name );
					jit_call( m_compiled_code, &initproperty::call );
					jit_popargs( m_compiled_code, 2 );
					break;
				}

				case 0xD0:	// getlocal_0
				case 0xD1:	// getlocal_1
				case 0xD2:	// getlocal_2
				case 0xD3:	// getlocal_3
				{
					//as_value& val = lregister[opcode & 0x03];
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 0 ) );
					jit_pushi( m_compiled_code, opcode & 0x03 );
					jit_this_call( m_compiled_code, (index_function)&array<as_value>::operator[] );
					jit_popargs( m_compiled_code, 1 );

					//stack.push_back(val);
					jit_push( m_compiled_code, jit_result );
					jit_load( m_compiled_code, jit_this_pointer, jit_getarg( 1 ) );
					jit_this_call( m_compiled_code, (push_value_function) &array<as_value>::push_back );
					jit_popargs( m_compiled_code, 1 );

					//IF_VERBOSE_ACTION(log_msg("EX: getlocal_%d\t %s\n", opcode & 0x03, val.to_xstring()));
					break;
				}

				default:
					log_msg("TODO opcode 0x%02X\n", opcode);
					break;
			}

		}
		while (ip < m_code.size());

		jit_return( m_compiled_code );
		m_compiled_code.initialize();
#else
		assert( false );
#endif
	}
Beispiel #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();
}
Beispiel #4
0
void
outrun(int ch, int count)
{
    jit_node_t    *argp;

    switch(ch) {
    case '!':
	if (bytecell) tape_step = 1; else
	tape_step = sizeof(int);

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

    case '~':
	jit_ret();
	jit_epilog();
	end = jit_note(__FILE__, __LINE__);
	codeptr = jit_emit();
	jit_clear_state();
	codeptr(calloc(tape_step, tapelen));
	jit_destroy_state();
	finish_jit();
	codeptr = 0;
	if (loopstack) { free(loopstack); loopstack = 0; }
	break;

    case '>':
	jit_addi(REG_P, REG_P, count * tape_step);
	break;

    case '<':
	jit_subi(REG_P, REG_P, count * tape_step);
	break;

    case '+':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);
	jit_addi(REG_ACC, REG_ACC, count);
	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);
	break;

    case '-':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);
	jit_subi(REG_ACC, REG_ACC, count);
	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);
	break;

    case '[':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

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

	loopstack[stackptr] = jit_beqi(REG_ACC, 0);
	loopstack[stackptr+1] = jit_label();
	stackptr += 2;
	break;

    case ']':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

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

	{
	    jit_node_t *ref;
	    ref = jit_bnei(REG_ACC, 0);
	    jit_patch_at(ref, loopstack[stackptr+1]);
	    jit_patch(loopstack[stackptr]);
	}
	break;

    case '.':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

	jit_prepare();
	jit_pushargr(REG_ACC);
	jit_finishi(putchar);
	break;

    case ',':
	jit_prepare();
	jit_pushargr(REG_ACC);
	jit_finishi(getchar);
	jit_retval(REG_ACC);

	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);

	break;
    }
}