5
5
#include " config.hpp"
6
6
#include " controls.hpp"
7
7
#include " heap_mem_bookkeeper.hpp"
8
+ #include " immer/map.hpp"
9
+ #include " immer/map_transient.hpp"
10
+ #include " immer/vector_transient.hpp"
8
11
#include " profile.hpp"
9
12
#include " utils.hpp"
10
13
#include < cassert>
@@ -238,47 +241,81 @@ class SymStack_t {
238
241
printf (" [Debug] poping from stack, size of symbolic stack is: %zu\n " ,
239
242
stack.size ());
240
243
#endif
244
+ #ifdef USE_IMM
245
+ auto ret = *(stack.end () - 1 );
246
+ stack.take (stack.size () - 1 );
247
+ return ret;
248
+ #else
241
249
auto ret = stack.back ();
242
250
stack.pop_back ();
243
251
return ret;
252
+ #endif
244
253
}
245
254
246
- SymVal peek () { return stack.back ( ); }
255
+ SymVal peek () { return *( stack.end () - 1 ); }
247
256
248
257
std::monostate shift (int32_t offset, int32_t size) {
249
258
auto n = stack.size ();
250
259
for (size_t i = n - size; i < n; ++i) {
251
260
assert (i - offset >= 0 );
261
+ #ifdef USE_IMM
262
+ stack.set (i - offset, stack[i]);
263
+ #else
252
264
stack[i - offset] = stack[i];
265
+ #endif
253
266
}
267
+ #ifdef USE_IMM
268
+ stack.take (n - offset);
269
+ #else
254
270
stack.resize (n - offset);
271
+ #endif
255
272
return std::monostate ();
256
273
}
257
274
258
275
void reset () {
259
- // Reset the symbolic stack
276
+ // Reset the symbolic stack
277
+ #ifdef USE_IMM
278
+ stack = immer::vector_transient<SymVal>();
279
+ #else
260
280
stack.clear ();
281
+ #endif
261
282
}
262
283
263
284
size_t size () const { return stack.size (); }
264
285
265
286
SymVal operator [](size_t index) const { return stack[index]; }
266
287
267
288
private:
289
+ #ifdef USE_IMM
290
+ immer::vector_transient<SymVal> stack;
291
+ #else
268
292
std::vector<SymVal> stack;
293
+ #endif
269
294
};
270
295
271
296
static SymStack_t SymStack;
272
297
273
298
class SymFrames_t {
299
+
274
300
public:
275
301
void pushFrame (int size) {
276
302
// Push a new frame with the given size
303
+ #ifdef USE_IMM
304
+ for (int i = 0 ; i < size; ++i) {
305
+ stack.push_back (SymVal ());
306
+ }
307
+ #else
277
308
stack.resize (size + stack.size ());
309
+ #endif
278
310
}
279
311
std::monostate popFrame (int size) {
280
312
// Pop the frame of the given size
313
+
314
+ #ifdef USE_IMM
315
+ stack.take (stack.size () - size);
316
+ #else
281
317
stack.resize (stack.size () - size);
318
+ #endif
282
319
return std::monostate ();
283
320
}
284
321
@@ -291,40 +328,79 @@ class SymFrames_t {
291
328
void set (int index, SymVal val) {
292
329
// Set the symbolic value at the given index
293
330
assert (val.symptr != nullptr );
331
+ #ifdef USE_IMM
332
+ stack.set (stack.size () - 1 - index, val);
333
+ #else
294
334
stack[stack.size () - 1 - index] = val;
335
+ #endif
295
336
}
296
337
297
338
void reset () {
298
339
// Reset the symbolic frames
340
+
341
+ #ifdef USE_IMM
342
+ stack = immer::vector_transient<SymVal>();
343
+ #else
299
344
stack.clear ();
345
+ #endif
300
346
}
301
347
302
348
size_t size () const { return stack.size (); }
303
349
304
350
SymVal operator [](size_t index) const { return stack[index]; }
305
351
306
352
private:
353
+ #ifdef USE_IMM
354
+ immer::vector_transient<SymVal> stack;
355
+ #else
307
356
std::vector<SymVal> stack;
357
+ #endif
308
358
};
309
359
310
360
struct NodeBox ;
311
361
struct SymEnv_t ;
312
362
313
363
class SymMemory_t {
314
364
public:
365
+ #ifdef USE_IMM
366
+ immer::map_transient<int , SymVal> memory;
367
+ #else
315
368
std::unordered_map<int , SymVal> memory;
369
+ #endif
316
370
317
371
SymVal loadSymByte (int32_t addr) {
318
- // if the address is not in the memory, it must be a zero-initialized memory
372
+ // if the address is not in the memory, it must be a zero-initialized memory
373
+ #ifdef USE_IMM
319
374
auto it = memory.find (addr);
320
- SymVal s = (it != memory.end ())
321
- ? it->second
322
- : SymVal (SymBookKeeper.allocate <SmallBV>(8 , 0 ));
375
+ if (it != nullptr ) {
376
+ return *it;
377
+ } else {
378
+ auto s = SymVal (ZeroByte);
379
+ return s;
380
+ }
381
+ #else
382
+ auto it = memory.find (addr);
383
+ SymVal s = (it != memory.end ()) ? it->second : SymVal (ZeroByte);
323
384
return s;
385
+ #endif
324
386
}
325
387
326
388
SymVal loadSym (int32_t base, int32_t offset) {
327
389
// calculate the real address
390
+
391
+ #ifdef USE_IMM
392
+ int32_t addr = base + offset;
393
+ auto it = memory.find (addr);
394
+ SymVal s0 = it ? *it : SymVal (ZeroByte);
395
+ it = memory.find (addr + 1 );
396
+ SymVal s1 = it ? *it : SymVal (ZeroByte);
397
+ it = memory.find (addr + 2 );
398
+ SymVal s2 = it ? *it : SymVal (ZeroByte);
399
+ it = memory.find (addr + 3 );
400
+ SymVal s3 = it ? *it : SymVal (ZeroByte);
401
+
402
+ return s3.concat (s2).concat (s1).concat (s0);
403
+ #else
328
404
int32_t addr = base + offset;
329
405
auto it = memory.find (addr);
330
406
SymVal s0 = (it != memory.end ()) ? it->second : SymVal (ZeroByte);
@@ -336,6 +412,7 @@ class SymMemory_t {
336
412
SymVal s3 = (it != memory.end ()) ? it->second : SymVal (ZeroByte);
337
413
338
414
return s3.concat (s2).concat (s1).concat (s0);
415
+ #endif
339
416
}
340
417
341
418
// when loading a symval, we need to concat 4 symbolic values
@@ -349,15 +426,26 @@ class SymMemory_t {
349
426
SymVal s1 = value.extract (2 , 2 );
350
427
SymVal s2 = value.extract (3 , 3 );
351
428
SymVal s3 = value.extract (4 , 4 );
429
+ #ifdef USE_IMM
430
+ memory.set (addr, s0);
431
+ memory.set (addr + 1 , s1);
432
+ memory.set (addr + 2 , s2);
433
+ memory.set (addr + 3 , s3);
434
+ #else
352
435
memory[addr] = s0;
353
436
memory[addr + 1 ] = s1;
354
437
memory[addr + 2 ] = s2;
355
438
memory[addr + 3 ] = s3;
439
+ #endif
356
440
return std::monostate{};
357
441
}
358
442
359
443
std::monostate reset () {
444
+ #ifdef USE_IMM
445
+ memory = immer::map_transient<int , SymVal>();
446
+ #else
360
447
memory.clear ();
448
+ #endif
361
449
return std::monostate{};
362
450
}
363
451
};
0 commit comments