added: string constants to backend llvm
This commit is contained in:
parent
de253a94ab
commit
560e24950e
|
@ -106,6 +106,7 @@ TargetConfig* default_target_config() {
|
||||||
config->link_search_paths = g_array_new(FALSE, FALSE, sizeof(char*));
|
config->link_search_paths = g_array_new(FALSE, FALSE, sizeof(char*));
|
||||||
config->lld_fatal_warnings = FALSE;
|
config->lld_fatal_warnings = FALSE;
|
||||||
config->gsc_fatal_warnings = FALSE;
|
config->gsc_fatal_warnings = FALSE;
|
||||||
|
config->import_paths = mem_new_g_array(MemoryNamespaceOpt, sizeof(char*));
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
@ -208,6 +209,9 @@ TargetConfig* default_target_config_from_args() {
|
||||||
g_array_free(files, TRUE);
|
g_array_free(files, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* default_import_path = mem_strdup(MemoryNamespaceOpt, ".");
|
||||||
|
g_array_append_val(config->import_paths, default_import_path);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ typedef struct TargetConfig_t {
|
||||||
bool lld_fatal_warnings;
|
bool lld_fatal_warnings;
|
||||||
// treat parser warnings as errors
|
// treat parser warnings as errors
|
||||||
bool gsc_fatal_warnings;
|
bool gsc_fatal_warnings;
|
||||||
|
GArray* import_paths;
|
||||||
} TargetConfig;
|
} TargetConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -164,7 +164,35 @@ static void run_backend_codegen(const Module* module, const TargetConfig* target
|
||||||
err = deinit_backend();
|
err = deinit_backend();
|
||||||
}
|
}
|
||||||
|
|
||||||
static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, ModuleFile* file) {
|
const char* get_absolute_import_path(const TargetConfig* config, const char* import_target_name) {
|
||||||
|
INFO("resolving absolute path for import target: %s", import_target_name);
|
||||||
|
|
||||||
|
for (guint i = 0; i < config->import_paths->len; i++) {
|
||||||
|
const char* import_directory_path = g_array_index(config->import_paths, char*, i);
|
||||||
|
|
||||||
|
char* path = g_build_filename(import_directory_path, import_target_name, NULL);
|
||||||
|
char* cwd = g_get_current_dir();
|
||||||
|
char* canonical = g_canonicalize_filename(path, cwd);
|
||||||
|
|
||||||
|
const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS);
|
||||||
|
const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR);
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
|
g_free(cwd);
|
||||||
|
|
||||||
|
if (exists && !is_dir) {
|
||||||
|
INFO("import target found at: %s", canonical);
|
||||||
|
return canonical;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(canonical);
|
||||||
|
}
|
||||||
|
|
||||||
|
// file not found
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, ModuleFile* file, const TargetConfig *target) {
|
||||||
AST_NODE_PTR root_module = AST_new_node(empty_location(), AST_Module, NULL);
|
AST_NODE_PTR root_module = AST_new_node(empty_location(), AST_Module, NULL);
|
||||||
|
|
||||||
if (compile_file_to_ast(root_module, file) == EXIT_SUCCESS) {
|
if (compile_file_to_ast(root_module, file) == EXIT_SUCCESS) {
|
||||||
|
@ -175,7 +203,12 @@ static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, Modu
|
||||||
if (child->kind == AST_Import) {
|
if (child->kind == AST_Import) {
|
||||||
AST_NODE_PTR imported_module = AST_new_node(empty_location(), AST_Module, NULL);
|
AST_NODE_PTR imported_module = AST_new_node(empty_location(), AST_Module, NULL);
|
||||||
|
|
||||||
ModuleFile *imported_file = push_file(unit, child->value);
|
const char* path = get_absolute_import_path(target, child->value);
|
||||||
|
if (path == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleFile *imported_file = push_file(unit, path);
|
||||||
|
|
||||||
if (compile_file_to_ast(imported_module, imported_file) == EXIT_SUCCESS) {
|
if (compile_file_to_ast(imported_module, imported_file) == EXIT_SUCCESS) {
|
||||||
AST_merge_modules(root_module, i + 1, imported_module);
|
AST_merge_modules(root_module, i + 1, imported_module);
|
||||||
|
@ -196,7 +229,7 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) {
|
||||||
print_message(Info, "Building target: %s", target->name);
|
print_message(Info, "Building target: %s", target->name);
|
||||||
|
|
||||||
ModuleFile *file = push_file(unit, target->root_module);
|
ModuleFile *file = push_file(unit, target->root_module);
|
||||||
AST_NODE_PTR ast = compile_module_with_dependencies(unit, file);
|
AST_NODE_PTR ast = compile_module_with_dependencies(unit, file, target);
|
||||||
|
|
||||||
if (ast != NULL) {
|
if (ast != NULL) {
|
||||||
if (setup_target_environment(target) == 0) {
|
if (setup_target_environment(target) == 0) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <llvm/llvm-ir/expr.h>
|
#include <llvm/llvm-ir/expr.h>
|
||||||
#include <llvm/llvm-ir/types.h>
|
#include <llvm/llvm-ir/types.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit,
|
BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit,
|
||||||
LLVMLocalScope *scope,
|
LLVMLocalScope *scope,
|
||||||
|
@ -394,6 +395,29 @@ BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
|
LLVMBuilderRef builder, Dereference* dereference,
|
||||||
|
LLVMValueRef *llvm_result) {
|
||||||
|
BackendError err;
|
||||||
|
|
||||||
|
LLVMValueRef llvm_pointer = get_variable(scope, dereference->variable->impl.variable->name);
|
||||||
|
LLVMTypeRef llvm_deref_type = NULL;
|
||||||
|
err = get_type_impl(unit, scope->func_scope->global_scope, dereference->variable->result, &llvm_deref_type);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMValueRef* index = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef));
|
||||||
|
err = impl_expr(unit, scope, builder, dereference->index, FALSE, index);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*llvm_result = LLVMBuildGEP2(builder, llvm_deref_type, llvm_pointer, index, 1, "expr.deref");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder, Expression *expr,
|
LLVMBuilderRef builder, Expression *expr,
|
||||||
LLVMBool reference,
|
LLVMBool reference,
|
||||||
|
@ -427,6 +451,10 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
err = impl_address_of(unit, scope, builder, &expr->impl.addressOf,
|
err = impl_address_of(unit, scope, builder, &expr->impl.addressOf,
|
||||||
llvm_result);
|
llvm_result);
|
||||||
break;
|
break;
|
||||||
|
case ExpressionKindDereference:
|
||||||
|
err = impl_deref(unit, scope, builder, &expr->impl.dereference,
|
||||||
|
llvm_result);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
err = new_backend_impl_error(Implementation, NULL, "unknown expression");
|
err = new_backend_impl_error(Implementation, NULL, "unknown expression");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <llvm/parser.h>
|
#include <llvm/parser.h>
|
||||||
#include <set/types.h>
|
#include <set/types.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <set/set.h>
|
||||||
|
|
||||||
#define BASE_BYTES 4
|
#define BASE_BYTES 4
|
||||||
#define BITS_PER_BYTE 8
|
#define BITS_PER_BYTE 8
|
||||||
|
@ -33,6 +34,17 @@ static BackendError get_const_composite_value(CompositeType composite,
|
||||||
llvm_value);
|
llvm_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackendError impl_reference_const(TypeValue* value, LLVMValueRef* llvm_value) {
|
||||||
|
BackendError err = SUCCESS;
|
||||||
|
if (value->type->kind == TypeKindReference && compareTypes(value->type, (Type*) &StringLiteralType)) {
|
||||||
|
// is string literal
|
||||||
|
*llvm_value = LLVMConstString(value->value, strlen(value->value), FALSE);
|
||||||
|
} else {
|
||||||
|
err = new_backend_impl_error(Implementation, value->nodePtr, "reference initializer can only be string literals");
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
BackendError get_const_type_value(LLVMBackendCompileUnit* unit,
|
BackendError get_const_type_value(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
TypeValue* gemstone_value,
|
TypeValue* gemstone_value,
|
||||||
|
@ -58,9 +70,7 @@ BackendError get_const_type_value(LLVMBackendCompileUnit* unit,
|
||||||
llvm_value);
|
llvm_value);
|
||||||
break;
|
break;
|
||||||
case TypeKindReference:
|
case TypeKindReference:
|
||||||
err =
|
err = impl_reference_const(gemstone_value, llvm_value);
|
||||||
new_backend_impl_error(Implementation, gemstone_value->nodePtr,
|
|
||||||
"reference cannot be constant value");
|
|
||||||
break;
|
break;
|
||||||
case TypeKindBox:
|
case TypeKindBox:
|
||||||
err =
|
err =
|
||||||
|
|
|
@ -207,6 +207,9 @@ static BackendError build_module(LLVMBackendCompileUnit* unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = impl_functions(unit, global_scope, module->functions);
|
err = impl_functions(unit, global_scope, module->functions);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
char* error = NULL;
|
char* error = NULL;
|
||||||
if (LLVMVerifyModule(unit->module, LLVMAbortProcessAction, &error)) {
|
if (LLVMVerifyModule(unit->module, LLVMAbortProcessAction, &error)) {
|
||||||
|
|
|
@ -1292,7 +1292,8 @@ int createDeref(Expression *ParentExpression, AST_NODE_PTR currentNode) {
|
||||||
assert(currentNode->child_count == 2);
|
assert(currentNode->child_count == 2);
|
||||||
Dereference deref;
|
Dereference deref;
|
||||||
deref.nodePtr = currentNode;
|
deref.nodePtr = currentNode;
|
||||||
deref.index = createExpression(AST_get_node(currentNode, 0));
|
AST_NODE_PTR expression_node = AST_get_node(currentNode, 1);
|
||||||
|
deref.index = createExpression(expression_node);
|
||||||
|
|
||||||
//index has to be made
|
//index has to be made
|
||||||
if (deref.index == NULL) {
|
if (deref.index == NULL) {
|
||||||
|
@ -1323,11 +1324,11 @@ int createDeref(Expression *ParentExpression, AST_NODE_PTR currentNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deref.variable = createExpression(AST_get_node(currentNode, 1));
|
deref.variable = createExpression(AST_get_node(currentNode, 0));
|
||||||
|
|
||||||
//variable has to be made
|
//variable has to be made
|
||||||
if (deref.index == NULL) {
|
if (deref.index == NULL) {
|
||||||
print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error, "Invalid index");
|
print_diagnostic(current_file, &AST_get_node(currentNode, 0)->location, Error, "Invalid index");
|
||||||
return SEMANTIC_ERROR;
|
return SEMANTIC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,13 @@
|
||||||
#define SEMANTIC_OK 0
|
#define SEMANTIC_OK 0
|
||||||
#define SEMANTIC_ERROR 1
|
#define SEMANTIC_ERROR 1
|
||||||
|
|
||||||
|
// type of string literal
|
||||||
|
extern const Type StringLiteralType;
|
||||||
|
|
||||||
Module * create_set(AST_NODE_PTR rootNodePtr );
|
Module * create_set(AST_NODE_PTR rootNodePtr );
|
||||||
|
|
||||||
void delete_set(Module* module);
|
void delete_set(Module* module);
|
||||||
|
|
||||||
|
bool compareTypes(Type *leftType, Type *rightType);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue