| 1152 | } |
| 1153 | |
| 1154 | vector<Byte> Memory::load(const Pointer &ptr, unsigned bytes, set<expr> &undef, |
| 1155 | uint64_t align, bool left2right, DataType type) { |
| 1156 | if (bytes == 0) |
| 1157 | return {}; |
| 1158 | |
| 1159 | unsigned bytesz = (bits_byte / 8); |
| 1160 | unsigned loaded_bytes = bytes / bytesz; |
| 1161 | vector<DisjointExpr<expr>> loaded; |
| 1162 | expr poison = Byte::mkPoisonByte(*this)(); |
| 1163 | loaded.resize(loaded_bytes, poison); |
| 1164 | |
| 1165 | auto fn = [&](MemBlock &blk, const Pointer &ptr, unsigned bid, bool local, |
| 1166 | expr &&cond) { |
| 1167 | bool is_poison = (type & blk.type) == DATA_NONE; |
| 1168 | if (is_poison) { |
| 1169 | for (unsigned i = 0; i < loaded_bytes; ++i) { |
| 1170 | loaded[i].add(poison, cond); |
| 1171 | } |
| 1172 | } else { |
| 1173 | uint64_t blk_size = UINT64_MAX; |
| 1174 | bool single_load |
| 1175 | = ptr.blockSizeAligned().isUInt(blk_size) && blk_size == bytes; |
| 1176 | auto offset = ptr.getShortOffset(); |
| 1177 | expr blk_offset = single_load ? expr::mkUInt(0, offset) : offset; |
| 1178 | |
| 1179 | for (unsigned i = 0; i < loaded_bytes; ++i) { |
| 1180 | unsigned idx = left2right ? i : (loaded_bytes - i - 1); |
| 1181 | assert(idx < blk_size); |
| 1182 | uint64_t max_idx = blk_size - bytes + idx; |
| 1183 | expr off = blk_offset + expr::mkUInt(idx, offset); |
| 1184 | loaded[i].add(::raw_load(blk.val, off, max_idx), cond); |
| 1185 | } |
| 1186 | undef.insert(blk.undef.begin(), blk.undef.end()); |
| 1187 | } |
| 1188 | }; |
| 1189 | |
| 1190 | access(ptr, expr::mkUInt(bytes, bits_size_t), align, false, fn); |
| 1191 | |
| 1192 | vector<Byte> ret; |
| 1193 | for (auto &disj : loaded) { |
| 1194 | ret.emplace_back(*this, *std::move(disj)()); |
| 1195 | } |
| 1196 | return ret; |
| 1197 | } |
| 1198 | |
| 1199 | Memory::DataType Memory::data_type(const vector<pair<unsigned, expr>> &data, |
| 1200 | bool full_store) const { |
no test coverage detected