浏览代码

LibJS: Add bytecode instructions for a bunch of unary operators

~, !, +, -, typeof, and void.
Linus Groh 4 年之前
父节点
当前提交
fa9bad912e

+ 1 - 0
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;

+ 32 - 0
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();

+ 6 - 1
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 {
 

+ 51 - 0
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);

+ 85 - 0
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)