Fix pure php implementation for 32-bit machine. (#2282)

diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index 417a972..30d7350 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -37,6 +37,28 @@
 
 class GPBUtil
 {
+    public function divideInt64ToInt32($value, &$high, &$low, $trim = false)
+    {
+        $isNeg = (bccomp($value, 0) < 0);
+        if ($isNeg) {
+            $value = bcsub(0, $value);
+        }
+        $high = (int) bcdiv(bcadd($value, 1), 4294967296);
+        $low = (int) bcmod($value, 4294967296);
+        if ($isNeg) {
+            $high = ~$high;
+            $low = ~$low;
+            $low++;
+            if (!$low) {
+                $high++;
+            }
+        }
+
+        if ($trim) {
+            $high = 0;
+        }
+    }
+
 
     public static function checkString(&$var, $check_utf8)
     {
@@ -70,9 +92,14 @@
     public static function checkUint32(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
             if (PHP_INT_SIZE === 8) {
+                $var = intval($var);
                 $var |= ((-(($var >> 31) & 0x1)) & ~0xFFFFFFFF);
+            } else {
+                if (bccomp($var, 0x7FFFFFFF) > 0) {
+                    $var = bcsub($var, "4294967296");
+                }
+                $var = (int) $var;
             }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
@@ -82,7 +109,11 @@
     public static function checkInt64(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
+            if (PHP_INT_SIZE == 8) {
+                $var = intval($var);
+            } else {
+                $var = bcdiv($var, 1, 0);
+            }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
         }
@@ -91,7 +122,11 @@
     public static function checkUint64(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
+            if (PHP_INT_SIZE == 8) {
+                $var = intval($var);
+            } else {
+                $var = bcdiv($var, 1, 0);
+            }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
         }
diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php
index 0e741e1..7e2c124 100644
--- a/php/src/Google/Protobuf/Internal/GPBWire.php
+++ b/php/src/Google/Protobuf/Internal/GPBWire.php
@@ -32,10 +32,6 @@
 
 namespace Google\Protobuf\Internal;
 
-use Google\Protobuf\Internal\GPBUtil;
-use Google\Protobuf\Internal\Int64;
-use Google\Protobuf\Internal\Uint64;
-
 class GPBWire
 {
 
@@ -150,20 +146,28 @@
 
     public static function zigZagEncode64($int64)
     {
-        $a = $int64->copy()->leftShift(1);
-        $b = $int64->copy()->rightShift(63);
-        $result = $a->bitXor($b);
-        $uint64 = Uint64::newValue($result->high, $result->low);
-        return $uint64;
+        if (PHP_INT_SIZE == 4) {
+            if (bccomp($int64, 0) >= 0) {
+                return bcmul($int64, 2);
+            } else {
+                return bcsub(bcmul(bcsub(0, $int64), 2), 1);
+            }
+        } else {
+            return ($int64 << 1) ^ ($int64 >> 63);
+        }
     }
 
     public static function zigZagDecode64($uint64)
     {
-        $a = $uint64->copy()->rightShift(1);
-        $b = $uint64->oddMask();
-        $result = $a->bitXor($b);
-        $int64 = Int64::newValue($result->high, $result->low);
-        return $int64;
+        if (PHP_INT_SIZE == 4) {
+            if (bcmod($uint64, 2) == 0) {
+                return bcdiv($uint64, 2, 0);
+            } else {
+                return bcsub(0, bcdiv(bcadd($uint64, 1), 2, 0));
+            }
+        } else {
+            return (($uint64 >> 1) & 0x7FFFFFFFFFFFFFFF) ^ (-($uint64 & 1));
+        }
     }
 
     public static function readInt32(&$input, &$value)
@@ -227,11 +231,7 @@
 
     public static function readSfixed64(&$input, &$value)
     {
-        if (!self::readFixed64($input, $value)) {
-            return false;
-        }
-        $value = Int64::newValue($value->high, $value->low);
-        return true;
+        return $input->readLittleEndian64($value);
     }
 
     public static function readFloat(&$input, &$value)
@@ -259,7 +259,7 @@
         if (!$input->readVarint64($value)) {
             return false;
         }
-        if ($value->high === 0 && $value->low === 0) {
+        if ($value == 0) {
             $value = false;
         } else {
             $value = true;
@@ -324,8 +324,8 @@
 
     public static function writeSint64(&$output, $value)
     {
-        $value = GPBWire::zigZagEncode64(GPBUtil::Int64($value));
-        return $output->writeVarint64($value->toInteger());
+        $value = GPBWire::zigZagEncode64($value);
+        return $output->writeVarint64($value);
     }
 
     public static function writeFixed32(&$output, $value)
@@ -431,9 +431,8 @@
 
     public static function sint64Size($value)
     {
-        $value = GPBUtil::Int64($value);
         $value = self::zigZagEncode64($value);
-        return self::varint64Size($value->toInteger());
+        return self::varint64Size($value);
     }
 
     public static function varint64Size($value)
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/InputStream.php
index 18d0707..6d6c74e 100644
--- a/php/src/Google/Protobuf/Internal/InputStream.php
+++ b/php/src/Google/Protobuf/Internal/InputStream.php
@@ -34,6 +34,24 @@
 
 use Google\Protobuf\Internal\Uint64;
 
+function combineInt32ToInt64($high, $low)
+{
+    $isNeg = $high < 0;
+    if ($isNeg) {
+        $high = ~$high;
+        $low = ~$low;
+        $low++;
+        if (!$low) {
+            $high++;
+        }
+    }
+    $result = bcadd(bcmul($high, 4294967296), $low);
+    if ($isNeg) {
+      $result = bcsub(0, $result);
+    }
+    return $result;
+}
+
 class InputStream
 {
 
@@ -116,11 +134,23 @@
         if (!$this->readVarint64($var)) {
             return false;
         }
-        $var = $var->toInteger() & 0xFFFFFFFF;
-        // Convert large uint32 to int32.
-        if (PHP_INT_SIZE === 8 && ($var > 0x7FFFFFFF)) {
-            $var = $var | (0xFFFFFFFF << 32);
+
+        if (PHP_INT_SIZE == 4) {
+            $var = bcmod($var, 4294967296);
+        } else {
+            $var &= 0xFFFFFFFF;
         }
+
+        // Convert large uint32 to int32.
+        if ($var > 0x7FFFFFFF) {
+            if (PHP_INT_SIZE === 8) {
+                $var = $var | (0xFFFFFFFF << 32);
+            } else {
+                $var = bcsub($var, 4294967296);
+            }
+        }
+
+        $var = intval($var);
         return true;
     }
 
@@ -130,7 +160,8 @@
      */
     public function readVarint64(&$var)
     {
-        $result = new Uint64(0);
+        $high = 0;
+        $low = 0;
         $count = 0;
         $b = 0;
 
@@ -142,12 +173,27 @@
                 return false;
             }
             $b = ord($this->buffer[$this->current]);
-            $result->bitOr((new Uint64($b & 0x7F))->leftShift(7 * $count));
+            $bits = 7 * $count;
+            if ($bits >= 32) {
+                $high |= (($b & 0x7F) << ($bits - 32));
+            } else if ($bits > 25){
+                $high_bits = $bits - 25;
+                $low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
+                $high = $b & ((0x1 << $high_bits) -1);
+            } else {
+                $low |= (($b & 0x7F) << $bits);
+            }
+
             $this->advance(1);
             $count += 1;
         } while ($b & 0x80);
 
-        $var = $result;
+        if (PHP_INT_SIZE == 4) {
+            $var = combineInt32ToInt64($high, $low);
+        } else {
+            $var = ($high & 0xFFFFFFFF) << 32 |
+                   ($low & 0xFFFFFFFF);
+        }
         return true;
     }
 
@@ -161,7 +207,7 @@
         if (!$this->readVarint64($var)) {
             return false;
         }
-        $var = $var->toInteger();
+        $var = (int)$var;
         return true;
     }
 
@@ -197,7 +243,11 @@
             return false;
         }
         $high = unpack('V', $data)[1];
-        $var = Uint64::newValue($high, $low);
+        if (PHP_INT_SIZE == 4) {
+            $var = combineInt32ToInt64($high, $low);
+        } else {
+            $var = ($high << 32) | $low;
+        }
         return true;
     }
 
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 7bdc6a8..38513e9 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -210,13 +210,11 @@
                 if (!GPBWire::readInt64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::UINT64:
                 if (!GPBWire::readUint64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::INT32:
                 if (!GPBWire::readInt32($input, $value)) {
@@ -227,7 +225,6 @@
                 if (!GPBWire::readFixed64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::FIXED32:
                 if (!GPBWire::readFixed32($input, $value)) {
@@ -285,7 +282,6 @@
                 if (!GPBWire::readSfixed64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::SINT32:
                 if (!GPBWire::readSint32($input, $value)) {
@@ -296,7 +292,6 @@
                 if (!GPBWire::readSint64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             default:
                 user_error("Unsupported type.");
diff --git a/php/src/Google/Protobuf/Internal/OutputStream.php b/php/src/Google/Protobuf/Internal/OutputStream.php
index fcc5ce6..587ac35 100644
--- a/php/src/Google/Protobuf/Internal/OutputStream.php
+++ b/php/src/Google/Protobuf/Internal/OutputStream.php
@@ -90,8 +90,6 @@
     public function writeRaw($data, $size)
     {
         if ($this->buffer_size < $size) {
-            var_dump($this->buffer_size);
-            var_dump($size);
             trigger_error("Output stream doesn't have enough buffer.");
             return false;
         }
@@ -107,15 +105,28 @@
     private static function writeVarintToArray($value, &$buffer, $trim = false)
     {
         $current = 0;
-        if ($trim) {
-            $value &= 0xFFFFFFFF;
+
+        $high = 0;
+        $low = 0;
+        if (PHP_INT_SIZE == 4) {
+            GPBUtil::divideInt64ToInt32($value, $high, $low, $trim);
+        } else {
+            if ($trim) {
+                $low = $value & 0xFFFFFFFF;
+            } else {
+                $low = $value;
+            }
         }
-        while ($value >= 0x80 || $value < 0) {
-            $buffer[$current] = chr($value | 0x80);
+
+        while ($low >= 0x80 || $low < 0) {
+            $buffer[$current] = chr($low | 0x80);
             $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
+            $carry = ($high & 0x7F) << ((PHP_INT_SIZE << 3) - 7);
+            $high = ($high >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
+            $low = (($low >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)) | $carry);
             $current++;
         }
-        $buffer[$current] = chr($value);
+        $buffer[$current] = chr($low);
         return $current + 1;
     }
 
@@ -130,14 +141,24 @@
 
     private static function writeLittleEndian64ToArray($value, &$buffer)
     {
-        $buffer[0] = chr($value & 0x000000FF);
-        $buffer[1] = chr(($value >> 8) & 0x000000FF);
-        $buffer[2] = chr(($value >> 16) & 0x000000FF);
-        $buffer[3] = chr(($value >> 24) & 0x000000FF);
-        $buffer[4] = chr(($value >> 32) & 0x000000FF);
-        $buffer[5] = chr(($value >> 40) & 0x000000FF);
-        $buffer[6] = chr(($value >> 48) & 0x000000FF);
-        $buffer[7] = chr(($value >> 56) & 0x000000FF);
+        $high = 0;
+        $low = 0;
+        if (PHP_INT_SIZE == 4) {
+            GPBUtil::divideInt64ToInt32($value, $high, $low);
+        } else {
+            $low = $value & 0xFFFFFFFF;
+            $high = ($value >> 32) & 0xFFFFFFFF;
+        }
+
+        $buffer[0] = chr($low & 0x000000FF);
+        $buffer[1] = chr(($low >> 8) & 0x000000FF);
+        $buffer[2] = chr(($low >> 16) & 0x000000FF);
+        $buffer[3] = chr(($low >> 24) & 0x000000FF);
+        $buffer[4] = chr($high & 0x000000FF);
+        $buffer[5] = chr(($high >> 8) & 0x000000FF);
+        $buffer[6] = chr(($high >> 16) & 0x000000FF);
+        $buffer[7] = chr(($high >> 24) & 0x000000FF);
         return 8;
     }
+
 }
diff --git a/php/src/Google/Protobuf/Internal/Type.php b/php/src/Google/Protobuf/Internal/Type.php
deleted file mode 100644
index 088f0e0..0000000
--- a/php/src/Google/Protobuf/Internal/Type.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-namespace Google\Protobuf\Internal;
-
-class GPBInteger
-{
-    public $high = 0;
-    public $low = 0;
-
-    public function __construct($value = 0)
-    {
-        $this->low = $value & 0xFFFFFFFF;
-        if (PHP_INT_SIZE === 8) {
-            $this->high = ($value >> 32) & 0xFFFFFFFF;
-        }
-    }
-
-    // Return 0 for unsigned integers and 1 for signed integers.
-    protected function sign()
-    {
-        trigger_error("Not implemented", E_ERROR);
-    }
-
-    public function leftShift($count)
-    {
-        if ($count > 63) {
-            $this->low = 0;
-            $this->high = 0;
-            return;
-        }
-        if ($count > 32) {
-            $this->high = $this->low;
-            $this->low = 0;
-            $count -= 32;
-        }
-        $mask = (1 << $count) - 1;
-        $this->high = (($this->high << $count) & 0xFFFFFFFF) |
-                  (($this->low >> (32 - $count)) & $mask);
-        $this->low = ($this->low << $count) & 0xFFFFFFFF;
-
-        $this->high &= 0xFFFFFFFF;
-        $this->low &= 0xFFFFFFFF;
-        return $this;
-    }
-
-    public function rightShift($count)
-    {
-        $sign = (($this->high & 0x80000000) >> 31) & $this->sign();
-        if ($count > 63) {
-            $this->low = -$sign;
-            $this->high = -$sign;
-            return;
-        }
-        if ($count > 32) {
-            $this->low = $this->high;
-            $this->high = -$sign;
-            $count -= 32;
-        }
-        $this->low = (($this->low >> $count) & 0xFFFFFFFF) |
-                 (($this->high << (32 - $count)) & 0xFFFFFFFF);
-        $this->high = (($this->high >> $count) | (-$sign << $count));
-
-        $this->high &= 0xFFFFFFFF;
-        $this->low &= 0xFFFFFFFF;
-
-        return $this;
-    }
-
-    public function bitOr($var)
-    {
-        $this->high |= $var->high;
-        $this->low |= $var->low;
-        return $this;
-    }
-
-    public function bitXor($var)
-    {
-        $this->high ^= $var->high;
-        $this->low ^= $var->low;
-        return $this;
-    }
-
-    public function bitAnd($var)
-    {
-        $this->high &= $var->high;
-        $this->low &= $var->low;
-        return $this;
-    }
-
-    // Even: all zero; Odd: all one.
-    public function oddMask()
-    {
-        $low = (-($this->low & 1)) & 0xFFFFFFFF;
-        $high = $low;
-        return UInt64::newValue($high, $low);
-    }
-
-    public function toInteger()
-    {
-        if (PHP_INT_SIZE === 8) {
-            return ($this->high << 32) | $this->low;
-        } else {
-            return $this->low;
-        }
-    }
-
-    public function copy()
-    {
-        return static::newValue($this->high, $this->low);
-    }
-}
-
-class Uint64 extends GPBInteger
-{
-
-    public static function newValue($high, $low)
-    {
-        $uint64 = new Uint64(0);
-        $uint64->high = $high;
-        $uint64->low = $low;
-        return $uint64;
-    }
-
-    protected function sign()
-    {
-        return 0;
-    }
-}
-
-class Int64 extends GPBInteger
-{
-
-    public static function newValue($high, $low)
-    {
-        $int64 = new Int64(0);
-        $int64->high = $high;
-        $int64->low = $low;
-        return $int64;
-    }
-
-    protected function sign()
-    {
-        return 1;
-    }
-}
diff --git a/php/tests/array_test.php b/php/tests/array_test.php
index 09d4dc8..a118b54 100644
--- a/php/tests/array_test.php
+++ b/php/tests/array_test.php
@@ -225,46 +225,68 @@
 
         // Test append.
         $arr []= MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[0]);
         $arr []= MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[1]);
-
         $arr []= 1.1;
-        $this->assertSame(1, $arr[2]);
-
         $arr []= '2';
-        $this->assertSame(2, $arr[3]);
         $arr []= '3.1';
-        $this->assertSame(3, $arr[4]);
         $arr []= MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[5]);
         $arr []= MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[6]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame('1', $arr[2]);
+            $this->assertSame('2', $arr[3]);
+            $this->assertSame('3', $arr[4]);
+            $this->assertSame(MAX_INT64_STRING, $arr[5]);
+            $this->assertSame(MIN_INT64_STRING, $arr[6]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame(1, $arr[2]);
+            $this->assertSame(2, $arr[3]);
+            $this->assertSame(3, $arr[4]);
+            $this->assertSame(MAX_INT64, $arr[5]);
+            $this->assertSame(MIN_INT64, $arr[6]);
+        }
+
 
         $this->assertEquals(7, count($arr));
 
         for ($i = 0; $i < count($arr); $i++) {
             $arr[$i] = 0;
-            $this->assertSame(0, $arr[$i]);
+            if (PHP_INT_SIZE == 4) {
+                $this->assertSame('0', $arr[$i]);
+            } else {
+                $this->assertSame(0, $arr[$i]);
+            }
         }
 
         // Test set.
         $arr [0]= MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[0]);
         $arr [1]= MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[1]);
-
         $arr [2]= 1.1;
-        $this->assertSame(1, $arr[2]);
-
         $arr [3]= '2';
-        $this->assertSame(2, $arr[3]);
         $arr [4]= '3.1';
-        $this->assertSame(3, $arr[4]);
         $arr [5]= MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[5]);
         $arr [6]= MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[6]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $arr[0]);
+            $this->assertSame(MIN_INT64_STRING, $arr[1]);
+            $this->assertSame('1', $arr[2]);
+            $this->assertSame('2', $arr[3]);
+            $this->assertSame('3', $arr[4]);
+            $this->assertSame(MAX_INT64_STRING, $arr[5]);
+            $this->assertEquals(MIN_INT64_STRING, $arr[6]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame(1, $arr[2]);
+            $this->assertSame(2, $arr[3]);
+            $this->assertSame(3, $arr[4]);
+            $this->assertSame(MAX_INT64, $arr[5]);
+            $this->assertEquals(MIN_INT64, $arr[6]);
+        }
     }
 
     /**
@@ -315,38 +337,57 @@
 
         // Test append.
         $arr []= MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[0]);
-
         $arr []= 1.1;
-        $this->assertSame(1, $arr[1]);
-
         $arr []= '2';
-        $this->assertSame(2, $arr[2]);
         $arr []= '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr []= MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[4]);
 
-        $this->assertEquals(5, count($arr));
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[0]);
+            $this->assertSame('1', $arr[1]);
+            $this->assertSame('2', $arr[2]);
+            $this->assertSame('3', $arr[3]);
+            $this->assertSame(MAX_UINT64_STRING, $arr[4]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[0]);
+            $this->assertSame(1, $arr[1]);
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[4]);
+            $this->assertSame(5, count($arr));
+        }
+
+        $this->assertSame(5, count($arr));
 
         for ($i = 0; $i < count($arr); $i++) {
             $arr[$i] = 0;
-            $this->assertSame(0, $arr[$i]);
+            if (PHP_INT_SIZE == 4) {
+                $this->assertSame('0', $arr[$i]);
+            } else {
+                $this->assertSame(0, $arr[$i]);
+            }
         }
 
         // Test set.
         $arr [0]= MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[0]);
-
         $arr [1]= 1.1;
-        $this->assertSame(1, $arr[1]);
-
         $arr [2]= '2';
-        $this->assertSame(2, $arr[2]);
         $arr [3]= '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr [4]= MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[4]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[0]);
+            $this->assertSame('1', $arr[1]);
+            $this->assertSame('2', $arr[2]);
+            $this->assertSame('3', $arr[3]);
+            $this->assertSame(MAX_UINT64_STRING, $arr[4]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[0]);
+            $this->assertSame(1, $arr[1]);
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[4]);
+        }
     }
 
     /**
diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php
index d1a0bd5..b3ecd3a 100644
--- a/php/tests/generated_class_test.php
+++ b/php/tests/generated_class_test.php
@@ -148,17 +148,40 @@
 
         // Set float.
         $m->setOptionalInt64(1.1);
-        $this->assertSame(1, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(1, $m->getOptionalInt64());
+        }
 
         // Set string.
         $m->setOptionalInt64('2');
-        $this->assertSame(2, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(2, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64('3.1');
-        $this->assertSame(3, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('3', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(3, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64(MAX_INT64_STRING);
-        $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $m->getOptionalInt64());
+        } else {
+            $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64(MIN_INT64_STRING);
-        $this->assertEquals(MIN_INT64, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MIN_INT64_STRING, $m->getOptionalInt64());
+        } else {
+            $this->assertSame(MIN_INT64, $m->getOptionalInt64());
+        }
     }
 
     /**
@@ -189,19 +212,41 @@
 
         // Set integer.
         $m->setOptionalUint64(MAX_UINT64);
-        $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64());
+        } else {
+            $this->assertSame(MAX_UINT64, $m->getOptionalUint64());
+        }
 
         // Set float.
         $m->setOptionalUint64(1.1);
-        $this->assertSame(1, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(1, $m->getOptionalUint64());
+        }
 
         // Set string.
         $m->setOptionalUint64('2');
-        $this->assertSame(2, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(2, $m->getOptionalUint64());
+        }
+
         $m->setOptionalUint64('3.1');
-        $this->assertSame(3, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('3', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(3, $m->getOptionalUint64());
+        }
+
         $m->setOptionalUint64(MAX_UINT64_STRING);
-        $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64());
+        } else {
+            $this->assertSame(MAX_UINT64, $m->getOptionalUint64());
+        }
     }
 
     /**
diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php
index d79d0da..4e42361 100644
--- a/php/tests/map_field_test.php
+++ b/php/tests/map_field_test.php
@@ -205,9 +205,14 @@
 
         // Test integer argument.
         $arr[MAX_INT64] = MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
         $arr[MIN_INT64] = MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]);
+            $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+            $this->assertSame(MIN_INT64, $arr[MIN_INT64]);
+        }
         $this->assertEquals(2, count($arr));
         unset($arr[MAX_INT64]);
         unset($arr[MIN_INT64]);
@@ -215,20 +220,31 @@
 
         // Test float argument.
         $arr[1.1] = 1.1;
-        $this->assertSame(1, $arr[1]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $arr['1']);
+        } else {
+            $this->assertSame(1, $arr[1]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[1.1]);
         $this->assertEquals(0, count($arr));
 
         // Test string argument.
         $arr['2'] = '2';
-        $this->assertSame(2, $arr[2]);
         $arr['3.1'] = '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr[MAX_INT64_STRING] = MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
         $arr[MIN_INT64_STRING] = MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $arr['2']);
+            $this->assertSame('3', $arr['3']);
+            $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]);
+            $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]);
+        } else {
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+            $this->assertSame(MIN_INT64, $arr[MIN_INT64]);
+        }
         $this->assertEquals(4, count($arr));
         unset($arr['2']);
         unset($arr['3.1']);
@@ -282,25 +298,41 @@
 
         // Test integer argument.
         $arr[MAX_UINT64] = MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[MAX_UINT64]);
         $this->assertEquals(0, count($arr));
 
         // Test float argument.
         $arr[1.1] = 1.1;
-        $this->assertSame(1, $arr[1]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $arr['1']);
+        } else {
+            $this->assertSame(1, $arr[1]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[1.1]);
         $this->assertEquals(0, count($arr));
 
         // Test string argument.
         $arr['2'] = '2';
-        $this->assertSame(2, $arr[2]);
         $arr['3.1'] = '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $arr['2']);
+            $this->assertSame('3', $arr['3']);
+            $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]);
+        } else {
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]);
+        }
+
         $this->assertEquals(3, count($arr));
         unset($arr['2']);
         unset($arr['3.1']);
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 82941dd..485956c 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -9,14 +9,10 @@
 use Foo\TestPackedMessage;
 use Google\Protobuf\Internal\InputStream;
 use Google\Protobuf\Internal\FileDescriptorSet;
-use Google\Protobuf\Internal\GPBUtil;
-use Google\Protobuf\Internal\Int64;
-use Google\Protobuf\Internal\Uint64;
 use Google\Protobuf\Internal\GPBLabel;
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\OutputStream;
-use Google\Protobuf\Internal\RepeatedField;
 
 class ImplementationTest extends TestBase
 {
@@ -68,17 +64,17 @@
         // Positive number.
         $input = new InputStream(hex2bin("01"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(1, $value->toInteger());
+        $this->assertEquals(1, $value);
 
         // Negative number.
         $input = new InputStream(hex2bin("ffffffffffffffffff01"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
         $input = new InputStream(hex2bin("ffffffffffffffffff0f"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
     }
 
     public function testReadUint64()
@@ -88,17 +84,17 @@
         // Positive number.
         $input = new InputStream(hex2bin("01"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(1, $value->toInteger());
+        $this->assertEquals(1, $value);
 
         // Negative number.
         $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF01"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
         $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
     }
 
     public function testReadSint32()
@@ -124,15 +120,15 @@
 
         $input = new InputStream(hex2bin("00"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(0), $value);
+        $this->assertEquals(0, $value);
 
         $input = new InputStream(hex2bin("01"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(-1), $value);
+        $this->assertEquals(-1, $value);
 
         $input = new InputStream(hex2bin("02"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(1), $value);
+        $this->assertEquals(1, $value);
     }
 
     public function testReadFixed32()
@@ -148,7 +144,11 @@
         $value = null;
         $input = new InputStream(hex2bin("1234567812345678"));
         GPBWire::readFixed64($input, $value);
-        $this->assertEquals(Uint64::newValue(0x78563412, 0x78563412), $value);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame("8671175386481439762", $value);
+        } else {
+            $this->assertSame(0x7856341278563412, $value);
+        }
     }
 
     public function testReadSfixed32()
@@ -193,7 +193,11 @@
         $value = null;
         $input = new InputStream(hex2bin("1234567812345678"));
         GPBWire::readSfixed64($input, $value);
-        $this->assertEquals(Int64::newValue(0x78563412, 0x78563412), $value);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame("8671175386481439762", $value);
+        } else {
+            $this->assertSame(0x7856341278563412, $value);
+        }
     }
 
     public function testZigZagEncodeDecode()
@@ -214,43 +218,65 @@
         $this->assertSame(0x3FFFFFFF,  GPBWire::zigZagDecode32(0x7FFFFFFE));
         $this->assertSame(-1073741824, GPBWire::zigZagDecode32(0x7FFFFFFF));
         $this->assertSame(0x7FFFFFFF,  GPBWire::zigZagDecode32(0xFFFFFFFE));
-        $this->assertSame(-2147483648, GPBWire::zigZagDecode32(0xFFFFFFFF));
+        $this->assertSame((int)-2147483648,GPBWire::zigZagDecode32(0xFFFFFFFF));
 
-        $this->assertEquals(GPBUtil::Uint64(0),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(0)));
-        $this->assertEquals(GPBUtil::Uint64(1),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(-1)));
-        $this->assertEquals(GPBUtil::Uint64(2),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(1)));
-        $this->assertEquals(GPBUtil::Uint64(3),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(-2)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x000000007FFFFFFE),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000003FFFFFFF)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x000000007FFFFFFF),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFFC0000000)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x00000000FFFFFFFE),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000007FFFFFFF)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x00000000FFFFFFFF),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFF80000000)));
-        $this->assertEquals(
-        Uint64::newValue(4294967295, 4294967294),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x7FFFFFFFFFFFFFFF)));
-        $this->assertEquals(
-        Uint64::newValue(4294967295, 4294967295),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x8000000000000000)));
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('0', GPBWire::zigZagEncode64(0));
+            $this->assertSame('1', GPBWire::zigZagEncode64(-1));
+            $this->assertSame('2', GPBWire::zigZagEncode64(1));
+            $this->assertSame('3', GPBWire::zigZagEncode64(-2));
+            $this->assertSame(
+                '2147483646',  // 0x7FFFFFE
+                GPBWire::zigZagEncode64(0x3FFFFFFF));
+            $this->assertSame(
+                '2147483647',  // 0x7FFFFFF
+                GPBWire::zigZagEncode64(-1073741824));  // 0xFFFFFFFFC0000000
+            $this->assertSame(
+                '4294967294',                           // 0xFFFFFFFE
+                GPBWire::zigZagEncode64(2147483647));   // 0x7FFFFFFF
+            $this->assertSame(
+                '4294967295',                           // 0xFFFFFFFF
+                GPBWire::zigZagEncode64(-2147483648));  // 0xFFFFFFFF80000000
+            $this->assertSame(
+                '18446744073709551614',  // 0xFFFFFFFFFFFFFFFE
+                                         // 0x7FFFFFFFFFFFFFFF
+                GPBWire::zigZagEncode64("9223372036854775807"));
+            $this->assertSame(
+                '18446744073709551615',  // 0xFFFFFFFFFFFFFFFF
+                                         // 0x8000000000000000
+                GPBWire::zigZagEncode64("-9223372036854775808"));
 
-        $this->assertEquals(GPBUtil::Int64(0),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(0)));
-        $this->assertEquals(GPBUtil::Int64(-1),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(1)));
-        $this->assertEquals(GPBUtil::Int64(1),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(2)));
-        $this->assertEquals(GPBUtil::Int64(-2),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(3)));
+            $this->assertSame('0', GPBWire::zigZagDecode64(0));
+            $this->assertSame('-1', GPBWire::zigZagDecode64(1));
+            $this->assertSame('1', GPBWire::zigZagDecode64(2));
+            $this->assertSame('-2', GPBWire::zigZagDecode64(3));
+        } else {
+            $this->assertSame(0, GPBWire::zigZagEncode64(0));
+            $this->assertSame(1, GPBWire::zigZagEncode64(-1));
+            $this->assertSame(2, GPBWire::zigZagEncode64(1));
+            $this->assertSame(3, GPBWire::zigZagEncode64(-2));
+            $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode64(0x3FFFFFFF));
+            $this->assertSame(
+                0x7FFFFFFF,
+                GPBWire::zigZagEncode64(0xFFFFFFFFC0000000));
+            $this->assertSame(
+                0xFFFFFFFE,
+                GPBWire::zigZagEncode64(0x7FFFFFFF));
+            $this->assertSame(
+                0xFFFFFFFF,
+                GPBWire::zigZagEncode64(0xFFFFFFFF80000000));
+            $this->assertSame(
+                -2,  // 0xFFFFFFFFFFFFFFFE
+                GPBWire::zigZagEncode64(0x7FFFFFFFFFFFFFFF));
+            $this->assertSame(
+                -1,  // 0xFFFFFFFFFFFFFFFF
+                GPBWire::zigZagEncode64(0x8000000000000000));
+
+            $this->assertSame(0, GPBWire::zigZagDecode64(0));
+            $this->assertSame(-1, GPBWire::zigZagDecode64(1));
+            $this->assertSame(1, GPBWire::zigZagDecode64(2));
+            $this->assertSame(-2, GPBWire::zigZagDecode64(3));
+        }
 
         // Round trip
         $this->assertSame(0, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(0)));
@@ -319,15 +345,27 @@
         // Normal case.
         $input = new InputStream(hex2bin('808001'));
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(16384, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('16384', $var);
+        } else {
+            $this->assertSame(16384, $var);
+        }
         $this->assertFalse($input->readVarint64($var));
 
         // Read two varint.
         $input = new InputStream(hex2bin('808001808002'));
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(16384, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('16384', $var);
+        } else {
+            $this->assertSame(16384, $var);
+        }
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(32768, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('32768', $var);
+        } else {
+            $this->assertSame(32768, $var);
+        }
         $this->assertFalse($input->readVarint64($var));
     }
 
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
index 25f18f7..4988605 100644
--- a/php/tests/test_base.php
+++ b/php/tests/test_base.php
@@ -13,22 +13,28 @@
 
     public function expectFields(TestMessage $m)
     {
-        $this->assertSame(-42,  $m->getOptionalInt32());
-        $this->assertSame(42,   $m->getOptionalUint32());
-        $this->assertSame(-43,  $m->getOptionalInt64());
-        $this->assertSame(43,   $m->getOptionalUint64());
         $this->assertSame(-44,  $m->getOptionalSint32());
-        $this->assertSame(-45,  $m->getOptionalSint64());
         $this->assertSame(46,   $m->getOptionalFixed32());
-        $this->assertSame(47,   $m->getOptionalFixed64());
         $this->assertSame(-46,  $m->getOptionalSfixed32());
-        $this->assertSame(-47,  $m->getOptionalSfixed64());
         $this->assertSame(1.5,  $m->getOptionalFloat());
         $this->assertSame(1.6,  $m->getOptionalDouble());
         $this->assertSame(true, $m->getOptionalBool());
         $this->assertSame('a',  $m->getOptionalString());
         $this->assertSame('b',  $m->getOptionalBytes());
         $this->assertSame(33,   $m->getOptionalMessage()->getA());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('-43',  $m->getOptionalInt64());
+            $this->assertSame('43',   $m->getOptionalUint64());
+            $this->assertSame('-45',  $m->getOptionalSint64());
+            $this->assertSame('47',   $m->getOptionalFixed64());
+            $this->assertSame('-47',  $m->getOptionalSfixed64());
+        } else {
+            $this->assertSame(-43,  $m->getOptionalInt64());
+            $this->assertSame(43,   $m->getOptionalUint64());
+            $this->assertSame(-45,  $m->getOptionalSint64());
+            $this->assertSame(47,   $m->getOptionalFixed64());
+            $this->assertSame(-47,  $m->getOptionalSfixed64());
+        }
 
         $this->assertEquals(-42,  $m->getRepeatedInt32()[0]);
         $this->assertEquals(42,   $m->getRepeatedUint32()[0]);
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
index 2f6e4dd..7f2aae1 100644
--- a/php/tests/test_util.php
+++ b/php/tests/test_util.php
@@ -20,7 +20,7 @@
 define('MAX_INT32_FLOAT', 2147483647.0);
 define('MAX_INT32_STRING', '2147483647');
 
-define('MIN_INT32', -2147483648);
+define('MIN_INT32', (int)-2147483648);
 define('MIN_INT32_FLOAT', -2147483648.0);
 define('MIN_INT32_STRING', '-2147483648');
 
@@ -28,22 +28,23 @@
 define('MAX_UINT32_FLOAT', 4294967295.0);
 define('MAX_UINT32_STRING', '4294967295');
 
-define('MIN_UINT32', -2147483648);
+define('MIN_UINT32', (int)-2147483648);
 define('MIN_UINT32_FLOAT', -2147483648.0);
 define('MIN_UINT32_STRING', '-2147483648');
 
-define('MAX_INT64', 9223372036854775807);
-define('MAX_INT64_STRING', '9223372036854775807');
-
-define('MIN_INT64_STRING', '-9223372036854775808');
-if (PHP_INT_SIZE === 8) {
-    define('MIN_INT64', -9223372036854775808);
-} else {
-    define('MIN_INT64', MIN_INT64_STRING);
-}
-
+define('MAX_INT64_STRING',  '9223372036854775807');
+define('MIN_INT64_STRING',  '-9223372036854775808');
 define('MAX_UINT64_STRING', '-9223372036854775808');
-define('MAX_UINT64', MAX_UINT64_STRING);
+
+if (PHP_INT_SIZE === 8) {
+    define('MAX_INT64',  (int)9223372036854775807);
+    define('MIN_INT64',  (int)-9223372036854775808);
+    define('MAX_UINT64', (int)-9223372036854775808);
+} else {
+    define('MAX_INT64', MAX_INT64_STRING);
+    define('MIN_INT64', MIN_INT64_STRING);
+    define('MAX_UINT64', MAX_UINT64_STRING);
+}
 
 class TestUtil
 {
@@ -129,16 +130,24 @@
 
     public static function assertTestMessage(TestMessage $m)
     {
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getOptionalInt64());
+            assert('43'  === $m->getOptionalUint64());
+            assert('-45' === $m->getOptionalSint64());
+            assert('47'  === $m->getOptionalFixed64());
+            assert('-47' === $m->getOptionalSfixed64());
+        } else {
+            assert(-43 === $m->getOptionalInt64());
+            assert(43  === $m->getOptionalUint64());
+            assert(-45 === $m->getOptionalSint64());
+            assert(47  === $m->getOptionalFixed64());
+            assert(-47 === $m->getOptionalSfixed64());
+        }
         assert(-42 === $m->getOptionalInt32());
         assert(42  === $m->getOptionalUint32());
-        assert(-43 === $m->getOptionalInt64());
-        assert(43  === $m->getOptionalUint64());
         assert(-44 === $m->getOptionalSint32());
-        assert(-45 === $m->getOptionalSint64());
         assert(46  === $m->getOptionalFixed32());
-        assert(47  === $m->getOptionalFixed64());
         assert(-46 === $m->getOptionalSfixed32());
-        assert(-47 === $m->getOptionalSfixed64());
         assert(1.5 === $m->getOptionalFloat());
         assert(1.6 === $m->getOptionalDouble());
         assert(true=== $m->getOptionalBool());
@@ -147,16 +156,24 @@
         assert(TestEnum::ONE === $m->getOptionalEnum());
         assert(33  === $m->getOptionalMessage()->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getRepeatedInt64()[0]);
+            assert('43'  === $m->getRepeatedUint64()[0]);
+            assert('-45' === $m->getRepeatedSint64()[0]);
+            assert('47'  === $m->getRepeatedFixed64()[0]);
+            assert('-47' === $m->getRepeatedSfixed64()[0]);
+        } else {
+            assert(-43 === $m->getRepeatedInt64()[0]);
+            assert(43  === $m->getRepeatedUint64()[0]);
+            assert(-45 === $m->getRepeatedSint64()[0]);
+            assert(47  === $m->getRepeatedFixed64()[0]);
+            assert(-47 === $m->getRepeatedSfixed64()[0]);
+        }
         assert(-42 === $m->getRepeatedInt32()[0]);
         assert(42  === $m->getRepeatedUint32()[0]);
-        assert(-43 === $m->getRepeatedInt64()[0]);
-        assert(43  === $m->getRepeatedUint64()[0]);
         assert(-44 === $m->getRepeatedSint32()[0]);
-        assert(-45 === $m->getRepeatedSint64()[0]);
         assert(46  === $m->getRepeatedFixed32()[0]);
-        assert(47  === $m->getRepeatedFixed64()[0]);
         assert(-46 === $m->getRepeatedSfixed32()[0]);
-        assert(-47 === $m->getRepeatedSfixed64()[0]);
         assert(1.5 === $m->getRepeatedFloat()[0]);
         assert(1.6 === $m->getRepeatedDouble()[0]);
         assert(true=== $m->getRepeatedBool()[0]);
@@ -165,16 +182,24 @@
         assert(TestEnum::ZERO === $m->getRepeatedEnum()[0]);
         assert(34  === $m->getRepeatedMessage()[0]->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-53' === $m->getRepeatedInt64()[1]);
+            assert('53'  === $m->getRepeatedUint64()[1]);
+            assert('-55' === $m->getRepeatedSint64()[1]);
+            assert('57'  === $m->getRepeatedFixed64()[1]);
+            assert('-57' === $m->getRepeatedSfixed64()[1]);
+        } else {
+            assert(-53 === $m->getRepeatedInt64()[1]);
+            assert(53  === $m->getRepeatedUint64()[1]);
+            assert(-55 === $m->getRepeatedSint64()[1]);
+            assert(57  === $m->getRepeatedFixed64()[1]);
+            assert(-57 === $m->getRepeatedSfixed64()[1]);
+        }
         assert(-52 === $m->getRepeatedInt32()[1]);
         assert(52  === $m->getRepeatedUint32()[1]);
-        assert(-53 === $m->getRepeatedInt64()[1]);
-        assert(53  === $m->getRepeatedUint64()[1]);
         assert(-54 === $m->getRepeatedSint32()[1]);
-        assert(-55 === $m->getRepeatedSint64()[1]);
         assert(56  === $m->getRepeatedFixed32()[1]);
-        assert(57  === $m->getRepeatedFixed64()[1]);
         assert(-56 === $m->getRepeatedSfixed32()[1]);
-        assert(-57 === $m->getRepeatedSfixed64()[1]);
         assert(2.5 === $m->getRepeatedFloat()[1]);
         assert(2.6 === $m->getRepeatedDouble()[1]);
         assert(false === $m->getRepeatedBool()[1]);
@@ -183,14 +208,21 @@
         assert(TestEnum::ONE === $m->getRepeatedEnum()[1]);
         assert(35  === $m->getRepeatedMessage()[1]->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-63' === $m->getMapInt64Int64()['-63']);
+            assert('63'  === $m->getMapUint64Uint64()['63']);
+            assert('-65' === $m->getMapSint64Sint64()['-65']);
+            assert('67'  === $m->getMapFixed64Fixed64()['67']);
+        } else {
+            assert(-63 === $m->getMapInt64Int64()[-63]);
+            assert(63  === $m->getMapUint64Uint64()[63]);
+            assert(-65 === $m->getMapSint64Sint64()[-65]);
+            assert(67  === $m->getMapFixed64Fixed64()[67]);
+        }
         assert(-62 === $m->getMapInt32Int32()[-62]);
-        assert(-63 === $m->getMapInt64Int64()[-63]);
         assert(62  === $m->getMapUint32Uint32()[62]);
-        assert(63  === $m->getMapUint64Uint64()[63]);
         assert(-64 === $m->getMapSint32Sint32()[-64]);
-        assert(-65 === $m->getMapSint64Sint64()[-65]);
         assert(66  === $m->getMapFixed32Fixed32()[66]);
-        assert(67  === $m->getMapFixed64Fixed64()[67]);
         assert(3.5 === $m->getMapInt32Float()[1]);
         assert(3.6 === $m->getMapInt32Double()[1]);
         assert(true === $m->getMapBoolBool()[true]);
@@ -325,24 +357,14 @@
 
         assert(-42 === $m->getRepeatedInt32()[0]);
         assert(-52 === $m->getRepeatedInt32()[1]);
-        assert(-43 === $m->getRepeatedInt64()[0]);
-        assert(-53 === $m->getRepeatedInt64()[1]);
         assert(42  === $m->getRepeatedUint32()[0]);
         assert(52  === $m->getRepeatedUint32()[1]);
-        assert(43  === $m->getRepeatedUint64()[0]);
-        assert(53  === $m->getRepeatedUint64()[1]);
         assert(-44 === $m->getRepeatedSint32()[0]);
         assert(-54 === $m->getRepeatedSint32()[1]);
-        assert(-45 === $m->getRepeatedSint64()[0]);
-        assert(-55 === $m->getRepeatedSint64()[1]);
         assert(46  === $m->getRepeatedFixed32()[0]);
         assert(56  === $m->getRepeatedFixed32()[1]);
-        assert(47  === $m->getRepeatedFixed64()[0]);
-        assert(57  === $m->getRepeatedFixed64()[1]);
         assert(-46 === $m->getRepeatedSfixed32()[0]);
         assert(-56 === $m->getRepeatedSfixed32()[1]);
-        assert(-47 === $m->getRepeatedSfixed64()[0]);
-        assert(-57 === $m->getRepeatedSfixed64()[1]);
         assert(1.5 === $m->getRepeatedFloat()[0]);
         assert(2.5 === $m->getRepeatedFloat()[1]);
         assert(1.6 === $m->getRepeatedDouble()[0]);
@@ -351,6 +373,29 @@
         assert(false === $m->getRepeatedBool()[1]);
         assert(TestEnum::ONE  === $m->getRepeatedEnum()[0]);
         assert(TestEnum::ZERO === $m->getRepeatedEnum()[1]);
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getRepeatedInt64()[0]);
+            assert('-53' === $m->getRepeatedInt64()[1]);
+            assert('43'  === $m->getRepeatedUint64()[0]);
+            assert('53'  === $m->getRepeatedUint64()[1]);
+            assert('-45' === $m->getRepeatedSint64()[0]);
+            assert('-55' === $m->getRepeatedSint64()[1]);
+            assert('47'  === $m->getRepeatedFixed64()[0]);
+            assert('57'  === $m->getRepeatedFixed64()[1]);
+            assert('-47' === $m->getRepeatedSfixed64()[0]);
+            assert('-57' === $m->getRepeatedSfixed64()[1]);
+        } else {
+            assert(-43 === $m->getRepeatedInt64()[0]);
+            assert(-53 === $m->getRepeatedInt64()[1]);
+            assert(43  === $m->getRepeatedUint64()[0]);
+            assert(53  === $m->getRepeatedUint64()[1]);
+            assert(-45 === $m->getRepeatedSint64()[0]);
+            assert(-55 === $m->getRepeatedSint64()[1]);
+            assert(47  === $m->getRepeatedFixed64()[0]);
+            assert(57  === $m->getRepeatedFixed64()[1]);
+            assert(-47 === $m->getRepeatedSfixed64()[0]);
+            assert(-57 === $m->getRepeatedSfixed64()[1]);
+        }
     }
 
     public static function getGoldenTestPackedMessage()