e484046b23b55ae83635d1b0f3921d2b3d99391b
[oota-llvm.git] / lib / CodeGen / MIR / 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/MIR/MIRParser.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/AsmParser/Parser.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Support/SMLoc.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/YAMLTraits.h"
24 #include <memory>
25
26 using namespace llvm;
27
28 namespace {
29
30 /// This class implements the parsing of LLVM IR that's embedded inside a MIR
31 /// file.
32 class MIRParserImpl {
33   SourceMgr SM;
34   StringRef Filename;
35   LLVMContext &Context;
36
37 public:
38   MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
39                 LLVMContext &Context);
40
41   /// Try to parse the optional LLVM module in the MIR file.
42   ///
43   /// Return null if an error occurred while parsing the LLVM module.
44   std::unique_ptr<Module> parseLLVMModule(SMDiagnostic &Error);
45 };
46
47 } // end anonymous namespace
48
49 MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
50                              StringRef Filename, LLVMContext &Context)
51     : SM(), Filename(Filename), Context(Context) {
52   SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
53 }
54
55 std::unique_ptr<Module> MIRParserImpl::parseLLVMModule(SMDiagnostic &Error) {
56   yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer());
57
58   // Parse the block scalar manually so that we can return unique pointer
59   // without having to go trough YAML traits.
60   if (In.setCurrentDocument()) {
61     if (const auto *BSN =
62             dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
63       return parseAssembly(MemoryBufferRef(BSN->getValue(), Filename), Error,
64                            Context);
65     }
66   }
67
68   // Create an new, empty module.
69   return llvm::make_unique<Module>(Filename, Context);
70 }
71
72 std::unique_ptr<Module> llvm::parseMIRFile(StringRef Filename,
73                                            SMDiagnostic &Error,
74                                            LLVMContext &Context) {
75   auto FileOrErr = MemoryBuffer::getFile(Filename);
76   if (std::error_code EC = FileOrErr.getError()) {
77     Error = SMDiagnostic(Filename, SourceMgr::DK_Error,
78                          "Could not open input file: " + EC.message());
79     return std::unique_ptr<Module>();
80   }
81   return parseMIR(std::move(FileOrErr.get()), Error, Context);
82 }
83
84 std::unique_ptr<Module> llvm::parseMIR(std::unique_ptr<MemoryBuffer> Contents,
85                                        SMDiagnostic &Error,
86                                        LLVMContext &Context) {
87   auto Filename = Contents->getBufferIdentifier();
88   MIRParserImpl Parser(std::move(Contents), Filename, Context);
89   return Parser.parseLLVMModule(Error);
90 }