fixed: loops
This commit is contained in:
parent
7f93daa780
commit
5a59f0fb3d
|
@ -159,6 +159,10 @@ TargetConfig* default_target_config_from_args() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: free vvvvvvvvvvvvv
|
||||||
|
char* cwd = g_get_current_dir();
|
||||||
|
g_array_append_val(config->link_search_paths, cwd);
|
||||||
|
|
||||||
if (is_option_set("link-paths")) {
|
if (is_option_set("link-paths")) {
|
||||||
const Option* opt = get_option("link-paths");
|
const Option* opt = get_option("link-paths");
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,8 @@ Target create_target_from_config(const TargetConfig* config) {
|
||||||
|
|
||||||
target.opt = llvm_opt_from_int(config->optimization_level);
|
target.opt = llvm_opt_from_int(config->optimization_level);
|
||||||
|
|
||||||
INFO("Configured target: %s/%d: (%s) on %s { %s }", target.name, target.opt,
|
INFO("Configured target: %s/%d: (%s) on %s { %s }", target.name.str, target.opt,
|
||||||
target.triple, target.cpu, target.features);
|
target.triple.str, target.cpu.str, target.features.str);
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
extern int lld_main(int Argc, const char **Argv, const char **outstr);
|
extern int lld_main(int Argc, const char **Argv, const char **outstr);
|
||||||
|
|
||||||
const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) {
|
const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) {
|
||||||
|
INFO("resolving absolute path for link target: %s", link_target_name);
|
||||||
|
|
||||||
for (guint i = 0; i < config->link_search_paths->len; i++) {
|
for (guint i = 0; i < config->link_search_paths->len; i++) {
|
||||||
const char* link_directory_path = g_array_index(config->link_search_paths, char*, i);
|
const char* link_directory_path = g_array_index(config->link_search_paths, char*, i);
|
||||||
|
@ -28,6 +29,7 @@ const char* get_absolute_link_path(const TargetConfig* config, const char* link_
|
||||||
g_free(cwd);
|
g_free(cwd);
|
||||||
|
|
||||||
if (exists && !is_dir) {
|
if (exists && !is_dir) {
|
||||||
|
INFO("link target found at: %s", canonical);
|
||||||
return canonical;
|
return canonical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,9 +50,11 @@ TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfi
|
||||||
config->colorize = stdout_supports_ansi_esc();
|
config->colorize = stdout_supports_ansi_esc();
|
||||||
|
|
||||||
// append build object file
|
// append build object file
|
||||||
const char* target_object = get_absolute_link_path(target_config, (const char*) target->name.str);
|
char* basename = g_strjoin(".", target_config->name, "o", NULL);
|
||||||
|
char* filename = g_build_filename(target_config->archive_directory, basename, NULL);
|
||||||
|
const char* target_object = get_absolute_link_path(target_config, (const char*) filename);
|
||||||
if (target_object == NULL) {
|
if (target_object == NULL) {
|
||||||
ERROR("failed to resolve path to target object: %s", target->name.str);
|
ERROR("failed to resolve path to target object: %s", filename);
|
||||||
lld_delete_link_config(config);
|
lld_delete_link_config(config);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -99,13 +103,18 @@ GArray* lld_create_lld_arguments(TargetLinkConfig* config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError lld_link_target(TargetLinkConfig* config) {
|
BackendError lld_link_target(TargetLinkConfig* config) {
|
||||||
|
DEBUG("linking target...");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
GArray* argv = lld_create_lld_arguments(config);
|
GArray* argv = lld_create_lld_arguments(config);
|
||||||
|
|
||||||
|
INFO("Linking target...");
|
||||||
|
|
||||||
const char* message = NULL;
|
const char* message = NULL;
|
||||||
int status = lld_main((int) argv->len, (const char**) argv->data, &message);
|
int status = lld_main((int) argv->len, (const char**) argv->data, &message);
|
||||||
|
|
||||||
|
INFO("done linking target...");
|
||||||
|
|
||||||
g_array_free(argv, TRUE);
|
g_array_free(argv, TRUE);
|
||||||
|
|
||||||
if (message != NULL) {
|
if (message != NULL) {
|
||||||
|
|
|
@ -6,33 +6,41 @@
|
||||||
#include <llvm/llvm-ir/types.h>
|
#include <llvm/llvm-ir/types.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
|
||||||
BackendError impl_bitwise_operation([[maybe_unused]] LLVMBackendCompileUnit *unit,
|
BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit,
|
||||||
[[maybe_unused]] LLVMLocalScope *scope,
|
LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder,
|
LLVMBuilderRef builder,
|
||||||
Operation *operation,
|
Operation *operation,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve lhs and rhs or op
|
Expression *rhs = NULL;
|
||||||
LLVMValueRef rhs = NULL;
|
Expression *lhs = NULL;
|
||||||
LLVMValueRef lhs = NULL;
|
LLVMValueRef llvm_rhs = NULL;
|
||||||
|
LLVMValueRef llvm_lhs = NULL;
|
||||||
|
|
||||||
if (operation->impl.bitwise == BitwiseNot) {
|
if (operation->impl.arithmetic == BitwiseNot) {
|
||||||
// single operand
|
// single operand
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
} else {
|
} else {
|
||||||
// two operands
|
// two operands
|
||||||
|
lhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, lhs, &llvm_lhs);
|
||||||
|
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 1);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (operation->impl.bitwise) {
|
switch (operation->impl.bitwise) {
|
||||||
case BitwiseAnd:
|
case BitwiseAnd:
|
||||||
*llvm_result = LLVMBuildAnd(builder, lhs, rhs, "bitwise and");
|
*llvm_result = LLVMBuildAnd(builder, llvm_lhs, llvm_rhs, "bitwise and");
|
||||||
break;
|
break;
|
||||||
case BitwiseOr:
|
case BitwiseOr:
|
||||||
*llvm_result = LLVMBuildOr(builder, lhs, rhs, "bitwise or");
|
*llvm_result = LLVMBuildOr(builder, llvm_lhs, llvm_rhs, "bitwise or");
|
||||||
break;
|
break;
|
||||||
case BitwiseXor:
|
case BitwiseXor:
|
||||||
*llvm_result = LLVMBuildXor(builder, lhs, rhs, "bitwise xor");
|
*llvm_result = LLVMBuildXor(builder, llvm_lhs, llvm_rhs, "bitwise xor");
|
||||||
break;
|
break;
|
||||||
case BitwiseNot:
|
case BitwiseNot:
|
||||||
*llvm_result = LLVMBuildNot(builder, rhs, "bitwise not");
|
*llvm_result = LLVMBuildNot(builder, llvm_rhs, "bitwise not");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,67 +65,89 @@ static LLVMValueRef convert_integral_to_boolean(
|
||||||
return LLVMBuildICmp(builder, LLVMIntNE, zero, integral, "to boolean");
|
return LLVMBuildICmp(builder, LLVMIntNE, zero, integral, "to boolean");
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_logical_operation([[maybe_unused]] LLVMBackendCompileUnit *unit,
|
BackendError impl_logical_operation(LLVMBackendCompileUnit *unit,
|
||||||
[[maybe_unused]] LLVMLocalScope *scope,
|
LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder,
|
LLVMBuilderRef builder,
|
||||||
Operation *operation,
|
Operation *operation,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve lhs and rhs or op
|
Expression *rhs = NULL;
|
||||||
LLVMValueRef rhs = NULL;
|
Expression *lhs = NULL;
|
||||||
LLVMValueRef lhs = NULL;
|
LLVMValueRef llvm_rhs = NULL;
|
||||||
|
LLVMValueRef llvm_lhs = NULL;
|
||||||
|
|
||||||
if (operation->impl.logical == LogicalNot) {
|
if (operation->impl.arithmetic == LogicalNot) {
|
||||||
// single operand
|
// single operand
|
||||||
rhs = convert_integral_to_boolean(builder, rhs);
|
rhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
} else {
|
} else {
|
||||||
// two operands
|
// two operands
|
||||||
lhs = convert_integral_to_boolean(builder, lhs);
|
lhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
rhs = convert_integral_to_boolean(builder, rhs);
|
impl_expr(unit, scope, builder, lhs, &llvm_lhs);
|
||||||
|
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 1);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (operation->impl.logical) {
|
switch (operation->impl.logical) {
|
||||||
case LogicalAnd:
|
case LogicalAnd:
|
||||||
*llvm_result = LLVMBuildAnd(builder, lhs, rhs, "logical and");
|
*llvm_result = LLVMBuildAnd(builder, llvm_lhs, llvm_rhs, "logical and");
|
||||||
break;
|
break;
|
||||||
case LogicalOr:
|
case LogicalOr:
|
||||||
*llvm_result = LLVMBuildOr(builder, lhs, rhs, "logical or");
|
*llvm_result = LLVMBuildOr(builder, llvm_lhs, llvm_rhs, "logical or");
|
||||||
break;
|
break;
|
||||||
case LogicalXor:
|
case LogicalXor:
|
||||||
*llvm_result = LLVMBuildXor(builder, lhs, rhs, "logical xor");
|
*llvm_result = LLVMBuildXor(builder, llvm_lhs, llvm_rhs, "logical xor");
|
||||||
break;
|
break;
|
||||||
case LogicalNot:
|
case LogicalNot:
|
||||||
*llvm_result = LLVMBuildNot(builder, rhs, "logical not");
|
*llvm_result = LLVMBuildNot(builder, llvm_rhs, "logical not");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMBool is_floating_point(LLVMValueRef value) {
|
static LLVMBool is_floating_point(Type *value) {
|
||||||
LLVMTypeRef valueType = LLVMTypeOf(value);
|
if (value->kind == TypeKindPrimitive) {
|
||||||
LLVMTypeKind typeKind = LLVMGetTypeKind(valueType);
|
return value->impl.primitive == Float;
|
||||||
|
}
|
||||||
|
|
||||||
return typeKind == LLVMFloatTypeKind || typeKind == LLVMHalfTypeKind || typeKind == LLVMDoubleTypeKind ||
|
if (value->kind == TypeKindComposite) {
|
||||||
typeKind == LLVMFP128TypeKind;
|
return value->impl.composite.primitive == Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMBool is_integral(LLVMValueRef value) {
|
static LLVMBool is_integral(Type *value) {
|
||||||
LLVMTypeRef valueType = LLVMTypeOf(value);
|
if (value->kind == TypeKindPrimitive) {
|
||||||
LLVMTypeKind typeKind = LLVMGetTypeKind(valueType);
|
return value->impl.primitive == Int;
|
||||||
|
}
|
||||||
|
|
||||||
return typeKind == LLVMIntegerTypeKind;
|
if (value->kind == TypeKindComposite) {
|
||||||
|
return value->impl.composite.primitive == Int;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit *unit,
|
BackendError impl_relational_operation(LLVMBackendCompileUnit *unit,
|
||||||
[[maybe_unused]] LLVMLocalScope *scope,
|
LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder,
|
LLVMBuilderRef builder,
|
||||||
Operation *operation,
|
Operation *operation,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve lhs and rhs or op
|
Expression *rhs = NULL;
|
||||||
LLVMValueRef rhs = NULL;
|
Expression *lhs = NULL;
|
||||||
LLVMValueRef lhs = NULL;
|
LLVMValueRef llvm_rhs = NULL;
|
||||||
|
LLVMValueRef llvm_lhs = NULL;
|
||||||
|
|
||||||
if ((is_integral(lhs) && is_integral(rhs)) == 1) {
|
// two operands
|
||||||
|
lhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, lhs, &llvm_lhs);
|
||||||
|
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 1);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
|
|
||||||
|
if (is_integral(rhs->result)) {
|
||||||
// integral type
|
// integral type
|
||||||
LLVMIntPredicate operator = 0;
|
LLVMIntPredicate operator = 0;
|
||||||
|
|
||||||
|
@ -133,8 +163,9 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit *
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*llvm_result = LLVMBuildICmp(builder, operator, lhs, rhs, "integral comparison");
|
*llvm_result = LLVMBuildICmp(builder, operator, llvm_lhs, llvm_rhs, "integral comparison");
|
||||||
} else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) {
|
|
||||||
|
} else if (is_floating_point(rhs->result)) {
|
||||||
// integral type
|
// integral type
|
||||||
LLVMRealPredicate operator = 0;
|
LLVMRealPredicate operator = 0;
|
||||||
|
|
||||||
|
@ -150,7 +181,7 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit *
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison");
|
*llvm_result = LLVMBuildFCmp(builder, operator, llvm_lhs, llvm_rhs, "floating point comparison");
|
||||||
} else {
|
} else {
|
||||||
PANIC("invalid type for relational operator");
|
PANIC("invalid type for relational operator");
|
||||||
}
|
}
|
||||||
|
@ -158,53 +189,69 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit *
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_arithmetic_operation([[maybe_unused]] LLVMBackendCompileUnit *unit,
|
BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit,
|
||||||
[[maybe_unused]] LLVMLocalScope *scope,
|
LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder,
|
LLVMBuilderRef builder,
|
||||||
Operation *operation,
|
Operation *operation,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve lhs and rhs or op
|
Expression *rhs = NULL;
|
||||||
LLVMValueRef rhs = NULL;
|
Expression *lhs = NULL;
|
||||||
LLVMValueRef lhs = NULL;
|
LLVMValueRef llvm_rhs = NULL;
|
||||||
|
LLVMValueRef llvm_lhs = NULL;
|
||||||
|
|
||||||
if ((is_integral(lhs) && is_integral(rhs)) == 1) {
|
if (operation->impl.arithmetic == Negate) {
|
||||||
// integral type
|
// single operand
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
|
} else {
|
||||||
|
// two operands
|
||||||
|
lhs = g_array_index(operation->operands, Expression*, 0);
|
||||||
|
impl_expr(unit, scope, builder, lhs, &llvm_lhs);
|
||||||
|
|
||||||
|
rhs = g_array_index(operation->operands, Expression*, 1);
|
||||||
|
impl_expr(unit, scope, builder, rhs, &llvm_rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_integral(rhs->result)) {
|
||||||
|
|
||||||
switch (operation->impl.arithmetic) {
|
switch (operation->impl.arithmetic) {
|
||||||
case Add:
|
case Add:
|
||||||
*llvm_result = LLVMBuildNSWAdd(builder, lhs, rhs, "signed integer addition");
|
*llvm_result = LLVMBuildNSWAdd(builder, llvm_lhs, llvm_rhs, "signed integer addition");
|
||||||
break;
|
break;
|
||||||
case Sub:
|
case Sub:
|
||||||
*llvm_result = LLVMBuildNSWSub(builder, lhs, rhs, "signed integer subtraction");
|
*llvm_result = LLVMBuildNSWSub(builder, llvm_lhs, llvm_rhs, "signed integer subtraction");
|
||||||
break;
|
break;
|
||||||
case Mul:
|
case Mul:
|
||||||
*llvm_result = LLVMBuildNSWMul(builder, lhs, rhs, "signed integer multiply");
|
*llvm_result = LLVMBuildNSWMul(builder, llvm_lhs, llvm_rhs, "signed integer multiply");
|
||||||
break;
|
break;
|
||||||
case Div:
|
case Div:
|
||||||
*llvm_result = LLVMBuildSDiv(builder, lhs, rhs, "signed integer divide");
|
*llvm_result = LLVMBuildSDiv(builder, llvm_lhs, llvm_rhs, "signed integer divide");
|
||||||
|
break;
|
||||||
|
case Negate:
|
||||||
|
*llvm_result = LLVMBuildNeg(builder, llvm_rhs, "signed integer negate");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) {
|
} else if (is_floating_point(rhs->result)) {
|
||||||
// integral type
|
|
||||||
LLVMRealPredicate operator = 0;
|
|
||||||
|
|
||||||
switch (operation->impl.arithmetic) {
|
switch (operation->impl.arithmetic) {
|
||||||
case Add:
|
case Add:
|
||||||
*llvm_result = LLVMBuildFAdd(builder, lhs, rhs, "floating point addition");
|
*llvm_result = LLVMBuildFAdd(builder, llvm_lhs, llvm_rhs, "floating point addition");
|
||||||
break;
|
break;
|
||||||
case Sub:
|
case Sub:
|
||||||
*llvm_result = LLVMBuildFSub(builder, lhs, rhs, "floating point subtraction");
|
*llvm_result = LLVMBuildFSub(builder, llvm_lhs, llvm_rhs, "floating point subtraction");
|
||||||
break;
|
break;
|
||||||
case Mul:
|
case Mul:
|
||||||
*llvm_result = LLVMBuildFMul(builder, lhs, rhs, "floating point multiply");
|
*llvm_result = LLVMBuildFMul(builder, llvm_lhs, llvm_rhs, "floating point multiply");
|
||||||
break;
|
break;
|
||||||
case Div:
|
case Div:
|
||||||
*llvm_result = LLVMBuildFDiv(builder, lhs, rhs, "floating point divide");
|
*llvm_result = LLVMBuildFDiv(builder, llvm_lhs, llvm_rhs, "floating point divide");
|
||||||
|
break;
|
||||||
|
case Negate:
|
||||||
|
*llvm_result = LLVMBuildFNeg(builder, llvm_rhs, "floating point negate");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison");
|
|
||||||
} else {
|
} else {
|
||||||
PANIC("invalid type for arithmetic operator");
|
PANIC("invalid type for arithmetic operator");
|
||||||
}
|
}
|
||||||
|
@ -244,8 +291,10 @@ BackendError impl_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder, Transmute *transmute,
|
LLVMBuilderRef builder, Transmute *transmute,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve sub expression
|
|
||||||
LLVMValueRef operand = NULL;
|
LLVMValueRef operand = NULL;
|
||||||
|
impl_expr(unit, scope, builder, transmute->operand, &operand);
|
||||||
|
|
||||||
LLVMTypeRef target_type = NULL;
|
LLVMTypeRef target_type = NULL;
|
||||||
BackendError err = get_type_impl(unit, scope->func_scope->global_scope,
|
BackendError err = get_type_impl(unit, scope->func_scope->global_scope,
|
||||||
transmute->targetType, &target_type);
|
transmute->targetType, &target_type);
|
||||||
|
@ -272,8 +321,9 @@ static LLVMBool is_type_signed(const Type *type) {
|
||||||
BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder, TypeCast *typecast,
|
LLVMBuilderRef builder, TypeCast *typecast,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
// TODO: resolve sub expression
|
|
||||||
LLVMValueRef operand = NULL;
|
LLVMValueRef operand = NULL;
|
||||||
|
impl_expr(unit, scope, builder, typecast->operand, &operand);
|
||||||
|
|
||||||
LLVMTypeRef target_type = NULL;
|
LLVMTypeRef target_type = NULL;
|
||||||
BackendError err = get_type_impl(unit, scope->func_scope->global_scope,
|
BackendError err = get_type_impl(unit, scope->func_scope->global_scope,
|
||||||
typecast->targetType, &target_type);
|
typecast->targetType, &target_type);
|
||||||
|
@ -283,18 +333,34 @@ BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMBool dst_signed = is_type_signed(typecast->targetType);
|
LLVMBool dst_signed = is_type_signed(typecast->targetType);
|
||||||
// TODO: derive source type sign
|
LLVMBool src_signed = is_type_signed(typecast->operand->result);
|
||||||
const LLVMOpcode opcode =
|
const LLVMOpcode opcode =
|
||||||
LLVMGetCastOpcode(operand, 0, target_type, dst_signed);
|
LLVMGetCastOpcode(operand, src_signed, target_type, dst_signed);
|
||||||
*llvm_result =
|
*llvm_result =
|
||||||
LLVMBuildCast(builder, opcode, operand, target_type, "transmute");
|
LLVMBuildCast(builder, opcode, operand, target_type, "transmute");
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackendError impl_variable_load(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
|
LLVMBuilderRef builder, Variable *variable,
|
||||||
|
LLVMValueRef *llvm_result) {
|
||||||
|
|
||||||
|
LLVMValueRef llvm_variable = get_variable(scope, variable->name);
|
||||||
|
|
||||||
|
if (llvm_variable == NULL) {
|
||||||
|
return new_backend_impl_error(Implementation, NULL, "Variable not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
*llvm_result = llvm_variable;
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
LLVMBuilderRef builder, Expression *expr,
|
LLVMBuilderRef builder, Expression *expr,
|
||||||
LLVMValueRef *llvm_result) {
|
LLVMValueRef *llvm_result) {
|
||||||
|
DEBUG("implementing expression: %ld", expr->kind);
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
switch (expr->kind) {
|
switch (expr->kind) {
|
||||||
|
@ -314,6 +380,13 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
||||||
err = impl_operation(unit, scope, builder, &expr->impl.operation,
|
err = impl_operation(unit, scope, builder, &expr->impl.operation,
|
||||||
llvm_result);
|
llvm_result);
|
||||||
break;
|
break;
|
||||||
|
case ExpressionKindVariable:
|
||||||
|
err = impl_variable_load(unit, scope, builder, expr->impl.variable,
|
||||||
|
llvm_result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = new_backend_impl_error(Implementation, NULL, "unknown expression");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <llvm/parser.h>
|
#include <llvm/parser.h>
|
||||||
#include <llvm/llvm-ir/types.h>
|
#include <llvm/llvm-ir/types.h>
|
||||||
#include <llvm/llvm-ir/stmt.h>
|
#include <llvm/llvm-ir/stmt.h>
|
||||||
|
#include <llvm/llvm-ir/variables.h>
|
||||||
#include <set/types.h>
|
#include <set/types.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
|
||||||
|
@ -43,7 +44,13 @@ LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name) {
|
||||||
return get_variable(scope->parent_scope, name);
|
return get_variable(scope->parent_scope, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_parameter(scope->func_scope, name);
|
LLVMValueRef param = get_parameter(scope->func_scope, name);
|
||||||
|
if (param != NULL) {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMValueRef global_var = get_global_variable(scope->func_scope->global_scope, name);
|
||||||
|
return global_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_param_type(LLVMBackendCompileUnit* unit,
|
BackendError impl_param_type(LLVMBackendCompileUnit* unit,
|
||||||
|
@ -110,7 +117,7 @@ BackendError impl_func_decl(LLVMBackendCompileUnit* unit,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_func(LLVMBackendCompileUnit* unit,
|
BackendError impl_func_def(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* global_scope,
|
LLVMGlobalScope* global_scope,
|
||||||
FunctionDefinition* fundef, const char* name) {
|
FunctionDefinition* fundef, const char* name) {
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
@ -131,10 +138,10 @@ BackendError impl_func(LLVMBackendCompileUnit* unit,
|
||||||
g_hash_table_insert(global_scope->functions, (gpointer)name, llvm_func);
|
g_hash_table_insert(global_scope->functions, (gpointer)name, llvm_func);
|
||||||
|
|
||||||
// create function body builder
|
// create function body builder
|
||||||
LLVMBasicBlockRef body =
|
LLVMBasicBlockRef entry =
|
||||||
LLVMAppendBasicBlockInContext(unit->context, llvm_func, "entry");
|
LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.entry");
|
||||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(unit->context);
|
LLVMBuilderRef builder = LLVMCreateBuilderInContext(unit->context);
|
||||||
LLVMPositionBuilderAtEnd(builder, body);
|
LLVMPositionBuilderAtEnd(builder, entry);
|
||||||
|
|
||||||
// create value references for parameter
|
// create value references for parameter
|
||||||
const size_t params = fundef->parameter->len;
|
const size_t params = fundef->parameter->len;
|
||||||
|
@ -144,7 +151,20 @@ BackendError impl_func(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGetParam(llvm_func, i));
|
LLVMGetParam(llvm_func, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
err = impl_block(unit, builder, func_scope, fundef->body);
|
LLVMBasicBlockRef llvm_start_body_block = NULL;
|
||||||
|
LLVMBasicBlockRef llvm_end_body_block = NULL;
|
||||||
|
err = impl_block(unit, builder, func_scope, &llvm_start_body_block, &llvm_end_body_block, fundef->body);
|
||||||
|
LLVMPositionBuilderAtEnd(builder, entry);
|
||||||
|
LLVMBuildBr(builder, llvm_start_body_block);
|
||||||
|
|
||||||
|
// insert returning end block
|
||||||
|
LLVMBasicBlockRef end_block =
|
||||||
|
LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.end");
|
||||||
|
LLVMPositionBuilderAtEnd(builder, end_block);
|
||||||
|
LLVMBuildRetVoid(builder);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(builder, llvm_end_body_block);
|
||||||
|
LLVMBuildBr(builder, end_block);
|
||||||
|
|
||||||
LLVMDisposeBuilder(builder);
|
LLVMDisposeBuilder(builder);
|
||||||
|
|
||||||
|
@ -168,11 +188,16 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit,
|
||||||
|
|
||||||
size_t function_count = 0;
|
size_t function_count = 0;
|
||||||
while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) {
|
while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) {
|
||||||
err =
|
Function* func = (Function*) val;
|
||||||
impl_func(unit, scope, (FunctionDefinition*)val, (const char*)key);
|
|
||||||
|
if (func->kind == FunctionDeclarationKind) {
|
||||||
|
// err = impl_func_decl(unit, scope, &func->impl.declaration, (const char*) key);
|
||||||
|
} else {
|
||||||
|
err = impl_func_def(unit, scope, &func->impl.definition, (const char*)key);
|
||||||
|
}
|
||||||
|
|
||||||
if (err.kind != Success) {
|
if (err.kind != Success) {
|
||||||
break;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
function_count++;
|
function_count++;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <llvm/llvm-ir/expr.h>
|
#include <llvm/llvm-ir/expr.h>
|
||||||
#include <llvm/llvm-ir/func.h>
|
#include <llvm/llvm-ir/func.h>
|
||||||
#include <llvm/llvm-ir/types.h>
|
#include <llvm/llvm-ir/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
BackendError impl_assign_stmt(
|
BackendError impl_assign_stmt(
|
||||||
LLVMBackendCompileUnit *unit,
|
LLVMBackendCompileUnit *unit,
|
||||||
|
@ -31,6 +32,7 @@ BackendError impl_assign_stmt(
|
||||||
case VariableKindDefinition:
|
case VariableKindDefinition:
|
||||||
LLVMValueRef llvm_ptr =
|
LLVMValueRef llvm_ptr =
|
||||||
get_variable(scope, assignment->variable->name);
|
get_variable(scope, assignment->variable->name);
|
||||||
|
|
||||||
LLVMBuildStore(builder, llvm_value, llvm_ptr
|
LLVMBuildStore(builder, llvm_value, llvm_ptr
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -44,20 +46,39 @@ BackendError impl_assign_stmt(
|
||||||
|
|
||||||
BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
|
BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
||||||
const Block *block, LLVMBasicBlockRef *llvm_block) {
|
const Block *block, LLVMBasicBlockRef *llvm_start_block, LLVMBasicBlockRef *llvm_end_block) {
|
||||||
|
DEBUG("implementing basic block...");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
LLVMLocalScope *block_scope = new_local_scope(scope);
|
LLVMLocalScope *block_scope = new_local_scope(scope);
|
||||||
// append a new LLVM basic block
|
// append a new LLVM basic block
|
||||||
*llvm_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
*llvm_start_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
||||||
"basic block");
|
"stmt.block.start");
|
||||||
LLVMPositionBuilderAtEnd(builder, *llvm_block);
|
LLVMPositionBuilderAtEnd(builder, *llvm_start_block);
|
||||||
|
|
||||||
|
LLVMBasicBlockRef end_previous_block = *llvm_start_block;
|
||||||
|
|
||||||
for (size_t i = 0; i < block->statemnts->len; i++) {
|
for (size_t i = 0; i < block->statemnts->len; i++) {
|
||||||
Statement *stmt = ((Statement *) block->statemnts->data) + i;
|
DEBUG("building block statement %d of %d", i, block->statemnts->len);
|
||||||
impl_stmt(unit, builder, scope, stmt);
|
Statement* stmt = g_array_index(block->statemnts, Statement*, i);
|
||||||
|
|
||||||
|
LLVMBasicBlockRef llvm_next_start_block = NULL;
|
||||||
|
LLVMBasicBlockRef llvm_next_end_block = NULL;
|
||||||
|
err = impl_stmt(unit, builder, scope, stmt, &llvm_next_start_block, &llvm_next_end_block);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (llvm_next_end_block != NULL) {
|
||||||
|
LLVMPositionBuilderAtEnd(builder, end_previous_block);
|
||||||
|
LLVMBuildBr(builder, llvm_next_start_block);
|
||||||
|
LLVMPositionBuilderAtEnd(builder, llvm_next_end_block);
|
||||||
|
end_previous_block = llvm_next_end_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*llvm_end_block = end_previous_block;
|
||||||
|
|
||||||
delete_local_scope(block_scope);
|
delete_local_scope(block_scope);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -65,21 +86,33 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
|
||||||
|
|
||||||
BackendError impl_while(LLVMBackendCompileUnit *unit,
|
BackendError impl_while(LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
||||||
|
LLVMBasicBlockRef* llvm_start_block,
|
||||||
|
LLVMBasicBlockRef* llvm_end_block,
|
||||||
const While *while_stmt) {
|
const While *while_stmt) {
|
||||||
|
DEBUG("implementing while...");
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
// Create condition block
|
// Create condition block
|
||||||
LLVMBasicBlockRef while_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
LLVMBasicBlockRef while_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
||||||
"loop.while.cond");
|
"loop.while.cond");
|
||||||
|
*llvm_start_block = while_cond_block;
|
||||||
LLVMPositionBuilderAtEnd(builder, while_cond_block);
|
LLVMPositionBuilderAtEnd(builder, while_cond_block);
|
||||||
// Resolve condition in block to a variable
|
// Resolve condition in block to a variable
|
||||||
LLVMValueRef cond_result = NULL;
|
LLVMValueRef cond_result = NULL;
|
||||||
impl_expr(unit, scope, builder, (Expression *) &while_stmt->conditon, &cond_result);
|
err = impl_expr(unit, scope, builder, (Expression *) while_stmt->conditon, &cond_result);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// build body of loop
|
// build body of loop
|
||||||
LLVMBasicBlockRef while_body_block = NULL;
|
LLVMBasicBlockRef while_start_body_block = NULL;
|
||||||
err = impl_basic_block(unit, builder, scope, &while_stmt->block, &while_body_block);
|
LLVMBasicBlockRef while_end_body_block = NULL;
|
||||||
LLVMPositionBuilderAtEnd(builder, while_body_block);
|
err = impl_basic_block(unit, builder, scope, &while_stmt->block, &while_start_body_block, &while_end_body_block);
|
||||||
|
if (err.kind != Success) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(builder, while_end_body_block);
|
||||||
// jump back to condition after body end
|
// jump back to condition after body end
|
||||||
LLVMBuildBr(builder, while_cond_block);
|
LLVMBuildBr(builder, while_cond_block);
|
||||||
|
|
||||||
|
@ -88,10 +121,12 @@ BackendError impl_while(LLVMBackendCompileUnit *unit,
|
||||||
"loop.while.after");
|
"loop.while.after");
|
||||||
// build conditional branch at end of condition block
|
// build conditional branch at end of condition block
|
||||||
LLVMPositionBuilderAtEnd(builder, while_cond_block);
|
LLVMPositionBuilderAtEnd(builder, while_cond_block);
|
||||||
LLVMBuildCondBr(builder, cond_result, while_body_block, while_after_block);
|
LLVMBuildCondBr(builder, cond_result, while_start_body_block, while_after_block);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(builder, while_after_block);
|
LLVMPositionBuilderAtEnd(builder, while_after_block);
|
||||||
|
|
||||||
|
*llvm_end_block = while_after_block;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +159,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameter *parameter = g_array_index(call->function->parameter, Parameter*, i);
|
Parameter *parameter = g_array_index(call->function->impl.declaration.parameter, Parameter*, i);
|
||||||
|
|
||||||
if (is_parameter_out(parameter)) {
|
if (is_parameter_out(parameter)) {
|
||||||
LLVMValueRef zero = LLVMConstInt(LLVMInt32TypeInContext(unit->context), 0, 0);
|
LLVMValueRef zero = LLVMConstInt(LLVMInt32TypeInContext(unit->context), 0, 0);
|
||||||
|
@ -148,7 +183,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit,
|
||||||
|
|
||||||
BackendError
|
BackendError
|
||||||
impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond,
|
impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond,
|
||||||
const Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *body_block,
|
const Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *start_body_block, LLVMBasicBlockRef *end_body_block,
|
||||||
LLVMValueRef *llvm_cond) {
|
LLVMValueRef *llvm_cond) {
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
|
@ -159,7 +194,7 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS
|
||||||
err = impl_expr(unit, scope, builder, cond, llvm_cond);
|
err = impl_expr(unit, scope, builder, cond, llvm_cond);
|
||||||
if (err.kind == Success) {
|
if (err.kind == Success) {
|
||||||
// build body of loop
|
// build body of loop
|
||||||
err = impl_basic_block(unit, builder, scope, block, body_block);
|
err = impl_basic_block(unit, builder, scope, block, start_body_block, end_body_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -167,49 +202,57 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS
|
||||||
|
|
||||||
BackendError impl_branch(LLVMBackendCompileUnit *unit,
|
BackendError impl_branch(LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
||||||
|
LLVMBasicBlockRef* branch_start_block,
|
||||||
|
LLVMBasicBlockRef* branch_end_block,
|
||||||
const Branch *branch) {
|
const Branch *branch) {
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
GArray *cond_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
|
GArray *cond_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
|
||||||
GArray *body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
|
GArray *start_body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
|
||||||
|
GArray *end_body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
|
||||||
GArray *cond_values = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef));
|
GArray *cond_values = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef));
|
||||||
|
|
||||||
// add If to arrays
|
// add If to arrays
|
||||||
{
|
{
|
||||||
LLVMBasicBlockRef cond_block = NULL;
|
LLVMBasicBlockRef cond_block = NULL;
|
||||||
LLVMBasicBlockRef body_block = NULL;
|
LLVMBasicBlockRef start_body_block = NULL;
|
||||||
|
LLVMBasicBlockRef end_body_block = NULL;
|
||||||
LLVMValueRef cond_value = NULL;
|
LLVMValueRef cond_value = NULL;
|
||||||
|
|
||||||
err = impl_cond_block(unit, builder, scope, (Expression *) &branch->ifBranch.conditon, &branch->ifBranch.block,
|
err = impl_cond_block(unit, builder, scope, (Expression *) &branch->ifBranch.conditon, &branch->ifBranch.block,
|
||||||
&cond_block,
|
&cond_block,
|
||||||
&body_block, &cond_value);
|
&start_body_block, &end_body_block, &cond_value);
|
||||||
|
|
||||||
g_array_append_val(cond_blocks, cond_block);
|
g_array_append_val(cond_blocks, cond_block);
|
||||||
g_array_append_val(body_blocks, body_block);
|
g_array_append_val(start_body_blocks, start_body_block);
|
||||||
|
g_array_append_val(end_body_blocks, end_body_block);
|
||||||
g_array_append_val(cond_values, cond_value);
|
g_array_append_val(cond_values, cond_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate else if(s)
|
// generate else if(s)
|
||||||
for (size_t i = 0; i < branch->elseIfBranches->len; i++) {
|
for (size_t i = 0; i < branch->elseIfBranches->len; i++) {
|
||||||
LLVMBasicBlockRef cond_block = NULL;
|
LLVMBasicBlockRef cond_block = NULL;
|
||||||
LLVMBasicBlockRef body_block = NULL;
|
LLVMBasicBlockRef start_body_block = NULL;
|
||||||
|
LLVMBasicBlockRef end_body_block = NULL;
|
||||||
LLVMValueRef cond_value = NULL;
|
LLVMValueRef cond_value = NULL;
|
||||||
|
|
||||||
ElseIf *elseIf = ((ElseIf *) branch->elseIfBranches->data) + i;
|
ElseIf *elseIf = ((ElseIf *) branch->elseIfBranches->data) + i;
|
||||||
|
|
||||||
err = impl_cond_block(unit, builder, scope, elseIf->conditon, &elseIf->block, &cond_block,
|
err = impl_cond_block(unit, builder, scope, elseIf->conditon, &elseIf->block, &cond_block,
|
||||||
&body_block, &cond_value);
|
&start_body_block, &end_body_block, &cond_value);
|
||||||
|
|
||||||
g_array_append_val(cond_blocks, cond_block);
|
g_array_append_val(cond_blocks, cond_block);
|
||||||
g_array_append_val(body_blocks, body_block);
|
g_array_append_val(start_body_blocks, start_body_block);
|
||||||
|
g_array_append_val(end_body_blocks, end_body_block);
|
||||||
g_array_append_val(cond_values, cond_value);
|
g_array_append_val(cond_values, cond_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// else block
|
// else block
|
||||||
if (branch->elseBranch.nodePtr != NULL) {
|
if (branch->elseBranch.nodePtr != NULL) {
|
||||||
LLVMBasicBlockRef else_block = NULL;
|
LLVMBasicBlockRef start_else_block = NULL;
|
||||||
err = impl_basic_block(unit, builder, scope, &branch->elseBranch.block, &else_block);
|
LLVMBasicBlockRef end_else_block = NULL;
|
||||||
g_array_append_val(cond_blocks, else_block);
|
err = impl_basic_block(unit, builder, scope, &branch->elseBranch.block, &start_else_block, &end_else_block);
|
||||||
|
g_array_append_val(cond_blocks, start_else_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMBasicBlockRef after_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
LLVMBasicBlockRef after_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
|
||||||
|
@ -224,18 +267,23 @@ BackendError impl_branch(LLVMBackendCompileUnit *unit,
|
||||||
for (size_t i = 0; i < cond_blocks->len - 1; i++) {
|
for (size_t i = 0; i < cond_blocks->len - 1; i++) {
|
||||||
LLVMBasicBlockRef next_block = ((LLVMBasicBlockRef *) cond_blocks->data)[i + 1];
|
LLVMBasicBlockRef next_block = ((LLVMBasicBlockRef *) cond_blocks->data)[i + 1];
|
||||||
LLVMBasicBlockRef cond_block = ((LLVMBasicBlockRef *) cond_blocks->data)[i];
|
LLVMBasicBlockRef cond_block = ((LLVMBasicBlockRef *) cond_blocks->data)[i];
|
||||||
LLVMBasicBlockRef body_block = ((LLVMBasicBlockRef *) body_blocks->data)[i];
|
LLVMBasicBlockRef start_body_block = ((LLVMBasicBlockRef *) start_body_blocks->data)[i];
|
||||||
|
LLVMBasicBlockRef end_body_block = ((LLVMBasicBlockRef *) end_body_blocks->data)[i];
|
||||||
LLVMValueRef cond_value = ((LLVMValueRef *) cond_values->data)[i];
|
LLVMValueRef cond_value = ((LLVMValueRef *) cond_values->data)[i];
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(builder, cond_block);
|
LLVMPositionBuilderAtEnd(builder, cond_block);
|
||||||
LLVMBuildCondBr(builder, cond_value, body_block, next_block);
|
LLVMBuildCondBr(builder, cond_value, start_body_block, next_block);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(builder, body_block);
|
LLVMPositionBuilderAtEnd(builder, end_body_block);
|
||||||
LLVMBuildBr(builder, after_block);
|
LLVMBuildBr(builder, after_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*branch_start_block = g_array_index(cond_blocks, LLVMBasicBlockRef, 0);
|
||||||
|
*branch_end_block = g_array_index(cond_blocks, LLVMBasicBlockRef, cond_blocks->len - 1);
|
||||||
|
|
||||||
g_array_free(cond_blocks, TRUE);
|
g_array_free(cond_blocks, TRUE);
|
||||||
g_array_free(body_blocks, TRUE);
|
g_array_free(start_body_blocks, TRUE);
|
||||||
|
g_array_free(end_body_blocks, TRUE);
|
||||||
g_array_free(cond_values, TRUE);
|
g_array_free(cond_values, TRUE);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -308,10 +356,10 @@ BackendError impl_var(LLVMBackendCompileUnit *unit,
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
switch (var->kind) {
|
switch (var->kind) {
|
||||||
VariableKindDeclaration:
|
case VariableKindDeclaration:
|
||||||
err = impl_decl(unit, builder, scope, &var->impl.declaration, var->name);
|
err = impl_decl(unit, builder, scope, &var->impl.declaration, var->name);
|
||||||
break;
|
break;
|
||||||
VariableKindDefinition:
|
case VariableKindDefinition:
|
||||||
err = impl_def(unit, builder, scope, &var->impl.definiton, var->name);
|
err = impl_def(unit, builder, scope, &var->impl.definiton, var->name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -322,28 +370,31 @@ BackendError impl_var(LLVMBackendCompileUnit *unit,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Statement *stmt) {
|
BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Statement *stmt, LLVMBasicBlockRef* llvm_start_block, LLVMBasicBlockRef* llvm_end_block) {
|
||||||
|
assert(stmt != NULL);
|
||||||
|
DEBUG("implementing statement: %ld", stmt->kind);
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
switch (stmt->kind) {
|
switch (stmt->kind) {
|
||||||
StatementKindAssignment:
|
case StatementKindAssignment:
|
||||||
err = impl_assign_stmt(unit, builder, scope, &stmt->impl.assignment);
|
err = impl_assign_stmt(unit, builder, scope, &stmt->impl.assignment);
|
||||||
break;
|
break;
|
||||||
StatementKindBranch:
|
case StatementKindBranch:
|
||||||
err = impl_branch(unit, builder, scope, &stmt->impl.branch);
|
err = impl_branch(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.branch);
|
||||||
break;
|
break;
|
||||||
StatementKindDeclaration:
|
case StatementKindDeclaration:
|
||||||
StatementKindDefinition:
|
case StatementKindDefinition:
|
||||||
err = impl_var(unit, builder, scope, stmt->impl.variable);
|
err = impl_var(unit, builder, scope, stmt->impl.variable);
|
||||||
break;
|
break;
|
||||||
StatementKindWhile:
|
case StatementKindWhile:
|
||||||
err = impl_while(unit, builder, scope, &stmt->impl.whileLoop);
|
err = impl_while(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.whileLoop);
|
||||||
break;
|
break;
|
||||||
StatementKindFunctionCall:
|
case StatementKindFunctionCall:
|
||||||
err = impl_func_call(unit, builder, scope, &stmt->impl.call);
|
err = impl_func_call(unit, builder, scope, &stmt->impl.call);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind");
|
err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -351,7 +402,10 @@ BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLV
|
||||||
|
|
||||||
BackendError impl_block(LLVMBackendCompileUnit *unit,
|
BackendError impl_block(LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef builder, LLVMFuncScope *scope,
|
LLVMBuilderRef builder, LLVMFuncScope *scope,
|
||||||
|
LLVMBasicBlockRef* llvm_start_block,
|
||||||
|
LLVMBasicBlockRef* llvm_end_block,
|
||||||
const Block *block) {
|
const Block *block) {
|
||||||
|
DEBUG("Implementing function block...");
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
|
|
||||||
LLVMLocalScope *function_entry_scope = malloc(sizeof(LLVMLocalScope));
|
LLVMLocalScope *function_entry_scope = malloc(sizeof(LLVMLocalScope));
|
||||||
|
@ -359,8 +413,7 @@ BackendError impl_block(LLVMBackendCompileUnit *unit,
|
||||||
function_entry_scope->vars = g_hash_table_new(g_str_hash, g_str_equal);
|
function_entry_scope->vars = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
function_entry_scope->parent_scope = NULL;
|
function_entry_scope->parent_scope = NULL;
|
||||||
|
|
||||||
LLVMBasicBlockRef llvm_block = NULL;
|
err = impl_basic_block(unit, builder, function_entry_scope, block, llvm_start_block, llvm_end_block);
|
||||||
err = impl_basic_block(unit, builder, function_entry_scope, block, &llvm_block);
|
|
||||||
|
|
||||||
delete_local_scope(function_entry_scope);
|
delete_local_scope(function_entry_scope);
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,11 @@
|
||||||
|
|
||||||
BackendError impl_block(LLVMBackendCompileUnit *unit,
|
BackendError impl_block(LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef builder, LLVMFuncScope *scope,
|
LLVMBuilderRef builder, LLVMFuncScope *scope,
|
||||||
|
LLVMBasicBlockRef* llvm_start_block,
|
||||||
|
LLVMBasicBlockRef* llvm_end_block,
|
||||||
const Block *block);
|
const Block *block);
|
||||||
|
|
||||||
BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Statement *stmt);
|
BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Statement *stmt,
|
||||||
|
LLVMBasicBlockRef *llvm_start_block, LLVMBasicBlockRef *llvm_end_block);
|
||||||
|
|
||||||
#endif // LLVM_BACKEND_STMT_H
|
#endif // LLVM_BACKEND_STMT_H
|
||||||
|
|
|
@ -96,7 +96,7 @@ 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) {
|
||||||
size_t bits = (int)(4 * scale) * BITS_PER_BYTE;
|
size_t bits = (int)(BASE_BYTES * scale) * BITS_PER_BYTE;
|
||||||
DEBUG("implementing integral type of size: %ld", bits);
|
DEBUG("implementing integral type of size: %ld", bits);
|
||||||
LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits);
|
LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits);
|
||||||
|
|
||||||
|
|
|
@ -120,3 +120,11 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMValueRef get_global_variable(LLVMGlobalScope* scope, char* name) {
|
||||||
|
if (g_hash_table_contains(scope->variables, name)) {
|
||||||
|
return g_hash_table_lookup(scope->variables, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -12,4 +12,6 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit,
|
||||||
LLVMGlobalScope* scope,
|
LLVMGlobalScope* scope,
|
||||||
GHashTable* variables);
|
GHashTable* variables);
|
||||||
|
|
||||||
|
LLVMValueRef get_global_variable(LLVMGlobalScope* scope, char* name);
|
||||||
|
|
||||||
#endif // LLVM_BACKEND_VARIABLES_H_
|
#endif // LLVM_BACKEND_VARIABLES_H_
|
||||||
|
|
|
@ -75,7 +75,7 @@ BackendError emit_module_to_file(LLVMBackendCompileUnit* unit,
|
||||||
filename = g_build_filename(config->archive_directory, basename, NULL);
|
filename = g_build_filename(config->archive_directory, basename, NULL);
|
||||||
break;
|
break;
|
||||||
case LLVMObjectFile:
|
case LLVMObjectFile:
|
||||||
basename = g_strjoin("", config->name, "o", NULL);
|
basename = g_strjoin(".", config->name, "o", NULL);
|
||||||
filename = g_build_filename(config->archive_directory, basename, NULL);
|
filename = g_build_filename(config->archive_directory, basename, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -83,6 +83,10 @@ BackendError emit_module_to_file(LLVMBackendCompileUnit* unit,
|
||||||
"invalid codegen file");
|
"invalid codegen file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add custom link libraries
|
||||||
|
|
||||||
|
INFO("export to file: %s", filename);
|
||||||
|
|
||||||
if (LLVMTargetMachineEmitToFile(target_machine, unit->module, filename,
|
if (LLVMTargetMachineEmitToFile(target_machine, unit->module, filename,
|
||||||
file_type, &error) != 0) {
|
file_type, &error) != 0) {
|
||||||
ERROR("failed to emit code: %s", error);
|
ERROR("failed to emit code: %s", error);
|
||||||
|
|
Loading…
Reference in New Issue