| 1513 | } |
| 1514 | |
| 1515 | Memory::Memory(State &state) |
| 1516 | : state(&state), escaped_local_blks(*this), observed_addrs(*this) { |
| 1517 | if (memory_unused()) |
| 1518 | return; |
| 1519 | |
| 1520 | next_nonlocal_bid |
| 1521 | = has_null_block + num_globals_src + num_ptrinputs + has_fncall; |
| 1522 | |
| 1523 | if (skip_null()) |
| 1524 | non_local_block_val.emplace_back(); |
| 1525 | |
| 1526 | // TODO: should skip initialization of fully initialized constants |
| 1527 | for (unsigned bid = skip_null(), e = numNonlocals(); bid != e; ++bid) { |
| 1528 | non_local_block_val.emplace_back(mk_block_val_array(bid)); |
| 1529 | } |
| 1530 | |
| 1531 | non_local_block_liveness = mk_liveness_array(); |
| 1532 | |
| 1533 | // initialize all local blocks as non-pointer, poison value |
| 1534 | // This is okay because loading a pointer as non-pointer is also poison. |
| 1535 | if (numLocals() > 0) { |
| 1536 | auto poison_array |
| 1537 | = expr::mkConstArray(expr::mkUInt(0, Pointer::bitsShortOffset()), |
| 1538 | Byte::mkPoisonByte(*this)()); |
| 1539 | local_block_val.resize(numLocals(), {std::move(poison_array), DATA_NONE}); |
| 1540 | |
| 1541 | // all local blocks are dead in the beginning |
| 1542 | local_block_liveness = expr::mkUInt(0, numLocals()); |
| 1543 | } |
| 1544 | |
| 1545 | // no argument has been written to at entry |
| 1546 | if (has_initializes_attr) { |
| 1547 | unsigned bits = Pointer::bitsShortBid() + Pointer::bitsShortOffset(); |
| 1548 | has_stored_arg = expr::mkConstArray(expr::mkUInt(0, bits), false); |
| 1549 | } |
| 1550 | |
| 1551 | stored_pointers.resize(numNonlocals()); |
| 1552 | |
| 1553 | // Initialize a memory block for null pointer. |
| 1554 | if (skip_null()) { |
| 1555 | auto zero = expr::mkUInt(0, bits_size_t); |
| 1556 | alloc(&zero, bits_byte / 8, GLOBAL, false, false, 0); |
| 1557 | } |
| 1558 | } |
| 1559 | |
| 1560 | Memory Memory::dupNoRead() const { |
| 1561 | Memory ret(*state); |
nothing calls this directly
no test coverage detected