| 2434 | } |
| 2435 | |
| 2436 | void Memory::memset_pattern(const expr &ptr0, const expr &pattern0, |
| 2437 | const expr &bytesize, unsigned pattern_length) { |
| 2438 | assert(!memory_unused()); |
| 2439 | unsigned bytesz = bits_byte / 8; |
| 2440 | Pointer ptr(*this, ptr0); |
| 2441 | state->addUB(ptr.isDereferenceable(bytesize, 1, true)); |
| 2442 | |
| 2443 | Pointer pattern(*this, pattern0); |
| 2444 | expr length = bytesize.umin(expr::mkUInt(pattern_length, bytesize)); |
| 2445 | state->addUB(pattern.isDereferenceable(length, 1, false)); |
| 2446 | |
| 2447 | set<expr> undef_vars; |
| 2448 | auto bytes |
| 2449 | = load(pattern, pattern_length, undef_vars, 1, little_endian, DATA_ANY); |
| 2450 | |
| 2451 | vector<pair<unsigned, expr>> to_store; |
| 2452 | uint64_t n; |
| 2453 | if (bytesize.isUInt(n) && (n / bytesz) <= 4) { |
| 2454 | for (unsigned i = 0; i < n; i += bytesz) { |
| 2455 | to_store.emplace_back(i, std::move(bytes[i/bytesz])()); |
| 2456 | } |
| 2457 | store(ptr, to_store, undef_vars, 1); |
| 2458 | } else { |
| 2459 | assert(bytes.size() * bytesz == pattern_length); |
| 2460 | for (unsigned i = 0; i < pattern_length; i += bytesz) { |
| 2461 | to_store.emplace_back(i * bytesz, std::move(bytes[i/bytesz])()); |
| 2462 | } |
| 2463 | expr offset = expr::mkQVar(0, Pointer::bitsShortOffset()); |
| 2464 | storeLambda(ptr, offset, bytesize, to_store, undef_vars, 1); |
| 2465 | } |
| 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) { |
no test coverage detected