@@ -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
14671559using IDEInstInteractionAnalysis = IDEInstInteractionAnalysisT<>;
0 commit comments