feature: codegen

This commit is contained in:
Sven Vogel 2024-05-27 13:05:56 +02:00
parent ad7355c94c
commit 92f4708ce7
3 changed files with 169 additions and 0 deletions

View File

@ -1,10 +1,55 @@
#include <codegen/backend.h>
#include <llvm-c/Core.h>
#include <llvm-c/TargetMachine.h>
#include <sys/log.h>
#include <ast/ast.h>
#include <llvm/backend.h>
#include <llvm/parser.h>
Target create_native_target() {
Target target;
target.triple.str = LLVMGetDefaultTargetTriple();
target.triple.allocation = LLVM;
target.cpu.str = LLVMGetHostCPUName();
target.cpu.allocation = LLVM;
target.features.str = LLVMGetHostCPUFeatures();
target.features.allocation = LLVM;
target.opt = LLVMCodeGenLevelDefault;
target.reloc = LLVMRelocDefault;
target.model = LLVMCodeModelDefault;
return target;
}
Target create_target_from_config() {
PANIC("NOT IMPLEMENTED");
}
static void delete_string(String string) {
switch (string.allocation) {
case LLVM:
LLVMDisposeMessage(string.str);
break;
case LIBC:
free(string.str);
break;
case NONE:
break;
}
}
void delete_target(Target target) {
delete_string(target.name);
delete_string(target.cpu);
delete_string(target.features);
delete_string(target.triple);
}
typedef enum LLVMBackendError_t {
UnresolvedImport
} LLVMBackendError;

View File

@ -2,6 +2,35 @@
#ifndef LLVM_CODEGEN_BACKEND_H_
#define LLVM_CODEGEN_BACKEND_H_
#include <llvm-c/TargetMachine.h>
enum StringAllocation_t {
LLVM,
LIBC,
NONE
};
typedef struct String_t {
enum StringAllocation_t allocation;
char* str;
} String;
typedef struct Target_t {
String name;
String triple;
String cpu;
String features;
LLVMCodeGenOptLevel opt;
LLVMRelocMode reloc;
LLVMCodeModel model;
} Target;
Target create_native_target();
Target create_target_from_config();
void delete_target(Target target);
void llvm_backend_init(void);
#endif // LLVM_CODEGEN_BACKEND_H_

View File

@ -1,14 +1,103 @@
#include <codegen/backend.h>
#include <llvm-c/Core.h>
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#include <llvm-c/Types.h>
#include <llvm/parser.h>
#include <llvm/types.h>
#include <llvm/variables.h>
#include <set/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llvm/backend.h"
BackendError export_IR(LLVMBackendCompileUnit* unit) {
BackendError err = SUCCESS;
char* ir = LLVMPrintModuleToString(unit->module);
FILE* output = fopen("module.ll", "w");
if (output == NULL) {
err = new_backend_impl_error(Implementation, NULL,
"unable to open file for writing");
LLVMDisposeMessage(ir);
}
fprintf(output, "%s", ir);
fflush(output);
fclose(output);
LLVMDisposeMessage(ir);
return err;
}
BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) {
LLVMTargetRef llvm_target = NULL;
char* error = NULL;
if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) !=
0) {
BackendError err =
new_backend_impl_error(Implementation, NULL, strdup(error));
LLVMDisposeMessage(error);
return err;
}
LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(
llvm_target, target->triple.str, target->cpu.str, target->features.str,
target->opt, target->reloc, target->model);
LLVMCodeGenFileType file_type = LLVMObjectFile;
if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output",
file_type, &error) != 0) {
BackendError err =
new_backend_impl_error(Implementation, NULL, strdup(error));
LLVMDisposeMessage(error);
return err;
}
return SUCCESS;
}
void list_available_targets() {
LLVMInitializeAllTargetInfos();
printf("Available targets:\n");
LLVMTargetRef target = LLVMGetFirstTarget();
while (target) {
const char* name = LLVMGetTargetName(target);
const char* desc = LLVMGetTargetDescription(target);
printf(" - %s: (%s)\n", name, desc);
target = LLVMGetNextTarget(target);
}
char* default_triple = LLVMGetDefaultTargetTriple();
printf("Default: %s\n", default_triple);
LLVMDisposeMessage(default_triple);
}
BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) {
BackendError err = SUCCESS;
export_object(unit, target);
return err;
}
BackendError parse_module(const Module* module, void**) {
if (module == NULL) {
return new_backend_impl_error(Implementation, NULL, "no module");
}
LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit));
// we start with a LLVM module
@ -32,6 +121,12 @@ BackendError parse_module(const Module* module, void**) {
err = new_backend_impl_error(Implementation, NULL, err_msg);
}
Target target = create_native_target();
export_module(unit, &target);
delete_target(target);
delete_global_scope(global_scope);
LLVMDisposeModule(unit->module);