Skip to content

Commit abeb431

Browse files
committed
Implement allocated-types collection in terms of debug info
1 parent 1feaf45 commit abeb431

File tree

7 files changed

+140
-80
lines changed

7 files changed

+140
-80
lines changed

include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
#include "llvm/IR/PassManager.h"
2121

2222
#include <set>
23+
#include <vector>
2324

2425
namespace llvm {
2526
class Type;
2627
class Value;
2728
class Instruction;
2829
class AnalysisUsage;
2930
class Module;
31+
class DICompositeType;
3032
} // namespace llvm
3133

3234
namespace psr {
@@ -67,7 +69,7 @@ struct GeneralStatistics {
6769
size_t NumInstWithMultipleUses = 0;
6870
size_t NumInstsUsedOutsideBB = 0;
6971
size_t NonVoidInsts = 0;
70-
std::set<const llvm::Type *> AllocatedTypes;
72+
std::vector<const llvm::DICompositeType *> AllocatedTypes;
7173
std::set<const llvm::Instruction *> AllocaInstructions;
7274
std::set<const llvm::Instruction *> RetResInstructions;
7375
std::string ModuleName{};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/******************************************************************************
2+
* Copyright (c) 2025 Fabian Schiebel.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_PHASARLLVM_UTILS_ALLOCATEDTYPES_H
11+
#define PHASAR_PHASARLLVM_UTILS_ALLOCATEDTYPES_H
12+
13+
#include "llvm/IR/DebugInfoMetadata.h"
14+
15+
#include <vector>
16+
17+
namespace psr {
18+
class LLVMProjectIRDB;
19+
20+
[[nodiscard]] std::vector<const llvm::DICompositeType *>
21+
collectAllocatedTypes(const LLVMProjectIRDB &IRDB);
22+
23+
[[nodiscard]] std::vector<const llvm::DICompositeType *>
24+
collectAllocatedTypes(const llvm::Module &Mod);
25+
} // namespace psr
26+
27+
#endif // PHASAR_PHASARLLVM_UTILS_ALLOCATEDTYPES_H

include/phasar/PhasarLLVM/Utils/LLVMShorthands.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ std::string llvmIRToShortString(const llvm::Value *V);
104104
[[nodiscard]] std::string llvmTypeToString(const llvm::Type *Ty,
105105
bool Shorten = false);
106106

107+
/**
108+
* @brief Returns a string-representation of a LLVM Debug-Info type.
109+
*
110+
* @param Shorten Tries to shorten the output
111+
*/
112+
[[nodiscard]] std::string llvmTypeToString(const llvm::DIType *Ty,
113+
bool Shorten = false);
114+
107115
LLVM_DUMP_METHOD void dumpIRValue(const llvm::Value *V);
108116
LLVM_DUMP_METHOD void dumpIRValue(const llvm::Instruction *V);
109117
LLVM_DUMP_METHOD void dumpIRValue(const llvm::Function *V);

lib/PhasarLLVM/ControlFlow/Resolver/RTAResolver.cpp

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,12 @@
1818

1919
#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h"
2020
#include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h"
21-
#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h"
21+
#include "phasar/PhasarLLVM/Utils/AllocatedTypes.h"
2222
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
2323
#include "phasar/Utils/Logger.h"
2424

25-
#include "llvm/BinaryFormat/Dwarf.h"
26-
#include "llvm/IR/DebugInfoMetadata.h"
27-
#include "llvm/IR/DerivedTypes.h"
2825
#include "llvm/IR/Function.h"
2926
#include "llvm/IR/InstrTypes.h"
30-
#include "llvm/IR/Instructions.h"
31-
#include "llvm/Support/Casting.h"
3227
#include "llvm/Support/raw_ostream.h"
3328

3429
using namespace psr;
@@ -85,52 +80,10 @@ void RTAResolver::resolveVirtualCall(FunctionSetTy &PossibleTargets,
8580

8681
std::string RTAResolver::str() const { return "RTA"; }
8782

88-
static const llvm::DICompositeType *
89-
isCompositeStructType(const llvm::DIType *Ty) {
90-
if (const auto *CompTy = llvm::dyn_cast_if_present<llvm::DICompositeType>(Ty);
91-
CompTy && (CompTy->getTag() == llvm::dwarf::DW_TAG_structure_type ||
92-
CompTy->getTag() == llvm::dwarf::DW_TAG_class_type)) {
93-
94-
return CompTy;
95-
}
96-
97-
return nullptr;
98-
}
99-
10083
void RTAResolver::resolveAllocatedCompositeTypes() {
10184
if (!AllocatedCompositeTypes.empty()) {
10285
return;
10386
}
10487

105-
llvm::DenseSet<const llvm::DICompositeType *> AllocatedTypes;
106-
107-
for (const auto *Inst : IRDB->getAllInstructions()) {
108-
if (const auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Inst)) {
109-
if (const auto *Ty = isCompositeStructType(getVarTypeFromIR(Alloca))) {
110-
AllocatedTypes.insert(Ty);
111-
}
112-
} else if (const auto *Call = llvm::dyn_cast<llvm::CallBase>(Inst)) {
113-
if (const auto *Callee = llvm::dyn_cast<llvm::Function>(
114-
Call->getCalledOperand()->stripPointerCastsAndAliases())) {
115-
if (psr::isHeapAllocatingFunction(Callee)) {
116-
const auto *MDNode = Call->getMetadata("heapallocsite");
117-
if (const auto *CompTy = llvm::
118-
#if LLVM_VERSION_MAJOR >= 15
119-
dyn_cast_if_present
120-
#else
121-
dyn_cast_or_null
122-
#endif
123-
<llvm::DICompositeType>(MDNode);
124-
isCompositeStructType(CompTy)) {
125-
126-
AllocatedTypes.insert(CompTy);
127-
}
128-
}
129-
}
130-
}
131-
}
132-
133-
AllocatedCompositeTypes.reserve(AllocatedTypes.size());
134-
AllocatedCompositeTypes.insert(AllocatedCompositeTypes.end(),
135-
AllocatedTypes.begin(), AllocatedTypes.end());
88+
AllocatedCompositeTypes = collectAllocatedTypes(*IRDB);
13689
}

lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h"
1111

12+
#include "phasar/PhasarLLVM/Utils/AllocatedTypes.h"
1213
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
1314
#include "phasar/Utils/Logger.h"
1415
#include "phasar/Utils/NlohmannLogging.h"
@@ -41,31 +42,6 @@ static bool isAddressTaken(const llvm::Function &Fun) noexcept {
4142
return false;
4243
}
4344

44-
template <typename Set>
45-
static void collectAllocatedTypes(const llvm::CallBase *CallSite, Set &Into) {
46-
for (const auto *User : CallSite->users()) {
47-
if (const auto *Cast = llvm::dyn_cast<llvm::BitCastInst>(User);
48-
Cast && Cast->getDestTy()->isPointerTy() &&
49-
!Cast->getDestTy()->isOpaquePointerTy()) {
50-
const auto *ElemTy = Cast->getDestTy()->getNonOpaquePointerElementType();
51-
if (ElemTy->isStructTy()) {
52-
// finally check for ctor call
53-
for (const auto *User : Cast->users()) {
54-
if (llvm::isa<llvm::CallBase>(User)) {
55-
// potential call to the structures ctor
56-
const auto *CTor = llvm::cast<llvm::CallBase>(User);
57-
if (CTor->getCalledFunction() &&
58-
CTor->getCalledFunction()->getArg(0)->getType() ==
59-
Cast->getDestTy()) {
60-
Into.insert(ElemTy);
61-
}
62-
}
63-
}
64-
}
65-
}
66-
}
67-
}
68-
6945
llvm::AnalysisKey GeneralStatisticsAnalysis::Key; // NOLINT
7046
GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) {
7147
PHASAR_LOG_LEVEL(INFO, "Running GeneralStatisticsAnalysis");
@@ -131,7 +107,6 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) {
131107
// check for alloca instruction for possible types
132108
if (const llvm::AllocaInst *Alloc =
133109
llvm::dyn_cast<llvm::AllocaInst>(&I)) {
134-
Stats.AllocatedTypes.insert(Alloc->getAllocatedType());
135110
// do not add allocas from llvm internal functions
136111
Stats.AllocaInstructions.insert(&I);
137112
++Stats.AllocationSites;
@@ -186,9 +161,6 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) {
186161
// do not add allocas from llvm internal functions
187162
Stats.AllocaInstructions.insert(&I);
188163
++Stats.AllocationSites;
189-
// check if an instance of a user-defined type is allocated on the
190-
// heap
191-
collectAllocatedTypes(CallSite, Stats.AllocatedTypes);
192164
}
193165
} else {
194166
++Stats.IndCalls;
@@ -197,6 +169,9 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) {
197169
}
198170
}
199171
}
172+
173+
Stats.AllocatedTypes = collectAllocatedTypes(M);
174+
200175
// check for global pointers
201176
for (const auto &Global : M.globals()) {
202177
++Stats.Globals;
@@ -323,7 +298,7 @@ template <typename T> struct AlignNum {
323298
}
324299
};
325300
template <typename T> AlignNum(llvm::StringRef, T) -> AlignNum<T>;
326-
AlignNum(llvm::StringRef, size_t, size_t)->AlignNum<double>;
301+
AlignNum(llvm::StringRef, size_t, size_t) -> AlignNum<double>;
327302
} // namespace
328303

