feature: codegen
This commit is contained in:
parent
ad7355c94c
commit
92f4708ce7
|
@ -1,10 +1,55 @@
|
||||||
|
|
||||||
#include <codegen/backend.h>
|
#include <codegen/backend.h>
|
||||||
|
#include <llvm-c/Core.h>
|
||||||
|
#include <llvm-c/TargetMachine.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <llvm/backend.h>
|
#include <llvm/backend.h>
|
||||||
#include <llvm/parser.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 {
|
typedef enum LLVMBackendError_t {
|
||||||
UnresolvedImport
|
UnresolvedImport
|
||||||
} LLVMBackendError;
|
} LLVMBackendError;
|
||||||
|
|
|
@ -2,6 +2,35 @@
|
||||||
#ifndef LLVM_CODEGEN_BACKEND_H_
|
#ifndef LLVM_CODEGEN_BACKEND_H_
|
||||||
#define 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);
|
void llvm_backend_init(void);
|
||||||
|
|
||||||
#endif // LLVM_CODEGEN_BACKEND_H_
|
#endif // LLVM_CODEGEN_BACKEND_H_
|
||||||
|
|
|
@ -1,14 +1,103 @@
|
||||||
|
|
||||||
#include <codegen/backend.h>
|
#include <codegen/backend.h>
|
||||||
#include <llvm-c/Core.h>
|
#include <llvm-c/Core.h>
|
||||||
|
#include <llvm-c/Target.h>
|
||||||
|
#include <llvm-c/TargetMachine.h>
|
||||||
#include <llvm-c/Types.h>
|
#include <llvm-c/Types.h>
|
||||||
#include <llvm/parser.h>
|
#include <llvm/parser.h>
|
||||||
#include <llvm/types.h>
|
#include <llvm/types.h>
|
||||||
#include <llvm/variables.h>
|
#include <llvm/variables.h>
|
||||||
#include <set/types.h>
|
#include <set/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.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**) {
|
BackendError parse_module(const Module* module, void**) {
|
||||||
|
if (module == NULL) {
|
||||||
|
return new_backend_impl_error(Implementation, NULL, "no module");
|
||||||
|
}
|
||||||
|
|
||||||
LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit));
|
LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit));
|
||||||
|
|
||||||
// we start with a LLVM module
|
// 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);
|
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);
|
delete_global_scope(global_scope);
|
||||||
|
|
||||||
LLVMDisposeModule(unit->module);
|
LLVMDisposeModule(unit->module);
|
||||||
|
|
Loading…
Reference in New Issue