[llvm][AArch64] Add missing FPCR, H and B registers to Codeview mapping

Fixes https://github.com/llvm/llvm-project/issues/56484

H registers are 16 bit views of AArch64's Neon registers and
B are the 8 bit views.

msvc does not support 16 bit float (some mention in DirectX but I
couldn't find a way to get to it) so for lack of a better reference
I'm using:
85c9b41b33/server/references/dia/include/cvconst.h
(the other microsoft-pdb repo is no longer up to date)

Luckily clang does support fp16 so a test is added for that.

There is no 8 bit float type so I had to get creative with the
test case. We're not testing for correct debug info here just
that we can select the B register and not crash in the process.

For FPCR it's never going to be passed as an argument so I've
not added a test for it. It is included to keep our list looking
the same as the reference.

Reviewed By: majnemer

Differential Revision: https://reviews.llvm.org/D129774
This commit is contained in:
David Spickett 2022-07-14 09:36:03 +00:00
parent e717f91c96
commit 5d14873249
4 changed files with 281 additions and 2 deletions

View File

@ -523,10 +523,12 @@ CV_REGISTER(ARM_NQ15, 415)
#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64)
// arm64intr.h from MSVC defines ARM64_FPSR, which conflicts with
// arm64intr.h from MSVC defines ARM64_FPSR and ARM64_FPCR, which conflicts with
// these declarations.
#pragma push_macro("ARM64_FPSR")
#pragma push_macro("ARM64_FPCR")
#undef ARM64_FPSR
#undef ARM64_FPCR
// ARM64 registers
@ -715,7 +717,79 @@ CV_REGISTER(ARM64_Q31, 211)
// Floating point status register
CV_REGISTER(ARM64_FPSR, 220)
CV_REGISTER(ARM64_FPCR, 221)
// 8 bit floating point registers
CV_REGISTER(ARM64_B0, 230)
CV_REGISTER(ARM64_B1, 231)
CV_REGISTER(ARM64_B2, 232)
CV_REGISTER(ARM64_B3, 233)
CV_REGISTER(ARM64_B4, 234)
CV_REGISTER(ARM64_B5, 235)
CV_REGISTER(ARM64_B6, 236)
CV_REGISTER(ARM64_B7, 237)
CV_REGISTER(ARM64_B8, 238)
CV_REGISTER(ARM64_B9, 239)
CV_REGISTER(ARM64_B10, 240)
CV_REGISTER(ARM64_B11, 241)
CV_REGISTER(ARM64_B12, 242)
CV_REGISTER(ARM64_B13, 243)
CV_REGISTER(ARM64_B14, 244)
CV_REGISTER(ARM64_B15, 245)
CV_REGISTER(ARM64_B16, 246)
CV_REGISTER(ARM64_B17, 247)
CV_REGISTER(ARM64_B18, 248)
CV_REGISTER(ARM64_B19, 249)
CV_REGISTER(ARM64_B20, 250)
CV_REGISTER(ARM64_B21, 251)
CV_REGISTER(ARM64_B22, 252)
CV_REGISTER(ARM64_B23, 253)
CV_REGISTER(ARM64_B24, 254)
CV_REGISTER(ARM64_B25, 255)
CV_REGISTER(ARM64_B26, 256)
CV_REGISTER(ARM64_B27, 257)
CV_REGISTER(ARM64_B28, 258)
CV_REGISTER(ARM64_B29, 259)
CV_REGISTER(ARM64_B30, 260)
CV_REGISTER(ARM64_B31, 261)
// 16 bit floating point registers
CV_REGISTER(ARM64_H0, 270)
CV_REGISTER(ARM64_H1, 271)
CV_REGISTER(ARM64_H2, 272)
CV_REGISTER(ARM64_H3, 273)
CV_REGISTER(ARM64_H4, 274)
CV_REGISTER(ARM64_H5, 275)
CV_REGISTER(ARM64_H6, 276)
CV_REGISTER(ARM64_H7, 277)
CV_REGISTER(ARM64_H8, 278)
CV_REGISTER(ARM64_H9, 279)
CV_REGISTER(ARM64_H10, 280)
CV_REGISTER(ARM64_H11, 281)
CV_REGISTER(ARM64_H12, 282)
CV_REGISTER(ARM64_H13, 283)
CV_REGISTER(ARM64_H14, 284)
CV_REGISTER(ARM64_H15, 285)
CV_REGISTER(ARM64_H16, 286)
CV_REGISTER(ARM64_H17, 287)
CV_REGISTER(ARM64_H18, 288)
CV_REGISTER(ARM64_H19, 289)
CV_REGISTER(ARM64_H20, 290)
CV_REGISTER(ARM64_H21, 291)
CV_REGISTER(ARM64_H22, 292)
CV_REGISTER(ARM64_H23, 293)
CV_REGISTER(ARM64_H24, 294)
CV_REGISTER(ARM64_H25, 295)
CV_REGISTER(ARM64_H26, 296)
CV_REGISTER(ARM64_H27, 297)
CV_REGISTER(ARM64_H28, 298)
CV_REGISTER(ARM64_H29, 299)
CV_REGISTER(ARM64_H30, 300)
CV_REGISTER(ARM64_H31, 301)
#pragma pop_macro("ARM64_FPSR")
#pragma pop_macro("ARM64_FPCR")
#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64)

View File

@ -231,7 +231,70 @@ void AArch64_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {
{codeview::RegisterId::ARM64_Q29, AArch64::Q29},
{codeview::RegisterId::ARM64_Q30, AArch64::Q30},
{codeview::RegisterId::ARM64_Q31, AArch64::Q31},
{codeview::RegisterId::ARM64_B0, AArch64::B0},
{codeview::RegisterId::ARM64_B1, AArch64::B1},
{codeview::RegisterId::ARM64_B2, AArch64::B2},
{codeview::RegisterId::ARM64_B3, AArch64::B3},
{codeview::RegisterId::ARM64_B4, AArch64::B4},
{codeview::RegisterId::ARM64_B5, AArch64::B5},
{codeview::RegisterId::ARM64_B6, AArch64::B6},
{codeview::RegisterId::ARM64_B7, AArch64::B7},
{codeview::RegisterId::ARM64_B8, AArch64::B8},
{codeview::RegisterId::ARM64_B9, AArch64::B9},
{codeview::RegisterId::ARM64_B10, AArch64::B10},
{codeview::RegisterId::ARM64_B11, AArch64::B11},
{codeview::RegisterId::ARM64_B12, AArch64::B12},
{codeview::RegisterId::ARM64_B13, AArch64::B13},
{codeview::RegisterId::ARM64_B14, AArch64::B14},
{codeview::RegisterId::ARM64_B15, AArch64::B15},
{codeview::RegisterId::ARM64_B16, AArch64::B16},
{codeview::RegisterId::ARM64_B17, AArch64::B17},
{codeview::RegisterId::ARM64_B18, AArch64::B18},
{codeview::RegisterId::ARM64_B19, AArch64::B19},
{codeview::RegisterId::ARM64_B20, AArch64::B20},
{codeview::RegisterId::ARM64_B21, AArch64::B21},
{codeview::RegisterId::ARM64_B22, AArch64::B22},
{codeview::RegisterId::ARM64_B23, AArch64::B23},
{codeview::RegisterId::ARM64_B24, AArch64::B24},
{codeview::RegisterId::ARM64_B25, AArch64::B25},
{codeview::RegisterId::ARM64_B26, AArch64::B26},
{codeview::RegisterId::ARM64_B27, AArch64::B27},
{codeview::RegisterId::ARM64_B28, AArch64::B28},
{codeview::RegisterId::ARM64_B29, AArch64::B29},
{codeview::RegisterId::ARM64_B30, AArch64::B30},
{codeview::RegisterId::ARM64_B31, AArch64::B31},
{codeview::RegisterId::ARM64_H0, AArch64::H0},
{codeview::RegisterId::ARM64_H1, AArch64::H1},
{codeview::RegisterId::ARM64_H2, AArch64::H2},
{codeview::RegisterId::ARM64_H3, AArch64::H3},
{codeview::RegisterId::ARM64_H4, AArch64::H4},
{codeview::RegisterId::ARM64_H5, AArch64::H5},
{codeview::RegisterId::ARM64_H6, AArch64::H6},
{codeview::RegisterId::ARM64_H7, AArch64::H7},
{codeview::RegisterId::ARM64_H8, AArch64::H8},
{codeview::RegisterId::ARM64_H9, AArch64::H9},
{codeview::RegisterId::ARM64_H10, AArch64::H10},
{codeview::RegisterId::ARM64_H11, AArch64::H11},
{codeview::RegisterId::ARM64_H12, AArch64::H12},
{codeview::RegisterId::ARM64_H13, AArch64::H13},
{codeview::RegisterId::ARM64_H14, AArch64::H14},
{codeview::RegisterId::ARM64_H15, AArch64::H15},
{codeview::RegisterId::ARM64_H16, AArch64::H16},
{codeview::RegisterId::ARM64_H17, AArch64::H17},
{codeview::RegisterId::ARM64_H18, AArch64::H18},
{codeview::RegisterId::ARM64_H19, AArch64::H19},
{codeview::RegisterId::ARM64_H20, AArch64::H20},
{codeview::RegisterId::ARM64_H21, AArch64::H21},
{codeview::RegisterId::ARM64_H22, AArch64::H22},
{codeview::RegisterId::ARM64_H23, AArch64::H23},
{codeview::RegisterId::ARM64_H24, AArch64::H24},
{codeview::RegisterId::ARM64_H25, AArch64::H25},
{codeview::RegisterId::ARM64_H26, AArch64::H26},
{codeview::RegisterId::ARM64_H27, AArch64::H27},
{codeview::RegisterId::ARM64_H28, AArch64::H28},
{codeview::RegisterId::ARM64_H29, AArch64::H29},
{codeview::RegisterId::ARM64_H30, AArch64::H30},
{codeview::RegisterId::ARM64_H31, AArch64::H31},
};
for (const auto &I : RegMap)
MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));

