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,
|
||||
logical_or,
|
||||
logical_xor,
|
||||
left_shift,
|
||||
right_shift,
|
||||
equals,
|
||||
not_equals,
|
||||
less,
|
||||
|
|
@ -107,6 +109,12 @@ namespace pslang::ast
|
|||
case binary_operation_type::logical_xor:
|
||||
out << "xor";
|
||||
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:
|
||||
out << "equals";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -442,6 +442,21 @@ namespace pslang::ast
|
|||
return;
|
||||
}
|
||||
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:
|
||||
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)});
|
||||
}
|
||||
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:
|
||||
return primitive_value(primitive_value_base<bool>{arg1.value == arg2.value});
|
||||
case ast::binary_operation_type::not_equals:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ namespace pslang::ir
|
|||
case ast::binary_operation_type::logical_xor:
|
||||
out << "xor";
|
||||
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:
|
||||
out << "eq";
|
||||
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
|
||||
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
|
||||
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:
|
||||
builder.xor_reg(0, 1, 0);
|
||||
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:
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_circumflex(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_not_equals(ctx.location); }
|
||||
"<" { return bp::make_less(ctx.location); }
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ template <typename T>
|
|||
%token double_vertical_bar "||"
|
||||
%token circumflex "^"
|
||||
%token exclamation "!"
|
||||
%token left_shift "<<"
|
||||
%token right_shift ">>"
|
||||
%token equals "=="
|
||||
%token not_equals "!="
|
||||
%token less "<"
|
||||
|
|
@ -156,6 +158,7 @@ template <typename T>
|
|||
%left ampersand double_ampersand vertical_bar double_vertical_bar circumflex
|
||||
%left equals not_equals less greater less_equals greater_equals
|
||||
%nonassoc as
|
||||
%nonassoc left_shift right_shift
|
||||
%left plus minus
|
||||
%precedence UMINUS
|
||||
%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 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 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), @$ }; }
|
||||
| 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), @$ }; }
|
||||
|
|
|
|||
|
|
@ -31,3 +31,8 @@ General backlog:
|
|||
* Replace std::runtime_error with appropriate custom exception types
|
||||
* Replace std::ostringstream with std::format (need support for std::format in type/ast printing)
|
||||
* 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