diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -794,6 +794,18 @@ lastIndex = idx; } + // WebAssemblyDebugFixup pass can generate a DBG_VALUE instruction after a + // terminator, in case the terminator instruction consumes a stack operand. + // Consuming a stack operand changes the contents of the stack, so a DBG_VALUE + // instruction is necessary to terminate the associated variable's range. + // The DBG_VALUE instruction takes a form of + // DBG_VALUE $noreg, $noreg, !"variable", ... + if (TM->getTargetTriple().isWasm() && FirstTerminator && MI->isDebugValue() && + MI->getOperand(0).isReg() && MI->getOperand(1).isReg() && + !MI->getOperand(0).getReg().isValid() && + !MI->getOperand(1).getReg().isValid()) + return; + // Ensure non-terminators don't follow terminators. if (MI->isTerminator()) { if (!FirstTerminator) diff --git a/llvm/test/CodeGen/WebAssembly/stackified-debug.ll b/llvm/test/CodeGen/WebAssembly/stackified-debug.ll --- a/llvm/test/CodeGen/WebAssembly/stackified-debug.ll +++ b/llvm/test/CodeGen/WebAssembly/stackified-debug.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s | FileCheck %s +; RUN: llc -verify-machineinstrs < %s | FileCheck %s ; Input C code: @@ -42,8 +42,6 @@ ; CHECK: .int8 159 # DW_OP_stack_value - - source_filename = "stackified.c" target triple = "wasm32-unknown-unknown" @@ -57,10 +55,25 @@ ret void, !dbg !22 } -declare i32 @input() +; DebugFixup pass adds a DBG_VALUE instruction to clear the debug value range of +; "myvar" (!27) after BR_IF instruction in the entry BB. Even though it is +; generally not allowed to have more instructions after a terminator, this +; special case should not crash MachineVerifier. +define void @dbg_value_after_terminator(i32 %a, i32 %b) !dbg !23 { +entry: + %cmp = icmp ne i32 %a, %b, !dbg !25 + call void @llvm.dbg.value(metadata i1 %cmp, metadata !27, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !25 + br i1 %cmp, label %bb.1, label %bb.0, !dbg !25 -declare !dbg !4 void @output(i32, i32) +bb.0: ; preds = %entry + unreachable +bb.1: ; preds = %entry + ret void +} + +declare i32 @input() +declare !dbg !4 void @output(i32, i32) declare void @llvm.dbg.value(metadata, metadata, metadata) !llvm.dbg.cu = !{!0} @@ -90,3 +103,9 @@ !20 = !DILocation(line: 5, column: 11, scope: !12) !21 = !DILocation(line: 6, column: 3, scope: !12) !22 = !DILocation(line: 7, column: 1, scope: !12) +!23 = distinct !DISubprogram(name: "dbg_value_after_terminator", scope: null, type: !24, spFlags: DISPFlagDefinition, unit: !0) +!24 = !DISubroutineType(types: !2) +!25 = !DILocation(line: 0, scope: !26) +!26 = distinct !DILexicalBlock(scope: !23) +!27 = !DILocalVariable(name: "myvar", scope: !26, type: !28) +!28 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)