summaryrefslogtreecommitdiff
path: root/tools/standalone_miri/hir_sim.hpp
blob: 81d3635a3d2478f3d0079d827a0c620540b6b523 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/*
 * mrustc Standalone MIRI
 * - by John Hodge (Mutabah)
 *
 * hir_sim.hpp
 * - Clones of the mrustc HIR types (HEADER)
 */
#pragma once
#include <string>
#include <vector>
#include <memory>
#include "../../src/include/rc_string.hpp"

const size_t POINTER_SIZE = 8;

#define __ORD(fld)  do { auto o = ::ord(this->fld, x.fld); if( o != OrdEqual )  return o; } while(0)
#define __ORD_C(ty, fld)  do { auto o = ::ord((ty)this->fld, (ty)x.fld); if( o != OrdEqual )  return o; } while(0)
#define __NE(fld)  if(this->fld != x.fld) return true
#define __LT(fld)  if(this->fld != x.fld) return this->fld < x.fld

#if 0
enum Ordering
{
    OrdLess,
    OrdEqual,
    OrdGreater,
};
#endif

struct DataType;
struct FunctionType;

enum class RawType
{
    Unreachable,
    Function,   // TODO: Needs a way of indicating the signature?
    Unit,

    Bool,
    U8, I8,
    U16, I16,
    U32, I32,
    U64, I64,
    U128, I128,
    USize, ISize,

    F32, F64,

    Char, Str,

    Composite,  // Struct, Enum, Union, tuple, ...
    TraitObject,    // Data pointer is `*const ()`, vtable type stored in `composite_type`
};
struct TypeWrapper
{
    enum class Ty
    {
        Array,  // With size
        Borrow, // With BorrowType
        Pointer,    // With BorrowType
        Slice,  // Must be bottom
    } type;
    size_t  size;

    Ordering ord(const TypeWrapper& x) const {
        __ORD_C(int, type);
        __ORD(size);
        return OrdEqual;
    }
    bool operator==(const TypeWrapper& x) const {
        return this->ord(x) == OrdEqual;
    }
    bool operator!=(const TypeWrapper& x) const {
        return this->ord(x) != OrdEqual;
    }
    bool operator<(const TypeWrapper& x) const {
        return this->ord(x) == OrdLess;
    }
};

namespace HIR {

    enum class BorrowType
    {
        Shared,
        Unique,
        Move,
    };
    ::std::ostream& operator<<(::std::ostream& os, const BorrowType& x);
    struct CoreType
    {
        RawType raw_type;
    };
    /// Definition of a type
    struct TypeRef
    {
        // Top to bottom list of wrappers (first entry is the outermost wrapper)
        ::std::vector<TypeWrapper>  wrappers;
        RawType inner_type = RawType::Unit;
        union {
            const DataType* composite_type;
            const FunctionType* function_type;
        } ptr;

        TypeRef()
        {
            ptr.composite_type = nullptr;
        }

        explicit TypeRef(const DataType* dt):
            inner_type(RawType::Composite)
        {
            ptr.composite_type = dt;
        }
        explicit TypeRef(const FunctionType* fp):
            inner_type(RawType::Function)
        {
            ptr.function_type = fp;
        }
        explicit TypeRef(RawType rt):
            inner_type(rt)
        {
            ptr.composite_type = nullptr;
        }
        explicit TypeRef(CoreType ct):
            inner_type(ct.raw_type)
        {
            ptr.composite_type = nullptr;
        }
        static TypeRef diverge() {
            TypeRef rv;
            rv.inner_type = RawType::Unreachable;
            return rv;
        }
        static TypeRef unit() {
            TypeRef rv;
            rv.inner_type = RawType::Unit;
            return rv;
        }

        size_t get_size(size_t ofs=0) const;
        size_t get_align(size_t ofs=0) const;

        // Returns true if this (unsized) type is a wrapper around a slice
        // - Fills `out_inner_size` with the size of the slice element
        bool has_slice_meta(size_t& out_inner_size) const;    // The attached metadata is a count of elements
        // Returns the base unsized type for this type (returning nullptr if there's no unsized field)
        // - Fills `running_inner_size` with the offset to the unsized field
        const TypeRef* get_unsized_type(size_t& running_inner_size) const;
        // Returns the type of associated metadata for this (unsized) type (or `!` if not unsized)
        TypeRef get_meta_type() const;
        // Get the inner type (one level of wrapping removed)
        TypeRef get_inner() const;

