Improve CHECK_<op> logging.

This patch lets us show the lhs and rhs when a relational check fails. (I show
both, even though that looks silly in cases like CHECK_EQ(rc, 0) where we'll
say "rc=-1, 0=0", because it's helpful in cases like CHECK_LT(i, size()) where
we want "i=4, size=2".)

I had to add a few operator<<s for enums, and fix a bunch of signed/unsigned
mismatches, and put the StringPiece operator<< in the right namespace.

Change-Id: I390f38bd97b3f50e12182f36ff027ca067c48d69
diff --git a/src/assembler.cc b/src/assembler.cc
index d0a8aa4..689e0c8 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -61,7 +61,7 @@
 
   // Verify internal state.
   CHECK_EQ(Capacity(), kInitialBufferCapacity);
-  CHECK_EQ(Size(), 0);
+  CHECK_EQ(Size(), 0U);
 }
 
 
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc
index ce66fb2..3ce5199 100644
--- a/src/assembler_arm.cc
+++ b/src/assembler_arm.cc
@@ -61,6 +61,53 @@
 };
 
 
+static const char* kRegisterNames[] = {
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+  "fp", "ip", "sp", "lr", "pc"
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs) {
+  if (rhs >= R0 && rhs <= PC) {
+    os << kRegisterNames[rhs];
+  } else {
+     os << "Register[" << int(rhs) << "]";
+  }
+  return os;
+}
+
+
+std::ostream& operator<<(std::ostream& os, const SRegister& rhs) {
+  if (rhs >= S0 && rhs < kNumberOfSRegisters) {
+    os << "s" << int(rhs);
+  } else {
+    os << "SRegister[" << int(rhs) << "]";
+  }
+  return os;
+}
+
+
+std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
+  if (rhs >= D0 && rhs < kNumberOfDRegisters) {
+    os << "d" << int(rhs);
+  } else {
+    os << "DRegister[" << int(rhs) << "]";
+  }
+  return os;
+}
+
+
+static const char* kConditionNames[] = {
+  "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL",
+};
+std::ostream& operator<<(std::ostream& os, const Condition& rhs) {
+  if (rhs >= EQ && rhs <= AL) {
+    os << kConditionNames[rhs];
+  } else {
+    os << "Condition[" << int(rhs) << "]";
+  }
+  return os;
+}
+
+
 void Assembler::Emit(int32_t value) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   buffer_.Emit<int32_t>(value);
@@ -151,7 +198,7 @@
                                    Register rm,
                                    ShifterOperand so) {
   CHECK_NE(cond, kNoCondition);
-  CHECK_EQ(so.type(), 1);
+  CHECK_EQ(so.type(), 1U);
   int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
                      static_cast<int32_t>(MOV) << kOpcodeShift |
                      static_cast<int32_t>(rd) << kRdShift |
@@ -168,7 +215,7 @@
                                   Register rm,
                                   ShifterOperand so) {
   CHECK_NE(cond, kNoCondition);
-  CHECK_EQ(so.type(), 0);
+  CHECK_EQ(so.type(), 0U);
   int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
                      static_cast<int32_t>(MOV) << kOpcodeShift |
                      static_cast<int32_t>(rd) << kRdShift |
diff --git a/src/assembler_x86.cc b/src/assembler_x86.cc
index ce7f104..0c44c08 100644
--- a/src/assembler_x86.cc
+++ b/src/assembler_x86.cc
@@ -20,6 +20,18 @@
   }
 };
 
+static const char* kRegisterNames[] = {
+  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+};
+std::ostream& operator<<(std::ostream& os, const Register& rhs) {
+  if (rhs >= EAX && rhs <= EDI) {
+    os << kRegisterNames[rhs];
+  } else {
+    os << "Register[" << int(rhs) << "]";
+  }
+  return os;
+}
+
 
 void Assembler::InitializeMemoryWithBreakpoints(byte* data, size_t length) {
   memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e2ab39a..a205a06 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1118,10 +1118,10 @@
       const InstanceField* field = klass->GetInstanceField(i);
       size_t byte_offset = field->GetOffset();
       CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
-      CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0);
+      CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
       if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
         uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
