[Lldb-commits] [lldb] r346783 - [Cocoa] Implement formatter for the new NSDate representation.

Davide Italiano via lldb-commits lldb-commits at lists.llvm.org
Tue Nov 13 11:43:43 PST 2018


Author: davide
Date: Tue Nov 13 11:43:43 2018
New Revision: 346783

URL: http://llvm.org/viewvc/llvm-project?rev=346783&view=rev
Log:
[Cocoa] Implement formatter for the new NSDate representation.

<rdar://problem/46002786>

Modified:
    lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp

Modified: lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp?rev=346783&r1=346782&r2=346783&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp Tue Nov 13 11:43:43 2018
@@ -742,6 +742,60 @@ bool lldb_private::formatters::NSURLSumm
   return false;
 }
 
+/// Bias value for tagged pointer exponents.
+/// Recommended values:
+/// 0x3e3: encodes all dates between distantPast and distantFuture
+///   except for the range within about 1e-28 second of the reference date.
+/// 0x3ef: encodes all dates for a few million years beyond distantPast and
+///   distantFuture, except within about 1e-25 second of the reference date.
+const int TAGGED_DATE_EXPONENT_BIAS = 0x3ef;
+
+typedef union {
+  struct {
+    uint64_t fraction:52;  // unsigned
+    uint64_t exponent:11;  // signed
+    uint64_t sign:1;
+  };
+  uint64_t i;
+  double d;
+} DoubleBits;
+typedef union {
+  struct {
+    uint64_t fraction:52;  // unsigned
+    uint64_t exponent:7;   // signed
+    uint64_t sign:1;
+    uint64_t unused:4;  // placeholder for pointer tag bits
+  };
+  uint64_t i;
+} TaggedDoubleBits;
+
+static uint64_t decodeExponent(uint64_t exp) {
+  int64_t exp7 = exp;
+  // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits
+  // before performing arithmetic.
+  int64_t exp11 = ((exp7 << 57) >> 57) + TAGGED_DATE_EXPONENT_BIAS;
+  return exp11;
+}
+
+static uint64_t decodeTaggedTimeInterval(uint64_t encodedTimeInterval) {
+  if (encodedTimeInterval == 0)
+    return 0.0;
+  if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
+    return -0.0;
+
+  TaggedDoubleBits encodedBits = { .i = encodedTimeInterval };
+  DoubleBits decodedBits;
+
+  // Sign and fraction are represented exactly.
+  // Exponent is encoded.
+  assert(encodedBits.unused == 0);
+  decodedBits.sign = encodedBits.sign;
+  decodedBits.fraction = encodedBits.fraction;
+  decodedBits.exponent = decodeExponent(encodedBits.exponent);
+
+  return decodedBits.d;
+}
+
 bool lldb_private::formatters::NSDateSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
   ProcessSP process_sp = valobj.GetProcessSP();
@@ -781,9 +835,9 @@ bool lldb_private::formatters::NSDateSum
   if (class_name.IsEmpty())
     return false;
 
+  uint64_t info_bits = 0, value_bits = 0;
   if ((class_name == g_NSDate) || (class_name == g___NSDate) ||
       (class_name == g___NSTaggedDate)) {
-    uint64_t info_bits = 0, value_bits = 0;
     if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
       date_value_bits = ((value_bits << 8) | (info_bits << 4));
       memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
@@ -813,6 +867,14 @@ bool lldb_private::formatters::NSDateSum
     stream.Printf("0001-12-30 00:00:00 +0000");
     return true;
   }
+
+  // Accomodate for the __NSTaggedDate format introduced in Foundation 1600.
+  if (class_name == g___NSTaggedDate) {
+    auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
+    if (runtime && runtime->GetFoundationVersion() >= 1600)
+      date_value = decodeTaggedTimeInterval(value_bits << 4);
+  }
+
   // this snippet of code assumes that time_t == seconds since Jan-1-1970 this
   // is generally true and POSIXly happy, but might break if a library vendor
   // decides to get creative




More information about the lldb-commits mailing list