Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimal example using LLVM's C API yields error: function and module have different contexts

Tags:

c

llvm

I'm trying to implement a small example using the C API. I get an error message that the function context doesn't match the module context, which I can't figure out.

Here's my code:

#include <stdio.h>

#include <llvm-c/Analysis.h>
#include <llvm-c/Core.h>
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>

int
main() {
    LLVMInitializeNativeTarget();
    LLVMInitializeNativeAsmPrinter();
    char* triple = LLVMGetDefaultTargetTriple();
    char* error;
    LLVMTargetRef target_ref;
    if (LLVMGetTargetFromTriple(triple, &target_ref, &error)) {
        printf("Error: %s\n", error);
        return 1;
    }
    LLVMTargetMachineRef tm_ref = LLVMCreateTargetMachine(
      target_ref,
      triple,
      "",
      "",
      LLVMCodeGenLevelDefault,
      LLVMRelocStatic,
      LLVMCodeModelJITDefault);
    LLVMDisposeMessage(triple);

    LLVMContextRef context = LLVMContextCreate();
    LLVMModuleRef module = LLVMModuleCreateWithNameInContext("module_name", context);
    // LLVMModuleRef module = LLVMModuleCreateWithName("module_name");

    LLVMTypeRef param_types[] = {LLVMIntType(32), LLVMIntType(32)};
    LLVMTypeRef func_type = LLVMFunctionType(LLVMIntType(32), param_types, 2, 0);

    LLVMValueRef func = LLVMAddFunction(module, "function_name", func_type);
    LLVMBasicBlockRef entry = LLVMAppendBasicBlock(func, "entry");

    LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
    // LLVMBuilderRef builder = LLVMCreateBuilder();
    LLVMPositionBuilderAtEnd(builder, entry);
    LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(func, 0), LLVMGetParam(func, 1), "add");
    LLVMBuildRet(builder, tmp);

    LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
    LLVMDisposeMessage(error);
}

And then my execution:

$ llvm-config --version
8.0.0
$ clang++ trash.cpp `llvm-config --cflags --ldflags` `llvm-config --libs` `llvm-config --system-libs`
$ ./a.out 
Function context does not match Module context!
i32 (i32, i32)* @function_name
LLVM ERROR: Broken module found, compilation aborted!

This is not an API that lends itself to very small examples; consequently, there's a decent chunk of code here.

If I use the currently commented out code which doesn't reference context, everything works fine. It's not clear to me why, when I call LLVMAddFunction, it doesn't just take its context from the module I passed in.

like image 900
Michael Benfield Avatar asked May 26 '19 20:05

Michael Benfield


1 Answers

Well, I found the answer. Rather than LLVMIntType, I should be using LLVMIntTypeInContext. And rather than LLVMAppendBasicBlock, I should be using LLVMAppendBasicBlockInContext. I didn't realize previously such functions existed.

like image 125
Michael Benfield Avatar answered Oct 22 '22 05:10

Michael Benfield