Skip to content

Commit 0bd72f5

Browse files
committed
Extend addFnCall to return FnCallResult and handle allocsize
- Changed addFnCall return type from StateValue to FnCallResult (retval + optional alloc_size) - For allocators without allocsize, call addFnCall to obtain allocation size before memory setup
1 parent 0d3676c commit 0bd72f5

File tree

4 files changed

+49
-16
lines changed

4 files changed

+49
-16
lines changed

ir/instr.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,9 +2682,24 @@ StateValue FnCall::toSMT(State &s) const {
26822682
};
26832683

26842684
if (attrs.has(AllocKind::Alloc) ||
2685-
attrs.has(AllocKind::Realloc) ||
2686-
attrs.has(FnAttrs::AllocSize)) {
2687-
auto [size, np_size] = attrs.computeAllocSize(s, args);
2685+
attrs.has(AllocKind::Realloc)) {
2686+
2687+
smt::expr size;
2688+
smt::expr np_size;
2689+
2690+
if (!attrs.has(FnAttrs::AllocSize)) {
2691+
auto result = s.addFnCall(std::move(fnName_mangled).str(), std::move(inputs),
2692+
std::move(ptr_inputs), getType(), std::move(ret_val),
2693+
ret_arg_ty, std::move(ret_vals), attrs, indirect_hash);
2694+
auto retval =std::move(result.retval);
2695+
size = std::move(result.alloc_size.value());
2696+
np_size = expr(true);
2697+
} else {
2698+
auto result = attrs.computeAllocSize(s, args);
2699+
size = std::move(result.first);
2700+
np_size = std::move(result.second);
2701+
}
2702+
26882703
expr nonnull = attrs.isNonNull() ? expr(true)
26892704
: expr::mkBoolVar("malloc_never_fails");
26902705
// FIXME: alloc-family below
@@ -2755,7 +2770,7 @@ StateValue FnCall::toSMT(State &s) const {
27552770
return {};
27562771
}
27572772

2758-
auto ret = s.addFnCall(std::move(fnName_mangled).str(), std::move(inputs),
2773+
auto [ret, alloc_size] = s.addFnCall(std::move(fnName_mangled).str(), std::move(inputs),
27592774
std::move(ptr_inputs), getType(), std::move(ret_val),
27602775
ret_arg_ty, std::move(ret_vals), attrs, indirect_hash);
27612776

ir/memory.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,6 @@ void Memory::syncWithSrc(const Memory &src) {
17181718
ptr_alias = src.ptr_alias;
17191719
// TODO: copy alias info for fn return ptrs from src?
17201720

1721-
// Add synchronizing non-deterministic variables for local_blk_size
17221721
}
17231722

17241723
void Memory::markByVal(unsigned bid, bool is_const) {
@@ -2263,8 +2262,6 @@ Memory::alloc(const expr *size, uint64_t align, BlockKind blockKind,
22632262
if (size)
22642263
(is_local ? local_blk_size : non_local_blk_size)
22652264
.replace(short_bid, std::move(size_zext));
2266-
// If size is unknown in the above condition, add a non-det variable for size
2267-
// and add it as a member of the FnCallOutput structure with the key being the function name and bid
22682265
(is_local ? local_blk_align : non_local_blk_align)
22692266
.add(short_bid, std::move(align_expr));
22702267
(is_local ? local_blk_kind : non_local_blk_kind)

ir/state.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ expr State::FnCallOutput::refines(const FnCallOutput &rhs,
10811081
return ret;
10821082
}
10831083

1084-
StateValue
1084+
State::FnCallResult
10851085
State::addFnCall(const string &name, vector<StateValue> &&inputs,
10861086
vector<PtrInput> &&ptr_inputs,
10871087
const Type &out_type, StateValue &&ret_arg,
@@ -1090,7 +1090,8 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
10901090
bool noret = attrs.has(FnAttrs::NoReturn);
10911091
bool willret = attrs.has(FnAttrs::WillReturn);
10921092
bool noundef = attrs.has(FnAttrs::NoUndef);
1093-
bool noalias = attrs.has(FnAttrs::NoAlias);
1093+
bool noalias = (attrs.has(FnAttrs::NoAlias)) ||
1094+
(attrs.has(AllocKind::Alloc) && !attrs.has(FnAttrs::AllocSize));
10941095
bool is_indirect = name.starts_with("#indirect_call");
10951096

10961097
expr fn_ptr_bid;
@@ -1278,8 +1279,17 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
12781279
addUB(I->second.ub);
12791280
addNoReturn(I->second.noreturns);
12801281
retval = I->second.retval;
1282+
1283+
optional<expr> alloc_size;
1284+
if (noalias && out_type.isPtrType() && !I->second.ret_data.empty()) {
1285+
alloc_size = I->second.ret_data[0].size;
1286+
}
1287+
12811288
memory.setState(I->second.callstate, memaccess, I->first.args_ptr,
12821289
inaccessible_bid);
1290+
1291+
1292+
return { std::move(retval), std::move(alloc_size) };
12831293
}
12841294
else {
12851295
// target: this fn call must match one from the source, otherwise it's UB
@@ -1336,15 +1346,23 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
13361346
fn_call_pre &= pre;
13371347
if (qvar.isValid())
13381348
fn_call_qvars.emplace(std::move(qvar));
1349+
1350+
// Extract allocation size for noalias functions returning pointers
1351+
optional<expr> alloc_size;
1352+
if (noalias && out_type.isPtrType() && !d.ret_data.empty()) {
1353+
alloc_size = d.ret_data[0].size;
1354+
}
1355+
1356+
analysis.ranges_fn_calls.inc(name, memaccess);
1357+
return { std::move(retval), std::move(alloc_size) };
13391358
} else {
13401359
addUB(expr(false));
13411360
retval = out_type.getDummyValue(false);
1361+
1362+
analysis.ranges_fn_calls.inc(name, memaccess);
1363+
return { std::move(retval), std::nullopt };
13421364
}
13431365
}
1344-
1345-
analysis.ranges_fn_calls.inc(name, memaccess);
1346-
1347-
return retval;
13481366
}
13491367

13501368
void State::doesApproximation(string &&name, optional<expr> e,

ir/state.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,6 @@ class State {
233233
Memory::CallState callstate;
234234
std::vector<Memory::FnRetData> ret_data;
235235

236-
// Add non-deterministic local_blk_size variable member
237-
238236
FnCallOutput replace(const StateValue &retval) const;
239237

240238
static FnCallOutput mkIf(const smt::expr &cond, const FnCallOutput &then,
@@ -243,6 +241,11 @@ class State {
243241
auto operator<=>(const FnCallOutput &rhs) const = default;
244242
};
245243

244+
struct FnCallResult {
245+
StateValue retval;
246+
std::optional<smt::expr> alloc_size;
247+
};
248+
246249
// Add non-deterministic local_blk_size variable member and pending variable to access it
247250

248251
std::map<std::string, std::map<FnCallInput, FnCallOutput>> fn_call_data;
@@ -313,7 +316,7 @@ class State {
313316
void addNoReturn(const smt::expr &cond);
314317
bool isViablePath() const { return domain.UB; }
315318

316-
StateValue
319+
FnCallResult
317320
addFnCall(const std::string &name, std::vector<StateValue> &&inputs,
318321
std::vector<PtrInput> &&ptr_inputs,
319322
const Type &out_type,

0 commit comments

Comments
 (0)