109467b48Spatrick //===---- IRReader.cpp - Reader for LLVM IR files -------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "llvm/IRReader/IRReader.h"
1009467b48Spatrick #include "llvm-c/IRReader.h"
1109467b48Spatrick #include "llvm/AsmParser/Parser.h"
1209467b48Spatrick #include "llvm/Bitcode/BitcodeReader.h"
1309467b48Spatrick #include "llvm/IR/LLVMContext.h"
1409467b48Spatrick #include "llvm/IR/Module.h"
1509467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
1609467b48Spatrick #include "llvm/Support/SourceMgr.h"
1709467b48Spatrick #include "llvm/Support/Timer.h"
1809467b48Spatrick #include "llvm/Support/raw_ostream.h"
19*d415bd75Srobert #include <optional>
2009467b48Spatrick #include <system_error>
2109467b48Spatrick
2209467b48Spatrick using namespace llvm;
2309467b48Spatrick
2409467b48Spatrick namespace llvm {
2509467b48Spatrick extern bool TimePassesIsEnabled;
2609467b48Spatrick }
2709467b48Spatrick
2873471bf0Spatrick const char TimeIRParsingGroupName[] = "irparse";
2973471bf0Spatrick const char TimeIRParsingGroupDescription[] = "LLVM IR Parsing";
3073471bf0Spatrick const char TimeIRParsingName[] = "parse";
3173471bf0Spatrick const char TimeIRParsingDescription[] = "Parse IR";
3209467b48Spatrick
3309467b48Spatrick std::unique_ptr<Module>
getLazyIRModule(std::unique_ptr<MemoryBuffer> Buffer,SMDiagnostic & Err,LLVMContext & Context,bool ShouldLazyLoadMetadata)3409467b48Spatrick llvm::getLazyIRModule(std::unique_ptr<MemoryBuffer> Buffer, SMDiagnostic &Err,
3509467b48Spatrick LLVMContext &Context, bool ShouldLazyLoadMetadata) {
3609467b48Spatrick if (isBitcode((const unsigned char *)Buffer->getBufferStart(),
3709467b48Spatrick (const unsigned char *)Buffer->getBufferEnd())) {
3809467b48Spatrick Expected<std::unique_ptr<Module>> ModuleOrErr = getOwningLazyBitcodeModule(
3909467b48Spatrick std::move(Buffer), Context, ShouldLazyLoadMetadata);
4009467b48Spatrick if (Error E = ModuleOrErr.takeError()) {
4109467b48Spatrick handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
4209467b48Spatrick Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error,
4309467b48Spatrick EIB.message());
4409467b48Spatrick });
4509467b48Spatrick return nullptr;
4609467b48Spatrick }
4709467b48Spatrick return std::move(ModuleOrErr.get());
4809467b48Spatrick }
4909467b48Spatrick
5009467b48Spatrick return parseAssembly(Buffer->getMemBufferRef(), Err, Context);
5109467b48Spatrick }
5209467b48Spatrick
getLazyIRFileModule(StringRef Filename,SMDiagnostic & Err,LLVMContext & Context,bool ShouldLazyLoadMetadata)5309467b48Spatrick std::unique_ptr<Module> llvm::getLazyIRFileModule(StringRef Filename,
5409467b48Spatrick SMDiagnostic &Err,
5509467b48Spatrick LLVMContext &Context,
5609467b48Spatrick bool ShouldLazyLoadMetadata) {
5709467b48Spatrick ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
5809467b48Spatrick MemoryBuffer::getFileOrSTDIN(Filename);
5909467b48Spatrick if (std::error_code EC = FileOrErr.getError()) {
6009467b48Spatrick Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
6109467b48Spatrick "Could not open input file: " + EC.message());
6209467b48Spatrick return nullptr;
6309467b48Spatrick }
6409467b48Spatrick
6509467b48Spatrick return getLazyIRModule(std::move(FileOrErr.get()), Err, Context,
6609467b48Spatrick ShouldLazyLoadMetadata);
6709467b48Spatrick }
6809467b48Spatrick
parseIR(MemoryBufferRef Buffer,SMDiagnostic & Err,LLVMContext & Context,ParserCallbacks Callbacks)6909467b48Spatrick std::unique_ptr<Module> llvm::parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
7009467b48Spatrick LLVMContext &Context,
71*d415bd75Srobert ParserCallbacks Callbacks) {
7209467b48Spatrick NamedRegionTimer T(TimeIRParsingName, TimeIRParsingDescription,
7309467b48Spatrick TimeIRParsingGroupName, TimeIRParsingGroupDescription,
7409467b48Spatrick TimePassesIsEnabled);
7509467b48Spatrick if (isBitcode((const unsigned char *)Buffer.getBufferStart(),
7609467b48Spatrick (const unsigned char *)Buffer.getBufferEnd())) {
7709467b48Spatrick Expected<std::unique_ptr<Module>> ModuleOrErr =
78*d415bd75Srobert parseBitcodeFile(Buffer, Context, Callbacks);
7909467b48Spatrick if (Error E = ModuleOrErr.takeError()) {
8009467b48Spatrick handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
8109467b48Spatrick Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
8209467b48Spatrick EIB.message());
8309467b48Spatrick });
8409467b48Spatrick return nullptr;
8509467b48Spatrick }
8609467b48Spatrick return std::move(ModuleOrErr.get());
8709467b48Spatrick }
8809467b48Spatrick
89*d415bd75Srobert return parseAssembly(Buffer, Err, Context, nullptr,
90*d415bd75Srobert Callbacks.DataLayout.value_or(
91*d415bd75Srobert [](StringRef, StringRef) { return std::nullopt; }));
9209467b48Spatrick }
9309467b48Spatrick
parseIRFile(StringRef Filename,SMDiagnostic & Err,LLVMContext & Context,ParserCallbacks Callbacks)94*d415bd75Srobert std::unique_ptr<Module> llvm::parseIRFile(StringRef Filename, SMDiagnostic &Err,
95*d415bd75Srobert LLVMContext &Context,
96*d415bd75Srobert ParserCallbacks Callbacks) {
9709467b48Spatrick ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
9873471bf0Spatrick MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
9909467b48Spatrick if (std::error_code EC = FileOrErr.getError()) {
10009467b48Spatrick Err = SMDiagnostic(Filename, SourceMgr::DK_Error,
10109467b48Spatrick "Could not open input file: " + EC.message());
10209467b48Spatrick return nullptr;
10309467b48Spatrick }
10409467b48Spatrick
105*d415bd75Srobert return parseIR(FileOrErr.get()->getMemBufferRef(), Err, Context, Callbacks);
10609467b48Spatrick }
10709467b48Spatrick
10809467b48Spatrick //===----------------------------------------------------------------------===//
10909467b48Spatrick // C API.
11009467b48Spatrick //===----------------------------------------------------------------------===//
11109467b48Spatrick
LLVMParseIRInContext(LLVMContextRef ContextRef,LLVMMemoryBufferRef MemBuf,LLVMModuleRef * OutM,char ** OutMessage)11209467b48Spatrick LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef,
11309467b48Spatrick LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
11409467b48Spatrick char **OutMessage) {
11509467b48Spatrick SMDiagnostic Diag;
11609467b48Spatrick
11709467b48Spatrick std::unique_ptr<MemoryBuffer> MB(unwrap(MemBuf));
11809467b48Spatrick *OutM =
11909467b48Spatrick wrap(parseIR(MB->getMemBufferRef(), Diag, *unwrap(ContextRef)).release());
12009467b48Spatrick
12109467b48Spatrick if(!*OutM) {
12209467b48Spatrick if (OutMessage) {
12309467b48Spatrick std::string buf;
12409467b48Spatrick raw_string_ostream os(buf);
12509467b48Spatrick
12609467b48Spatrick Diag.print(nullptr, os, false);
12709467b48Spatrick os.flush();
12809467b48Spatrick
12909467b48Spatrick *OutMessage = strdup(buf.c_str());
13009467b48Spatrick }
13109467b48Spatrick return 1;
13209467b48Spatrick }
13309467b48Spatrick
13409467b48Spatrick return 0;
13509467b48Spatrick }
136