Skip to content

Commit afcf8d8

Browse files
committed
apply temporary fix for global support in IIA analysis
1 parent e909fd2 commit afcf8d8

2 files changed

Lines changed: 114 additions & 22 deletions

File tree

include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDEInstInteractionAnalysis.h

Lines changed: 113 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class IDEInstInteractionAnalysisT
124124
this->ZeroValue =
125125
IDEInstInteractionAnalysisT<EdgeFactType, SyntacticAnalysisOnly,
126126
EnableIndirectTaints>::createZeroValue();
127+
this->Seeds =
128+
IDEInstInteractionAnalysisT<EdgeFactType, SyntacticAnalysisOnly,
129+
EnableIndirectTaints>::initialSeeds();
127130
IIAAAddLabelsEF::initEdgeFunctionCleaner();
128131
IIAAKillOrReplaceEF::initEdgeFunctionCleaner();
129132
}
@@ -156,10 +159,11 @@ class IDEInstInteractionAnalysisT
156159
// v v v
157160
// 0 x G
158161
//
159-
static auto Seeds = this->initialSeeds();
160-
static bool initGlobals = true;
161-
if (initGlobals && Seeds.countInitialSeeds(curr)) {
162-
initGlobals = false;
162+
// Global variables may only be initialized once.
163+
// They may also be initialized within getCallToRetFlowFunction() in case an
164+
// entry point is a function call. (See getCallToRetFlowFunction().)
165+
if (InitGlobals && Seeds.countInitialSeeds(curr)) {
166+
InitGlobals = false; // We are initializing globals here now.
163167
std::set<d_t> Globals;
164168
for (const auto *Mod : this->IRDB->getAllModules()) {
165169
for (const auto &Global : Mod->globals()) {
@@ -575,6 +579,40 @@ class IDEInstInteractionAnalysisT
575579
}
576580
}
577581
}
582+
// The entry point of a function may also be a call statement, which is why
583+
// we need to replicate the global generating code that we already saw in
584+
// getNormalFlowFunction(). Generate all global variables and handle the
585+
// instruction that we currently misuse to generate them.
586+
// TODO The handling of global variables, global constructors and global
587+
// destructors will soon be possible using a dedicated mechanism.
588+
//
589+
// Flow function:
590+
//
591+
// Let G be the set of global variables.
592+
//
593+
// 0
594+
// |\
595+
// some instruction | \--\
596+
// v v v
597+
// 0 x G
598+
//
599+
// Variable that will hold our generating globals function.
600+
FlowFunctionPtrType GlobalFlowFun = nullptr;
601+
// Global variables may only be initialized once.
602+
// They may also be initialized within getCallToRetFlowFunction() in case an
603+
// entry point is a function call. (See getCallToRetFlowFunction().)
604+
if (InitGlobals && Seeds.countInitialSeeds(callSite)) {
605+
InitGlobals = false; // We are initializing globals here now.
606+
std::set<d_t> Globals;
607+
for (const auto *Mod : this->IRDB->getAllModules()) {
608+
for (const auto &Global : Mod->globals()) {
609+
Globals.insert(&Global); // collect all global variables
610+
}
611+
}
612+
// Create the flow function that generates the globals.
613+
GlobalFlowFun =
614+
std::make_shared<GenAll<d_t>>(Globals, this->getZeroValue());
615+
}
578616
// Just use the auto mapping for values, pointer parameters and global
579617
// variables are killed and handled by getCallFlowfunction() and
580618
// getRetFlowFunction().
@@ -589,18 +627,36 @@ class IDEInstInteractionAnalysisT
589627
}
590628
}
591629
// Declarations only case
592-
return std::make_shared<MapFactsAlongsideCallSite<container_type>>(
593-
llvm::cast<llvm::CallBase>(callSite),
594-
true /* propagate globals alongsite the call site */,
595-
[](const llvm::CallBase *CS, const llvm::Value *V) {
596-
return false; // not involved in the call
597-
});
630+
if (OnlyDecls) {
631+
auto PassAsId =
632+
std::make_shared<MapFactsAlongsideCallSite<container_type>>(
633+
llvm::cast<llvm::CallBase>(callSite),
634+
true /* propagate globals alongsite the call site */,
635+
[](const llvm::CallBase *CS, const llvm::Value *V) {
636+
return false; // not involved in the call
637+
});
638+
if (GlobalFlowFun) {
639+
// We potentially need to combine this flow function with the global
640+
// generating flow function.
641+
return std::make_shared<Union<d_t>>(
642+
std::vector<FlowFunctionPtrType>({PassAsId, GlobalFlowFun}));
643+
}
644+
return PassAsId;
645+
}
598646
// Otherwise
599-
return std::make_shared<MapFactsAlongsideCallSite<container_type>>(
600-
llvm::cast<llvm::CallBase>(callSite),
601-
false // do not propagate globals (as they are propagated via call- and
602-
// ret-functions)
603-
);
647+
auto KillGlobals =
648+
std::make_shared<MapFactsAlongsideCallSite<container_type>>(
649+
llvm::cast<llvm::CallBase>(callSite),
650+
false // do not propagate globals (as they are propagated via call-
651+
// and ret-functions)
652+
);
653+
if (GlobalFlowFun) {
654+
// We potentially need to combine this flow function with the global
655+
// generating flow function.
656+
return std::make_shared<Union<d_t>>(
657+
std::vector<FlowFunctionPtrType>({KillGlobals, GlobalFlowFun}));
658+
}
659+
return KillGlobals;
604660
}
605661

