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 10 commits into
base: development
Choose a base branch
from
124 changes: 124 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/******************************************************************************
* 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/Support/ErrorHandling.h"

#include "nlohmann/json_fwd.hpp"

#include <type_traits>
#include <utility>

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

namespace psr {

class LLVMAliasSet;
class FilteredLLVMAliasSet;

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

class FilteredLLVMAliasSet {
public:
using traits_t = AliasInfoTraits<FilteredLLVMAliasSet>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

you might call it alias_traits_t so it easier to see what kind of traits one accesses in the following code.

using n_t = traits_t::n_t;
using v_t = traits_t::v_t;
using AliasSetTy = traits_t::AliasSetTy;
using AliasSetPtrTy = traits_t::AliasSetPtrTy;
using AllocationSiteSetPtrTy = traits_t::AllocationSiteSetPtrTy;

FilteredLLVMAliasSet(LLVMAliasSet *AS) noexcept;

FilteredLLVMAliasSet(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(FilteredLLVMAliasSet &&) = 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 &operator=(FilteredLLVMAliasSet &&) = delete;
FilteredLLVMAliasSet &operator=(FilteredLLVMAliasSet &&) noexcept = delete;

Copy link
Member Author

Choose a reason for hiding this comment

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

Does it make a difference to declare a deleted function noexcept?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, a) you do the same thing for the move ctor and b) with noexcept is the correct signature of the function, so deleting it like this is the proper way


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:
FilteredLLVMAliasSet(MaybeUniquePtr<LLVMAliasSet, true> AS) noexcept;

MaybeUniquePtr<LLVMAliasSet, true> AS;
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
MaybeUniquePtr<LLVMAliasSet, true> AS;
MaybeUniquePtr<LLVMAliasSet, true /*requiresAlignment*/> AS;

Copy link
Member Author

Choose a reason for hiding this comment

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

done

AliasSetOwner<AliasSetTy> Owner;
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
AliasSetMap;
};
} // 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
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)) {
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