@@ -107,14 +107,39 @@ predicate hasIndirectInstruction(Instruction instr, int indirectionIndex) {
107107cached
108108private newtype TDefOrUseImpl =
109109 TDefImpl ( Operand address , int indirectionIndex ) {
110- isDef ( _, _, address , _, _, indirectionIndex ) and
111- // We only include the definition if the SSA pruning stage
112- // concluded that the definition is live after the write.
113- any ( SsaInternals0:: Def def ) .getAddressOperand ( ) = address
110+ exists ( Instruction base | isDef ( _, _, address , base , _, indirectionIndex ) |
111+ // We only include the definition if the SSA pruning stage
112+ // concluded that the definition is live after the write.
113+ any ( SsaInternals0:: Def def ) .getAddressOperand ( ) = address
114+ or
115+ // Since the pruning stage doesn't know about global variables we can't use the above check to
116+ // rule out dead assignments to globals.
117+ base .( VariableAddressInstruction ) .getAstVariable ( ) instanceof Cpp:: GlobalOrNamespaceVariable
118+ )
114119 } or
115120 TUseImpl ( Operand operand , int indirectionIndex ) {
116121 isUse ( _, operand , _, _, indirectionIndex ) and
117122 not isDef ( _, _, operand , _, _, _)
123+ } or
124+ TGlobalUse ( Cpp:: GlobalOrNamespaceVariable v , IRFunction f , int indirectionIndex ) {
125+ // Represents a final "use" of a global variable to ensure that
126+ // the assignment to a global variable isn't ruled out as dead.
127+ exists ( VariableAddressInstruction vai , int defIndex |
128+ vai .getEnclosingIRFunction ( ) = f and
129+ vai .getAstVariable ( ) = v and
130+ isDef ( _, _, _, vai , _, defIndex ) and
131+ indirectionIndex = [ 0 .. defIndex ] + 1
132+ )
133+ } or
134+ TGlobalDef ( Cpp:: GlobalOrNamespaceVariable v , IRFunction f , int indirectionIndex ) {
135+ // Represents the initial "definition" of a global variable when entering
136+ // a function body.
137+ exists ( VariableAddressInstruction vai |
138+ vai .getEnclosingIRFunction ( ) = f and
139+ vai .getAstVariable ( ) = v and
140+ isUse ( _, _, vai , _, indirectionIndex ) and
141+ not isDef ( _, _, vai .getAUse ( ) , _, _, _)
142+ )
118143 }
119144
120145abstract private class DefOrUseImpl extends TDefOrUseImpl {
@@ -254,6 +279,70 @@ class UseImpl extends DefOrUseImpl, TUseImpl {
254279 predicate isCertain ( ) { isUse ( true , operand , _, _, ind ) }
255280}
256281
282+ class GlobalUse extends TGlobalUse {
283+ Cpp:: GlobalOrNamespaceVariable global ;
284+ IRFunction f ;
285+ int indirectionIndex ;
286+
287+ GlobalUse ( ) { this = TGlobalUse ( global , f , indirectionIndex ) }
288+
289+ Cpp:: GlobalOrNamespaceVariable getVariable ( ) { result = global }
290+
291+ IRFunction getIRFunction ( ) { result = f }
292+
293+ final predicate hasIndexInBlock ( IRBlock block , int index ) {
294+ exists ( ExitFunctionInstruction exit |
295+ exit = f .getExitFunctionInstruction ( ) and
296+ block .getInstruction ( index ) = exit
297+ )
298+ }
299+
300+ int getIndirectionIndex ( ) { result = indirectionIndex }
301+
302+ SourceVariable getSourceVariable ( ) { sourceVariableIsGlobal ( result , global , f , indirectionIndex ) }
303+
304+ final predicate hasIndexInBlock ( IRBlock block , int index , SourceVariable sv ) {
305+ this .hasIndexInBlock ( block , index ) and
306+ sv = this .getSourceVariable ( )
307+ }
308+
309+ final Cpp:: Location getLocation ( ) { result = f .getLocation ( ) }
310+
311+ string toString ( ) { result = global .toString ( ) + " [final value from " + f .toString ( ) + "]" }
312+ }
313+
314+ class GlobalDef extends TGlobalDef {
315+ Cpp:: GlobalOrNamespaceVariable global ;
316+ IRFunction f ;
317+ int indirectionIndex ;
318+
319+ GlobalDef ( ) { this = TGlobalDef ( global , f , indirectionIndex ) }
320+
321+ Cpp:: GlobalOrNamespaceVariable getVariable ( ) { result = global }
322+
323+ IRFunction getIRFunction ( ) { result = f }
324+
325+ int getIndirectionIndex ( ) { result = indirectionIndex }
326+
327+ final predicate hasIndexInBlock ( IRBlock block , int index ) {
328+ exists ( EnterFunctionInstruction enter |
329+ enter = f .getEnterFunctionInstruction ( ) and
330+ block .getInstruction ( index ) = enter
331+ )
332+ }
333+
334+ SourceVariable getSourceVariable ( ) { sourceVariableIsGlobal ( result , global , f , indirectionIndex ) }
335+
336+ final predicate hasIndexInBlock ( IRBlock block , int index , SourceVariable sv ) {
337+ this .hasIndexInBlock ( block , index ) and
338+ sv = this .getSourceVariable ( )
339+ }
340+
341+ final Cpp:: Location getLocation ( ) { result = f .getLocation ( ) }
342+
343+ string toString ( ) { result = global .toString ( ) + " [initial value in " + f .toString ( ) + "]" }
344+ }
345+
257346/**
258347 * Holds if `defOrUse1` is a definition which is first read by `use`,
259348 * or if `defOrUse1` is a use and `use` is a next subsequent use.
@@ -280,6 +369,32 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
280369 )
281370}
282371
372+ /**
373+ * Holds if `defOrUse` should flow to the final use of the
374+ * global variable use represetned by `globalUse`.
375+ */
376+ private predicate defOrUseToGlobalUse ( DefOrUse defOrUse , GlobalUse globalUse ) {
377+ exists ( IRBlock bb1 , int i1 , IRBlock bb2 , int i2 , SourceVariable v |
378+ defOrUse .asDefOrUse ( ) .hasIndexInBlock ( bb1 , i1 , v ) and
379+ globalUse .hasIndexInBlock ( bb2 , i2 , v ) and
380+ adjacentDefRead ( _, pragma [ only_bind_into ] ( bb1 ) , pragma [ only_bind_into ] ( i1 ) ,
381+ pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) )
382+ )
383+ }
384+
385+ /**
386+ * Holds if `globalDef` represents the initial definition of a global variable that
387+ * flows to `useOrPhi`.
388+ */
389+ private predicate globalDefToUse ( GlobalDef globalDef , UseOrPhi useOrPhi ) {
390+ exists ( IRBlock bb1 , int i1 , IRBlock bb2 , int i2 , SourceVariable v |
391+ globalDef .hasIndexInBlock ( bb1 , i1 , v ) and
392+ adjacentDefRead ( _, pragma [ only_bind_into ] ( bb1 ) , pragma [ only_bind_into ] ( i1 ) ,
393+ pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) ) and
394+ useOrPhi .asDefOrUse ( ) .hasIndexInBlock ( bb2 , i2 , v )
395+ )
396+ }
397+
283398private predicate useToNode ( UseOrPhi use , Node nodeTo ) {
284399 exists ( UseImpl useImpl |
285400 useImpl = use .asDefOrUse ( ) and
@@ -369,6 +484,20 @@ predicate ssaFlow(Node nodeFrom, Node nodeTo) {
369484 adjacentDefRead ( defOrUse1 , use ) and
370485 useToNode ( use , nodeTo )
371486 )
487+ or
488+ // Def/use to final value of global vairable
489+ exists ( DefOrUse defOrUse , GlobalUse globalUse |
490+ nodeToDefOrUse ( nodeFrom , defOrUse ) and
491+ defOrUseToGlobalUse ( defOrUse , globalUse ) and
492+ nodeTo .( FinalGlobalValue ) .getGlobalUse ( ) = globalUse
493+ )
494+ or
495+ // Initial global variable value to a first use
496+ exists ( GlobalDef globalDef , UseOrPhi use |
497+ nodeFrom .( InitialGlobalValue ) .getGlobalDef ( ) = globalDef and
498+ globalDefToUse ( globalDef , use ) and
499+ useToNode ( use , nodeTo )
500+ )
372501}
373502
374503/**
@@ -421,6 +550,17 @@ private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
421550 )
422551}
423552
553+ private predicate sourceVariableIsGlobal (
554+ SourceVariable sv , Cpp:: GlobalOrNamespaceVariable global , IRFunction func , int indirectionIndex
555+ ) {
556+ exists ( IRVariable irVar , BaseIRVariable base |
557+ sourceVariableHasBaseAndIndex ( sv , base , indirectionIndex ) and
558+ irVar = base .getIRVariable ( ) and
559+ irVar .getEnclosingIRFunction ( ) = func and
560+ global = irVar .getAst ( )
561+ )
562+ }
563+
424564private module SsaInput implements SsaImplCommon:: InputSig {
425565 import InputSigCommon
426566 import SourceVariables
@@ -431,10 +571,18 @@ private module SsaInput implements SsaImplCommon::InputSig {
431571 */
432572 predicate variableWrite ( IRBlock bb , int i , SourceVariable v , boolean certain ) {
433573 DataFlowImplCommon:: forceCachingInSameStage ( ) and
434- variableWriteCand ( bb , i , v ) and
574+ (
575+ variableWriteCand ( bb , i , v ) or
576+ sourceVariableIsGlobal ( v , _, _, _)
577+ ) and
435578 exists ( DefImpl def | def .hasIndexInBlock ( bb , i , v ) |
436579 if def .isCertain ( ) then certain = true else certain = false
437580 )
581+ or
582+ exists ( GlobalDef global |
583+ global .hasIndexInBlock ( bb , i , v ) and
584+ certain = true
585+ )
438586 }
439587
440588 /**
@@ -445,6 +593,11 @@ private module SsaInput implements SsaImplCommon::InputSig {
445593 exists ( UseImpl use | use .hasIndexInBlock ( bb , i , v ) |
446594 if use .isCertain ( ) then certain = true else certain = false
447595 )
596+ or
597+ exists ( GlobalUse global |
598+ global .hasIndexInBlock ( bb , i , v ) and
599+ certain = true
600+ )
448601 }
449602}
450603
0 commit comments