ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/libcpjit/cpjit.C
(Generate patch)

Comparing cvsroot/libcpjit/cpjit.C (file contents):
Revision 1.9 by root, Fri Oct 14 02:34:13 2005 UTC vs.
Revision 1.10 by root, Fri Oct 14 23:40:24 2005 UTC

28#include <cstdarg> 28#include <cstdarg>
29#include <cstdio> 29#include <cstdio>
30#include <cstring> 30#include <cstring>
31#include <cerrno> 31#include <cerrno>
32 32
33#include <iostream>
33#include <sstream> 34#include <sstream>
34#include <fstream> 35#include <fstream>
35#include <stdexcept> 36#include <stdexcept>
36#include <iomanip> 37#include <iomanip>
37 38
48#include <dlfcn.h> 49#include <dlfcn.h>
49 50
50#define STR_(str) #str 51#define STR_(str) #str
51#define STR(str) STR_(str) 52#define STR(str) STR_(str)
52 53
54#define IDX_VERSION 1
55
53namespace cpjit 56namespace cpjit
54{ 57{
58
59using namespace std;
55 60
56const char typestr<U8 >::str[] = "unsigned " STR(TYPE_INT8); 61const char typestr<U8 >::str[] = "unsigned " STR(TYPE_INT8);
57const char typestr<U16 >::str[] = "unsigned " STR(TYPE_INT16); 62const char typestr<U16 >::str[] = "unsigned " STR(TYPE_INT16);
58const char typestr<U32 >::str[] = "unsigned " STR(TYPE_INT32); 63const char typestr<U32 >::str[] = "unsigned " STR(TYPE_INT32);
59const char typestr<U64 >::str[] = "unsigned " STR(TYPE_INT64); 64const char typestr<U64 >::str[] = "unsigned " STR(TYPE_INT64);
80///////////////////////////////////////////////////////////////////////////// 85/////////////////////////////////////////////////////////////////////////////
81 86
82struct digest : md5_ctx 87struct digest : md5_ctx
83{ 88{
84 digest (); 89 digest ();
85 void operator ()(const std::string &data); 90 void operator ()(const string &data);
86 operator std::string(); 91 operator string();
87}; 92};
88 93
89digest::digest () 94digest::digest ()
90{ 95{
91 md5_init_ctx (this); 96 md5_init_ctx (this);
92} 97}
93 98
94void digest::operator ()(const std::string &data) 99void digest::operator ()(const string &data)
95{ 100{
96 md5_process_bytes (data.c_str (), data.size (), this); 101 md5_process_bytes (data.c_str (), data.size (), this);
97} 102}
98 103
99digest::operator std::string () 104digest::operator string ()
100{ 105{
101 unsigned char data[16]; 106 unsigned char data[16];
102 std::ostringstream s; 107 std::ostringstream s;
103 108
104 md5_finish_ctx (this, data); 109 md5_finish_ctx (this, data);
110} 115}
111 116
112///////////////////////////////////////////////////////////////////////////// 117/////////////////////////////////////////////////////////////////////////////
113 118
114static inline bool 119static inline bool
115is_null (const std::string &s) 120is_null (const string &s)
116{ 121{
117 return s.empty (); 122 return s.empty ();
118} 123}
119 124
120///////////////////////////////////////////////////////////////////////////// 125/////////////////////////////////////////////////////////////////////////////
141 FATAL ("could not get file stamp"); 146 FATAL ("could not get file stamp");
142 147
143 return (long)st.st_mtime; 148 return (long)st.st_mtime;
144} 149}
145 150
146static void set_stamp (const std::string &path, long stamp) 151static void set_stamp (const string &path, long stamp)
147{ 152{
148 struct utimbuf ut; 153 struct utimbuf ut;
149 154
150 ut.actime = stamp; 155 ut.actime = stamp;
151 ut.modtime = stamp; 156 ut.modtime = stamp;
152 157
153 if (utime (path.c_str (), &ut)) 158 if (utime (path.c_str (), &ut))
154 FATAL ("could not set file stamp"); 159 FATAL ("could not set file stamp");
155} 160}
156 161
157env::env (const std::string &path, bool temporary) 162env::env (const string &path, bool temporary)
158: path(path), temporary(temporary) 163: path(path), temporary(temporary)
159{ 164{
165 bool create;
160 mode_t oflags = O_RDWR | O_EXCL; 166 mode_t oflags = O_RDWR | O_EXCL;
161 167
162 if (is_null (path)) 168 if (is_null (path))
163 { 169 {
170 temporary = true;
164 this->path = tmpnam (0); 171 this->path = tmpnam (0);
165
166 temporary = true;
167 } 172 }
168 173
169 if (mkdir (this->path.c_str (), 0777) == 0) 174 create = mkdir (this->path.c_str (), 0777) == 0;
170 oflags |= O_CREAT; 175
171 else 176 if (!create && temporary)
172 if (temporary)
173 FATAL ("error while creating libcpjit temporary directory" << ERRNO); 177 FATAL ("error while creating libcpjit temporary directory" << ERRNO);
174 178
175 idxpath = this->path + "/libcpjit.idx"; 179 idxpath = this->path + "/libcpjit.idx";
176 idxfd = open (idxpath.c_str (), oflags, 0666); 180 idxfd = open (idxpath.c_str (), O_RDWR | (create ? O_CREAT | O_EXCL : 0), 0666);
177 if (idxfd < 0) 181 if (idxfd < 0)
178 FATAL (path << ": unable to open index file" << idxpath); 182 FATAL (path << ": unable to open index file " << idxpath);
179 183
180 lock (); 184 lock ();
185
186 if (create)
187 {
188 idxstamp = get_stamp (idxfd) - 1;
189 nextid = 0;
190 save_index ();
191 }
192
181 load_index (); 193 load_index ();
194 unlock ();
182 compact (); 195 compact ();
183 unlock ();
184} 196}
185 197
186env::~env () 198env::~env ()
187{ 199{
188 if (temporary) 200 if (temporary)
199 while ((de = readdir (dir))) 211 while ((de = readdir (dir)))
200 { 212 {
201 if (de->d_name [0] == '.') 213 if (de->d_name [0] == '.')
202 continue; 214 continue;
203 215
204 std::string f = path + "/" + de->d_name; 216 string f = path + "/" + de->d_name;
205 unlink (f.c_str ()); 217 unlink (f.c_str ());
206 } 218 }
207 219
208 closedir (dir); 220 closedir (dir);
209 } 221 }
234void env::unlock () 246void env::unlock ()
235{ 247{
236 dolock (false); 248 dolock (false);
237} 249}
238 250
239void 251bool
240env::load_index () 252env::load_index ()
241{ 253{
242 // caller must lock() 254 // caller must lock()
243 255
244 long stamp = get_stamp (idxfd); 256 long stamp = get_stamp (idxfd);
245 257
246 if (stamp == idxstamp) 258 if (stamp == idxstamp)
247 return; 259 return false;
248 260
249 idxstamp = stamp; 261 idxstamp = stamp;
250 262
251 // ... TODO 263 fstream f (idxpath.c_str (), ios::in);
252 264
265 if (!f)
266 FATAL (idxpath << ": unable to read index" << ERRNO);
267
268 f >> nextid;
269
270 if (nextid != IDX_VERSION)
271 FATAL (idxpath << ": index file corrupted");
272
273 f >> nextid;
274
275 id2file.clear ();
276
277 while (f)
278 {
279 string id; f >> id;
280
281 if (id == "-")
282 break;
283
284 string fileid; f >> fileid;
285
286 id2file [id] = fileid;
287
288 }
289
290 string end; f >> end;
291
292 if (end != "__end__" || !f)
293 FATAL (idxpath << ": index file corrupted");
294
295 f.close ();
296
297 return true;
253} 298}
254 299
255void 300void
256env::save_index () 301env::save_index ()
257{ 302{
258 // caller must lock()+load_index() 303 // caller must lock()+load_index()
259 304
260 // ... TODO 305 std::fstream f (idxpath.c_str ());
306
307 if (!f)
308 FATAL (idxpath << ": unable to write index" << ERRNO);
309
310 f << IDX_VERSION << "\n"
311 << nextid << "\n";
312
313 for (map<string, string>::const_iterator i = id2file.begin ();
314 i != id2file.end ();
315 ++i)
316 f << (*i).first << " " << (*i).second << "\n";
317
318 f << "-\n";
319 f << "__end__\n";
320
321 f.close ();
322
261 set_stamp (idxpath, ++idxstamp); 323 set_stamp (idxpath, ++idxstamp);
262} 324}
263 325
264void 326void
265env::compact () 327env::compact ()
266{ 328{
329 lock ();
330 save_index ();
331 unlock ();
267} 332}
268 333
269///////////////////////////////////////////////////////////////////////////// 334void env::register_fragment (const string &id, const string &source)
335{
336 fragments.push_back (pair<string, string> (id, source));
337}
270 338
339void *env::dlsym (const string &id, const char *symbol)
340{
341 assert (id2file.find (id) != id2file.end ());
342
343 const string &fileid = id2file [id];
344
345 void *so;
346
347 // load so
348 if (file2so.find (fileid) == file2so.end ())
349 {
350 string sopath = path + "/" + fileid + ".so";
351
352 so = dlopen (sopath.c_str (), RTLD_LAZY | RTLD_GLOBAL);
353 if (!so)
354 FATAL (sopath << ": so file should be there but isn't" << ERRNO);
355 }
356 else
357 so = file2so [fileid];
358
359 return ::dlsym (so, symbol);
360}
361
362void *env::sym (const string &id, const char *symbol)
363{
364 // not yet compiled?
365 if (id2file.find (id) == id2file.end ())
366 {
367 lock ();
368
369 // nobody else compiled it?
370 if (!load_index () || id2file.find (id) == id2file.end ())
371 {
372 ostringstream sfile;
373 sfile << nextid++;
374 string fileid = sfile.str ();
375 string base = path + "/" + fileid;
376
377 string fc = base + ".c";
378 string fo = base + ".o";
379 string fso = base + ".so";
380
381 std::ofstream f (fc.c_str ());
382
383 for (vector< pair<string, string> >::const_iterator i = fragments.begin ();
384 i != fragments.end ();
385 ++i)
386 if (id2file.find ((*i).first) == id2file.end ())
387 {
388 f << "#line 1 \"" << (*i).first << "\"\n"
389 << (*i).second << "\n";
390
391 id2file [(*i).first] = fileid;
392 }
393
394 f.close ();
395
396 fragments.clear ();
397
398 system (("gcc -O6 -c -o " + fo + " " + fc).c_str ());
399
400 //unlink (fc.c_str ());
401
402 system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ());
403
404 printf ("%s\n", fso.c_str ());
405
406#if 0
407 void *so = dlopen (fso.c_str (), RTLD_LAZY);
408 assert (so);
409
410 funptr = dlsym (so, id.c_str ());
411 assert (funptr);
412#endif
413
414 save_index ();
415 }
416
417 unlock ();
418 }
419
420 void *p = dlsym (id, symbol);
421
422 if (!p)
423 {
424 lock ();
425 load_index ();
426 unlock ();
427 p = dlsym (id, symbol);
428 }
429
430 if (!p)
431 FATAL ("symbol " << id << ":" << symbol << " not where it should be");
432
433 return p;
434}
435
436/////////////////////////////////////////////////////////////////////////////
437
271fun::fun (env &e, const std::string &id, const std::string &source) 438fun::fun (env &e, const string &id, const string &source)
272: e(e), id(id), source(source), funptr(0) 439: e(e), id(id), funptr(0)
273{ 440{
441 e.register_fragment (id, source);
274} 442}
275 443
276void *fun::ptr () 444void *fun::ptr ()
277{ 445{
278 if (!funptr) 446 if (!funptr)
279 {
280 e.lock ();
281 e.load_index ();
282
283 std::string base = e.path + "/" + id;
284
285 std::string fc = base + ".c";
286 std::string fo = base + ".o";
287 std::string fso = base + ".so";
288 std::string fa = base + ".a";
289
290 std::ofstream f (fc.c_str ());
291 f << source;
292 f.close ();
293
294 system (("gcc -O6 -c -o " + fo + " " + fc).c_str ());
295
296 unlink (fc.c_str ());
297
298 system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ());
299
300 printf ("%s\n", fso.c_str ());
301
302 void *so = dlopen (fso.c_str (), RTLD_LAZY);
303 assert (so);
304
305 funptr = dlsym (so, id.c_str ()); 447 funptr = e.sym (id, id.c_str ());
306 assert (funptr);
307
308 e.save_index ();
309 e.unlock ();
310 }
311 448
312 return funptr; 449 return funptr;
313} 450}
314 451
315///////////////////////////////////////////////////////////////////////////// 452/////////////////////////////////////////////////////////////////////////////
337 474
338 arglist = argl.str (); 475 arglist = argl.str ();
339} 476}
340 477
341void 478void
342funbuild::finish (std::string &id, std::string &source) 479funbuild::finish (string &id, string &source)
343{ 480{
344 digest dgst; 481 digest dgst;
345 482
346 dgst (retlist); 483 dgst (retlist);
347 dgst (arglist); 484 dgst (arglist);
348 dgst (str ()); 485 dgst (str ());
349 486
350 id = "f_" + (std::string) dgst; 487 id = "f_" + (string) dgst;
351 488
352 std::ostringstream o; 489 std::ostringstream o;
353 o << retlist << " " << id << " (" << arglist << ")\n{\n" << str () << "\n}\n"; 490 o << retlist << " " << id << " (" << arglist << ")\n{\n" << str () << "\n}\n";
354 source = o.str (); 491 source = o.str ();
355} 492}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines