簡體   English   中英

核心對象的 LLVM C-API 生命周期

[英]LLVM C-API Lifecycles of core objects

我已經開始玩 LLVM,制作一種寵物語言。 我正在使用 C-API。 我有一個解析器和基本的 AST,但我在 LLVM 方面遇到了一些障礙。

以下是我的代碼的縮小版本,用於說明我當前的問題:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llvm-c/Core.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm-c/Target.h"
#include "llvm-c/Analysis.h"
#include "llvm-c/BitWriter.h"

static LLVMModuleRef mod;
static LLVMBuilderRef builder;
static LLVMExecutionEngineRef engine;

typedef struct oper_t {
    const char * name;
    
    LLVMTypeRef args[2];
    LLVMTypeRef ret; 
    LLVMValueRef val;
} oper_t;

#define NUM_OPER 2
static oper_t oper[NUM_OPER] = {
    { .name = "function1" },
    { .name = "function2" },
};

void codegen_init(const char * filename)
{
    char *error;
 
    mod = LLVMModuleCreateWithName(filename);
    builder = LLVMCreateBuilder();
    
    error = NULL;
    LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
    if(error) printf("LLVM init Verify message \"%s\"\n", error);
    LLVMDisposeMessage(error);
    
    error = NULL;
    LLVMLinkInMCJIT();
    LLVMInitializeNativeTarget();
    LLVMInitializeNativeAsmPrinter();
    if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0)
    {
        fprintf(stderr, "LLVM failed to create execution engine\n");
        abort();
    }
    if(error) 
    {
        printf("LLVM Execution Engine message %s\n", error);
        LLVMDisposeMessage(error);
        exit(EXIT_FAILURE);
    }
}

int runOper(oper_t * o, long a, long b) 
{
    LLVMValueRef v, l, r;
    
    o->args[0] = LLVMInt32Type();
    o->args[1] = LLVMInt32Type();
    
    o->ret = LLVMFunctionType(LLVMInt32Type(), o->args, 2, 0);
    o->val = LLVMAddFunction(mod, o->name, o->ret);
    
    LLVMBasicBlockRef entry = LLVMAppendBasicBlock(o->val, "entry");
    LLVMPositionBuilderAtEnd(builder, entry);
    
    l = LLVMConstInt(LLVMInt32Type(), a, 0); 
    r = LLVMConstInt(LLVMInt32Type(), b, 0); 
    v = LLVMBuildAdd(builder, l, r, "add");
    
    LLVMBuildRet(builder, v);
    
    char *error = NULL;
    LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
    if(error) printf("LLVM func Verify message \"%s\"\n", error);
    LLVMDisposeMessage(error);
    
    LLVMGenericValueRef g = LLVMRunFunction(engine, o->val, 0, NULL);
    
    printf("LLVM func executed without crash\n");
    
    LLVMDeleteFunction(o->val);
    
    return (long)LLVMGenericValueToInt(g, 1);
}

int main(int argc, char const *argv[])
{
    long val;
    
    codegen_init("test");

    val = runOper(&oper[0], 3, 4);
    printf("3 + 4 is %ld\n", val);
    
    val = runOper(&oper[1], 6, 7);
    printf("6 + 7 is %ld\n", val);
}

我可以使用以下命令編譯它:

gcc test.c `llvm-config --cflags --cppflags --ldflags --libs core executionengine mcjit interpreter analysis native bitwriter --system-libs` -o test.exe

或者,我也嘗試過:

gcc `llvm-config --cflags --cppflags` -c test.c
g++ test.o `llvm-config --cxxflags --ldflags --libs core executionengine mcjit interpreter analysis native bitwriter --system-libs` -o test.exe

無論哪種方式,我都會得到這個結果:

$ ./test.exe
LLVM init Verify message ""
LLVM func Verify message ""
LLVM func executed without crash
3 + 4 is 7
LLVM func Verify message ""
Segmentation fault

我也試過使用 clang 只是為了很好的衡量。

顯然我在濫用 LLVM C-API。 我一直在努力了解何時可以安全調用 API 函數,以及何時可以安全地釋放/刪除 LLVM 引用的 memory。 例如LLVMTypeRef args[2]參數,我在LLVMFunctionType的 LLVM C-API 源代碼中看到它正在為 args 參數創建一個 ArrayRef。 這意味着我必須堅持使用 args 參數,直到 LLVM 完成它。 我真的不知道那是什么時候。 (我打算在堆上分配這個memory)

簡單地說,如果有人不能在這個例子中解釋我做錯了什么,而是更根本地解釋我應該如何找出我做錯了什么,我會很高興。

LLVM C-API 文檔對 API 中可用的函數進行了很好的細分,但我沒有發現它對如何調用 API 函數給出太多描述,即。 什么順序是安全的/預期的。

我還發現此文檔很有幫助,因為可以輕松搜索單個 function 原型。 但同樣它沒有給出如何使用 C-API 的上下文或示例。

最后我不得不參考Paul Smith 的博客,它現在有點過時了,但絕對是我能走到這一步的原因。

PS我不希望一切都為我拼寫出來,我只是想建議如何自學LLVM

C++ 中最容易理解基本設計:如果將指向object的指針作為構造函數參數傳遞,即。 x=new Foo(…, y, …) ,那么y的壽命必須比x長。 這也適用於諸如CallInst::Create()ConstantInt::get()之類的包裝器,它們都采用指向對象的指針並返回構造的對象。

但還有更多。 一些對象承擔了構造對象的所有權,因此您根本不允許刪除構造的 object。 例如,您不能刪除ConstantInt::get()返回的內容。 作為一般規則,任何在 C++ API 中稱為 create... 的東西都會返回您可以刪除的東西,而任何稱為 get... 的東西都會返回由另一個 LLVM object 擁有的東西。 我敢肯定也有例外。

你可能會發現構建 LLVM 的調試版本很有幫助,除非你比我聰明得多。額外的斷言很棒。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM