From 832202c797450c665d516b3b8fecc0db80009c15 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 23 Jul 2015 23:09:07 +0000 Subject: [PATCH] MIR Serialization: Serialize the '.cfi_offset' CFI instruction. Reviewers: Duncan P. N. Exon Smith git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243062 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MIRParser/MILexer.cpp | 1 + lib/CodeGen/MIRParser/MILexer.h | 1 + lib/CodeGen/MIRParser/MIParser.cpp | 69 +++++++++++++++++-- lib/CodeGen/MIRPrinter.cpp | 24 ++++++- test/CodeGen/MIR/X86/cfi-offset.mir | 47 +++++++++++++ .../X86/expected-comma-after-cfi-register.mir | 44 ++++++++++++ .../expected-register-after-cfi-operand.mir | 44 ++++++++++++ 7 files changed, 220 insertions(+), 10 deletions(-) create mode 100644 test/CodeGen/MIR/X86/cfi-offset.mir create mode 100644 test/CodeGen/MIR/X86/expected-comma-after-cfi-register.mir create mode 100644 test/CodeGen/MIR/X86/expected-register-after-cfi-operand.mir diff --git a/lib/CodeGen/MIRParser/MILexer.cpp b/lib/CodeGen/MIRParser/MILexer.cpp index 1b483330e54..27d661760cc 100644 --- a/lib/CodeGen/MIRParser/MILexer.cpp +++ b/lib/CodeGen/MIRParser/MILexer.cpp @@ -124,6 +124,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("undef", MIToken::kw_undef) .Case("frame-setup", MIToken::kw_frame_setup) .Case("debug-location", MIToken::kw_debug_location) + .Case(".cfi_offset", MIToken::kw_cfi_offset) .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset) .Default(MIToken::Identifier); } diff --git a/lib/CodeGen/MIRParser/MILexer.h b/lib/CodeGen/MIRParser/MILexer.h index 71356e37971..bae9dcd1ebe 100644 --- a/lib/CodeGen/MIRParser/MILexer.h +++ b/lib/CodeGen/MIRParser/MILexer.h @@ -46,6 +46,7 @@ struct MIToken { kw_undef, kw_frame_setup, kw_debug_location, + kw_cfi_offset, kw_cfi_def_cfa_offset, // Identifier tokens diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index de2f6158b45..656f2314315 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -115,6 +115,7 @@ public: bool parseMDNode(MDNode *&Node); bool parseMetadataOperand(MachineOperand &Dest); bool parseCFIOffset(int &Offset); + bool parseCFIRegister(unsigned &Reg); bool parseCFIOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest); @@ -124,6 +125,10 @@ private: /// Return true if an error occurred. bool getUnsigned(unsigned &Result); + /// If the current token is of the given kind, consume it and return false. + /// Otherwise report an error and return true. + bool expectAndConsume(MIToken::TokenKind TokenKind); + void initNames2InstrOpCodes(); /// Try to convert an instruction name to an opcode. Return true if the @@ -181,6 +186,22 @@ bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) { return true; } +static const char *toString(MIToken::TokenKind TokenKind) { + switch (TokenKind) { + case MIToken::comma: + return "','"; + default: + return ""; + } +} + +bool MIParser::expectAndConsume(MIToken::TokenKind TokenKind) { + if (Token.isNot(TokenKind)) + return error(Twine("expected ") + toString(TokenKind)); + lex(); + return false; +} + bool MIParser::parse(MachineInstr *&MI) { lex(); @@ -623,16 +644,49 @@ bool MIParser::parseCFIOffset(int &Offset) { return false; } +bool MIParser::parseCFIRegister(unsigned &Reg) { + if (Token.isNot(MIToken::NamedRegister)) + return error("expected a cfi register"); + unsigned LLVMReg; + if (parseRegister(LLVMReg)) + return true; + const auto *TRI = MF.getSubtarget().getRegisterInfo(); + assert(TRI && "Expected target register info"); + int DwarfReg = TRI->getDwarfRegNum(LLVMReg, true); + if (DwarfReg < 0) + return error("invalid DWARF register"); + Reg = (unsigned)DwarfReg; + lex(); + return false; +} + bool MIParser::parseCFIOperand(MachineOperand &Dest) { - // TODO: Parse the other CFI operands. - assert(Token.is(MIToken::kw_cfi_def_cfa_offset)); + auto Kind = Token.kind(); lex(); + auto &MMI = MF.getMMI(); int Offset; - if (parseCFIOffset(Offset)) - return true; - // NB: MCCFIInstruction::createDefCfaOffset negates the offset. - Dest = MachineOperand::CreateCFIIndex(MF.getMMI().addFrameInst( - MCCFIInstruction::createDefCfaOffset(nullptr, -Offset))); + unsigned Reg; + unsigned CFIIndex; + switch (Kind) { + case MIToken::kw_cfi_offset: + if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) || + parseCFIOffset(Offset)) + return true; + CFIIndex = + MMI.addFrameInst(MCCFIInstruction::createOffset(nullptr, Reg, Offset)); + break; + case MIToken::kw_cfi_def_cfa_offset: + if (parseCFIOffset(Offset)) + return true; + // NB: MCCFIInstruction::createDefCfaOffset negates the offset. + CFIIndex = MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(nullptr, -Offset)); + break; + default: + // TODO: Parse the other CFI operands. + llvm_unreachable("The current token should be a cfi operand"); + } + Dest = MachineOperand::CreateCFIIndex(CFIIndex); return false; } @@ -668,6 +722,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) { return parseExternalSymbolOperand(Dest); case MIToken::exclaim: return parseMetadataOperand(Dest); + case MIToken::kw_cfi_offset: case MIToken::kw_cfi_def_cfa_offset: return parseCFIOperand(Dest); case MIToken::Error: diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index da1ebe15c8b..2ae5466392f 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -105,7 +105,7 @@ public: void printStackObjectReference(int FrameIndex); void print(const MachineOperand &Op, const TargetRegisterInfo *TRI); - void print(const MCCFIInstruction &CFI); + void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI); }; } // end anonymous namespace @@ -465,7 +465,7 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { break; case MachineOperand::MO_CFIIndex: { const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI(); - print(MMI.getFrameInstructions()[Op.getCFIIndex()]); + print(MMI.getFrameInstructions()[Op.getCFIIndex()], TRI); break; } default: @@ -474,8 +474,26 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { } } -void MIPrinter::print(const MCCFIInstruction &CFI) { +static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS, + const TargetRegisterInfo *TRI) { + int Reg = TRI->getLLVMRegNum(DwarfReg, true); + if (Reg == -1) { + OS << ""; + return; + } + printReg(Reg, OS, TRI); +} + +void MIPrinter::print(const MCCFIInstruction &CFI, + const TargetRegisterInfo *TRI) { switch (CFI.getOperation()) { + case MCCFIInstruction::OpOffset: + OS << ".cfi_offset "; + if (CFI.getLabel()) + OS << " "; + printCFIRegister(CFI.getRegister(), OS, TRI); + OS << ", " << CFI.getOffset(); + break; case MCCFIInstruction::OpDefCfaOffset: OS << ".cfi_def_cfa_offset "; if (CFI.getLabel()) diff --git a/test/CodeGen/MIR/X86/cfi-offset.mir b/test/CodeGen/MIR/X86/cfi-offset.mir new file mode 100644 index 00000000000..548bcb45924 --- /dev/null +++ b/test/CodeGen/MIR/X86/cfi-offset.mir @@ -0,0 +1,47 @@ +# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the MIR parser parses the .cfi_offset operands +# correctly. + +--- | + + declare void @foo(i32) + + define i32 @test(i32 %a, i32 %b, i32 %c, i32 %d) { + entry: + %add = add nsw i32 %b, %a + %add1 = add nsw i32 %add, %c + %add2 = add nsw i32 %add1, %d + tail call void @foo(i32 %add2) + %add6 = add nsw i32 %add2, %add2 + ret i32 %add6 + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 8 + adjustsStack: true + hasCalls: true +fixedStack: + - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 } +body: + - id: 0 + name: entry + instructions: + - 'PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp' + - 'CFI_INSTRUCTION .cfi_def_cfa_offset 16' + # CHECK: CFI_INSTRUCTION .cfi_offset %rbx, -16 + - 'CFI_INSTRUCTION .cfi_offset %rbx, -16' + - '%ebx = COPY %edi, implicit-def %rbx' + - '%ebx = ADD32rr %ebx, killed %esi, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %edx, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %ecx, implicit-def dead %eflags' + - '%edi = COPY %ebx' + - 'CALL64pcrel32 @foo, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp' + - '%eax = LEA64_32r killed %rbx, 1, %rbx, 0, _' + - '%rbx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +... + diff --git a/test/CodeGen/MIR/X86/expected-comma-after-cfi-register.mir b/test/CodeGen/MIR/X86/expected-comma-after-cfi-register.mir new file mode 100644 index 00000000000..8c4eac037fa --- /dev/null +++ b/test/CodeGen/MIR/X86/expected-comma-after-cfi-register.mir @@ -0,0 +1,44 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + declare void @foo(i32) + + define i32 @test(i32 %a, i32 %b, i32 %c, i32 %d) { + entry: + %add = add nsw i32 %b, %a + %add1 = add nsw i32 %add, %c + %add2 = add nsw i32 %add1, %d + tail call void @foo(i32 %add2) + %add6 = add nsw i32 %add2, %add2 + ret i32 %add6 + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 8 + adjustsStack: true + hasCalls: true +fixedStack: + - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 } +body: + - id: 0 + name: entry + instructions: + - 'PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp' + - 'CFI_INSTRUCTION .cfi_def_cfa_offset 16' + # CHECK: [[@LINE+1]]:43: expected ',' + - 'CFI_INSTRUCTION .cfi_offset %rbx -16' + - '%ebx = COPY %edi, implicit-def %rbx' + - '%ebx = ADD32rr %ebx, killed %esi, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %edx, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %ecx, implicit-def dead %eflags' + - '%edi = COPY %ebx' + - 'CALL64pcrel32 @foo, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp' + - '%eax = LEA64_32r killed %rbx, 1, %rbx, 0, _' + - '%rbx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/expected-register-after-cfi-operand.mir b/test/CodeGen/MIR/X86/expected-register-after-cfi-operand.mir new file mode 100644 index 00000000000..7178c1d4568 --- /dev/null +++ b/test/CodeGen/MIR/X86/expected-register-after-cfi-operand.mir @@ -0,0 +1,44 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + declare void @foo(i32) + + define i32 @test(i32 %a, i32 %b, i32 %c, i32 %d) { + entry: + %add = add nsw i32 %b, %a + %add1 = add nsw i32 %add, %c + %add2 = add nsw i32 %add1, %d + tail call void @foo(i32 %add2) + %add6 = add nsw i32 %add2, %add2 + ret i32 %add6 + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 8 + adjustsStack: true + hasCalls: true +fixedStack: + - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 } +body: + - id: 0 + name: entry + instructions: + - 'PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp' + - 'CFI_INSTRUCTION .cfi_def_cfa_offset 16' + # CHECK: [[@LINE+1]]:38: expected a cfi register + - 'CFI_INSTRUCTION .cfi_offset %0, -16' + - '%ebx = COPY %edi, implicit-def %rbx' + - '%ebx = ADD32rr %ebx, killed %esi, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %edx, implicit-def dead %eflags' + - '%ebx = ADD32rr %ebx, killed %ecx, implicit-def dead %eflags' + - '%edi = COPY %ebx' + - 'CALL64pcrel32 @foo, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp' + - '%eax = LEA64_32r killed %rbx, 1, %rbx, 0, _' + - '%rbx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +... -- 2.34.1