llvm.org GIT mirror llvm / d986612
MIR Serialization: Serialize global address machine operands. This commit serializes the global address machine operands. This commit doesn't serialize the operand's offset and target flags, it serializes only the global value reference. Reviewers: Duncan P. N. Exon Smith Differential Revision: http://reviews.llvm.org/D10671 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240851 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Lorenz 5 years ago
9 changed file(s) with 199 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
105105 return C;
106106 }
107107
108 static Cursor lexGlobalValue(Cursor C, MIToken &Token) {
109 auto Range = C;
110 C.advance(); // Skip the '@'
111 // TODO: add support for quoted names.
112 if (!isdigit(C.peek())) {
113 while (isIdentifierChar(C.peek()))
114 C.advance();
115 Token = MIToken(MIToken::NamedGlobalValue, Range.upto(C),
116 /*StringOffset=*/1); // Drop the '@'
117 return C;
118 }
119 auto NumberRange = C;
120 while (isdigit(C.peek()))
121 C.advance();
122 Token =
123 MIToken(MIToken::GlobalValue, Range.upto(C), APSInt(NumberRange.upto(C)));
124 return C;
125 }
126
108127 static Cursor lexIntegerLiteral(Cursor C, MIToken &Token) {
109128 auto Range = C;
110129 C.advance();
150169 return lexMachineBasicBlock(C, Token, ErrorCallback).remaining();
151170 return lexPercent(C, Token).remaining();
152171 }
172 if (Char == '@')
173 return lexGlobalValue(C, Token).remaining();
153174 if (isdigit(Char) || (Char == '-' && isdigit(C.peek(1))))
154175 return lexIntegerLiteral(C, Token).remaining();
155176 MIToken::TokenKind Kind = symbolToken(Char);
3939 Identifier,
4040 NamedRegister,
4141 MachineBasicBlock,
42 NamedGlobalValue,
43 GlobalValue,
4244
4345 // Other tokens
4446 IntegerLiteral
7779 const APSInt &integerValue() const { return IntVal; }
7880
7981 bool hasIntegerValue() const {
80 return Kind == IntegerLiteral || Kind == MachineBasicBlock;
82 return Kind == IntegerLiteral || Kind == MachineBasicBlock ||
83 Kind == GlobalValue;
8184 }
8285 };
8386
1313 #include "MIParser.h"
1414 #include "MILexer.h"
1515 #include "llvm/ADT/StringMap.h"
16 #include "llvm/AsmParser/SlotMapping.h"
1617 #include "llvm/CodeGen/MachineBasicBlock.h"
1718 #include "llvm/CodeGen/MachineFunction.h"
1819 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/IR/Module.h"
1921 #include "llvm/Support/raw_ostream.h"
2022 #include "llvm/Support/SourceMgr.h"
2123 #include "llvm/Target/TargetSubtargetInfo.h"
3335 MIToken Token;
3436 /// Maps from basic block numbers to MBBs.
3537 const DenseMap &MBBSlots;
38 /// Maps from indices to unnamed global values and metadata nodes.
39 const SlotMapping &IRSlots;
3640 /// Maps from instruction names to op codes.
3741 StringMap Names2InstrOpCodes;
3842 /// Maps from register names to registers.
4145 public:
4246 MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
4347 StringRef Source,
44 const DenseMap &MBBSlots);
48 const DenseMap &MBBSlots,
49 const SlotMapping &IRSlots);
4550
4651 void lex();
4752
6166 bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
6267 bool parseImmediateOperand(MachineOperand &Dest);
6368 bool parseMBBOperand(MachineOperand &Dest);
69 bool parseGlobalAddressOperand(MachineOperand &Dest);
6470 bool parseMachineOperand(MachineOperand &Dest);
6571
6672 private:
8894
8995 MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
9096 StringRef Source,
91 const DenseMap &MBBSlots)
97 const DenseMap &MBBSlots,
98 const SlotMapping &IRSlots)
9299 : SM(SM), MF(MF), Error(Error), Source(Source), CurrentSource(Source),
93 Token(MIToken::Error, StringRef()), MBBSlots(MBBSlots) {}
100 Token(MIToken::Error, StringRef()), MBBSlots(MBBSlots), IRSlots(IRSlots) {
101 }
94102
95103 void MIParser::lex() {
96104 CurrentSource = lexMIToken(
249257 return false;
250258 }
251259
260 bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) {
261 switch (Token.kind()) {
262 case MIToken::NamedGlobalValue: {
263 auto Name = Token.stringValue();
264 const Module *M = MF.getFunction()->getParent();
265 if (const auto *GV = M->getNamedValue(Name)) {
266 Dest = MachineOperand::CreateGA(GV, /*Offset=*/0);
267 break;
268 }
269 return error(Twine("use of undefined global value '@") + Name + "'");
270 }
271 case MIToken::GlobalValue: {
272 unsigned GVIdx;
273 if (getUnsigned(GVIdx))
274 return true;
275 if (GVIdx >= IRSlots.GlobalValues.size())
276 return error(Twine("use of undefined global value '@") + Twine(GVIdx) +
277 "'");
278 Dest = MachineOperand::CreateGA(IRSlots.GlobalValues[GVIdx],
279 /*Offset=*/0);
280 break;
281 }
282 default:
283 llvm_unreachable("The current token should be a global value");
284 }
285 // TODO: Parse offset and target flags.
286 lex();
287 return false;
288 }
289
252290 bool MIParser::parseMachineOperand(MachineOperand &Dest) {
253291 switch (Token.kind()) {
254292 case MIToken::underscore:
258296 return parseImmediateOperand(Dest);
259297 case MIToken::MachineBasicBlock:
260298 return parseMBBOperand(Dest);
299 case MIToken::GlobalValue:
300 case MIToken::NamedGlobalValue:
301 return parseGlobalAddressOperand(Dest);
261302 case MIToken::Error:
262303 return true;
263304 default:
313354 MachineInstr *
314355 llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF, StringRef Src,
315356 const DenseMap &MBBSlots,
316 SMDiagnostic &Error) {
317 return MIParser(SM, MF, Error, Src, MBBSlots).parse();
318 }
357 const SlotMapping &IRSlots, SMDiagnostic &Error) {
358 return MIParser(SM, MF, Error, Src, MBBSlots, IRSlots).parse();
359 }
2121 class MachineBasicBlock;
2222 class MachineInstr;
2323 class MachineFunction;
24 struct SlotMapping;
2425 class SMDiagnostic;
2526 class SourceMgr;
2627
2728 MachineInstr *
2829 parseMachineInstr(SourceMgr &SM, MachineFunction &MF, StringRef Src,
2930 const DenseMap &MBBSlots,
30 SMDiagnostic &Error);
31 const SlotMapping &IRSlots, SMDiagnostic &Error);
3132
3233 } // end namespace llvm
3334
1818 #include "llvm/ADT/StringMap.h"
1919 #include "llvm/ADT/STLExtras.h"
2020 #include "llvm/AsmParser/Parser.h"
21 #include "llvm/AsmParser/SlotMapping.h"
2122 #include "llvm/CodeGen/MachineFunction.h"
2223 #include "llvm/CodeGen/MachineRegisterInfo.h"
2324 #include "llvm/CodeGen/MIRYamlMapping.h"
4546 StringRef Filename;
4647 LLVMContext &Context;
4748 StringMap> Functions;
49 SlotMapping IRSlots;
4850
4951 public:
5052 MIRParserImpl(std::unique_ptr Contents, StringRef Filename,
156158 dyn_cast_or_null(In.getCurrentNode())) {
157159 SMDiagnostic Error;
158160 M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
159 Context);
161 Context, &IRSlots);
160162 if (!M) {
161163 reportDiagnostic(diagFromLLVMAssemblyDiag(Error, BSN->getSourceRange()));
162164 return M;
262264 // Parse the instructions.
263265 for (const auto &MISource : YamlMBB.Instructions) {
264266 SMDiagnostic Error;
265 if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, MBBSlots, Error)) {
267 if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, MBBSlots, IRSlots,
268 Error)) {
266269 MBB.insert(MBB.end(), MI);
267270 continue;
268271 }
3939 void print(const MachineFunction &MF);
4040
4141 void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
42 void convert(yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB);
42 void convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
43 const MachineBasicBlock &MBB);
4344 };
4445
4546 /// This class prints out the machine instructions using the MIR serialization
4647 /// format.
4748 class MIPrinter {
49 const Module &M;
4850 raw_ostream &OS;
4951
5052 public:
51 MIPrinter(raw_ostream &OS) : OS(OS) {}
53 MIPrinter(const Module &M, raw_ostream &OS) : M(M), OS(OS) {}
5254
5355 void print(const MachineInstr &MI);
5456 void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
8284 convert(YamlMF, MF.getRegInfo());
8385
8486 int I = 0;
87 const auto &M = *MF.getFunction()->getParent();
8588 for (const auto &MBB : MF) {
8689 // TODO: Allow printing of non sequentially numbered MBBs.
8790 // This is currently needed as the basic block references get their index
9194 "Can't print MBBs that aren't sequentially numbered");
9295 (void)I;
9396 yaml::MachineBasicBlock YamlMBB;
94 convert(YamlMBB, MBB);
97 convert(M, YamlMBB, MBB);
9598 YamlMF.BasicBlocks.push_back(YamlMBB);
9699 }
97100 yaml::Output Out(OS);
105108 MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
106109 }
107110
108 void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB,
111 void MIRPrinter::convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
109112 const MachineBasicBlock &MBB) {
110113 assert(MBB.getNumber() >= 0 && "Invalid MBB number");
111114 YamlMBB.ID = (unsigned)MBB.getNumber();
123126 std::string Str;
124127 for (const auto &MI : MBB) {
125128 raw_string_ostream StrOS(Str);
126 MIPrinter(StrOS).print(MI);
129 MIPrinter(M, StrOS).print(MI);
127130 YamlMBB.Instructions.push_back(StrOS.str());
128131 Str.clear();
129132 }
190193 OS << '.' << BB->getName();
191194 }
192195 break;
196 case MachineOperand::MO_GlobalAddress:
197 // FIXME: Make this faster - print as operand will create a slot tracker to
198 // print unnamed values for the whole module every time it's called, which
199 // is inefficient.
200 Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, &M);
201 // TODO: Print offset and target flags.
202 break;
193203 default:
194204 // TODO: Print the other machine operands.
195205 llvm_unreachable("Can't print this machine operand at the moment");
0 # RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
1 # This test ensures that the MIR parser parses global value operands correctly.
2
3 --- |
4
5 @G = external global i32
6 @0 = external global i32
7
8 define i32 @inc() {
9 entry:
10 %a = load i32, i32* @G
11 %b = add i32 %a, 1
12 ret i32 %b
13 }
14
15 define i32 @inc2() {
16 entry:
17 %a = load i32, i32* @0
18 %b = add i32 %a, 1
19 ret i32 %b
20 }
21
22 ...
23 ---
24 # CHECK: name: inc
25 name: inc
26 body:
27 - id: 0
28 name: entry
29 instructions:
30 # CHECK: - '%rax = MOV64rm %rip, 1, _, @G, _'
31 - '%rax = MOV64rm %rip, 1, _, @G, _'
32 - '%eax = MOV32rm %rax, 1, _, 0, _'
33 - '%eax = INC32r %eax'
34 - 'RETQ %eax'
35 ...
36 ---
37 # CHECK: name: inc2
38 name: inc2
39 body:
40 - id: 0
41 name: entry
42 instructions:
43 # CHECK: - '%rax = MOV64rm %rip, 1, _, @0, _'
44 - '%rax = MOV64rm %rip, 1, _, @0, _'
45 - '%eax = MOV32rm %rax, 1, _, 0, _'
46 - '%eax = INC32r %eax'
47 - 'RETQ %eax'
48 ...
0 # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
1 # This test ensures that an error is reported when an invalid global value index
2 # is used.
3
4 --- |
5
6 @0 = external global i32
7
8 define i32 @inc() {
9 entry:
10 %a = load i32, i32* @0
11 %b = add i32 %a, 1
12 ret i32 %b
13 }
14
15 ...
16 ---
17 name: inc
18 body:
19 - id: 0
20 name: entry
21 instructions:
22 # CHECK: [[@LINE+1]]:37: use of undefined global value '@2'
23 - '%rax = MOV64rm %rip, 1, _, @2, _'
24 - '%eax = MOV32rm %rax, 1, _, 0, _'
25 - '%eax = INC32r %eax'
26 - 'RETQ %eax'
27 ...
0 # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
1 # This test ensures that an error is reported when an undefined global value is
2 # used.
3
4 --- |
5
6 @G = external global i32
7
8 define i32 @inc() {
9 entry:
10 %a = load i32, i32* @G
11 %b = add i32 %a, 1
12 ret i32 %b
13 }
14
15 ...
16 ---
17 name: inc
18 body:
19 - id: 0
20 name: entry
21 instructions:
22 # CHECK: [[@LINE+1]]:37: use of undefined global value '@GG'
23 - '%rax = MOV64rm %rip, 1, _, @GG, _'
24 - '%eax = MOV32rm %rax, 1, _, 0, _'
25 - '%eax = INC32r %eax'
26 - 'RETQ %eax'
27 ...