]> granicus.if.org Git - clang/commitdiff
Added initial transfer function support for inline asm.
authorTed Kremenek <kremenek@apple.com>
Mon, 17 Mar 2008 21:11:24 +0000 (21:11 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 17 Mar 2008 21:11:24 +0000 (21:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48466 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/GRExprEngine.h
lib/Analysis/GRExprEngine.cpp

index 4e50745e2225893e22e638d32b94f9a234d4dd37..9e83f5cd1fc81cfae512b848ec1db6b32c030371 100644 (file)
@@ -365,6 +365,19 @@ protected:
   ///  other functions that handle specific kinds of statements.
   void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
   
+  /// VisitAsmStmt - Transfer function logic for inline asm.
+  void VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst);
+  
+  void VisitAsmStmtHelperOutputs(AsmStmt* A,
+                                 AsmStmt::outputs_iterator I,
+                                 AsmStmt::outputs_iterator E,
+                                 NodeTy* Pred, NodeSet& Dst);
+  
+  void VisitAsmStmtHelperInputs(AsmStmt* A,
+                                AsmStmt::inputs_iterator I,
+                                AsmStmt::inputs_iterator E,
+                                NodeTy* Pred, NodeSet& Dst);
+  
   /// VisitBinaryOperator - Transfer function logic for binary operators.
   void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
   
index f1108df405198b8bb3bd938025bb3b8f316a2e40..cc0923e7968ca90105c8d392ce95ece0e34e3850 100644 (file)
@@ -1013,6 +1013,68 @@ void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
   Visit(Ex, Pred, Dst);
 }
 
+void GRExprEngine::VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst) {
+  VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
+}  
+
+void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A,
+                                             AsmStmt::outputs_iterator I,
+                                             AsmStmt::outputs_iterator E,
+                                             NodeTy* Pred, NodeSet& Dst) {
+  if (I == E) {
+    VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
+    return;
+  }
+  
+  NodeSet Tmp;
+  VisitLVal(*I, Pred, Tmp);
+  
+  ++I;
+  
+  for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+    VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
+}
+
+void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
+                                            AsmStmt::inputs_iterator I,
+                                            AsmStmt::inputs_iterator E,
+                                            NodeTy* Pred, NodeSet& Dst) {
+  if (I == E) {
+    
+    // We have processed both the inputs and the outputs.  All of the outputs
+    // should evaluate to LVals.  Nuke all of their values.
+    
+    // FIXME: Some day in the future it would be nice to allow a "plug-in"
+    // which interprets the inline asm and stores proper results in the
+    // outputs.
+    
+    ValueState* St = GetState(Pred);
+    
+    for (AsmStmt::outputs_iterator OI = A->begin_outputs(),
+                                   OE = A->end_outputs(); OI != OE; ++OI) {
+      
+      RVal X = GetLVal(St, *OI);
+      
+      assert (!isa<NonLVal>(X));
+      
+      if (isa<LVal>(X))
+        St = SetRVal(St, cast<LVal>(X), UnknownVal());
+    }
+    
+    Nodify(Dst, A, Pred, St);
+    return;
+  }
+  
+  NodeSet Tmp;
+  Visit(*I, Pred, Tmp);
+  
+  ++I;
+  
+  for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+    VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
+}
+
+
 void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
                                        GRExprEngine::NodeTy* Pred,
                                        GRExprEngine::NodeSet& Dst) {