从 AST 内存错误生成 LLVM 代码

LLVM code generation from AST memory error

提问人:mantissa 提问时间:11/14/2023 最后编辑:mantissa 更新时间:11/14/2023 访问量:30

问:

我有这个 AST 结构,它填充了 Bison 生成的 parser.c。 首先,我尝试编译的虚拟代码:

start
int a;
a = 5;
end

AST:

struct ASTNode {
    NodeType type;       
    LLVMValueRef llvmValue;
    union {
        int intValue;                            
        double doubleValue;                     
        bool boolValue;                          
        char *identifier;                       
        struct BinaryOpNode binaryOp;            
        struct AssignmentNode assignment;        
        struct VariableDeclarationNode variableDeclaration; 
    } data;
};

我像这样设置 llvm:

void setupLLVM() {
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();

GlobalContext = LLVMContextCreate();
GlobalModule = LLVMModuleCreateWithNameInContext("test_module", GlobalContext);
GlobalBuilder = LLVMCreateBuilderInContext(GlobalContext); }

这是ast.c,它包含实际代码:

ASTNode* createVariableDeclarationNode(char *type, char *identifier) {
    ASTNode* node = malloc(sizeof(ASTNode));
    node->type = AST_VARIABLE_DECLARATION;
    node->data.variableDeclaration.type = _strdup(type);
    node->data.variableDeclaration.identifier = _strdup(identifier);
    
    LLVMTypeRef varType = 0;

    if (strcmp(type, "int") == 0) {
        varType = LLVMInt32TypeInContext(GlobalContext);
    }
    else if (strcmp(type, "double") == 0) {
        varType = LLVMDoubleTypeInContext(GlobalContext);
    }
    else if (strcmp(type, "bool") == 0) {
        varType = LLVMInt1TypeInContext(GlobalContext);
    }

    LLVMValueRef var = LLVMAddGlobal(GlobalModule, varType, identifier);
    LLVMSetInitializer(var, LLVMConstInt(varType, 0, 0));
    node->llvmValue = var;

    printNode(node);
    return node;
}

以及生成 const int 节点的代码:

ASTNode* createIntNode(int value) {
    ASTNode* node = malloc(sizeof(ASTNode));
    node->type = AST_INTEGER;
    node->data.intValue = value;
    node->llvmValue = LLVMConstInt(LLVMInt32TypeInContext(GlobalContext), value, 0);
    printNode(node);
    return node;
}

现在,当我想做作业 a = 5 时,我会这样做:

ASTNode* createAssignmentNode(char *identifier, ASTNode *expression) {
    ASTNode* node = malloc(sizeof(ASTNode));
    node->type = AST_ASSIGNMENT;
    node->data.assignment.identifier = _strdup(identifier);
    node->data.assignment.expression = expression;
    LLVMValueRef var = LLVMGetNamedGlobal(GlobalModule, identifier);

    if (!var || !expression->llvmValue) {
        printf("assigment error\n");
    }
    // CRASH
    node->llvmValue = LLVMBuildStore(GlobalBuilder, expression->llvmValue, var);
  
    printNode(node);
    return node;
}

但是在 node->llvmValue = LLVMBuildStore(GlobalBuilder, expression->llvmValue, var); 我在0x0000000000000050地址中读取了错误: 调用堆栈:

enter image description here

本地变量:

enter image description here

请帮我找到错误的原因。

C 编译器构造 LLVM bison

评论

0赞 Harith 11/14/2023
作为最后两个参数传递是否像您在定义的行为中所做的那样?NULLLLVMBuildStore()LLVMBuildStore(GlobalBuilder, expression->llvmValue, var);
0赞 mantissa 11/14/2023
@Harith 你为什么这么认为?在我的本地变量屏幕中,定义了此变量。NULL
0赞 Harith 11/14/2023
我问的是笼统的,因为允许将指针传递给 ,这可能是也可能不是定义的行为。if (!var || !expression->llvmValue) { printf("assigment error\n"); }NULLLLVMBuildStore()
0赞 mantissa 11/14/2023
@Harith是的,这是 If 语句中的失误,但 nvm

答:

1赞 mantissa 11/14/2023 #1

好的,我想通了。我的设置LLVM是错误的。现在是

void setupLLVM() {
    LLVMInitializeNativeTarget();
    LLVMInitializeNativeAsmPrinter();
    LLVMInitializeNativeAsmParser();

    GlobalContext = LLVMContextCreate();
    GlobalModule = LLVMModuleCreateWithNameInContext("test_module", GlobalContext);
    GlobalBuilder = LLVMCreateBuilderInContext(GlobalContext);

    LLVMTypeRef mainFuncType = LLVMFunctionType(LLVMVoidTypeInContext(GlobalContext), NULL, 0, 0);
    LLVMValueRef mainFunc = LLVMAddFunction(GlobalModule, "main", mainFuncType);

    LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(GlobalContext, mainFunc, "entry");
    LLVMPositionBuilderAtEnd(GlobalBuilder, entry);
}

我需要为自己创建模块。(EP)。