Use llvm::APFloat for formatting if a target is available. Each target when debugging has a "ASTContext" that helps us to use the correct floating point semantics. Now that APFloat supports toString we now use that. If we don't have a target, we still fall back on the old display methodology, but the important formatting should always have a target available and thus use the compiler floating point code.

Modified the test programs to use floating point constants that always will display correctly. We had some numbers that were being rounded, and now that we are using clang, we no longer round them and we get more correct results.

llvm-svn: 183792
This commit is contained in:
Greg Clayton 2013-06-11 21:56:55 +00:00
parent 1f16b743d9
commit bc8fc0f5e0
7 changed files with 188 additions and 70 deletions

View File

@ -1003,7 +1003,16 @@ public:
const char *s,
uint8_t *dst,
size_t dst_size);
lldb::clang_type_t
GetFloatTypeFromBitSize (size_t bit_size)
{
return GetFloatTypeFromBitSize (getASTContext(), bit_size);
}
static lldb::clang_type_t
GetFloatTypeFromBitSize (clang::ASTContext *ast,
size_t bit_size);
//------------------------------------------------------------------
// Qualifiers
//------------------------------------------------------------------

View File

@ -15,11 +15,15 @@
#include <sstream>
#include <string>
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/MathExtras.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DataBuffer.h"
@ -30,6 +34,7 @@
#include "lldb/Core/UUID.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Target.h"
@ -1234,8 +1239,8 @@ DataExtractor::Skip_LEB128 (offset_t *offset_ptr) const
return bytes_consumed;
}
static lldb::offset_t
DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix)
static bool
GetAPInt (const DataExtractor &data, lldb::offset_t *offset_ptr, lldb::offset_t byte_size, llvm::APInt &result)
{
llvm::SmallVector<uint64_t, 2> uint64_array;
lldb::offset_t bytes_left = byte_size;
@ -1247,20 +1252,22 @@ DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::of
{
if (bytes_left >= 8)
{
u64 = data.GetU64(&offset);
u64 = data.GetU64(offset_ptr);
bytes_left -= 8;
}
else
{
u64 = data.GetMaxU64(&offset, (uint32_t)bytes_left);
u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
bytes_left = 0;
}
}
uint64_array.push_back(u64);
}
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
}
else if (byte_order == lldb::eByteOrderBig)
{
lldb::offset_t be_offset = offset + byte_size;
lldb::offset_t be_offset = *offset_ptr + byte_size;
lldb::offset_t temp_offset;
while (bytes_left > 0)
{
@ -1277,28 +1284,36 @@ DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::of
temp_offset = be_offset;
u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
bytes_left = 0;
}
}
uint64_array.push_back(u64);
}
*offset_ptr += byte_size;
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
}
else
return offset;
return false;
}
llvm::APInt apint (byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
std::string apint_str(apint.toString(radix, is_signed));
switch (radix)
static lldb::offset_t
DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix)
{
llvm::APInt apint;
if (GetAPInt (data, &offset, byte_size, apint))
{
case 2:
s->Write ("0b", 2);
break;
case 8:
s->Write ("0", 1);
break;
case 10:
break;
std::string apint_str(apint.toString(radix, is_signed));
switch (radix)
{
case 2:
s->Write ("0b", 2);
break;
case 8:
s->Write ("0", 1);
break;
case 10:
break;
}
s->Write(apint_str.c_str(), apint_str.size());
}
s->Write(apint_str.c_str(), apint_str.size());
return offset;
}
@ -1702,39 +1717,117 @@ DataExtractor::Dump (Stream *s,
case eFormatFloat:
{
std::ostringstream ss;
if (item_byte_size == sizeof(float) || item_byte_size == 2)
TargetSP target_sp;
bool used_apfloat = false;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp)
{
float f;
if (item_byte_size == 2)
ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
if (clang_ast)
{
uint16_t half = this->GetU16(&offset);
f = half2float(half);
clang::ASTContext *ast = clang_ast->getASTContext();
if (ast)
{
llvm::SmallVector<char, 256> sv;
// Show full precision when printing float values
const unsigned format_precision = 0;
const unsigned format_max_padding = 100;
size_t item_bit_size = item_byte_size * 8;
if (item_bit_size == ast->getTypeSize(ast->FloatTy))
{
llvm::APInt apint(item_bit_size, this->GetMaxU64(&offset, item_byte_size));
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->FloatTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
else if (item_bit_size == ast->getTypeSize(ast->DoubleTy))
{
llvm::APInt apint;
if (GetAPInt (*this, &offset, item_byte_size, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->DoubleTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
}
else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy))
{
llvm::APInt apint;
switch (target_sp->GetArchitecture().GetCore())
{
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_32_i486:
case ArchSpec::eCore_x86_32_i486sx:
case ArchSpec::eCore_x86_64_x86_64:
// clang will assert when contructing the apfloat if we use a 16 byte integer value
if (GetAPInt (*this, &offset, 10, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
break;
default:
if (GetAPInt (*this, &offset, item_byte_size, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
break;
}
}
else if (item_bit_size == ast->getTypeSize(ast->HalfTy))
{
llvm::APInt apint(item_bit_size, this->GetU16(&offset));
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->HalfTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
if (!sv.empty())
{
s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data());
used_apfloat = true;
}
}
}
}
if (!used_apfloat)
{
std::ostringstream ss;
if (item_byte_size == sizeof(float) || item_byte_size == 2)
{
float f;
if (item_byte_size == 2)
{
uint16_t half = this->GetU16(&offset);
f = half2float(half);
}
else
{
f = GetFloat (&offset);
}
ss.precision(std::numeric_limits<float>::digits10);
ss << f;
}
else if (item_byte_size == sizeof(double))
{
ss.precision(std::numeric_limits<double>::digits10);
ss << GetDouble(&offset);
}
else if (item_byte_size == sizeof(long double))
{
ss.precision(std::numeric_limits<long double>::digits10);
ss << GetLongDouble(&offset);
}
else
{
f = GetFloat (&offset);
s->Printf("error: unsupported byte size (%zu) for float format", item_byte_size);
return offset;
}
ss.precision(std::numeric_limits<float>::digits10);
ss << f;
}
else if (item_byte_size == sizeof(double))
{
ss.precision(std::numeric_limits<double>::digits10);
ss << GetDouble(&offset);
ss.flush();
s->Printf("%s", ss.str().c_str());
}
else if (item_byte_size == sizeof(long double))
{
ss.precision(std::numeric_limits<long double>::digits10);
ss << GetLongDouble(&offset);
}
else
{
s->Printf("error: unsupported byte size (%zu) for float format", item_byte_size);
return offset;
}
ss.flush();
s->Printf("%s", ss.str().c_str());
}
break;

View File

@ -6682,6 +6682,24 @@ ClangASTContext::ConvertStringToFloatValue (ASTContext *ast, clang_type_t clang_
return 0;
}
lldb::clang_type_t
ClangASTContext::GetFloatTypeFromBitSize (clang::ASTContext *ast,
size_t bit_size)
{
if (ast)
{
if (bit_size == ast->getTypeSize(ast->FloatTy))
return ast->FloatTy.getAsOpaquePtr();
else if (bit_size == ast->getTypeSize(ast->DoubleTy))
return ast->DoubleTy.getAsOpaquePtr();
else if (bit_size == ast->getTypeSize(ast->LongDoubleTy))
return ast->LongDoubleTy.getAsOpaquePtr();
else if (bit_size == ast->getTypeSize(ast->HalfTy))
return ast->HalfTy.getAsOpaquePtr();
}
return NULL;
}
unsigned
ClangASTContext::GetTypeQualifiers(clang_type_t clang_type)
{
@ -6704,7 +6722,7 @@ ClangASTContext::GetCompleteType (clang::ASTContext *ast, lldb::clang_type_t cla
bool
ClangASTContext::GetCompleteType (clang_type_t clang_type)
{
{
return ClangASTContext::GetCompleteType (getASTContext(), clang_type);
}

View File

@ -81,7 +81,7 @@ class NamedSummariesDataFormatterTestCase(TestBase):
self.expect("frame variable second --summary AllUseIt",
substrs = ['AllUseIt: x=65',
'y=43.21'])
'y=43.25'])
self.expect("frame variable third --summary AllUseIt",
substrs = ['AllUseIt: x=96',

View File

@ -46,7 +46,7 @@ struct Third
int main (int argc, const char * argv[])
{
First first(12,34);
Second second(65,43.21);
Second second(65,43.25);
Third *third = new Third(96,'E');
first.dummy = 1; // Set break point at this line.

View File

@ -283,29 +283,29 @@ class SmartArrayDataFormatterTestCase(TestBase):
self.expect("frame variable flarr",
substrs = ['flarr = arr =',
'{78.5},{77.4},{78},{76.1},{76.7},{76.8},{77}'])
'{78.5},{77.25},{78},{76.125},{76.75},{76.875},{77}'])
self.expect("frame variable other.flarr",
substrs = ['flarr = arr = ',
'{25.5},{25.7},{25.9},{26.4},{27.1},{27.3},{26.9}'])
'{25.5},{25.25},{25.125},{26.75},{27.375},{27.5},{26.125}'])
# printing full array as an array
self.runCmd("type summary add --summary-string \"arr = ${var%float32[]}\" \"float [7]\"")
self.expect("frame variable flarr",
substrs = ['flarr = arr =',
'78.5,77.4,78,76.1,76.7,76.8,77'])
'78.5,77.25,78,76.125,76.75,76.875,77'])
self.expect("frame variable other.flarr",
substrs = ['flarr = arr =',
'25.5,25.7,25.9,26.4,27.1,27.3,26.9'])
'25.5,25.25,25.125,26.75,27.375,27.5,26.125'])
# using array smart summary strings for pointers should make no sense
self.runCmd("type summary add --summary-string \"arr = ${var%float32[]}\" \"float *\"")
self.runCmd("type summary add --summary-string \"arr = ${var%int32_t[]}\" \"int *\"")
self.expect("frame variable flptr", matching=False,
substrs = ['78.5,77.4,78,76.1,76.7,76.8,77'])
substrs = ['78.5,77.25,78,76.125,76.75,76.875,77'])
self.expect("frame variable intptr", matching=False,
substrs = ['1,1,2,3,5'])
@ -316,11 +316,11 @@ class SmartArrayDataFormatterTestCase(TestBase):
self.expect("frame variable flarr",
substrs = ['flarr = arr =',
'00 00 9d 42,cd cc 9a 42,00 00 9c 42,33 33 98 42,66 66 99 42,9a 99 99 42,00 00 9a 42'])
'00 00 9d 42,00 80 9a 42,00 00 9c 42,00 40 98 42,00 80 99 42,00 c0 99 42,00 00 9a 42'])
self.expect("frame variable other.flarr",
substrs = ['flarr = arr =',
'00 00 cc 41,9a 99 cd 41,33 33 cf 41,33 33 d3 41,cd cc d8 41,66 66 da 41,33 33 d7 41'])
'00 00 cc 41,00 00 ca 41,00 00 c9 41,00 00 d6 41,00 00 db 41,00 00 dc 41,00 00 d1 41'])
self.expect("frame variable intarr",
substrs = ['intarr = arr =',
@ -335,13 +335,11 @@ class SmartArrayDataFormatterTestCase(TestBase):
self.expect("frame variable flarr",
substrs = ['flarr = arr =',
'...B,cd cc 9a 42',
'ff.B,9a 99 99 42'])
'00 00 9d 42 ...B,00 80 9a 42 ...B,00 00 9c 42 ...B,00 40 98 42 .@.B,00 80 99 42 ...B,00 c0 99 42 ...B,00 00 9a 42 ...B'])
self.expect("frame variable other.flarr",
substrs = ['flarr = arr =',
'...A,33 33 cf 41',
'33.A,cd cc d8 41'])
'00 00 cc 41 ...A,00 00 ca 41 ...A,00 00 c9 41 ...A,00 00 d6 41 ...A,00 00 db 41 ...A,00 00 dc 41 ...A,00 00 d1 41 ...A'])
self.expect("frame variable intarr",
substrs = ['intarr = arr =',

View File

@ -36,12 +36,12 @@ struct SomeOtherData
intarr[4] = 5;
flarr[0] = 25.5;
flarr[1] = 25.7;
flarr[2] = 25.9;
flarr[3] = 26.4;
flarr[4] = 27.1;
flarr[5] = 27.3;
flarr[6] = 26.9;
flarr[1] = 25.25;
flarr[2] = 25.125;
flarr[3] = 26.75;
flarr[4] = 27.375;
flarr[5] = 27.5;
flarr[6] = 26.125;
}
};
@ -51,7 +51,7 @@ int main (int argc, const char * argv[])
char *strptr = NULL;
strptr = "Hello world!";
int intarr[5] = {1,1,2,3,5};
float flarr[7] = {78.5,77.4,78.0,76.1,76.7,76.8,77.0};
float flarr[7] = {78.5,77.25,78.0,76.125,76.75,76.875,77.0};
SomeData data;