diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 5abcb95..8820120 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,10 +1,55 @@ #include +#include +#include #include #include #include #include +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; diff --git a/src/llvm/backend.h b/src/llvm/backend.h index 26ef165..4625aa7 100644 --- a/src/llvm/backend.h +++ b/src/llvm/backend.h @@ -2,6 +2,35 @@ #ifndef LLVM_CODEGEN_BACKEND_H_ #define LLVM_CODEGEN_BACKEND_H_ +#include + +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_ diff --git a/src/llvm/parser.c b/src/llvm/parser.c index e143d0c..4ff827d 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -1,14 +1,103 @@ #include #include +#include +#include #include #include #include #include #include +#include #include +#include + +#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);