summaryrefslogtreecommitdiff
path: root/tools/standalone_miri/miri.hpp
blob: f835fedb85e79884b4a815dafe1a10e5b018a04d (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * mrustc Standalone MIRI
 * - by John Hodge (Mutabah)
 *
 * miri.hpp
 * - MIR Interpreter State (HEADER)
 */
#pragma once
#include "module_tree.hpp"
#include "value.hpp"

struct ThreadState
{
    static unsigned s_next_tls_key;
    unsigned call_stack_depth;
    ::std::vector< ::std::pair<uint64_t, RelocationPtr> > tls_values;

    unsigned    panic_count;
    bool    panic_active;
    Value   panic_value;

    ThreadState():
        call_stack_depth(0)
        ,panic_count(0)
        ,panic_active(false)
    {
    }

    struct DecOnDrop {
        unsigned* p;
        ~DecOnDrop() { (*p) --; }
    };
    DecOnDrop enter_function() {
        this->call_stack_depth ++;
        return DecOnDrop { &this->call_stack_depth };
    }
};

class InterpreterThread
{
    friend struct MirHelpers;
    struct StackFrame
    {
        static unsigned s_next_frame_index;
        unsigned    frame_index;

        ::std::function<bool(Value&,Value)> cb;
        const Function* fcn;
        Value ret;
        ::std::vector<Value>    args;
        ::std::vector<Value>    locals;
        ::std::vector<bool>     drop_flags;

        unsigned    bb_idx;
        unsigned    stmt_idx;

        StackFrame(const Function& fcn, ::std::vector<Value> args);
        static StackFrame make_wrapper(::std::function<bool(Value&,Value)> cb) {
            static Function f;
            StackFrame  rv(f, {});
            rv.cb = ::std::move(cb);
            return rv;
        }
    };

    ModuleTree& m_modtree;
    ThreadState m_thread;
    size_t  m_instruction_count;
    ::std::vector<StackFrame>   m_stack;

public:
    InterpreterThread(ModuleTree& modtree):
        m_modtree(modtree),
        m_instruction_count(0)
    {
    }
    ~InterpreterThread();

    void start(const ::HIR::Path& p, ::std::vector<Value> args);
    // Returns `true` if the call stack empties
    bool step_one(Value& out_thread_result);

private:
    bool pop_stack(Value& out_thread_result);

    // Returns true if the call was resolved instantly
    bool call_path(Value& ret_val, const ::HIR::Path& p, ::std::vector<Value> args);
    // Returns true if the call was resolved instantly
    bool call_extern(Value& ret_val, const ::std::string& name, const ::std::string& abi, ::std::vector<Value> args);
    // Returns true if the call was resolved instantly
    bool call_intrinsic(Value& ret_val, const RcString& name, const ::HIR::PathParams& pp, ::std::vector<Value> args);

    // Returns true if the call was resolved instantly
    bool drop_value(Value ptr, const ::HIR::TypeRef& ty, bool is_shallow=false);
};