a0de3715bb563dec4ec4ae8c96525dde017d4d09
[oota-llvm.git] / lib / CodeGen / MIRParser / MIRParser.cpp
1 //===- MIRParser.cpp - MIR serialization format 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 class that parses the optional LLVM IR and machine
11 // functions that are stored in MIR files.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/CodeGen/MIRParser/MIRParser.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/AsmParser/Parser.h"
19 #include "llvm/CodeGen/MIRYamlMapping.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Support/SMLoc.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include <memory>
26
27 using namespace llvm;
28
29 namespace {
30
31 /// This class implements the parsing of LLVM IR that's embedded inside a MIR
32 /// file.
33 class MIRParserImpl {
34   SourceMgr SM;
35   StringRef Filename;
36   LLVMContext &Context;
37
38 public:
39   MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
40                 LLVMContext &Context);
41
42   /// Try to parse the optional LLVM module and the machine functions in the MIR
43   /// file.
44   ///
45   /// Return null if an error occurred.
46   std::unique_ptr<Module> parse(SMDiagnostic &Error);
47
48   /// Parse the machine function in the current YAML document.
49   ///
50   /// Return true if an error occurred.
51   bool parseMachineFunction(yaml::Input &In);
52 };
53
54 } // end anonymous namespace
55
56 MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
57                              StringRef Filename, LLVMContext &Context)
58     : SM(), Filename(Filename), Context(Context) {
59   SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
60 }
61
62 static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
63   *reinterpret_cast<SMDiagnostic *>(Context) = Diag;
64 }
65
66 std::unique_ptr<Module> MIRParserImpl::parse(SMDiagnostic &Error) {
67   yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
68                  /*Ctxt=*/nullptr, handleYAMLDiag, &Error);
69
70   if (!In.setCurrentDocument()) {
71     if (!Error.getMessage().empty())
72       return nullptr;
73     // Create an empty module when the MIR file is empty.
74     return llvm::make_unique<Module>(Filename, Context);
75   }
76
77   std::unique_ptr<Module> M;
78   // Parse the block scalar manually so that we can return unique pointer
79   // without having to go trough YAML traits.
80   if (const auto *BSN =
81           dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
82     M = parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
83                       Context);
84     if (!M)
85       return M;
86     In.nextDocument();
87     if (!In.setCurrentDocument())
88       return M;
89   } else {
90     // Create an new, empty module.
91     M = llvm::make_unique<Module>(Filename, Context);
92   }
93
94   // Parse the machine functions.
95   do {
96     if (parseMachineFunction(In))
97       return nullptr;
98     In.nextDocument();
99   } while (In.setCurrentDocument());
100
101   return M;
102 }
103
104 bool MIRParserImpl::parseMachineFunction(yaml::Input &In) {
105   yaml::MachineFunction MF;
106   yaml::yamlize(In, MF, false);
107   if (In.error())
108     return true;
109   // TODO: Initialize the real machine function with the state in the yaml
110   // machine function later on.
111   return false;
112 }
113
114 std::unique_ptr<Module> llvm::parseMIRFile(StringRef Filename,
115                                            SMDiagnostic &Error,
116                                            LLVMContext &Context) {
117   auto FileOrErr = MemoryBuffer::getFile(Filename);
118   if (std::error_code EC = FileOrErr.getError()) {
119     Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
120                          "Could not open input file: " + EC.message());
121     return std::unique_ptr<Module>();
122   }
123   return parseMIR(std::move(FileOrErr.get()), Error, Context);
124 }
125
126 std::unique_ptr<Module> llvm::parseMIR(std::unique_ptr<MemoryBuffer> Contents,
127                                        SMDiagnostic &Error,
128                                        LLVMContext &Context) {
129   auto Filename = Contents->getBufferIdentifier();
130   MIRParserImpl Parser(std::move(Contents), Filename, Context);
131   return Parser.parse(Error);
132 }