Skip to content

Commit b058de9

Browse files
committed
Add Natvis visualiser and debuginfo tests for f16
1 parent d7c5937 commit b058de9

11 files changed

+218
-36
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+40-3
Original file line numberDiff line numberDiff line change
@@ -705,17 +705,51 @@ impl MsvcBasicName for ty::UintTy {
705705

706706
impl MsvcBasicName for ty::FloatTy {
707707
fn msvc_basic_name(self) -> &'static str {
708-
// FIXME: f16 and f128 have no MSVC representation. We could improve the debuginfo.
709-
// See: <https://github.com/rust-lang/rust/pull/114607/files#r1454683264>
708+
// FIXME(f16_f128): `f16` and `f128` have no MSVC representation. We could improve the
709+
// debuginfo. See: <https://github.com/rust-lang/rust/issues/121837>
710710
match self {
711-
ty::FloatTy::F16 => "half",
711+
ty::FloatTy::F16 => {
712+
bug!("`f16` should have been handled in `build_basic_type_di_node`")
713+
}
712714
ty::FloatTy::F32 => "float",
713715
ty::FloatTy::F64 => "double",
714716
ty::FloatTy::F128 => "fp128",
715717
}
716718
}
717719
}
718720

721+
fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreationResult<'ll> {
722+
// MSVC has no native support for `f16`. Instead, emit `struct f16 { bits: u16 }` to allow the
723+
// `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`.
724+
let float_ty = cx.tcx.types.f16;
725+
let bits_ty = cx.tcx.types.u16;
726+
type_map::build_type_with_children(
727+
cx,
728+
type_map::stub(
729+
cx,
730+
Stub::Struct,
731+
UniqueTypeId::for_ty(cx.tcx, float_ty),
732+
"f16",
733+
cx.size_and_align_of(float_ty),
734+
NO_SCOPE_METADATA,
735+
DIFlags::FlagZero,
736+
),
737+
// Fields:
738+
|cx, float_di_node| {
739+
smallvec![build_field_di_node(
740+
cx,
741+
float_di_node,
742+
"bits",
743+
cx.size_and_align_of(bits_ty),
744+
Size::ZERO,
745+
DIFlags::FlagZero,
746+
type_di_node(cx, bits_ty),
747+
)]
748+
},
749+
NO_GENERICS,
750+
)
751+
}
752+
719753
fn build_basic_type_di_node<'ll, 'tcx>(
720754
cx: &CodegenCx<'ll, 'tcx>,
721755
t: Ty<'tcx>,
@@ -739,6 +773,9 @@ fn build_basic_type_di_node<'ll, 'tcx>(
739773
ty::Char => ("char", DW_ATE_UTF),
740774
ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
741775
ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
776+
ty::Float(ty::FloatTy::F16) if cpp_like_debuginfo => {
777+
return build_cpp_f16_di_node(cx);
778+
}
742779
ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
743780
ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
744781
ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),

src/etc/natvis/intrinsic.natvis

+26
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,32 @@
3333
</ArrayItems>
3434
</Expand>
3535
</Type>
36+
<Type Name="f16">
37+
<Intrinsic Name="sign_mask" Expression="(unsigned __int16) 0x8000" />
38+
<Intrinsic Name="exponent_mask" Expression="(unsigned __int16) 0x7c00" />
39+
<Intrinsic Name="significand_mask" Expression="(unsigned __int16) 0x03ff" />
40+
<Intrinsic Name="sign_bit" Expression="(unsigned __int16) (bits &amp; sign_mask())" />
41+
<Intrinsic Name="exponent_bits" Expression="(unsigned __int16) (bits &amp; exponent_mask())" />
42+
<Intrinsic Name="significand_bits" Expression="(unsigned __int16) (bits &amp; significand_mask())" />
43+
44+
<Intrinsic Name="if_set" Expression="(bits &amp; mask) != 0 ? value : 1.0">
45+
<Parameter Name="mask" Type="unsigned __int16" />
46+
<Parameter Name="value" Type="float" />
47+
</Intrinsic>
48+
<!-- Calculates 2**exp without needing a pow function. Each float in if_set() is the square of the previous float. 32768 == 2.pow(bias), bias == 15 -->
49+
<Intrinsic Name="two_pow_exponent" Expression="if_set(0x0400, 2.0) * if_set(0x0800, 4.0) * if_set(0x1000, 16.0) * if_set(0x2000, 256.0) * if_set(0x4000, 65536.0) / 32768.0" />
50+
<!-- Calculates 0.significand, without any implicit bit. 1024 == 2.pow(explicit significand width), explicit significand width == 10 -->
51+
<Intrinsic Name="raw_significand" Expression="((float) significand_bits()) / 1024.0" />
52+
<Intrinsic Name="sign" Expression="sign_bit() == 0 ? 1.0 : -1.0" />
53+
54+
<DisplayString Condition="bits == 0x7c00">inf</DisplayString>
55+
<DisplayString Condition="bits == 0xfc00">-inf</DisplayString>
56+
<DisplayString Condition="exponent_bits() == exponent_mask()">NaN</DisplayString>
57+
<!-- Subnormal or zero (16384 == 2.pow(bias - 1), bias - 1 == 14) -->
58+
<DisplayString Condition="exponent_bits() == 0">{(float) (sign() * raw_significand() / 16384.0)}</DisplayString>
59+
<!-- Normal -->
60+
<DisplayString>{(float) (sign() * (raw_significand() + 1.0) * two_pow_exponent())}</DisplayString>
61+
</Type>
3662
<Type Name="tuple$&lt;&gt;">
3763
<DisplayString>()</DisplayString>
3864
</Type>

tests/debuginfo/basic-types-globals-metadata.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
// gdbg-command:whatis 'basic_types_globals_metadata::U64'
4040
// gdbr-command:whatis basic_types_globals_metadata::U64
4141
// gdb-check:type = u64
42+
// gdbg-command:whatis 'basic_types_globals_metadata::F16'
43+
// gdbr-command:whatis basic_types_globals_metadata::F16
44+
// gdb-check:type = f16
4245
// gdbg-command:whatis 'basic_types_globals_metadata::F32'
4346
// gdbr-command:whatis basic_types_globals_metadata::F32
4447
// gdb-check:type = f32
@@ -51,6 +54,7 @@
5154
#![allow(dead_code)]
5255
#![feature(omit_gdb_pretty_printer_section)]
5356
#![omit_gdb_pretty_printer_section]
57+
#![feature(f16)]
5458

5559
// N.B. These are `mut` only so they don't constant fold away.
5660
static mut B: bool = false;
@@ -65,13 +69,14 @@ static mut U8: u8 = 100;
6569
static mut U16: u16 = 16;
6670
static mut U32: u32 = 32;
6771
static mut U64: u64 = 64;
72+
static mut F16: f16 = 1.5;
6873
static mut F32: f32 = 2.5;
6974
static mut F64: f64 = 3.5;
7075

7176
fn main() {
7277
_zzz(); // #break
7378

74-
let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) };
79+
let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F16, F32, F64) };
7580
}
7681

