… | |
… | |
74 | const char typestr<I32 *>::str[] = STR(TYPE_INT32) " *"; |
74 | const char typestr<I32 *>::str[] = STR(TYPE_INT32) " *"; |
75 | const char typestr<I64 *>::str[] = STR(TYPE_INT64) " *"; |
75 | const char typestr<I64 *>::str[] = STR(TYPE_INT64) " *"; |
76 | const char typestr<FLT *>::str[] = "float" " *"; |
76 | const char typestr<FLT *>::str[] = "float" " *"; |
77 | const char typestr<DBL *>::str[] = "double" " *"; |
77 | const char typestr<DBL *>::str[] = "double" " *"; |
78 | |
78 | |
79 | struct digest |
79 | struct digest : md5_ctx |
80 | { |
80 | { |
81 | unsigned char data[16]; |
81 | digest (); |
82 | |
82 | void operator ()(const std::string &data); |
83 | digest (const std::string &str); |
|
|
84 | operator std::string(); |
83 | operator std::string(); |
85 | }; |
84 | }; |
86 | |
85 | |
87 | digest::digest (const std::string &str) |
86 | digest::digest () |
88 | { |
87 | { |
89 | MD5_CTX ctx; |
88 | md5_init_ctx (this); |
90 | MD5Init (&ctx); |
89 | } |
91 | MD5Update (&ctx, (const unsigned char *)str.c_str (), str.size ()); |
|
|
92 | MD5Final (&ctx); |
|
|
93 | |
90 | |
94 | memcpy (data, ctx.digest, sizeof (data)); |
91 | void digest::operator ()(const std::string &data) |
|
|
92 | { |
|
|
93 | md5_process_bytes (data.c_str (), data.size (), this); |
95 | } |
94 | } |
96 | |
95 | |
97 | digest::operator std::string () |
96 | digest::operator std::string () |
98 | { |
97 | { |
|
|
98 | unsigned char data[16]; |
99 | std::ostringstream s; |
99 | std::ostringstream s; |
100 | |
100 | |
|
|
101 | md5_finish_ctx (this, data); |
|
|
102 | |
101 | for (int i = 0; i < 15; i++) |
103 | for (int i = 0; i < 16; i++) |
102 | s << std::setfill ('0') << std::hex << std::setw (2) << (int)data [i]; |
104 | s << std::setfill ('0') << std::hex << std::setw (2) << (int)data [i]; |
103 | |
105 | |
104 | return s.str (); |
106 | return s.str (); |
105 | } |
107 | } |
106 | |
108 | |
… | |
… | |
143 | FATAL (path << ": unable to open index file" << index); |
145 | FATAL (path << ": unable to open index file" << index); |
144 | |
146 | |
145 | lock (); |
147 | lock (); |
146 | load_index (); |
148 | load_index (); |
147 | unlock (); |
149 | unlock (); |
148 | |
|
|
149 | nextid = 0; |
|
|
150 | } |
150 | } |
151 | |
151 | |
152 | env::~env () |
152 | env::~env () |
153 | { |
153 | { |
154 | if (temporary) |
154 | if (temporary) |
|
|
155 | clear (); |
|
|
156 | } |
|
|
157 | |
|
|
158 | void env::clear () |
|
|
159 | { |
|
|
160 | DIR *dir = opendir (path.c_str ()); |
|
|
161 | |
|
|
162 | if (dir) |
155 | { |
163 | { |
156 | DIR *dir = opendir (path.c_str ()); |
164 | struct dirent *de; |
157 | |
165 | while ((de = readdir (dir))) |
158 | if (dir) |
|
|
159 | { |
166 | { |
160 | struct dirent *de; |
|
|
161 | while ((de = readdir (dir))) |
|
|
162 | { |
|
|
163 | if (de->d_name [0] == '.') |
167 | if (de->d_name [0] == '.') |
164 | continue; |
168 | continue; |
165 | |
169 | |
166 | std::string f = path + "/" + de->d_name; |
170 | std::string f = path + "/" + de->d_name; |
167 | unlink (f.c_str ()); |
171 | unlink (f.c_str ()); |
168 | } |
|
|
169 | |
|
|
170 | closedir (dir); |
|
|
171 | } |
172 | } |
172 | |
173 | |
173 | if (rmdir (path.c_str ())) |
174 | closedir (dir); |
174 | FATAL (path << ": unable to remove libcpjit temporary directory" << ERRNO); |
|
|
175 | } |
175 | } |
|
|
176 | |
|
|
177 | if (rmdir (path.c_str ())) |
|
|
178 | FATAL (path << ": unable to remove libcpjit directory" << ERRNO); |
176 | } |
179 | } |
177 | |
180 | |
178 | void env::dolock (bool lock) |
181 | void env::dolock (bool lock) |
179 | { |
182 | { |
180 | struct flock fl; |
183 | struct flock fl; |
… | |
… | |
205 | std::ifstream f ((this->path + "/libcpjit.idx").c_str ()); |
208 | std::ifstream f ((this->path + "/libcpjit.idx").c_str ()); |
206 | assert (("not a cpjit directory", f)); |
209 | assert (("not a cpjit directory", f)); |
207 | f.close (); |
210 | f.close (); |
208 | } |
211 | } |
209 | |
212 | |
210 | std::string |
213 | void |
211 | env::genid () |
214 | env::save_index () |
212 | { |
215 | { |
213 | std::ostringstream os; |
216 | std::ifstream f ((this->path + "/libcpjit.idx").c_str ()); |
214 | |
217 | assert (("not a cpjit directory", f)); |
215 | os << "i" << ++nextid; |
218 | f.close (); |
216 | return os.str (); |
|
|
217 | } |
219 | } |
218 | |
220 | |
219 | fun::fun (env &e, const idstr &id) |
221 | fun::fun (env &e, const std::string &id, const std::string &source) |
220 | : e(e), id(id), funptr(0) |
222 | : e(e), id(id), source(source), funptr(0) |
221 | { |
223 | { |
222 | } |
|
|
223 | |
|
|
224 | void fun::set_source (const std::string source) |
|
|
225 | { |
|
|
226 | this->source = source; |
|
|
227 | } |
224 | } |
228 | |
225 | |
229 | void *fun::ptr () |
226 | void *fun::ptr () |
230 | { |
227 | { |
231 | if (!funptr) |
228 | if (!funptr) |
232 | { |
229 | { |
233 | std::string base = e.path + "/" + (std::string) digest (source); |
230 | e.lock (); |
|
|
231 | e.load_index (); |
|
|
232 | |
|
|
233 | std::string base = e.path + "/" + id; |
234 | |
234 | |
235 | std::string fc = base + ".c"; |
235 | std::string fc = base + ".c"; |
236 | std::string fo = base + ".o"; |
236 | std::string fo = base + ".o"; |
237 | std::string fso = base + ".so"; |
237 | std::string fso = base + ".so"; |
238 | std::string fa = base + ".a"; |
238 | std::string fa = base + ".a"; |
… | |
… | |
246 | unlink (fc.c_str ()); |
246 | unlink (fc.c_str ()); |
247 | |
247 | |
248 | system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ()); |
248 | system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ()); |
249 | |
249 | |
250 | printf ("%s\n", fso.c_str ()); |
250 | printf ("%s\n", fso.c_str ()); |
251 | sleep (10); |
|
|
252 | |
251 | |
253 | void *so = dlopen (fso.c_str (), RTLD_LAZY); |
252 | void *so = dlopen (fso.c_str (), RTLD_LAZY); |
254 | assert (so); |
253 | assert (so); |
255 | |
254 | |
256 | funptr = dlsym (so, id.c_str ()); |
255 | funptr = dlsym (so, id.c_str ()); |
257 | assert (funptr); |
256 | assert (funptr); |
|
|
257 | |
|
|
258 | e.save_index (); |
|
|
259 | e.unlock (); |
258 | } |
260 | } |
259 | |
261 | |
260 | return funptr; |
262 | return funptr; |
261 | } |
263 | } |
262 | |
264 | |
263 | funbuild::funbuild (env &e, const idstr &id, const char *rettype, ...) |
265 | funbuild::funbuild (env &e, const char *rettype, ...) |
264 | : e(e), id(id) |
266 | : e(e) |
265 | { |
267 | { |
|
|
268 | retlist = rettype; |
|
|
269 | |
266 | std::ostringstream hdrs; |
270 | std::ostringstream argl; |
267 | |
|
|
268 | if (is_null (id)) |
|
|
269 | this->id = e.genid (); |
|
|
270 | |
|
|
271 | hdrs << rettype << " " << this->id << "("; |
|
|
272 | |
271 | |
273 | va_list ap; |
272 | va_list ap; |
274 | va_start (ap, rettype); |
273 | va_start (ap, rettype); |
275 | |
274 | |
276 | int args = 0; |
275 | int args = 0; |
277 | while ((rettype = va_arg (ap, const char *))) |
276 | while ((rettype = va_arg (ap, const char *))) |
278 | { |
277 | { |
279 | if (args++) |
278 | if (args++) |
280 | hdrs << ", "; |
279 | argl << ", "; |
281 | |
280 | |
282 | hdrs << rettype << " a" << args; |
281 | argl << rettype << " a" << args; |
283 | } |
282 | } |
284 | |
283 | |
285 | va_end (ap); |
284 | va_end (ap); |
286 | |
285 | |
287 | hdrs << ")\n{\n"; |
286 | arglist = argl.str (); |
288 | |
|
|
289 | hdr = hdrs.str (); |
|
|
290 | } |
287 | } |
291 | |
288 | |
292 | std::string |
289 | void |
293 | funbuild::finish () |
290 | funbuild::finish (std::string &id, std::string &source) |
294 | { |
291 | { |
295 | *this << "\n}\n"; |
292 | digest dgst; |
296 | |
293 | |
297 | return hdr + str (); |
294 | dgst (retlist); |
298 | } |
295 | dgst (arglist); |
|
|
296 | dgst (str ()); |
299 | |
297 | |
|
|
298 | id = "f_" + (std::string) dgst; |
|
|
299 | |
|
|
300 | std::ostringstream o; |
|
|
301 | o << retlist << " " << id << " (" << arglist << ")\n{\n" << str () << "\n}\n"; |
|
|
302 | source = o.str (); |
300 | } |
303 | } |
|
|
304 | |
|
|
305 | } |