-        CHECK_NE(new_bit, 0);
+        CHECK_NE(new_bit, 0U);
         reference_offsets |= new_bit;
       } else {
         reference_offsets = CLASS_WALK_SUPER;
diff --git a/src/constants_arm.h b/src/constants_arm.h
index 0849a09..bb693d3 100644
--- a/src/constants_arm.h
+++ b/src/constants_arm.h
@@ -3,6 +3,7 @@
 #ifndef ART_SRC_CONSTANTS_ARM_H_
 #define ART_SRC_CONSTANTS_ARM_H_
 
+#include <iosfwd>
 #include <stdint.h>
 #include "src/casts.h"
 #include "src/logging.h"
@@ -54,6 +55,7 @@
   kNumberOfCoreRegisters = 16,
   kNoRegister = -1,
 };
+std::ostream& operator<<(std::ostream& os, const Register& rhs);
 
 
 enum ScaleFactor {
@@ -101,6 +103,7 @@
   kNumberOfSRegisters = 32,
   kNoSRegister = -1,
 };
+std::ostream& operator<<(std::ostream& os, const SRegister& rhs);
 
 
 // Values for double-precision floating point registers.
@@ -145,6 +148,7 @@
   kNumberOfOverlappingDRegisters = 16,
   kNoDRegister = -1,
 };
+std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
 
 
 // Values for the condition field as defined in section A3.2.
@@ -168,6 +172,7 @@
   kSpecialCondition = 15,  // special condition (refer to section A3.2.1)
   kMaxCondition = 16,
 };
+std::ostream& operator<<(std::ostream& os, const Condition& rhs);
 
 
 // Opcodes for Data-processing instructions (instructions with a type 0 and 1)
diff --git a/src/constants_x86.h b/src/constants_x86.h
index 70a79e9..d96e6dc 100644
--- a/src/constants_x86.h
+++ b/src/constants_x86.h
@@ -7,6 +7,8 @@
 #include "src/logging.h"
 #include "src/macros.h"
 
+#include <iosfwd>
+
 namespace art {
 
 enum Register {
@@ -22,6 +24,7 @@
   kFirstByteUnsafeRegister = 4,
   kNoRegister = -1  // Signals an illegal register.
 };
+std::ostream& operator<<(std::ostream& os, const Register& rhs);
 
 
 enum ByteRegister {
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 7840827..53bc305 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -2,6 +2,10 @@
 
 #include "src/dex_verifier.h"
 
+#include <iostream>
+
+#include "logging.h"
+#include "stringpiece.h"
 
 namespace art {
 
@@ -12,14 +16,14 @@
   for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
     Method* method = klass->GetDirectMethod(i);
     if (!VerifyMethod(method)) {
-      LG << "Verifier rejected class " << klass->GetDescriptor();
+        LOG(ERROR) << "Verifier rejected class " << klass->GetDescriptor();
       return false;
     }
   }
   for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
     Method* method = klass->GetVirtualMethod(i);
     if (!VerifyMethod(method)) {
-      LG << "Verifier rejected class " << klass->GetDescriptor();
+        LOG(ERROR) << "Verifier rejected class " << klass->GetDescriptor();
       return false;
     }
   }
diff --git a/src/logging.h b/src/logging.h
index 98eb953..0a96504 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -25,14 +25,23 @@
   if (!(x)) \
     LogMessage(__FILE__, __LINE__, FATAL, -1).stream() << "Check failed: " #x
 
-#define CHECK_EQ(x, y) CHECK((x) == (y))
-#define CHECK_NE(x, y) CHECK((x) != (y))
-#define CHECK_LE(x, y) CHECK((x) <= (y))
-#define CHECK_LT(x, y) CHECK((x) < (y))
-#define CHECK_GE(x, y) CHECK((x) >= (y))
-#define CHECK_GT(x, y) CHECK((x) > (y))
-#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
-#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
+#define CHECK_OP(LHS, RHS, OP) \
+  do { \
+    typeof (LHS) _lhs = (LHS); \
+    typeof (RHS) _rhs = (RHS); \
+    if (!(_lhs OP _rhs)) { \
+      LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
+          << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
+          << " (" #LHS "=" << _lhs << ", " #RHS "=" << _rhs << ")";  \
+    } \
+  } while (false)
+
+#define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
+#define CHECK_NE(x, y) CHECK_OP(x, y, !=)
+#define CHECK_LE(x, y) CHECK_OP(x, y, <=)
+#define CHECK_LT(x, y) CHECK_OP(x, y, <)
+#define CHECK_GE(x, y) CHECK_OP(x, y, >=)
+#define CHECK_GT(x, y) CHECK_OP(x, y, >)
 
 #define CHECK_STROP(s1, s2, sense) \
   do { \
@@ -44,6 +53,9 @@
     } \
   } while (false)
 