7782
fn _zzz() {()}

tests/debuginfo/basic-types-globals.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,21 @@
4949
// gdbg-command:print 'basic_types_globals::U64'
5050
// gdbr-command:print U64
5151
// gdb-check:$12 = 64
52+
// gdbg-command:print 'basic_types_globals::F16'
53+
// gdbr-command:print F16
54+
// gdb-check:$13 = 1.5
5255
// gdbg-command:print 'basic_types_globals::F32'
5356
// gdbr-command:print F32
54-
// gdb-check:$13 = 2.5
57+
// gdb-check:$14 = 2.5
5558
// gdbg-command:print 'basic_types_globals::F64'
5659
// gdbr-command:print F64
57-
// gdb-check:$14 = 3.5
60+
// gdb-check:$15 = 3.5
5861
// gdb-command:continue
5962

6063
#![allow(unused_variables)]
6164
#![feature(omit_gdb_pretty_printer_section)]
6265
#![omit_gdb_pretty_printer_section]
66+
#![feature(f16)]
6367

6468
// N.B. These are `mut` only so they don't constant fold away.
6569
static mut B: bool = false;
@@ -74,13 +78,14 @@ static mut U8: u8 = 100;
7478
static mut U16: u16 = 16;
7579
static mut U32: u32 = 32;
7680
static mut U64: u64 = 64;
81+
static mut F16: f16 = 1.5;
7782
static mut F32: f32 = 2.5;
7883
static mut F64: f64 = 3.5;
7984

8085
fn main() {
8186
_zzz(); // #break
8287

83-
let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) };
88+
let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F16, F32, F64) };
8489
}
8590

8691
fn _zzz() {()}

tests/debuginfo/basic-types-metadata.rs

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
// gdb-check:type = u32
3030
// gdb-command:whatis u64
3131
// gdb-check:type = u64
32+
// gdb-command:whatis f16
33+
// gdb-check:type = f16
3234
// gdb-command:whatis f32
3335
// gdb-check:type = f32
3436
// gdb-command:whatis f64
@@ -66,6 +68,7 @@
6668
#![allow(unused_variables)]
6769
#![feature(omit_gdb_pretty_printer_section)]
6870
#![omit_gdb_pretty_printer_section]
71+
#![feature(f16)]
6972

