Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
8908155
Initial vide-coded impl of andersen analysis with OTF CG construction
fabianbs96 Apr 23, 2026
c59d591
Add online cycle detection
fabianbs96 Apr 23, 2026
d06b6ec
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Apr 29, 2026
ace582c
Fix reference invalidation, missing retroactive firing, and arg alias…
fabianbs96 Apr 29, 2026
c244b9f
Merge branch 'development' into f-AndersOTFAA
fabianbs96 May 3, 2026
8bba47d
Vibe code some tests + identify bug that converts many alias sets int…
fabianbs96 May 3, 2026
87641c6
Reduce the size of AndersenVar by half (sth the AI apparently could n…
fabianbs96 May 3, 2026
a289f5f
Add AndersenOTF tests for deep chains, recursion, and function pointers
fabianbs96 May 14, 2026
c8c0260
Perf improvement in AndersOTFAA
fabianbs96 May 19, 2026
992604d
Vibe-code delta propagation
fabianbs96 May 19, 2026
8f3f88e
Let AI write more tests
fabianbs96 May 19, 2026
4619bcb
Handle global initializers
fabianbs96 May 20, 2026
0f54781
Reduce unnecessary copies
fabianbs96 May 20, 2026
532c621
Fix globals + fnptr handling
fabianbs96 May 26, 2026
4789a3a
Better vtable handling
fabianbs96 May 27, 2026
ed0b6cb
Fix minor bug in vtable handling + add failing test case for too earl…
fabianbs96 May 27, 2026
057076a
Let claude fix the early fixpoint bug
fabianbs96 May 27, 2026
76020c1
minor
fabianbs96 May 27, 2026
a1be493
minor
fabianbs96 May 28, 2026
fd3e394
Expose call-graph built by AndersenOTFAA + add some configurable soun…
fabianbs96 May 28, 2026
c130387
Debug missing callees in AndersenOTFAA
fabianbs96 May 30, 2026
b47acc1
minor perf improvement
fabianbs96 May 30, 2026
098d60b
minor
fabianbs96 May 30, 2026
c8621e7
Add library-summary handling to AndersenOTFAA.
fabianbs96 Jun 3, 2026
9876945
Best-effort approach to more precisely handle calls through hand-roll…
fabianbs96 Jun 3, 2026
ec5b5a3
Small deduplication
fabianbs96 Jun 4, 2026
d96da4a
Small manual refactorings
fabianbs96 Jun 4, 2026
8f03c60
minor in test
fabianbs96 Jun 4, 2026
b0d6a79
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Jun 4, 2026
86cdd07
Add MemorySSA to AndersenOTFAA + let AI debug a soundness-bug.
fabianbs96 Jun 4, 2026
9eeb88a
Add other lightweight alias oracles from LLVM to MemSSABundle for sli…
fabianbs96 Jun 4, 2026
b499c67
Remove stale commented-out debug print in handleCall
fabianbs96 Jun 4, 2026
8d527c6
pre-commit
fabianbs96 Jun 4, 2026
af9e847
Fix compilation with LLVM > 19
fabianbs96 Jun 4, 2026
886dac8
Add missing parts from phasarllvm/pointer to C++20 module
fabianbs96 Jun 4, 2026
175025a
Let AI fix a LLVM-version compatibility issue in AndersenOTFAATest
fabianbs96 Jun 4, 2026
8d71110
Fix dependency between phasar_llvm_controlflow and phasar_llvm_pointer
fabianbs96 Jun 4, 2026
718cc0b
pre-commit
fabianbs96 Jun 4, 2026
d902f2a
Fix CRoaring install
fabianbs96 Jun 4, 2026
75b1377
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Jul 4, 2026
a2c84d3
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Jul 4, 2026
b0dfac3
Fix small bug that pointer-params of entry-functions had no aliases +…
fabianbs96 Jul 5, 2026
063c0c7
Let the AI add a special case for factory functions
fabianbs96 Jul 14, 2026
b5c9b22
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Jul 14, 2026
b43140b
Allow analyzing a single file with the ptaben benchmark tool
fabianbs96 Jul 25, 2026
7cae64f
Guard AllocWrapper classification against escaping pointer uses
fabianbs96 Jul 25, 2026
ba376b4
Resolve heap/stack function-pointer dispatch tables field-sensitively
fabianbs96 Jul 25, 2026
d3777dd
Split FieldWriteRecord
fabianbs96 Jul 25, 2026
409904c
Fix TypedArray::enumerate with LLVM 22
fabianbs96 Jul 25, 2026
27671d3
Update license to include the newly added submodule CRoaring
fabianbs96 Jul 25, 2026
10368e2
added anders-otf results to README
mxHuber Jul 29, 2026
0302517
initial context sensitivity
fabianbs96 Jul 29, 2026
4840348
Attempt to fix CI by explicitly disallowing march=native
fabianbs96 Jul 31, 2026
e59ace9
Use newer clang in CI to fix internal compiler error
fabianbs96 Jul 31, 2026
d775542
Merge branch 'f-AndersOTFAA' into f-CtxAndersOTFAA
fabianbs96 Aug 3, 2026
f063837
Merge branch 'development' into f-AndersOTFAA
fabianbs96 Aug 3, 2026
b8fdefa
Merge branch 'f-AndersOTFAA' into f-CtxAndersOTFAA
fabianbs96 Aug 3, 2026
f39954f
Keep points-to elements canonical to preserve object identity
fabianbs96 Aug 3, 2026
2320a15
Re-check fn-ptr callback entry points every round
fabianbs96 Aug 4, 2026
77507c0
Small update on ptaben benchmark tool
fabianbs96 Aug 4, 2026
d45ecc2
Let AI add failing test cases
fabianbs96 Aug 5, 2026
0fef1d6
Fix the AndersenOTFAA defects found in the review
fabianbs96 Aug 6, 2026
d4d9864
Remove redundant set
fabianbs96 Aug 11, 2026
dca59bf
Report invalid context-selection globs; annotate solver lifetimes
fabianbs96 Aug 12, 2026
cd604bd
Retune the dynamic context-sensitivity defaults
fabianbs96 Aug 13, 2026
7fbce44
Model punned pointer accesses in the PAG builder
fabianbs96 Aug 13, 2026
454a9f3
Model atomicrmw and cmpxchg in the PAG builder
fabianbs96 Aug 13, 2026
91cf18a
Recover aliases that addAlias could not record
fabianbs96 Aug 13, 2026
5e160c6
Announce pre-populated ValueCompressor ids to the PAG strategy
fabianbs96 Aug 13, 2026
7ffdf3f
Share the LLVM memory-access semantics between both PAG frontends
fabianbs96 Aug 13, 2026
da4e5fd
Annotate the union-find AA lifetimes with PSR_LIFETIMEBOUND
fabianbs96 Aug 14, 2026
30221ee
Merge branch 'development' into f-CtxAndersOTFAA
fabianbs96 Aug 14, 2026
3919152
Clean up leftovers from the AndersenOTFAA review
fabianbs96 Aug 14, 2026
978242b
Untrack the AndersenOTFAA context-sensitivity design doc
fabianbs96 Aug 14, 2026
fbeeb8f
Dump IR to debug issue on ARM in CI
fabianbs96 Aug 16, 2026
56677da
Attempt to fix issue on ARM
fabianbs96 Aug 16, 2026
b930500
Merge branch 'development' into f-CtxAndersOTFAA
fabianbs96 Aug 16, 2026
427b96b
Unify UnionFindAAResult etc. to RawAAResult, making it fit for anders…
fabianbs96 Aug 17, 2026
3274dbf
Fix double global-model construction + make LLVMProjectIRDB::insertFu…
fabianbs96 Aug 17, 2026
da93e69
Fix modules build after rename
fabianbs96 Aug 17, 2026
1a251c5
Merge branch 'development' into f-CtxAndersOTFAA
fabianbs96 Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,38 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


CRoaring
-------------------------------------------------------------------------------
The CRoaring project is under a dual license (Apache/MIT).
Users of the library may choose one or the other license.
---

MIT License

Copyright 2016-2022 The CRoaring authors

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
9 changes: 6 additions & 3 deletions include/phasar/ControlFlow/CallGraphBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "phasar/Utils/Compressor.h"
#include "phasar/Utils/GraphTraits.h"
#include "phasar/Utils/IotaIterator.h"
#include "phasar/Utils/Macros.h"
#include "phasar/Utils/NonNullPtr.h"
#include "phasar/Utils/TypeTraits.h"

Expand Down Expand Up @@ -147,13 +148,15 @@ template <typename CallGraphTy, typename DB> class ReverseCGGraph {
typename CallGraphTy::f_t>;

constexpr ReverseCGGraph(
NonNullPtr<const CallGraphTy> CGView, NonNullPtr<const DB> IRDB,
NonNullPtr<const CallGraphTy> CGView PSR_LIFETIMEBOUND,
NonNullPtr<const DB> IRDB PSR_LIFETIMEBOUND,
Compressor<typename CallGraphTy::f_t, FunctionId> FC) noexcept
requires(NeedsMapping)
: CGView(CGView), IRDB(IRDB), FC(std::move(FC)) {}

constexpr ReverseCGGraph(NonNullPtr<const CallGraphTy> CGView,
NonNullPtr<const DB> IRDB) noexcept
constexpr ReverseCGGraph(NonNullPtr<const CallGraphTy> CGView
PSR_LIFETIMEBOUND,
NonNullPtr<const DB> IRDB PSR_LIFETIMEBOUND) noexcept
: CGView(CGView), IRDB(IRDB) {
FC.reserve(CGView->getNumVertexFunctions());
for (const auto &Fun : CGView->getAllVertexFunctions()) {
Expand Down
1 change: 1 addition & 0 deletions include/phasar/PhasarLLVM/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h"
#include "phasar/PhasarLLVM/Pointer/LLVMGlobalInitCache.h"
#include "phasar/PhasarLLVM/Pointer/LLVMPointerSemantics.h"
#include "phasar/PhasarLLVM/Pointer/LLVMPointsToInfo.h"
#include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h"
#include "phasar/PhasarLLVM/Pointer/LLVMUnionFindAA.h"
Expand Down
75 changes: 65 additions & 10 deletions include/phasar/PhasarLLVM/Pointer/AndersenOTFAA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "phasar/PhasarLLVM/Pointer/LLVMUnionFindAA.h"
#include "phasar/Pointer/RawAliasSet.h"
#include "phasar/Pointer/UnionFindAA.h"
#include "phasar/Utils/Macros.h"
#include "phasar/Utils/MaybeUniquePtr.h"
#include "phasar/Utils/NonNullPtr.h"
#include "phasar/Utils/Soundness.h"
Expand All @@ -22,6 +23,10 @@

#include "llvm/ADT/ArrayRef.h"

#include <cstdint>
#include <string>
#include <vector>

namespace llvm {
class Function;
} // namespace llvm
Expand All @@ -30,10 +35,54 @@ namespace psr {

class LLVMProjectIRDB;

/// Opt-in call-string context-sensitivity for \c AndersenOTFSolver.
///
/// The call-string k-limit is fixed at 1: a selected function gets one set of
/// PAG nodes per call-site that reaches it. Non-selected functions keep a
/// single set of nodes shared by all callers, exactly as before.
struct ContextSensitivityOptions {
enum class Mode : uint8_t {
Off, ///< Root context only; identical to the insensitive solver.
Manual, ///< Only functions matching \c AllowList.
Dynamic, ///< \c AllowList plus functions observed as precision-critical.
All, ///< Every function, until \c MaxContextualNodes is reached.
};

Mode SelectionMode = Mode::Off;
/// Function-name globs (\c llvm::GlobPattern). \c DenyList wins over
/// \c AllowList.
std::vector<std::string> AllowList{};
std::vector<std::string> DenyList{};
/// Hard cap on context-qualified PAG nodes. Once reached, no function is
/// newly selected and no already-selected function gets a further context:
/// sound, just less precise. This is the knob that bounds run time; solve
/// time grows super-linearly in the node count, so raising it is not a
/// proportional trade.
size_t MaxContextualNodes = 20'000;
/// Cap on distinct calling contexts per function; further call sites fall
/// back to the shared root context. A selected function costs one clone of
/// its whole body per context, so without this a single hot function can
/// consume \c MaxContextualNodes on its own.
unsigned MaxContextsPerFunction = 32;
/// \c Mode::Dynamic only: functions with more LLVM instructions than this
/// are never selected. Cloning a large body per context is expensive, and
/// large functions are rarely the point where callers merge.
unsigned MaxContextualFunctionSize = 256;
/// \c Mode::Dynamic only: tighter size limit for the weaker signal where
/// the merged parameters never leave the function body. Off by default:
/// that signal's only payoff is formal-vs-formal aliasing inside the body,
/// which \c buildResult unions back together across contexts anyway.
unsigned MaxLocalMergeFunctionSize = 0;

[[nodiscard]] constexpr bool isOff() const noexcept {
return SelectionMode == Mode::Off;
}
};

/// Alias-analysis result for the Andersen-style OTF points-to analysis.
///
/// Two values may-alias iff their points-to sets share at least one abstract
/// object. Satisfies \c UnionFindAAResult so it can be wrapped by
/// object. Satisfies \c RawAAResult so it can be wrapped by
/// \c LLVMUnionFindAliasIterator.
struct AndersenOTFResult {
TypedVector<ValueId, RawAliasSet<ValueId>> AliasSets;
Expand Down Expand Up @@ -63,7 +112,7 @@ struct AndersenOTFResult {
}
};

static_assert(UnionFindAAResult<AndersenOTFResult>);
static_assert(RawAAResult<AndersenOTFResult>);

/// Andersen-style inclusion-based points-to analysis that co-refines the call
/// graph and points-to sets in a single fixpoint.
Expand All @@ -72,13 +121,16 @@ static_assert(UnionFindAAResult<AndersenOTFResult>);
/// function-worklist loop: direct calls add callees immediately; indirect
/// calls are resolved as \c pts(fp) grows.
///
/// Phase 1: context- and field-insensitive.
/// Context-sensitivity is opt-in via \c ContextSensitivityOptions and off by
/// default.
class AndersenOTFSolver {
public:
explicit AndersenOTFSolver(const LLVMProjectIRDB &IRDB,
llvm::ArrayRef<const llvm::Function *> Entries,
ValueCompressor<PAGVariable> &VC,
Soundness S = Soundness::Soundy) noexcept;
explicit AndersenOTFSolver(const LLVMProjectIRDB &IRDB PSR_LIFETIMEBOUND,
llvm::ArrayRef<const llvm::Function *> Entries
PSR_LIFETIMEBOUND,
ValueCompressor<PAGVariable> &VC PSR_LIFETIMEBOUND,
Soundness S = Soundness::Soundy,
ContextSensitivityOptions CSOpts = {}) noexcept;

/// Run the full OTF fixpoint and return the alias-analysis result.
[[nodiscard]] AndersenOTFResult solve();
Expand All @@ -90,6 +142,7 @@ class AndersenOTFSolver {
llvm::ArrayRef<const llvm::Function *> Entries;
NonNullPtr<ValueCompressor<PAGVariable>> VC;
Soundness S;
ContextSensitivityOptions CSOpts;
};

// ---- Factory functions ------------------------------------------------
Expand All @@ -100,14 +153,16 @@ class AndersenOTFSolver {
computeAndersenOTFRaw(const LLVMProjectIRDB &IRDB,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
MaybeUniquePtr<ValueCompressor<PAGVariable>> VC = nullptr,
Soundness S = Soundness::Soundy);
Soundness S = Soundness::Soundy,
ContextSensitivityOptions CSOpts = {});

/// Runs the Andersen OTF fixpoint and returns an \c LLVMUnionFindAliasIterator
/// that implements \c IsLLVMAliasIterator.
[[nodiscard]] LLVMUnionFindAliasIterator<AndersenOTFResult>
[[nodiscard]] LLVMRawAliasIterator<AndersenOTFResult>
computeAndersenOTF(const LLVMProjectIRDB &IRDB,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
MaybeUniquePtr<ValueCompressor<PAGVariable>> VC = nullptr,
Soundness S = Soundness::Soundy);
Soundness S = Soundness::Soundy,
ContextSensitivityOptions CSOpts = {});

} // namespace psr
170 changes: 170 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/LLVMPointerSemantics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#pragma once

/******************************************************************************
* Copyright (c) 2026 Fabian Schiebel.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of LICENSE.txt.
*
* Contributors:
* Fabian Schiebel and others
*****************************************************************************/

#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
#include "phasar/Utils/Utilities.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"

#include <optional>

/// LLVM-level questions that LLVMPAGBuilder and AndersenOTFSolver must answer
/// identically. They emit different node and edge kinds, but must not disagree
/// on which IR constructs carry pointers.

namespace psr {

/// Whether a value of the pointer-free type \p Ty is laid out such that it
/// could hold pointer bit patterns.
[[nodiscard]] inline bool mayHidePointer(const llvm::DataLayout &DL,
const llvm::Type *Ty) {
if (Ty->isIntegerTy(DL.getPointerSizeInBits())) {
return true;
}
if (const auto *Arr = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
return mayHidePointer(DL, Arr->getElementType());
}
const auto *Struct = llvm::dyn_cast<llvm::StructType>(Ty);
return Struct && !Struct->isOpaque() && !Struct->elements().empty() &&
llvm::all_of(Struct->elements(), [&DL](const llvm::Type *ElemTy) {
return mayHidePointer(DL, ElemTy);
});
}

/// Whether Ptr is a memory-location (alloca or global), accessed as an
/// integer.
///
/// Useful for handling atomicrmw of pointers, which clang punns to i64, and
/// for ABI-coerced aggregates (see PunnedABICache).
[[nodiscard]] inline bool isPunnedPointerAccess(const llvm::DataLayout &DL,
const llvm::Value *Ptr,
const llvm::Type *AccessedTy) {
if (!mayHidePointer(DL, AccessedTy)) {
return false;
}
const llvm::Value *Base = Ptr->stripPointerCastsAndAliases();
if (const auto *A = llvm::dyn_cast<llvm::AllocaInst>(Base)) {
return !definitelyContainsNoPointer(A->getAllocatedType());
}
if (const auto *G = llvm::dyn_cast<llvm::GlobalVariable>(Base)) {
return !definitelyContainsNoPointer(G->getValueType());
}
return false;
}

/// The memory access to model for a load, store, atomicrmw or cmpxchg.
struct LLVMMemoryAccess {
const llvm::Instruction *Instr{};
const llvm::Value *Pointer{};
/// Null if the access only reads.
const llvm::Value *StoredValue{};
/// Null if the access only writes; \c Instr itself for an atomic.
const llvm::Instruction *LoadedInto{};
bool Punned{};

/// The value whose type decides whether a pointer is transferred. For a
/// cmpxchg that is the new value, not the { ty, i1 } result.
[[nodiscard]] const llvm::Value *transferredValue() const noexcept {
return StoredValue ? StoredValue : LoadedInto;
}

/// Whether the access has to be modeled at all. Gating on
/// definitelyContainsNoPointer alone would drop punned accesses.
[[nodiscard]] bool mayTransferPointer() const {
return Punned || !definitelyContainsNoPointer(transferredValue());
}
};

/// Decomposes \p I, or returns nullopt if it is not a memory access. Field-
/// insensitively an atomicrmw is a store of the new value plus a load of the
/// old one; cmpxchg likewise, into its { ty, i1 } result.
///
/// The result still has to pass mayTransferPointer().
[[nodiscard]] inline std::optional<LLVMMemoryAccess>
asMemoryAccess(const llvm::Instruction &I, const llvm::DataLayout &DL) {
const auto Make = [&DL, &I](const llvm::Value *Ptr,
const llvm::Value *StoredValue,
const llvm::Instruction *LoadedInto) {
const auto *Transferred = StoredValue ? StoredValue : LoadedInto;
return LLVMMemoryAccess{
.Instr = &I,
.Pointer = Ptr,
.StoredValue = StoredValue,
.LoadedInto = LoadedInto,
.Punned = isPunnedPointerAccess(DL, Ptr, Transferred->getType()),
};
};

if (const auto *S = llvm::dyn_cast<llvm::StoreInst>(&I)) {
return Make(S->getPointerOperand(), S->getValueOperand(), nullptr);
}
if (const auto *L = llvm::dyn_cast<llvm::LoadInst>(&I)) {
return Make(L->getPointerOperand(), nullptr, L);
}
if (const auto *RMW = llvm::dyn_cast<llvm::AtomicRMWInst>(&I)) {
return Make(RMW->getPointerOperand(), RMW->getValOperand(), RMW);
}
if (const auto *CX = llvm::dyn_cast<llvm::AtomicCmpXchgInst>(&I)) {
return Make(CX->getPointerOperand(), CX->getNewValOperand(), CX);
}
return std::nullopt;
}

/// Recognizes ABI-coerced boundary values: values that carry a pointer
/// although their type has none.
///
/// A small pointer-carrying struct is passed and returned in registers:
///
/// For whatever reason, on AArch64 clang punns such nested pointers as i64
/// instead of ptr. This here is a best-effort approcach to keep pointer
/// data-flows in such situations.
class PunnedABICache {
public:
explicit PunnedABICache(const llvm::DataLayout *DL) noexcept
: DL(&assertNotNull(DL)) {}

/// Whether \p V -- an argument, returned value or call result of \p F --
/// carries a pointer that its type does not reveal.
[[nodiscard]] bool isCoercedPointer(const llvm::Value *V,
const llvm::Function *F) {
return !llvm::isa<llvm::ConstantData>(V) &&
definitelyContainsNoPointer(V->getType()) &&
mayHidePointer(*DL, V->getType()) && punsPointers(F);
}

private:
bool punsPointers(const llvm::Function *F) {
auto [It, Inserted] = Cache.try_emplace(F, false);
if (Inserted) {
It->second = llvm::any_of(llvm::instructions(*F), [this](const auto &I) {
const auto Access = asMemoryAccess(I, *DL);
return Access && Access->Punned;
});
}
return It->second;
}

const llvm::DataLayout *DL;
llvm::DenseMap<const llvm::Function *, bool> Cache;
};

} // namespace psr
Loading
Loading