Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtered AliasSet #723

Open
wants to merge 9 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
154 changes: 154 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/******************************************************************************
* Copyright (c) 2020 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
*****************************************************************************/

#ifndef PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
#define PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H

#include "phasar/Pointer/AliasAnalysisType.h"
#include "phasar/Pointer/AliasInfoTraits.h"
#include "phasar/Pointer/AliasResult.h"
#include "phasar/Pointer/AliasSetOwner.h"
#include "phasar/Utils/AnalysisProperties.h"
#include "phasar/Utils/MaybeUniquePtr.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/ErrorHandling.h"

#include "nlohmann/json_fwd.hpp"

#include <type_traits>
#include <utility>

namespace llvm {
class Value;
class Instruction;
} // namespace llvm

namespace psr {

class LLVMAliasSet;
class FilteredLLVMAliasSet;

template <>
struct AliasInfoTraits<FilteredLLVMAliasSet>
: DefaultAATraits<const llvm::Value *, const llvm::Instruction *> {};

class FilteredLLVMAliasSet {
public:
using alias_traits_t = AliasInfoTraits<FilteredLLVMAliasSet>;
using n_t = alias_traits_t::n_t;
using v_t = alias_traits_t::v_t;
using AliasSetTy = alias_traits_t::AliasSetTy;
using AliasSetPtrTy = alias_traits_t::AliasSetPtrTy;
using AllocationSiteSetPtrTy = alias_traits_t::AllocationSiteSetPtrTy;

FilteredLLVMAliasSet(LLVMAliasSet *AS) noexcept;

FilteredLLVMAliasSet(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(FilteredLLVMAliasSet &&) noexcept = delete;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

FilteredLLVMAliasSet(FilteredLLVMAliasSet &&) noexcept = default;

~FilteredLLVMAliasSet();

template <typename... ArgsT,
typename = std::enable_if_t<
std::is_constructible_v<LLVMAliasSet, ArgsT...>>>
explicit FilteredLLVMAliasSet(ArgsT &&...Args)
: FilteredLLVMAliasSet(std::forward<ArgsT>(Args)...) {}

// --- API Functions:

[[nodiscard]] inline bool isInterProcedural() const noexcept {
return false;
};

[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept;

[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
const llvm::Instruction *I);
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
const llvm::Function *Fun);

[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
const llvm::Instruction *I);
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
const llvm::Function *Fun);

[[nodiscard]] AllocationSiteSetPtrTy
getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false,
const llvm::Instruction *I = nullptr);

// Checks if PotentialValue is in the reachable allocation sites of V.
[[nodiscard]] bool isInReachableAllocationSites(
const llvm::Value *V, const llvm::Value *PotentialValue,
bool IntraProcOnly = false, const llvm::Instruction *I = nullptr);

void mergeWith(const FilteredLLVMAliasSet & /*OtherPTI*/) {
llvm::report_fatal_error("Not Supported");
}

void introduceAlias(const llvm::Value * /*V1*/, const llvm::Value * /*V2*/,
const llvm::Instruction * /*I*/ = nullptr,
AliasResult /*Kind*/ = AliasResult::MustAlias) {
llvm::report_fatal_error("Not Supported");
}

void print(llvm::raw_ostream &OS = llvm::outs()) const;

[[nodiscard]] nlohmann::json getAsJson() const;

void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;

[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
return AnalysisProperties::None;
}

private:
struct ReachableAllocationSitesKey {
llvm::PointerIntPair<const llvm::Function *, 1, bool> FunAndIntraProcOnly;
v_t Value{};
};

struct ReachableAllocationSitesKeyDMI {
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
}
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
}
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
Key.Value);
}
inline static bool isEqual(ReachableAllocationSitesKey Key1,
ReachableAllocationSitesKey Key2) noexcept {
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
Key1.Value == Key2.Value;
}
};

FilteredLLVMAliasSet(MaybeUniquePtr<LLVMAliasSet, true> AS) noexcept;

MaybeUniquePtr<LLVMAliasSet, /*RequireAlignment=*/true> AS;
AliasSetOwner<AliasSetTy> Owner;
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
AliasSetMap;
llvm::DenseMap<ReachableAllocationSitesKey, std::unique_ptr<AliasSetTy>,
ReachableAllocationSitesKeyDMI>
ReachableAllocationSitesMap;
};
} // namespace psr

#endif // PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
2 changes: 2 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct AliasInfoTraits<LLVMAliasSet>

class LLVMAliasSet : public AnalysisPropertiesMixin<LLVMAliasSet>,
public AliasInfoBaseUtils {
// For int*IsReachableAllocationSiteTy:
friend class FilteredLLVMAliasSet;

public:
using traits_t = AliasInfoTraits<LLVMAliasSet>;
Expand Down
5 changes: 2 additions & 3 deletions include/phasar/Pointer/AliasInfoTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
#define PHASAR_POINTER_ALIASINFOTRAITS_H

#include "phasar/Utils/BoxedPointer.h"
#include "phasar/Utils/MaybeUniquePtr.h"

#include "llvm/ADT/DenseSet.h"

#include <memory>

namespace psr {

template <typename T> struct AliasInfoTraits {
Expand All @@ -31,7 +30,7 @@ template <typename V, typename N> struct DefaultAATraits {
using v_t = V;
using AliasSetTy = llvm::DenseSet<v_t>;
using AliasSetPtrTy = BoxedConstPtr<AliasSetTy>;
using AllocationSiteSetPtrTy = std::unique_ptr<AliasSetTy>;
using AllocationSiteSetPtrTy = MaybeUniquePtr<const AliasSetTy>;
};
} // namespace psr

Expand Down
8 changes: 5 additions & 3 deletions include/phasar/Utils/MaybeUniquePtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ template <typename T> class MaybeUniquePtrBase<T, true> {
/// \tparam RequireAlignment If true, the datastructure only works if
/// alignof(T) > 1 holds. Enables incomplete T types
template <typename T, bool RequireAlignment = false>
class MaybeUniquePtr : detail::MaybeUniquePtrBase<T, RequireAlignment> {
class [[clang::trivial_abi]] MaybeUniquePtr
: detail::MaybeUniquePtrBase<T, RequireAlignment> {
using detail::MaybeUniquePtrBase<T, RequireAlignment>::Data;

public:
Expand All @@ -79,8 +80,9 @@ class MaybeUniquePtr : detail::MaybeUniquePtrBase<T, RequireAlignment> {
: MaybeUniquePtr(Owner.release(), true) {}

constexpr MaybeUniquePtr(MaybeUniquePtr &&Other) noexcept
: detail::MaybeUniquePtrBase<T, RequireAlignment>(
std::exchange(Other.Data, {})) {}
: detail::MaybeUniquePtrBase<T, RequireAlignment>(std::move(Other)) {
Other.Data = {};
}

constexpr void swap(MaybeUniquePtr &Other) noexcept {
std::swap(Data, Other.Data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void IFDSTaintAnalysis::populateWithMayAliases(
container_type &Facts, const llvm::Instruction *Context) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name Context is misleading/confusing me, context rather resembles a calling context, while here it is used as the statement at which the aliases are requested, in the sense of flow-sensitivity

container_type Tmp = Facts;
for (const auto *Fact : Facts) {
auto Aliases = PT.getAliasSet(Fact);
auto Aliases = PT.getAliasSet(Fact, Context);
for (const auto *Alias : *Aliases) {
if (canSkipAtContext(Alias, Context)) {
continue;
Expand Down
Loading
Loading