1249259Sdim//===---- IRReader.cpp - Reader for LLVM IR files -------------------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim
10249259Sdim#include "llvm/IRReader/IRReader.h"
11276479Sdim#include "llvm-c/Core.h"
12276479Sdim#include "llvm-c/IRReader.h"
13276479Sdim#include "llvm/AsmParser/Parser.h"
14249259Sdim#include "llvm/Bitcode/ReaderWriter.h"
15261991Sdim#include "llvm/IR/LLVMContext.h"
16261991Sdim#include "llvm/IR/Module.h"
17249259Sdim#include "llvm/Support/MemoryBuffer.h"
18249259Sdim#include "llvm/Support/SourceMgr.h"
19249259Sdim#include "llvm/Support/Timer.h"
20261991Sdim#include "llvm/Support/raw_ostream.h"
21276479Sdim#include <system_error>
22249259Sdim
23249259Sdimusing namespace llvm;
24249259Sdim
25249259Sdimnamespace llvm {
26249259Sdim  extern bool TimePassesIsEnabled;
27249259Sdim}
28249259Sdim
29261991Sdimstatic const char *const TimeIRParsingGroupName = "LLVM IR Parsing";
30261991Sdimstatic const char *const TimeIRParsingName = "Parse IR";
31249259Sdim
32280031Sdimstatic std::unique_ptr<Module>
33280031SdimgetLazyIRModule(std::unique_ptr<MemoryBuffer> Buffer, SMDiagnostic &Err,
34296417Sdim                LLVMContext &Context, bool ShouldLazyLoadMetadata) {
35249259Sdim  if (isBitcode((const unsigned char *)Buffer->getBufferStart(),
36249259Sdim                (const unsigned char *)Buffer->getBufferEnd())) {
37296417Sdim    ErrorOr<std::unique_ptr<Module>> ModuleOrErr = getLazyBitcodeModule(
38296417Sdim        std::move(Buffer), Context, ShouldLazyLoadMetadata);
39276479Sdim    if (std::error_code EC = ModuleOrErr.getError()) {
40249259Sdim      Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error,
41276479Sdim                         EC.message());
42276479Sdim      return nullptr;
43249259Sdim    }
44288943Sdim    return std::move(ModuleOrErr.get());
45249259Sdim  }
46249259Sdim
47280031Sdim  return parseAssembly(Buffer->getMemBufferRef(), Err, Context);
48249259Sdim}
49249259Sdim
50280031Sdimstd::unique_ptr<Module> llvm::getLazyIRFileModule(StringRef Filename,
51280031Sdim                                                  SMDiagnostic &Err,
52296417Sdim                                                  LLVMContext &Context,
53296417Sdim                                                  bool ShouldLazyLoadMetadata) {
54276479Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
55276479Sdim      MemoryBuffer::getFileOrSTDIN(Filename);
56276479Sdim  if (std::error_code EC = FileOrErr.getError()) {
57249259Sdim    Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
58276479Sdim                       "Could not open input file: " + EC.message());
59276479Sdim    return nullptr;
60249259Sdim  }
61249259Sdim
62296417Sdim  return getLazyIRModule(std::move(FileOrErr.get()), Err, Context,
63296417Sdim                         ShouldLazyLoadMetadata);
64249259Sdim}
65249259Sdim
66280031Sdimstd::unique_ptr<Module> llvm::parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
67280031Sdim                                      LLVMContext &Context) {
68249259Sdim  NamedRegionTimer T(TimeIRParsingName, TimeIRParsingGroupName,
69249259Sdim                     TimePassesIsEnabled);
70280031Sdim  if (isBitcode((const unsigned char *)Buffer.getBufferStart(),
71280031Sdim                (const unsigned char *)Buffer.getBufferEnd())) {
72288943Sdim    ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
73288943Sdim        parseBitcodeFile(Buffer, Context);
74280031Sdim    if (std::error_code EC = ModuleOrErr.getError()) {
75280031Sdim      Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
76276479Sdim                         EC.message());
77280031Sdim      return nullptr;
78280031Sdim    }
79288943Sdim    return std::move(ModuleOrErr.get());
80249259Sdim  }
81249259Sdim
82280031Sdim  return parseAssembly(Buffer, Err, Context);
83249259Sdim}
84249259Sdim
85280031Sdimstd::unique_ptr<Module> llvm::parseIRFile(StringRef Filename, SMDiagnostic &Err,
86280031Sdim                                          LLVMContext &Context) {
87276479Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
88276479Sdim      MemoryBuffer::getFileOrSTDIN(Filename);
89276479Sdim  if (std::error_code EC = FileOrErr.getError()) {
90249259Sdim    Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
91276479Sdim                       "Could not open input file: " + EC.message());
92276479Sdim    return nullptr;
93249259Sdim  }
94249259Sdim
95280031Sdim  return parseIR(FileOrErr.get()->getMemBufferRef(), Err, Context);
96249259Sdim}
97261991Sdim
98261991Sdim//===----------------------------------------------------------------------===//
99261991Sdim// C API.
100261991Sdim//===----------------------------------------------------------------------===//
101261991Sdim
102261991SdimLLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef,
103261991Sdim                              LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
104261991Sdim                              char **OutMessage) {
105261991Sdim  SMDiagnostic Diag;
106261991Sdim
107276479Sdim  std::unique_ptr<MemoryBuffer> MB(unwrap(MemBuf));
108280031Sdim  *OutM =
109280031Sdim      wrap(parseIR(MB->getMemBufferRef(), Diag, *unwrap(ContextRef)).release());
110261991Sdim
111261991Sdim  if(!*OutM) {
112261991Sdim    if (OutMessage) {
113261991Sdim      std::string buf;
114261991Sdim      raw_string_ostream os(buf);
115261991Sdim
116276479Sdim      Diag.print(nullptr, os, false);
117261991Sdim      os.flush();
118261991Sdim
119261991Sdim      *OutMessage = strdup(buf.c_str());
120261991Sdim    }
121261991Sdim    return 1;
122261991Sdim  }
123261991Sdim
124261991Sdim  return 0;
125261991Sdim}
126