LLVMGetBitcodeModuleInContext2 problem

I’m trying to use LLVMGetBitcodeModuleInContext2 to load a .bc file.

However, it’s not working.

The code looks something like this:

void llvm_load_IR_library(char *path)

{
LLVMContextRef global_context;
LLVMMemoryBufferRef module_path;
LLVMModuleRef ir_lib_module;
bool flag;

module_path = LLVMCreateMemoryBufferWithMemoryRange(path, strlen(path), “path”, 1);

global_context = LLVMGetGlobalContext();

flag = LLVMGetBitcodeModuleInContext2(global_context, module_path, &ir_lib_module);

printf(“LLVMGetBitcodeModuleInContet2() returned %d\n”, flag);
}

When this code is called, this is printed:

error: Invalid bitcode signature

from what I can tell, the bitcode file is correct:

00000000 42 43 c0 de 35 14 00 00 05 00 00 00 62 0c 30 24 |BC…5…b.0$|

This seems to match this code:

/// Helper to read the header common to all bitcode files.
static bool hasValidBitcodeHeader(BitstreamCursor &Stream) {
// Sniff for the signature.
if (Stream.Read(8) != ‘B’ ||
Stream.Read(8) != ‘C’ ||
Stream.Read(4) != 0x0 ||
Stream.Read(4) != 0xC ||
Stream.Read(4) != 0xE ||
Stream.Read(4) != 0xD)
return false;
return true;
}

I’m out of ideas. Anything obvious I’m doing wrong?

Toshi

LLVMCreateMemoryBufferWithContentsOfFile takes a path.

-Eli

module_path = LLVMCreateMemoryBufferWithMemoryRange(path, strlen(path), “path”, 1);

LLVMCreateMemoryBufferWithContentsOfFile takes a path.

Erm…no…the code is calling LLVMCreateMemoryBufferWithMemoryRange, not LLVMCreateMemoryBufferWithContentsOfFile…

Or do you mean I need to load the module into memory before calling LLVMGetBitcodeModuleInContext2?

Toshi

Yes, you need to load the module into memory first. LLVMCreateMemoryBufferWithContentsOfFile will do that for you. -Eli

Or do you mean I need to load the module into memory before calling LLVMGetBitcodeModuleInContext2?

Yes, you need to load the module into memory first.
LLVMCreateMemoryBufferWithContentsOfFile will do that for you.

Thanks!

Made it a bit further. Here’s the current code:

void llvm_load_IR_library(char *path)
{
char error;
LLVMExecutionEngineRef engine;
object0_t
(*func)(void), *output;
LLVMContextRef global_context;
LLVMMemoryBufferRef module;
LLVMModuleRef ir_lib_module;
bool flag;

printf(“loading IR library from path: %s\n”, path);

LLVMCreateMemoryBufferWithContentsOfFile(path, &module, &error);

global_context = LLVMGetGlobalContext();

flag = LLVMGetBitcodeModuleInContext2(global_context, module, &ir_lib_module);

printf(“LLVMGetBitcodeModuleInContext2() returned %d\n”, flag);

LLVMVerifyModule(ir_lib_module, LLVMAbortProcessAction, &error);
LLVMDumpModule(ir_lib_module);

if (LLVMCreateExecutionEngineForModule(&engine, ir_lib_module, &error) != 0) {
fprintf(stderr, “failed to create execution engine\n”);
abort();
}

// Call the function
func = (object0_t * (*)(void))LLVMGetFunctionAddress(engine, “test”);
output = (*func)();
}

when this code is executed, i see:


LLVMGetBitcodeModuleInContext2() returned 0
; ModuleID = ‘/home/toshi/tensyr/debug_build/test.bc’
source_filename = “test.c”
target datalayout = “e-m:e-i64:64-f80:128-n8:16:32:64-S128”
target triple = “x86_64-unknown-linux-gnu”

@str = private unnamed_addr constant [16 x i8] c"test successful\00"

; Materializable
; Function Attrs: nounwind uwtable
define void @test() local_unnamed_addr #0 {}

; Function Attrs: nounwind
declare i32 @puts(i8* nocapture readonly) #1

attributes #0 = { nounwind uwtable “disable-tail-calls”=“false” “less-precise-fpmad”=“false” “no-frame-pointer-elim”=“false” “no-infs-fp-math”=“false” “no-jump-tables”=“false” “no-nans-fp-math”=“false” “no-signed-zeros-fp-math”=“false” “stack-protector-buffer-size”=“8” “target-cpu”=“x86-64” “target-features”=“+fxsr,+mmx,+sse,+sse2,+x87” “unsafe-fp-math”=“false” “use-soft-float”=“false” }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = !{!“clang version 3.9.1 (tags/RELEASE_391/final)”}
failed to create execution engine
Aborted (core dumped)

Not sure why LLVMCreateExecutionEngineForModule is failing.

Any help appreciated.

Toshi

Oops, missed initializing some stuff. Added:

LLVMLinkInMCJIT();
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();

Now it crashes in LLVMGetFunctionAddress().

Hmm.

You're going to have to read the C++ headers for a lot of things to make sense; the C headers don't really have much documentation.

In this case:

   /// getFunctionAddress - Return the address of the specified function.
   /// This may involve code generation.
   virtual uint64_t getFunctionAddress(const std::string &Name) {
     // Default implementation for the interpreter. MCJIT will override this.
     // Interpreter clients should use getPointerToFunction instead.
     return 0;
   }

I would suggest using MCJIT (LLVMCreateMCJITCompilerForModule).

-Eli

LLVMMCLinkInMCJIT() is not enough?

The current code is:

void llvm_load_IR_library(char *path)
{
char error;
LLVMExecutionEngineRef engine;
object0_t
(*func)(void), *output;
LLVMContextRef global_context;
LLVMMemoryBufferRef module;
LLVMModuleRef ir_lib_module;
bool flag;

printf(“loading IR library from path: %s\n”, path);

LLVMCreateMemoryBufferWithContentsOfFile(path, &module, &error);

global_context = LLVMGetGlobalContext();

flag = LLVMGetBitcodeModuleInContext2(global_context, module, &ir_lib_module);

printf(“LLVMGetBitcodeModuleInContext2() returned %d\n”, flag);

LLVMVerifyModule(ir_lib_module, LLVMAbortProcessAction, &error);
LLVMDumpModule(ir_lib_module);

LLVMLinkInMCJIT();
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();

if (LLVMCreateExecutionEngineForModule(&engine, ir_lib_module, &error) != 0) {
fprintf(stderr, “failed to create execution engine\n”);
abort();
}

// Call the function
func = (object0_t * (*)(void))LLVMGetFunctionAddress(engine, “test”);
output = (*func)();
}