From e01d4c48084ae0bc4669da30fb3b33f46287621c Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 15:56:44 +0200 Subject: [PATCH] added debug and error messages --- src/llvm/backend.c | 6 ++++ src/llvm/parser.c | 67 ++++++++++++++++++++++++++++++++++++-------- src/llvm/types.c | 51 +++++++++++++++++++++++++++++---- src/llvm/variables.c | 28 ++++++++++++++---- 4 files changed, 128 insertions(+), 24 deletions(-) diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 8820120..dc24897 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -8,16 +9,20 @@ #include Target create_native_target() { + DEBUG("creating native target..."); Target target; target.triple.str = LLVMGetDefaultTargetTriple(); target.triple.allocation = LLVM; + assert(target.triple.str != NULL); target.cpu.str = LLVMGetHostCPUName(); target.cpu.allocation = LLVM; + assert(target.cpu.str != NULL); target.features.str = LLVMGetHostCPUFeatures(); target.features.allocation = LLVM; + assert(target.features.str != NULL); target.opt = LLVMCodeGenLevelDefault; target.reloc = LLVMRelocDefault; @@ -31,6 +36,7 @@ Target create_target_from_config() { } static void delete_string(String string) { + DEBUG("deleting string..."); switch (string.allocation) { case LLVM: LLVMDisposeMessage(string.str); diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 4ff827d..e7d8287 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,52 +12,81 @@ #include #include #include +#include -#include "llvm/backend.h" +#define EXPORT_IR 1 + +BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting module to LLVM-IR..."); -BackendError export_IR(LLVMBackendCompileUnit* unit) { BackendError err = SUCCESS; + // convert module to LLVM-IR char* ir = LLVMPrintModuleToString(unit->module); - FILE* output = fopen("module.ll", "w"); + // construct file name + char* filename = alloca(strlen(target->name.str) + 2); + sprintf(filename, "%s.ll", target->name.str); + + INFO("Writing LLVM-IR to %s", filename); + + DEBUG("opening file..."); + FILE* output = fopen(filename, "w"); if (output == NULL) { + ERROR("unable to open file: %s", filename); err = new_backend_impl_error(Implementation, NULL, "unable to open file for writing"); LLVMDisposeMessage(ir); } - fprintf(output, "%s", ir); + DEBUG("printing LLVM-IR to file..."); + + size_t bytes = fprintf(output, "%s", ir); + + // flush and close output file fflush(output); fclose(output); + INFO("%ld bytes written to %s", bytes, filename); + + // clean up LLVM-IR string LLVMDisposeMessage(ir); return err; } BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting object file..."); + + INFO("Using target (%s): %s with features: %s", target->name.str, + target->triple.str, target->features.str); + LLVMTargetRef llvm_target = NULL; char* error = NULL; + DEBUG("creating target..."); if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != 0) { - BackendError err = - new_backend_impl_error(Implementation, NULL, strdup(error)); + ERROR("failed to create target machine: %s", error); + BackendError err = new_backend_impl_error( + Implementation, NULL, "unable to create target machine"); LLVMDisposeMessage(error); return err; } + DEBUG("Creating target machine..."); 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; + DEBUG("Generating code..."); if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output", file_type, &error) != 0) { + ERROR("failed to emit code: %s", error); BackendError err = - new_backend_impl_error(Implementation, NULL, strdup(error)); + new_backend_impl_error(Implementation, NULL, "failed to emit code"); LLVMDisposeMessage(error); return err; } @@ -65,6 +95,7 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { } void list_available_targets() { + DEBUG("initializing all available targets..."); LLVMInitializeAllTargetInfos(); printf("Available targets:\n"); @@ -86,21 +117,32 @@ void list_available_targets() { } BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting module..."); + BackendError err = SUCCESS; export_object(unit, target); + if (EXPORT_IR) { + export_IR(unit, target); + } else { + DEBUG("not exporting LLVM-IR"); + } + return err; } BackendError parse_module(const Module* module, void**) { + DEBUG("generating code for module %p", module); if (module == NULL) { + ERROR("no module for codegen"); return new_backend_impl_error(Implementation, NULL, "no module"); } LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit)); // we start with a LLVM module + DEBUG("creating LLVM context and module"); unit->context = LLVMContextCreate(); unit->module = LLVMModuleCreateWithNameInContext("gemstone application", unit->context); @@ -109,6 +151,8 @@ BackendError parse_module(const Module* module, void**) { BackendError err = new_backend_error(Success); + DEBUG("generating code..."); + err = impl_types(unit, global_scope, module->types); // NOTE: functions of boxes are not stored in the box itself, // thus for a box we only implement the type @@ -116,11 +160,6 @@ BackendError parse_module(const Module* module, void**) { err = impl_global_variables(unit, global_scope, module->variables); - char* err_msg = NULL; - if (LLVMPrintModuleToFile(unit->module, "out.s", &err_msg)) { - err = new_backend_impl_error(Implementation, NULL, err_msg); - } - Target target = create_native_target(); export_module(unit, &target); @@ -138,6 +177,7 @@ BackendError parse_module(const Module* module, void**) { } LLVMGlobalScope* new_global_scope() { + DEBUG("creating global scope..."); LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope)); scope->functions = g_hash_table_new(g_str_hash, g_str_equal); @@ -149,6 +189,7 @@ LLVMGlobalScope* new_global_scope() { LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, LLVMLocalScope* parent_scope) { + DEBUG("creating local scope..."); LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); scope->variables = g_hash_table_new(g_str_hash, g_str_equal); @@ -160,11 +201,13 @@ LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, } void delete_local_scope(LLVMLocalScope* scope) { + DEBUG("deleting global scope..."); g_hash_table_unref(scope->variables); free(scope); } void delete_global_scope(LLVMGlobalScope* scope) { + DEBUG("deleting global scope..."); g_hash_table_unref(scope->functions); g_hash_table_unref(scope->types); g_hash_table_unref(scope->variables); diff --git a/src/llvm/types.c b/src/llvm/types.c index 87d87ca..e41ff95 100644 --- a/src/llvm/types.c +++ b/src/llvm/types.c @@ -1,21 +1,28 @@ #include #include #include +#include #include #include -#include +#include + +#define BASE_BYTES 4 +#define BITS_PER_BYTE 8 BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, PrimitiveType primtive, LLVMTypeRef* llvm_type) { switch (primtive) { case Int: + DEBUG("implementing primtive integral type..."); *llvm_type = LLVMInt32TypeInContext(unit->context); break; case Float: + DEBUG("implementing primtive float type..."); *llvm_type = LLVMFloatTypeInContext(unit->context); break; default: + PANIC("invalid primitive type"); break; } @@ -24,8 +31,9 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, LLVMTypeRef* llvm_type) { - LLVMTypeRef integral_type = - LLVMIntTypeInContext(unit->context, (int)(4 * scale) * 8); + size_t bits = (int)(4 * scale) * BITS_PER_BYTE; + DEBUG("implementing integral type of size: %ld", bits); + LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits); *llvm_type = integral_type; @@ -34,9 +42,12 @@ BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, LLVMTypeRef* llvm_type) { + DEBUG("implementing floating point..."); LLVMTypeRef float_type = NULL; - switch ((int)(scale * 4)) { + size_t bytes = (int)(scale * BASE_BYTES); + DEBUG("requested float of bytes: %ld", bytes); + switch (bytes) { case 2: float_type = LLVMHalfTypeInContext(unit->context); break; @@ -50,6 +61,8 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, float_type = LLVMFP128TypeInContext(unit->context); break; default: + ERROR("invalid floating point size: %ld bit", + bytes * BITS_PER_BYTE); break; } @@ -65,6 +78,7 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, BackendError impl_composite_type(LLVMBackendCompileUnit* unit, CompositeType* composite, LLVMTypeRef* llvm_type) { + DEBUG("implementing composite type..."); BackendError err = SUCCESS; switch (composite->primitive) { @@ -75,12 +89,14 @@ BackendError impl_composite_type(LLVMBackendCompileUnit* unit, if (composite->sign == Signed) { err = impl_float_type(unit, composite->scale, llvm_type); } else { + ERROR("unsgined floating point not supported"); err = new_backend_impl_error( Implementation, composite->nodePtr, "unsigned floating-point not supported"); } break; default: + PANIC("invalid primitive kind: %ld", composite->primitive); break; } @@ -97,6 +113,7 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Type* gemstone_type, LLVMTypeRef* llvm_type) { + DEBUG("retrieving type implementation..."); BackendError err = new_backend_impl_error(Implementation, gemstone_type->nodePtr, "No type implementation covers type"); @@ -118,6 +135,9 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, err = impl_box_type(unit, scope, &gemstone_type->impl.box, llvm_type); break; + default: + PANIC("invalid type kind: %ld", gemstone_type->kind); + break; } return err; @@ -125,6 +145,7 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BoxType* box, LLVMTypeRef* llvm_type) { + DEBUG("implementing box type..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, box->member); @@ -135,8 +156,11 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GArray* members = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef)); + DEBUG("implementing box members..."); while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { - Type* member_type = ((BoxMember*) val)->type; + Type* member_type = ((BoxMember*)val)->type; + + DEBUG("implementing member: %s ", ((BoxMember*)val)->name); LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, member_type, &llvm_type); @@ -147,6 +171,7 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, g_array_append_val(members, llvm_type); } + DEBUG("implemented %ld members", members->len); if (err.kind == Success) { *llvm_type = @@ -162,6 +187,7 @@ BackendError impl_reference_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, ReferenceType reference, LLVMTypeRef* llvm_type) { + DEBUG("implementing reference type..."); BackendError err = SUCCESS; LLVMTypeRef type = NULL; err = get_type_impl(unit, scope, reference, &type); @@ -176,6 +202,7 @@ BackendError impl_reference_type(LLVMBackendCompileUnit* unit, BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type, const char* alias, LLVMGlobalScope* scope) { BackendError err = SUCCESS; + DEBUG("implementing type of kind: %ld as %s", gemstone_type->kind, alias); LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, gemstone_type, &llvm_type); @@ -189,6 +216,7 @@ BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type, BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GHashTable* types) { + DEBUG("implementing given types of %p", types); GHashTableIter iterator; g_hash_table_iter_init(&iterator, types); @@ -211,6 +239,7 @@ BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError get_primitive_default_value(PrimitiveType type, LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building primitive %ld default value", type); switch (type) { case Int: *llvm_value = LLVMConstIntOfString(llvm_type, "0", 10); @@ -219,6 +248,7 @@ BackendError get_primitive_default_value(PrimitiveType type, *llvm_value = LLVMConstRealOfString(llvm_type, "0"); break; default: + ERROR("invalid primitive type: %ld", type); return new_backend_impl_error(Implementation, NULL, "unknown primitive type"); } @@ -229,6 +259,7 @@ BackendError get_primitive_default_value(PrimitiveType type, BackendError get_composite_default_value(CompositeType* composite, LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building composite default value"); BackendError err = SUCCESS; switch (composite->primitive) { @@ -245,6 +276,7 @@ BackendError get_composite_default_value(CompositeType* composite, } break; default: + ERROR("invalid primitive type: %ld", composite->primitive); break; } @@ -253,6 +285,7 @@ BackendError get_composite_default_value(CompositeType* composite, BackendError get_reference_default_value(LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building reference default value"); *llvm_value = LLVMConstPointerNull(llvm_type); return SUCCESS; @@ -261,6 +294,7 @@ BackendError get_reference_default_value(LLVMTypeRef llvm_type, BackendError get_box_default_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BoxType* type, LLVMValueRef* llvm_value) { + DEBUG("building box default value..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, type->member); @@ -282,8 +316,10 @@ BackendError get_box_default_value(LLVMBackendCompileUnit* unit, } } + DEBUG("build %ld member default values", constants->len); + *llvm_value = LLVMConstStructInContext( - unit->context, (LLVMValueRef*) constants->data, constants->len, 0); + unit->context, (LLVMValueRef*)constants->data, constants->len, 0); g_array_free(constants, FALSE); @@ -318,6 +354,9 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, err = get_box_default_value(unit, scope, &gemstone_type->impl.box, llvm_value); break; + default: + PANIC("invalid type kind: %ld", gemstone_type->kind); + break; } return err; diff --git a/src/llvm/variables.c b/src/llvm/variables.c index 51d2170..4552e39 100644 --- a/src/llvm/variables.c +++ b/src/llvm/variables.c @@ -5,11 +5,13 @@ #include #include #include +#include BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, VariableDeclaration* decl, const char* name) { + DEBUG("implementing global declaration: ", name); BackendError err = SUCCESS; LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, &decl->type, &llvm_type); @@ -18,12 +20,14 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, return err; } + DEBUG("creating global variable..."); LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); LLVMValueRef initial_value = NULL; err = get_type_default_value(unit, scope, &decl->type, &initial_value); if (err.kind == Success) { + DEBUG("setting default value..."); LLVMSetInitializer(global, initial_value); g_hash_table_insert(scope->variables, (gpointer)name, global); } @@ -32,9 +36,9 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, } BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, - LLVMGlobalScope* scope, - VariableDefiniton* def, - const char* name) { + LLVMGlobalScope* scope, + VariableDefiniton* def, const char* name) { + DEBUG("implementing global definition: %s", name); BackendError err = SUCCESS; LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, &def->declaration.type, &llvm_type); @@ -43,13 +47,16 @@ BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, return err; } + DEBUG("creating global variable..."); LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); // FIXME: resolve initializer expression! LLVMValueRef initial_value = NULL; - err = get_type_default_value(unit, scope, &def->declaration.type, &initial_value); + err = get_type_default_value(unit, scope, &def->declaration.type, + &initial_value); if (err.kind == Success) { + DEBUG("setting default value"); LLVMSetInitializer(global, initial_value); g_hash_table_insert(scope->variables, (gpointer)name, global); } @@ -68,13 +75,16 @@ BackendError impl_global_variable(LLVMBackendCompileUnit* unit, unit, scope, &gemstone_var->impl.declaration, alias); break; case VariableKindDefinition: - err = impl_global_definiton( - unit, scope, &gemstone_var->impl.definiton, alias); + err = impl_global_definiton(unit, scope, + &gemstone_var->impl.definiton, alias); break; case VariableKindBoxMember: err = new_backend_impl_error(Implementation, gemstone_var->nodePtr, "member variable cannot be "); break; + default: + PANIC("invalid variable kind: %ld", gemstone_var->kind); + break; } return err; @@ -83,6 +93,7 @@ BackendError impl_global_variable(LLVMBackendCompileUnit* unit, BackendError impl_global_variables(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GHashTable* variables) { + DEBUG("implementing global variables..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, variables); @@ -91,6 +102,7 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, BackendError err; + size_t variable_count = 0; while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { err = impl_global_variable(unit, (Variable*)val, (const char*)key, scope); @@ -98,7 +110,11 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, if (err.kind != Success) { break; } + + variable_count++; } + DEBUG("implemented %ld global variables", variable_count); + return err; }