From: Alex Lorenz Date: Mon, 22 Jun 2015 17:02:30 +0000 (+0000) Subject: MIR Serialization: Serialize machine instruction names. X-Git-Tag: llvmorg-3.7.0-rc1~1852 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8e0a1b4857faf0ea9504ec254020dc22cd4f6cc1;p=platform%2Fupstream%2Fllvm.git MIR Serialization: Serialize machine instruction names. This commit implements initial machine instruction serialization. It serializes machine instruction names. The instructions are represented using a YAML sequence of string literals and are a part of machine basic block YAML mapping. This commit introduces a class called 'MIParser' which will be used to parse the machine instructions and operands. Reviewers: Duncan P. N. Exon Smith Differential Revision: http://reviews.llvm.org/D10481 llvm-svn: 240295 --- diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h index b1fe47a..8b20511 100644 --- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -22,6 +22,8 @@ #include "llvm/Support/YAMLTraits.h" #include +LLVM_YAML_IS_SEQUENCE_VECTOR(std::string) + namespace llvm { namespace yaml { @@ -31,7 +33,8 @@ struct MachineBasicBlock { bool IsLandingPad = false; bool AddressTaken = false; // TODO: Serialize the successors and liveins. - // TODO: Serialize machine instructions. + + std::vector Instructions; }; template <> struct MappingTraits { @@ -41,6 +44,7 @@ template <> struct MappingTraits { YamlIO.mapOptional("alignment", MBB.Alignment); YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad); YamlIO.mapOptional("addressTaken", MBB.AddressTaken); + YamlIO.mapOptional("instructions", MBB.Instructions); } }; diff --git a/llvm/lib/CodeGen/MIRParser/CMakeLists.txt b/llvm/lib/CodeGen/MIRParser/CMakeLists.txt index 468f072..d9cf3d8 100644 --- a/llvm/lib/CodeGen/MIRParser/CMakeLists.txt +++ b/llvm/lib/CodeGen/MIRParser/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMMIRParser + MIParser.cpp MIRParser.cpp ) diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp new file mode 100644 index 0000000..9427de4 --- /dev/null +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -0,0 +1,106 @@ +//===- MIParser.cpp - Machine instructions parser implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the parsing of machine instructions. +// +//===----------------------------------------------------------------------===// + +#include "MIParser.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Target/TargetInstrInfo.h" + +using namespace llvm; + +namespace { + +class MIParser { + SourceMgr &SM; + MachineFunction &MF; + SMDiagnostic &Error; + StringRef Source; + /// Maps from instruction names to op codes. + StringMap Names2InstrOpCodes; + +public: + MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error, + StringRef Source); + + /// Report an error at the current location with the given message. + /// + /// This function always return true. + bool error(const Twine &Msg); + + MachineInstr *parse(); + +private: + void initNames2InstrOpCodes(); + + /// Try to convert an instruction name to an opcode. Return true if the + /// instruction name is invalid. + bool parseInstrName(StringRef InstrName, unsigned &OpCode); +}; + +} // end anonymous namespace + +MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error, + StringRef Source) + : SM(SM), MF(MF), Error(Error), Source(Source) {} + +bool MIParser::error(const Twine &Msg) { + // TODO: Get the proper location in the MIR file, not just a location inside + // the string. + Error = + SMDiagnostic(SM, SMLoc(), SM.getMemoryBuffer(SM.getMainFileID()) + ->getBufferIdentifier(), + 1, 0, SourceMgr::DK_Error, Msg.str(), Source, None, None); + return true; +} + +MachineInstr *MIParser::parse() { + StringRef InstrName = Source; + unsigned OpCode; + if (parseInstrName(InstrName, OpCode)) { + error(Twine("unknown machine instruction name '") + InstrName + "'"); + return nullptr; + } + + // TODO: Parse the rest of instruction - machine operands, etc. + const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode); + auto *MI = MF.CreateMachineInstr(MCID, DebugLoc()); + return MI; +} + +void MIParser::initNames2InstrOpCodes() { + if (!Names2InstrOpCodes.empty()) + return; + const auto *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "Expected target instruction info"); + for (unsigned I = 0, E = TII->getNumOpcodes(); I < E; ++I) + Names2InstrOpCodes.insert(std::make_pair(StringRef(TII->getName(I)), I)); +} + +bool MIParser::parseInstrName(StringRef InstrName, unsigned &OpCode) { + initNames2InstrOpCodes(); + auto InstrInfo = Names2InstrOpCodes.find(InstrName); + if (InstrInfo == Names2InstrOpCodes.end()) + return true; + OpCode = InstrInfo->getValue(); + return false; +} + +MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF, + StringRef Src, SMDiagnostic &Error) { + return MIParser(SM, MF, Error, Src).parse(); +} diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.h b/llvm/lib/CodeGen/MIRParser/MIParser.h new file mode 100644 index 0000000..b55d70a --- /dev/null +++ b/llvm/lib/CodeGen/MIRParser/MIParser.h @@ -0,0 +1,31 @@ +//===- MIParser.h - Machine Instructions Parser ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the function that parses the machine instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H +#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +class MachineInstr; +class MachineFunction; +class SMDiagnostic; +class SourceMgr; + +MachineInstr *parseMachineInstr(SourceMgr &SM, MachineFunction &MF, + StringRef Src, SMDiagnostic &Error); + +} // end namespace llvm + +#endif diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index 1fef3f6..1ba7f1f 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "MIParser.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/STLExtras.h" @@ -79,7 +80,7 @@ public: /// Initialize the machine basic block using it's YAML representation. /// /// Return true if an error occurred. - bool initializeMachineBasicBlock(MachineBasicBlock &MBB, + bool initializeMachineBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, const yaml::MachineBasicBlock &YamlMBB); private: @@ -218,18 +219,29 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { } auto *MBB = MF.CreateMachineBasicBlock(BB); MF.insert(MF.end(), MBB); - if (initializeMachineBasicBlock(*MBB, YamlMBB)) + if (initializeMachineBasicBlock(MF, *MBB, YamlMBB)) return true; } return false; } bool MIRParserImpl::initializeMachineBasicBlock( - MachineBasicBlock &MBB, const yaml::MachineBasicBlock &YamlMBB) { + MachineFunction &MF, MachineBasicBlock &MBB, + const yaml::MachineBasicBlock &YamlMBB) { MBB.setAlignment(YamlMBB.Alignment); if (YamlMBB.AddressTaken) MBB.setHasAddressTaken(); MBB.setIsLandingPad(YamlMBB.IsLandingPad); + // Parse the instructions. + for (const auto &MISource : YamlMBB.Instructions) { + SMDiagnostic Error; + if (auto *MI = parseMachineInstr(SM, MF, MISource, Error)) { + MBB.insert(MBB.end(), MI); + continue; + } + reportDiagnostic(Error); + return true; + } return false; } diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index bbf163a..7aa1b69 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -21,6 +21,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/YAMLTraits.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; @@ -39,6 +41,17 @@ public: void convert(yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB); }; +/// This class prints out the machine instructions using the MIR serialization +/// format. +class MIPrinter { + raw_ostream &OS; + +public: + MIPrinter(raw_ostream &OS) : OS(OS) {} + + void print(const MachineInstr &MI); +}; + } // end anonymous namespace namespace llvm { @@ -83,6 +96,25 @@ void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB, YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); + + // Print the machine instructions. + YamlMBB.Instructions.reserve(MBB.size()); + std::string Str; + for (const auto &MI : MBB) { + raw_string_ostream StrOS(Str); + MIPrinter(StrOS).print(MI); + YamlMBB.Instructions.push_back(StrOS.str()); + Str.clear(); + } +} + +void MIPrinter::print(const MachineInstr &MI) { + const auto &SubTarget = MI.getParent()->getParent()->getSubtarget(); + const auto *TII = SubTarget.getInstrInfo(); + assert(TII && "Expected target instruction info"); + + OS << TII->getName(MI.getOpcode()); + // TODO: Print the instruction flags, machine operands, machine mem operands. } void llvm::printMIR(raw_ostream &OS, const Module &M) { diff --git a/llvm/test/CodeGen/MIR/X86/lit.local.cfg b/llvm/test/CodeGen/MIR/X86/lit.local.cfg new file mode 100644 index 0000000..c8625f4 --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'X86' in config.root.targets: + config.unsupported = True diff --git a/llvm/test/CodeGen/MIR/X86/machine-instructions.mir b/llvm/test/CodeGen/MIR/X86/machine-instructions.mir new file mode 100644 index 0000000..801a6d8 --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/machine-instructions.mir @@ -0,0 +1,24 @@ +# 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 X86 machine instructions +# correctly. + +--- | + + define i32 @inc(i32 %a) { + entry: + %b = mul i32 %a, 11 + ret i32 %b + } + +... +--- +# CHECK: name: inc +name: inc +body: + - name: entry + instructions: + # CHECK: - IMUL32rri8 + # CHECK-NEXT: - RETQ + - IMUL32rri8 + - RETQ +... diff --git a/llvm/test/CodeGen/MIR/X86/unknown-instruction.mir b/llvm/test/CodeGen/MIR/X86/unknown-instruction.mir new file mode 100644 index 0000000..05decaa --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/unknown-instruction.mir @@ -0,0 +1,20 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that an error is reported when an unknown instruction is +# encountered. + +--- | + + define i32 @foo() { + entry: + ret i32 0 + } + +... +--- +name: foo +body: + - name: entry + instructions: + # CHECK: 1:1: unknown machine instruction name 'retJust0' + - retJust0 +...