Skip to content

Commit

Permalink
MIR Serialization: Serialize machine instruction names.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hyp committed Jun 22, 2015
1 parent 7f09a98 commit 8e0a1b4
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 4 deletions.
6 changes: 5 additions & 1 deletion llvm/include/llvm/CodeGen/MIRYamlMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "llvm/Support/YAMLTraits.h"
#include <vector>

LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)

namespace llvm {
namespace yaml {

Expand All @@ -31,7 +33,8 @@ struct MachineBasicBlock {
bool IsLandingPad = false;
bool AddressTaken = false;
// TODO: Serialize the successors and liveins.
// TODO: Serialize machine instructions.

std::vector<std::string> Instructions;
};

template <> struct MappingTraits<MachineBasicBlock> {
Expand All @@ -41,6 +44,7 @@ template <> struct MappingTraits<MachineBasicBlock> {
YamlIO.mapOptional("alignment", MBB.Alignment);
YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad);
YamlIO.mapOptional("addressTaken", MBB.AddressTaken);
YamlIO.mapOptional("instructions", MBB.Instructions);
}
};

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/MIRParser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_llvm_library(LLVMMIRParser
MIParser.cpp
MIRParser.cpp
)

Expand Down
106 changes: 106 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
@@ -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<unsigned> 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();
}
31 changes: 31 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MIParser.h
Original file line number Diff line number Diff line change
@@ -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
18 changes: 15 additions & 3 deletions llvm/lib/CodeGen/MIRParser/MIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -79,7 +80,7 @@ class MIRParserImpl {
/// 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:
Expand Down Expand Up @@ -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;
}

Expand Down
32 changes: 32 additions & 0 deletions llvm/lib/CodeGen/MIRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -39,6 +41,17 @@ class MIRPrinter {
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 {
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/MIR/X86/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
if not 'X86' in config.root.targets:
config.unsupported = True
24 changes: 24 additions & 0 deletions llvm/test/CodeGen/MIR/X86/machine-instructions.mir
Original file line number Diff line number Diff line change
@@ -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
...
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/MIR/X86/unknown-instruction.mir
Original file line number Diff line number Diff line change
@@ -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
...

0 comments on commit 8e0a1b4

Please sign in to comment.