feature: codegen
This commit is contained in:
parent
ad7355c94c
commit
92f4708ce7
|
@ -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;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue