1 //===-- BitReader.cpp -----------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm-c/BitReader.h" 11 #include "llvm-c/Core.h" 12 #include "llvm/Bitcode/ReaderWriter.h" 13 #include "llvm/IR/DiagnosticPrinter.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/Support/MemoryBuffer.h" 17 #include "llvm/Support/raw_ostream.h" 18 #include <cstring> 19 #include <string> 20 21 using namespace llvm; 22 23 /* Builds a module from the bitcode in the specified memory buffer, returning a 24 reference to the module via the OutModule parameter. Returns 0 on success. 25 Optionally returns a human-readable error message via OutMessage. */ 26 LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, 27 LLVMModuleRef *OutModule, char **OutMessage) { 28 return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule, 29 OutMessage); 30 } 31 32 static void diagnosticHandler(const DiagnosticInfo &DI, void *C) { 33 auto *Message = reinterpret_cast<std::string *>(C); 34 raw_string_ostream Stream(*Message); 35 DiagnosticPrinterRawOStream DP(Stream); 36 DI.print(DP); 37 } 38 39 LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, 40 LLVMMemoryBufferRef MemBuf, 41 LLVMModuleRef *OutModule, 42 char **OutMessage) { 43 MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef(); 44 LLVMContext &Ctx = *unwrap(ContextRef); 45 46 LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = 47 Ctx.getDiagnosticHandler(); 48 void *OldDiagnosticContext = Ctx.getDiagnosticContext(); 49 std::string Message; 50 Ctx.setDiagnosticHandler(diagnosticHandler, &Message, true); 51 52 ErrorOr<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buf, Ctx); 53 54 Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext, true); 55 56 if (ModuleOrErr.getError()) { 57 if (OutMessage) 58 *OutMessage = strdup(Message.c_str()); 59 *OutModule = wrap((Module*)nullptr); 60 return 1; 61 } 62 63 *OutModule = wrap(ModuleOrErr.get().release()); 64 return 0; 65 } 66 67 /* Reads a module from the specified path, returning via the OutModule parameter 68 a module provider which performs lazy deserialization. Returns 0 on success. 69 Optionally returns a human-readable error message via OutMessage. */ 70 LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, 71 LLVMMemoryBufferRef MemBuf, 72 LLVMModuleRef *OutM, 73 char **OutMessage) { 74 LLVMContext &Ctx = *unwrap(ContextRef); 75 LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = 76 Ctx.getDiagnosticHandler(); 77 void *OldDiagnosticContext = Ctx.getDiagnosticContext(); 78 79 std::string Message; 80 Ctx.setDiagnosticHandler(diagnosticHandler, &Message, true); 81 std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf)); 82 83 ErrorOr<std::unique_ptr<Module>> ModuleOrErr = 84 getLazyBitcodeModule(std::move(Owner), Ctx); 85 Owner.release(); 86 Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext, true); 87 88 if (ModuleOrErr.getError()) { 89 *OutM = wrap((Module *)nullptr); 90 if (OutMessage) 91 *OutMessage = strdup(Message.c_str()); 92 return 1; 93 } 94 95 *OutM = wrap(ModuleOrErr.get().release()); 96 97 return 0; 98 99 } 100 101 LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, 102 char **OutMessage) { 103 return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM, 104 OutMessage); 105 } 106