Start dumping assignment expressions to bytecode; revise bytecode instructions

This commit is contained in:
Ilmir Usmanov 2014-07-16 22:23:55 +04:00
parent 438318d788
commit 270ee301b4
6 changed files with 417 additions and 108 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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++;
}

View File

@ -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;
}

View File

@ -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);