diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -120,6 +120,7 @@ kw_shufflemask, kw_pre_instr_symbol, kw_post_instr_symbol, + kw_heap_alloc_marker, kw_unknown_size, // Named metadata keywords diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -252,6 +252,7 @@ .Case("shufflemask", MIToken::kw_shufflemask) .Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol) .Case("post-instr-symbol", MIToken::kw_post_instr_symbol) + .Case("heap-alloc-marker", MIToken::kw_heap_alloc_marker) .Case("unknown-size", MIToken::kw_unknown_size) .Default(MIToken::Identifier); } @@ -582,8 +583,8 @@ .Default(MIToken::Error); } -static Cursor maybeLexExlaim(Cursor C, MIToken &Token, - ErrorCallbackType ErrorCallback) { +static Cursor maybeLexExclaim(Cursor C, MIToken &Token, + ErrorCallbackType ErrorCallback) { if (C.peek() != '!') return None; auto Range = C; @@ -719,7 +720,7 @@ return R.remaining(); if (Cursor R = maybeLexNumericalLiteral(C, Token)) return R.remaining(); - if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback)) + if (Cursor R = maybeLexExclaim(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexSymbol(C, Token)) return R.remaining(); diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -471,6 +471,7 @@ bool parseOptionalAtomicOrdering(AtomicOrdering &Order); bool parseMachineMemoryOperand(MachineMemOperand *&Dest); bool parsePreOrPostInstrSymbol(MCSymbol *&Symbol); + bool parseHeapAllocMarker(MDNode *&Node); private: /// Convert the integer literal in the current token into an unsigned integer. @@ -906,6 +907,7 @@ // Parse the remaining machine operands. while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_pre_instr_symbol) && Token.isNot(MIToken::kw_post_instr_symbol) && + Token.isNot(MIToken::kw_heap_alloc_marker) && Token.isNot(MIToken::kw_debug_location) && Token.isNot(MIToken::coloncolon) && Token.isNot(MIToken::lbrace)) { auto Loc = Token.location(); @@ -932,6 +934,10 @@ if (Token.is(MIToken::kw_post_instr_symbol)) if (parsePreOrPostInstrSymbol(PostInstrSymbol)) return true; + MDNode *HeapAllocMarker = nullptr; + if (Token.is(MIToken::kw_heap_alloc_marker)) + if (parseHeapAllocMarker(HeapAllocMarker)) + return true; DebugLoc DebugLocation; if (Token.is(MIToken::kw_debug_location)) { @@ -985,6 +991,8 @@ MI->setPreInstrSymbol(MF, PreInstrSymbol); if (PostInstrSymbol) MI->setPostInstrSymbol(MF, PostInstrSymbol); + if (HeapAllocMarker) + MI->setHeapAllocMarker(MF, HeapAllocMarker); if (!MemOperands.empty()) MI->setMemRefs(MF, MemOperands); return false; @@ -2956,6 +2964,22 @@ return false; } +bool MIParser::parseHeapAllocMarker(MDNode *&Node) { + assert(Token.is(MIToken::kw_heap_alloc_marker) && + "Invalid token for a heap alloc marker!"); + lex(); + parseMDNode(Node); + if (!Node) + return error("expected a MDNode after 'heap-alloc-marker'"); + if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) || + Token.is(MIToken::lbrace)) + return false; + if (Token.isNot(MIToken::comma)) + return error("expected ',' before the next machine operand"); + lex(); + return false; +} + static void initSlots2BasicBlocks( const Function &F, DenseMap &Slots2BasicBlocks) { diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -784,6 +784,13 @@ MachineOperand::printSymbol(OS, *PostInstrSymbol); NeedComma = true; } + if (MDNode *HeapAllocMarker = MI.getHeapAllocMarker()) { + if (NeedComma) + OS << ','; + OS << " heap-alloc-marker "; + HeapAllocMarker->printAsOperand(OS, MST); + NeedComma = true; + } if (const DebugLoc &DL = MI.getDebugLoc()) { if (NeedComma) diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1701,12 +1701,13 @@ OS << " post-instr-symbol "; MachineOperand::printSymbol(OS, *PostInstrSymbol); } - if (/*MDNode *HeapAllocMarker =*/getHeapAllocMarker()) { + if (MDNode *HeapAllocMarker = getHeapAllocMarker()) { if (!FirstOp) { FirstOp = false; OS << ','; } - OS << " heap-alloc-marker"; + OS << " heap-alloc-marker "; + HeapAllocMarker->printAsOperand(OS, MST); } if (!SkipDebugLoc) { diff --git a/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir @@ -0,0 +1,42 @@ +# RUN: llc -march=x86-64 -run-pass none -o - %s | FileCheck %s +# This test ensures that the MIR parser parses heap alloc markers correctly. + +--- | + declare i8* @f(i32) nounwind + + define i32 @test(i32 %x) nounwind { + entry: + call i8* @f(i32 %x), !heapallocsite !2 + ret i32 undef + } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) + !1 = !DIFile(filename: "test.ll", directory: "") + !2 = !{} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = !{i32 1, !"wchar_size", i32 2} + +... +--- +name: test +# CHECK-LABEL: name: test +tracksRegLiveness: true +frameInfo: + hasCalls: true +body: | + bb.0.entry: + liveins: $ecx + + %0:gr32 = COPY $ecx + ADJCALLSTACKDOWN64 32, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $ecx = COPY %0 + CALL64pcrel32 @f, csr_win64, implicit $rsp, implicit $ssp, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax, heap-alloc-marker !2 + ; CHECK: CALL64pcrel32 @f, {{.*}} heap-alloc-marker !2 + ADJCALLSTACKUP64 32, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $eax = MOV32r0 implicit-def dead $eflags + RET 0, killed $eax + +... diff --git a/llvm/test/CodeGen/X86/heap-alloc-markers.mir b/llvm/test/CodeGen/X86/heap-alloc-markers.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/heap-alloc-markers.mir @@ -0,0 +1,50 @@ +# RUN: llc -mtriple=x86_64-unknown-windows-msvc -start-before=x86-flags-copy-lowering -o - %s | FileCheck %s +# +# Test the emission of heap alloc site instruction labels. + +--- | + declare i8* @alloc(i32) nounwind + + define i32 @test(i32 %x) nounwind !dbg !6 { + entry: + call i8* @alloc(i32 %x), !dbg !11, !heapallocsite !2 + ret i32 0, !dbg !12 + } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4, !5} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) + !1 = !DIFile(filename: "", directory: "") + !2 = !{} + !3 = !{i32 2, !"CodeView", i32 1} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = !{i32 1, !"wchar_size", i32 2} + !6 = distinct !DISubprogram(name: "test", scope: !7, file: !7, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) + !7 = !DIFile(filename: "test.c", directory: "") + !8 = !DISubroutineType(types: !9) + !9 = !{!10, !10} + !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !11 = !DILocation(line: 3, scope: !6) + !12 = !DILocation(line: 4, scope: !6) + +... +--- +name: test +# CHECK-LABEL: {{^}}test: +tracksRegLiveness: true +frameInfo: + hasCalls: true +body: | + bb.0.entry: + liveins: $ecx + + ADJCALLSTACKDOWN64 32, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !11 + CALL64pcrel32 @alloc, csr_win64, implicit $rsp, implicit $ssp, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax, heap-alloc-marker !2, debug-location !11 + ; CHECK: callq alloc + ; CHECK-NEXT: .Ltmp{{.*}}: + ADJCALLSTACKUP64 32, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !11 + $eax = MOV32r0 implicit-def dead $eflags, debug-location !12 + RET 0, killed $eax, debug-location !12 + +...