<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Tue, Nov 13, 2018 at 11:46 AM Davide Italiano via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: davide<br>
Date: Tue Nov 13 11:43:43 2018<br>
New Revision: 346783<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=346783&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=346783&view=rev</a><br>
Log:<br>
[Cocoa] Implement formatter for the new NSDate representation.<br>
<br>
<rdar://problem/46002786><br>
<br>
Modified:<br>
lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp<br>
<br>
Modified: lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp?rev=346783&r1=346782&r2=346783&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp?rev=346783&r1=346782&r2=346783&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp (original)<br>
+++ lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp Tue Nov 13 11:43:43 2018<br>
@@ -742,6 +742,60 @@ bool lldb_private::formatters::NSURLSumm<br>
return false;<br>
}<br>
<br>
+/// Bias value for tagged pointer exponents.<br>
+/// Recommended values:<br>
+/// 0x3e3: encodes all dates between distantPast and distantFuture<br>
+/// except for the range within about 1e-28 second of the reference date.<br>
+/// 0x3ef: encodes all dates for a few million years beyond distantPast and<br>
+/// distantFuture, except within about 1e-25 second of the reference date.<br>
+const int TAGGED_DATE_EXPONENT_BIAS = 0x3ef;<br>
+<br>
+typedef union {<br>
+ struct {<br>
+ uint64_t fraction:52; // unsigned<br>
+ uint64_t exponent:11; // signed<br>
+ uint64_t sign:1;<br>
+ };<br>
+ uint64_t i;<br>
+ double d;<br>
+} DoubleBits;<br>
+typedef union {<br>
+ struct {<br>
+ uint64_t fraction:52; // unsigned<br>
+ uint64_t exponent:7; // signed<br>
+ uint64_t sign:1;<br>
+ uint64_t unused:4; // placeholder for pointer tag bits<br>
+ };<br>
+ uint64_t i;<br>
+} TaggedDoubleBits;<br>
+<br>
+static uint64_t decodeExponent(uint64_t exp) {<br>
+ int64_t exp7 = exp;<br>
+ // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits<br>
+ // before performing arithmetic.<br>
+ int64_t exp11 = ((exp7 << 57) >> 57) + TAGGED_DATE_EXPONENT_BIAS;<br>
+ return exp11;<br>
+}<br>
+<br>
+static uint64_t decodeTaggedTimeInterval(uint64_t encodedTimeInterval) {<br>
+ if (encodedTimeInterval == 0)<br>
+ return 0.0;<br>
+ if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())<br>
+ return -0.0;<br>
+<br>
+ TaggedDoubleBits encodedBits = { .i = encodedTimeInterval };<br>
+ DoubleBits decodedBits;<br>
+<br>
+ // Sign and fraction are represented exactly.<br>
+ // Exponent is encoded.<br>
+ assert(encodedBits.unused == 0);<br>
+ decodedBits.sign = encodedBits.sign;<br>
+ decodedBits.fraction = encodedBits.fraction;<br>
+ decodedBits.exponent = decodeExponent(encodedBits.exponent);<br>
+<br>
+ return decodedBits.d;<br></blockquote><div>This is undefined behavior since it's type punning through a union. Normally this is harmless and all compilers actually do what you would expect them to do. In this case, however, it isn't because bitfield layout is implementation defined so not every compiler will lay the bitfield out in the way you expect. So if you want this to be correct you have to explicitly construct the bits of the double using bitshifts, going through a union will fail on some implementations.</div></div></div>