ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/libcpjit/cpjit.C
Revision: 1.4
Committed: Fri Oct 14 00:21:57 2005 UTC (21 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.3: +108 -21 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     struct digest
80     {
81     unsigned char data[16];
82    
83     digest (const std::string &str);
84     operator std::string();
85     };
86    
87     digest::digest (const std::string &str)
88     {
89     MD5_CTX ctx;
90     MD5Init (&ctx);
91     MD5Update (&ctx, (const unsigned char *)str.c_str (), str.size ());
92     MD5Final (&ctx);
93    
94     memcpy (data, ctx.digest, sizeof (data));
95     }
96    
97     digest::operator std::string ()
98     {
99     std::ostringstream s;
100    
101     for (int i = 0; i < 15; i++)
102     s << std::setfill ('0') << std::hex << std::setw (2) << (int)data [i];
103    
104     return s.str ();
105     }
106 root 1.1
107 root 1.2 static inline bool
108     is_null (const std::string &s)
109     {
110     return s.empty ();
111     }
112    
113 root 1.4 // error exception builder
114     struct error : std::ostringstream
115     {
116     ~error ()
117     {
118     throw std::runtime_error (str ());
119     }
120     };
121    
122     #define FATAL(msg) do { error o; o << msg << std::endl; } while (0)
123     #define ERRNO " (" << strerror (errno) << ")"
124    
125 root 1.2 env::env (const std::string &path, bool temporary)
126     : path(path), temporary(temporary)
127     {
128     if (is_null (path))
129     {
130     this->path = tmpnam (0);
131    
132     if (mkdir (this->path.c_str (), 0777))
133 root 1.4 FATAL ("error while creating libcpjit temporary directory" << ERRNO);
134 root 1.2
135     temporary = true;
136     }
137    
138 root 1.4 std::string index = this->path + "/libcpjit.idx";
139    
140     idxfd = open (index.c_str (), O_RDWR|O_CREAT, 0666);
141    
142     if (idxfd < 0)
143     FATAL (path << ": unable to open index file" << index);
144    
145     lock ();
146     load_index ();
147     unlock ();
148 root 1.2
149 root 1.4 nextid = 0;
150 root 1.2 }
151    
152     env::~env ()
153     {
154     if (temporary)
155     {
156     DIR *dir = opendir (path.c_str ());
157    
158     if (dir)
159     {
160     struct dirent *de;
161     while ((de = readdir (dir)))
162     {
163     if (de->d_name [0] == '.')
164     continue;
165    
166     std::string f = path + "/" + de->d_name;
167     unlink (f.c_str ());
168     }
169    
170     closedir (dir);
171     }
172    
173     if (rmdir (path.c_str ()))
174 root 1.4 FATAL (path << ": unable to remove libcpjit temporary directory" << ERRNO);
175 root 1.2 }
176     }
177    
178 root 1.4 void env::dolock (bool lock)
179     {
180     struct flock fl;
181    
182     fl.l_type = lock ? F_WRLCK : F_UNLCK;
183     fl.l_whence = SEEK_SET;
184     fl.l_start = 0;
185     fl.l_len = 0;
186    
187     while (fcntl (idxfd, F_SETLKW, &fl) < 0)
188     if (errno != EINTR)
189     FATAL (path << ": unable to lock index file" << ERRNO);
190     }
191    
192     void env::lock ()
193     {
194     dolock (true);
195     }
196    
197     void env::unlock ()
198     {
199     dolock (false);
200     }
201    
202     void
203     env::load_index ()
204     {
205     std::ifstream f ((this->path + "/libcpjit.idx").c_str ());
206     assert (("not a cpjit directory", f));
207     f.close ();
208     }
209    
210 root 1.2 std::string
211     env::genid ()
212     {
213     std::ostringstream os;
214    
215     os << "i" << ++nextid;
216     return os.str ();
217     }
218    
219 root 1.1 fun::fun (env &e, const idstr &id)
220 root 1.2 : e(e), id(id), funptr(0)
221     {
222     }
223    
224 root 1.3 void fun::set_source (const std::string source)
225     {
226     this->source = source;
227     }
228    
229 root 1.2 void *fun::ptr ()
230 root 1.1 {
231 root 1.2 if (!funptr)
232     {
233 root 1.4 std::string base = e.path + "/" + (std::string) digest (source);
234    
235     std::string fc = base + ".c";
236     std::string fo = base + ".o";
237     std::string fso = base + ".so";
238     std::string fa = base + ".a";
239 root 1.2
240     std::ofstream f (fc.c_str ());
241     f << source;
242     f.close ();
243    
244     system (("gcc -O6 -c -o " + fo + " " + fc).c_str ());
245    
246     unlink (fc.c_str ());
247    
248     system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ());
249    
250 root 1.4 printf ("%s\n", fso.c_str ());
251     sleep (10);
252    
253 root 1.2 void *so = dlopen (fso.c_str (), RTLD_LAZY);
254     assert (so);
255    
256     funptr = dlsym (so, id.c_str ());
257     assert (funptr);
258     }
259    
260     return funptr;
261 root 1.1 }
262    
263     funbuild::funbuild (env &e, const idstr &id, const char *rettype, ...)
264     : e(e), id(id)
265     {
266 root 1.3 std::ostringstream hdrs;
267    
268 root 1.2 if (is_null (id))
269     this->id = e.genid ();
270    
271 root 1.3 hdrs << rettype << " " << this->id << "(";
272 root 1.1
273     va_list ap;
274     va_start (ap, rettype);
275    
276     int args = 0;
277     while ((rettype = va_arg (ap, const char *)))
278     {
279     if (args++)
280 root 1.3 hdrs << ", ";
281 root 1.1
282 root 1.3 hdrs << rettype << " a" << args;
283 root 1.1 }
284    
285     va_end (ap);
286    
287 root 1.3 hdrs << ")\n{\n";
288    
289     hdr = hdrs.str ();
290 root 1.1 }
291    
292 root 1.3 std::string
293 root 1.1 funbuild::finish ()
294     {
295     *this << "\n}\n";
296 root 1.3
297     return hdr + str ();
298 root 1.1 }
299    
300     }