From 1b75dd2bc23ec559555a2f9decef82dddfe720f1 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 21 Jul 2015 22:28:27 +0000 Subject: [PATCH] MIR Serialization: Start serializing the CFI operands with .cfi_def_cfa_offset. This commit begins serialization of the CFI index machine operands by serializing one kind of CFI instruction - the .cfi_def_cfa_offset instruction. Reviewers: Duncan P. N. Exon Smith git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242845 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MIRParser/MILexer.cpp | 3 +- lib/CodeGen/MIRParser/MILexer.h | 1 + lib/CodeGen/MIRParser/MIParser.cpp | 28 +++++++++++++++++ lib/CodeGen/MIRPrinter.cpp | 25 +++++++++++++++ test/CodeGen/MIR/X86/cfi-def-cfa-offset.mir | 31 +++++++++++++++++++ .../X86/expected-offset-after-cfi-operand.mir | 29 +++++++++++++++++ .../MIR/X86/large-cfi-offset-number-error.mir | 29 +++++++++++++++++ 7 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/MIR/X86/cfi-def-cfa-offset.mir create mode 100644 test/CodeGen/MIR/X86/expected-offset-after-cfi-operand.mir create mode 100644 test/CodeGen/MIR/X86/large-cfi-offset-number-error.mir diff --git a/lib/CodeGen/MIRParser/MILexer.cpp b/lib/CodeGen/MIRParser/MILexer.cpp index ab9dff8632e..c88333e6f59 100644 --- a/lib/CodeGen/MIRParser/MILexer.cpp +++ b/lib/CodeGen/MIRParser/MILexer.cpp @@ -123,11 +123,12 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("killed", MIToken::kw_killed) .Case("undef", MIToken::kw_undef) .Case("frame-setup", MIToken::kw_frame_setup) + .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset) .Default(MIToken::Identifier); } static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { - if (!isalpha(C.peek()) && C.peek() != '_') + if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.') return None; auto Range = C; while (isIdentifierChar(C.peek())) diff --git a/lib/CodeGen/MIRParser/MILexer.h b/lib/CodeGen/MIRParser/MILexer.h index 7f36b9ab7f6..771f6047e5c 100644 --- a/lib/CodeGen/MIRParser/MILexer.h +++ b/lib/CodeGen/MIRParser/MILexer.h @@ -44,6 +44,7 @@ struct MIToken { kw_killed, kw_undef, kw_frame_setup, + kw_cfi_def_cfa_offset, // Identifier tokens Identifier, diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index ca98ae3c97f..498ca0615d5 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" @@ -111,6 +112,8 @@ public: bool parseConstantPoolIndexOperand(MachineOperand &Dest); bool parseJumpTableIndexOperand(MachineOperand &Dest); bool parseExternalSymbolOperand(MachineOperand &Dest); + bool parseCFIOffset(int &Offset); + bool parseCFIOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest); private: @@ -572,6 +575,29 @@ bool MIParser::parseExternalSymbolOperand(MachineOperand &Dest) { return false; } +bool MIParser::parseCFIOffset(int &Offset) { + if (Token.isNot(MIToken::IntegerLiteral)) + return error("expected a cfi offset"); + if (Token.integerValue().getMinSignedBits() > 32) + return error("expected a 32 bit integer (the cfi offset is too large)"); + Offset = (int)Token.integerValue().getExtValue(); + lex(); + return false; +} + +bool MIParser::parseCFIOperand(MachineOperand &Dest) { + // TODO: Parse the other CFI operands. + assert(Token.is(MIToken::kw_cfi_def_cfa_offset)); + lex(); + int Offset; + if (parseCFIOffset(Offset)) + return true; + // NB: MCCFIInstruction::createDefCfaOffset negates the offset. + Dest = MachineOperand::CreateCFIIndex(MF.getMMI().addFrameInst( + MCCFIInstruction::createDefCfaOffset(nullptr, -Offset))); + return false; +} + bool MIParser::parseMachineOperand(MachineOperand &Dest) { switch (Token.kind()) { case MIToken::kw_implicit: @@ -602,6 +628,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) { case MIToken::ExternalSymbol: case MIToken::QuotedExternalSymbol: return parseExternalSymbolOperand(Dest); + case MIToken::kw_cfi_def_cfa_offset: + return parseCFIOperand(Dest); case MIToken::Error: return true; case MIToken::Identifier: diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index 9413a7e3811..08eafb6f0ec 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -17,6 +17,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/IR/BasicBlock.h" @@ -103,6 +104,8 @@ public: void printMBBReference(const MachineBasicBlock &MBB); void printStackObjectReference(int FrameIndex); void print(const MachineOperand &Op, const TargetRegisterInfo *TRI); + + void print(const MCCFIInstruction &CFI); }; } // end anonymous namespace @@ -347,6 +350,8 @@ void MIPrinter::print(const MachineInstr &MI) { assert(TRI && "Expected target register info"); const auto *TII = SubTarget.getInstrInfo(); assert(TII && "Expected target instruction info"); + if (MI.isCFIInstruction()) + assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction"); unsigned I = 0, E = MI.getNumOperands(); for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() && @@ -448,12 +453,32 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { llvm_unreachable("Can't print this machine register mask yet."); break; } + case MachineOperand::MO_CFIIndex: { + const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI(); + print(MMI.getFrameInstructions()[Op.getCFIIndex()]); + break; + } default: // TODO: Print the other machine operands. llvm_unreachable("Can't print this machine operand at the moment"); } } +void MIPrinter::print(const MCCFIInstruction &CFI) { + switch (CFI.getOperation()) { + case MCCFIInstruction::OpDefCfaOffset: + OS << ".cfi_def_cfa_offset "; + if (CFI.getLabel()) + OS << " "; + OS << CFI.getOffset(); + break; + default: + // TODO: Print the other CFI Operations. + OS << ""; + break; + } +} + void llvm::printMIR(raw_ostream &OS, const Module &M) { yaml::Output Out(OS); Out << const_cast(M); diff --git a/test/CodeGen/MIR/X86/cfi-def-cfa-offset.mir b/test/CodeGen/MIR/X86/cfi-def-cfa-offset.mir new file mode 100644 index 00000000000..3fb5395602d --- /dev/null +++ b/test/CodeGen/MIR/X86/cfi-def-cfa-offset.mir @@ -0,0 +1,31 @@ +# 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_def_cfa_offset operands +# correctly. + +--- | + + define void @test() { + entry: + %tmp = alloca [4168 x i8], align 4 + ret void + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 4040 +stack: + - { id: 0, name: tmp, offset: -4176, size: 4168, alignment: 4 } +body: + - id: 0 + name: entry + instructions: + - '%rsp = SUB64ri32 %rsp, 4040, implicit-def dead %eflags' + # CHECK: CFI_INSTRUCTION .cfi_def_cfa_offset 4048 + - 'CFI_INSTRUCTION .cfi_def_cfa_offset 4048' + - '%rsp = ADD64ri32 %rsp, 4040, implicit-def dead %eflags' + - 'RETQ' +... + diff --git a/test/CodeGen/MIR/X86/expected-offset-after-cfi-operand.mir b/test/CodeGen/MIR/X86/expected-offset-after-cfi-operand.mir new file mode 100644 index 00000000000..42fb1400268 --- /dev/null +++ b/test/CodeGen/MIR/X86/expected-offset-after-cfi-operand.mir @@ -0,0 +1,29 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + define void @test() { + entry: + %tmp = alloca [4168 x i8], align 4 + ret void + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 4040 +stack: + - { id: 0, name: tmp, offset: -4176, size: 4168, alignment: 4 } +body: + - id: 0 + name: entry + instructions: + - '%rsp = SUB64ri32 %rsp, 4040, implicit-def dead %eflags' + # CHECK: [[@LINE+1]]:46: expected a cfi offset + - 'CFI_INSTRUCTION .cfi_def_cfa_offset _' + - '%rsp = ADD64ri32 %rsp, 4040, implicit-def dead %eflags' + - 'RETQ' +... + diff --git a/test/CodeGen/MIR/X86/large-cfi-offset-number-error.mir b/test/CodeGen/MIR/X86/large-cfi-offset-number-error.mir new file mode 100644 index 00000000000..5f395b1ef01 --- /dev/null +++ b/test/CodeGen/MIR/X86/large-cfi-offset-number-error.mir @@ -0,0 +1,29 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + define void @test() { + entry: + %tmp = alloca [4168 x i8], align 4 + ret void + } + +... +--- +name: test +tracksRegLiveness: true +frameInfo: + stackSize: 4040 +stack: + - { id: 0, name: tmp, offset: -4176, size: 4168, alignment: 4 } +body: + - id: 0 + name: entry + instructions: + - '%rsp = SUB64ri32 %rsp, 4040, implicit-def dead %eflags' + # CHECK: [[@LINE+1]]:46: expected a 32 bit integer (the cfi offset is too large) + - 'CFI_INSTRUCTION .cfi_def_cfa_offset 123456789123456' + - '%rsp = ADD64ri32 %rsp, 4040, implicit-def dead %eflags' + - 'RETQ' +... + -- 2.34.1