@@ -338,6 +338,92 @@ static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
338338 return llvm::APFloat::Bogus ();
339339}
340340
341+
342+ static std::optional<llvm::APInt> ReadAPIntFromMemory (const DataExtractor &data, Process * process,
343+ lldb::addr_t load_addr,
344+ size_t byte_size) {
345+ if (byte_size == 0 )
346+ return std::nullopt ;
347+
348+ llvm::SmallVector<uint64_t , 2 > uint64_array;
349+ size_t bytes_left = byte_size;
350+ uint64_t u64 ;
351+ Status error;
352+ const lldb::ByteOrder byte_order = data.GetByteOrder ();
353+ if (byte_order == lldb::eByteOrderLittle) {
354+ while (bytes_left > 0 ) {
355+ if (bytes_left >= 8 ) {
356+ u64 = process->ReadUnsignedIntegerFromMemory (load_addr, 8 , 0 , error);
357+ bytes_left -= 8 ;
358+ load_addr += 8 ;
359+ if (error.Fail ())
360+ return std::nullopt ;
361+ } else {
362+ u64 = process->ReadUnsignedIntegerFromMemory (load_addr, bytes_left, 0 , error);
363+ if (error.Fail ())
364+ return std::nullopt ;
365+ bytes_left = 0 ;
366+ }
367+ uint64_array.push_back (u64 );
368+ }
369+ return llvm::APInt (byte_size * 8 , llvm::ArrayRef<uint64_t >(uint64_array));
370+ }
371+ // CR sspies: big endian not supported
372+ return std::nullopt ;
373+ }
374+
375+
376+
377+ void PrintAPIntAsFloat (Stream *s, llvm::APInt apint,
378+ const llvm::fltSemantics &semantics,
379+ std::optional<unsigned > format_max_padding,
380+ std::string prefix = " " , std::string suffix = " " ) {
381+
382+ llvm::APFloat apfloat (semantics, apint);
383+ llvm::SmallVector<char , 256 > sv;
384+ if (format_max_padding)
385+ apfloat.toPossiblyShortString (sv, *format_max_padding);
386+ else
387+ apfloat.toPossiblyShortString (sv);
388+
389+ s->AsRawOstream () << prefix;
390+ s->AsRawOstream () << sv;
391+ // OCaml Specific:
392+ // Following OCaml conventions, print the trailing "." to
393+ // identify that the integer is in fact a float, but don't
394+ // print any trailing zeros.
395+ bool print_trailing_dot = true ;
396+ for (char c : sv) {
397+ switch (c) {
398+ case ' -' :
399+ case ' 0' :
400+ case ' 1' :
401+ case ' 2' :
402+ case ' 3' :
403+ case ' 4' :
404+ case ' 5' :
405+ case ' 6' :
406+ case ' 7' :
407+ case ' 8' :
408+ case ' 9' :
409+ continue ;
410+ default :
411+ // if we find something that is not a number such as 'e' or 'E' or '.'
412+ // there is no need to print the trailing ".".
413+ print_trailing_dot = false ;
414+ }
415+ break ; // we found something that is not a number, so we will not print
416+ // the trailing "."
417+ }
418+ if (print_trailing_dot){
419+ s->AsRawOstream () << " ." ;
420+ }
421+
422+ s->AsRawOstream () << suffix;
423+
424+ }
425+
426+
341427static offset_t FormatOCamlValue (const DataExtractor &DE, Stream *s,
342428 offset_t start_offset, uint64_t base_addr,
343429 ExecutionContextScope *exe_ctx_scope,
@@ -365,6 +451,16 @@ static offset_t FormatOCamlValue(const DataExtractor &DE, Stream *s,
365451 exe_ctx_scope->CalculateExecutionContext (exe_ctx);
366452 Process *process = exe_ctx.GetProcessPtr ();
367453
454+ // max padding for floating point numbers
455+ TargetSP target_sp;
456+ if (exe_ctx_scope)
457+ target_sp = exe_ctx_scope->CalculateTarget ();
458+
459+ std::optional<unsigned > format_max_padding;
460+ if (target_sp)
461+ format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat ();
462+
463+
368464 if (process) {
369465 Status error;
370466 lldb::addr_t header = process->ReadPointerFromMemory (value - 8 , error);
@@ -497,51 +593,40 @@ static offset_t FormatOCamlValue(const DataExtractor &DE, Stream *s,
497593 }
498594
499595 case 253 : { // Double_tag
500- union {
501- double f;
502- uint64_t i;
503- } u;
504- u.i = process->ReadUnsignedIntegerFromMemory (value, 8 , 0 , error);
505- if (error.Fail ()) {
596+ std::optional<llvm::APInt> apint = ReadAPIntFromMemory (DE, process, value, 8 );
597+ if (!apint) {
506598 s->Printf (" <could not read float>@" );
507- } else {
508- // CR mshinwell: should probably use proper float printing code
509- // elsewhere in this file
510- s->Printf (" %g" , u.f );
511- print_default = false ;
599+ break ;
512600 }
601+ const llvm::fltSemantics &semantics = llvm::APFloat::IEEEdouble ();
602+ PrintAPIntAsFloat (s, *apint, semantics, format_max_padding);
603+ print_default = false ;
513604 break ;
514605 }
515606
516607 case 254 : { // Double_array_tag
517608 // N.B. Empty float arrays have tag zero
518609 uint64_t wosize_to_print = wosize <= 10 ? wosize : 10 ;
519- s->Printf (" [|" );
610+ print_default = false ; // we still print the default if one of the fields fails
611+ s->Printf (" [| " );
520612 for (uint64_t field = 0 ; field < wosize_to_print; field++) {
521- union {
522- double f;
523- uint64_t i;
524- } u;
525- u.i = process->ReadUnsignedIntegerFromMemory (value, 8 , 0 , error);
526- if (error.Fail ()) {
613+ std::optional<llvm::APInt> apint = ReadAPIntFromMemory (DE, process, value + field * 8 , 8 );
614+ if (!apint) {
527615 s->Printf (" <could not read floatarray field %" PRIu64 " >" , field);
616+ print_default = true ;
528617 } else {
529- // CR mshinwell: should probably use proper float printing code
530- // elsewhere in this file
531- s->Printf (" %g" , u.f );
618+ const llvm::fltSemantics &semantics = llvm::APFloat::IEEEdouble ();
619+ PrintAPIntAsFloat (s, *apint, semantics, format_max_padding);
532620 }
533621
534622 if (field < wosize_to_print - 1 )
535- s->Printf (" , " );
623+ s->Printf (" ; " );
536624 }
537625 if (wosize_to_print < wosize) {
538- s->Printf (" , <%" PRIu64 " more elements in floatarray>" ,
626+ s->Printf (" ; <%" PRIu64 " more elements in floatarray>" ,
539627 wosize - wosize_to_print);
540628 }
541- s->Printf (" |]" );
542-
543- if (!error.Fail ())
544- print_default = false ;
629+ s->Printf (" |]" );
545630 break ;
546631 }
547632
@@ -612,7 +697,17 @@ static offset_t FormatOCamlValue(const DataExtractor &DE, Stream *s,
612697 (void *)bigarray_data_ptr);
613698 print_default = false ;
614699 }
615- } else {
700+ } else if (identifier_str == " _f32" ) {
701+ std::optional<llvm::APInt> apint = ReadAPIntFromMemory (DE, process, value + 8 , 4 );
702+ if (!apint) {
703+ s->Printf (" <could not read float32>@" );
704+ break ;
705+ }
706+ const llvm::fltSemantics &semantics = llvm::APFloat::IEEEsingle ();
707+ PrintAPIntAsFloat (s, *apint, semantics, format_max_padding, " " , " s" );
708+ print_default = false ;
709+ }
710+ else {
616711 // CR mshinwell: check about converting Address.t to (void*)
617712 s->Printf (" <custom|\" %s\" )>@" , identifier_str.c_str ());
618713 }
@@ -987,9 +1082,6 @@ lldb::offset_t lldb_private::DumpDataExtractor(
9871082 if (target_sp)
9881083 format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat ();
9891084
990- // Show full precision when printing float values
991- const unsigned format_precision = 0 ;
992-
9931085 const llvm::fltSemantics &semantics =
9941086 GetFloatSemantics (target_sp, item_byte_size);
9951087
@@ -1001,13 +1093,12 @@ lldb::offset_t lldb_private::DumpDataExtractor(
10011093 std::optional<llvm::APInt> apint =
10021094 GetAPInt (DE, &offset, semantics_byte_size);
10031095 if (apint) {
1004- llvm::APFloat apfloat (semantics, *apint);
1005- llvm::SmallVector<char , 256 > sv;
1006- if (format_max_padding)
1007- apfloat.toString (sv, format_precision, *format_max_padding);
1008- else
1009- apfloat.toString (sv, format_precision);
1010- s->AsRawOstream () << sv;
1096+ std::string suffix = " " ;
1097+ if (semantics_byte_size == 4 ){
1098+ suffix = " s" ;
1099+ }
1100+ PrintAPIntAsFloat (s, *apint, semantics,
1101+ format_max_padding, " #" , suffix);
10111102 } else {
10121103 s->Format (" error: unsupported byte size ({0}) for float format" ,
10131104 item_byte_size);
0 commit comments