I’m working on a repl for a simple language using the LLVM C API.
So far I’m able to generate IR for an expression and execute it,
but if I do that again the function cannot be found
here is a simplified version of my ‘runner’ code:
#include "lang_runner.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
#include "codegen.h"
#include "llvm_backend.h"
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/Utils.h>
int run_value(LLVMExecutionEngineRef engine, LLVMValueRef value) {
if (value == NULL) {
fprintf(stderr, "Unable to codegen for node\n");
return 1;
}
// Dump IR.
LLVMDumpValue(value);
void *fp = LLVMGetPointerToGlobal(engine, value);
double (*FP)() = (double (*)())(intptr_t)fp;
if (FP) {
fprintf(stderr, "Evaluted to %f\n", FP());
return 0;
} else {
fprintf(stderr, "Could not find function pointer");
return 1;
}
}
int LLVMRuntime(int repl, char *path) {
LLVMModuleRef module = LLVMModuleCreateWithName("ylc");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMExecutionEngineRef engine;
LLVMInitializeNativeTarget();
LLVMLinkInMCJIT();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
char *msg;
if (LLVMCreateExecutionEngineForModule(&engine, module, &msg) == 1) {
fprintf(stderr, "%s\n", msg);
LLVMDisposeMessage(msg);
return 1;
}
char *input = malloc(sizeof(char) * INPUT_BUFSIZE);
for (;;) {
repl_input(input, INPUT_BUFSIZE, "> ");
AST *ast = parse(input);
print_ast(*ast, 0);
printf("\n");
LLVMValueRef value = codegen(ast, module, builder);
run_value(engine, value);
free_ast(ast);
}
// Dump entire module.
LLVMDumpModule(module);
LLVMDisposeBuilder(builder);
LLVMDisposeModule(module);
return 0;
}
and this is the function that generates the IR for the ‘top-level’ expression:
#include "codegen.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/Core.h>
#include <llvm-c/Types.h>
#include <stdio.h>
#include <stdlib.h>
static int counter = 0;
static LLVMValueRef codegen_main(AST *ast, LLVMModuleRef module,
LLVMBuilderRef builder) {
LLVMTypeRef funcType = LLVMFunctionType(LLVMDoubleType(), NULL, 0, 0);
// Create function.
char name[10];
snprintf(name, sizeof(name), "main_%d", counter);
counter++;
LLVMValueRef func = LLVMAddFunction(module, name, funcType);
LLVMSetLinkage(func, LLVMExternalLinkage);
// Create basic block.
LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, name);
LLVMPositionBuilderAtEnd(builder, block);
// Generate body.
LLVMValueRef body = codegen(ast->data.AST_MAIN.body, module, builder);
if (body == NULL) {
printf("delete func??");
LLVMDeleteFunction(func);
return NULL;
}
// Insert body as return vale.
LLVMBuildRet(builder, body);
// Verify function.
if (LLVMVerifyFunction(func, LLVMPrintMessageAction) == 1) {
fprintf(stderr, "Invalid function");
LLVMDeleteFunction(func);
return NULL;
}
return func;
}
and this is the output when I try to execute more than one expression with the dumped IR and comments:
> ./build/lang # call the repl executable
> -1.23 # prompt + input for the repl
main: # printed representation of my ast
statements:
(-1.230000 )
define double @main_0() { # IR dump
main_0:
ret double 0xBFF3AE1480000000
}
Evaluted to -1.230000 # works the first time
> -2.3 # second input
main: # ast dump
statements:
(-2.300000 )
define double @main_1() { # IR dump
main_1:
ret double 0xC002666660000000
}
Could not find function pointer # execution failed
I’m still quite new to LLVM and I’m struggling to understand how to ‘reuse’ the module & execution engine I’ve set up
here is a link to my repository: GitHub - crawdaddie/ylc at llvm-codegen-be
please let me know if this question needs more clarification or info