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