Add left/right shift operators
This commit is contained in:
parent
138bddf187
commit
38fd23b50e
10 changed files with 78 additions and 0 deletions
|
|
@ -24,6 +24,8 @@ namespace pslang::ast
|
||||||
binary_or,
|
binary_or,
|
||||||
logical_or,
|
logical_or,
|
||||||
logical_xor,
|
logical_xor,
|
||||||
|
left_shift,
|
||||||
|
right_shift,
|
||||||
equals,
|
equals,
|
||||||
not_equals,
|
not_equals,
|
||||||
less,
|
less,
|
||||||
|
|
@ -107,6 +109,12 @@ namespace pslang::ast
|
||||||
case binary_operation_type::logical_xor:
|
case binary_operation_type::logical_xor:
|
||||||
out << "xor";
|
out << "xor";
|
||||||
break;
|
break;
|
||||||
|
case binary_operation_type::left_shift:
|
||||||
|
out << "left shift";
|
||||||
|
break;
|
||||||
|
case binary_operation_type::right_shift:
|
||||||
|
out << "right shift";
|
||||||
|
break;
|
||||||
case binary_operation_type::equals:
|
case binary_operation_type::equals:
|
||||||
out << "equals";
|
out << "equals";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,21 @@ namespace pslang::ast
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case binary_operation_type::left_shift:
|
||||||
|
case binary_operation_type::right_shift:
|
||||||
|
if (both_integers)
|
||||||
|
{
|
||||||
|
if (!types::is_unsigned_integer_type(*arg2_type))
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Shift amount must be an unsigned integer type, but got ";
|
||||||
|
ast::print(os, *arg2_type);
|
||||||
|
throw type_error(os.str(), ast::get_location(*node.arg2));
|
||||||
|
}
|
||||||
|
node.inferred_type = arg1_type;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case binary_operation_type::equals:
|
case binary_operation_type::equals:
|
||||||
if (equal || both_integers)
|
if (equal || both_integers)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,9 @@ namespace pslang::interpreter
|
||||||
return primitive_value(primitive_value_base<T>{static_cast<T>(arg1.value ^ arg2.value)});
|
return primitive_value(primitive_value_base<T>{static_cast<T>(arg1.value ^ arg2.value)});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ast::binary_operation_type::left_shift:
|
||||||
|
case ast::binary_operation_type::right_shift:
|
||||||
|
throw std::runtime_error("Not implemented");
|
||||||
case ast::binary_operation_type::equals:
|
case ast::binary_operation_type::equals:
|
||||||
return primitive_value(primitive_value_base<bool>{arg1.value == arg2.value});
|
return primitive_value(primitive_value_base<bool>{arg1.value == arg2.value});
|
||||||
case ast::binary_operation_type::not_equals:
|
case ast::binary_operation_type::not_equals:
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,12 @@ namespace pslang::ir
|
||||||
case ast::binary_operation_type::logical_xor:
|
case ast::binary_operation_type::logical_xor:
|
||||||
out << "xor";
|
out << "xor";
|
||||||
break;
|
break;
|
||||||
|
case ast::binary_operation_type::left_shift:
|
||||||
|
out << "shl";
|
||||||
|
break;
|
||||||
|
case ast::binary_operation_type::right_shift:
|
||||||
|
out << "shr";
|
||||||
|
break;
|
||||||
case ast::binary_operation_type::equals:
|
case ast::binary_operation_type::equals:
|
||||||
out << "eq";
|
out << "eq";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,15 @@ namespace pslang::jit::aarch64
|
||||||
// Compute the value of unsigned division (@reg_src1 / @reg_src2) and store the result in @reg_dst
|
// Compute the value of unsigned division (@reg_src1 / @reg_src2) and store the result in @reg_dst
|
||||||
void udiv_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst);
|
void udiv_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst);
|
||||||
|
|
||||||
|
// Compute the value of logical left bit shift (@reg_src1 << @reg_src2) and store the result in @reg_dst
|
||||||
|
void lsl_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst);
|
||||||
|
|
||||||
|
// Compute the value of logical (zero-extended) right bit shift (@reg_src1 >> @reg_src2) and store the result in @reg_dst
|
||||||
|
void lsr_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst);
|
||||||
|
|
||||||
|
// Compute the value of arithmetic (sign-extended) right bit shift (@reg_src1 >> @reg_src2) and store the result in @reg_dst
|
||||||
|
void asr_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst);
|
||||||
|
|
||||||
// Compare the values of @reg_src1 and @reg_src2 and set the flags
|
// Compare the values of @reg_src1 and @reg_src2 and set the flags
|
||||||
void cmp_reg(std::uint8_t reg_src1, std::uint8_t reg_src2);
|
void cmp_reg(std::uint8_t reg_src1, std::uint8_t reg_src2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,16 @@ namespace pslang::jit::aarch64
|
||||||
case ast::binary_operation_type::logical_xor:
|
case ast::binary_operation_type::logical_xor:
|
||||||
builder.xor_reg(0, 1, 0);
|
builder.xor_reg(0, 1, 0);
|
||||||
break;
|
break;
|
||||||
|
case ast::binary_operation_type::left_shift:
|
||||||
|
builder.lsl_reg(0, 1, 0);
|
||||||
|
break;
|
||||||
|
case ast::binary_operation_type::right_shift:
|
||||||
|
extend(0, arg1_type);
|
||||||
|
if (types::is_unsigned_integer_type(*arg1_type))
|
||||||
|
builder.lsr_reg(0, 1, 0);
|
||||||
|
else
|
||||||
|
builder.asr_reg(0, 1, 0);
|
||||||
|
break;
|
||||||
case ast::binary_operation_type::equals:
|
case ast::binary_operation_type::equals:
|
||||||
if (is_fp)
|
if (is_fp)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,21 @@ namespace pslang::jit::aarch64
|
||||||
do_push(0x9ac00800u | (reg_dst & REG_MASK) | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
do_push(0x9ac00800u | (reg_dst & REG_MASK) | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void instruction_builder::lsl_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst)
|
||||||
|
{
|
||||||
|
do_push(0x9ac02000u | (reg_dst & REG_MASK) | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void instruction_builder::lsr_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst)
|
||||||
|
{
|
||||||
|
do_push(0x9ac02400u | (reg_dst & REG_MASK) | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void instruction_builder::asr_reg(std::uint8_t reg_src1, std::uint8_t reg_src2, std::uint8_t reg_dst)
|
||||||
|
{
|
||||||
|
do_push(0x9ac02800u | (reg_dst & REG_MASK) | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
||||||
|
}
|
||||||
|
|
||||||
void instruction_builder::cmp_reg(std::uint8_t reg_src1, std::uint8_t reg_src2)
|
void instruction_builder::cmp_reg(std::uint8_t reg_src1, std::uint8_t reg_src2)
|
||||||
{
|
{
|
||||||
do_push(0xeb20601fu | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
do_push(0xeb20601fu | ((reg_src1 & REG_MASK) << 5) | ((reg_src2 & REG_MASK) << 16));
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ f64 { return bp::make_f64(ctx.location); }
|
||||||
"|" { return bp::make_vertical_bar(ctx.location); }
|
"|" { return bp::make_vertical_bar(ctx.location); }
|
||||||
"^" { return bp::make_circumflex(ctx.location); }
|
"^" { return bp::make_circumflex(ctx.location); }
|
||||||
"!" { return bp::make_exclamation(ctx.location); }
|
"!" { return bp::make_exclamation(ctx.location); }
|
||||||
|
"<<" { return bp::make_left_shift(ctx.location); }
|
||||||
|
">>" { return bp::make_right_shift(ctx.location); }
|
||||||
"==" { return bp::make_equals(ctx.location); }
|
"==" { return bp::make_equals(ctx.location); }
|
||||||
"!=" { return bp::make_not_equals(ctx.location); }
|
"!=" { return bp::make_not_equals(ctx.location); }
|
||||||
"<" { return bp::make_less(ctx.location); }
|
"<" { return bp::make_less(ctx.location); }
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ template <typename T>
|
||||||
%token double_vertical_bar "||"
|
%token double_vertical_bar "||"
|
||||||
%token circumflex "^"
|
%token circumflex "^"
|
||||||
%token exclamation "!"
|
%token exclamation "!"
|
||||||
|
%token left_shift "<<"
|
||||||
|
%token right_shift ">>"
|
||||||
%token equals "=="
|
%token equals "=="
|
||||||
%token not_equals "!="
|
%token not_equals "!="
|
||||||
%token less "<"
|
%token less "<"
|
||||||
|
|
@ -156,6 +158,7 @@ template <typename T>
|
||||||
%left ampersand double_ampersand vertical_bar double_vertical_bar circumflex
|
%left ampersand double_ampersand vertical_bar double_vertical_bar circumflex
|
||||||
%left equals not_equals less greater less_equals greater_equals
|
%left equals not_equals less greater less_equals greater_equals
|
||||||
%nonassoc as
|
%nonassoc as
|
||||||
|
%nonassoc left_shift right_shift
|
||||||
%left plus minus
|
%left plus minus
|
||||||
%precedence UMINUS
|
%precedence UMINUS
|
||||||
%left asterisk slash percent
|
%left asterisk slash percent
|
||||||
|
|
@ -311,6 +314,8 @@ expression
|
||||||
| expression less_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
| expression less_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
| expression greater_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
| expression greater_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
| expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<ast::type>($3), @$ }; }
|
| expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<ast::type>($3), @$ }; }
|
||||||
|
| expression left_shift expression { $$ = ast::binary_operation{ast::binary_operation_type::left_shift, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
|
| expression right_shift expression { $$ = ast::binary_operation{ast::binary_operation_type::right_shift, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
| minus expression %prec UMINUS { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2), @$ }; }
|
| minus expression %prec UMINUS { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2), @$ }; }
|
||||||
| expression plus expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
| expression plus expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
| expression minus expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
| expression minus expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,8 @@ General backlog:
|
||||||
* Replace std::runtime_error with appropriate custom exception types
|
* Replace std::runtime_error with appropriate custom exception types
|
||||||
* Replace std::ostringstream with std::format (need support for std::format in type/ast printing)
|
* Replace std::ostringstream with std::format (need support for std::format in type/ast printing)
|
||||||
* TEST COVERAGE!!!
|
* TEST COVERAGE!!!
|
||||||
|
|
||||||
|
Platform-dependent operations backlog:
|
||||||
|
* Division by zero (returns 0 on arm64, triggers an interrupt on x86) - declare as UB?
|
||||||
|
* Floating-point <-> integer conversion (is rounding the same on all platforms?)
|
||||||
|
* Shifts (bit count is taken modulo integer size on arm64, x86 - ???)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue