| 2466 | } |
| 2467 | |
| 2468 | void Memory::memcpy(const expr &d, const expr &s, const expr &bytesize, |
| 2469 | uint64_t align_dst, uint64_t align_src, bool is_move) { |
| 2470 | assert(!memory_unused()); |
| 2471 | unsigned bytesz = bits_byte / 8; |
| 2472 | |
| 2473 | Pointer dst(*this, d), src(*this, s); |
| 2474 | state->addUB(dst.isDereferenceable(bytesize, align_dst, true, false, false)); |
| 2475 | state->addUB(src.isDereferenceable(bytesize, align_src, false, false, false)); |
| 2476 | if (!is_move) |
| 2477 | src.isDisjointOrEqual(bytesize, dst, bytesize); |
| 2478 | |
| 2479 | // copy to itself |
| 2480 | if ((src == dst).isTrue()) |
| 2481 | return; |
| 2482 | |
| 2483 | uint64_t n; |
| 2484 | if (bytesize.isUInt(n) && (n / bytesz) <= 4) { |
| 2485 | vector<pair<unsigned, expr>> to_store; |
| 2486 | set<expr> undef; |
| 2487 | unsigned i = 0; |
| 2488 | for (auto &byte : load(src, n, undef, align_src)) { |
| 2489 | to_store.emplace_back(i++ * bytesz, std::move(byte)()); |
| 2490 | } |
| 2491 | store(dst, to_store, undef, align_dst); |
| 2492 | } else { |
| 2493 | expr offset = expr::mkQVar(0, Pointer::bitsShortOffset()); |
| 2494 | Pointer ptr_src = src + (offset - dst.getShortOffset()); |
| 2495 | set<expr> undef; |
| 2496 | storeLambda(dst, offset, bytesize, {{0, raw_load(ptr_src, undef)()}}, undef, |
| 2497 | align_dst); |
| 2498 | } |
| 2499 | } |
| 2500 | |
| 2501 | void Memory::copy(const Pointer &src, const Pointer &dst) { |
| 2502 | auto local = dst.isLocal(); |
no test coverage detected