+#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
+#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
+
 #ifndef NDEBUG
 
 #define DCHECK(x) CHECK(x)
diff --git a/src/memory_region.cc b/src/memory_region.cc
index a10516f..30d61ed 100644
--- a/src/memory_region.cc
+++ b/src/memory_region.cc
@@ -9,8 +9,8 @@
 namespace art {
 
 void MemoryRegion::CopyFrom(size_t offset, const MemoryRegion& from) const {
-  CHECK_NE(from.pointer(), NULL);
-  CHECK_GT(from.size(), 0);
+  CHECK(from.pointer() != NULL);
+  CHECK_GT(from.size(), 0U);
   CHECK_GE(this->size(), from.size());
   CHECK_LE(offset, this->size() - from.size());
   memmove(reinterpret_cast<void*>(start() + offset),
diff --git a/src/object.cc b/src/object.cc
index d897c52..f5792fc 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -117,5 +117,24 @@
   return NULL;  // TODO
 }
 
+static const char* kClassStatusNames[] = {
+  "Error",
+  "NotReady",
+  "Idx",
+  "Loaded",
+  "Resolved",
+  "Verifying",
+  "Verified",
+  "Initializing",
+  "Initialized"
+};
+std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
+  if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
+    os << kClassStatusNames[rhs - 1];
+  } else {
+    os << "Class::Status[" << int(rhs) << "]";
+  }
+  return os;
+}
 
 }  // namespace art
diff --git a/src/object.h b/src/object.h
index 3bad627..ac42081 100644
--- a/src/object.h
+++ b/src/object.h
@@ -702,6 +702,7 @@
   size_t num_sfields_;
   StaticField* sfields_;
 };
+std::ostream& operator<<(std::ostream& os, const Class::Status& rhs);
 
 class DataObject : public Object {
  public:
diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc
index 2aaa5d9..caa159a 100644
--- a/src/raw_dex_file.cc
+++ b/src/raw_dex_file.cc
@@ -146,7 +146,7 @@
 }
 
 void RawDexFile::InitIndex() {
-  CHECK_EQ(index_.size(), 0);
+  CHECK_EQ(index_.size(), 0U);
   for (size_t i = 0; i < NumClassDefs(); ++i) {
     const ClassDef& class_def = GetClassDef(i);
     const char* descriptor = GetClassDescriptor(class_def);
diff --git a/src/stringpiece.cc b/src/stringpiece.cc
index 27e24d1..4b1ef7b 100644
--- a/src/stringpiece.cc
+++ b/src/stringpiece.cc
@@ -90,9 +90,9 @@
 
 const StringPiece::size_type StringPiece::npos = size_type(-1);
 
-}  // namespace art
-
 std::ostream& operator<<(std::ostream& o, const art::StringPiece& piece) {
   o.write(piece.data(), piece.size());
   return o;
 }
+
+}  // namespace art
diff --git a/src/stringpiece.h b/src/stringpiece.h
index 3aefa57..6a5c60b 100644
--- a/src/stringpiece.h
+++ b/src/stringpiece.h
@@ -198,9 +198,8 @@
   return !(x < y);
 }
 
-}  // namespace art
-
-// allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, const art::StringPiece& piece);
 
+}  // namespace art
+
 #endif  // ART_SRC_STRINGPIECE_H_
diff --git a/src/thread.cc b/src/thread.cc
index a3899c7..60e977f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -137,7 +137,7 @@
   // Make sure that all threads have exited and unregistered when we
   // reach this point. This means that all daemon threads had been
   // shutdown cleanly.
-  CHECK_EQ(list_.size(), 0);
+  CHECK_EQ(list_.size(), 0U);
   delete lock_;
   lock_ = NULL;
 }