aboutsummaryrefslogtreecommitdiffstats
path: root/moth/qv4isel_moth_p.h
blob: dece41323f1baaf2fcb82485ea6d957ef2b3fa50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef QV4ISEL_MOTH_P_H
#define QV4ISEL_MOTH_P_H

#include "qv4isel_p.h"
#include "qv4ir_p.h"
#include "qmljs_objects.h"
#include "qv4instr_moth_p.h"

namespace QQmlJS {
namespace Moth {

class InstructionSelection : public IR::StmtVisitor, public EvalInstructionSelection
{
public:
    InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
    ~InstructionSelection();

    virtual void run(VM::Function *vmFunction, IR::Function *function);

protected:
    virtual void visitExp(IR::Exp *);
    virtual void visitEnter(IR::Enter *);
    virtual void visitLeave(IR::Leave *);
    virtual void visitMove(IR::Move *);
    virtual void visitJump(IR::Jump *);
    virtual void visitCJump(IR::CJump *);
    virtual void visitRet(IR::Ret *);

private:
    struct Instruction {
#define MOTH_INSTR_DATA_TYPEDEF(I, FMT) typedef InstrData<Instr::I> I;
    FOR_EACH_MOTH_INSTR(MOTH_INSTR_DATA_TYPEDEF)
#undef MOTH_INSTR_DATA_TYPEDEF
    private:
        Instruction();
    };

    void simpleMove(IR::Move *);
    void callActivationProperty(IR::Call *c, int targetTempIndex);
    void callValue(IR::Call *c, int targetTempIndex);
    void callProperty(IR::Call *c, int targetTempIndex);
    void construct(IR::New *ctor, int targetTempIndex);
    void prepareCallArgs(IR::ExprList *, quint32 &, quint32 &);

    int outgoingArgumentTempStart() const { return _function->tempCount; }
    int scratchTempIndex() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
    int frameSize() const { return scratchTempIndex() + 1 - _function->locals.size(); }

    template <int Instr>
    inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
    ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);

    IR::Function *_function;
    IR::BasicBlock *_block;

    QHash<IR::BasicBlock *, QVector<ptrdiff_t> > _patches;
    QHash<IR::BasicBlock *, ptrdiff_t> _addrs;

    uchar *_code;
    uchar *_ccode;
};

class ISelFactory: public EvalISelFactory
{
public:
    virtual ~ISelFactory() {}
    virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine, IR::Module *module)
    { return new InstructionSelection(engine, module); }
};

template<int InstrT>
ptrdiff_t InstructionSelection::addInstruction(const InstrData<InstrT> &data)
{
    Instr genericInstr;
    InstrMeta<InstrT>::setData(genericInstr, data);
    return addInstructionHelper(static_cast<Instr::Type>(InstrT), genericInstr);
}

} // namespace Moth
} // namespace QQmlJS

#endif // QV4ISEL_MOTH_P_H