View File

@ -0,0 +1,72 @@
# This test checks that we have a mapping between the B registers and their Codeview numbers.
# There is no 8 bit float type so this is a modified version of codeview-h-register.mir to
# have a B register in the location info but not the instructions. Which is incorrect
# but in ways this test does not care about.
#
# RUN: llc %s -mtriple=arm64-windows -filetype=obj -o %t --start-after=unpack-mi-bundles
# RUN: llvm-readobj --codeview %t | FileCheck %s --check-prefix=OBJ
#
# OBJ: LocalSym {
# OBJ: Kind: S_LOCAL (0x113E)
# OBJ: Type: __half (0x46)
# OBJ: Flags [ (0x1)
# OBJ: IsParameter (0x1)
# OBJ: ]
# OBJ: VarName: x
# OBJ: }
# OBJ: DefRangeRegisterSym {
# OBJ: Kind: S_DEFRANGE_REGISTER (0x1141)
# OBJ: Register: ARM64_B0 (0xE6)
# OBJ: MayHaveNoName: 0
# OBJ: LocalVariableAddrRange {
# OBJ: OffsetStart: .text+0x0
# OBJ: ISectStart: 0x0
# OBJ: Range: 0x4
# OBJ: }
# OBJ: }
#
--- |
define internal fastcc i1 @test.fn(half %0) !dbg !4 {
Entry:
call void @llvm.dbg.value(metadata half %0, metadata !11, metadata !DIExpression()), !dbg !13
%1 = fcmp une half 0xH0000, %0, !dbg !14
ret i1 %1
}
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata) #0
attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"CodeView", i32 1}
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
!3 = !DIFile(filename: "test", directory: ".")
!4 = distinct !DISubprogram(name: "fn", linkageName: "test.fn", scope: !5, file: !5, line: 32, type: !6, scopeLine: 32, flags: DIFlagStaticMember, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !10)
!5 = !DIFile(filename: "test.o", directory: ".")
!6 = !DISubroutineType(types: !7)
!7 = !{!8, !9}
!8 = !DIBasicType(name: "bool", size: 1, encoding: DW_ATE_boolean)
!9 = !DIBasicType(name: "f16", size: 16, encoding: DW_ATE_float)
!10 = !{!11}
!11 = !DILocalVariable(name: "x", arg: 1, scope: !12, file: !5, line: 32, type: !9)
!12 = distinct !DILexicalBlock(scope: !4, file: !5, line: 32, column: 1)
!13 = !DILocation(line: 32, column: 31, scope: !12)
!14 = !DILocation(line: 33, column: 5, scope: !15)
!15 = distinct !DILexicalBlock(scope: !12, file: !5)
...
---
name: test.fn
body: |
bb.0:
liveins: $b0
DBG_VALUE $b0, $noreg, !11, !DIExpression(), debug-location !13
renamable $s0 = nofpexcept FCVTSHr killed renamable $h0, debug-location !14
DBG_VALUE $b0, $noreg, !11, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !13
nofpexcept FCMPSri killed renamable $s0, implicit-def $nzcv, debug-location !14
renamable $w0 = CSINCWr $wzr, $wzr, 0, implicit killed $nzcv, debug-location !14
RET undef $lr, implicit killed $w0
...

