[llvm] [MIR] Replace bespoke DIExpression parser (PR #96827)
Scott Linder via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 26 15:25:45 PDT 2024
https://github.com/slinder1 created https://github.com/llvm/llvm-project/pull/96827
Resolve FIXME by using the LLParser implementation of parseDIExpression from the MIParser.
>From c6cae2d66ef9cc999939659186cda8d2c82c13bb Mon Sep 17 00:00:00 2001
From: Scott Linder <Scott.Linder at amd.com>
Date: Wed, 26 Jun 2024 21:11:00 +0000
Subject: [PATCH 1/2] [NFC] Add DIExpression MIParser tests
Prepare for patch to replace MIParser implementation of DIExpression
parser with the LLParser version.
---
.../CodeGen/MIR/Generic/diexpression-err.mir | 152 ++++++++++++++++
.../test/CodeGen/MIR/Generic/diexpression.mir | 167 ++++++++++++++++++
2 files changed, 319 insertions(+)
create mode 100644 llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
create mode 100644 llvm/test/CodeGen/MIR/Generic/diexpression.mir
diff --git a/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir b/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
new file mode 100644
index 0000000000000..394c0d5d48eaa
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
@@ -0,0 +1,152 @@
+# RUN: not llc -run-pass none -o - %s 2>&1 | FileCheck %s
+# Note: generated via:
+# printf 'extern long long sink; int func(int arg) { int purelocal = arg * 42; int pinnedlocal = arg * 43; sink = (long long)&pinnedlocal; return purelocal; }' | clang -cc1 -O1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -mllvm -stop-after=x86-isel - -o -
+--- |
+ source_filename = "-"
+ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+ target triple = "x86_64-unknown-linux-gnu"
+
+ @sink = external local_unnamed_addr global i64, align 8
+
+ define dso_local i32 @func(i32 noundef %arg) local_unnamed_addr #0 !dbg !8 {
+ entry:
+ %pinnedlocal = alloca i32, align 4, !DIAssignID !16
+ #dbg_assign(i1 undef, !15, !DIExpression(), !16, ptr %pinnedlocal, !DIExpression(), !17)
+ #dbg_value(i32 %arg, !13, !DIExpression(), !17)
+ %mul = mul nsw i32 %arg, 42, !dbg !18
+ #dbg_value(i32 %mul, !14, !DIExpression(), !17)
+ call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %pinnedlocal) #2, !dbg !19
+ %mul1 = mul nsw i32 %arg, 43, !dbg !20
+ store i32 %mul1, ptr %pinnedlocal, align 4, !dbg !21, !tbaa !22, !DIAssignID !26
+ #dbg_assign(i32 %mul1, !15, !DIExpression(), !26, ptr %pinnedlocal, !DIExpression(), !17)
+ %0 = ptrtoint ptr %pinnedlocal to i64, !dbg !27
+ store i64 %0, ptr @sink, align 8, !dbg !28, !tbaa !29
+ call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %pinnedlocal) #2, !dbg !31
+ ret i32 %mul, !dbg !32
+ }
+
+ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+ attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+ attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+ attributes #2 = { nounwind }
+
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!4, !5, !6}
+ !llvm.ident = !{!7}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0git (git at github.com:slinder1/llvm-project.git a32b7199f0c15ea1c6c9490b6166c019c9d4bd2b)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+ !1 = !DIFile(filename: "<stdin>", directory: "/home/slinder1/llvm-project/main")
+ !2 = !{!3}
+ !3 = !DIBasicType(name: "long long", size: 64, encoding: DW_ATE_signed)
+ !4 = !{i32 2, !"Debug Info Version", i32 3}
+ !5 = !{i32 1, !"wchar_size", i32 4}
+ !6 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+ !7 = !{!"clang version 19.0.0git (git at github.com:slinder1/llvm-project.git a32b7199f0c15ea1c6c9490b6166c019c9d4bd2b)"}
+ !8 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !9 = !DISubroutineType(types: !10)
+ !10 = !{!11, !11}
+ !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+ !12 = !{!13, !14, !15}
+ !13 = !DILocalVariable(name: "arg", arg: 1, scope: !8, file: !1, line: 1, type: !11)
+ !14 = !DILocalVariable(name: "purelocal", scope: !8, file: !1, line: 1, type: !11)
+ !15 = !DILocalVariable(name: "pinnedlocal", scope: !8, file: !1, line: 1, type: !11)
+ !16 = distinct !DIAssignID()
+ !17 = !DILocation(line: 0, scope: !8)
+ !18 = !DILocation(line: 1, column: 64, scope: !8)
+ !19 = !DILocation(line: 1, column: 70, scope: !8)
+ !20 = !DILocation(line: 1, column: 92, scope: !8)
+ !21 = !DILocation(line: 1, column: 74, scope: !8)
+ !22 = !{!23, !23, i64 0}
+ !23 = !{!"int", !24, i64 0}
+ !24 = !{!"omnipotent char", !25, i64 0}
+ !25 = !{!"Simple C/C++ TBAA"}
+ !26 = distinct !DIAssignID()
+ !27 = !DILocation(line: 1, column: 105, scope: !8)
+ !28 = !DILocation(line: 1, column: 103, scope: !8)
+ !29 = !{!30, !30, i64 0}
+ !30 = !{!"long long", !24, i64 0}
+ !31 = !DILocation(line: 1, column: 148, scope: !8)
+ !32 = !DILocation(line: 1, column: 130, scope: !8)
+
+...
+---
+name: func
+alignment: 16
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHCatchret: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: true
+failsVerification: false
+tracksDebugUserValues: false
+registers:
+ - { id: 0, class: gr32, preferred-register: '' }
+ - { id: 1, class: gr32, preferred-register: '' }
+ - { id: 2, class: gr64, preferred-register: '' }
+ - { id: 3, class: gr64, preferred-register: '' }
+liveins:
+ - { reg: '$edi', virtual-reg: '%0' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 4
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ functionContext: ''
+ maxCallFrameSize: 4294967295
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ isCalleeSavedInfoValid: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack:
+ - { id: 0, name: pinnedlocal, type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '!15', debug-info-expression: '!DIExpression()',
+ debug-info-location: '!17' }
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants: []
+machineFunctionInfo:
+ amxProgModel: None
+body: |
+ bb.0.entry:
+ liveins: $edi
+
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !17
+ %0:gr32 = COPY $edi
+ %1:gr32 = nsw IMUL32rri %0, 42, implicit-def dead $eflags, debug-instr-number 1, debug-location !18
+ ; CHECK: {{.*}}.mir:[[#@LINE+1]]:38: invalid DWARF op 'W_OP_LLVM_arg'
+ DBG_INSTR_REF !14, !DIExpression(W_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !17
+ LIFETIME_START %stack.0.pinnedlocal, debug-location !19
+ %2:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @sink, $noreg, debug-location !28 :: (load (s64) from got)
+ %3:gr64 = LEA64r %stack.0.pinnedlocal, 1, $noreg, 0, $noreg
+ MOV64mr killed %2, 1, $noreg, 0, $noreg, killed %3, debug-location !28 :: (store (s64) into @sink, !tbaa !29)
+ LIFETIME_END %stack.0.pinnedlocal, debug-location !31
+ $eax = COPY %1, debug-location !32
+ RET 0, $eax, debug-location !32
+
+...
diff --git a/llvm/test/CodeGen/MIR/Generic/diexpression.mir b/llvm/test/CodeGen/MIR/Generic/diexpression.mir
new file mode 100644
index 0000000000000..085c16fd7d6d6
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/diexpression.mir
@@ -0,0 +1,167 @@
+# NOTE: Hand-modified after being autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -run-pass none -o - %s 2>&1 | FileCheck %s
+# Note: generated via:
+# printf 'extern long long sink; int func(int arg) { int purelocal = arg * 42; int pinnedlocal = arg * 43; sink = (long long)&pinnedlocal; return purelocal; }' | clang -cc1 -O1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -mllvm -stop-after=x86-isel - -o -
+--- |
+ source_filename = "-"
+ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+ target triple = "x86_64-unknown-linux-gnu"
+
+ @sink = external local_unnamed_addr global i64, align 8
+
+ define dso_local i32 @func(i32 noundef %arg) local_unnamed_addr #0 !dbg !8 {
+ entry:
+ %pinnedlocal = alloca i32, align 4, !DIAssignID !16
+ #dbg_assign(i1 undef, !15, !DIExpression(), !16, ptr %pinnedlocal, !DIExpression(), !17)
+ #dbg_value(i32 %arg, !13, !DIExpression(), !17)
+ %mul = mul nsw i32 %arg, 42, !dbg !18
+ #dbg_value(i32 %mul, !14, !DIExpression(), !17)
+ call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %pinnedlocal) #2, !dbg !19
+ %mul1 = mul nsw i32 %arg, 43, !dbg !20
+ store i32 %mul1, ptr %pinnedlocal, align 4, !dbg !21, !tbaa !22, !DIAssignID !26
+ #dbg_assign(i32 %mul1, !15, !DIExpression(), !26, ptr %pinnedlocal, !DIExpression(), !17)
+ %0 = ptrtoint ptr %pinnedlocal to i64, !dbg !27
+ store i64 %0, ptr @sink, align 8, !dbg !28, !tbaa !29
+ call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %pinnedlocal) #2, !dbg !31
+ ret i32 %mul, !dbg !32
+ }
+
+ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+ attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+ attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+ attributes #2 = { nounwind }
+
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!4, !5, !6}
+ !llvm.ident = !{!7}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0git (git at github.com:slinder1/llvm-project.git a32b7199f0c15ea1c6c9490b6166c019c9d4bd2b)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+ !1 = !DIFile(filename: "<stdin>", directory: "/home/slinder1/llvm-project/main")
+ !2 = !{!3}
+ !3 = !DIBasicType(name: "long long", size: 64, encoding: DW_ATE_signed)
+ !4 = !{i32 2, !"Debug Info Version", i32 3}
+ !5 = !{i32 1, !"wchar_size", i32 4}
+ !6 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+ !7 = !{!"clang version 19.0.0git (git at github.com:slinder1/llvm-project.git a32b7199f0c15ea1c6c9490b6166c019c9d4bd2b)"}
+ !8 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+ !9 = !DISubroutineType(types: !10)
+ !10 = !{!11, !11}
+ !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+ !12 = !{!13, !14, !15}
+ !13 = !DILocalVariable(name: "arg", arg: 1, scope: !8, file: !1, line: 1, type: !11)
+ !14 = !DILocalVariable(name: "purelocal", scope: !8, file: !1, line: 1, type: !11)
+ !15 = !DILocalVariable(name: "pinnedlocal", scope: !8, file: !1, line: 1, type: !11)
+ !16 = distinct !DIAssignID()
+ !17 = !DILocation(line: 0, scope: !8)
+ !18 = !DILocation(line: 1, column: 64, scope: !8)
+ !19 = !DILocation(line: 1, column: 70, scope: !8)
+ !20 = !DILocation(line: 1, column: 92, scope: !8)
+ !21 = !DILocation(line: 1, column: 74, scope: !8)
+ !22 = !{!23, !23, i64 0}
+ !23 = !{!"int", !24, i64 0}
+ !24 = !{!"omnipotent char", !25, i64 0}
+ !25 = !{!"Simple C/C++ TBAA"}
+ !26 = distinct !DIAssignID()
+ !27 = !DILocation(line: 1, column: 105, scope: !8)
+ !28 = !DILocation(line: 1, column: 103, scope: !8)
+ !29 = !{!30, !30, i64 0}
+ !30 = !{!"long long", !24, i64 0}
+ !31 = !DILocation(line: 1, column: 148, scope: !8)
+ !32 = !DILocation(line: 1, column: 130, scope: !8)
+
+...
+---
+name: func
+alignment: 16
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHCatchret: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: true
+failsVerification: false
+tracksDebugUserValues: false
+registers:
+ - { id: 0, class: gr32, preferred-register: '' }
+ - { id: 1, class: gr32, preferred-register: '' }
+ - { id: 2, class: gr64, preferred-register: '' }
+ - { id: 3, class: gr64, preferred-register: '' }
+liveins:
+ - { reg: '$edi', virtual-reg: '%0' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 4
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ functionContext: ''
+ maxCallFrameSize: 4294967295
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ isCalleeSavedInfoValid: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack:
+ - { id: 0, name: pinnedlocal, type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '!15', debug-info-expression: '!DIExpression()',
+ debug-info-location: '!17' }
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants: []
+machineFunctionInfo:
+ amxProgModel: None
+body: |
+ bb.0.entry:
+ liveins: $edi
+
+ ; CHECK-LABEL: name: func
+ ; CHECK: debug-info-expression: '!DIExpression()',
+ ; CHECK: liveins: $edi
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !17
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+ ; CHECK-NEXT: [[IMUL32rri:%[0-9]+]]:gr32 = nsw IMUL32rri [[COPY]], 42, implicit-def dead $eflags, debug-instr-number 1, debug-location !18
+ ; CHECK-NEXT: DBG_INSTR_REF !14, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !17
+ ; CHECK-NEXT: LIFETIME_START %stack.0.pinnedlocal, debug-location !19
+ ; CHECK-NEXT: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @sink, $noreg, debug-location !28 :: (load (s64) from got)
+ ; CHECK-NEXT: [[LEA64r:%[0-9]+]]:gr64 = LEA64r %stack.0.pinnedlocal, 1, $noreg, 0, $noreg
+ ; CHECK-NEXT: MOV64mr killed [[MOV64rm]], 1, $noreg, 0, $noreg, killed [[LEA64r]], debug-location !28 :: (store (s64) into @sink, !tbaa !29)
+ ; CHECK-NEXT: LIFETIME_END %stack.0.pinnedlocal, debug-location !31
+ ; CHECK-NEXT: $eax = COPY [[IMUL32rri]], debug-location !32
+ ; CHECK-NEXT: RET 0, $eax, debug-location !32
+ DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !17
+ %0:gr32 = COPY $edi
+ %1:gr32 = nsw IMUL32rri %0, 42, implicit-def dead $eflags, debug-instr-number 1, debug-location !18
+ DBG_INSTR_REF !14, !DIExpression(DW_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !17
+ LIFETIME_START %stack.0.pinnedlocal, debug-location !19
+ %2:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @sink, $noreg, debug-location !28 :: (load (s64) from got)
+ %3:gr64 = LEA64r %stack.0.pinnedlocal, 1, $noreg, 0, $noreg
+ MOV64mr killed %2, 1, $noreg, 0, $noreg, killed %3, debug-location !28 :: (store (s64) into @sink, !tbaa !29)
+ LIFETIME_END %stack.0.pinnedlocal, debug-location !31
+ $eax = COPY %1, debug-location !32
+ RET 0, $eax, debug-location !32
+
+...
>From e56ae029391783d2c505d0953b067394918fe787 Mon Sep 17 00:00:00 2001
From: Scott Linder <Scott.Linder at amd.com>
Date: Tue, 25 Jun 2024 17:40:33 +0000
Subject: [PATCH 2/2] [MIR] Replace bespoke DIExpression parser
Resolve FIXME by using the LLParser implementation of parseDIExpression
from the MIParser.
---
llvm/include/llvm/AsmParser/LLParser.h | 3 ++
llvm/include/llvm/AsmParser/Parser.h | 5 ++
llvm/lib/AsmParser/LLParser.cpp | 19 ++++++-
llvm/lib/AsmParser/Parser.cpp | 17 +++++++
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 50 +++----------------
.../CodeGen/MIR/Generic/diexpression-err.mir | 2 +-
llvm/unittests/AsmParser/AsmParserTest.cpp | 46 +++++++++++++++++
7 files changed, 97 insertions(+), 45 deletions(-)
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 2b08fcc7f16a0..1e93fc0f8cc7d 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -201,6 +201,9 @@ namespace llvm {
bool parseTypeAtBeginning(Type *&Ty, unsigned &Read,
const SlotMapping *Slots);
+ bool parseDIExpressionAtBeginning(MDNode *&Result, unsigned &Read,
+ const SlotMapping *Slots);
+
LLVMContext &getContext() { return Context; }
private:
diff --git a/llvm/include/llvm/AsmParser/Parser.h b/llvm/include/llvm/AsmParser/Parser.h
index b3adfd7fd76cf..01193a0240b83 100644
--- a/llvm/include/llvm/AsmParser/Parser.h
+++ b/llvm/include/llvm/AsmParser/Parser.h
@@ -21,6 +21,7 @@
namespace llvm {
class Constant;
+class DIExpression;
class LLVMContext;
class MemoryBufferRef;
class Module;
@@ -202,6 +203,10 @@ Type *parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
Type *parseTypeAtBeginning(StringRef Asm, unsigned &Read, SMDiagnostic &Err,
const Module &M, const SlotMapping *Slots = nullptr);
+DIExpression *parseDIExpressionAtBeginning(StringRef Asm, unsigned &Read,
+ SMDiagnostic &Err, const Module &M,
+ const SlotMapping *Slots);
+
} // End llvm namespace
#endif
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 21d386097fc63..7486afc05a3c0 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -124,6 +124,21 @@ bool LLParser::parseTypeAtBeginning(Type *&Ty, unsigned &Read,
return false;
}
+bool LLParser::parseDIExpressionAtBeginning(MDNode *&Result, unsigned &Read,
+ const SlotMapping *Slots) {
+ restoreParsingState(Slots);
+ Lex.Lex();
+
+ Read = 0;
+ SMLoc Start = Lex.getLoc();
+ Result = nullptr;
+ bool Status = parseDIExpression(Result, /*IsDistinct=*/false);
+ SMLoc End = Lex.getLoc();
+ Read = End.getPointer() - Start.getPointer();
+
+ return Status;
+}
+
void LLParser::restoreParsingState(const SlotMapping *Slots) {
if (!Slots)
return;
@@ -5827,8 +5842,8 @@ bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) {
/// parseDIExpression:
/// ::= !DIExpression(0, 7, -1)
bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) {
- assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
- Lex.Lex();
+ if (Lex.getKind() == lltok::MetadataVar)
+ Lex.Lex();
if (parseToken(lltok::lparen, "expected '(' here"))
return true;
diff --git a/llvm/lib/AsmParser/Parser.cpp b/llvm/lib/AsmParser/Parser.cpp
index eded892f358a8..17bdec3a090e7 100644
--- a/llvm/lib/AsmParser/Parser.cpp
+++ b/llvm/lib/AsmParser/Parser.cpp
@@ -12,6 +12,7 @@
#include "llvm/AsmParser/Parser.h"
#include "llvm/AsmParser/LLParser.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -224,3 +225,19 @@ Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read,
return nullptr;
return Ty;
}
+
+DIExpression *llvm::parseDIExpressionAtBeginning(StringRef Asm, unsigned &Read,
+ SMDiagnostic &Err,
+ const Module &M,
+ const SlotMapping *Slots) {
+ SourceMgr SM;
+ std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm);
+ SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
+ MDNode *MD;
+ if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext())
+ .parseDIExpressionAtBeginning(MD, Read, Slots))
+ return nullptr;
+ if (auto *Expr = dyn_cast<DIExpression>(MD))
+ return Expr;
+ return nullptr;
+}
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 1a12eefc8675b..188d6c9bbcf15 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -2302,48 +2302,14 @@ bool MIParser::parseMDNode(MDNode *&Node) {
}
bool MIParser::parseDIExpression(MDNode *&Expr) {
- assert(Token.is(MIToken::md_diexpr));
- lex();
-
- // FIXME: Share this parsing with the IL parser.
- SmallVector<uint64_t, 8> Elements;
-
- if (expectAndConsume(MIToken::lparen))
- return true;
-
- if (Token.isNot(MIToken::rparen)) {
- do {
- if (Token.is(MIToken::Identifier)) {
- if (unsigned Op = dwarf::getOperationEncoding(Token.stringValue())) {
- lex();
- Elements.push_back(Op);
- continue;
- }
- if (unsigned Enc = dwarf::getAttributeEncoding(Token.stringValue())) {
- lex();
- Elements.push_back(Enc);
- continue;
- }
- return error(Twine("invalid DWARF op '") + Token.stringValue() + "'");
- }
-
- if (Token.isNot(MIToken::IntegerLiteral) ||
- Token.integerValue().isSigned())
- return error("expected unsigned integer");
-
- auto &U = Token.integerValue();
- if (U.ugt(UINT64_MAX))
- return error("element too large, limit is " + Twine(UINT64_MAX));
- Elements.push_back(U.getZExtValue());
- lex();
-
- } while (consumeIfPresent(MIToken::comma));
- }
-
- if (expectAndConsume(MIToken::rparen))
- return true;
-
- Expr = DIExpression::get(MF.getFunction().getContext(), Elements);
+ unsigned Read;
+ Expr = llvm::parseDIExpressionAtBeginning(CurrentSource, Read, Error,
+ *PFS.MF.getFunction().getParent(),
+ &PFS.IRSlots);
+ CurrentSource = CurrentSource.slice(Read, StringRef::npos);
+ lex();
+ if (!Expr)
+ return error(Error.getMessage());
return false;
}
diff --git a/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir b/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
index 394c0d5d48eaa..f5c81411ede90 100644
--- a/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
+++ b/llvm/test/CodeGen/MIR/Generic/diexpression-err.mir
@@ -139,7 +139,7 @@ body: |
DBG_VALUE $edi, $noreg, !13, !DIExpression(), debug-location !17
%0:gr32 = COPY $edi
%1:gr32 = nsw IMUL32rri %0, 42, implicit-def dead $eflags, debug-instr-number 1, debug-location !18
- ; CHECK: {{.*}}.mir:[[#@LINE+1]]:38: invalid DWARF op 'W_OP_LLVM_arg'
+ ; CHECK: {{.*}}.mir:[[#@LINE+1]]:38: expected unsigned integer
DBG_INSTR_REF !14, !DIExpression(W_OP_LLVM_arg, 0), dbg-instr-ref(1, 0), debug-location !17
LIFETIME_START %stack.0.pinnedlocal, debug-location !19
%2:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @sink, $noreg, debug-location !28 :: (load (s64) from got)
diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index f296848ed665f..3749714fd4677 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -11,6 +11,7 @@
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Error.h"
@@ -411,4 +412,49 @@ TEST(AsmParserTest, InvalidDataLayoutStringCallback) {
EXPECT_EQ(Mod2->getDataLayout(), FixedDL);
}
+TEST(AsmParserTest, DIExpressionAtBeginningWithSlotMappingParsing) {
+ LLVMContext Ctx;
+ SMDiagnostic Error;
+ StringRef Source =
+ "%st = type { i32, i32 }\n"
+ "@v = common global [50 x %st] zeroinitializer, align 16\n"
+ "%0 = type { i32, i32, i32, i32 }\n"
+ "@g = common global [50 x %0] zeroinitializer, align 16\n"
+ "define void @marker4(i64 %d) {\n"
+ "entry:\n"
+ " %conv = trunc i64 %d to i32\n"
+ " store i32 %conv, ptr getelementptr inbounds "
+ " ([50 x %st], ptr @v, i64 0, i64 0, i32 0), align 16\n"
+ " store i32 %conv, ptr getelementptr inbounds "
+ " ([50 x %0], ptr @g, i64 0, i64 0, i32 0), align 16\n"
+ " ret void\n"
+ "}";
+ SlotMapping Mapping;
+ auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);
+ ASSERT_TRUE(Mod != nullptr);
+ auto &M = *Mod;
+ unsigned Read;
+
+ DIExpression *Expr;
+
+ Expr = parseDIExpressionAtBeginning("i32", Read, Error, M, &Mapping);
+ ASSERT_FALSE(Expr);
+
+ Expr = parseDIExpressionAtBeginning("!DIExpression()", Read, Error, M, &Mapping);
+ ASSERT_TRUE(Expr);
+ ASSERT_EQ(Expr->getNumElements(), 0);
+
+ Expr = parseDIExpressionAtBeginning("!DIExpression(0)", Read, Error, M, &Mapping);
+ ASSERT_TRUE(Expr);
+ ASSERT_EQ(Expr->getNumElements(), 1);
+
+ Expr = parseDIExpressionAtBeginning("!DIExpression(DW_OP_LLVM_fragment, 0, 1)", Read, Error, M, &Mapping);
+ ASSERT_TRUE(Expr);
+ ASSERT_EQ(Expr->getNumElements(), 3);
+
+ Expr = parseDIExpressionAtBeginning("(DW_OP_LLVM_fragment, 0, 1)", Read, Error, M, &Mapping);
+ ASSERT_TRUE(Expr);
+ ASSERT_EQ(Expr->getNumElements(), 3);
+}
+
} // end anonymous namespace
More information about the llvm-commits
mailing list