summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-06-07 19:53:47 +0100
committerLinus Groh <mail@linusgroh.de>2021-06-07 19:53:47 +0100
commitfa9bad912effbe2cf3334e29a7df4908a3174022 (patch)
tree12c5cd0364a979d37ea74f79fecf491774755a65 /Userland
parent54fc7079c636bc7a20270632a88883ed959b4f79 (diff)
downloadserenity-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.h1
-rw-r--r--Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp32
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Instruction.h7
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.cpp51
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.h85
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)