Skip to content

Commit 8e0a1b4

Browse files
committedJun 22, 2015
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
1 parent 7f09a98 commit 8e0a1b4

File tree

9 files changed

+236
-4
lines changed

9 files changed

+236
-4
lines changed
 

‎llvm/include/llvm/CodeGen/MIRYamlMapping.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "llvm/Support/YAMLTraits.h"
2323
#include <vector>
2424

25+
LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
26+
2527
namespace llvm {
2628
namespace yaml {
2729

@@ -31,7 +33,8 @@ struct MachineBasicBlock {
3133
bool IsLandingPad = false;
3234
bool AddressTaken = false;
3335
// TODO: Serialize the successors and liveins.
34-
// TODO: Serialize machine instructions.
36+
37+
std::vector<std::string> Instructions;
3538
};
3639

3740
template <> struct MappingTraits<MachineBasicBlock> {
@@ -41,6 +44,7 @@ template <> struct MappingTraits<MachineBasicBlock> {
4144
YamlIO.mapOptional("alignment", MBB.Alignment);
4245
YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad);
4346
YamlIO.mapOptional("addressTaken", MBB.AddressTaken);
47+
YamlIO.mapOptional("instructions", MBB.Instructions);
4448
}
4549
};
4650

‎llvm/lib/CodeGen/MIRParser/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_llvm_library(LLVMMIRParser
2+
MIParser.cpp
23
MIRParser.cpp
34
)
45

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===- MIParser.cpp - Machine instructions parser implementation ----------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file implements the parsing of machine instructions.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "MIParser.h"
15+
#include "llvm/ADT/StringMap.h"
16+
#include "llvm/CodeGen/MachineBasicBlock.h"
17+
#include "llvm/CodeGen/MachineFunction.h"
18+
#include "llvm/CodeGen/MachineInstr.h"
19+
#include "llvm/Support/raw_ostream.h"
20+
#include "llvm/Support/SourceMgr.h"
21+
#include "llvm/Target/TargetSubtargetInfo.h"
22+
#include "llvm/Target/TargetInstrInfo.h"
23+
24+
using namespace llvm;
25+
26+
namespace {
27+
28+
class MIParser {
29+
SourceMgr &SM;
30+
MachineFunction &MF;
31+
SMDiagnostic &Error;
32+
StringRef Source;
33+
/// Maps from instruction names to op codes.
34+
StringMap<unsigned> Names2InstrOpCodes;
35+
36+
public:
37+
MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
38+
StringRef Source);
39+
40+
/// Report an error at the current location with the given message.
41+
///
42+
/// This function always return true.
43+
bool error(const Twine &Msg);
44+
45+
MachineInstr *parse();
46+
47+
private:
48+
void initNames2InstrOpCodes();
49+
50+
/// Try to convert an instruction name to an opcode. Return true if the
51+
/// instruction name is invalid.
52+
bool parseInstrName(StringRef InstrName, unsigned &OpCode);
53+
};
54+
55+
} // end anonymous namespace
56+
57+
MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
58+
StringRef Source)
59+
: SM(SM), MF(MF), Error(Error), Source(Source) {}
60+
61+
bool MIParser::error(const Twine &Msg) {
62+
// TODO: Get the proper location in the MIR file, not just a location inside
63+
// the string.
64+
Error =
65+
SMDiagnostic(SM, SMLoc(), SM.getMemoryBuffer(SM.getMainFileID())
66+
->getBufferIdentifier(),
67+
1, 0, SourceMgr::DK_Error, Msg.str(), Source, None, None);
68+
return true;
69+
}
70+
71+
MachineInstr *MIParser::parse() {
72+
StringRef InstrName = Source;
73+
unsigned OpCode;
74+
if (parseInstrName(InstrName, OpCode)) {
75+
error(Twine("unknown machine instruction name '") + InstrName + "'");
76+
return nullptr;
77+
}
78+
79+
// TODO: Parse the rest of instruction - machine operands, etc.
80+
const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
81+
auto *MI = MF.CreateMachineInstr(MCID, DebugLoc());
82+
return MI;
83+
}
84+
85+
void MIParser::initNames2InstrOpCodes() {
86+
if (!Names2InstrOpCodes.empty())
87+
return;
88+
const auto *TII = MF.getSubtarget().getInstrInfo();
89+
assert(TII && "Expected target instruction info");
90+
for (unsigned I = 0, E = TII->getNumOpcodes(); I < E; ++I)
91+
Names2InstrOpCodes.insert(std::make_pair(StringRef(TII->getName(I)), I));
92+
}
93+
94+
bool MIParser::parseInstrName(StringRef InstrName, unsigned &OpCode) {
95+
initNames2InstrOpCodes();
96+
auto InstrInfo = Names2InstrOpCodes.find(InstrName);
97+
if (InstrInfo == Names2InstrOpCodes.end())
98+
return true;
99+
OpCode = InstrInfo->getValue();
100+
return false;
101+
}
102+
103+
MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
104+
StringRef Src, SMDiagnostic &Error) {
105+
return MIParser(SM, MF, Error, Src).parse();
106+
}

‎llvm/lib/CodeGen/MIRParser/MIParser.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===- MIParser.h - Machine Instructions Parser ---------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file declares the function that parses the machine instructions.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
15+
#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
16+
17+
#include "llvm/ADT/StringRef.h"
18+
19+
namespace llvm {
20+
21+
class MachineInstr;
22+
class MachineFunction;
23+
class SMDiagnostic;
24+
class SourceMgr;
25+
26+
MachineInstr *parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
27+
StringRef Src, SMDiagnostic &Error);
28+
29+
} // end namespace llvm
30+
31+
#endif

