Replace RS object assignments with rsSetObject().

Reference counting works now for all scalar/array types. It still needs to be
modified slightly to support structs, initializers and break/continue.

Change-Id: I6e531df86508f261b784932fca930bc666cb0084
b: 3092382
diff --git a/slang_rs_object_ref_count.cpp b/slang_rs_object_ref_count.cpp
index d2c088c..59ec672 100644
--- a/slang_rs_object_ref_count.cpp
+++ b/slang_rs_object_ref_count.cpp
@@ -142,6 +142,39 @@
   return;
 }
 
+static void ReplaceinCompoundStmt(clang::ASTContext& C,
+                                  clang::CompoundStmt *CS,
+                                  clang::Stmt* OldStmt,
+                                  clang::Stmt* NewStmt) {
+  clang::CompoundStmt::body_iterator bI = CS->body_begin();
+
+  unsigned StmtCount = 0;
+  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
+    StmtCount++;
+  }
+
+  //OldStmt->dump();
+  //NewStmt->dump();
+
+  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
+
+  unsigned UpdatedStmtCount = 0;
+  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
+    if (*bI == OldStmt) {
+      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
+    } else {
+      UpdatedStmtList[UpdatedStmtCount++] = *bI;
+    }
+  }
+
+  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
+
+  delete [] UpdatedStmtList;
+
+  return;
+}
+
+
 // This class visits a compound statement and inserts the StmtList containing
 // destructors in proper locations. This includes inserting them before any
 // return statement in any sub-block, at the end of the logical enclosing
@@ -376,6 +409,61 @@
 
 }  // namespace
 
+void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
+    clang::BinaryOperator *AS) {
+
+  clang::QualType QT = AS->getType();
+  RSExportPrimitiveType::DataType DT =
+      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
+
+  clang::FunctionDecl *SetObjectFD =
+      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
+  assert((SetObjectFD != NULL) &&
+      "rsSetObject doesn't cover all RS object types");
+  clang::ASTContext &C = SetObjectFD->getASTContext();
+
+  clang::QualType SetObjectFDType = SetObjectFD->getType();
+  clang::QualType SetObjectFDArgType[2];
+  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
+  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
+
+  clang::SourceLocation Loc = SetObjectFD->getLocation();
+  clang::Expr *RefRSSetObjectFD =
+      clang::DeclRefExpr::Create(C,
+                                 NULL,
+                                 SetObjectFD->getQualifierRange(),
+                                 SetObjectFD,
+                                 Loc,
+                                 SetObjectFDType);
+
+  clang::Expr *RSSetObjectFP =
+      clang::ImplicitCastExpr::Create(C,
+                                      C.getPointerType(SetObjectFDType),
+                                      clang::CK_FunctionToPointerDecay,
+                                      RefRSSetObjectFD,
+                                      NULL,
+                                      clang::VK_RValue);
+
+  clang::Expr *ArgList[2];
+  ArgList[0] = new(C) clang::UnaryOperator(AS->getLHS(),
+                                           clang::UO_AddrOf,
+                                           SetObjectFDArgType[0],
+                                           Loc);
+  ArgList[1] = AS->getRHS();
+
+  clang::CallExpr *RSSetObjectCall =
+      new(C) clang::CallExpr(C,
+                             RSSetObjectFP,
+                             ArgList,
+                             2,
+                             SetObjectFD->getCallResultType(),
+                             Loc);
+
+  ReplaceinCompoundStmt(C, mCS, AS, RSSetObjectCall);
+
+  return;
+}
+
 void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
   std::list<clang::Stmt*> RSClearObjectCalls;
   for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
@@ -634,8 +722,6 @@
     VisitStmt(CS);
 
     // Destroy the scope
-    // TODO(srhines): Update reference count of the RS object refenced by
-    //                getCurrentScope().
     assert((getCurrentScope() == S) && "Corrupted scope stack!");
     S->InsertLocalVarDestructors();
     mScopeStack.pop();
@@ -645,7 +731,14 @@
 }
 
 void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
-  // TODO(srhines): Update reference count
+  clang::QualType QT = AS->getType();
+  RSExportPrimitiveType::DataType DT =
+      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
+
+  if (RSExportPrimitiveType::IsRSObjectType(DT)) {
+    getCurrentScope()->ReplaceRSObjectAssignment(AS);
+  }
+
   return;
 }