added debug and error messages
This commit is contained in:
parent
92f4708ce7
commit
e01d4c4808
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <codegen/backend.h>
|
#include <codegen/backend.h>
|
||||||
#include <llvm-c/Core.h>
|
#include <llvm-c/Core.h>
|
||||||
#include <llvm-c/TargetMachine.h>
|
#include <llvm-c/TargetMachine.h>
|
||||||
|
@ -8,16 +9,20 @@
|
||||||
#include <llvm/parser.h>
|
#include <llvm/parser.h>
|
||||||
|
|
||||||
Target create_native_target() {
|
Target create_native_target() {
|
||||||
|
DEBUG("creating native target...");
|
||||||
Target target;
|
Target target;
|
||||||
|
|
||||||
target.triple.str = LLVMGetDefaultTargetTriple();
|
target.triple.str = LLVMGetDefaultTargetTriple();
|
||||||
target.triple.allocation = LLVM;
|
target.triple.allocation = LLVM;
|
||||||
|
assert(target.triple.str != NULL);
|
||||||
|
|
||||||
target.cpu.str = LLVMGetHostCPUName();
|
target.cpu.str = LLVMGetHostCPUName();
|
||||||
target.cpu.allocation = LLVM;
|
target.cpu.allocation = LLVM;
|
||||||
|
assert(target.cpu.str != NULL);
|
||||||
|
|
||||||
target.features.str = LLVMGetHostCPUFeatures();
|
target.features.str = LLVMGetHostCPUFeatures();
|
||||||
target.features.allocation = LLVM;
|
target.features.allocation = LLVM;
|
||||||
|
assert(target.features.str != NULL);
|
||||||
|
|
||||||
target.opt = LLVMCodeGenLevelDefault;
|
target.opt = LLVMCodeGenLevelDefault;
|
||||||
target.reloc = LLVMRelocDefault;
|
target.reloc = LLVMRelocDefault;
|
||||||
|
@ -31,6 +36,7 @@ Target create_target_from_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_string(String string) {
|
static void delete_string(String string) {
|
||||||
|
DEBUG("deleting string...");
|
||||||
switch (string.allocation) {
|
switch (string.allocation) {
|
||||||
case LLVM:
|
case LLVM:
|
||||||
LLVMDisposeMessage(string.str);
|
LLVMDisposeMessage(string.str);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <llvm-c/Target.h>
|
#include <llvm-c/Target.h>
|
||||||
#include <llvm-c/TargetMachine.h>
|
#include <llvm-c/TargetMachine.h>
|
||||||
#include <llvm-c/Types.h>
|
#include <llvm-c/Types.h>
|
||||||
|
#include <llvm/backend.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>
|
||||||
|
@ -11,52 +12,81 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/log.h>
|
||||||
|
|
||||||
#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;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
|
// convert module to LLVM-IR
|
||||||
char* ir = LLVMPrintModuleToString(unit->module);
|
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) {
|
if (output == NULL) {
|
||||||
|
ERROR("unable to open file: %s", filename);
|
||||||
err = new_backend_impl_error(Implementation, NULL,
|
err = new_backend_impl_error(Implementation, NULL,
|
||||||
"unable to open file for writing");
|
"unable to open file for writing");
|
||||||
LLVMDisposeMessage(ir);
|
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);
|
fflush(output);
|
||||||
fclose(output);
|
fclose(output);
|
||||||
|
|
||||||
|
INFO("%ld bytes written to %s", bytes, filename);
|
||||||
|
|
||||||
|
// clean up LLVM-IR string
|
||||||
LLVMDisposeMessage(ir);
|
LLVMDisposeMessage(ir);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) {
|
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;
|
LLVMTargetRef llvm_target = NULL;
|
||||||
char* error = NULL;
|
char* error = NULL;
|
||||||
|
|
||||||
|
DEBUG("creating target...");
|
||||||
if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) !=
|
if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) !=
|
||||||
0) {
|
0) {
|
||||||
BackendError err =
|
ERROR("failed to create target machine: %s", error);
|
||||||
new_backend_impl_error(Implementation, NULL, strdup(error));
|
BackendError err = new_backend_impl_error(
|
||||||
|
Implementation, NULL, "unable to create target machine");
|
||||||
LLVMDisposeMessage(error);
|
LLVMDisposeMessage(error);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("Creating target machine...");
|
||||||
LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(
|
LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(
|
||||||
llvm_target, target->triple.str, target->cpu.str, target->features.str,
|
llvm_target, target->triple.str, target->cpu.str, target->features.str,
|
||||||
target->opt, target->reloc, target->model);
|
target->opt, target->reloc, target->model);
|
||||||
|
|
||||||
LLVMCodeGenFileType file_type = LLVMObjectFile;
|
LLVMCodeGenFileType file_type = LLVMObjectFile;
|
||||||
|
|
||||||
|
DEBUG("Generating code...");
|
||||||
if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output",
|
if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output",
|
||||||
file_type, &error) != 0) {
|
file_type, &error) != 0) {
|
||||||
|
ERROR("failed to emit code: %s", error);
|
||||||
BackendError err =
|
BackendError err =
|
||||||
new_backend_impl_error(Implementation, NULL, strdup(error));
|
new_backend_impl_error(Implementation, NULL, "failed to emit code");
|
||||||
LLVMDisposeMessage(error);
|
LLVMDisposeMessage(error);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +95,7 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_available_targets() {
|
void list_available_targets() {
|
||||||
|
DEBUG("initializing all available targets...");
|
||||||
LLVMInitializeAllTargetInfos();
|
LLVMInitializeAllTargetInfos();
|
||||||
|
|
||||||
printf("Available targets:\n");
|
printf("Available targets:\n");
|
||||||
|
@ -86,21 +117,32 @@ void list_available_targets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) {
|
BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) {
|
||||||
|
DEBUG("exporting module...");
|
||||||
|
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
export_object(unit, target);
|
export_object(unit, target);
|
||||||
|
|
||||||
|
if (EXPORT_IR) {
|
||||||
|
export_IR(unit, target);
|
||||||
|
} else {
|
||||||
|
DEBUG("not exporting LLVM-IR");
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError parse_module(const Module* module, void**) {
|
BackendError parse_module(const Module* module, void**) {
|
||||||
|
DEBUG("generating code for module %p", module);
|
||||||
if (module == NULL) {
|
if (module == NULL) {
|
||||||
|
ERROR("no module for codegen");
|
||||||
return new_backend_impl_error(Implementation, NULL, "no module");
|
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
|
||||||
|
DEBUG("creating LLVM context and module");
|
||||||
unit->context = LLVMContextCreate();
|
unit->context = LLVMContextCreate();
|
||||||
unit->module = LLVMModuleCreateWithNameInContext("gemstone application",
|
unit->module = LLVMModuleCreateWithNameInContext("gemstone application",
|
||||||
unit->context);
|
unit->context);
|
||||||
|
@ -109,6 +151,8 @@ BackendError parse_module(const Module* module, void**) {
|
||||||
|
|
||||||
BackendError err = new_backend_error(Success);
|
BackendError err = new_backend_error(Success);
|
||||||
|
|
||||||
|
DEBUG("generating code...");
|
||||||
|
|
||||||
err = impl_types(unit, global_scope, module->types);
|
err = impl_types(unit, global_scope, module->types);
|
||||||
// NOTE: functions of boxes are not stored in the box itself,
|
// NOTE: functions of boxes are not stored in the box itself,
|
||||||
// thus for a box we only implement the type
|
// 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);
|
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();
|
Target target = create_native_target();
|
||||||
|
|
||||||
export_module(unit, &target);
|
export_module(unit, &target);
|
||||||
|
@ -138,6 +177,7 @@ BackendError parse_module(const Module* module, void**) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMGlobalScope* new_global_scope() {
|
LLVMGlobalScope* new_global_scope() {
|
||||||
|
DEBUG("creating global scope...");
|
||||||
LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope));
|
LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope));
|
||||||
|
|
||||||
scope->functions = g_hash_table_new(g_str_hash, g_str_equal);
|
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* new_local_scope(LLVMGlobalScope* global_scope,
|
||||||
LLVMLocalScope* parent_scope) {
|
LLVMLocalScope* parent_scope) {
|
||||||
|
DEBUG("creating local scope...");
|
||||||
LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope));
|
LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope));
|
||||||
|
|
||||||
scope->variables = g_hash_table_new(g_str_hash, g_str_equal);
|
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) {
|
void delete_local_scope(LLVMLocalScope* scope) {
|
||||||
|
DEBUG("deleting global scope...");
|
||||||
g_hash_table_unref(scope->variables);
|
g_hash_table_unref(scope->variables);
|
||||||
free(scope);
|
free(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_global_scope(LLVMGlobalScope* scope) {
|
void delete_global_scope(LLVMGlobalScope* scope) {
|
||||||
|
DEBUG("deleting global scope...");
|
||||||
g_hash_table_unref(scope->functions);
|
g_hash_table_unref(scope->functions);
|
||||||
g_hash_table_unref(scope->types);
|
g_hash_table_unref(scope->types);
|
||||||
g_hash_table_unref(scope->variables);
|
g_hash_table_unref(scope->variables);
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
#include <codegen/backend.h>
|
#include <codegen/backend.h>
|
||||||
#include <llvm-c/Core.h>
|
#include <llvm-c/Core.h>
|
||||||
#include <llvm-c/Types.h>
|
#include <llvm-c/Types.h>
|
||||||
|
#include <llvm/parser.h>
|
||||||
#include <llvm/types.h>
|
#include <llvm/types.h>
|
||||||
#include <set/types.h>
|
#include <set/types.h>
|
||||||
#include <llvm/parser.h>
|
#include <sys/log.h>
|
||||||
|
|
||||||
|
#define BASE_BYTES 4
|
||||||
|
#define BITS_PER_BYTE 8
|
||||||
|
|
||||||
BackendError impl_primtive_type(LLVMBackendCompileUnit* unit,
|
BackendError impl_primtive_type(LLVMBackendCompileUnit* unit,
|
||||||
PrimitiveType primtive,
|
PrimitiveType primtive,
|
||||||
LLVMTypeRef* llvm_type) {
|
LLVMTypeRef* llvm_type) {
|
||||||
switch (primtive) {
|
switch (primtive) {
|
||||||
case Int:
|
case Int:
|
||||||
|
DEBUG("implementing primtive integral type...");
|
||||||
*llvm_type = LLVMInt32TypeInContext(unit->context);
|
*llvm_type = LLVMInt32TypeInContext(unit->context);
|
||||||
break;
|
break;
|
||||||
case Float:
|
case Float:
|
||||||
|
DEBUG("implementing primtive float type...");
|
||||||
*llvm_type = LLVMFloatTypeInContext(unit->context);
|
*llvm_type = LLVMFloatTypeInContext(unit->context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
PANIC("invalid primitive type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +31,9 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit,
|
||||||
|
|
||||||
BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale,
|
BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale,
|
||||||
LLVMTypeRef* llvm_type) {
|
LLVMTypeRef* llvm_type) {
|
||||||
LLVMTypeRef integral_type =
|
size_t bits = (int)(4 * scale) * BITS_PER_BYTE;
|
||||||
LLVMIntTypeInContext(unit->context, (int)(4 * scale) * 8);
|
DEBUG("implementing integral type of size: %ld", bits);
|
||||||
|
LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits);
|
||||||
|
|
||||||
*llvm_type = integral_type;
|
*llvm_type = integral_type;
|
||||||
|
|
||||||
|
@ -34,9 +42,12 @@ BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale,
|
||||||
|
|
||||||
BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale,
|
BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale,
|
||||||
LLVMTypeRef* llvm_type) {
|
LLVMTypeRef* llvm_type) {
|
||||||
|
DEBUG("implementing floating point...");
|
||||||
LLVMTypeRef float_type = NULL;
|
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:
|
case 2:
|
||||||
float_type = LLVMHalfTypeInContext(unit->context);
|
float_type = LLVMHalfTypeInContext(unit->context);
|
||||||
break;
|
break;
|
||||||
|
@ -50,6 +61,8 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale,
|
||||||
float_type = LLVMFP128TypeInContext(unit->context);
|
float_type = LLVMFP128TypeInContext(unit->context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ERROR("invalid floating point size: %ld bit",
|
||||||
|
bytes * BITS_PER_BYTE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +78,7 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale,
|
||||||
BackendError impl_composite_type(LLVMBackendCompileUnit* unit,
|
BackendError impl_composite_type(LLVMBackendCompileUnit* unit,
|
||||||
CompositeType* composite,
|
CompositeType* composite,
|
||||||
LLVMTypeRef* llvm_type) {
|
LLVMTypeRef* llvm_type) {
|
||||||
|
DEBUG("implementing composite type...");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
switch (composite->primitive) {
|
switch (composite->primitive) {
|
||||||
|
@ -75,12 +89,14 @@ BackendError impl_composite_type(LLVMBackendCompileUnit* unit,
|
||||||
if (composite->sign == Signed) {
|
if (composite->sign == Signed) {
|
||||||
err = impl_float_type(unit, composite->scale, llvm_type);
|
err = impl_float_type(unit, composite->scale, llvm_type);
|
||||||
} else {
|
} else {
|
||||||
|
ERROR("unsgined floating point not supported");
|
||||||
err = new_backend_impl_error(
|
err = new_backend_impl_error(
|
||||||
Implementation, composite->nodePtr,
|
Implementation, composite->nodePtr,
|
||||||
"unsigned floating-point not supported");
|
"unsigned floating-point not supported");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
PANIC("invalid primitive kind: %ld", composite->primitive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +113,7 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
|
|
||||||
BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
Type* gemstone_type, LLVMTypeRef* llvm_type) {
|
Type* gemstone_type, LLVMTypeRef* llvm_type) {
|
||||||
|
DEBUG("retrieving type implementation...");
|
||||||
BackendError err =
|
BackendError err =
|
||||||
new_backend_impl_error(Implementation, gemstone_type->nodePtr,
|
new_backend_impl_error(Implementation, gemstone_type->nodePtr,
|
||||||
"No type implementation covers type");
|
"No type implementation covers type");
|
||||||
|
@ -118,6 +135,9 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
err =
|
err =
|
||||||
impl_box_type(unit, scope, &gemstone_type->impl.box, llvm_type);
|
impl_box_type(unit, scope, &gemstone_type->impl.box, llvm_type);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
PANIC("invalid type kind: %ld", gemstone_type->kind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -125,6 +145,7 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
|
|
||||||
BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
BoxType* box, LLVMTypeRef* llvm_type) {
|
BoxType* box, LLVMTypeRef* llvm_type) {
|
||||||
|
DEBUG("implementing box type...");
|
||||||
GHashTableIter iterator;
|
GHashTableIter iterator;
|
||||||
g_hash_table_iter_init(&iterator, box->member);
|
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));
|
GArray* members = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef));
|
||||||
|
|
||||||
|
DEBUG("implementing box members...");
|
||||||
while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) {
|
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;
|
LLVMTypeRef llvm_type = NULL;
|
||||||
err = get_type_impl(unit, scope, member_type, &llvm_type);
|
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);
|
g_array_append_val(members, llvm_type);
|
||||||
}
|
}
|
||||||
|
DEBUG("implemented %ld members", members->len);
|
||||||
|
|
||||||
if (err.kind == Success) {
|
if (err.kind == Success) {
|
||||||
*llvm_type =
|
*llvm_type =
|
||||||
|
@ -162,6 +187,7 @@ BackendError impl_reference_type(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
ReferenceType reference,
|
ReferenceType reference,
|
||||||
LLVMTypeRef* llvm_type) {
|
LLVMTypeRef* llvm_type) {
|
||||||
|
DEBUG("implementing reference type...");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
LLVMTypeRef type = NULL;
|
LLVMTypeRef type = NULL;
|
||||||
err = get_type_impl(unit, scope, reference, &type);
|
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,
|
BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type,
|
||||||
const char* alias, LLVMGlobalScope* scope) {
|
const char* alias, LLVMGlobalScope* scope) {
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
DEBUG("implementing type of kind: %ld as %s", gemstone_type->kind, alias);
|
||||||
|
|
||||||
LLVMTypeRef llvm_type = NULL;
|
LLVMTypeRef llvm_type = NULL;
|
||||||
err = get_type_impl(unit, scope, gemstone_type, &llvm_type);
|
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,
|
BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
|
||||||
GHashTable* types) {
|
GHashTable* types) {
|
||||||
|
DEBUG("implementing given types of %p", types);
|
||||||
GHashTableIter iterator;
|
GHashTableIter iterator;
|
||||||
g_hash_table_iter_init(&iterator, types);
|
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,
|
BackendError get_primitive_default_value(PrimitiveType type,
|
||||||
LLVMTypeRef llvm_type,
|
LLVMTypeRef llvm_type,
|
||||||
LLVMValueRef* llvm_value) {
|
LLVMValueRef* llvm_value) {
|
||||||
|
DEBUG("building primitive %ld default value", type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Int:
|
case Int:
|
||||||
*llvm_value = LLVMConstIntOfString(llvm_type, "0", 10);
|
*llvm_value = LLVMConstIntOfString(llvm_type, "0", 10);
|
||||||
|
@ -219,6 +248,7 @@ BackendError get_primitive_default_value(PrimitiveType type,
|
||||||
*llvm_value = LLVMConstRealOfString(llvm_type, "0");
|
*llvm_value = LLVMConstRealOfString(llvm_type, "0");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ERROR("invalid primitive type: %ld", type);
|
||||||
return new_backend_impl_error(Implementation, NULL,
|
return new_backend_impl_error(Implementation, NULL,
|
||||||
"unknown primitive type");
|
"unknown primitive type");
|
||||||
}
|
}
|
||||||
|
@ -229,6 +259,7 @@ BackendError get_primitive_default_value(PrimitiveType type,
|
||||||
BackendError get_composite_default_value(CompositeType* composite,
|
BackendError get_composite_default_value(CompositeType* composite,
|
||||||
LLVMTypeRef llvm_type,
|
LLVMTypeRef llvm_type,
|
||||||
LLVMValueRef* llvm_value) {
|
LLVMValueRef* llvm_value) {
|
||||||
|
DEBUG("building composite default value");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
switch (composite->primitive) {
|
switch (composite->primitive) {
|
||||||
|
@ -245,6 +276,7 @@ BackendError get_composite_default_value(CompositeType* composite,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ERROR("invalid primitive type: %ld", composite->primitive);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +285,7 @@ BackendError get_composite_default_value(CompositeType* composite,
|
||||||
|
|
||||||
BackendError get_reference_default_value(LLVMTypeRef llvm_type,
|
BackendError get_reference_default_value(LLVMTypeRef llvm_type,
|
||||||
LLVMValueRef* llvm_value) {
|
LLVMValueRef* llvm_value) {
|
||||||
|
DEBUG("building reference default value");
|
||||||
*llvm_value = LLVMConstPointerNull(llvm_type);
|
*llvm_value = LLVMConstPointerNull(llvm_type);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
@ -261,6 +294,7 @@ BackendError get_reference_default_value(LLVMTypeRef llvm_type,
|
||||||
BackendError get_box_default_value(LLVMBackendCompileUnit* unit,
|
BackendError get_box_default_value(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope, BoxType* type,
|
LLVMGlobalScope* scope, BoxType* type,
|
||||||
LLVMValueRef* llvm_value) {
|
LLVMValueRef* llvm_value) {
|
||||||
|
DEBUG("building box default value...");
|
||||||
GHashTableIter iterator;
|
GHashTableIter iterator;
|
||||||
g_hash_table_iter_init(&iterator, type->member);
|
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(
|
*llvm_value = LLVMConstStructInContext(
|
||||||
unit->context, (LLVMValueRef*) constants->data, constants->len, 0);
|
unit->context, (LLVMValueRef*)constants->data, constants->len, 0);
|
||||||
|
|
||||||
g_array_free(constants, FALSE);
|
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,
|
err = get_box_default_value(unit, scope, &gemstone_type->impl.box,
|
||||||
llvm_value);
|
llvm_value);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
PANIC("invalid type kind: %ld", gemstone_type->kind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
#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 <sys/log.h>
|
||||||
|
|
||||||
BackendError impl_global_declaration(LLVMBackendCompileUnit* unit,
|
BackendError impl_global_declaration(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
VariableDeclaration* decl,
|
VariableDeclaration* decl,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
|
DEBUG("implementing global declaration: ", name);
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
LLVMTypeRef llvm_type = NULL;
|
LLVMTypeRef llvm_type = NULL;
|
||||||
err = get_type_impl(unit, scope, &decl->type, &llvm_type);
|
err = get_type_impl(unit, scope, &decl->type, &llvm_type);
|
||||||
|
@ -18,12 +20,14 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("creating global variable...");
|
||||||
LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name);
|
LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name);
|
||||||
|
|
||||||
LLVMValueRef initial_value = NULL;
|
LLVMValueRef initial_value = NULL;
|
||||||
err = get_type_default_value(unit, scope, &decl->type, &initial_value);
|
err = get_type_default_value(unit, scope, &decl->type, &initial_value);
|
||||||
|
|
||||||
if (err.kind == Success) {
|
if (err.kind == Success) {
|
||||||
|
DEBUG("setting default value...");
|
||||||
LLVMSetInitializer(global, initial_value);
|
LLVMSetInitializer(global, initial_value);
|
||||||
g_hash_table_insert(scope->variables, (gpointer)name, global);
|
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,
|
BackendError impl_global_definiton(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
VariableDefiniton* def,
|
VariableDefiniton* def, const char* name) {
|
||||||
const char* name) {
|
DEBUG("implementing global definition: %s", name);
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
LLVMTypeRef llvm_type = NULL;
|
LLVMTypeRef llvm_type = NULL;
|
||||||
err = get_type_impl(unit, scope, &def->declaration.type, &llvm_type);
|
err = get_type_impl(unit, scope, &def->declaration.type, &llvm_type);
|
||||||
|
@ -43,13 +47,16 @@ BackendError impl_global_definiton(LLVMBackendCompileUnit* unit,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("creating global variable...");
|
||||||
LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name);
|
LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name);
|
||||||
|
|
||||||
// FIXME: resolve initializer expression!
|
// FIXME: resolve initializer expression!
|
||||||
LLVMValueRef initial_value = NULL;
|
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) {
|
if (err.kind == Success) {
|
||||||
|
DEBUG("setting default value");
|
||||||
LLVMSetInitializer(global, initial_value);
|
LLVMSetInitializer(global, initial_value);
|
||||||
g_hash_table_insert(scope->variables, (gpointer)name, global);
|
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);
|
unit, scope, &gemstone_var->impl.declaration, alias);
|
||||||
break;
|
break;
|
||||||
case VariableKindDefinition:
|
case VariableKindDefinition:
|
||||||
err = impl_global_definiton(
|
err = impl_global_definiton(unit, scope,
|
||||||
unit, scope, &gemstone_var->impl.definiton, alias);
|
&gemstone_var->impl.definiton, alias);
|
||||||
break;
|
break;
|
||||||
case VariableKindBoxMember:
|
case VariableKindBoxMember:
|
||||||
err = new_backend_impl_error(Implementation, gemstone_var->nodePtr,
|
err = new_backend_impl_error(Implementation, gemstone_var->nodePtr,
|
||||||
"member variable cannot be ");
|
"member variable cannot be ");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
PANIC("invalid variable kind: %ld", gemstone_var->kind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -83,6 +93,7 @@ BackendError impl_global_variable(LLVMBackendCompileUnit* unit,
|
||||||
BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
GHashTable* variables) {
|
GHashTable* variables) {
|
||||||
|
DEBUG("implementing global variables...");
|
||||||
GHashTableIter iterator;
|
GHashTableIter iterator;
|
||||||
g_hash_table_iter_init(&iterator, variables);
|
g_hash_table_iter_init(&iterator, variables);
|
||||||
|
|
||||||
|
@ -91,6 +102,7 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
||||||
|
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
|
size_t variable_count = 0;
|
||||||
while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) {
|
while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) {
|
||||||
err =
|
err =
|
||||||
impl_global_variable(unit, (Variable*)val, (const char*)key, scope);
|
impl_global_variable(unit, (Variable*)val, (const char*)key, scope);
|
||||||
|
@ -98,7 +110,11 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
||||||
if (err.kind != Success) {
|
if (err.kind != Success) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("implemented %ld global variables", variable_count);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue