Work around For and While loop bugs on Intel Mac OSX

Condition calculation in for and while loops has bug on Intel Mac. Work
around it by converting "CONDITION" to "CONDITION && true".

This CL also adds previous SH_EMULATE_ABS_INT_FUNCTION workaround to
the ANGLE GL back-end on OSX

BUG=chromium:644669
TEST=deqp/functional/gles3/shaderloop_for/while.html

Change-Id: I910f662b054f259fcb601b9938841b3a2d066840
Reviewed-on: https://chromium-review.googlesource.com/381678
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Qiankun Miao <qiankun.miao@intel.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/compiler/translator/AddAndTrueToLoopCondition.cpp
new file mode 100644
index 0000000..0177fea
--- /dev/null
+++ b/src/compiler/translator/AddAndTrueToLoopCondition.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that rewrites for and while loops by replacing "condition" with
+// "condition && true" to work around condition bug on Intel Mac.
+class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
+{
+  public:
+    AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
+
+    bool visitLoop(Visit, TIntermLoop *loop) override
+    {
+        // do-while loop doesn't have this bug.
+        if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
+        {
+            return true;
+        }
+
+        // For loop may not have a condition.
+        if (loop->getCondition() == nullptr)
+        {
+            return true;
+        }
+
+        // Constant true.
+        TConstantUnion *trueConstant = new TConstantUnion();
+        trueConstant->setBConst(true);
+        TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool));
+
+        // CONDITION && true.
+        TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
+        loop->setCondition(andOp);
+
+        return true;
+    }
+};
+
+}  // anonymous namespace
+
+void AddAndTrueToLoopCondition(TIntermNode *root)
+{
+    AddAndTrueToLoopConditionTraverser traverser;
+    root->traverse(&traverser);
+}
+
+}  // namespace sh
diff --git a/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/compiler/translator/AddAndTrueToLoopCondition.h
new file mode 100644
index 0000000..34debe0
--- /dev/null
+++ b/src/compiler/translator/AddAndTrueToLoopCondition.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
+
+#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void AddAndTrueToLoopCondition(TIntermNode *root);
+
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index ddeb05a..62e2c17 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -4,6 +4,7 @@
 // found in the LICENSE file.
 //
 
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
 #include "compiler/translator/Cache.h"
 #include "compiler/translator/Compiler.h"
 #include "compiler/translator/CallDAG.h"
@@ -331,6 +332,9 @@
         if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
             RewriteDoWhile(root, getTemporaryIndex());
 
+        if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
+            sh::AddAndTrueToLoopCondition(root);
+
         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
         {
             UnfoldShortCircuitAST unfoldShortCircuit;