Line data Source code
1 : #include <iostream>
2 : #include <cstring>
3 : #include <unistd.h>
4 : #include <signal.h>
5 : #include <sys/wait.h>
6 : #include <sys/types.h>
7 : #include <sys/stat.h>
8 : #include <fcntl.h>
9 : #include "runtime/vmachine.hpp"
10 : #include "common/exprtype.hpp"
11 : #include "common/obstacle.hpp"
12 :
13 52 : void VirtualMachine::loadBIN(const char * filename) {
14 52 : std::ifstream bin;
15 52 : bin.open(filename, std::ios_base::binary | std::ios_base::in);
16 :
17 52 : bin.seekg(0, std::ios::end);
18 52 : int size = bin.tellg();
19 52 : base = new char [size];
20 52 : bin.seekg(0, std::ios::beg);
21 52 : bin.read(base, size * sizeof(char));
22 :
23 52 : cmd = base + *reinterpret_cast<int*>(base);
24 52 : bin.close();
25 52 : cmdNum = (size - *reinterpret_cast<int*>(base)) / (sizeof(int) + sizeof(bool));
26 52 : }
27 :
28 52 : void VirtualMachine::run(void) {
29 : op_t op;
30 52 : int * eip = new int (0);
31 52 : std::cout << std::boolalpha;
32 :
33 : while (true) {
34 6876 : if (*reinterpret_cast<bool*>(cmd + 4 + *eip * 5)) { // ExecBit = 1
35 3352 : op = (op_t) *reinterpret_cast<int *>(cmd + *eip * 5);
36 3352 : if (exec(op, eip)) break;
37 : } else { // ExecBit = 0
38 3524 : int shift = * reinterpret_cast<int *>(cmd + *eip * 5);
39 3524 : stackVM.push(static_cast<void *>(base + shift));
40 : }
41 6824 : *eip += 1;
42 6824 : }
43 :
44 52 : if (inThread) {
45 4 : void * nullp = nullptr;
46 4 : write(pipefd.back()[1], &nullp, sizeof(void*));
47 : #ifdef DEBUG
48 : std::cout << "Передал отцовскому процессу нуль." << std::endl;
49 : #endif
50 : }
51 :
52 : #ifdef DEBUG
53 : std::cout << "Машина завершила свою работу." << std::endl;
54 : #endif
55 :
56 58 : while (pipefd.size() != 0) {
57 6 : delete[] pipefd.back();
58 6 : pipefd.pop_back();
59 : }
60 :
61 52 : delete eip;
62 52 : }
63 :
64 : template <class lval_t, class rval_t, class res_t>
65 829 : void VirtualMachine::tempOp(res_t (*f) (lval_t, rval_t), type_t TYPE) {
66 829 : rval_t b = * static_cast<rval_t *>(stackVM.pop());
67 829 : lval_t a = * static_cast<lval_t *>(stackVM.pop());
68 829 : stackVM.push(new res_t ( f(a, b) ), TYPE);
69 829 : }
70 :
71 : template <class lval_t, class rval_t>
72 388 : void VirtualMachine::assign(void) {
73 388 : if (inThread) {
74 48 : rval_t x = * static_cast<rval_t *>(stackVM.pop());
75 48 : lval_t * p = static_cast<lval_t *>(stackVM.pop());
76 48 : *p = x;
77 48 : int n = sizeof(rval_t);
78 48 : write(pipefd.back()[1], &p, sizeof(void*));
79 48 : write(pipefd.back()[1], &n, sizeof(int));
80 48 : write(pipefd.back()[1], &x, sizeof(rval_t));
81 : } else {
82 340 : rval_t x = * static_cast<rval_t *>(stackVM.pop());
83 340 : * static_cast<lval_t *>(stackVM.pop()) = x;
84 : }
85 388 : }
86 :
87 381 : char * VirtualMachine::getString(void * x) {
88 381 : return (static_cast<char **>( x )[0] == nullptr)
89 381 : ? static_cast<char *>( x ) + sizeof(char*)
90 381 : : * static_cast<char**>( x );
91 : }
92 :
93 3352 : bool VirtualMachine::exec(op_t op, int * eip) {
94 3352 : bool exitStatus = false;
95 3352 : type_t rest = (type_t) ((op >> 24) & 0xFF);
96 3352 : type_t lval = (type_t) ((op >> 16) & 0xFF);
97 3352 : type_t rval = (type_t) ((op >> 8) & 0xFF);
98 :
99 3352 : if ((lval == _STRUCT_) || (rval == _STRUCT_))
100 0 : throw Obstacle(PANIC);
101 :
102 3352 : switch(op & 0xFF) {
103 239 : case PLUS:
104 239 : if (rest == _STRING_){
105 13 : char * b = getString(stackVM.pop());
106 13 : char * a = getString(stackVM.pop());
107 :
108 13 : int alen = 0;
109 13 : int blen = 0;
110 132 : for (; a[alen] != '\0'; ++alen) {}
111 61 : for (; b[blen] != '\0'; ++blen) {}
112 :
113 13 : char * c = new char [alen + blen + 1 + sizeof(char*)];
114 13 : memcpy(c, "\0\0\0\0\0\0\0\0", sizeof(char*));
115 13 : memcpy(c + sizeof(char*), a, alen);
116 13 : memcpy(c + alen + sizeof(char*), b, blen);
117 13 : c[alen + blen + sizeof(char*)] = '\0';
118 13 : stackVM.push(c);
119 13 : dynamicStrings.push(c, _STRING_);
120 : } else {
121 452 : ARITH_OPERATION(+)
122 : }
123 239 : break;
124 144 : case MINUS: ARITH_OPERATION(-) break;
125 288 : case MUL: ARITH_OPERATION(*) break;
126 208 : case DIV: ARITH_OPERATION(/) break;
127 12 : case MOD: {
128 12 : int b = * static_cast<int *>(stackVM.pop());
129 12 : int a = * static_cast<int *>(stackVM.pop());
130 12 : stackVM.push(new int (a % b), _INT_);
131 12 : break;
132 : }
133 0 : case INV:
134 0 : if (rest == _INT_) {
135 0 : int a = * static_cast<int *>(stackVM.pop());
136 0 : stackVM.push(new int (-a), _INT_);
137 : } else {
138 0 : float a = * static_cast<float *>(stackVM.pop());
139 0 : stackVM.push(new float (-a), _REAL_);
140 : }
141 0 : break;
142 221 : case LOAD: {
143 221 : int x = * static_cast<int *>(stackVM.pop());
144 221 : void * shv = sharedVars.get(x);
145 221 : void * a = registerVM.get(x);
146 221 : stackVM.push(shv == nullptr? a : shv);
147 221 : break;
148 : }
149 402 : case ASSIGN:
150 402 : if (lval == _INT_) {
151 274 : if (rval == _INT_) assign<int, int>();
152 6 : else assign<int, float>();
153 128 : } else if (lval == _REAL_) {
154 102 : if (rval == _INT_) assign<float, int>();
155 99 : else assign<float, float>();
156 26 : } else if (lval == _STRING_){
157 14 : char * b = getString(stackVM.pop());
158 14 : char * a = static_cast<char *>(stackVM.pop());
159 14 : memcpy(a, &b, sizeof(void*));
160 12 : } else if (lval == _BOOLEAN_) {
161 12 : assign<bool, bool>();
162 0 : } else throw Obstacle(PANIC);
163 402 : break;
164 52 : case STOP:
165 52 : exitStatus = true;
166 52 : break;
167 733 : case WRITE:
168 733 : if (rval == _INT_) {
169 378 : int x = * static_cast<int *>(stackVM.pop());
170 378 : std::cout << x;
171 355 : } else if (rval == _REAL_) {
172 20 : float x = * static_cast<float *>(stackVM.pop());
173 20 : std::cout << x;
174 335 : } else if (rval == _STRING_) {
175 319 : char * x = getString(stackVM.pop());
176 319 : std::cout << x;
177 16 : } else if (rval == _BOOLEAN_) {
178 16 : bool x = * static_cast<bool *>(stackVM.pop());
179 16 : std::cout << x;
180 0 : } else throw Obstacle(PANIC);
181 733 : break;
182 225 : case ENDL:
183 225 : std::cout << std::endl;
184 225 : break;
185 298 : case JIT: {
186 298 : int offset = * static_cast<int *>(stackVM.pop());
187 298 : bool condition = * static_cast<bool *>(stackVM.pop());
188 298 : if (condition) *eip = offset - 1;
189 298 : break;
190 : }
191 226 : case JMP: {
192 226 : int offset = * static_cast<int *>(stackVM.pop());
193 226 : *eip = offset - 1;
194 226 : break;
195 : }
196 34 : case LESS:
197 34 : if ((lval == _STRING_) && (rval == _STRING_)) {
198 5 : char * b = getString(stackVM.pop());
199 5 : char * a = getString(stackVM.pop());
200 5 : int i = 0;
201 20 : for (; (a[i] != '\0') && (b[i] != '\0'); i++) {}
202 5 : stackVM.push(new bool ((a[i] == '\0') && (b[i] != '\0')), _BOOLEAN_);
203 : } else {
204 58 : LOGIC_OPERATION(<)
205 : }
206 34 : break;
207 30 : case GRTR:
208 30 : if ((lval == _STRING_) && (rval == _STRING_)) {
209 0 : char * b = getString(stackVM.pop());
210 0 : char * a = getString(stackVM.pop());
211 0 : int i = 0;
212 0 : for (; (a[i] != '\0') && (b[i] != '\0'); i++) {}
213 0 : stackVM.push(new bool (b[i] == '\0'), _BOOLEAN_);
214 : } else {
215 60 : LOGIC_OPERATION(>)
216 : }
217 30 : break;
218 290 : case LESSEQ: LOGIC_OPERATION(<=) break;
219 12 : case GRTREQ: LOGIC_OPERATION(>=) break;
220 33 : case EQ:
221 33 : if ((lval == _STRING_) && (rval == _STRING_)) {
222 6 : char * b = getString(stackVM.pop());
223 6 : char * a = getString(stackVM.pop());
224 6 : bool r = true;
225 6 : int i = 0;
226 25 : for (; (a[i] != '\0') && (b[i] != '\0'); i++) {
227 21 : if (a[i] != b[i]) {
228 2 : r = false;
229 2 : break;
230 : }
231 : }
232 6 : r = r && (a[i] == '\0') && (b[i] == '\0');
233 6 : stackVM.push(new bool (r), _BOOLEAN_);
234 : } else {
235 54 : LOGIC_OPERATION(==)
236 : }
237 33 : break;
238 46 : case NEQ:
239 46 : if ((lval == _STRING_) && (rval == _STRING_)) {
240 0 : char * b = getString(stackVM.pop());
241 0 : char * a = getString(stackVM.pop());
242 0 : bool r = true;
243 0 : int i = 0;
244 0 : for (; (a[i] != '\0') && (b[i] != '\0'); i++) {
245 0 : if (a[i] != b[i]) {
246 0 : r = false;
247 0 : break;
248 : }
249 : }
250 0 : r = r && (a[i] == '\0') && (b[i] == '\0');
251 0 : stackVM.push(new bool (!r), _BOOLEAN_);
252 : } else {
253 92 : LOGIC_OPERATION(!=)
254 : }
255 46 : break;
256 59 : case READ:
257 59 : if (rval == _INT_) {
258 : float temp;
259 39 : std::cin >> temp;
260 :
261 39 : stackVM.updateType(_INT_);
262 39 : * static_cast<int *>(stackVM.pop()) = (int)temp;
263 20 : } else if (rval == _REAL_) {
264 8 : std::cin >> * static_cast<float *>(stackVM.pop());
265 12 : } else if (rval == _STRING_) {
266 16 : std::string x;
267 8 : std::cin >> x;
268 8 : char * newString = new char[x.length() + 1];
269 8 : memcpy(newString, x.data(), x.length() + 1);
270 8 : char * a = static_cast<char *>(stackVM.pop());
271 8 : const char * b = newString;
272 8 : memcpy(a, &b, sizeof(void*));
273 8 : dynamicStrings.push(newString, _STRING_);
274 : } else {
275 4 : std::string x;
276 4 : do { std::cin >> x; }
277 4 : while ((x != "True") && (x != "true") && (x != "False") && (x != "false"));
278 4 : * static_cast<bool *>(stackVM.pop()) = (x == "True") || (x == "true");
279 : }
280 59 : break;
281 :
282 4 : case LAND: {
283 4 : bool b = * static_cast<bool *>(stackVM.pop());
284 4 : bool a = * static_cast<bool *>(stackVM.pop());
285 4 : stackVM.push(new bool (a && b), _BOOLEAN_);
286 4 : break;
287 : }
288 5 : case LOR: {
289 5 : bool b = * static_cast<bool *>(stackVM.pop());
290 5 : bool a = * static_cast<bool *>(stackVM.pop());
291 5 : stackVM.push(new bool (a || b), _BOOLEAN_);
292 5 : break;
293 : }
294 110 : case LNOT: {
295 110 : bool a = * static_cast<bool *>(stackVM.pop());
296 110 : stackVM.push(new bool (!a), _BOOLEAN_);
297 110 : break;
298 : }
299 62 : case CALL: {
300 62 : int offset = * static_cast<int *>(stackVM.pop());
301 62 : int param = * static_cast<int *>(stackVM.pop());
302 144 : for (int i = 0; i < param; i++) {
303 82 : registerVM.push( stackVM.pop() );
304 82 : sharedVars.push(nullptr);
305 : }
306 62 : params.push(new int (param), _INT_);
307 62 : offsets.push(new int (*eip + 1), _INT_);
308 62 : *eip = offset - 1;
309 62 : break;
310 : }
311 62 : case RET: {
312 62 : int offset = * static_cast<int *>(offsets.pop());
313 62 : int param = * static_cast<int *>(params.pop());
314 144 : while (param--) registerVM.pop();
315 62 : *eip = offset - 1;
316 62 : break;
317 : }
318 13 : case SHARE: {
319 13 : int x = * static_cast<int *>(stackVM.pop());
320 13 : sharedVars.set(x, registerVM.get(x));
321 13 : break;
322 : }
323 10 : case FORK: {
324 10 : pipefd.push_back(new int[2]);
325 10 : pipe(pipefd.back());
326 :
327 10 : pid_t pid = fork();
328 10 : threads.push_back(pid);
329 :
330 10 : if (pid == -1) throw Obstacle(PANIC);
331 10 : if (pid == 0) {
332 4 : inThread = true;
333 4 : int offset = * static_cast<int *>(stackVM.pop());
334 4 : *eip = offset - 1;
335 : }
336 : #ifdef DEBUG
337 : else {
338 : std::cout << "Запущен новый поток с PID = " << pid << std::endl;
339 : }
340 : #endif
341 10 : break;
342 : }
343 6 : case LOCK: {
344 6 : while (threads.size() != 0) {
345 4 : int st, ret = 0;
346 4 : updateVars();
347 4 : pid_t pid = threads.back();
348 4 : ret = waitpid(pid, &st, 0);
349 4 : if (ret == -1) throw Obstacle(PANIC);
350 4 : else if (WIFEXITED(st)) threads.pop_back();
351 : }
352 2 : break;
353 : }
354 3 : case UNPACK: {
355 3 : int fieldSize = * static_cast<int *>(stackVM.pop());
356 15 : for (int i = 0; i < fieldSize * 2; i++) {
357 12 : registerVM.push(stackVM.pop());
358 : }
359 9 : for (int i = 0; i < fieldSize; i++) {
360 6 : stackVM.push(registerVM.get(i));
361 6 : stackVM.push(registerVM.get(i + fieldSize));
362 : }
363 15 : for (int i = 0; i < fieldSize * 2; i++) {
364 12 : registerVM.pop();
365 : }
366 3 : break;
367 : }
368 0 : default:
369 0 : std::cout << "Неизвестная команда." << std::endl;
370 0 : exit(-1);
371 : }
372 :
373 3352 : return exitStatus;
374 : }
375 :
376 56 : void VirtualMachine::updateVars(void) {
377 : void * p;
378 : int n;
379 56 : while (pipefd.size() != 0) {
380 52 : read(pipefd.back()[0], &p, sizeof(void *));
381 52 : if (p == nullptr) {
382 4 : delete[] pipefd.back();
383 4 : pipefd.pop_back();
384 4 : continue;
385 : }
386 48 : read(pipefd.back()[0], &n, sizeof(int));
387 48 : read(pipefd.back()[0], p, n);
388 : }
389 4 : }
390 :
391 52 : VirtualMachine::~VirtualMachine(void) {
392 52 : delete [] base;
393 52 : dynamicStrings.burn();
394 52 : }
|