Fix usage of APInt.getRawData for big-endian systems
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 14 Apr 2016 14:32:01 +0000 (14:32 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 14 Apr 2016 14:32:01 +0000 (14:32 +0000)
commitca07434234476d05e15e4e23ac927a70a88bd80b
tree1ca4158f15ddbea51e246bf04662705eea84e00c
parentb00ef10b70b1939e7ef3a499eedbeac6860fa3fc
Fix usage of APInt.getRawData for big-endian systems

The Scalar implementation and a few other places in LLDB directly
access the internal implementation of APInt values using the
getRawData method.  Unfortunately, pretty much all of these places
do not handle big-endian systems correctly.  While on little-endian
machines, the pointer returned by getRawData can simply be used as
a pointer to the integer value in its natural format, no matter
what size, this is not true on big-endian systems: getRawData
actually points to an array of type uint64_t, with the first element
of the array always containing the least-significant word of the
integer.  This means that if the bitsize of that integer is smaller
than 64, we need to add an offset to the pointer returned by
getRawData in order to access the value in its natural type, and
if the bitsize is *larger* than 64, we actually have to swap the
constituent words before we can access the value in its natural type.

This patch fixes every incorrect use of getRawData in the code base.
For the most part, this is done by simply removing uses of getRawData
in the first place, and using other APInt member functions to operate
on the integer data.

This can be done in many member functions of Scalar itself, as well
as in Symbol/Type.h and in IRInterpreter::Interpret.  For the latter,
I've had to add a Scalar::MakeUnsigned routine to parallel the existing
Scalar::MakeSigned, e.g. in order to implement an unsigned divide.

The Scalar::RawUInt, Scalar::RawULong, and Scalar::RawULongLong
were already unused and can be simply removed.  I've also removed
the Scalar::GetRawBits64 function and its few users.

The one remaining user of getRawData in Scalar.cpp is GetBytes.
I've implemented all the cases described above to correctly
implement access to the underlying integer data on big-endian
systems.  GetData now simply calls GetBytes instead of reimplementing
its contents.

Finally, two places in the clang interface code were also accessing
APInt.getRawData in order to actually construct a byte representation
of an integer.  I've changed those to make use of a Scalar instead,
to avoid having to re-implement the logic there.

The patch also adds a couple of unit tests verifying correct operation
of the GetBytes routine as well as the conversion routines.  Those tests
actually exposed more problems in the Scalar code: the SetValueFromData
routine didn't work correctly for 128- and 256-bit data types, and the
SChar routine should have an explicit "signed char" return type to work
correctly on platforms where char defaults to unsigned.

Differential Revision: http://reviews.llvm.org/D18981

llvm-svn: 266311
lldb/include/lldb/Core/Scalar.h
lldb/include/lldb/Symbol/Type.h
lldb/source/Core/Scalar.cpp
lldb/source/Expression/IRInterpreter.cpp
lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
lldb/source/Symbol/ClangASTContext.cpp
lldb/unittests/Core/ScalarTest.cpp