+2014-12-09 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/64206
+ * Make-lang.in (jit_OBJS): Add jit/jit-tempdir.o.
+ * jit-common.h (gcc::jit::tempdir): New forward decl.
+ * jit-playback.c: Include jit-tempdir.h.
+ (gcc::jit::playback::context::context): Initialize m_tempdir.
+ (gcc::jit::playback::context::~context): Move tempdir
+ cleanup to new file jit-tempdir.c
+ (make_tempdir_path_template): Move to new file jit-tempdir.c.
+ (gcc::jit::playback::context::compile): Move tempdir creation
+ to new tempdir object in new file jit-tempdir.c.
+ (gcc::jit::playback::context::make_fake_args): Get path from
+ tempdir object rather than from member data.
+ (gcc::jit::playback::context::convert_to_dso): Likewise.
+ (gcc::jit::playback::context::dlopen_built_dso): Likewise.
+ (gcc::jit::playback::context::dump_generated_code): Likewise.
+ (gcc::jit::playback::context::get_path_c_file): New function.
+ (gcc::jit::playback::context::get_path_s_file): New function.
+ (gcc::jit::playback::context::get_path_so_file): New function.
+ * jit-playback.h (gcc::jit::playback::context::get_path_c_file):
+ New function.
+ (gcc::jit::playback::context::get_path_s_file): New function.
+ (gcc::jit::playback::context::get_path_so_file): New function.
+ (gcc::jit::playback::context): Move fields "m_path_template",
+ "m_path_tempdir", "m_path_c_file", "m_path_s_file",
+ "m_path_so_file" to new jit::tempdir class; add field "m_tempdir".
+ * jit-tempdir.c: New file.
+ * jit-tempdir.h: New file.
+
2014-12-09 David Malcolm <dmalcolm@redhat.com>
* jit-playback.c (gcc::jit::playback::context::compile): Acquire the
jit/jit-recording.o \
jit/jit-playback.o \
jit/jit-result.o \
+ jit/jit-tempdir.o \
jit/jit-builtins.o
# Use strict warnings for this front end.
class result;
class dump;
class builtins_manager; // declared within jit-builtins.h
+class tempdir;
namespace recording {
#include "jit-playback.h"
#include "jit-result.h"
#include "jit-builtins.h"
+#include "jit-tempdir.h"
/* gcc::jit::playback::context::build_cast uses the convert.h API,
playback::context::context (recording::context *ctxt)
: m_recording_ctxt (ctxt),
+ m_tempdir (NULL),
m_char_array_type_node (NULL),
m_const_char_ptr (NULL)
{
playback::context::~context ()
{
- if (get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES))
- fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir);
- else
- {
- /* Clean up .s/.so and tempdir. */
- if (m_path_s_file)
- unlink (m_path_s_file);
- if (m_path_so_file)
- unlink (m_path_so_file);
- if (m_path_tempdir)
- rmdir (m_path_tempdir);
- }
-
- free (m_path_template);
- /* m_path_tempdir aliases m_path_template, or is NULL, so don't
- attempt to free it . */
- free (m_path_c_file);
- free (m_path_s_file);
- free (m_path_so_file);
+ if (m_tempdir)
+ delete m_tempdir;
m_functions.release ();
}
m_label_expr = NULL;
}
-/* Construct a tempdir path template suitable for use by mkdtemp
- e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in
- libiberty's choose_tempdir rather than hardcoding "/tmp/".
-
- The memory is allocated using malloc and must be freed.
- Aborts the process if allocation fails. */
-
-static char *
-make_tempdir_path_template ()
-{
- const char *tmpdir_buf;
- size_t tmpdir_len;
- const char *file_template_buf;
- size_t file_template_len;
- char *result;
-
- /* The result of choose_tmpdir is a cached buffer within libiberty, so
- we must *not* free it. */
- tmpdir_buf = choose_tmpdir ();
-
- /* choose_tmpdir aborts on malloc failure. */
- gcc_assert (tmpdir_buf);
-
- tmpdir_len = strlen (tmpdir_buf);
- /* tmpdir_buf should now have a dir separator as the final byte. */
- gcc_assert (tmpdir_len > 0);
- gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR);
-
- file_template_buf = "libgccjit-XXXXXX";
- file_template_len = strlen (file_template_buf);
-
- result = XNEWVEC (char, tmpdir_len + file_template_len + 1);
- strcpy (result, tmpdir_buf);
- strcpy (result + tmpdir_len, file_template_buf);
-
- return result;
-}
-
/* A subclass of auto_vec <char *> that frees all of its elements on
deletion. */
const char *ctxt_progname;
result *result_obj = NULL;
- m_path_template = make_tempdir_path_template ();
- if (!m_path_template)
- return NULL;
+ int keep_intermediates =
+ get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES);
- /* Create tempdir using mkdtemp. This is created with 0700 perms and
- is unique. Hence no other (non-root) users should have access to
- the paths within it. */
- m_path_tempdir = mkdtemp (m_path_template);
- if (!m_path_tempdir)
+ m_tempdir = new tempdir (keep_intermediates);
+ if (!m_tempdir->create ())
return NULL;
- m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL);
- m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL);
- m_path_so_file = concat (m_path_tempdir, "/fake.so", NULL);
/* Call into the rest of gcc.
For now, we have to assemble command-line options to pass into
#define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
ADD_ARG (ctxt_progname);
- ADD_ARG (m_path_c_file);
+ ADD_ARG (get_path_c_file ());
ADD_ARG ("-fPIC");
/* Handle int options: */
argv[0] = gcc_driver_name;
argv[1] = "-shared";
/* The input: assembler. */
- argv[2] = m_path_s_file;
+ argv[2] = m_tempdir->get_path_s_file ();
/* The output: shared library. */
argv[3] = "-o";
- argv[4] = m_path_so_file;
+ argv[4] = m_tempdir->get_path_so_file ();
/* Don't use the linker plugin.
If running with just a "make" and not a "make install", then we'd
/* Clear any existing error. */
dlerror ();
- handle = dlopen (m_path_so_file, RTLD_NOW | RTLD_LOCAL);
+ handle = dlopen (m_tempdir->get_path_so_file (),
+ RTLD_NOW | RTLD_LOCAL);
if ((error = dlerror()) != NULL) {
add_error (NULL, "%s", error);
}
{
char buf[4096];
size_t sz;
- FILE *f_in = fopen (m_path_s_file, "r");
+ FILE *f_in = fopen (get_path_s_file (), "r");
if (!f_in)
return;
fclose (f_in);
}
+/* Get the supposed path of the notional "fake.c" file within the
+ tempdir. This file doesn't exist, but the rest of the compiler
+ needs a name. */
+
+const char *
+playback::context::
+get_path_c_file () const
+{
+ return m_tempdir->get_path_c_file ();
+}
+
+/* Get the path of the assembler output file "fake.s" file within the
+ tempdir. */
+
+const char *
+playback::context::
+get_path_s_file () const
+{
+ return m_tempdir->get_path_s_file ();
+}
+
+/* Get the path of the DSO object file "fake.so" file within the
+ tempdir. */
+
+const char *
+playback::context::
+get_path_so_file () const
+{
+ return m_tempdir->get_path_so_file ();
+}
+
/* qsort comparator for comparing pairs of playback::source_line *,
ordering them by line number. */
void handle_locations ();
+ const char * get_path_c_file () const;
+ const char * get_path_s_file () const;
+ const char * get_path_so_file () const;
+
private:
/* Functions for implementing "compile". */
private:
::gcc::jit::recording::context *m_recording_ctxt;
- /* Allocated using xmalloc (by xstrdup). */
- char *m_path_template;
-
- /* This either aliases m_path_template, or is NULL. */
- char *m_path_tempdir;
-
- /* The following are allocated using xmalloc. */
- char *m_path_c_file;
- char *m_path_s_file;
- char *m_path_so_file;
+ tempdir *m_tempdir;
auto_vec<function *> m_functions;
tree m_char_array_type_node;
--- /dev/null
+/* Managing temporary directories and their content within libgccjit.so
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+#include "jit-tempdir.h"
+
+
+/* Construct a tempdir path template suitable for use by mkdtemp
+ e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in
+ libiberty's choose_tempdir rather than hardcoding "/tmp/".
+
+ The memory is allocated using malloc and must be freed.
+ Aborts the process if allocation fails. */
+
+static char *
+make_tempdir_path_template ()
+{
+ const char *tmpdir_buf;
+ size_t tmpdir_len;
+ const char *file_template_buf;
+ size_t file_template_len;
+ char *result;
+
+ /* The result of choose_tmpdir is a cached buffer within libiberty, so
+ we must *not* free it. */
+ tmpdir_buf = choose_tmpdir ();
+
+ /* choose_tmpdir aborts on malloc failure. */
+ gcc_assert (tmpdir_buf);
+
+ tmpdir_len = strlen (tmpdir_buf);
+ /* tmpdir_buf should now have a dir separator as the final byte. */
+ gcc_assert (tmpdir_len > 0);
+ gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR);
+
+ file_template_buf = "libgccjit-XXXXXX";
+ file_template_len = strlen (file_template_buf);
+
+ result = XNEWVEC (char, tmpdir_len + file_template_len + 1);
+ strcpy (result, tmpdir_buf);
+ strcpy (result + tmpdir_len, file_template_buf);
+
+ return result;
+}
+
+/* The constructor for the jit::tempdir object.
+ The real work is done by the jit::tempdir::create method. */
+
+gcc::jit::tempdir::tempdir (int keep_intermediates)
+ : m_keep_intermediates (keep_intermediates),
+ m_path_template (NULL),
+ m_path_tempdir (NULL),
+ m_path_c_file (NULL),
+ m_path_s_file (NULL),
+ m_path_so_file (NULL)
+{
+}
+
+/* Do the real work of creating the on-disk tempdir.
+ We do this here, rather than in the jit::tempdir constructor
+ so that we can handle failure without needing exceptions. */
+
+bool
+gcc::jit::tempdir::create ()
+{
+ m_path_template = make_tempdir_path_template ();
+ if (!m_path_template)
+ return false;
+
+ /* Create tempdir using mkdtemp. This is created with 0700 perms and
+ is unique. Hence no other (non-root) users should have access to
+ the paths within it. */
+ m_path_tempdir = mkdtemp (m_path_template);
+ if (!m_path_tempdir)
+ return false;
+ m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL);
+ m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL);
+ m_path_so_file = concat (m_path_tempdir, "/fake.so", NULL);
+
+ /* Success. */
+ return true;
+}
+
+/* The destructor for the jit::tempdir object, which
+ cleans up the filesystem directory and its contents
+ (unless keep_intermediates was set). */
+
+gcc::jit::tempdir::~tempdir ()
+{
+ if (m_keep_intermediates)
+ fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir);
+ else
+ {
+ /* Clean up .s/.so and tempdir. */
+ if (m_path_s_file)
+ unlink (m_path_s_file);
+ if (m_path_so_file)
+ unlink (m_path_so_file);
+ if (m_path_tempdir)
+ rmdir (m_path_tempdir);
+ }
+
+ free (m_path_template);
+ /* m_path_tempdir aliases m_path_template, or is NULL, so don't
+ attempt to free it . */
+ free (m_path_c_file);
+ free (m_path_s_file);
+ free (m_path_so_file);
+}
--- /dev/null
+/* Managing temporary directories and their content within libgccjit.so
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef JIT_TEMPDIR_H
+#define JIT_TEMPDIR_H
+
+namespace gcc {
+
+namespace jit {
+
+/* A class to keep track of the jit::playback::context's tempdir.
+
+ The tempdir has the following layout:
+
+ /tmp/libgccjit-XXXXXX/
+ ./fake.c
+ (doesn't exist, but the rest of the
+ compiler needs a source code filename)
+
+ ./fake.s
+ (created by toplev::main)
+
+ ./fake.so
+ (created by playback::context::convert_to_dso).
+
+ It is normally deleted from the filesystem in the playback::context's
+ dtor, unless GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES was set. */
+
+class tempdir
+{
+ public:
+ tempdir (int keep_intermediates);
+ ~tempdir ();
+
+ bool create ();
+
+ const char * get_path () const { return m_path_tempdir; }
+ const char * get_path_c_file () const { return m_path_c_file; }
+ const char * get_path_s_file () const { return m_path_s_file; }
+ const char * get_path_so_file () const { return m_path_so_file; }
+
+ private:
+ /* Was GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES set? If so, keep the
+ on-disk tempdir around after this wrapper object goes away. */
+ int m_keep_intermediates;
+
+ /* Allocated using xmalloc (by xstrdup). */
+ char *m_path_template;
+
+ /* This either aliases m_path_template, or is NULL. */
+ char *m_path_tempdir;
+
+ /* The following are allocated using xmalloc. */
+ char *m_path_c_file;
+ char *m_path_s_file;
+ char *m_path_so_file;
+
+};
+
+} // namespace gcc::jit
+
+} // namespace gcc
+
+#endif /* JIT_TEMPDIR_H */