329304
llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include "phasar/PhasarLLVM/Utils/AllocatedTypes.h"
2+
3+
#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h"
4+
#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h"
5+
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
6+
7+
#include "llvm/ADT/DenseSet.h"
8+
#include "llvm/BinaryFormat/Dwarf.h"
9+
#include "llvm/IR/InstIterator.h"
10+
#include "llvm/IR/InstrTypes.h"
11+
#include "llvm/IR/Instructions.h"
12+
13+
static const llvm::DICompositeType *
14+
isCompositeStructType(const llvm::DIType *Ty) {
15+
if (const auto *CompTy = llvm::dyn_cast_if_present<llvm::DICompositeType>(Ty);
16+
CompTy && (CompTy->getTag() == llvm::dwarf::DW_TAG_structure_type ||
17+
CompTy->getTag() == llvm::dwarf::DW_TAG_class_type)) {
18+
19+
return CompTy;
20+
}
21+
22+
return nullptr;
23+
}
24+
25+
std::vector<const llvm::DICompositeType *>
26+
psr::collectAllocatedTypes(const llvm::Module &Mod) {
27+
llvm::DenseSet<const llvm::DICompositeType *> AllocatedTypes;
28+
29+
for (const auto &Fun : Mod) {
30+
for (const auto &Inst : llvm::instructions(Fun)) {
31+
if (const auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(&Inst)) {
32+
if (const auto *Ty = isCompositeStructType(getVarTypeFromIR(Alloca))) {
33+
AllocatedTypes.insert(Ty);
34+
}
35+
} else if (const auto *Call = llvm::dyn_cast<llvm::CallBase>(&Inst)) {
36+
if (const auto *Callee = llvm::dyn_cast<llvm::Function>(
37+
Call->getCalledOperand()->stripPointerCastsAndAliases())) {
38+
if (psr::isHeapAllocatingFunction(Callee)) {
39+
const auto *MDNode = Call->getMetadata("heapallocsite");
40+
if (const auto *CompTy = llvm::
41+
#if LLVM_VERSION_MAJOR >= 15
42+
dyn_cast_if_present
43+
#else
44+
dyn_cast_or_null
45+
#endif
46+
<llvm::DICompositeType>(MDNode);
47+
isCompositeStructType(CompTy)) {
48+
49+
AllocatedTypes.insert(CompTy);
50+
}
51+
}
52+
}
53+
}
54+
}
55+
}
56+
57+
std::vector<const llvm::DICompositeType *> AllocatedCompositeTypes;
58+
AllocatedCompositeTypes.reserve(AllocatedTypes.size());
59+
AllocatedCompositeTypes.insert(AllocatedCompositeTypes.end(),
60+
AllocatedTypes.begin(), AllocatedTypes.end());
61+
return AllocatedCompositeTypes;
62+
}
63+
64+
std::vector<const llvm::DICompositeType *>
65+
psr::collectAllocatedTypes(const LLVMProjectIRDB &IRDB) {
66+
return collectAllocatedTypes(*IRDB.getModule());
67+
}

