Skip to content

Commit

Permalink
Split LLVMBasedICFG (#726)
Browse files Browse the repository at this point in the history
* Out-source globals model

* Mode call-graph construction

* small refactor

* Cleanup resolver headers

* buildCallGraph speedup for non-OTF resolvers

* Move isVirtualCall into Resolver + some refactoring

* Move EntryFunctionUtils into phasar_llvm_controlflow to avoid circular library dependencies between phasar_llvm_db and phasar_llvm_utils

* Add more constness
  • Loading branch information
fabianbs96 authored Oct 22, 2024
1 parent f17594d commit bb86c25
Show file tree
Hide file tree
Showing 22 changed files with 692 additions and 429 deletions.
1 change: 1 addition & 0 deletions include/phasar/PhasarLLVM/ControlFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef PHASAR_PHASARLLVM_CONTROLFLOW_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_H

#include "phasar/PhasarLLVM/ControlFlow/EntryFunctionUtils.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardCFG.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h"
Expand Down
31 changes: 31 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/EntryFunctionUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/******************************************************************************
* Copyright (c) 2024 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_UTILS_ENTRYFUNCTIONUTILS_H
#define PHASAR_PHASARLLVM_UTILS_ENTRYFUNCTIONUTILS_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Function.h"

#include <string>
#include <vector>

namespace psr {
class LLVMProjectIRDB;

[[nodiscard]] std::vector<const llvm::Function *>
getEntryFunctions(const LLVMProjectIRDB &IRDB,
llvm::ArrayRef<std::string> EntryPoints);

[[nodiscard]] std::vector<llvm::Function *>
getEntryFunctionsMut(LLVMProjectIRDB &IRDB,
llvm::ArrayRef<std::string> EntryPoints);
} // namespace psr

#endif // PHASAR_PHASARLLVM_UTILS_ENTRYFUNCTIONUTILS_H
45 changes: 45 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/GlobalCtorsDtorsModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2024 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_CONTROLFLOW_GLOBALCTORSDTORSMODEL_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_GLOBALCTORSDTORSMODEL_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Function.h"

namespace psr {
class LLVMProjectIRDB;

class GlobalCtorsDtorsModel {
public:
static constexpr llvm::StringLiteral ModelName =
"__psrCRuntimeGlobalCtorsModel";

static constexpr llvm::StringLiteral DtorModelName =
"__psrCRuntimeGlobalDtorsModel";

static constexpr llvm::StringLiteral DtorsCallerName =
"__psrGlobalDtorsCaller";

static constexpr llvm::StringLiteral UserEntrySelectorName =
"__psrCRuntimeUserEntrySelector";

static llvm::Function *
buildModel(LLVMProjectIRDB &IRDB,
llvm::ArrayRef<llvm::Function *> UserEntryPoints);
static llvm::Function *
buildModel(LLVMProjectIRDB &IRDB,
llvm::ArrayRef<std::string> UserEntryPoints);

/// Returns true, if a function was generated by phasar.
[[nodiscard]] static bool isPhasarGenerated(const llvm::Function &F) noexcept;
};
} // namespace psr

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_GLOBALCTORSDTORSMODEL_H
25 changes: 25 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2024 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_CONTROLFLOW_LLVMBASEDCALLGRAPH_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCALLGRAPH_H

#include "phasar/ControlFlow/CallGraph.h"

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

namespace psr {
using LLVMBasedCallGraph =
CallGraph<const llvm::Instruction *, const llvm::Function *>;
} // namespace psr

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCALLGRAPH_H
49 changes: 49 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraphBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/******************************************************************************
* Copyright (c) 2024 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_CONTROLFLOW_LLVMBASEDCALLGRAPHBUILDER_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCALLGRAPHBUILDER_H

#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/Utils/Soundness.h"

namespace psr {
class LLVMProjectIRDB;
enum class CallGraphAnalysisType;
class LLVMTypeHierarchy;
class LLVMVFTableProvider;
class Resolver;

[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
LLVMTypeHierarchy &TH, LLVMVFTableProvider &VTP,
LLVMAliasInfoRef PT = nullptr,
Soundness S = Soundness::Soundy);

[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
Soundness S = Soundness::Soundy);

[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
llvm::ArrayRef<std::string> EntryPoints,
LLVMTypeHierarchy &TH, LLVMVFTableProvider &VTP,
LLVMAliasInfoRef PT = nullptr,
Soundness S = Soundness::Soundy);

[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
llvm::ArrayRef<std::string> EntryPoints,
Soundness S = Soundness::Soundy);
} // namespace psr

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCALLGRAPHBUILDER_H
37 changes: 16 additions & 21 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
#include "phasar/ControlFlow/CallGraph.h"
#include "phasar/ControlFlow/CallGraphAnalysisType.h"
#include "phasar/ControlFlow/ICFGBase.h"
#include "phasar/PhasarLLVM/ControlFlow/GlobalCtorsDtorsModel.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h"
#include "phasar/PhasarLLVM/ControlFlow/LLVMVFTableProvider.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/PhasarLLVM/Utils/LLVMBasedContainerConfig.h"
#include "phasar/Utils/MaybeUniquePtr.h"
#include "phasar/Utils/Soundness.h"

#include "llvm/ADT/ArrayRef.h"
Expand All @@ -46,20 +49,10 @@ template <> struct CFGTraits<LLVMBasedICFG> : CFGTraits<LLVMBasedCFG> {};
class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
friend ICFGBase;

struct Builder;

public:
// For backward compatibility
static constexpr llvm::StringLiteral GlobalCRuntimeModelName =
"__psrCRuntimeGlobalCtorsModel";

static constexpr llvm::StringLiteral GlobalCRuntimeDtorModelName =
"__psrCRuntimeGlobalDtorsModel";

static constexpr llvm::StringLiteral GlobalCRuntimeDtorsCallerName =
"__psrGlobalDtorsCaller";

static constexpr llvm::StringLiteral GlobalCRuntimeUserEntrySelectorName =
"__psrCRuntimeUserEntrySelector";
GlobalCtorsDtorsModel::ModelName;

/// Constructs the ICFG based on the given IRDB and the entry-points using a
/// fixpoint iteration. This may take a long time.
Expand Down Expand Up @@ -95,9 +88,9 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
bool IncludeGlobals = true);

/// Creates an ICFG with an already given call-graph
explicit LLVMBasedICFG(CallGraph<n_t, f_t> CG, LLVMProjectIRDB *IRDB);
explicit LLVMBasedICFG(CallGraph<n_t, f_t> CG, const LLVMProjectIRDB *IRDB);

explicit LLVMBasedICFG(LLVMProjectIRDB *IRDB,
explicit LLVMBasedICFG(const LLVMProjectIRDB *IRDB,
const CallGraphData &SerializedCG);

// Deleter of LLVMTypeHierarchy may be unknown here...
Expand Down Expand Up @@ -131,10 +124,13 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
}

/// Gets the underlying IRDB
[[nodiscard]] LLVMProjectIRDB *getIRDB() const noexcept { return IRDB; }
[[nodiscard]] const LLVMProjectIRDB *getIRDB() const noexcept { return IRDB; }

/// Returns true, if a function was generated by phasar.
[[nodiscard]] static bool isPhasarGenerated(const llvm::Function &) noexcept;
[[nodiscard]] static bool
isPhasarGenerated(const llvm::Function &F) noexcept {
return GlobalCtorsDtorsModel::isPhasarGenerated(F);
}

using CFGBase::print;
using ICFGBase::print;
Expand All @@ -157,22 +153,21 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
void printImpl(llvm::raw_ostream &OS) const;
void printAsJsonImpl(llvm::raw_ostream &OS) const;
[[nodiscard, deprecated]] nlohmann::json getAsJsonImpl() const;
[[nodiscard]] const CallGraph<n_t, f_t> &getCallGraphImpl() const noexcept {
[[nodiscard]] const LLVMBasedCallGraph &getCallGraphImpl() const noexcept {
return CG;
}

[[nodiscard]] llvm::Function *buildCRuntimeGlobalCtorsDtorsModel(
llvm::Module &M, llvm::ArrayRef<llvm::Function *> UserEntryPoints);

void initialize(LLVMProjectIRDB *IRDB, Resolver &CGResolver,
llvm::ArrayRef<std::string> EntryPoints,
const LLVMVFTableProvider &VTP, Soundness S,
llvm::ArrayRef<std::string> EntryPoints, Soundness S,
bool IncludeGlobals);

// ---

CallGraph<const llvm::Instruction *, const llvm::Function *> CG;
LLVMProjectIRDB *IRDB = nullptr;
LLVMBasedCallGraph CG;
const LLVMProjectIRDB *IRDB = nullptr;
LLVMVFTableProvider VTP;
};

Expand Down
6 changes: 5 additions & 1 deletion include/phasar/PhasarLLVM/ControlFlow/Resolver/CHAResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

namespace llvm {
class CallBase;
class Function;
} // namespace llvm

namespace psr {
Expand All @@ -38,6 +37,11 @@ class CHAResolver : public Resolver {

[[nodiscard]] std::string str() const override;

[[nodiscard]] bool
mutatesHelperAnalysisInformation() const noexcept override {
return false;
}

protected:
MaybeUniquePtr<const LLVMTypeHierarchy, true> TH;
};
Expand Down
28 changes: 16 additions & 12 deletions include/phasar/PhasarLLVM/ControlFlow/Resolver/DTAResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ class DTAResolver : public CHAResolver {
public:
using TypeGraph_t = CachedTypeGraph;

DTAResolver(const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP,
const LLVMTypeHierarchy *TH);

~DTAResolver() override = default;

FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;

void otherInst(const llvm::Instruction *Inst) override;

[[nodiscard]] std::string str() const override;

[[nodiscard]] bool
mutatesHelperAnalysisInformation() const noexcept override {
return false;
}

protected:
TypeGraph_t TypeGraph;

Expand All @@ -53,18 +69,6 @@ class DTAResolver : public CHAResolver {
* of vtable)
*/
bool heuristicAntiConstructorVtablePos(const llvm::BitCastInst *BitCast);

public:
DTAResolver(const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP,
const LLVMTypeHierarchy *TH);

~DTAResolver() override = default;

FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;

void otherInst(const llvm::Instruction *Inst) override;

[[nodiscard]] std::string str() const override;
};
} // namespace psr

Expand Down
24 changes: 6 additions & 18 deletions include/phasar/PhasarLLVM/ControlFlow/Resolver/NOResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,27 @@
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"

namespace llvm {
class Instruction;
class CallBase;
class Function;
class StructType;
} // namespace llvm

namespace psr {

class NOResolver final : public Resolver {
protected:
const llvm::Function *
getNonPureVirtualVFTEntry(const llvm::StructType *T, unsigned Idx,
const llvm::CallBase *CallSite);

public:
NOResolver(const LLVMProjectIRDB *IRDB);
NOResolver(const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP);

~NOResolver() override = default;

void preCall(const llvm::Instruction *Inst) override;

void handlePossibleTargets(const llvm::CallBase *CallSite,
FunctionSetTy &PossibleTargets) override;

void postCall(const llvm::Instruction *Inst) override;

FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;

FunctionSetTy resolveFunctionPointer(const llvm::CallBase *CallSite) override;

void otherInst(const llvm::Instruction *Inst) override;

[[nodiscard]] std::string str() const override;

[[nodiscard]] bool
mutatesHelperAnalysisInformation() const noexcept override {
return false;
}
};
} // namespace psr

Expand Down
Loading

0 comments on commit bb86c25

Please sign in to comment.