diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 5b33ad9..d907961 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -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")) { const Option* opt = get_option("link-paths"); diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 1c536a8..925aabb 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -67,8 +67,8 @@ Target create_target_from_config(const TargetConfig* config) { target.opt = llvm_opt_from_int(config->optimization_level); - INFO("Configured target: %s/%d: (%s) on %s { %s }", target.name, target.opt, - target.triple, target.cpu, target.features); + INFO("Configured target: %s/%d: (%s) on %s { %s }", target.name.str, target.opt, + target.triple.str, target.cpu.str, target.features.str); return target; } diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c index b3189c4..1ccc31b 100644 --- a/src/llvm/link/lld.c +++ b/src/llvm/link/lld.c @@ -13,6 +13,7 @@ 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) { + INFO("resolving absolute path for link target: %s", link_target_name); 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); @@ -28,6 +29,7 @@ const char* get_absolute_link_path(const TargetConfig* config, const char* link_ g_free(cwd); if (exists && !is_dir) { + INFO("link target found at: %s", canonical); return canonical; } @@ -48,9 +50,11 @@ TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfi config->colorize = stdout_supports_ansi_esc(); // 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) { - 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); return NULL; } @@ -99,13 +103,18 @@ GArray* lld_create_lld_arguments(TargetLinkConfig* config) { } BackendError lld_link_target(TargetLinkConfig* config) { + DEBUG("linking target..."); BackendError err = SUCCESS; GArray* argv = lld_create_lld_arguments(config); + INFO("Linking target..."); + const char* message = NULL; int status = lld_main((int) argv->len, (const char**) argv->data, &message); + INFO("done linking target..."); + g_array_free(argv, TRUE); if (message != NULL) { diff --git a/src/llvm/llvm-ir/expr.c b/src/llvm/llvm-ir/expr.c index 771b471..c1e59c3 100644 --- a/src/llvm/llvm-ir/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -6,33 +6,41 @@ #include #include -BackendError impl_bitwise_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, - [[maybe_unused]] LLVMLocalScope *scope, +BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { - // TODO: resolve lhs and rhs or op - LLVMValueRef rhs = NULL; - LLVMValueRef lhs = NULL; + Expression *rhs = NULL; + Expression *lhs = NULL; + LLVMValueRef llvm_rhs = NULL; + LLVMValueRef llvm_lhs = NULL; - if (operation->impl.bitwise == BitwiseNot) { + if (operation->impl.arithmetic == BitwiseNot) { // 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); } switch (operation->impl.bitwise) { case BitwiseAnd: - *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "bitwise and"); + *llvm_result = LLVMBuildAnd(builder, llvm_lhs, llvm_rhs, "bitwise and"); break; case BitwiseOr: - *llvm_result = LLVMBuildOr(builder, lhs, rhs, "bitwise or"); + *llvm_result = LLVMBuildOr(builder, llvm_lhs, llvm_rhs, "bitwise or"); break; case BitwiseXor: - *llvm_result = LLVMBuildXor(builder, lhs, rhs, "bitwise xor"); + *llvm_result = LLVMBuildXor(builder, llvm_lhs, llvm_rhs, "bitwise xor"); break; case BitwiseNot: - *llvm_result = LLVMBuildNot(builder, rhs, "bitwise not"); + *llvm_result = LLVMBuildNot(builder, llvm_rhs, "bitwise not"); break; } @@ -57,67 +65,89 @@ static LLVMValueRef convert_integral_to_boolean( return LLVMBuildICmp(builder, LLVMIntNE, zero, integral, "to boolean"); } -BackendError impl_logical_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, - [[maybe_unused]] LLVMLocalScope *scope, +BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { - // TODO: resolve lhs and rhs or op - LLVMValueRef rhs = NULL; - LLVMValueRef lhs = NULL; + Expression *rhs = NULL; + Expression *lhs = NULL; + LLVMValueRef llvm_rhs = NULL; + LLVMValueRef llvm_lhs = NULL; - if (operation->impl.logical == LogicalNot) { + if (operation->impl.arithmetic == LogicalNot) { // 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 { // two operands - lhs = convert_integral_to_boolean(builder, lhs); - rhs = convert_integral_to_boolean(builder, rhs); + 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.logical) { case LogicalAnd: - *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "logical and"); + *llvm_result = LLVMBuildAnd(builder, llvm_lhs, llvm_rhs, "logical and"); break; case LogicalOr: - *llvm_result = LLVMBuildOr(builder, lhs, rhs, "logical or"); + *llvm_result = LLVMBuildOr(builder, llvm_lhs, llvm_rhs, "logical or"); break; case LogicalXor: - *llvm_result = LLVMBuildXor(builder, lhs, rhs, "logical xor"); + *llvm_result = LLVMBuildXor(builder, llvm_lhs, llvm_rhs, "logical xor"); break; case LogicalNot: - *llvm_result = LLVMBuildNot(builder, rhs, "logical not"); + *llvm_result = LLVMBuildNot(builder, llvm_rhs, "logical not"); break; } return SUCCESS; } -static LLVMBool is_floating_point(LLVMValueRef value) { - LLVMTypeRef valueType = LLVMTypeOf(value); - LLVMTypeKind typeKind = LLVMGetTypeKind(valueType); +static LLVMBool is_floating_point(Type *value) { + if (value->kind == TypeKindPrimitive) { + return value->impl.primitive == Float; + } - return typeKind == LLVMFloatTypeKind || typeKind == LLVMHalfTypeKind || typeKind == LLVMDoubleTypeKind || - typeKind == LLVMFP128TypeKind; + if (value->kind == TypeKindComposite) { + return value->impl.composite.primitive == Float; + } + + return FALSE; } -static LLVMBool is_integral(LLVMValueRef value) { - LLVMTypeRef valueType = LLVMTypeOf(value); - LLVMTypeKind typeKind = LLVMGetTypeKind(valueType); +static LLVMBool is_integral(Type *value) { + if (value->kind == TypeKindPrimitive) { + 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, - [[maybe_unused]] LLVMLocalScope *scope, +BackendError impl_relational_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { - // TODO: resolve lhs and rhs or op - LLVMValueRef rhs = NULL; - LLVMValueRef lhs = NULL; + Expression *rhs = NULL; + Expression *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 LLVMIntPredicate operator = 0; @@ -133,8 +163,9 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit * break; } - *llvm_result = LLVMBuildICmp(builder, operator, lhs, rhs, "integral comparison"); - } else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) { + *llvm_result = LLVMBuildICmp(builder, operator, llvm_lhs, llvm_rhs, "integral comparison"); + + } else if (is_floating_point(rhs->result)) { // integral type LLVMRealPredicate operator = 0; @@ -150,7 +181,7 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit * break; } - *llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison"); + *llvm_result = LLVMBuildFCmp(builder, operator, llvm_lhs, llvm_rhs, "floating point comparison"); } else { PANIC("invalid type for relational operator"); } @@ -158,53 +189,69 @@ BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit * return SUCCESS; } -BackendError impl_arithmetic_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, - [[maybe_unused]] LLVMLocalScope *scope, +BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { - // TODO: resolve lhs and rhs or op - LLVMValueRef rhs = NULL; - LLVMValueRef lhs = NULL; + Expression *rhs = NULL; + Expression *lhs = NULL; + LLVMValueRef llvm_rhs = NULL; + LLVMValueRef llvm_lhs = NULL; - if ((is_integral(lhs) && is_integral(rhs)) == 1) { - // integral type + if (operation->impl.arithmetic == Negate) { + // 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) { case Add: - *llvm_result = LLVMBuildNSWAdd(builder, lhs, rhs, "signed integer addition"); + *llvm_result = LLVMBuildNSWAdd(builder, llvm_lhs, llvm_rhs, "signed integer addition"); break; case Sub: - *llvm_result = LLVMBuildNSWSub(builder, lhs, rhs, "signed integer subtraction"); + *llvm_result = LLVMBuildNSWSub(builder, llvm_lhs, llvm_rhs, "signed integer subtraction"); break; case Mul: - *llvm_result = LLVMBuildNSWMul(builder, lhs, rhs, "signed integer multiply"); + *llvm_result = LLVMBuildNSWMul(builder, llvm_lhs, llvm_rhs, "signed integer multiply"); break; 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; } - } else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) { - // integral type - LLVMRealPredicate operator = 0; + } else if (is_floating_point(rhs->result)) { switch (operation->impl.arithmetic) { case Add: - *llvm_result = LLVMBuildFAdd(builder, lhs, rhs, "floating point addition"); + *llvm_result = LLVMBuildFAdd(builder, llvm_lhs, llvm_rhs, "floating point addition"); break; case Sub: - *llvm_result = LLVMBuildFSub(builder, lhs, rhs, "floating point subtraction"); + *llvm_result = LLVMBuildFSub(builder, llvm_lhs, llvm_rhs, "floating point subtraction"); break; case Mul: - *llvm_result = LLVMBuildFMul(builder, lhs, rhs, "floating point multiply"); + *llvm_result = LLVMBuildFMul(builder, llvm_lhs, llvm_rhs, "floating point multiply"); break; 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; } - *llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison"); } else { PANIC("invalid type for arithmetic operator"); } @@ -244,8 +291,10 @@ BackendError impl_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Transmute *transmute, LLVMValueRef *llvm_result) { - // TODO: resolve sub expression + LLVMValueRef operand = NULL; + impl_expr(unit, scope, builder, transmute->operand, &operand); + LLVMTypeRef target_type = NULL; BackendError err = get_type_impl(unit, scope->func_scope->global_scope, transmute->targetType, &target_type); @@ -272,8 +321,9 @@ static LLVMBool is_type_signed(const Type *type) { BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, TypeCast *typecast, LLVMValueRef *llvm_result) { - // TODO: resolve sub expression LLVMValueRef operand = NULL; + impl_expr(unit, scope, builder, typecast->operand, &operand); + LLVMTypeRef target_type = NULL; BackendError err = get_type_impl(unit, scope->func_scope->global_scope, typecast->targetType, &target_type); @@ -283,24 +333,40 @@ BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, } 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 = - LLVMGetCastOpcode(operand, 0, target_type, dst_signed); + LLVMGetCastOpcode(operand, src_signed, target_type, dst_signed); *llvm_result = LLVMBuildCast(builder, opcode, operand, target_type, "transmute"); 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, LLVMBuilderRef builder, Expression *expr, LLVMValueRef *llvm_result) { + DEBUG("implementing expression: %ld", expr->kind); BackendError err = SUCCESS; switch (expr->kind) { case ExpressionKindConstant: err = get_const_type_value(unit, scope->func_scope->global_scope, - &expr->impl.constant, llvm_result); + &expr->impl.constant, llvm_result); break; case ExpressionKindTransmute: err = impl_transmute(unit, scope, builder, &expr->impl.transmute, @@ -314,6 +380,13 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, err = impl_operation(unit, scope, builder, &expr->impl.operation, llvm_result); 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; diff --git a/src/llvm/llvm-ir/func.c b/src/llvm/llvm-ir/func.c index 5fa251e..a2cac61 100644 --- a/src/llvm/llvm-ir/func.c +++ b/src/llvm/llvm-ir/func.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,13 @@ LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* 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, @@ -110,7 +117,7 @@ BackendError impl_func_decl(LLVMBackendCompileUnit* unit, return err; } -BackendError impl_func(LLVMBackendCompileUnit* unit, +BackendError impl_func_def(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_scope, FunctionDefinition* fundef, const char* name) { BackendError err = SUCCESS; @@ -131,10 +138,10 @@ BackendError impl_func(LLVMBackendCompileUnit* unit, g_hash_table_insert(global_scope->functions, (gpointer)name, llvm_func); // create function body builder - LLVMBasicBlockRef body = - LLVMAppendBasicBlockInContext(unit->context, llvm_func, "entry"); + LLVMBasicBlockRef entry = + LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.entry"); LLVMBuilderRef builder = LLVMCreateBuilderInContext(unit->context); - LLVMPositionBuilderAtEnd(builder, body); + LLVMPositionBuilderAtEnd(builder, entry); // create value references for parameter const size_t params = fundef->parameter->len; @@ -144,7 +151,20 @@ BackendError impl_func(LLVMBackendCompileUnit* unit, 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); @@ -168,11 +188,16 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit, size_t function_count = 0; while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { - err = - impl_func(unit, scope, (FunctionDefinition*)val, (const char*)key); + Function* func = (Function*) val; + + 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) { - break; + return err; } function_count++; diff --git a/src/llvm/llvm-ir/stmt.c b/src/llvm/llvm-ir/stmt.c index 189636b..bd3ba09 100644 --- a/src/llvm/llvm-ir/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -9,6 +9,7 @@ #include #include #include +#include BackendError impl_assign_stmt( LLVMBackendCompileUnit *unit, @@ -31,6 +32,7 @@ BackendError impl_assign_stmt( case VariableKindDefinition: LLVMValueRef llvm_ptr = get_variable(scope, assignment->variable->name); + LLVMBuildStore(builder, llvm_value, llvm_ptr ); break; @@ -44,20 +46,39 @@ BackendError impl_assign_stmt( BackendError impl_basic_block(LLVMBackendCompileUnit *unit, 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; LLVMLocalScope *block_scope = new_local_scope(scope); // append a new LLVM basic block - *llvm_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, - "basic block"); - LLVMPositionBuilderAtEnd(builder, *llvm_block); + *llvm_start_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.block.start"); + LLVMPositionBuilderAtEnd(builder, *llvm_start_block); + + LLVMBasicBlockRef end_previous_block = *llvm_start_block; for (size_t i = 0; i < block->statemnts->len; i++) { - Statement *stmt = ((Statement *) block->statemnts->data) + i; - impl_stmt(unit, builder, scope, stmt); + DEBUG("building block statement %d of %d", i, block->statemnts->len); + 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); return err; @@ -65,21 +86,33 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit, BackendError impl_while(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, + LLVMBasicBlockRef* llvm_start_block, + LLVMBasicBlockRef* llvm_end_block, const While *while_stmt) { + DEBUG("implementing while..."); BackendError err; // Create condition block LLVMBasicBlockRef while_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, "loop.while.cond"); + *llvm_start_block = while_cond_block; LLVMPositionBuilderAtEnd(builder, while_cond_block); // Resolve condition in block to a variable 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 - LLVMBasicBlockRef while_body_block = NULL; - err = impl_basic_block(unit, builder, scope, &while_stmt->block, &while_body_block); - LLVMPositionBuilderAtEnd(builder, while_body_block); + LLVMBasicBlockRef while_start_body_block = NULL; + LLVMBasicBlockRef while_end_body_block = NULL; + 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 LLVMBuildBr(builder, while_cond_block); @@ -88,10 +121,12 @@ BackendError impl_while(LLVMBackendCompileUnit *unit, "loop.while.after"); // build conditional branch at end of condition 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); + *llvm_end_block = while_after_block; + return err; } @@ -124,7 +159,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, 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)) { LLVMValueRef zero = LLVMConstInt(LLVMInt32TypeInContext(unit->context), 0, 0); @@ -148,7 +183,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, BackendError 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) { BackendError err; @@ -159,7 +194,7 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS err = impl_expr(unit, scope, builder, cond, llvm_cond); if (err.kind == Success) { // 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; @@ -167,49 +202,57 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS BackendError impl_branch(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, + LLVMBasicBlockRef* branch_start_block, + LLVMBasicBlockRef* branch_end_block, const Branch *branch) { BackendError err = SUCCESS; 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)); // add If to arrays { LLVMBasicBlockRef cond_block = NULL; - LLVMBasicBlockRef body_block = NULL; + LLVMBasicBlockRef start_body_block = NULL; + LLVMBasicBlockRef end_body_block = NULL; LLVMValueRef cond_value = NULL; err = impl_cond_block(unit, builder, scope, (Expression *) &branch->ifBranch.conditon, &branch->ifBranch.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(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); } // generate else if(s) for (size_t i = 0; i < branch->elseIfBranches->len; i++) { LLVMBasicBlockRef cond_block = NULL; - LLVMBasicBlockRef body_block = NULL; + LLVMBasicBlockRef start_body_block = NULL; + LLVMBasicBlockRef end_body_block = NULL; LLVMValueRef cond_value = NULL; ElseIf *elseIf = ((ElseIf *) branch->elseIfBranches->data) + i; 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(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); } // else block if (branch->elseBranch.nodePtr != NULL) { - LLVMBasicBlockRef else_block = NULL; - err = impl_basic_block(unit, builder, scope, &branch->elseBranch.block, &else_block); - g_array_append_val(cond_blocks, else_block); + LLVMBasicBlockRef start_else_block = NULL; + LLVMBasicBlockRef end_else_block = NULL; + 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, @@ -224,18 +267,23 @@ BackendError impl_branch(LLVMBackendCompileUnit *unit, for (size_t i = 0; i < cond_blocks->len - 1; i++) { LLVMBasicBlockRef next_block = ((LLVMBasicBlockRef *) cond_blocks->data)[i + 1]; 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]; 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); } + *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(body_blocks, TRUE); + g_array_free(start_body_blocks, TRUE); + g_array_free(end_body_blocks, TRUE); g_array_free(cond_values, TRUE); return err; @@ -308,10 +356,10 @@ BackendError impl_var(LLVMBackendCompileUnit *unit, BackendError err; switch (var->kind) { - VariableKindDeclaration: + case VariableKindDeclaration: err = impl_decl(unit, builder, scope, &var->impl.declaration, var->name); break; - VariableKindDefinition: + case VariableKindDefinition: err = impl_def(unit, builder, scope, &var->impl.definiton, var->name); break; default: @@ -322,28 +370,31 @@ BackendError impl_var(LLVMBackendCompileUnit *unit, 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; switch (stmt->kind) { - StatementKindAssignment: + case StatementKindAssignment: err = impl_assign_stmt(unit, builder, scope, &stmt->impl.assignment); break; - StatementKindBranch: - err = impl_branch(unit, builder, scope, &stmt->impl.branch); + case StatementKindBranch: + err = impl_branch(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.branch); break; - StatementKindDeclaration: - StatementKindDefinition: + case StatementKindDeclaration: + case StatementKindDefinition: err = impl_var(unit, builder, scope, stmt->impl.variable); break; - StatementKindWhile: - err = impl_while(unit, builder, scope, &stmt->impl.whileLoop); + case StatementKindWhile: + err = impl_while(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.whileLoop); break; - StatementKindFunctionCall: + case StatementKindFunctionCall: err = impl_func_call(unit, builder, scope, &stmt->impl.call); break; default: err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind"); + break; } return err; @@ -351,7 +402,10 @@ BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLV BackendError impl_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMFuncScope *scope, + LLVMBasicBlockRef* llvm_start_block, + LLVMBasicBlockRef* llvm_end_block, const Block *block) { + DEBUG("Implementing function block..."); BackendError err = SUCCESS; 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->parent_scope = NULL; - LLVMBasicBlockRef llvm_block = NULL; - err = impl_basic_block(unit, builder, function_entry_scope, block, &llvm_block); + err = impl_basic_block(unit, builder, function_entry_scope, block, llvm_start_block, llvm_end_block); delete_local_scope(function_entry_scope); diff --git a/src/llvm/llvm-ir/stmt.h b/src/llvm/llvm-ir/stmt.h index a20c27c..8cc3dfe 100644 --- a/src/llvm/llvm-ir/stmt.h +++ b/src/llvm/llvm-ir/stmt.h @@ -8,9 +8,12 @@ #include BackendError impl_block(LLVMBackendCompileUnit *unit, - LLVMBuilderRef builder, LLVMFuncScope *scope, - const Block *block); + LLVMBuilderRef builder, LLVMFuncScope *scope, + LLVMBasicBlockRef* llvm_start_block, + LLVMBasicBlockRef* llvm_end_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 diff --git a/src/llvm/llvm-ir/types.c b/src/llvm/llvm-ir/types.c index 2b8a994..52b08a9 100644 --- a/src/llvm/llvm-ir/types.c +++ b/src/llvm/llvm-ir/types.c @@ -96,7 +96,7 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, 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); LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits); diff --git a/src/llvm/llvm-ir/variables.c b/src/llvm/llvm-ir/variables.c index 05465d7..a535aa0 100644 --- a/src/llvm/llvm-ir/variables.c +++ b/src/llvm/llvm-ir/variables.c @@ -120,3 +120,11 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, 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; +} diff --git a/src/llvm/llvm-ir/variables.h b/src/llvm/llvm-ir/variables.h index 346e856..fb0c94f 100644 --- a/src/llvm/llvm-ir/variables.h +++ b/src/llvm/llvm-ir/variables.h @@ -12,4 +12,6 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GHashTable* variables); +LLVMValueRef get_global_variable(LLVMGlobalScope* scope, char* name); + #endif // LLVM_BACKEND_VARIABLES_H_ diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 6cc1d21..bd37eaf 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -75,7 +75,7 @@ BackendError emit_module_to_file(LLVMBackendCompileUnit* unit, filename = g_build_filename(config->archive_directory, basename, NULL); break; 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); break; default: @@ -83,6 +83,10 @@ BackendError emit_module_to_file(LLVMBackendCompileUnit* unit, "invalid codegen file"); } + // TODO: add custom link libraries + + INFO("export to file: %s", filename); + if (LLVMTargetMachineEmitToFile(target_machine, unit->module, filename, file_type, &error) != 0) { ERROR("failed to emit code: %s", error); diff --git a/src/set/types.c b/src/set/types.c deleted file mode 100644 index e69de29..0000000