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 | |
18 | using 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. */ |
23 | LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, |
24 | char **OutMessage) { |
25 | return LLVMParseBitcodeInContext(ContextRef: LLVMGetGlobalContext(), MemBuf, OutModule, |
26 | OutMessage); |
27 | } |
28 | |
29 | LLVMBool LLVMParseBitcode2(LLVMMemoryBufferRef MemBuf, |
30 | LLVMModuleRef *OutModule) { |
31 | return LLVMParseBitcodeInContext2(ContextRef: LLVMGetGlobalContext(), MemBuf, OutModule); |
32 | } |
33 | |
34 | LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, |
35 | LLVMMemoryBufferRef MemBuf, |
36 | LLVMModuleRef *OutModule, |
37 | char **OutMessage) { |
38 | MemoryBufferRef Buf = unwrap(P: MemBuf)->getMemBufferRef(); |
39 | LLVMContext &Ctx = *unwrap(P: ContextRef); |
40 | |
41 | Expected<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buffer: Buf, Context&: Ctx); |
42 | if (Error Err = ModuleOrErr.takeError()) { |
43 | std::string Message; |
44 | handleAllErrors(E: std::move(Err), Handlers: [&](ErrorInfoBase &EIB) { |
45 | Message = EIB.message(); |
46 | }); |
47 | if (OutMessage) |
48 | *OutMessage = strdup(s: Message.c_str()); |
49 | *OutModule = wrap(P: (Module *)nullptr); |
50 | return 1; |
51 | } |
52 | |
53 | *OutModule = wrap(P: ModuleOrErr.get().release()); |
54 | return 0; |
55 | } |
56 | |
57 | LLVMBool LLVMParseBitcodeInContext2(LLVMContextRef ContextRef, |
58 | LLVMMemoryBufferRef MemBuf, |
59 | LLVMModuleRef *OutModule) { |
60 | MemoryBufferRef Buf = unwrap(P: MemBuf)->getMemBufferRef(); |
61 | LLVMContext &Ctx = *unwrap(P: ContextRef); |
62 | |
63 | ErrorOr<std::unique_ptr<Module>> ModuleOrErr = |
64 | expectedToErrorOrAndEmitErrors(Ctx, Val: parseBitcodeFile(Buffer: Buf, Context&: Ctx)); |
65 | if (ModuleOrErr.getError()) { |
66 | *OutModule = wrap(P: (Module *)nullptr); |
67 | return 1; |
68 | } |
69 | |
70 | *OutModule = wrap(P: 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. */ |
77 | LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, |
78 | LLVMMemoryBufferRef MemBuf, |
79 | LLVMModuleRef *OutM, char **OutMessage) { |
80 | LLVMContext &Ctx = *unwrap(P: ContextRef); |
81 | std::unique_ptr<MemoryBuffer> Owner(unwrap(P: MemBuf)); |
82 | Expected<std::unique_ptr<Module>> ModuleOrErr = |
83 | getOwningLazyBitcodeModule(Buffer: std::move(Owner), Context&: 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(E: std::move(Err), Handlers: [&](ErrorInfoBase &EIB) { |
91 | Message = EIB.message(); |
92 | }); |
93 | if (OutMessage) |
94 | *OutMessage = strdup(s: Message.c_str()); |
95 | *OutM = wrap(P: (Module *)nullptr); |
96 | return 1; |
97 | } |
98 | |
99 | *OutM = wrap(P: ModuleOrErr.get().release()); |
100 | |
101 | return 0; |
102 | } |
103 | |
104 | LLVMBool LLVMGetBitcodeModuleInContext2(LLVMContextRef ContextRef, |
105 | LLVMMemoryBufferRef MemBuf, |
106 | LLVMModuleRef *OutM) { |
107 | LLVMContext &Ctx = *unwrap(P: ContextRef); |
108 | std::unique_ptr<MemoryBuffer> Owner(unwrap(P: MemBuf)); |
109 | |
110 | ErrorOr<std::unique_ptr<Module>> ModuleOrErr = expectedToErrorOrAndEmitErrors( |
111 | Ctx, Val: getOwningLazyBitcodeModule(Buffer: std::move(Owner), Context&: Ctx)); |
112 | Owner.release(); |
113 | |
114 | if (ModuleOrErr.getError()) { |
115 | *OutM = wrap(P: (Module *)nullptr); |
116 | return 1; |
117 | } |
118 | |
119 | *OutM = wrap(P: ModuleOrErr.get().release()); |
120 | return 0; |
121 | } |
122 | |
123 | LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, |
124 | char **OutMessage) { |
125 | return LLVMGetBitcodeModuleInContext(ContextRef: LLVMGetGlobalContext(), MemBuf, OutM, |
126 | OutMessage); |
127 | } |
128 | |
129 | LLVMBool LLVMGetBitcodeModule2(LLVMMemoryBufferRef MemBuf, |
130 | LLVMModuleRef *OutM) { |
131 | return LLVMGetBitcodeModuleInContext2(ContextRef: LLVMGetGlobalContext(), MemBuf, OutM); |
132 | } |
133 | |