7073
fn main() {
7174
let unit: () = ();
@@ -81,6 +84,7 @@ fn main() {
8184
let u16: u16 = 16;
8285
let u32: u32 = 32;
8386
let u64: u64 = 64;
87+
let f16: f16 = 1.5;
8488
let f32: f32 = 2.5;
8589
let f64: f64 = 3.5;
8690
let fnptr : fn() = _zzz;

tests/debuginfo/basic-types-mut-globals.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// its numerical value.
66

77
//@ min-lldb-version: 310
8-
//@ ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
98

109
//@ compile-flags:-g
1110

@@ -49,62 +48,69 @@
4948
// gdbg-command:print 'basic_types_mut_globals::U64'
5049
// gdbr-command:print U64
5150
// gdb-check:$12 = 64
51+
// gdbg-command:print 'basic_types_mut_globals::F16'
52+
// gdbr-command:print F16
53+
// gdb-check:$13 = 1.5
5254
// gdbg-command:print 'basic_types_mut_globals::F32'
5355
// gdbr-command:print F32
54-
// gdb-check:$13 = 2.5
56+
// gdb-check:$14 = 2.5
5557
// gdbg-command:print 'basic_types_mut_globals::F64'
5658
// gdbr-command:print F64
57-
// gdb-check:$14 = 3.5
59+
// gdb-check:$15 = 3.5
5860
// gdb-command:continue
5961

6062
// Check new values
6163
// gdbg-command:print 'basic_types_mut_globals'::B
6264
// gdbr-command:print B
63-
// gdb-check:$15 = true
65+
// gdb-check:$16 = true
6466
// gdbg-command:print 'basic_types_mut_globals'::I
6567
// gdbr-command:print I
66-
// gdb-check:$16 = 2
68+
// gdb-check:$17 = 2
6769
// gdbg-command:print/d 'basic_types_mut_globals'::C
6870
// gdbr-command:print C
69-
// gdbg-check:$17 = 102
70-
// gdbr-check:$17 = 102 'f'
71+
// gdbg-check:$18 = 102
72+
// gdbr-check:$18 = 102 'f'
7173
// gdbg-command:print/d 'basic_types_mut_globals'::I8
7274
// gdbr-command:print/d I8
73-
// gdb-check:$18 = 78
75+
// gdb-check:$19 = 78
7476
// gdbg-command:print 'basic_types_mut_globals'::I16
7577
// gdbr-command:print I16
76-
// gdb-check:$19 = -26
78+
// gdb-check:$20 = -26
7779
// gdbg-command:print 'basic_types_mut_globals'::I32
7880
// gdbr-command:print I32
79-
// gdb-check:$20 = -12
81+
// gdb-check:$21 = -12
8082
// gdbg-command:print 'basic_types_mut_globals'::I64
8183
// gdbr-command:print I64
82-
// gdb-check:$21 = -54
84+
// gdb-check:$22 = -54
8385
// gdbg-command:print 'basic_types_mut_globals'::U
8486
// gdbr-command:print U
85-
// gdb-check:$22 = 5
87+
// gdb-check:$23 = 5
8688
// gdbg-command:print/d 'basic_types_mut_globals'::U8
8789
// gdbr-command:print/d U8
88-
// gdb-check:$23 = 20
90+
// gdb-check:$24 = 20
8991
// gdbg-command:print 'basic_types_mut_globals'::U16
9092
// gdbr-command:print U16
91-
// gdb-check:$24 = 32
93+
// gdb-check:$25 = 32
9294
// gdbg-command:print 'basic_types_mut_globals'::U32
9395
// gdbr-command:print U32
94-
// gdb-check:$25 = 16
96+
// gdb-check:$26 = 16
9597
// gdbg-command:print 'basic_types_mut_globals'::U64
9698
// gdbr-command:print U64
97-
// gdb-check:$26 = 128
99+
// gdb-check:$27 = 128
100+
// gdbg-command:print 'basic_types_mut_globals'::F16
101+
// gdbr-command:print F16
102+
// gdb-check:$28 = 2.25
98103
// gdbg-command:print 'basic_types_mut_globals'::F32
99104
// gdbr-command:print F32
100-
// gdb-check:$27 = 5.75
105+
// gdb-check:$29 = 5.75
101106
// gdbg-command:print 'basic_types_mut_globals'::F64
102107
// gdbr-command:print F64
103-
// gdb-check:$28 = 9.25
108+
// gdb-check:$30 = 9.25
104109

105110
#![allow(unused_variables)]
106111
#![feature(omit_gdb_pretty_printer_section)]
107112
#![omit_gdb_pretty_printer_section]
113+
#![feature(f16)]
108114

109115
static mut B: bool = false;
110116
static mut I: isize = -1;
@@ -118,6 +124,7 @@ static mut U8: u8 = 100;
118124
static mut U16: u16 = 16;
119125
static mut U32: u32 = 32;
120126
static mut U64: u64 = 64;
127+
static mut F16: f16 = 1.5;
121128
static mut F32: f32 = 2.5;
122129
static mut F64: f64 = 3.5;
123130

@@ -137,6 +144,7 @@ fn main() {
137144
U16 = 32;
138145
U32 = 16;
139146
U64 = 128;
147+
F16 = 2.25;
140148
F32 = 5.75;
141149
F64 = 9.25;
142150
}

tests/debuginfo/basic-types.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@
3939
// gdb-check:$11 = 32
4040
// gdb-command:print u64
4141
// gdb-check:$12 = 64
42+
// gdb-command:print f16
43+
// gdb-check:$13 = 1.5
4244
// gdb-command:print f32
43-
// gdb-check:$13 = 2.5
45+
// gdb-check:$14 = 2.5
4446
// gdb-command:print f64
45-
// gdb-check:$14 = 3.5
47+
// gdb-check:$15 = 3.5
4648
// gdb-command:print s
47-
// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
48-
// gdbr-check:$15 = "Hello, World!"
49+
// gdbg-check:$16 = {data_ptr = [...] "Hello, World!", length = 13}
50+
// gdbr-check:$16 = "Hello, World!"
4951

5052
// === LLDB TESTS ==================================================================================
5153

@@ -122,6 +124,8 @@
122124
// cdb-check:u32 : 0x20 [Type: unsigned int]
123125
// cdb-command:dx u64
124126
// cdb-check:u64 : 0x40 [Type: unsigned __int64]
127+
// cdb-command:dx f16
128+
// cdb-check:f16 : 1.500000 [Type: f16]
125129
// cdb-command:dx f32
126130
// cdb-check:f32 : 2.500000 [Type: float]
127131
// cdb-command:dx f64
@@ -134,6 +138,7 @@
134138
#![allow(unused_variables)]
135139
#![feature(omit_gdb_pretty_printer_section)]
136140
#![omit_gdb_pretty_printer_section]
141+
#![feature(f16)]
137142

138143
fn main() {
139144
let b: bool = false;
@@ -148,6 +153,7 @@ fn main() {
148153
let u16: u16 = 16;
149154
let u32: u32 = 32;
150155
let u64: u64 = 64;
156+
let f16: f16 = 1.5;
151157
let f32: f32 = 2.5;
152158
let f64: f64 = 3.5;
153159
let s: &str = "Hello, World!";

tests/debuginfo/borrowed-basic.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@
4242
// gdb-command:print *u64_ref
4343
// gdb-check:$12 = 64
4444

45+
// gdb-command:print *f16_ref
46+
// gdb-check:$13 = 1.5
47+
4548
// gdb-command:print *f32_ref
46-
// gdb-check:$13 = 2.5
49+
// gdb-check:$14 = 2.5
4750

4851
// gdb-command:print *f64_ref
49-
// gdb-check:$14 = 3.5
52+
// gdb-check:$15 = 3.5
5053

5154

5255
// === LLDB TESTS ==================================================================================
@@ -100,6 +103,10 @@
100103
// lldbg-check:[...] 64
101104
// lldbr-check:(u64) *u64_ref = 64
102105

106+
// lldb-command:v *f16_ref
107+
// lldbg-check:[...] 1.5
108+
// lldbr-check:(f16) *f16_ref = 1.5
109+
103110
// lldb-command:v *f32_ref
104111
// lldbg-check:[...] 2.5
105112
// lldbr-check:(f32) *f32_ref = 2.5
@@ -111,6 +118,7 @@
111118
#![allow(unused_variables)]
112119
#![feature(omit_gdb_pretty_printer_section)]
113120
#![omit_gdb_pretty_printer_section]
121+
#![feature(f16)]
114122

115123
fn main() {
116124
let bool_val: bool = true;
@@ -149,6 +157,9 @@ fn main() {
149157
let u64_val: u64 = 64;
150158
let u64_ref: &u64 = &u64_val;
151159

160+
let f16_val: f16 = 1.5;
161+
let f16_ref: &f16 = &f16_val;
162+
152163
let f32_val: f32 = 2.5;
153164
let f32_ref: &f32 = &f32_val;
154165

0 commit comments

Comments
 (0)