Commit 52b9468f by David Malcolm Committed by David Malcolm

PR jit/63854: Fix leaks in toyvm.c

gcc/jit/ChangeLog:
	PR jit/63854
	* docs/examples/tut04-toyvm/toyvm.c
	(toyvm_compiled_function): New typedef.
	(toyvm_compiled_func) Rename to...
	(toyvm_compiled_code) ...this.
	(struct toyvm_compiled_function): New struct.
	(toyvm_function_compile): Return a toyvm_compiled_function *
	rather than a toyvm_compiled_func, so that the caller can fully
	clean things up.  Free "funcname".
	(test_script): Update for change to toyvm_function_compile.
	Clean up the toyvm_compiled_function.
	(main): Likewise.
	(docs/intro/tutorial04.rst): Update to reflect the above changes,
	and to better spell out the lifetime of the compiled code.

From-SVN: r218234
parent 33b625ed
2014-12-01 David Malcolm <dmalcolm@redhat.com>
PR jit/63854
* docs/examples/tut04-toyvm/toyvm.c
(toyvm_compiled_function): New typedef.
(toyvm_compiled_func) Rename to...
(toyvm_compiled_code) ...this.
(struct toyvm_compiled_function): New struct.
(toyvm_function_compile): Return a toyvm_compiled_function *
rather than a toyvm_compiled_func, so that the caller can fully
clean things up. Free "funcname".
(test_script): Update for change to toyvm_function_compile.
Clean up the toyvm_compiled_function.
(main): Likewise.
(docs/intro/tutorial04.rst): Update to reflect the above changes,
and to better spell out the lifetime of the compiled code.
2014-12-01 David Malcolm <dmalcolm@redhat.com>
PR jit/63854
* jit-builtins.c
(gcc::jit::recording::builtins_manager::make_fn_type): Call the
context's new_function_type method, rather than directly creating
......
......@@ -33,9 +33,10 @@ typedef struct toyvm_op toyvm_op;
typedef struct toyvm_function toyvm_function;
typedef struct toyvm_frame toyvm_frame;
typedef struct compilation_state compilation_state;
typedef struct toyvm_compiled_function toyvm_compiled_function;
/* Functions are compiled to this function ptr type. */
typedef int (*toyvm_compiled_func) (int);
typedef int (*toyvm_compiled_code) (int);
enum opcode {
/* Ops taking no operand. */
......@@ -440,9 +441,17 @@ add_pop (compilation_state *state,
gcc_jit_lvalue_as_rvalue (state->stack_depth))));
}
/* A struct to hold the compilation results. */
struct toyvm_compiled_function
{
gcc_jit_result *cf_jit_result;
toyvm_compiled_code cf_code;
};
/* The main compilation hook. */
static toyvm_compiled_func
static toyvm_compiled_function *
toyvm_function_compile (toyvm_function *fn)
{
compilation_state state;
......@@ -724,12 +733,26 @@ toyvm_function_compile (toyvm_function *fn)
} /* end of loop on PC locations. */
/* We've now finished populating the context. Compile it. */
gcc_jit_result *result = gcc_jit_context_compile (state.ctxt);
gcc_jit_result *jit_result = gcc_jit_context_compile (state.ctxt);
gcc_jit_context_release (state.ctxt);
return (toyvm_compiled_func)gcc_jit_result_get_code (result,
toyvm_compiled_function *toyvm_result =
(toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function));
if (!toyvm_result)
{
fprintf (stderr, "out of memory allocating toyvm_compiled_function\n");
gcc_jit_result_release (jit_result);
return NULL;
}
toyvm_result->cf_jit_result = jit_result;
toyvm_result->cf_code =
(toyvm_compiled_code)gcc_jit_result_get_code (jit_result,
funcname);
/* (this leaks "result" and "funcname") */
free (funcname);
return toyvm_result;
}
char test[1024];
......@@ -768,7 +791,8 @@ test_script (const char *scripts_dir, const char *script_name, int input,
char *script_path;
toyvm_function *fn;
int interpreted_result;
toyvm_compiled_func code;
toyvm_compiled_function *compiled_fn;
toyvm_compiled_code code;
int compiled_result;
snprintf (test, sizeof (test), "toyvm.c: %s", script_name);
......@@ -784,12 +808,18 @@ test_script (const char *scripts_dir, const char *script_name, int input,
interpreted_result = toyvm_function_interpret (fn, input, NULL);
CHECK_VALUE (interpreted_result, expected_result);
code = toyvm_function_compile (fn);
compiled_fn = toyvm_function_compile (fn);
CHECK_NON_NULL (compiled_fn);
code = (toyvm_compiled_code)compiled_fn->cf_code;
CHECK_NON_NULL (code);
compiled_result = code (input);
CHECK_VALUE (compiled_result, expected_result);
gcc_jit_result_release (compiled_fn->cf_jit_result);
free (compiled_fn);
free (fn);
free (script_path);
}
......@@ -853,9 +883,15 @@ main (int argc, char **argv)
toyvm_function_interpret (fn, atoi (argv[2]), NULL));
/* JIT-compilation. */
toyvm_compiled_func code = toyvm_function_compile (fn);
toyvm_compiled_function *compiled_fn
= toyvm_function_compile (fn);
toyvm_compiled_code code = compiled_fn->cf_code;
printf ("compiler result: %d\n",
code (atoi (argv[2])));
gcc_jit_result_release (compiled_fn->cf_jit_result);
free (compiled_fn);
return 0;
}
......@@ -101,6 +101,15 @@ then directly executed in-process:
:end-before: enum opcode
:language: c
The lifetime of the code is tied to that of a :c:type:`gcc_jit_result *`.
We'll handle this by bundling them up in a structure, so that we can
clean them up together by calling :c:func:`gcc_jit_result_release`:
.. literalinclude:: ../examples/tut04-toyvm/toyvm.c
:start-after: /* A struct to hold the compilation results. */
:end-before: /* The main compilation hook. */
:language: c
Our compiler isn't very sophisticated; it takes the implementation of
each opcode above, and maps it directly to the operations supported by
the libgccjit API.
......@@ -155,7 +164,7 @@ a block, implementing pushing and popping values:
.. literalinclude:: ../examples/tut04-toyvm/toyvm.c
:start-after: /* Stack manipulation. */
:end-before: /* The main compilation hook. */
:end-before: /* A struct to hold the compilation results. */
:language: c
We will support single-stepping through the generated code in the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment