diff --git a/src/libcoreint/opcode-structures.h b/src/libcoreint/opcode-structures.h index 7f37165ff..b6f48c129 100644 --- a/src/libcoreint/opcode-structures.h +++ b/src/libcoreint/opcode-structures.h @@ -228,6 +228,58 @@ OP_CODE_DECL (logical_or, T_IDX_IDX_IDX, var_left, var_right) +// Equality operations. + +/** dst = L == R. */ +OP_CODE_DECL (equal_value, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L != R. */ +OP_CODE_DECL (not_equal_value, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L === R. */ +OP_CODE_DECL (equal_value_type, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L !== R. */ +OP_CODE_DECL (not_equal_value_type, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +// Relational operations. + +/** dst = L < R. */ +OP_CODE_DECL (less_than, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L > R. */ +OP_CODE_DECL (greater_than, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L <= R. */ +OP_CODE_DECL (less_or_equal_than, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + +/** dst = L >= R. */ +OP_CODE_DECL (greater_or_equal_than, T_IDX_IDX_IDX, + dst, + var_left, + var_right) + // Assignment operators. // Assign value to LEFT operand based on value of RIGHT operand. @@ -236,61 +288,6 @@ OP_CODE_DECL (assignment, T_IDX_IDX, value_left, value_right) -/** L *= R */ -OP_CODE_DECL (assignment_multiplication, T_IDX_IDX, - value_left, - value_right) - -/** L /= R */ -OP_CODE_DECL (assignment_devision, T_IDX_IDX, - value_left, - value_right) - -/** L %= R */ -OP_CODE_DECL (assignment_remainder, T_IDX_IDX, - value_left, - value_right) - -/** L += R */ -OP_CODE_DECL (assignment_addition, T_IDX_IDX, - value_left, - value_right) - -/** L -= R */ -OP_CODE_DECL (assignment_substruction, T_IDX_IDX, - value_left, - value_right) - -/** L <<= R */ -OP_CODE_DECL (assignment_shift_left, T_IDX_IDX, - value_left, - value_right) - -/** L >>= R */ -OP_CODE_DECL (assignment_shift_right, T_IDX_IDX, - value_left, - value_right) - -/** L >>>= R */ -OP_CODE_DECL (assignment_shift_uright, T_IDX_IDX, - value_left, - value_right) - -/** L &= R */ -OP_CODE_DECL (assignment_b_and, T_IDX_IDX, - value_left, - value_right) - -/** L ^= R */ -OP_CODE_DECL (assignment_b_xor, T_IDX_IDX, - value_left, - value_right) - -/** L |= R */ -OP_CODE_DECL (assignment_b_or, T_IDX_IDX, - value_left, - value_right) - // Functions calls, declarations and argument handling /** name(arg1); */ @@ -362,6 +359,8 @@ OP_CODE_DECL (retval, T_IDX, ret_value) OP_CODE_DECL_VOID (ret) +OP_CODE_DECL_VOID (nop) + // LOOPS // Lately, all loops should be translated into different JMPs in an optimizer. diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 87595d105..56f485722 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -41,6 +41,15 @@ void opfunc_varg_3 (OPCODE opdata __unused, struct __int_data *int_data __unused void opfunc_varg_3_end (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_retval (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_ret (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_nop (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_not_equal_value (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_equal_value_type (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_not_equal_value_type (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_less_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_greater_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_less_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } +void opfunc_greater_or_equal_than (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_assignment(OPCODE opdata __unused, @@ -49,17 +58,6 @@ opfunc_assignment(OPCODE opdata __unused, JERRY_UNREACHABLE (); } -void opfunc_assignment_multiplication (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_devision (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_remainder (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_addition (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_substruction (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_shift_left (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_shift_right (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_shift_uright (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_b_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_b_xor (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } -void opfunc_assignment_b_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_logical_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_logical_or (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } void opfunc_b_and (OPCODE opdata __unused, struct __int_data *int_data __unused) { JERRY_UNREACHABLE (); } @@ -150,18 +148,15 @@ GETOP_IMPL_3 (b_or, dst, var_left, var_right) GETOP_IMPL_3 (b_xor, dst, var_left, var_right) GETOP_IMPL_3 (logical_and, dst, var_left, var_right) GETOP_IMPL_3 (logical_or, dst, var_left, var_right) +GETOP_IMPL_3 (equal_value, dst, var_left, var_right) +GETOP_IMPL_3 (not_equal_value, dst, var_left, var_right) +GETOP_IMPL_3 (equal_value_type, dst, var_left, var_right) +GETOP_IMPL_3 (not_equal_value_type, dst, var_left, var_right) +GETOP_IMPL_3 (less_than, dst, var_left, var_right) +GETOP_IMPL_3 (greater_than, dst, var_left, var_right) +GETOP_IMPL_3 (less_or_equal_than, dst, var_left, var_right) +GETOP_IMPL_3 (greater_or_equal_than, dst, var_left, var_right) GETOP_IMPL_2 (assignment, value_left, value_right) -GETOP_IMPL_2 (assignment_multiplication, value_left, value_right) -GETOP_IMPL_2 (assignment_devision, value_left, value_right) -GETOP_IMPL_2 (assignment_remainder, value_left, value_right) -GETOP_IMPL_2 (assignment_addition, value_left, value_right) -GETOP_IMPL_2 (assignment_substruction, value_left, value_right) -GETOP_IMPL_2 (assignment_shift_left, value_left, value_right) -GETOP_IMPL_2 (assignment_shift_right, value_left, value_right) -GETOP_IMPL_2 (assignment_shift_uright, value_left, value_right) -GETOP_IMPL_2 (assignment_b_and, value_left, value_right) -GETOP_IMPL_2 (assignment_b_xor, value_left, value_right) -GETOP_IMPL_2 (assignment_b_or, value_left, value_right) GETOP_IMPL_2 (call_1, name_lit_idx, arg1_lit_idx) GETOP_IMPL_3 (call_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx) GETOP_IMPL_3 (call_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx) @@ -176,6 +171,7 @@ GETOP_IMPL_3 (varg_3, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx) GETOP_IMPL_3 (varg_3_end, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx) GETOP_IMPL_1 (retval, ret_value) GETOP_IMPL_0 (ret) +GETOP_IMPL_0 (nop) GETOP_IMPL_1 (loop_inf, loop_root) GETOP_IMPL_3 (loop_init_num, start, stop, step) GETOP_IMPL_2 (loop_precond_begin_num, condition, after_loop_op) diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 4af8a7e41..86766787d 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -54,22 +54,11 @@ typedef void (*opfunc)(OPCODE, struct __int_data *); op(varg_2_end) \ op(varg_3) \ op(varg_3_end) \ - op(retval)\ + op(retval) \ op(ret) #define OP_ASSIGNMENTS(op) \ - op(assignment) \ - op(assignment_multiplication) \ - op(assignment_devision) \ - op(assignment_remainder) \ - op(assignment_addition) \ - op(assignment_substruction) \ - op(assignment_shift_left) \ - op(assignment_shift_right) \ - op(assignment_shift_uright) \ - op(assignment_b_and) \ - op(assignment_b_xor) \ - op(assignment_b_or) + op(assignment) #define OP_B_SHIFTS(op) \ op(b_shift_left) \ @@ -85,6 +74,18 @@ typedef void (*opfunc)(OPCODE, struct __int_data *); op(logical_and) \ op(logical_or) +#define OP_EQUALITY(op) \ + op(equal_value) \ + op(not_equal_value) \ + op(equal_value_type) \ + op(not_equal_value_type) + +#define OP_RELATIONAL(op) \ + op(less_than) \ + op(greater_than) \ + op(less_or_equal_than) \ + op(greater_or_equal_than) + #define OP_ARITHMETIC(op) \ op(addition) \ op(substraction) \ @@ -95,7 +96,8 @@ typedef void (*opfunc)(OPCODE, struct __int_data *); #define OP_UNCONDITIONAL_JUMPS(op) \ op(jmp) \ op(jmp_up) \ - op(jmp_down) + op(jmp_down) \ + op(nop) #define OP_UNARY_OPS(op) \ op(is_true_jmp) \ @@ -119,6 +121,8 @@ typedef void (*opfunc)(OPCODE, struct __int_data *); OP_B_LOGICAL(op) \ OP_B_BITWISE(op) \ OP_B_SHIFTS(op) \ + OP_EQUALITY(op) \ + OP_RELATIONAL(op) \ OP_ARITHMETIC(op) \ OP_UNCONDITIONAL_JUMPS(op) \ OP_CONDITIONAL_JUMPS(op) diff --git a/src/libjsparser/bytecode-generator.c b/src/libjsparser/bytecode-generator.c index b9ef5293e..08127037b 100644 --- a/src/libjsparser/bytecode-generator.c +++ b/src/libjsparser/bytecode-generator.c @@ -61,10 +61,134 @@ generator_dump_strings (const char **strings, uint8_t num) serializer_dump_data (strings[i], __strlen (strings[i]) + 1); } +static bool +is_expression (statement stmt) +{ + switch (stmt.type) + { + case STMT_IF: + case STMT_ELSE_IF: + case STMT_END_DO_WHILE: + case STMT_WHILE: + case STMT_RETURN: + case STMT_WITH: + case STMT_SWITCH: + case STMT_CASE: + case STMT_THROW: + case STMT_EXPRESSION: + return true; + + default: + return false; + } +} + +static bool +is_assignment (statement stmt) +{ + JERRY_ASSERT (is_expression (stmt)); + return stmt.data.expr.oper != AO_NONE; +} + +static expression_type +get_expression_type (statement stmt) +{ + JERRY_ASSERT (is_expression (stmt)); + return stmt.data.expr.type; +} + +static bool +expression_has_operands (statement stmt) +{ + switch (get_expression_type (stmt)) + { + case ET_OBJECT: + case ET_FUNCTION: + case ET_ARRAY: + case ET_SUBEXPRESSION: + case ET_NONE: + return false; + + default: + return true; + } +} + +static operand +first_operand (statement stmt) +{ + JERRY_ASSERT (expression_has_operands (stmt)); + return stmt.data.expr.data.ops.op1; +} + +static literal +first_operand_as_literal (statement stmt) +{ + operand oper = first_operand (stmt); + + JERRY_ASSERT (oper.is_literal); + + return oper.data.lit; +} + +static uint8_t +first_operand_id (statement stmt) +{ + JERRY_ASSERT (expression_has_operands (stmt)); + if (first_operand (stmt).is_literal) + JERRY_UNIMPLEMENTED (); + return first_operand (stmt).data.name; +} + +static operand +second_operand (statement stmt) +{ + JERRY_ASSERT (expression_has_operands (stmt)); + return stmt.data.expr.data.ops.op2; +} + +static uint8_t +second_operand_id (statement stmt) +{ + JERRY_ASSERT (expression_has_operands (stmt)); + if (second_operand (stmt).is_literal) + JERRY_UNIMPLEMENTED (); + return second_operand (stmt).data.name; +} + +static uint8_t +lhs (statement stmt) +{ + JERRY_ASSERT (is_assignment (stmt)); + + return stmt.data.expr.var; +} + +static void +dump_opcode (OPCODE *opcode) +{ + serializer_dump_data (opcode, sizeof (OPCODE)); + opcode_index++; +} + +static assignment_operator +get_assignment_operator (statement stmt) +{ + JERRY_ASSERT (is_assignment (stmt)); + + return stmt.data.expr.oper; +} + +static OPCODE +generate_triple_address (OPCODE (*getop)(T_IDX, T_IDX, T_IDX), statement stmt) +{ + return (*getop) (lhs (stmt), first_operand_id (stmt), second_operand_id (stmt)); +} + void generator_dump_statement (statement stmt) { - OPCODE opcode; + OPCODE opcode = getop_nop (); JERRY_STATIC_ASSERT (sizeof (OPCODE) <= sizeof (uint32_t)); switch (stmt.type) @@ -73,21 +197,205 @@ generator_dump_statement (statement stmt) break; case STMT_WHILE: - TODO (Supports only infinite loops); - if (stmt.data.expr.oper == AO_NONE && stmt.data.expr.type == ET_NONE) + if (!is_assignment (stmt)) { - operand op = stmt.data.expr.data.ops.op1; - if (op.is_literal && op.data.lit.type == LIT_BOOL && op.data.lit.data.is_true) - { - opcode = getop_loop_inf ((uint8_t) (opcode_index + 1)); - push_opcode ((uint8_t) (opcode_index + 1)); - } + literal lit; + + switch (get_expression_type (stmt)) + { + case ET_LITERAL: + lit = first_operand_as_literal (stmt); + if (lit.type == LIT_BOOL && lit.data.is_true) + { + opcode = getop_loop_inf ((uint8_t) (opcode_index + 1)); + push_opcode ((uint8_t) (opcode_index + 1)); + dump_opcode (&opcode); + return; + } + else + JERRY_UNIMPLEMENTED (); + break; + + default: + JERRY_UNIMPLEMENTED (); + } } + else + JERRY_UNIMPLEMENTED (); break; case STMT_EXPRESSION: - TODO (Supports only calls); - if (stmt.data.expr.oper == AO_NONE) + if (is_assignment (stmt)) + { + switch (get_expression_type (stmt)) + { + case ET_NONE: + JERRY_UNREACHABLE (); + break; + + case ET_LOGICAL_OR: + opcode = generate_triple_address (getop_logical_or, stmt); + dump_opcode (&opcode); + break; + + case ET_LOGICAL_AND: + opcode = generate_triple_address (getop_logical_and, stmt); + dump_opcode (&opcode); + break; + + case ET_BITWISE_OR: + opcode = generate_triple_address (getop_b_or, stmt); + dump_opcode (&opcode); + break; + + case ET_BITWISE_XOR: + opcode = generate_triple_address (getop_b_xor, stmt); + dump_opcode (&opcode); + break; + + case ET_BITWISE_AND: + opcode = generate_triple_address (getop_b_and, stmt); + dump_opcode (&opcode); + break; + + case ET_DOUBLE_EQ: + opcode = generate_triple_address (getop_equal_value, stmt); + dump_opcode (&opcode); + break; + + case ET_NOT_EQ: + opcode = generate_triple_address (getop_not_equal_value, stmt); + dump_opcode (&opcode); + break; + + case ET_TRIPLE_EQ: + opcode = generate_triple_address (getop_equal_value_type, stmt); + dump_opcode (&opcode); + break; + + case ET_NOT_DOUBLE_EQ: + opcode = generate_triple_address (getop_not_equal_value_type, stmt); + dump_opcode (&opcode); + break; + + case ET_LESS: + opcode = generate_triple_address (getop_less_than, stmt); + dump_opcode (&opcode); + break; + + case ET_GREATER: + opcode = generate_triple_address (getop_greater_than, stmt); + dump_opcode (&opcode); + break; + + case ET_LESS_EQ: + opcode = generate_triple_address (getop_less_or_equal_than, stmt); + dump_opcode (&opcode); + break; + + case ET_GREATER_EQ: + opcode = generate_triple_address (getop_greater_or_equal_than, stmt); + dump_opcode (&opcode); + break; + + case ET_INSTANCEOF: + case ET_IN: + JERRY_UNIMPLEMENTED (); + break; + + case ET_LSHIFT: + opcode = generate_triple_address (getop_b_shift_left, stmt); + dump_opcode (&opcode); + break; + + case ET_RSHIFT: + opcode = generate_triple_address (getop_b_shift_right, stmt); + dump_opcode (&opcode); + break; + + case ET_RSHIFT_EX: + opcode = generate_triple_address (getop_b_shift_uright, stmt); + dump_opcode (&opcode); + break; + + case ET_PLUS: + opcode = generate_triple_address (getop_addition, stmt); + dump_opcode (&opcode); + break; + + case ET_MINUS: + opcode = generate_triple_address (getop_substraction, stmt); + dump_opcode (&opcode); + break; + + case ET_MULT: + opcode = generate_triple_address (getop_multiplication, stmt); + dump_opcode (&opcode); + break; + + case ET_DIV: + opcode = generate_triple_address (getop_division, stmt); + dump_opcode (&opcode); + break; + + case ET_MOD: + opcode = generate_triple_address (getop_remainder, stmt); + dump_opcode (&opcode); + break; + + case ET_UNARY_DELETE: + case ET_UNARY_VOID: + case ET_UNARY_TYPEOF: + JERRY_UNIMPLEMENTED (); + break; + + case ET_UNARY_INCREMENT: + // opcode = getop_addition (first_operand_id (stmt), first_operand_id (stmt), INTEGER_ONE); + case ET_UNARY_DECREMENT: + case ET_UNARY_PLUS: + case ET_UNARY_MINUS: + case ET_UNARY_COMPL: + case ET_UNARY_NOT: + case ET_POSTFIX_INCREMENT: + case ET_POSTFIX_DECREMENT: + case ET_CALL: + case ET_NEW: + case ET_INDEX: + case ET_PROP_REF: + case ET_OBJECT: + case ET_FUNCTION: + case ET_ARRAY: + case ET_SUBEXPRESSION: + JERRY_UNIMPLEMENTED (); + break; + + case ET_LITERAL: + case ET_IDENTIFIER: + switch (get_assignment_operator (stmt)) + { + case AO_NONE: + JERRY_UNREACHABLE (); + break; + + case AO_EQ: + opcode = getop_assignment (lhs (stmt), first_operand_id (stmt)); + dump_opcode (&opcode); + return; + + default: + JERRY_UNIMPLEMENTED (); + } + JERRY_UNREACHABLE (); + + default: + JERRY_UNREACHABLE (); + } + + if (get_assignment_operator (stmt) != AO_EQ) + JERRY_UNIMPLEMENTED (); + + } + else { call_expression expr = stmt.data.expr.data.call_expr; JERRY_ASSERT (!is_operand_list_empty (expr.args)); @@ -107,7 +415,4 @@ generator_dump_statement (statement stmt) __printf (" generator_dump_statement: %d ", stmt.type); JERRY_UNREACHABLE (); } - - serializer_dump_data (&opcode, sizeof (OPCODE)); - opcode_index++; } \ No newline at end of file diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index d189d7eaa..8c0644d57 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -541,7 +541,10 @@ parse_assigment_expression (void) assignment_expression res; if (tok.type != TOK_NAME) - goto parse_operands; + { + res.oper = AO_NONE; + goto parse_operands; + } current_token_must_be (TOK_NAME); @@ -813,7 +816,10 @@ parse_operator: default: lexer_save_token (tok); res.oper = AO_NONE; - res.type = ET_NONE; + if (res.data.ops.op1.is_literal) + res.type = ET_LITERAL; + else + res.type = ET_IDENTIFIER; res.data.ops.op2 = empty_operand; return res; } diff --git a/src/main.c b/src/main.c index d86a66ae7..1d26ccb48 100644 --- a/src/main.c +++ b/src/main.c @@ -212,7 +212,6 @@ main (int argc, char **argv) generator_dump_strings (strings, strings_num); st = parser_parse_statement (); JERRY_ASSERT (!is_statement_null (st)); - __printf (" ST_TYPE = %d", st.type == STMT_EOF); while (st.type != STMT_EOF) { generator_dump_statement (st);