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