| 2362 | } |
| 2363 | |
| 2364 | MemInstr::ByteAccessInfo FnCall::getByteAccessInfo() const { |
| 2365 | if (attrs.has(AllocKind::Uninitialized) || attrs.has(AllocKind::Free)) |
| 2366 | return {}; |
| 2367 | |
| 2368 | bool has_ptr_args = any_of(args.begin(), args.end(), |
| 2369 | [](const auto &pair) { |
| 2370 | auto &[val, attrs] = pair; |
| 2371 | return hasPtr(val->getType()) && |
| 2372 | !attrs.has(ParamAttrs::ByVal) && |
| 2373 | !attrs.has(ParamAttrs::NoCapture); |
| 2374 | }); |
| 2375 | |
| 2376 | // calloc style |
| 2377 | if (attrs.has(AllocKind::Zeroed)) { |
| 2378 | auto info = ByteAccessInfo::intOnly(1); |
| 2379 | auto [alloc, align] = getMaxAllocSize(); |
| 2380 | if (alloc) |
| 2381 | info.byteSize = gcd(alloc, align); |
| 2382 | info.observesAddresses = has_ptr_args; |
| 2383 | return info; |
| 2384 | } |
| 2385 | |
| 2386 | // If bytesize is zero, this call does not participate in byte encoding. |
| 2387 | uint64_t bytesize = 0; |
| 2388 | |
| 2389 | #define UPDATE(attr) \ |
| 2390 | do { \ |
| 2391 | uint64_t sz = 0; \ |
| 2392 | if (attr.has(decay<decltype(attr)>::type::Dereferenceable)) \ |
| 2393 | sz = attr.derefBytes; \ |
| 2394 | if (attr.has(decay<decltype(attr)>::type::DereferenceableOrNull)) \ |
| 2395 | sz = gcd(sz, attr.derefOrNullBytes); \ |
| 2396 | if (sz) { \ |
| 2397 | sz = gcd(sz, retattr.align ? retattr.align : 1); \ |
| 2398 | bytesize = bytesize ? gcd(bytesize, sz) : sz; \ |
| 2399 | } \ |
| 2400 | } while (0) |
| 2401 | |
| 2402 | auto &retattr = getAttributes(); |
| 2403 | UPDATE(retattr); |
| 2404 | |
| 2405 | for (auto &[arg, attrs] : args) { |
| 2406 | if (!arg->getType().isPtrType()) |
| 2407 | continue; |
| 2408 | |
| 2409 | UPDATE(attrs); |
| 2410 | // Pointer arguments without dereferenceable attr don't contribute to the |
| 2411 | // byte size. |
| 2412 | // call f(* dereferenceable(n) align m %p, * %q) is equivalent to a dummy |
| 2413 | // load followed by a function call: |
| 2414 | // load i<8*n> %p, align m |
| 2415 | // call f(* %p, * %q) |
| 2416 | // f(%p, %q) does not contribute to the bytesize. After bytesize is fixed, |
| 2417 | // function calls update a memory with the granularity. |
| 2418 | } |
| 2419 | #undef UPDATE |
| 2420 | |
| 2421 | ByteAccessInfo info; |
no test coverage detected