1f22ef01cSRoman Divacky //===-- BitReader.cpp -----------------------------------------------------===// 2f22ef01cSRoman Divacky // 3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure 4f22ef01cSRoman Divacky // 5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source 6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details. 7f22ef01cSRoman Divacky // 8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 9f22ef01cSRoman Divacky 10f22ef01cSRoman Divacky #include "llvm-c/BitReader.h" 117d523365SDimitry Andric #include "llvm-c/Core.h" 12f22ef01cSRoman Divacky #include "llvm/Bitcode/ReaderWriter.h" 1344f7b0dcSDimitry Andric #include "llvm/IR/DiagnosticPrinter.h" 14139f7f9bSDimitry Andric #include "llvm/IR/LLVMContext.h" 15284c1978SDimitry Andric #include "llvm/IR/Module.h" 16f22ef01cSRoman Divacky #include "llvm/Support/MemoryBuffer.h" 1744f7b0dcSDimitry Andric #include "llvm/Support/raw_ostream.h" 18f22ef01cSRoman Divacky #include <cstring> 19139f7f9bSDimitry Andric #include <string> 20f22ef01cSRoman Divacky 21f22ef01cSRoman Divacky using namespace llvm; 22f22ef01cSRoman Divacky 23f22ef01cSRoman Divacky /* Builds a module from the bitcode in the specified memory buffer, returning a 24f22ef01cSRoman Divacky reference to the module via the OutModule parameter. Returns 0 on success. 25f22ef01cSRoman Divacky Optionally returns a human-readable error message via OutMessage. */ 267d523365SDimitry Andric LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, 277d523365SDimitry Andric char **OutMessage) { 28*3ca95b02SDimitry Andric return LLVMParseBitcodeInContext(LLVMGetGlobalContext(), MemBuf, OutModule, 29f22ef01cSRoman Divacky OutMessage); 30f22ef01cSRoman Divacky } 31f22ef01cSRoman Divacky 327d523365SDimitry Andric LLVMBool LLVMParseBitcode2(LLVMMemoryBufferRef MemBuf, 337d523365SDimitry Andric LLVMModuleRef *OutModule) { 34*3ca95b02SDimitry Andric return LLVMParseBitcodeInContext2(LLVMGetGlobalContext(), MemBuf, OutModule); 357d523365SDimitry Andric } 367d523365SDimitry Andric 377d523365SDimitry Andric static void diagnosticHandler(const DiagnosticInfo &DI, void *C) { 387d523365SDimitry Andric auto *Message = reinterpret_cast<std::string *>(C); 397d523365SDimitry Andric raw_string_ostream Stream(*Message); 407d523365SDimitry Andric DiagnosticPrinterRawOStream DP(Stream); 417d523365SDimitry Andric DI.print(DP); 427d523365SDimitry Andric } 437d523365SDimitry Andric 44f22ef01cSRoman Divacky LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, 45f22ef01cSRoman Divacky LLVMMemoryBufferRef MemBuf, 46f22ef01cSRoman Divacky LLVMModuleRef *OutModule, 47f22ef01cSRoman Divacky char **OutMessage) { 4844f7b0dcSDimitry Andric MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef(); 4944f7b0dcSDimitry Andric LLVMContext &Ctx = *unwrap(ContextRef); 5044f7b0dcSDimitry Andric 517d523365SDimitry Andric LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = 527d523365SDimitry Andric Ctx.getDiagnosticHandler(); 537d523365SDimitry Andric void *OldDiagnosticContext = Ctx.getDiagnosticContext(); 5444f7b0dcSDimitry Andric std::string Message; 557d523365SDimitry Andric Ctx.setDiagnosticHandler(diagnosticHandler, &Message, true); 5644f7b0dcSDimitry Andric 577d523365SDimitry Andric ErrorOr<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buf, Ctx); 587d523365SDimitry Andric 597d523365SDimitry Andric Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext, true); 607d523365SDimitry Andric 6144f7b0dcSDimitry Andric if (ModuleOrErr.getError()) { 627d523365SDimitry Andric if (OutMessage) 6344f7b0dcSDimitry Andric *OutMessage = strdup(Message.c_str()); 647d523365SDimitry Andric *OutModule = wrap((Module *)nullptr); 657d523365SDimitry Andric return 1; 6644f7b0dcSDimitry Andric } 677d523365SDimitry Andric 687d523365SDimitry Andric *OutModule = wrap(ModuleOrErr.get().release()); 697d523365SDimitry Andric return 0; 707d523365SDimitry Andric } 717d523365SDimitry Andric 727d523365SDimitry Andric LLVMBool LLVMParseBitcodeInContext2(LLVMContextRef ContextRef, 737d523365SDimitry Andric LLVMMemoryBufferRef MemBuf, 747d523365SDimitry Andric LLVMModuleRef *OutModule) { 757d523365SDimitry Andric MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef(); 767d523365SDimitry Andric LLVMContext &Ctx = *unwrap(ContextRef); 777d523365SDimitry Andric 787d523365SDimitry Andric ErrorOr<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buf, Ctx); 797d523365SDimitry Andric if (ModuleOrErr.getError()) { 8091bc56edSDimitry Andric *OutModule = wrap((Module *)nullptr); 81f22ef01cSRoman Divacky return 1; 82f22ef01cSRoman Divacky } 83f22ef01cSRoman Divacky 848f0fd8f6SDimitry Andric *OutModule = wrap(ModuleOrErr.get().release()); 85f22ef01cSRoman Divacky return 0; 86f22ef01cSRoman Divacky } 87f22ef01cSRoman Divacky 88f22ef01cSRoman Divacky /* Reads a module from the specified path, returning via the OutModule parameter 89f22ef01cSRoman Divacky a module provider which performs lazy deserialization. Returns 0 on success. 90f22ef01cSRoman Divacky Optionally returns a human-readable error message via OutMessage. */ 91f22ef01cSRoman Divacky LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, 92f22ef01cSRoman Divacky LLVMMemoryBufferRef MemBuf, 937d523365SDimitry Andric LLVMModuleRef *OutM, char **OutMessage) { 947d523365SDimitry Andric LLVMContext &Ctx = *unwrap(ContextRef); 957d523365SDimitry Andric LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = 967d523365SDimitry Andric Ctx.getDiagnosticHandler(); 977d523365SDimitry Andric void *OldDiagnosticContext = Ctx.getDiagnosticContext(); 987d523365SDimitry Andric 99f22ef01cSRoman Divacky std::string Message; 1007d523365SDimitry Andric Ctx.setDiagnosticHandler(diagnosticHandler, &Message, true); 10139d628a0SDimitry Andric std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf)); 10239d628a0SDimitry Andric 1038f0fd8f6SDimitry Andric ErrorOr<std::unique_ptr<Module>> ModuleOrErr = 1047d523365SDimitry Andric getLazyBitcodeModule(std::move(Owner), Ctx); 10539d628a0SDimitry Andric Owner.release(); 1067d523365SDimitry Andric Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext, true); 107f22ef01cSRoman Divacky 1087d523365SDimitry Andric if (ModuleOrErr.getError()) { 10991bc56edSDimitry Andric *OutM = wrap((Module *)nullptr); 110f22ef01cSRoman Divacky if (OutMessage) 1117d523365SDimitry Andric *OutMessage = strdup(Message.c_str()); 112f22ef01cSRoman Divacky return 1; 113f22ef01cSRoman Divacky } 114f22ef01cSRoman Divacky 1158f0fd8f6SDimitry Andric *OutM = wrap(ModuleOrErr.get().release()); 11691bc56edSDimitry Andric 117f22ef01cSRoman Divacky return 0; 1187d523365SDimitry Andric } 119f22ef01cSRoman Divacky 1207d523365SDimitry Andric LLVMBool LLVMGetBitcodeModuleInContext2(LLVMContextRef ContextRef, 1217d523365SDimitry Andric LLVMMemoryBufferRef MemBuf, 1227d523365SDimitry Andric LLVMModuleRef *OutM) { 1237d523365SDimitry Andric LLVMContext &Ctx = *unwrap(ContextRef); 1247d523365SDimitry Andric std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf)); 1257d523365SDimitry Andric 1267d523365SDimitry Andric ErrorOr<std::unique_ptr<Module>> ModuleOrErr = 1277d523365SDimitry Andric getLazyBitcodeModule(std::move(Owner), Ctx); 1287d523365SDimitry Andric Owner.release(); 1297d523365SDimitry Andric 1307d523365SDimitry Andric if (ModuleOrErr.getError()) { 1317d523365SDimitry Andric *OutM = wrap((Module *)nullptr); 1327d523365SDimitry Andric return 1; 1337d523365SDimitry Andric } 1347d523365SDimitry Andric 1357d523365SDimitry Andric *OutM = wrap(ModuleOrErr.get().release()); 1367d523365SDimitry Andric return 0; 137f22ef01cSRoman Divacky } 138f22ef01cSRoman Divacky 139f22ef01cSRoman Divacky LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, 140f22ef01cSRoman Divacky char **OutMessage) { 141f22ef01cSRoman Divacky return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM, 142f22ef01cSRoman Divacky OutMessage); 143f22ef01cSRoman Divacky } 144f22ef01cSRoman Divacky 1457d523365SDimitry Andric LLVMBool LLVMGetBitcodeModule2(LLVMMemoryBufferRef MemBuf, 1467d523365SDimitry Andric LLVMModuleRef *OutM) { 1477d523365SDimitry Andric return LLVMGetBitcodeModuleInContext2(LLVMGetGlobalContext(), MemBuf, OutM); 148f22ef01cSRoman Divacky } 149