From 902a81528b9d2edcf93226a2ca13da6fcc1839e5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 23 Dec 2019 08:57:48 +0100 Subject: wip: function pointers and other stuff --- src/ir/ir.c | 214 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 146 insertions(+), 68 deletions(-) (limited to 'src/ir/ir.c') diff --git a/src/ir/ir.c b/src/ir/ir.c index 62d3516..1ca154a 100644 --- a/src/ir/ir.c +++ b/src/ir/ir.c @@ -294,34 +294,44 @@ static CHECK_RESULT int ir_ins_assign_reg(Ir *self, IrRegister dest, IrRegister return ir_add_ins_form1(self, IR_ASSIGN_REG, dest, src); } +static CHECK_RESULT int ir_ins_assign_func(Ir *self, IrRegister dest, IrFuncIndex func_index) { + amal_log_debug("r%d = f%d", dest, func_index); + return ir_add_ins_form1(self, IR_ASSIGN_FUNC, dest, func_index); +} + static CHECK_RESULT int ir_ins_binop(Ir *self, IrInstruction binop_type, IrRegister lhs, IrRegister rhs, IrRegister *result) { assert(binop_type >= IR_ADD && binop_type <= IR_GE); return ir_add_ins_form2(self, binop_type, lhs, rhs, result); } -static CHECK_RESULT int ir_ins_func_start(Ir *self, u8 func_flags, FunctionSignature *func_sig, IrFuncIndex *result, usize *func_metadata_index) { +static CHECK_RESULT int ir_ins_func_start(Ir *self, u8 func_flags, FunctionSignature *func_sig, usize *func_metadata_index) { const u8 ins_type = IR_FUNC_START; IrInsFuncStart ins_func_start; + IrFunc func; - /* Overflow */ - if(self->func_counter + 1 <= self->func_counter) { - amal_log_error("Ir too many closures!"); - return -1; - } + func.func_sig = func_sig; + return_if_error(buffer_append(&self->funcs, &func, sizeof(func))); - *result = self->func_counter++; - { - IrFunc func; - func.func_sig = func_sig; - return_if_error(buffer_append(&self->funcs, &func, sizeof(func))); - } ins_func_start.flags = func_flags; /* Dont set number of local registers yet. That will be set by @func_metadata_index later when it's known */ /*ins_func_start.num_local_vars_regs = ---*/ return_if_error(buffer_append(&self->instructions, &ins_type, 1)); return_if_error(buffer_append(&self->instructions, &ins_func_start, sizeof(ins_func_start))); *func_metadata_index = self->instructions.size - sizeof(ins_func_start.num_local_vars_regs); - amal_log_debug("FUNC_START f%u(%d) %d", *result, buffer_get_size(&func_sig->parameters, FunctionParameter), buffer_get_size(&func_sig->return_types, FunctionReturnType)); + amal_log_debug("FUNC_START f%d(%d) %d", + func_sig->func_decl ? func_sig->func_decl->ir_func_index : -1, + buffer_get_size(&func_sig->parameters, FunctionParameter), + buffer_get_size(&func_sig->return_types, FunctionReturnType)); + return 0; +} + +static CHECK_RESULT int ir_inc_func_index(Ir *self, IrFuncIndex *result) { + /* Overflow */ + if(self->func_counter + 1 <= self->func_counter) { + amal_log_error("Ir too many closures!"); + return -1; + } + *result = self->func_counter++; return 0; } @@ -373,6 +383,13 @@ static CHECK_RESULT int ir_ins_call_extern(Ir *self, int import_index, LhsExpr * return buffer_append(&self->instructions, &ins_func_call_extern, sizeof(ins_func_call_extern)); } +static CHECK_RESULT int ir_ins_call_reg(Ir *self, IrRegister reg) { + const u8 ins_type = IR_CALLR; + amal_log_debug("CALLR r%d", reg); + return_if_error(buffer_append(&self->instructions, &ins_type, 1)); + return buffer_append(&self->instructions, ®, sizeof(reg)); +} + static CHECK_RESULT int ir_ins_jumpzero(Ir *self, IrRegister condition_reg, IrLabelIndex target_label, usize *instruction_offset) { const u8 ins_type = IR_JUMP_ZERO; IrInsJumpZero ins_jump_zero; @@ -466,23 +483,6 @@ static bool ast_resolved_type_is_decl(AstResolvedType *self) { return lhs_expr->rhs_expr->type == AST_FUNCTION_DECL || lhs_expr->rhs_expr->type == AST_STRUCT_DECL; } #endif -static bool lhs_expr_is_decl(LhsExpr *self) { - if(self->rhs_expr) { - return self->rhs_expr->type == AST_FUNCTION_DECL || self->rhs_expr->type == AST_STRUCT_DECL; - } else { - switch(self->type.type) { - case VARIABLE_TYPE_NONE: - assert(bool_false); - return 0; - case VARIABLE_TYPE_VARIABLE: - return bool_false; - case VARIABLE_TYPE_SIGNATURE: - /* TODO: This should return bool_false when it's possible to use signature in expressions */ - return bool_true; - } - return 0; - } -} static CHECK_RESULT IrRegister number_generate_ir(Number *self, IrCompilerContext *context) { IrRegister reg; @@ -501,6 +501,17 @@ static CHECK_RESULT IrRegister number_generate_ir(Number *self, IrCompilerContex return reg; } +static CHECK_RESULT IrRegister ast_bool_generate_ir(AstBool *self, IrCompilerContext *context) { + IrRegister reg; + IrNumber number; + number.type = IR_NUMBER_TYPE_INTEGER; + number.value.integer = self->value; + throw_if_error(ir_get_unique_reg(context->ir, ®)); + /* TODO: Maybe bool shouldn't be a regular number? */ + throw_if_error(ir_ins_assign_inter(context->ir, reg, number)); + return reg; +} + static CHECK_RESULT IrRegister lhsexpr_extern_generate_ir(LhsExpr *self, IrCompilerContext *context) { /* TODO: IrRegister should be extended to include static and extern data */ if(self->type.type == VARIABLE_TYPE_SIGNATURE) { @@ -534,6 +545,7 @@ static CHECK_RESULT IrRegister lhsexpr_extern_generate_ir(LhsExpr *self, IrCompi return 0; } +#if 0 static CHECK_RESULT IrRegister lhsexpr_export_generate_ir(LhsExpr *self, IrCompilerContext *context) { /* TODO: IrRegister should be extended to include static and export data */ if(self->rhs_expr->type == AST_FUNCTION_DECL) { @@ -543,6 +555,7 @@ static CHECK_RESULT IrRegister lhsexpr_export_generate_ir(LhsExpr *self, IrCompi } return 0; } +#endif static CHECK_RESULT IrRegister lhsexpr_generate_ir(LhsExpr *self, AstResolveData *resolve_data, IrCompilerContext *context) { IrRegister reg; @@ -552,19 +565,17 @@ static CHECK_RESULT IrRegister lhsexpr_generate_ir(LhsExpr *self, AstResolveData if(self->rhs_expr) { Ast *rhs_expr = self->rhs_expr; - IrRegister rhs_reg; - rhs_reg = ast_generate_ir(rhs_expr, context); + IrRegister rhs_reg = ast_generate_ir(rhs_expr, context); +#if 0 if(LHS_EXPR_IS_EXPORT(self)) return lhsexpr_export_generate_ir(self, context); - +#endif /* - Declarations (struct and function declaration) resolves to itself and in that case this expression - is just a compile-time name for the declaration. Import expression also has no meaning in IR until it's used. TODO: Shouldn't lhsexpr that have struct/function declaration as rhs be different ast expression types? */ - if(lhs_expr_is_decl(self) || rhs_expr->type == AST_IMPORT) { + if(rhs_expr->type == AST_IMPORT) { /*assert(bool_false);*/ return 0; } @@ -620,12 +631,7 @@ static CHECK_RESULT void function_signature_generate_params_ir(FunctionSignature } } -/* -TODO: Each function declaration should be in separate IR instances so ast can be converted into ir -in any order. -*/ static CHECK_RESULT IrRegister funcdecl_generate_ir(FunctionDecl *self, IrCompilerContext *context) { - /* TODO: Implement */ /* Reset reg counter in each function, because each function has a separate register context that is reset after function end @@ -636,10 +642,7 @@ static CHECK_RESULT IrRegister funcdecl_generate_ir(FunctionDecl *self, IrCompil context->ir->param_counter = 0; context->ir->label_counter = 0; - /* - Parameters need to have generated ir so the first ir registers belong to the function. - This way we can know if a register access is for a parameter or not by checking the number - */ + /* All parameters need to be generated, so that the parameter matches its index... */ function_signature_generate_params_ir(self->signature, context); amal_log_debug("IR funcdecl %p", self); @@ -649,7 +652,7 @@ static CHECK_RESULT IrRegister funcdecl_generate_ir(FunctionDecl *self, IrCompil if(LHS_EXPR_IS_EXPORT(self->lhs_expr)) func_flags |= FUNC_FLAG_EXPORTED; } - throw_if_error(ir_ins_func_start(context->ir, func_flags, self->signature, &self->ir_func_index, &func_metadata_index)); + throw_if_error(ir_ins_func_start(context->ir, func_flags, self->signature, &func_metadata_index)); scope_generate_ir(&self->body, context); throw_if_error(ir_ins_func_end(context->ir)); @@ -658,27 +661,57 @@ static CHECK_RESULT IrRegister funcdecl_generate_ir(FunctionDecl *self, IrCompil return 0; } +static CHECK_RESULT IrRegister funcdecl_ref_generate_ir(FunctionDecl *self, IrCompilerContext *context) { + IrRegister reg; + if(self->lhs_expr && LHS_EXPR_IS_EXTERN(self->lhs_expr)) { + assert(bool_false && "TODO: Implement assign func for extern closures"); + throw(-1); + } + throw_if_error(ir_get_unique_reg(context->ir, ®)); + throw_if_error(ir_ins_assign_func(context->ir, reg, self->ir_func_index)); + return reg; +} + + static CHECK_RESULT IrRegister funccall_generate_ir(FunctionCall *self, IrCompilerContext *context) { IrRegister reg; FunctionSignature *func_sig; FunctionDecl *func_decl; LhsExpr *func_lhs_expr; + FunctionParameter *func_param_expr; int import_index = context->import_index; + + func_lhs_expr = NULL; + func_param_expr = NULL; context->import_index = 0; throw_if_error(ir_get_unique_reg(context->ir, ®)); - assert(self->func.resolved_var.type == NAMED_OBJECT_LHS_EXPR); - func_lhs_expr = self->func.resolved_var.value.lhs_expr; - if(func_lhs_expr->type.type == VARIABLE_TYPE_SIGNATURE) { - func_sig = func_lhs_expr->type.value.signature; - } else if(func_lhs_expr->type.type == VARIABLE_TYPE_VARIABLE) { - AstResolveData *resolve_data = func_lhs_expr->type.value.variable->resolved_var.resolve_data; - assert(resolve_data->type.type == RESOLVED_TYPE_FUNC_SIG); - func_sig = resolve_data->type.value.func_sig; - } else { - assert(func_lhs_expr->rhs_expr && func_lhs_expr->rhs_expr->resolve_data.type.type == RESOLVED_TYPE_FUNC_SIG); - func_sig = func_lhs_expr->rhs_expr->resolve_data.type.value.func_sig; + switch(self->func.resolved_var.type) { + case NAMED_OBJECT_NONE: + assert(bool_false); + break; + case NAMED_OBJECT_LHS_EXPR: { + func_lhs_expr = self->func.resolved_var.value.lhs_expr; + if(func_lhs_expr->type.type == VARIABLE_TYPE_SIGNATURE) { + func_sig = func_lhs_expr->type.value.signature; + } else if(func_lhs_expr->type.type == VARIABLE_TYPE_VARIABLE) { + AstResolveData *resolve_data = func_lhs_expr->type.value.variable->resolved_var.resolve_data; + assert(resolve_data->type.type == RESOLVED_TYPE_FUNC_SIG); + func_sig = resolve_data->type.value.func_sig; + } else { + assert(func_lhs_expr->rhs_expr && func_lhs_expr->rhs_expr->resolve_data.type.type == RESOLVED_TYPE_FUNC_SIG); + func_sig = func_lhs_expr->rhs_expr->resolve_data.type.value.func_sig; + } + break; + } + case NAMED_OBJECT_FUNC_PARAM: { + func_param_expr = self->func.resolved_var.value.func_param; + assert(func_param_expr->type.type == VARIABLE_TYPE_SIGNATURE); + func_sig = func_param_expr->type.value.signature; + break; + } } + func_decl = func_sig->func_decl; /* Push return arguments */ @@ -719,15 +752,16 @@ static CHECK_RESULT IrRegister funccall_generate_ir(FunctionCall *self, IrCompil if(func_lhs_expr && LHS_EXPR_IS_EXTERN(func_lhs_expr)) { throw_if_error(ir_ins_call_extern(context->ir, import_index, func_lhs_expr)); - } else { - assert(func_decl); - /* rhs wont be null here because only extern variable can't have rhs */ + } else if(func_decl) { throw_if_error(ir_ins_call(context->ir, import_index, func_decl)); + } else if(func_param_expr) { + throw_if_error(ir_ins_call_reg(context->ir, function_parameter_generate_ir(func_param_expr, context))); } return reg; } +#if 0 static CHECK_RESULT IrRegister structdecl_generate_ir(StructDecl *self, IrCompilerContext *context) { /* TODO: Implement */ /*assert(bool_false);*/ @@ -742,6 +776,7 @@ static CHECK_RESULT IrRegister structfield_generate_ir(StructField *self, IrComp (void)context; return 0; } +#endif static CHECK_RESULT IrRegister string_generate_ir(String *self, IrCompilerContext *context) { IrRegister reg; @@ -895,24 +930,29 @@ static void return_expr_generate_ir(ReturnExpr *self, IrCompilerContext *context } static CHECK_RESULT IrRegister ast_generate_ir_resolve_data(void *ast_data, AstType ast_type, AstResolveData *resolve_data, IrCompilerContext *context) { - if(resolve_data->status == AST_IR_RESOLVED) - return resolve_data->ir_reg; + /*if(resolve_data->status == AST_IR_RESOLVED) + return resolve_data->ir_reg;*/ switch(ast_type) { case AST_NUMBER: resolve_data->ir_reg = number_generate_ir(ast_data, context); break; + case AST_BOOL: + resolve_data->ir_reg = ast_bool_generate_ir(ast_data, context); + break; case AST_FUNCTION_DECL: - resolve_data->ir_reg = funcdecl_generate_ir(ast_data, context); + /* The IR for function declarations is done separately, in @scope_generate_functions_ir */ + resolve_data->ir_reg = funcdecl_ref_generate_ir(ast_data, context); break; case AST_FUNCTION_CALL: resolve_data->ir_reg = funccall_generate_ir(ast_data, context); break; case AST_STRUCT_DECL: - resolve_data->ir_reg = structdecl_generate_ir(ast_data, context); + resolve_data->ir_reg = 0;/*structdecl_generate_ir(ast_data, context);*/ break; case AST_STRUCT_FIELD: - resolve_data->ir_reg = structfield_generate_ir(ast_data, context); + assert(bool_false); + resolve_data->ir_reg = 0;/*structfield_generate_ir(ast_data, context);*/ break; case AST_LHS: resolve_data->ir_reg = lhsexpr_generate_ir(ast_data, resolve_data, context); @@ -941,7 +981,6 @@ static CHECK_RESULT IrRegister ast_generate_ir_resolve_data(void *ast_data, AstT break; case AST_RETURN: return_expr_generate_ir(ast_data, context); - resolve_data->ir_reg = 0; break; } @@ -950,13 +989,13 @@ static CHECK_RESULT IrRegister ast_generate_ir_resolve_data(void *ast_data, AstT } CHECK_RESULT IrRegister ast_generate_ir(Ast *self, IrCompilerContext *context) { +#ifdef DEBUG assert(self); - #ifdef DEBUG if(self->resolve_data.status != AST_RESOLVED && self->resolve_data.status != AST_IR_RESOLVED) { amal_log_error("Ast type not resolved: %d", self->type); assert(bool_false); } - #endif +#endif return ast_generate_ir_resolve_data(self->value.data, self->type, &self->resolve_data, context); } @@ -980,3 +1019,42 @@ void scope_generate_ir(Scope *self, IrCompilerContext *context) { ignore_result_int(ast_generate_ir(*ast, context)); } } + +void scope_generate_function_ids(Scope *self, IrCompilerContext *context) { + Ast **ast = buffer_begin(&self->ast_objects); + Ast **ast_end = buffer_end(&self->ast_objects); + for(; ast != ast_end; ++ast) { + if((*ast)->type == AST_LHS && (*ast)->value.lhs_expr->rhs_expr->type == AST_FUNCTION_DECL) { + LhsExpr *lhs_expr = (*ast)->value.lhs_expr; + FunctionDecl *func_decl = lhs_expr->rhs_expr->value.func_decl; + /* + Going depth first will optimize scope private closures, so they are declared + before the function they are defined in. This means calling them wont create a deferred function call + in program.c + */ + scope_generate_functions_ir(&func_decl->body, context); + /* TODO: Should this not be done for extern closures? */ + throw_if_error(ir_inc_func_index(context->ir, &func_decl->ir_func_index)); + } + } +} + +void scope_generate_functions_ir(Scope *self, IrCompilerContext *context) { + Ast **ast = buffer_begin(&self->ast_objects); + Ast **ast_end = buffer_end(&self->ast_objects); + for(; ast != ast_end; ++ast) { + if((*ast)->type == AST_LHS && (*ast)->value.lhs_expr->rhs_expr->type == AST_FUNCTION_DECL) { + LhsExpr *lhs_expr = (*ast)->value.lhs_expr; + FunctionDecl *func_decl = lhs_expr->rhs_expr->value.func_decl; + /* + Going depth first will optimize scope private closures, so they are declared + before the function they are defined in. This means calling them wont create a deferred function call + in program.c + */ + scope_generate_functions_ir(&func_decl->body, context); + ignore_result_int(funcdecl_generate_ir(func_decl, context)); + if(LHS_EXPR_IS_EXPORT(lhs_expr)) + throw_if_error(ir_try_add_export_func(context->ir, func_decl->signature, lhs_expr->var_name)); + } + } +} -- cgit v1.2.3