606662
inline FlowFunctionPtrType getSummaryFlowFunction(n_t callSite,
@@ -682,13 +738,12 @@ class IDEInstInteractionAnalysisT
682738
//
683739
// Let g be a global variable.
684740
//
685-
// 0
686-
// \
687-
// %a = alloca \ \x.x \cup { commit of('@global') }
688-
// v
689-
// g
741+
// 0
742+
// \
743+
// non-call/non-return instruction \ \x.x \cup { commit of('@global') }
744+
// v
745+
// g
690746
//
691-
static auto Seeds = this->initialSeeds();
692747
static auto Globals = [this]() {
693748
std::set<d_t> Globals;
694749
for (const auto *Mod : this->IRDB->getAllModules()) {
@@ -1066,6 +1121,39 @@ class IDEInstInteractionAnalysisT
10661121
}
10671122
}
10681123
}
1124+
// TODO use new mechanism to handle globals.
1125+
//
1126+
// Zero --> Global edges
1127+
//
1128+
// Edge function:
1129+
//
1130+
// Let g be a global variable.
1131+
//
1132+
// 0
1133+
// \
1134+
// some callsite \ \x.x \cup { commit of('@global') }
1135+
// v
1136+
// g
1137+
//
1138+
static auto Globals = [this]() {
1139+
std::set<d_t> Globals;
1140+
for (const auto *Mod : this->IRDB->getAllModules()) {
1141+
for (const auto &G : Mod->globals()) {
1142+
Globals.insert(&G);
1143+
}
1144+
}
1145+
return Globals;
1146+
}();
1147+
if (Seeds.countInitialSeeds(callSite) && isZeroValue(callNode) &&
1148+
Globals.count(retSiteNode)) {
1149+
if (const auto *GlobalVarDef =
1150+
llvm::dyn_cast<llvm::GlobalVariable>(retSiteNode)) {
1151+
EdgeFacts = edgeFactGen(GlobalVarDef);
1152+
// fill BitVectorSet
1153+
UserEdgeFacts = BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
1154+
return IIAAAddLabelsEF::createEdgeFunction(UserEdgeFacts);
1155+
}
1156+
}
10691157
// Capture interactions of the call instruction and its operands.
10701158
for (const auto &Op : callSite->operands()) {
10711159
//
@@ -1462,6 +1550,10 @@ class IDEInstInteractionAnalysisT
14621550
return {};
14631551
}
14641552

1553+
// TODO This is only a temporary mechanism to handle global variables.
1554+
InitialSeeds<n_t, d_t, l_t> Seeds;
1555+
bool InitGlobals = true; // Globals must be initialized!
1556+
14651557
}; // namespace psr
14661558

14671559
using IDEInstInteractionAnalysis = IDEInstInteractionAnalysisT<>;

lib/Controller/AnalysisController.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ AnalysisController::AnalysisController(
7878
ProjectIRDB &IRDB, std::vector<DataFlowAnalysisKind> DataFlowAnalyses,
7979
std::vector<std::string> AnalysisConfigs, PointerAnalysisType PTATy,
8080
CallGraphAnalysisType CGTy, Soundness SoundnessLevel,
81-
bool AutomatedGlobalSupport, const std::set<std::string> &EntryPoints,
81+
bool AutoGlobalSupport, const std::set<std::string> &EntryPoints,
8282
AnalysisStrategy Strategy, AnalysisControllerEmitterOptions EmitterOptions,
8383
const std::string &ProjectID, const std::string &OutDirectory)
8484
: IRDB(IRDB), TH(IRDB), PT(IRDB, !needsToEmitPTA(EmitterOptions), PTATy),

0 commit comments

Comments
 (0)