lib/PhasarLLVM/Utils/LLVMShorthands.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,34 @@ std::string psr::llvmTypeToString(const llvm::Type *Ty, bool Shorten) {
235235
return IRBuffer;
236236
}
237237

238+
std::string psr::llvmTypeToString(const llvm::DIType *Ty, bool Shorten) {
239+
if (!Ty) {
240+
return "<null>";
241+
}
242+
243+
std::string Ret;
244+
245+
if (Shorten) {
246+
Ret = Ty->getName().str();
247+
if (!Ret.empty()) {
248+
// Try to get a fully-qualified name
249+
250+
const auto *Scope = Ty->getScope();
251+
while (llvm::isa_and_nonnull<llvm::DINamespace, llvm::DISubprogram,
252+
llvm::DIType>(Scope)) {
253+
// XXX: Optimize this
254+
Ret = Scope->getName().str().append("::").append(Ret);
255+
Scope = Scope->getScope();
256+
}
257+
return Ret;
258+
}
259+
}
260+
261+
llvm::raw_string_ostream RSO(Ret);
262+
Ty->print(RSO);
263+
return Ret;
264+
}
265+
238266
void psr::dumpIRValue(const llvm::Value *V) {
239267
llvm::outs() << llvmIRToString(V) << '\n';
240268
}

0 commit comments

Comments
 (0)