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

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 14 09:20:11 PST 2018


On Tue, Nov 13, 2018 at 11:46 AM Davide Italiano via lldb-commits <
lldb-commits at lists.llvm.org> wrote:

> 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;
>
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20181114/9cc9455f/attachment.html>


More information about the lldb-commits mailing list