Home | History | Annotate | Line # | Download | only in IRReader
      1 //===---- IRReader.cpp - Reader for LLVM IR files -------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/IRReader/IRReader.h"
     10 #include "llvm-c/IRReader.h"
     11 #include "llvm/AsmParser/Parser.h"
     12 #include "llvm/Bitcode/BitcodeReader.h"
     13 #include "llvm/IR/LLVMContext.h"
     14 #include "llvm/IR/Module.h"
     15 #include "llvm/Support/MemoryBuffer.h"
     16 #include "llvm/Support/SourceMgr.h"
     17 #include "llvm/Support/Timer.h"
     18 #include "llvm/Support/raw_ostream.h"
     19 #include <system_error>
     20 
     21 using namespace llvm;
     22 
     23 namespace llvm {
     24   extern bool TimePassesIsEnabled;
     25 }
     26 
     27 const char TimeIRParsingGroupName[] = "irparse";
     28 const char TimeIRParsingGroupDescription[] = "LLVM IR Parsing";
     29 const char TimeIRParsingName[] = "parse";
     30 const char TimeIRParsingDescription[] = "Parse IR";
     31 
     32 std::unique_ptr<Module>
     33 llvm::getLazyIRModule(std::unique_ptr<MemoryBuffer> Buffer, SMDiagnostic &Err,
     34                       LLVMContext &Context, bool ShouldLazyLoadMetadata) {
     35   if (isBitcode((const unsigned char *)Buffer->getBufferStart(),
     36                 (const unsigned char *)Buffer->getBufferEnd())) {
     37     Expected<std::unique_ptr<Module>> ModuleOrErr = getOwningLazyBitcodeModule(
     38         std::move(Buffer), Context, ShouldLazyLoadMetadata);
     39     if (Error E = ModuleOrErr.takeError()) {
     40       handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
     41         Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error,
     42                            EIB.message());
     43       });
     44       return nullptr;
     45     }
     46     return std::move(ModuleOrErr.get());
     47   }
     48 
     49   return parseAssembly(Buffer->getMemBufferRef(), Err, Context);
     50 }
     51 
     52 std::unique_ptr<Module> llvm::getLazyIRFileModule(StringRef Filename,
     53                                                   SMDiagnostic &Err,
     54                                                   LLVMContext &Context,
     55                                                   bool ShouldLazyLoadMetadata) {
     56   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
     57       MemoryBuffer::getFileOrSTDIN(Filename);
     58   if (std::error_code EC = FileOrErr.getError()) {
     59     Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
     60                        "Could not open input file: " + EC.message());
     61     return nullptr;
     62   }
     63 
     64   return getLazyIRModule(std::move(FileOrErr.get()), Err, Context,
     65                          ShouldLazyLoadMetadata);
     66 }
     67 
     68 std::unique_ptr<Module> llvm::parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
     69                                       LLVMContext &Context,
     70                                       DataLayoutCallbackTy DataLayoutCallback) {
     71   NamedRegionTimer T(TimeIRParsingName, TimeIRParsingDescription,
     72                      TimeIRParsingGroupName, TimeIRParsingGroupDescription,
     73                      TimePassesIsEnabled);
     74   if (isBitcode((const unsigned char *)Buffer.getBufferStart(),
     75                 (const unsigned char *)Buffer.getBufferEnd())) {
     76     Expected<std::unique_ptr<Module>> ModuleOrErr =
     77         parseBitcodeFile(Buffer, Context, DataLayoutCallback);
     78     if (Error E = ModuleOrErr.takeError()) {
     79       handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
     80         Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
     81                            EIB.message());
     82       });
     83       return nullptr;
     84     }
     85     return std::move(ModuleOrErr.get());
     86   }
     87 
     88   return parseAssembly(Buffer, Err, Context, nullptr, DataLayoutCallback);
     89 }
     90 
     91 std::unique_ptr<Module>
     92 llvm::parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
     93                   DataLayoutCallbackTy DataLayoutCallback) {
     94   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
     95       MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
     96   if (std::error_code EC = FileOrErr.getError()) {
     97     Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
     98                        "Could not open input file: " + EC.message());
     99     return nullptr;
    100   }
    101 
    102   return parseIR(FileOrErr.get()->getMemBufferRef(), Err, Context,
    103                  DataLayoutCallback);
    104 }
    105 
    106 //===----------------------------------------------------------------------===//
    107 // C API.
    108 //===----------------------------------------------------------------------===//
    109 
    110 LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef,
    111                               LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
    112                               char **OutMessage) {
    113   SMDiagnostic Diag;
    114 
    115   std::unique_ptr<MemoryBuffer> MB(unwrap(MemBuf));
    116   *OutM =
    117       wrap(parseIR(MB->getMemBufferRef(), Diag, *unwrap(ContextRef)).release());
    118 
    119   if(!*OutM) {
    120     if (OutMessage) {
    121       std::string buf;
    122       raw_string_ostream os(buf);
    123 
    124       Diag.print(nullptr, os, false);
    125       os.flush();
    126 
    127       *OutMessage = strdup(buf.c_str());
    128     }
    129     return 1;
    130   }
    131 
    132   return 0;
    133 }
    134