diff options
author | Linus Groh <mail@linusgroh.de> | 2021-06-07 19:53:47 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-07 19:53:47 +0100 |
commit | fa9bad912effbe2cf3334e29a7df4908a3174022 (patch) | |
tree | 12c5cd0364a979d37ea74f79fecf491774755a65 /Userland | |
parent | 54fc7079c636bc7a20270632a88883ed959b4f79 (diff) | |
download | serenity-fa9bad912effbe2cf3334e29a7df4908a3174022.zip |
LibJS: Add bytecode instructions for a bunch of unary operators
~, !, +, -, typeof, and void.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/AST.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Instruction.h | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 51 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 85 |
5 files changed, 175 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index b8e9c4a2c9..45380bc975 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -584,6 +584,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual Optional<Bytecode::Register> generate_bytecode(Bytecode::Generator&) const override; private: UnaryOp m_op; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 6b5c2511c8..0230c526f5 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -93,6 +93,38 @@ Optional<Bytecode::Register> BinaryExpression::generate_bytecode(Bytecode::Gener } } +Optional<Bytecode::Register> UnaryExpression::generate_bytecode(Bytecode::Generator& generator) const +{ + auto lhs_reg = m_lhs->generate_bytecode(generator); + + VERIFY(lhs_reg.has_value()); + + auto dst_reg = generator.allocate_register(); + + switch (m_op) { + case UnaryOp::BitwiseNot: + generator.emit<Bytecode::Op::BitwiseNot>(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Not: + generator.emit<Bytecode::Op::Not>(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Plus: + generator.emit<Bytecode::Op::UnaryPlus>(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Minus: + generator.emit<Bytecode::Op::UnaryMinus>(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Typeof: + generator.emit<Bytecode::Op::Typeof>(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Void: + generator.emit<Bytecode::Op::Load>(dst_reg, js_undefined()); + return dst_reg; + default: + TODO(); + } +} + Optional<Bytecode::Register> NumericLiteral::generate_bytecode(Bytecode::Generator& generator) const { auto dst = generator.allocate_register(); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index ccf58871e0..84471e80e2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -37,7 +37,12 @@ O(Return) \ O(BitwiseAnd) \ O(BitwiseOr) \ - O(BitwiseXor) + O(BitwiseXor) \ + O(BitwiseNot) \ + O(Not) \ + O(UnaryPlus) \ + O(UnaryMinus) \ + O(Typeof) namespace JS::Bytecode { diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 58be18b91e..73703d1027 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -127,6 +127,32 @@ void BitwiseXor::execute(Bytecode::Interpreter& interpreter) const interpreter.reg(m_dst) = bitwise_xor(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); } +void BitwiseNot::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = bitwise_not(interpreter.global_object(), interpreter.reg(m_src)); +} + +void Not::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(!interpreter.reg(m_src).to_boolean()); +} + +void UnaryPlus::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(unary_plus(interpreter.global_object(), interpreter.reg(m_src))); +} + +void UnaryMinus::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(unary_minus(interpreter.global_object(), interpreter.reg(m_src))); +} + +void Typeof::execute(Bytecode::Interpreter& interpreter) const +{ + auto& vm = interpreter.global_object().vm(); + interpreter.reg(m_dst) = Value(js_string(vm, interpreter.reg(m_src).typeof())); +} + void NewString::execute(Bytecode::Interpreter& interpreter) const { interpreter.reg(m_dst) = js_string(interpreter.vm(), m_string); @@ -308,6 +334,31 @@ String BitwiseXor::to_string() const return String::formatted("BitwiseXor dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); } +String BitwiseNot::to_string() const +{ + return String::formatted("BitwiseNot dst:{}, src:{}", m_dst, m_src); +} + +String Not::to_string() const +{ + return String::formatted("Not dst:{}, src:{}", m_dst, m_src); +} + +String UnaryPlus::to_string() const +{ + return String::formatted("UnaryPlus dst:{}, src:{}", m_dst, m_src); +} + +String UnaryMinus::to_string() const +{ + return String::formatted("UnaryMinus dst:{}, src:{}", m_dst, m_src); +} + +String Typeof::to_string() const +{ + return String::formatted("Typeof dst:{}, src:{}", m_dst, m_src); +} + String NewString::to_string() const { return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 070856a4bb..17f96d135e 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -317,6 +317,91 @@ private: Register m_src2; }; +class BitwiseNot final : public Instruction { +public: + BitwiseNot(Register dst, Register src) + : Instruction(Type::BitwiseNot) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class Not final : public Instruction { +public: + Not(Register dst, Register src) + : Instruction(Type::Not) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class UnaryPlus final : public Instruction { +public: + UnaryPlus(Register dst, Register src) + : Instruction(Type::UnaryPlus) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class UnaryMinus final : public Instruction { +public: + UnaryMinus(Register dst, Register src) + : Instruction(Type::UnaryMinus) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class Typeof final : public Instruction { +public: + Typeof(Register dst, Register src) + : Instruction(Type::Typeof) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + class NewString final : public Instruction { public: NewString(Register dst, String string) |