예제 #1
0
void FunctionManager::build_function_thread()
{
    try
    {
        TRACE("JIT thread started");
        boost::mutex::scoped_lock jit_thread_cv_mutex_lock(
            jit_thread_cv_mutex_);
        while (true)
        {
            while (!quit_ && !work_available_)
            {
                TRACE("JIT thread waiting to be signalled");
                jit_thread_cv_.wait(jit_thread_cv_mutex_lock);
            }

            if (quit_)
            {
                TRACE("JIT thread quitting");
                return;
            }
            else
            {
                TRACE("JIT thread about to build Function at address 0x" <<
                      std::hex << std::setfill('0') << std::setw(4) << 
                      jit_thread_address_);
                assert(work_available_);
                assert(!jit_thread_idle_);

                // Note that we translate code from memory_snapshot_
                // not mpu_->memory. This is important, even though we
                // have update_memory_snapshot() which "should" invalidate
                // Function objects which depend on modified code before any
                // of them are used. The reason is that if a memory location
                // is temporarily modified by the interpreter before it can
                // be translated, then modified back to its original value
                // by the interpreter before update_memory_snapshot() is
                // called, update_memory_snapshot() can't notice the change,
                // but the change has been compiled into the Function object.
                // (See test/z-self-modify-2.xa; this breaks in hybrid mode
                // if memory_snapshot_ isn't used here.)
                build_function(jit_thread_address_, memory_snapshot_);
                work_available_ = false;

                boost::mutex::scoped_lock jit_thread_idle_lock(
                    jit_thread_idle_mutex_);
                jit_thread_idle_ = true;
            }
        }
    }
    catch (std::exception &e)
    {
        die(e.what());
    }
}
예제 #2
0
/* parsing language hook */
static void slang_parse_file ()
{

    int i;
    for(i = 0; i<num_in_fnames; ++i) {
        parse_program(in_fnames[i]);
    } 
#if 0
  tree  char_p = build_pointer_type (char_type_node);
  tree  puts_type   = build_function_type_list (integer_type_node,
						char_p, NULL_TREE);
  tree  puts_fndecl = build_function_decl ("puts", true, puts_type);

  tree  main_type   = build_function_type_list (integer_type_node, NULL_TREE);
  tree  main_fndecl = build_function_decl ("main", false, main_type);

  const char *msg = "HelloWorld , ... This is pradeeps compiler";
  tree hello_str = build_string_literal (strlen(msg) + 1, msg);

  tree  call = build_call_expr (puts_fndecl,1, hello_str);
  tree block = make_node(BLOCK);
  tree       c1 = build_pointer_type (char_type_node);
  tree stmts = NULL_TREE ;//alloc_stmt_list ();
  append_to_statement_list (call, &stmts);

  build_function (main_fndecl, stmts, block);

  FILE *fd = fopen("/home/pradeep/Desktop/dump.txt","w");


  gimplify_function_tree (main_fndecl);

  dump_function_to_file (main_fndecl, fd, 0);

  fclose(fd);

  cgraph_finalize_function (main_fndecl, false);

  current_function_decl = NULL_TREE;
  pop_cfun();
#endif

}
예제 #3
0
/* 
 * Make the given NODE simple - i.e. return a temporary for complex subtrees 
 * The appropriate code is also generated and pushed onto the code stack
*/
value *make_simple(environment *env, NODE *node, int flag, int return_type) {
	int i_value = 0;
	char *s_tmp = NULL;
	value *val1 = NULL, *val2 = NULL, *temporary = NULL, *temp = NULL;
	static int if_count = 0;
	static int while_count = 0;	
	tac_quad *temp_quad = NULL;
	environment *new_env = NULL;
	if (node==NULL) return NULL;
	switch(type_of(node)) {
		case LEAF: 
			return make_simple(env, node->left, flag, return_type);
		case CONSTANT:
			i_value = cast_from_node(node)->value;
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "%d", i_value);
			return int_value(i_value);
		case IDENTIFIER:
			return string_value(cast_from_node(node)->lexeme);
		case IF:
			build_if_stmt(env, node, ++if_count, NULL, NULL, flag, return_type);
			return NULL;
		case BREAK:
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "__while%dend", while_count);
			append_code(make_goto(s_tmp));
			return NULL;			
		case CONTINUE:
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "__while%d", while_count);
			append_code(make_goto(s_tmp));
			return NULL;
		case WHILE:
			build_while_stmt(env, node, ++while_count, ++if_count, flag, return_type);
			return NULL;	
		case '=':
			if (flag == INTERPRET_FN_SCAN) return NULL;
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val2 && val2->value_type!=VT_INTEGR && val2->value_type!=VT_FUNCTN) {
				if (val2->value_type == VT_STRING) {
					val2 = get(env, val2->data.string_value);
				}
				else {
					val2 = get(env, val2->identifier);
				}
				if (!val2) fatal("Undeclared identifier");					
			}
			/* Check the LHS variable has already been defined */
			temp = get(env, to_string(val1));
			assert(temp!=NULL, "Variable not defined");
			/* Type check the assignment */
			type_check_assignment(val1, val2, vt_type_convert(temp->value_type));
			temporary = assign(env, val1, val2, 0);
			if (flag != INTERPRET_FN_SCAN) append_code(make_quad_value("=", val2, NULL, temporary, TT_ASSIGN, 0));
			return NULL;
		case '*':
		case '/':
		case '>':
		case '<':										
		case '%':							
		case '-':									
		case '+':
		case NE_OP:
		case LE_OP:
		case GE_OP:				
		case EQ_OP:
			temporary = generate_temporary(env, int_value(0));
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val1->value_type==VT_STRING) val1 = get(env, correct_string_rep(val1));
			if (val2->value_type==VT_STRING) val2 = get(env, correct_string_rep(val2));
			assert(val1 != NULL, "Operand value 1 must not be null");	
			assert(val2 != NULL, "Operand value 2 must not be null");				
			if (flag != INTERPRET_FN_SCAN) append_code(make_quad_value(type_to_string(type_of(node)), val1, val2, temporary, TT_OP, type_of(node)));
			return temporary;
		case '~':
			if (flag != INTERPRET_PARAMS && flag!=INTERPRET_FN_SCAN) {
				/* Params should not be registered, because at this point we're not in the correct environment */
				register_variable_subtree_tac(env, node, VT_ANY);
			}
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (flag == INTERPRET_PARAMS) {
				return int_param(to_string(val2), to_int(env, val1));
			}			
			return NULL;
		case 'D':
			/* val1 is FN definition */
			/* val1 is executed in current environment */
			val1 = make_simple(env, node->left, flag, return_type);
			
			/* New FN body environment */
			new_env = create_environment(env);
			if (val1!=NULL) {
				/* Point function to the correct fn body */
				val1->data.func->node_value = node->right;			
				/* Store function definition in environment */
				val2 = store_function(env, val1, new_env);
			}
			if (flag != INTERPRET_FN_SCAN) {
				/* Write out FN Name label */
				append_code(make_begin_fn(val2));				
				append_code(make_fn_def(val2));
				/* Make init frame */
				temp_quad = make_init_frame();
				append_code(temp_quad);
				/* Define parameters with default empty values */
				register_params(new_env, val2->data.func->params);
				append_code(make_fn_body(val2));
				/* Look inside fn body */
				val2 = make_simple(new_env, node->right, EMBEDDED_FNS, val1->data.func->return_type);
				/* Update prepare frame with environment size */
				temp_quad->operand1 = int_value(env_size(new_env));
				/* Write end of function marker */
				append_code(make_end_fn(val2));
			}
			return NULL;
		case 'd':
			/* val1 is the type */
			val1 = make_simple(env, node->left, flag, return_type);
			/* val2 is fn name & params */
			val2 = make_simple(env, node->right, flag, return_type);
			/* Store return type */
			val2->data.func->return_type = to_int(env, val1);
			return val2;
		case 'F':
			/* FN name in val1 */
			val1 = make_simple(env, node->left, flag, return_type);
			/* Pull our parameters */
			val2 = make_simple(env, node->right, INTERPRET_PARAMS, return_type);
			return build_function(env, val1, val2);
		case RETURN:
			val1 = make_simple(env, node->left, flag, return_type);
			/* Provide lookup for non-constants */
			if (val1 && val1->value_type!=VT_INTEGR) {
				if (val1->value_type == VT_STRING) {
					val1 = get(env, val1->data.string_value);
				}
				else {
					val1 = get(env, val1->identifier);
				}
				if (!val1) fatal("Undeclared identifier");
			}
			type_check_return(val1, return_type);
			append_code(make_return(val1));
			return NULL;
		case ',':
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val1 && val2) {
				return join(val1, val2);
			}
			return NULL;	
		case APPLY:
			/* FN Name */
			val1 = make_simple(env, node->left, flag, return_type);
			/* Params */
			val2 = make_simple(env, node->right, flag, return_type);
			/* Lookup function */
			temp = search(env, to_string(val1), VT_FUNCTN, VT_ANY, 1);
			if (temp) {
				int fn_return_type;
				append_code(prepare_fn(val2));
				append_code(push_params(env, val2));
				/* If we can't typecheck, set a special UNDEFINED flag to say we can't */
				/* typecheck. This can happen with function variables, we do not EASILY know the */
				/* return type of the functions they are bound to until runtime. */
				fn_return_type = UNDEFINED;
				if (temp->data.func) {
					fn_return_type = temp->data.func->return_type;	
				} 
				/* Temporary for result (if any) */
				switch(fn_return_type) {
					case INT:
						temporary = generate_temporary(env, int_value(0));
						break;
					case VOID:
						temporary = generate_temporary(env, NULL);
						break;						
					case FUNCTION:
						temporary = generate_temporary(env, null_fn);
						break;
					default:
						temporary = generate_untypechecked_temporary(env);
						break;
				}
				append_code(make_fn_call(temporary, temp));
				return temporary;
			}
			else {
				fatal("Cannot find function '%s'", to_string(val1));
			}
			return NULL;
		case FUNCTION:
		case INT:
		case VOID:
			return int_value(type_of(node));
		case ';':
			make_simple(env, node->left, flag, return_type);
			make_simple(env, node->right, flag, return_type);			
			return NULL;
		default:
			fatal("Unrecognised node type");
			return NULL;
	}
}