1//===-- BitReader.cpp -----------------------------------------------------===//
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-c/BitReader.h"
10#include "llvm-c/Core.h"
11#include "llvm/Bitcode/BitcodeReader.h"
12#include "llvm/IR/LLVMContext.h"
13#include "llvm/IR/Module.h"
14#include "llvm/Support/MemoryBuffer.h"
15#include <cstring>
16#include <string>
17
18using namespace llvm;
19
20/* Builds a module from the bitcode in the specified memory buffer, returning a
21   reference to the module via the OutModule parameter. Returns 0 on success.
22   Optionally returns a human-readable error message via OutMessage. */
23LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule,
24                          char **OutMessage) {
25  return LLVMParseBitcodeInContext(LLVMGetGlobalContext(), MemBuf, OutModule,
26                                   OutMessage);
27}
28
29LLVMBool LLVMParseBitcode2(LLVMMemoryBufferRef MemBuf,
30                           LLVMModuleRef *OutModule) {
31  return LLVMParseBitcodeInContext2(LLVMGetGlobalContext(), MemBuf, OutModule);
32}
33
34LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef,
35                                   LLVMMemoryBufferRef MemBuf,
36                                   LLVMModuleRef *OutModule,
37                                   char **OutMessage) {
38  MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef();
39  LLVMContext &Ctx = *unwrap(ContextRef);
40
41  Expected<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buf, Ctx);
42  if (Error Err = ModuleOrErr.takeError()) {
43    std::string Message;
44    handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
45      Message = EIB.message();
46    });
47    if (OutMessage)
48      *OutMessage = strdup(Message.c_str());
49    *OutModule = wrap((Module *)nullptr);
50    return 1;
51  }
52
53  *OutModule = wrap(ModuleOrErr.get().release());
54  return 0;
55}
56
57LLVMBool LLVMParseBitcodeInContext2(LLVMContextRef ContextRef,
58                                    LLVMMemoryBufferRef MemBuf,
59                                    LLVMModuleRef *OutModule) {
60  MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef();
61  LLVMContext &Ctx = *unwrap(ContextRef);
62
63  ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
64      expectedToErrorOrAndEmitErrors(Ctx, parseBitcodeFile(Buf, Ctx));
65  if (ModuleOrErr.getError()) {
66    *OutModule = wrap((Module *)nullptr);
67    return 1;
68  }
69
70  *OutModule = wrap(ModuleOrErr.get().release());
71  return 0;
72}
73
74/* Reads a module from the specified path, returning via the OutModule parameter
75   a module provider which performs lazy deserialization. Returns 0 on success.
76   Optionally returns a human-readable error message via OutMessage. */
77LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef,
78                                       LLVMMemoryBufferRef MemBuf,
79                                       LLVMModuleRef *OutM, char **OutMessage) {
80  LLVMContext &Ctx = *unwrap(ContextRef);
81  std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf));
82  Expected<std::unique_ptr<Module>> ModuleOrErr =
83      getOwningLazyBitcodeModule(std::move(Owner), Ctx);
84  // Release the buffer if we didn't take ownership of it since we never owned
85  // it anyway.
86  (void)Owner.release();
87
88  if (Error Err = ModuleOrErr.takeError()) {
89    std::string Message;
90    handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
91      Message = EIB.message();
92    });
93    if (OutMessage)
94      *OutMessage = strdup(Message.c_str());
95    *OutM = wrap((Module *)nullptr);
96    return 1;
97  }
98
99  *OutM = wrap(ModuleOrErr.get().release());
100
101  return 0;
102}
103
104LLVMBool LLVMGetBitcodeModuleInContext2(LLVMContextRef ContextRef,
105                                        LLVMMemoryBufferRef MemBuf,
106                                        LLVMModuleRef *OutM) {
107  LLVMContext &Ctx = *unwrap(ContextRef);
108  std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf));
109
110  ErrorOr<std::unique_ptr<Module>> ModuleOrErr = expectedToErrorOrAndEmitErrors(
111      Ctx, getOwningLazyBitcodeModule(std::move(Owner), Ctx));
112  Owner.release();
113
114  if (ModuleOrErr.getError()) {
115    *OutM = wrap((Module *)nullptr);
116    return 1;
117  }
118
119  *OutM = wrap(ModuleOrErr.get().release());
120  return 0;
121}
122
123LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
124                              char **OutMessage) {
125  return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM,
126                                       OutMessage);
127}
128
129LLVMBool LLVMGetBitcodeModule2(LLVMMemoryBufferRef MemBuf,
130                               LLVMModuleRef *OutM) {
131  return LLVMGetBitcodeModuleInContext2(LLVMGetGlobalContext(), MemBuf, OutM);
132}
133