llvm.org GIT mirror llvm / 328f462
MIR Serialization: print and parse LLVM IR using MIR format. This commit is the initial commit for the MIR serialization project. It creates a new library under CodeGen called 'MIR'. This new library adds a new machine function pass that prints out the LLVM IR using the MIR format. This pass is then added as a last pass when a 'stop-after' option is used in llc. The new library adds the initial functionality for parsing of MIR files as well. This commit also extends the llc tool so that it can recognize and parse MIR input files. Reviewers: Duncan P. N. Exon Smith, Matthias Braun, Philip Reames Differential Revision: http://reviews.llvm.org/D9616 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237708 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Lorenz 5 years ago
21 changed file(s) with 417 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
0 //===- MIRParser.h - MIR serialization format parser ----------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This MIR serialization library is currently a work in progress. It can't
10 // serialize machine functions at this time.
11 //
12 // This file declares the functions that parse the MIR serialization format
13 // files.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #ifndef LLVM_CODEGEN_MIR_MIRPARSER_H
18 #define LLVM_CODEGEN_MIR_MIRPARSER_H
19
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include
24
25 namespace llvm {
26
27 class SMDiagnostic;
28
29 /// This function is the main interface to the MIR serialization format parser.
30 ///
31 /// It reads a YAML file that has an optional LLVM IR and returns an LLVM
32 /// module.
33 /// \param Filename - The name of the file to parse.
34 /// \param Error - Error result info.
35 /// \param Context - Context in which to allocate globals info.
36 std::unique_ptr parseMIRFile(StringRef Filename, SMDiagnostic &Error,
37 LLVMContext &Context);
38
39 /// This function is another interface to the MIR serialization format parser.
40 ///
41 /// It parses the optional LLVM IR in the given buffer, and returns an LLVM
42 /// module.
43 /// \param Contents - The MemoryBuffer containing the machine level IR.
44 /// \param Error - Error result info.
45 /// \param Context - Context in which to allocate globals info.
46 std::unique_ptr parseMIR(std::unique_ptr Contents,
47 SMDiagnostic &Error, LLVMContext &Context);
48
49 } // end namespace llvm
50
51 #endif
373373 createMachineFunctionPrinterPass(raw_ostream &OS,
374374 const std::string &Banner ="");
375375
376 /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream
377 /// using the MIR serialization format.
378 MachineFunctionPass *createPrintMIRPass(raw_ostream &OS);
379
376380 /// createCodeGenPreparePass - Transform the code to expose more pattern
377381 /// matching during instruction selection.
378382 FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
486490
487491 /// MachineFunctionPrinterPass - This pass prints out MachineInstr's.
488492 extern char &MachineFunctionPrinterPassID;
493
494 /// MIRPrintingPass - this pass prints out the LLVM IR using the MIR
495 /// serialization format.
496 extern char &MIRPrintingPassID;
489497
490498 /// TailDuplicate - Duplicate blocks with unconditional branches
491499 /// into tails of their predecessors.
288288 void initializeSLPVectorizerPass(PassRegistry&);
289289 void initializeBBVectorizePass(PassRegistry&);
290290 void initializeMachineFunctionPrinterPassPass(PassRegistry&);
291 void initializeMIRPrintingPassPass(PassRegistry&);
291292 void initializeStackMapLivenessPass(PassRegistry&);
292293 void initializeMachineCombinerPass(PassRegistry &);
293294 void initializeLoadCombinePass(PassRegistry&);
10881088 // if those templated things could be made friends.
10891089 bool setCurrentDocument();
10901090 bool nextDocument();
1091
1092 /// Returns the current node that's being parsed by the YAML Parser.
1093 const Node *getCurrentNode() const;
10911094
10921095 private:
10931096 llvm::SourceMgr SrcMgr; // must be before Strm
127127
128128 add_subdirectory(SelectionDAG)
129129 add_subdirectory(AsmPrinter)
130 add_subdirectory(MIR)
1515 ;===------------------------------------------------------------------------===;
1616
1717 [common]
18 subdirectories = AsmPrinter SelectionDAG
18 subdirectories = AsmPrinter SelectionDAG MIR
1919
2020 [component_0]
2121 type = Library
2222 name = CodeGen
2323 parent = Libraries
24 required_libraries = Analysis Core MC Scalar Support Target TransformUtils
24 required_libraries = Analysis Core MC Scalar Support Target TransformUtils MIR
149149 return true;
150150
151151 if (StopAfter) {
152 // FIXME: The intent is that this should eventually write out a YAML file,
153 // containing the LLVM IR, the machine-level IR (when stopping after a
154 // machine-level pass), and whatever other information is needed to
155 // deserialize the code and resume compilation. For now, just write the
156 // LLVM IR.
157 PM.add(createPrintModulePass(Out));
152 PM.add(createPrintMIRPass(outs()));
158153 return false;
159154 }
160155
0 add_llvm_library(LLVMMIR
1 MIRPrinter.cpp
2 MIRPrintingPass.cpp
3 MIRParser.cpp
4 )
5
6 add_dependencies(LLVMMIR intrinsics_gen)
0 ;===- ./lib/CodeGen/MIR/LLVMBuild.txt --------------------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = MIR
20 parent = CodeGen
21 required_libraries = Core Support Target AsmParser
0 //===- MIRParser.cpp - MIR serialization format parser implementation -----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the class that parses the optional LLVM IR and machine
10 // functions that are stored in MIR files.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/CodeGen/MIR/MIRParser.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/AsmParser/Parser.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Support/SMLoc.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include
24
25 using namespace llvm;
26
27 namespace {
28
29 /// This class implements the parsing of LLVM IR that's embedded inside a MIR
30 /// file.
31 class MIRParserImpl {
32 SourceMgr SM;
33 StringRef Filename;
34 LLVMContext &Context;
35
36 public:
37 MIRParserImpl(std::unique_ptr Contents, StringRef Filename,
38 LLVMContext &Context);
39
40 /// Try to parse the optional LLVM module in the MIR file.
41 ///
42 /// Return null if an error occurred while parsing the LLVM module.
43 std::unique_ptr parseLLVMModule(SMDiagnostic &Error);
44 };
45
46 } // end anonymous namespace
47
48 MIRParserImpl::MIRParserImpl(std::unique_ptr Contents,
49 StringRef Filename, LLVMContext &Context)
50 : SM(), Filename(Filename), Context(Context) {
51 SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
52 }
53
54 std::unique_ptr MIRParserImpl::parseLLVMModule(SMDiagnostic &Error) {
55 yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer());
56
57 // Parse the block scalar manually so that we can return unique pointer
58 // without having to go trough YAML traits.
59 if (In.setCurrentDocument()) {
60 if (const auto *BSN =
61 dyn_cast_or_null(In.getCurrentNode())) {
62 return parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
63 Context);
64 }
65 }
66
67 // Create an new, empty module.
68 return llvm::make_unique(Filename, Context);
69 }
70
71 std::unique_ptr llvm::parseMIRFile(StringRef Filename,
72 SMDiagnostic &Error,
73 LLVMContext &Context) {
74 auto FileOrErr = MemoryBuffer::getFile(Filename);
75 if (std::error_code EC = FileOrErr.getError()) {
76 Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
77 "Could not open input file: " + EC.message());
78 return std::unique_ptr();
79 }
80 return parseMIR(std::move(FileOrErr.get()), Error, Context);
81 }
82
83 std::unique_ptr llvm::parseMIR(std::unique_ptr Contents,
84 SMDiagnostic &Error,
85 LLVMContext &Context) {
86 auto Filename = Contents->getBufferIdentifier();
87 MIRParserImpl Parser(std::move(Contents), Filename, Context);
88 return Parser.parseLLVMModule(Error);
89 }
0 //===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the class that prints out the LLVM IR and machine
10 // functions using the MIR serialization format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "MIRPrinter.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/YAMLTraits.h"
20
21 using namespace llvm;
22
23 namespace {
24
25 /// This class prints out the LLVM IR using the MIR serialization format and
26 /// YAML I/O.
27 class MIRPrinter {
28 raw_ostream &OS;
29
30 public:
31 MIRPrinter(raw_ostream &OS);
32
33 void printModule(const Module &Mod);
34 };
35
36 } // end anonymous namespace
37
38 namespace llvm {
39 namespace yaml {
40
41 /// This struct serializes the LLVM IR module.
42 template <> struct BlockScalarTraits {
43 static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
44 Mod.print(OS, nullptr);
45 }
46 static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
47 llvm_unreachable("LLVM Module is supposed to be parsed separately");
48 return "";
49 }
50 };
51
52 } // end namespace yaml
53 } // end namespace llvm
54
55 MIRPrinter::MIRPrinter(raw_ostream &OS) : OS(OS) {}
56
57 void MIRPrinter::printModule(const Module &Mod) {
58 yaml::Output Out(OS);
59 Out << const_cast(Mod);
60 }
61
62 void llvm::printMIR(raw_ostream &OS, const Module &Mod) {
63 MIRPrinter Printer(OS);
64 Printer.printModule(Mod);
65 }
0 //===- MIRPrinter.h - MIR serialization format printer --------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the function that prints out the LLVM IR using the MIR
10 // serialization format.
11 // TODO: Print out machine functions.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_LIB_CODEGEN_MIR_MIRPRINTER_H
16 #define LLVM_LIB_CODEGEN_MIR_MIRPRINTER_H
17
18 namespace llvm {
19
20 class Module;
21 class raw_ostream;
22
23 /// Print LLVM IR using the MIR serialization format to the given output stream.
24 void printMIR(raw_ostream &OS, const Module &Mod);
25
26 } // end namespace llvm
27
28 #endif
0 //===- MIRPrintingPass.cpp - Pass that prints out using the MIR format ----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a pass that prints out the LLVM module using the MIR
10 // serialization format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "MIRPrinter.h"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/raw_ostream.h"
20
21 using namespace llvm;
22
23 namespace {
24
25 /// This pass prints out the LLVM IR to an output stream using the MIR
26 /// serialization format.
27 struct MIRPrintingPass : public MachineFunctionPass {
28 static char ID;
29 raw_ostream &OS;
30
31 MIRPrintingPass() : MachineFunctionPass(ID), OS(dbgs()) {}
32 MIRPrintingPass(raw_ostream &OS) : MachineFunctionPass(ID), OS(OS) {}
33
34 const char *getPassName() const override { return "MIR Printing Pass"; }
35
36 void getAnalysisUsage(AnalysisUsage &AU) const override {
37 AU.setPreservesAll();
38 MachineFunctionPass::getAnalysisUsage(AU);
39 }
40
41 virtual bool runOnMachineFunction(MachineFunction &MF) override {
42 // TODO: Print out the machine function.
43 return false;
44 }
45
46 virtual bool doFinalization(Module &M) override {
47 printMIR(OS, M);
48 return false;
49 }
50 };
51
52 char MIRPrintingPass::ID = 0;
53
54 } // end anonymous namespace
55
56 char &llvm::MIRPrintingPassID = MIRPrintingPass::ID;
57 INITIALIZE_PASS(MIRPrintingPass, "mir-printer", "MIR Printer", false, false)
58
59 namespace llvm {
60
61 MachineFunctionPass *createPrintMIRPass(raw_ostream &OS) {
62 return new MIRPrintingPass(OS);
63 }
64
65 } // end namespace llvm
0 ##===- lib/CodeGen/MIR/Makefile ----------------------------*- Makefile -*-===##
1 #
2 # The LLVM Compiler Infrastructure
3 #
4 # This file is distributed under the University of Illinois Open Source
5 # License. See LICENSE.TXT for details.
6 #
7 ##===----------------------------------------------------------------------===##
8
9 LEVEL = ../../..
10 LIBRARYNAME = LLVMMIR
11
12 include $(LEVEL)/Makefile.common
88
99 LEVEL = ../..
1010 LIBRARYNAME = LLVMCodeGen
11 PARALLEL_DIRS = SelectionDAG AsmPrinter
11 PARALLEL_DIRS = SelectionDAG AsmPrinter MIR
1212 BUILD_ARCHIVE = 1
1313
1414 include $(LEVEL)/Makefile.common
9494
9595 bool Input::nextDocument() {
9696 return ++DocIterator != Strm->end();
97 }
98
99 const Node *Input::getCurrentNode() const {
100 return CurrentNode ? CurrentNode->_node : nullptr;
97101 }
98102
99103 bool Input::mapTag(StringRef Tag, bool Default) {
0 ; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP
11 ; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START
22
3 ; STOP: -loop-reduce -print-module
3 ; STOP: -loop-reduce
44 ; STOP: Loop Strength Reduction
55 ; STOP-NEXT: Machine Function Analysis
6 ; STOP-NEXT: MIR Printing Pass
67
78 ; START: -machine-branch-prob -gc-lowering
89 ; START: FunctionPass Manager
0 config.suffixes = ['.mir']
1
0 # RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
1 # This test ensures that the LLVM IR that's embedded with MIR is parsed
2 # correctly.
3
4 --- |
5 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64-apple-darwin14.3.0"
7
8 ; CHECK: define i32 @foo(i32 %x, i32 %y)
9 ; CHECK: %z = alloca i32, align 4
10 ; CHECK: store i32 %x, i32* %z, align 4
11 ; CHECK: br label %Test
12 ; CHECK: Test:
13 ; CHECK: %m = load i32, i32* %z, align 4
14 ; CHECK: %cond = icmp eq i32 %y, %m
15 ; CHECK: br i1 %cond, label %IfEqual, label %IfUnequal
16 ; CHECK: IfEqual:
17 ; CHECK: ret i32 1
18 ; CHECK: IfUnequal:
19 ; CHECK: ret i32 0
20 define i32 @foo(i32 %x, i32 %y) {
21 %z = alloca i32, align 4
22 store i32 %x, i32* %z, align 4
23 br label %Test
24 Test:
25 %m = load i32, i32* %z, align 4
26 %cond = icmp eq i32 %y, %m
27 br i1 %cond, label %IfEqual, label %IfUnequal
28 IfEqual:
29 ret i32 1
30 IfUnequal:
31 ret i32 0
32 }
33
34 ...
0 # RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s
1 # This test ensures that the MIR parser accepts files without the LLVM IR.
2
3 ---
4 ...
1919 #include "llvm/CodeGen/CommandFlags.h"
2020 #include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
2121 #include "llvm/CodeGen/LinkAllCodegenComponents.h"
22 #include "llvm/CodeGen/MIR/MIRParser.h"
2223 #include "llvm/IR/DataLayout.h"
2324 #include "llvm/IR/IRPrintingPasses.h"
2425 #include "llvm/IR/LLVMContext.h"
108109 StringRef IFN = InputFilename;
109110 if (IFN.endswith(".bc") || IFN.endswith(".ll"))
110111 OutputFilename = IFN.drop_back(3);
112 else if (IFN.endswith(".mir"))
113 OutputFilename = IFN.drop_back(4);
111114 else
112115 OutputFilename = IFN;
113116
213216
214217 // If user just wants to list available options, skip module loading
215218 if (!SkipModule) {
216 M = parseIRFile(InputFilename, Err, Context);
219 if (StringRef(InputFilename).endswith_lower(".mir"))
220 M = parseMIRFile(InputFilename, Err, Context);
221 else
222 M = parseIRFile(InputFilename, Err, Context);
217223 if (!M) {
218224 Err.print(argv[0], errs());
219225 return 1;