‎llvm/lib/CodeGen/MIRParser/MIRParser.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "llvm/CodeGen/MIRParser/MIRParser.h"
16+
#include "MIParser.h"
1617
#include "llvm/ADT/StringRef.h"
1718
#include "llvm/ADT/StringMap.h"
1819
#include "llvm/ADT/STLExtras.h"
@@ -79,7 +80,7 @@ class MIRParserImpl {
7980
/// Initialize the machine basic block using it's YAML representation.
8081
///
8182
/// Return true if an error occurred.
82-
bool initializeMachineBasicBlock(MachineBasicBlock &MBB,
83+
bool initializeMachineBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB,
8384
const yaml::MachineBasicBlock &YamlMBB);
8485

8586
private:
@@ -218,18 +219,29 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
218219
}
219220
auto *MBB = MF.CreateMachineBasicBlock(BB);
220221
MF.insert(MF.end(), MBB);
221-
if (initializeMachineBasicBlock(*MBB, YamlMBB))
222+
if (initializeMachineBasicBlock(MF, *MBB, YamlMBB))
222223
return true;
223224
}
224225
return false;
225226
}
226227

227228
bool MIRParserImpl::initializeMachineBasicBlock(
228-
MachineBasicBlock &MBB, const yaml::MachineBasicBlock &YamlMBB) {
229+
MachineFunction &MF, MachineBasicBlock &MBB,
230+
const yaml::MachineBasicBlock &YamlMBB) {
229231
MBB.setAlignment(YamlMBB.Alignment);
230232
if (YamlMBB.AddressTaken)
231233
MBB.setHasAddressTaken();
232234
MBB.setIsLandingPad(YamlMBB.IsLandingPad);
235+
// Parse the instructions.
236+
for (const auto &MISource : YamlMBB.Instructions) {
237+
SMDiagnostic Error;
238+
if (auto *MI = parseMachineInstr(SM, MF, MISource, Error)) {
239+
MBB.insert(MBB.end(), MI);
240+
continue;
241+
}
242+
reportDiagnostic(Error);
243+
return true;
244+
}
233245
return false;
234246
}
235247

‎llvm/lib/CodeGen/MIRPrinter.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/Support/MemoryBuffer.h"
2222
#include "llvm/Support/raw_ostream.h"
2323
#include "llvm/Support/YAMLTraits.h"
24+
#include "llvm/Target/TargetInstrInfo.h"
25+
#include "llvm/Target/TargetSubtargetInfo.h"
2426

2527
using namespace llvm;
2628

@@ -39,6 +41,17 @@ class MIRPrinter {
3941
void convert(yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB);
4042
};
4143

44+
/// This class prints out the machine instructions using the MIR serialization
45+
/// format.
46+
class MIPrinter {
47+
raw_ostream &OS;
48+
49+
public:
50+
MIPrinter(raw_ostream &OS) : OS(OS) {}
51+
52+
void print(const MachineInstr &MI);
53+
};
54+
4255
} // end anonymous namespace
4356

4457
namespace llvm {
@@ -83,6 +96,25 @@ void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB,
8396
YamlMBB.Alignment = MBB.getAlignment();
8497
YamlMBB.AddressTaken = MBB.hasAddressTaken();
8598
YamlMBB.IsLandingPad = MBB.isLandingPad();
99+
100+
// Print the machine instructions.
101+
YamlMBB.Instructions.reserve(MBB.size());
102+
std::string Str;
103+
for (const auto &MI : MBB) {
104+
raw_string_ostream StrOS(Str);
105+
MIPrinter(StrOS).print(MI);
106+
YamlMBB.Instructions.push_back(StrOS.str());
107+
Str.clear();
108+
}
109+
}
110+
111+
void MIPrinter::print(const MachineInstr &MI) {
112+
const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
113+
const auto *TII = SubTarget.getInstrInfo();
114+
assert(TII && "Expected target instruction info");
115+
116+
OS << TII->getName(MI.getOpcode());
117+
// TODO: Print the instruction flags, machine operands, machine mem operands.
86118
}
87119

88120
void llvm::printMIR(raw_ostream &OS, const Module &M) {
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if not 'X86' in config.root.targets:
2+
config.unsupported = True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
2+
# This test ensures that the MIR parser parses X86 machine instructions
3+
# correctly.
4+
5+
--- |
6+
7+
define i32 @inc(i32 %a) {
8+
entry:
9+
%b = mul i32 %a, 11
10+
ret i32 %b
11+
}
12+
13+
...
14+
---
15+
# CHECK: name: inc
16+
name: inc
17+
body:
18+
- name: entry
19+
instructions:
20+
# CHECK: - IMUL32rri8
21+
# CHECK-NEXT: - RETQ
22+
- IMUL32rri8
23+
- RETQ
24+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
2+
# This test ensures that an error is reported when an unknown instruction is
3+
# encountered.
4+
5+
--- |
6+
7+
define i32 @foo() {
8+
entry:
9+
ret i32 0
10+
}
11+
12+
...
13+
---
14+
name: foo
15+
body:
16+
- name: entry
17+
instructions:
18+
# CHECK: 1:1: unknown machine instruction name 'retJust0'
19+
- retJust0
20+
...

0 commit comments

Comments
 (0)
Please sign in to comment.