From f5dc9ad48db4d22e7d6f15e340063dc7cb14c1e1 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 29 Sep 2019 23:47:52 +0200 Subject: Implicit cast from str to ?&c_char, fix use of parameters (to use sys v registers) --- src/ast.c | 19 +++++++++++++++++-- src/bytecode/bytecode.c | 13 +++++++++---- src/parser.c | 11 +++-------- src/program.c | 29 ++++++++++++++++++++++------- src/ssa/ssa.c | 31 +++++++++++++++++++------------ src/tokenizer.c | 11 +++++++++++ 6 files changed, 81 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/ast.c b/src/ast.c index 90af981..5336e1e 100644 --- a/src/ast.c +++ b/src/ast.c @@ -733,8 +733,17 @@ static usize min(usize a, usize b) { return a < b ? a : b; } +static bool is_c_pointer_compatible(VariableType *self) { + return self->variable_type_flags & (VARIABLE_TYPE_FLAG_OPTIONAL | VARIABLE_TYPE_FLAG_BORROW); +} + +static bool is_type_compatible_with(AstResolvedType *self, AstResolvedType *other, AstCompilerContext *context) { + return self->value.data == &context->compiler->default_types.str->lhs_expr && + other->value.data == context->compiler->default_types.c_char && is_c_pointer_compatible(&other->value.lhs_expr->type); +} + static bool resolve_data_type_equals(AstResolvedType *self, AstResolvedType *other) { - return self->type == other->type && self->value.data == other->value.data; + return self->value.data == other->value.data; } static bool function_parameter_is_vararg(FunctionParameter *self, AstCompilerContext *context) { @@ -742,6 +751,12 @@ static bool function_parameter_is_vararg(FunctionParameter *self, AstCompilerCon return self->resolve_data.type.value.data == &vararg_type->lhs_expr; } +static bool is_function_arg_compatible_with_parameter(AstResolvedType *arg, FunctionParameter *param, AstCompilerContext *context) { + return resolve_data_type_equals(arg, ¶m->resolve_data.type) || + is_type_compatible_with(arg, ¶m->resolve_data.type, context) || + function_parameter_is_vararg(param, context); +} + static void verify_func_call_matches_func_signature(FunctionCall *func_call, FunctionSignature *func_sig, AstCompilerContext *context) { Ast **arg = buffer_begin(&func_call->args); Ast **arg_end = buffer_end(&func_call->args); @@ -755,7 +770,7 @@ static void verify_func_call_matches_func_signature(FunctionCall *func_call, Fun usize num_check = min(num_args, num_params); usize i = 0; for(; i < num_check; ++i) { - if(!resolve_data_type_equals(&(*arg)->resolve_data.type, &func_param->resolve_data.type) && !function_parameter_is_vararg(func_param, context)) { + if(!is_function_arg_compatible_with_parameter(&(*arg)->resolve_data.type, func_param, context)) { BufferView arg_name = ast_resolved_type_get_name(&(*arg)->resolve_data.type); BufferView param_name = ast_resolved_type_get_name(&func_param->resolve_data.type); compiler_print_error(context->compiler, func_call->func.name.data, diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index a5e3abc..b947985 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -387,7 +387,7 @@ static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const cha } } -static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, const char *fmt) { +static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, AmalReg reg, const char *fmt) { Buffer *instructions = &self->bytecode->data; size_t index = instructions->size; @@ -398,7 +398,7 @@ static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, c fputc('\n', stderr); } -static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 src_reg, const char *fmt) { +static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, AmalReg dst_reg, AmalReg src_reg, const char *fmt) { Buffer *instructions = &self->bytecode->data; size_t index = instructions->size; @@ -421,7 +421,7 @@ static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data, fputc('\n', stderr); } -static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 reg1, i8 reg2, const char *fmt) { +static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, AmalReg dst_reg, AmalReg reg1, AmalReg reg2, const char *fmt) { Buffer *instructions = &self->bytecode->data; size_t index = instructions->size; @@ -434,7 +434,7 @@ static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re fputc('\n', stderr); } -static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, u16 data, const char *fmt) { +static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, AmalReg dst_reg, u16 data, const char *fmt) { Buffer *instructions = &self->bytecode->data; size_t index = instructions->size; @@ -525,6 +525,11 @@ static void add_instructions(BytecodeCompilerContext *self) { add_ins5(self, AMAL_OP_CMP, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "cmp r%d, r%d, r%d"); break; } + case SSA_AND: { + instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2)); + add_ins5(self, AMAL_OP_BIT_AND, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "and r%d, r%d, r%d"); + break; + } case SSA_FUNC_START: { instruction += ssa_extract_data(instruction, &ssa_ins_func_start, sizeof(ssa_ins_func_start)); add_ins6(self, AMAL_OP_FUNC_START, ssa_ins_func_start.flags, ssa_ins_func_start.num_local_vars_regs, "func_start 0x%02x, %u"); diff --git a/src/parser.c b/src/parser.c index dc39a6a..be19a33 100644 --- a/src/parser.c +++ b/src/parser.c @@ -290,14 +290,9 @@ void parser_parse_var_type(Parser *self, VariableType *result) { if(match) result->variable_type_flags |= VARIABLE_TYPE_FLAG_OPTIONAL; - throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); - if(match) { - if(self->tokenizer.value.binop_type != BINOP_MUL) { - self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), "Expected '*', type or closure signature"); - throw(PARSER_UNEXPECTED_TOKEN); - } + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_AMPERSAND, &match)); + if(match) result->variable_type_flags |= VARIABLE_TYPE_FLAG_BORROW; - } throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); if(match) { @@ -329,7 +324,7 @@ void parser_parse_var_type_def(Parser *self, VariableType *result) { if(result->type == VARIABLE_TYPE_NONE) { self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), - "Expected type or closure signature"); + "Expected '?', '&', type or closure signature"); throw(PARSER_UNEXPECTED_TOKEN); } } diff --git a/src/program.c b/src/program.c index 4c0f1a2..ac3c923 100644 --- a/src/program.c +++ b/src/program.c @@ -445,6 +445,14 @@ static void header_func_set_offset(amal_program *self, u16 func_index, u32 code_ am_memcpy(&header_func->func_offset, &code_offset, sizeof(code_offset)); } +static u8 header_func_get_num_params(amal_program *self, u16 func_index) { + u8 result; + BytecodeHeaderFunction *header_func = ((BytecodeHeaderFunction*)self->funcs_start) + func_index; + assert(sizeof(header_func->num_params) == sizeof(result)); + am_memcpy(&result, &header_func->num_params, sizeof(result)); + return result; +} + static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_executor *executor) { u32 instructions_size; u32 read_start; @@ -496,7 +504,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u16 intermediate_index; Number number; - am_memcpy(&intermediate_index, &self->data.data[self->read_index + sizeof(i8)], sizeof(intermediate_index)); + am_memcpy(&intermediate_index, &self->data.data[self->read_index + sizeof(AmalReg)], sizeof(intermediate_index)); return_if_error(amal_program_get_intermediate_by_index(self, intermediate_index, &number)); return_if_error(amal_exec_movi(executor, self->data.data[self->read_index], number.value.integer)); @@ -507,7 +515,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u16 data_index; BufferView data_ptr; - am_memcpy(&data_index, &self->data.data[self->read_index + sizeof(i8)], sizeof(data_index)); + am_memcpy(&data_index, &self->data.data[self->read_index + sizeof(AmalReg)], sizeof(data_index)); return_if_error(amal_program_get_data_by_index(self, data_index, &data_ptr)); return_if_error(amal_exec_movd(executor, self->data.data[self->read_index], data_ptr)); @@ -586,7 +594,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u8 import_index; u16 func_index; BytecodeHeaderFunction func_def; - i8 dst_reg; + AmalReg dst_reg; am_memcpy(&import_index, self->data.data + self->read_index, sizeof(import_index)); am_memcpy(&func_index, self->data.data + self->read_index + sizeof(import_index), sizeof(func_index)); @@ -632,7 +640,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ case AMAL_OP_CALLE: { u8 import_index; u16 extern_func_index; - i8 dst_reg; + AmalReg dst_reg; am_memcpy(&import_index, self->data.data + self->read_index, sizeof(import_index)); am_memcpy(&extern_func_index, self->data.data + self->read_index + sizeof(import_index), sizeof(extern_func_index)); @@ -653,8 +661,13 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ self->read_index += 3; break; } + case AMAL_OP_BIT_AND: { + assert(bool_false && "TODO: Implement!"); + self->read_index += 3; + break; + } case AMAL_OP_JZ: { - i8 reg; + AmalReg reg; u16 target_label; reg = self->data.data[self->read_index]; am_memcpy(&target_label, self->data.data + self->read_index + sizeof(reg), sizeof(target_label)); @@ -670,19 +683,21 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ break; } case AMAL_OP_RET: { - const i8 reg = self->data.data[self->read_index]; + const AmalReg reg = self->data.data[self->read_index]; return_if_error(amal_exec_ret(executor, reg)); self->read_index += 1; break; } case AMAL_OP_FUNC_START: { u8 func_flags; + u8 func_num_params; u16 func_num_local_var_regs; assert(!inside_func); inside_func = bool_true; assert(func_counter < self->num_functions); + func_num_params = header_func_get_num_params(self, func_counter); header_func_set_offset(self, func_counter, amal_exec_get_code_offset(executor)); return_if_error(resolve_deferred_func_calls(self, executor, func_counter)); ++func_counter; @@ -691,7 +706,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ am_memcpy(&func_num_local_var_regs, self->data.data + self->read_index + sizeof(func_flags), sizeof(func_num_local_var_regs)); if(func_flags & FUNC_FLAG_EXPORTED) return_if_error(amal_program_set_exported_function_instruction_offset_advance(self, amal_exec_get_code_offset(executor))); - return_if_error(amal_exec_func_start(executor, func_num_local_var_regs)); + return_if_error(amal_exec_func_start(executor, func_num_params, func_num_local_var_regs)); self->read_index += 3; break; } diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index 9955d9d..d875ea4 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -81,7 +81,7 @@ int ssa_init(Ssa *self, Parser *parser) { static CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { assert(result); /* Overflow */ - if((u16)self->reg_counter + self->param_counter + 1 > INT16_MAX) { + if((u16)self->reg_counter + 1 > INT16_MAX) { amal_log_error("Ssa too many registers!"); return -1; } @@ -90,6 +90,18 @@ static CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { return 0; } +static CHECK_RESULT int ssa_get_unique_param_reg(Ssa *self, SsaRegister *result) { + assert(result); + /* Overflow */ + if((u16)self->param_counter + 1 > INT16_MAX) { + amal_log_error("Ssa too many param registers!"); + return -1; + } + assert(self->param_counter <= INT8_MAX && "TODO: Implement usage of reg higher than 128"); + *result = self->param_counter++ | REG_FLAG_PARAM; + return 0; +} + SsaNumber ssa_get_intermediate(Ssa *self, SsaIntermediateIndex index) { SsaNumber result; assert(index < buffer_get_size(&self->intermediates, SsaNumber)); @@ -239,6 +251,7 @@ static const char* binop_type_to_string(SsaInstruction binop_type) { case SSA_MUL: return "*"; case SSA_DIV: return "/"; case SSA_EQUALS: return "=="; + case SSA_AND: return "&&"; default: return ""; } } @@ -274,7 +287,7 @@ static CHECK_RESULT int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegis } static CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstruction binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) { - assert(binop_type >= SSA_ADD && binop_type <= SSA_EQUALS); + assert(binop_type >= SSA_ADD && binop_type <= SSA_AND); return ssa_add_ins_form2(self, binop_type, lhs, rhs, result); } @@ -577,14 +590,7 @@ static CHECK_RESULT SsaRegister function_parameter_generate_ssa(FunctionParamete if(self->resolve_data.status == AST_SSA_RESOLVED) return self->resolve_data.ssa_reg; - throw_if_error(ssa_get_unique_reg(context->ssa, ®)); - /* Parameters start at -1 and decrement */ - if((u16)reg - 1 >= (u16)reg) { - amal_log_error("Ssa too many parameters!"); - throw(-1); - } - reg = -1 - reg; - assert(reg >= INT8_MIN && "TODO: Implement more than 128 params"); + throw_if_error(ssa_get_unique_param_reg(context->ssa, ®)); self->resolve_data.status = AST_SSA_RESOLVED; self->resolve_data.ssa_reg = reg; return reg; @@ -614,6 +620,7 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom usize func_metadata_index; u8 func_flags = 0; context->ssa->reg_counter = 0; + context->ssa->param_counter = 0; context->ssa->label_counter = 0; /* @@ -621,8 +628,6 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom This way we can know if a register access is for a parameter or not by checking the number */ function_signature_generate_params_ssa(self->signature, context); - context->ssa->param_counter = context->ssa->reg_counter; - context->ssa->reg_counter = 0; amal_log_debug("SSA funcdecl %p", self); /* Anonymous closure doesn't have lhs_expr, and neither can it have any flags (extern, export etc) */ @@ -754,6 +759,8 @@ static SsaInstruction binop_type_to_ssa_type(BinopType binop_type, amal_default_ return 0; case BINOP_EQUALS: return SSA_EQUALS; + case BINOP_AND: + return SSA_AND; } return 0; } diff --git a/src/tokenizer.c b/src/tokenizer.c index d753b20..da6ad53 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -339,6 +339,14 @@ static CHECK_RESULT int __tokenizer_next(Tokenizer *self, Token *token) { } else { *token = TOK_EQUALS; } + } else if(c == '&') { + ++self->index; + if(self->index < (int)self->code.size && tokenizer_get_char(self) == '&') { + ++self->index; + SET_BINOP(BINOP_AND); + } else { + *token = TOK_AMPERSAND; + } } else if(c == '(') { ++self->index; *token = TOK_OPEN_PAREN; @@ -517,6 +525,9 @@ static BufferView tokenizer_expected_token_as_string(Token token) { case TOK_QUESTION_MARK: str = "?"; break; + case TOK_AMPERSAND: + str = "&"; + break; case TOK_C_VARARGS: str = "..."; break; -- cgit v1.2.3