        // Add a wrapper over this type (moving)
        TypeRef wrap(TypeWrapper::Ty ty, size_t size)&&;
        // Add a wrapper over this type (copying)
        TypeRef wrapped(TypeWrapper::Ty ty, size_t size) const {
            return TypeRef(*this).wrap(ty, size);
        }
        // Get the wrapper at the provided offset (0 = outermost)
        const TypeWrapper* get_wrapper(size_t ofs=0) const {
            //assert(ofs <= this->wrappers.size());
            if( ofs < this->wrappers.size() ) {
                return &this->wrappers[ofs];
            }
            else {
                return nullptr;
            }
        }

        // Returns true if the type contains any pointers
        bool has_pointer() const;
        // Get the type and offset of the specified field index
        TypeRef get_field(size_t idx, size_t& ofs) const;
        // Get the offset and type of a field (recursing using `other_idx`)
        size_t get_field_ofs(size_t idx, const ::std::vector<size_t>& other_idx,  TypeRef& ty) const;

        const DataType& composite_type() const {
            assert(inner_type == RawType::Composite || inner_type == RawType::TraitObject);
            assert(ptr.composite_type);
            return *ptr.composite_type;
        }
        const FunctionType& function_type() const {
            assert(inner_type == RawType::Function);
            assert(ptr.function_type);
            return *ptr.function_type;
        }

        bool operator==(const RawType& x) const {
            if( this->wrappers.size() != 0 )
                return false;
            return this->inner_type == x;
        }
        bool operator!=(const RawType& x) const {
            return !(*this == x);
        }
        Ordering ord(const TypeRef& x) const {
            __ORD(wrappers);
            __ORD_C(int, inner_type);
            __ORD_C(uintptr_t, ptr.composite_type); // pointer comparison only
            return OrdEqual;
        }
        bool operator==(const TypeRef& x) const {
            return this->ord(x) == OrdEqual;
        }
        bool operator!=(const TypeRef& x) const {
            return this->ord(x) != OrdEqual;
        }
        bool operator<(const TypeRef& x) const {
            return this->ord(x) == OrdLess;
        }

        friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& x);
    };

    struct SimplePath
    {
        ::std::string   crate_name;
        ::std::vector<::std::string>    ents;
        Ordering ord(const SimplePath& x) const {
            __ORD(crate_name);
            __ORD(ents);
            return OrdEqual;
        }
        bool operator==(const SimplePath& x) const {
            return this->ord(x) == OrdEqual;
        }
        bool operator!=(const SimplePath& x) const {
            return this->ord(x) != OrdEqual;
        }
        bool operator<(const SimplePath& x) const {
            return this->ord(x) == OrdLess;
        }
        friend ::std::ostream& operator<<(::std::ostream& os, const SimplePath& x);
    };

    struct PathParams
    {
        ::std::vector<TypeRef>  tys;

        friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x);
    };
    struct GenericPath
    {
        SimplePath  m_simplepath;
        PathParams  m_params;

        GenericPath() {}
        GenericPath(SimplePath sp):
            m_simplepath(sp)
        {
        }
        Ordering ord(const GenericPath& x) const {
            __ORD(m_simplepath);
            __ORD(m_params.tys);
            return OrdEqual;
        }
        bool operator==(const GenericPath& x) const {
            return this->ord(x) == OrdEqual;
        }
        bool operator!=(const GenericPath& x) const {
            return this->ord(x) != OrdEqual;
        }
        bool operator<(const GenericPath& x) const {
            return this->ord(x) == OrdLess;
        }

        friend ::std::ostream& operator<<(::std::ostream& os, const GenericPath& x);
    };
    struct Path
    {
        TypeRef m_type;
        GenericPath m_trait;
        ::std::string   m_name; // if empty, the path is Generic in m_trait
        PathParams  m_params;

        Path()
        {
        }
        Path(SimplePath sp):
            Path(GenericPath(sp))
        {
        }
        Path(GenericPath gp):
            m_trait(gp)
        {
        }
        Path(TypeRef ty, GenericPath trait, ::std::string name, PathParams params):
            m_type(ty),
            m_trait(::std::move(trait)),
            m_name(name),
            m_params(params)
        {
        }

        Ordering ord(const Path& x) const {
            __ORD(m_type);
            __ORD(m_trait);
            __ORD(m_name);
            __ORD(m_params.tys);
            return OrdEqual;
        }
        bool operator==(const Path& x) const {
            return this->ord(x) == OrdEqual;
        }
        bool operator!=(const Path& x) const {
            return this->ord(x) != OrdEqual;
        }
        bool operator<(const Path& x) const {
            return this->ord(x) == OrdLess;
        }

        friend ::std::ostream& operator<<(::std::ostream& os, const Path& x);
    };

} // nameapce HIR


#undef __NE
#undef __LT