… | |
… | |
21 | |
21 | |
22 | #include "config.h" |
22 | #include "config.h" |
23 | |
23 | |
24 | #include "cpjit.h" |
24 | #include "cpjit.h" |
25 | |
25 | |
|
|
26 | #include <cassert> |
|
|
27 | #include <cstdlib> |
26 | #include <cstdarg> |
28 | #include <cstdarg> |
|
|
29 | #include <cstdio> |
27 | #include <sstream> |
30 | #include <sstream> |
|
|
31 | #include <fstream> |
|
|
32 | |
|
|
33 | #include <sys/stat.h> |
|
|
34 | #include <sys/types.h> |
|
|
35 | #include <dirent.h> |
|
|
36 | |
|
|
37 | #include <dlfcn.h> |
28 | |
38 | |
29 | #define STR_(str) #str |
39 | #define STR_(str) #str |
30 | #define STR(str) STR_(str) |
40 | #define STR(str) STR_(str) |
31 | |
41 | |
32 | namespace cpjit |
42 | namespace cpjit |
… | |
… | |
34 | |
44 | |
35 | const char typestr<U8 >::str[] = "unsigned " STR(TYPE_INT8); |
45 | const char typestr<U8 >::str[] = "unsigned " STR(TYPE_INT8); |
36 | const char typestr<U16 >::str[] = "unsigned " STR(TYPE_INT16); |
46 | const char typestr<U16 >::str[] = "unsigned " STR(TYPE_INT16); |
37 | const char typestr<U32 >::str[] = "unsigned " STR(TYPE_INT32); |
47 | const char typestr<U32 >::str[] = "unsigned " STR(TYPE_INT32); |
38 | const char typestr<U64 >::str[] = "unsigned " STR(TYPE_INT64); |
48 | const char typestr<U64 >::str[] = "unsigned " STR(TYPE_INT64); |
39 | const char typestr<I8 >::str[] = " signed " STR(TYPE_INT8); |
49 | const char typestr<I8 >::str[] = "signed " STR(TYPE_INT8); |
40 | const char typestr<I16 >::str[] = " signed " STR(TYPE_INT16); |
50 | const char typestr<I16 >::str[] = STR(TYPE_INT16); |
41 | const char typestr<I32 >::str[] = " signed " STR(TYPE_INT32); |
51 | const char typestr<I32 >::str[] = STR(TYPE_INT32); |
42 | const char typestr<I64 >::str[] = " signed " STR(TYPE_INT64); |
52 | const char typestr<I64 >::str[] = STR(TYPE_INT64); |
43 | const char typestr<F32 >::str[] = "float"; |
53 | const char typestr<F32 >::str[] = "float"; |
44 | const char typestr<F64 >::str[] = "double"; |
54 | const char typestr<F64 >::str[] = "double"; |
|
|
55 | |
|
|
56 | const char typestr<PTR >::str[] = "void" " *"; |
45 | |
57 | |
46 | const char typestr<U8 *>::str[] = "unsigned " STR(TYPE_INT8) " *"; |
58 | const char typestr<U8 *>::str[] = "unsigned " STR(TYPE_INT8) " *"; |
47 | const char typestr<U16 *>::str[] = "unsigned " STR(TYPE_INT16) " *"; |
59 | const char typestr<U16 *>::str[] = "unsigned " STR(TYPE_INT16) " *"; |
48 | const char typestr<U32 *>::str[] = "unsigned " STR(TYPE_INT32) " *"; |
60 | const char typestr<U32 *>::str[] = "unsigned " STR(TYPE_INT32) " *"; |
49 | const char typestr<U64 *>::str[] = "unsigned " STR(TYPE_INT64) " *"; |
61 | const char typestr<U64 *>::str[] = "unsigned " STR(TYPE_INT64) " *"; |
50 | const char typestr<I8 *>::str[] = " signed " STR(TYPE_INT8) " *"; |
62 | const char typestr<I8 *>::str[] = "signed " STR(TYPE_INT8) " *"; |
51 | const char typestr<I16 *>::str[] = " signed " STR(TYPE_INT16) " *"; |
63 | const char typestr<I16 *>::str[] = STR(TYPE_INT16) " *"; |
52 | const char typestr<I32 *>::str[] = " signed " STR(TYPE_INT32) " *"; |
64 | const char typestr<I32 *>::str[] = STR(TYPE_INT32) " *"; |
53 | const char typestr<I64 *>::str[] = " signed " STR(TYPE_INT64) " *"; |
65 | const char typestr<I64 *>::str[] = STR(TYPE_INT64) " *"; |
54 | const char typestr<F32 *>::str[] = "float" " *"; |
66 | const char typestr<F32 *>::str[] = "float" " *"; |
55 | const char typestr<F64 *>::str[] = "double" " *"; |
67 | const char typestr<F64 *>::str[] = "double" " *"; |
56 | |
68 | |
|
|
69 | static inline bool |
|
|
70 | is_null (const std::string &s) |
|
|
71 | { |
|
|
72 | return s.empty (); |
|
|
73 | } |
|
|
74 | |
|
|
75 | env::env (const std::string &path, bool temporary) |
|
|
76 | : path(path), temporary(temporary) |
|
|
77 | { |
|
|
78 | if (is_null (path)) |
|
|
79 | { |
|
|
80 | this->path = tmpnam (0); |
|
|
81 | |
|
|
82 | if (mkdir (this->path.c_str (), 0777)) |
|
|
83 | { |
|
|
84 | perror ("libcpjit temporary directory"); |
|
|
85 | exit (1); |
|
|
86 | } |
|
|
87 | |
|
|
88 | std::ofstream f ((this->path + "/libcpjit").c_str ()); |
|
|
89 | |
|
|
90 | temporary = true; |
|
|
91 | } |
|
|
92 | |
|
|
93 | std::ifstream f ((this->path + "/libcpjit").c_str ()); |
|
|
94 | assert (("not a cpjit directory", f)); |
|
|
95 | f.close (); |
|
|
96 | |
|
|
97 | if (temporary) |
|
|
98 | nextid = 0; |
|
|
99 | else |
|
|
100 | abort (); // fetch from database |
|
|
101 | } |
|
|
102 | |
|
|
103 | env::~env () |
|
|
104 | { |
|
|
105 | if (temporary) |
|
|
106 | { |
|
|
107 | DIR *dir = opendir (path.c_str ()); |
|
|
108 | |
|
|
109 | if (dir) |
|
|
110 | { |
|
|
111 | struct dirent *de; |
|
|
112 | while ((de = readdir (dir))) |
|
|
113 | { |
|
|
114 | if (de->d_name [0] == '.') |
|
|
115 | continue; |
|
|
116 | |
|
|
117 | std::string f = path + "/" + de->d_name; |
|
|
118 | unlink (f.c_str ()); |
|
|
119 | } |
|
|
120 | |
|
|
121 | closedir (dir); |
|
|
122 | } |
|
|
123 | |
|
|
124 | if (rmdir (path.c_str ())) |
|
|
125 | perror ("unable to remove libcpjit temporary directory"); |
|
|
126 | } |
|
|
127 | } |
|
|
128 | |
|
|
129 | std::string |
|
|
130 | env::genid () |
|
|
131 | { |
|
|
132 | std::ostringstream os; |
|
|
133 | |
|
|
134 | os << "i" << ++nextid; |
|
|
135 | return os.str (); |
|
|
136 | } |
|
|
137 | |
57 | fun::fun (env &e, const idstr &id) |
138 | fun::fun (env &e, const idstr &id) |
58 | : e(e), id(id) |
139 | : e(e), id(id), funptr(0) |
59 | { |
140 | { |
|
|
141 | } |
|
|
142 | |
|
|
143 | void *fun::ptr () |
|
|
144 | { |
|
|
145 | if (!funptr) |
|
|
146 | { |
|
|
147 | std::string fc = e.path + "/x.c"; |
|
|
148 | std::string fo = e.path + "/x.o"; |
|
|
149 | std::string fso = e.path + "/x.so"; |
|
|
150 | |
|
|
151 | std::ofstream f (fc.c_str ()); |
|
|
152 | f << source; |
|
|
153 | f.close (); |
|
|
154 | |
|
|
155 | system (("gcc -O6 -c -o " + fo + " " + fc).c_str ()); |
|
|
156 | |
|
|
157 | unlink (fc.c_str ()); |
|
|
158 | |
|
|
159 | system (("gcc -O6 -nostdlib -lgcc -shared -o " + fso + " " + fo).c_str ()); |
|
|
160 | |
|
|
161 | void *so = dlopen (fso.c_str (), RTLD_LAZY); |
|
|
162 | assert (so); |
|
|
163 | |
|
|
164 | funptr = dlsym (so, id.c_str ()); |
|
|
165 | assert (funptr); |
|
|
166 | } |
|
|
167 | |
|
|
168 | return funptr; |
60 | } |
169 | } |
61 | |
170 | |
62 | funbuild::funbuild (env &e, const idstr &id, const char *rettype, ...) |
171 | funbuild::funbuild (env &e, const idstr &id, const char *rettype, ...) |
63 | : e(e), id(id) |
172 | : e(e), id(id) |
64 | { |
173 | { |
65 | *this << rettype << " NAMExxxx ("; |
174 | if (is_null (id)) |
|
|
175 | this->id = e.genid (); |
|
|
176 | |
|
|
177 | *this << rettype << " " << this->id << "("; |
66 | |
178 | |
67 | va_list ap; |
179 | va_list ap; |
68 | va_start (ap, rettype); |
180 | va_start (ap, rettype); |
69 | |
181 | |
70 | int args = 0; |
182 | int args = 0; |