/* cpjit.C -- c portable jit in time compiler Copyright (C) 2005 Marc Lehmann This file is part of libcpjit. libcpjit 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 2 of the License, or (at your option) any later version. This program 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 gvpe; if not, write to the Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "cpjit.h" #include #include #include #include #include #include #include #include #include #include #define STR_(str) #str #define STR(str) STR_(str) namespace cpjit { const char typestr::str[] = "unsigned " STR(TYPE_INT8); const char typestr::str[] = "unsigned " STR(TYPE_INT16); const char typestr::str[] = "unsigned " STR(TYPE_INT32); const char typestr::str[] = "unsigned " STR(TYPE_INT64); const char typestr::str[] = "signed " STR(TYPE_INT8); const char typestr::str[] = STR(TYPE_INT16); const char typestr::str[] = STR(TYPE_INT32); const char typestr::str[] = STR(TYPE_INT64); const char typestr::str[] = "float"; const char typestr::str[] = "double"; const char typestr::str[] = "void" " *"; const char typestr::str[] = "unsigned " STR(TYPE_INT8) " *"; const char typestr::str[] = "unsigned " STR(TYPE_INT16) " *"; const char typestr::str[] = "unsigned " STR(TYPE_INT32) " *"; const char typestr::str[] = "unsigned " STR(TYPE_INT64) " *"; const char typestr::str[] = "signed " STR(TYPE_INT8) " *"; const char typestr::str[] = STR(TYPE_INT16) " *"; const char typestr::str[] = STR(TYPE_INT32) " *"; const char typestr::str[] = STR(TYPE_INT64) " *"; const char typestr::str[] = "float" " *"; const char typestr::str[] = "double" " *"; static inline bool is_null (const std::string &s) { return s.empty (); } env::env (const std::string &path, bool temporary) : path(path), temporary(temporary) { if (is_null (path)) { this->path = tmpnam (0); if (mkdir (this->path.c_str (), 0777)) { perror ("libcpjit temporary directory"); exit (1); } std::ofstream f ((this->path + "/libcpjit").c_str ()); temporary = true; } std::ifstream f ((this->path + "/libcpjit").c_str ()); assert (("not a cpjit directory", f)); f.close (); if (temporary) nextid = 0; else abort (); // fetch from database } env::~env () { if (temporary) { DIR *dir = opendir (path.c_str ()); if (dir) { struct dirent *de; while ((de = readdir (dir))) { if (de->d_name [0] == '.') continue; std::string f = path + "/" + de->d_name; unlink (f.c_str ()); } closedir (dir); } if (rmdir (path.c_str ())) perror ("unable to remove libcpjit temporary directory"); } } std::string env::genid () { std::ostringstream os; os << "i" << ++nextid; return os.str (); } fun::fun (env &e, const idstr &id) : e(e), id(id), funptr(0) { } void *fun::ptr () { if (!funptr) { std::string fc = e.path + "/x.c"; std::string fo = e.path + "/x.o"; std::string fso = e.path + "/x.so"; std::ofstream f (fc.c_str ()); f << source; f.close (); system (("gcc -O6 -c -o " + fo + " " + fc).c_str ()); unlink (fc.c_str ()); system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ()); void *so = dlopen (fso.c_str (), RTLD_LAZY); assert (so); funptr = dlsym (so, id.c_str ()); assert (funptr); } return funptr; } funbuild::funbuild (env &e, const idstr &id, const char *rettype, ...) : e(e), id(id) { if (is_null (id)) this->id = e.genid (); *this << rettype << " " << this->id << "("; va_list ap; va_start (ap, rettype); int args = 0; while ((rettype = va_arg (ap, const char *))) { if (args++) *this << ", "; *this << rettype << " a" << args; } va_end (ap); *this << ")\n{\n"; } void funbuild::finish () { *this << "\n}\n"; } }