View File

@ -0,0 +1,70 @@
# This test checks that we have a mapping between the H register chosen by codegen
# and the codeview number for that register.
#
# RUN: llc %s -mtriple=arm64-windows -filetype=obj -o %t --start-after=unpack-mi-bundles
# RUN: llvm-readobj --codeview %t | FileCheck %s --check-prefix=OBJ
#
# OBJ: LocalSym {
# OBJ: Kind: S_LOCAL (0x113E)
# OBJ: Type: __half (0x46)
# OBJ: Flags [ (0x1)
# OBJ: IsParameter (0x1)
# OBJ: ]
# OBJ: VarName: x
# OBJ: }
# OBJ: DefRangeRegisterSym {
# OBJ: Kind: S_DEFRANGE_REGISTER (0x1141)
# OBJ: Register: ARM64_H0 (0x10E)
# OBJ: MayHaveNoName: 0
# OBJ: LocalVariableAddrRange {
# OBJ: OffsetStart: .text+0x0
# OBJ: ISectStart: 0x0
# OBJ: Range: 0x4
# OBJ: }
# OBJ: }
#
--- |
define internal fastcc i1 @test.fn(half %0) !dbg !4 {
Entry:
call void @llvm.dbg.value(metadata half %0, metadata !11, metadata !DIExpression()), !dbg !13
%1 = fcmp une half 0xH0000, %0, !dbg !14
ret i1 %1
}
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata) #0
attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"CodeView", i32 1}
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
!3 = !DIFile(filename: "test", directory: ".")
!4 = distinct !DISubprogram(name: "fn", linkageName: "test.fn", scope: !5, file: !5, line: 32, type: !6, scopeLine: 32, flags: DIFlagStaticMember, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !10)
!5 = !DIFile(filename: "test.o", directory: ".")
!6 = !DISubroutineType(types: !7)
!7 = !{!8, !9}
!8 = !DIBasicType(name: "bool", size: 1, encoding: DW_ATE_boolean)
!9 = !DIBasicType(name: "f16", size: 16, encoding: DW_ATE_float)
!10 = !{!11}
!11 = !DILocalVariable(name: "x", arg: 1, scope: !12, file: !5, line: 32, type: !9)
!12 = distinct !DILexicalBlock(scope: !4, file: !5, line: 32, column: 1)
!13 = !DILocation(line: 32, column: 31, scope: !12)
!14 = !DILocation(line: 33, column: 5, scope: !15)
!15 = distinct !DILexicalBlock(scope: !12, file: !5)
...
---
name: test.fn
body: |
bb.0:
liveins: $h0
DBG_VALUE $h0, $noreg, !11, !DIExpression(), debug-location !13
renamable $s0 = nofpexcept FCVTSHr killed renamable $h0, debug-location !14
DBG_VALUE $h0, $noreg, !11, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !13
nofpexcept FCMPSri killed renamable $s0, implicit-def $nzcv, debug-location !14
renamable $w0 = CSINCWr $wzr, $wzr, 0, implicit killed $nzcv, debug-location !14
RET undef $lr, implicit killed $w0
...