ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/libcpjit/cpjit.C
Revision: 1.6
Committed: Fri Oct 14 01:37:18 2005 UTC (18 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.5: +9 -7 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     cpjit.C -- c portable jit in time compiler
3     Copyright (C) 2005 Marc Lehmann <cpjit@schmorp.de>
4    
5     This file is part of libcpjit.
6    
7     libcpjit is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with gvpe; if not, write to the Free Software
19     Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20     */
21    
22     #include "config.h"
23    
24     #include "cpjit.h"
25    
26 root 1.2 #include <cassert>
27     #include <cstdlib>
28 root 1.1 #include <cstdarg>
29 root 1.2 #include <cstdio>
30 root 1.4 #include <cstring>
31     #include <cerrno>
32    
33 root 1.1 #include <sstream>
34 root 1.2 #include <fstream>
35 root 1.4 #include <stdexcept>
36     #include <iomanip>
37    
38     #include <unistd.h>
39     #include <fcntl.h> // for locking
40 root 1.2
41     #include <sys/stat.h>
42     #include <sys/types.h>
43     #include <dirent.h>
44    
45 root 1.4 #include "md5.h"
46    
47 root 1.2 #include <dlfcn.h>
48 root 1.1
49     #define STR_(str) #str
50     #define STR(str) STR_(str)
51    
52     namespace cpjit
53     {
54    
55     const char typestr<U8 >::str[] = "unsigned " STR(TYPE_INT8);
56     const char typestr<U16 >::str[] = "unsigned " STR(TYPE_INT16);
57     const char typestr<U32 >::str[] = "unsigned " STR(TYPE_INT32);
58     const char typestr<U64 >::str[] = "unsigned " STR(TYPE_INT64);
59 root 1.2 const char typestr<I8 >::str[] = "signed " STR(TYPE_INT8);
60     const char typestr<I16 >::str[] = STR(TYPE_INT16);
61     const char typestr<I32 >::str[] = STR(TYPE_INT32);
62     const char typestr<I64 >::str[] = STR(TYPE_INT64);
63 root 1.4 const char typestr<FLT >::str[] = "float";
64     const char typestr<DBL >::str[] = "double";
65 root 1.1
66 root 1.2 const char typestr<PTR >::str[] = "void" " *";
67    
68 root 1.1 const char typestr<U8 *>::str[] = "unsigned " STR(TYPE_INT8) " *";
69     const char typestr<U16 *>::str[] = "unsigned " STR(TYPE_INT16) " *";
70     const char typestr<U32 *>::str[] = "unsigned " STR(TYPE_INT32) " *";
71     const char typestr<U64 *>::str[] = "unsigned " STR(TYPE_INT64) " *";
72 root 1.2 const char typestr<I8 *>::str[] = "signed " STR(TYPE_INT8) " *";
73     const char typestr<I16 *>::str[] = STR(TYPE_INT16) " *";
74     const char typestr<I32 *>::str[] = STR(TYPE_INT32) " *";
75     const char typestr<I64 *>::str[] = STR(TYPE_INT64) " *";
76 root 1.4 const char typestr<FLT *>::str[] = "float" " *";
77     const char typestr<DBL *>::str[] = "double" " *";
78    
79 root 1.5 struct digest : md5_ctx
80 root 1.4 {
81 root 1.5 digest ();
82     void operator ()(const std::string &data);
83 root 1.4 operator std::string();
84     };
85    
86 root 1.5 digest::digest ()
87 root 1.4 {
88 root 1.5 md5_init_ctx (this);
89     }
90 root 1.4
91 root 1.5 void digest::operator ()(const std::string &data)
92     {
93     md5_process_bytes (data.c_str (), data.size (), this);
94 root 1.4 }
95    
96     digest::operator std::string ()
97     {
98 root 1.5 unsigned char data[16];
99 root 1.4 std::ostringstream s;
100    
101 root 1.5 md5_finish_ctx (this, data);
102    
103     for (int i = 0; i < 16; i++)
104 root 1.4 s << std::setfill ('0') << std::hex << std::setw (2) << (int)data [i];
105    
106     return s.str ();
107     }
108 root 1.1
109 root 1.2 static inline bool
110     is_null (const std::string &s)
111     {
112     return s.empty ();
113     }
114    
115 root 1.4 // error exception builder
116     struct error : std::ostringstream
117     {
118     ~error ()
119     {
120     throw std::runtime_error (str ());
121     }
122     };
123    
124     #define FATAL(msg) do { error o; o << msg << std::endl; } while (0)
125     #define ERRNO " (" << strerror (errno) << ")"
126    
127 root 1.2 env::env (const std::string &path, bool temporary)
128     : path(path), temporary(temporary)
129     {
130 root 1.6 mode_t oflags = O_RDWR | O_EXCL;
131    
132 root 1.2 if (is_null (path))
133     {
134     this->path = tmpnam (0);
135    
136     temporary = true;
137     }
138    
139 root 1.6 if (mkdir (this->path.c_str (), 0777) == 0)
140     oflags |= O_CREAT;
141     else
142     if (temporary)
143     FATAL ("error while creating libcpjit temporary directory" << ERRNO);
144    
145 root 1.4 std::string index = this->path + "/libcpjit.idx";
146    
147 root 1.6 idxfd = open (index.c_str (), oflags, 0666);
148 root 1.4
149     if (idxfd < 0)
150     FATAL (path << ": unable to open index file" << index);
151    
152     lock ();
153     load_index ();
154     unlock ();
155 root 1.2 }
156    
157     env::~env ()
158     {
159     if (temporary)
160 root 1.5 clear ();
161     }
162    
163     void env::clear ()
164     {
165     DIR *dir = opendir (path.c_str ());
166    
167     if (dir)
168 root 1.2 {
169 root 1.5 struct dirent *de;
170     while ((de = readdir (dir)))
171 root 1.2 {
172 root 1.5 if (de->d_name [0] == '.')
173     continue;
174 root 1.2
175 root 1.5 std::string f = path + "/" + de->d_name;
176     unlink (f.c_str ());
177 root 1.2 }
178    
179 root 1.5 closedir (dir);
180 root 1.2 }
181 root 1.5
182     if (rmdir (path.c_str ()))
183     FATAL (path << ": unable to remove libcpjit directory" << ERRNO);
184 root 1.2 }
185    
186 root 1.4 void env::dolock (bool lock)
187     {
188     struct flock fl;
189    
190     fl.l_type = lock ? F_WRLCK : F_UNLCK;
191     fl.l_whence = SEEK_SET;
192     fl.l_start = 0;
193     fl.l_len = 0;
194    
195     while (fcntl (idxfd, F_SETLKW, &fl) < 0)
196     if (errno != EINTR)
197     FATAL (path << ": unable to lock index file" << ERRNO);
198     }
199    
200     void env::lock ()
201     {
202     dolock (true);
203     }
204    
205     void env::unlock ()
206     {
207     dolock (false);
208     }
209    
210     void
211     env::load_index ()
212     {
213     }
214    
215 root 1.5 void
216     env::save_index ()
217 root 1.2 {
218 root 1.5 std::ifstream f ((this->path + "/libcpjit.idx").c_str ());
219     assert (("not a cpjit directory", f));
220     f.close ();
221 root 1.2 }
222    
223 root 1.5 fun::fun (env &e, const std::string &id, const std::string &source)
224     : e(e), id(id), source(source), funptr(0)
225 root 1.3 {
226     }
227    
228 root 1.2 void *fun::ptr ()
229 root 1.1 {
230 root 1.2 if (!funptr)
231     {
232 root 1.5 e.lock ();
233     e.load_index ();
234    
235     std::string base = e.path + "/" + id;
236 root 1.4
237     std::string fc = base + ".c";
238     std::string fo = base + ".o";
239     std::string fso = base + ".so";
240     std::string fa = base + ".a";
241 root 1.2
242     std::ofstream f (fc.c_str ());
243     f << source;
244     f.close ();
245    
246     system (("gcc -O6 -c -o " + fo + " " + fc).c_str ());
247    
248     unlink (fc.c_str ());
249    
250     system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ());
251    
252 root 1.4 printf ("%s\n", fso.c_str ());
253    
254 root 1.2 void *so = dlopen (fso.c_str (), RTLD_LAZY);
255     assert (so);
256    
257     funptr = dlsym (so, id.c_str ());
258     assert (funptr);
259 root 1.5
260     e.save_index ();
261     e.unlock ();
262 root 1.2 }
263    
264     return funptr;
265 root 1.1 }
266    
267 root 1.5 funbuild::funbuild (env &e, const char *rettype, ...)
268     : e(e)
269 root 1.1 {
270 root 1.5 retlist = rettype;
271 root 1.3
272 root 1.5 std::ostringstream argl;
273 root 1.1
274     va_list ap;
275     va_start (ap, rettype);
276    
277     int args = 0;
278     while ((rettype = va_arg (ap, const char *)))
279     {
280     if (args++)
281 root 1.5 argl << ", ";
282 root 1.1
283 root 1.5 argl << rettype << " a" << args;
284 root 1.1 }
285    
286     va_end (ap);
287    
288 root 1.5 arglist = argl.str ();
289 root 1.1 }
290    
291 root 1.5 void
292     funbuild::finish (std::string &id, std::string &source)
293 root 1.1 {
294 root 1.5 digest dgst;
295    
296     dgst (retlist);
297     dgst (arglist);
298     dgst (str ());
299    
300     id = "f_" + (std::string) dgst;
301 root 1.3
302 root 1.5 std::ostringstream o;
303     o << retlist << " " << id << " (" << arglist << ")\n{\n" << str () << "\n}\n";
304     source = o.str ();
305 root 1.1 }
306    
307     }