简体   繁体   中英

How to use the LLVMBuildGEP function in the LLVM C API

I'm trying to make an LLVM function that reads a field from a struct i pass, I've googled some stuff about getelementptr instruction and i guess that's what I'll need here, but how is it exactly used in the C API. The struct is defined in C but I'm trying to access its fields via LLVM since they're in the same runtime I'm guessing it will work? (Correct me if I'm wrong)

Here's the code so far.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/ExecutionEngine.h>

typedef struct {
  char* name;
  int age;
} user;

int main() {
  LLVMTypeRef type = LLVMStructCreateNamed(LLVMGetGlobalContext(), "struct.user");
  LLVMModuleRef module = LLVMModuleCreateWithName("test");
  LLVMBuilderRef builder = LLVMCreateBuilder();
  LLVMTypeRef ret = LLVMFunctionType(LLVMPointerType(LLVMInt32Type(), 0),
      (LLVMTypeRef[]){ LLVMPointerType(type, 0) }, 1, false);
  LLVMValueRef fn = LLVMAddFunction(module, "stuff", ret);
  LLVMBasicBlockRef entry = LLVMAppendBasicBlock(fn, "entry");
  LLVMPositionBuilderAtEnd(builder, entry);
  LLVMValueRef gep = LLVMBuildGEP(builder, LLVMGetParam(fn, 0), (LLVMValueRef[]){ LLVMConstInt(LLVMInt32Type(), 0, false), 
    LLVMConstInt(LLVMInt32Type(), 1, false) }, 2, "gep");
  LLVMBuildRet(builder, gep);
  char *error = NULL;
  LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
  LLVMDisposeMessage(error);
  LLVMExecutionEngineRef engine;
  error = NULL;
  LLVMLinkInMCJIT();
  LLVMInitializeNativeTarget();
  LLVMInitializeNativeAsmPrinter();
  LLVMInitializeNativeAsmParser();
  if(LLVMCreateExecutionEngineForModule(&engine, module, &error) != 0) {
    fprintf(stderr, "failed to create execution engine\n");
    abort();
  }
  if(error) {
    fprintf(stderr, "error: %s\n", error);
    LLVMDisposeMessage(error);
    exit(EXIT_FAILURE);
  }
  user m;
  m.name = "John";
  m.age = 17;
  int* (*stuff)(user*) = (int* (*)(user*)) LLVMGetFunctionAddress(engine, "stuff");
  printf("%d\n", *stuff(&m));
  LLVMDisposeBuilder(builder);
  LLVMDisposeExecutionEngine(engine);
  return 0;
}

Basically the function I'm trying to build is equal to something like this in C

int* stuff(user* u) {
    return &u->age;
}

So what happens is it crashes with a segmentation fault, i've debugged it using GDB and it seems like it happens in the line where i do the BuildGEP call with the following error from the LLVM shared library

Program received signal SIGSEGV, Segmentation fault.
0xb533baec in llvm::PointerType::get(llvm::Type*, unsigned int) ()

Now at this point i have no idea what i'm doing.

The main 2 questions i need answer for: How do you use the LLVMBuildGEP from the C API? Am i thinking this completely wrong?

LLVMStructCreateNamed creates an opaque struct type (like struct user; would in C), meaning LLVM doesn't know what the elements inside are. You'll need to populate that struct with a definition, likely using LLVMStructSetBody . So something like:

LLVMTypeRef struct_user_members[] = {
    LLVMPointerType(LLVMInt8Type(), 0),
    LLVMInt32Type()
};
LLVMStructSetBody(type, struct_user_members, 2, false);

After that, LLVMBuildGEP should be able to dereference the members, which it looks to me like you've done appropriately.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM