File: lltypelayout.py

package info (click to toggle)
pypy 5.6.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 97,040 kB
  • ctags: 185,069
  • sloc: python: 1,147,862; ansic: 49,642; cpp: 5,245; asm: 5,169; makefile: 529; sh: 481; xml: 232; lisp: 45
file content (129 lines) | stat: -rw-r--r-- 4,638 bytes parent folder | download | duplicates (9)
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
from rpython.rtyper.lltypesystem import lltype, llmemory, llarena
from rpython.rlib.rarithmetic import is_emulated_long

import struct

memory_alignment = struct.calcsize("P")

primitive_to_fmt = {lltype.Signed:          "l",
                    lltype.Unsigned:        "L",
                    lltype.Char:            "c",
                    lltype.UniChar:         "i",     # 4 bytes
                    lltype.Bool:            "B",
                    lltype.Float:           "d",
                    llmemory.Address:       "P",
                    }
if is_emulated_long:
    primitive_to_fmt.update( {
        lltype.Signed:     "q",
        lltype.Unsigned:   "Q",
        } )

#___________________________________________________________________________
# Utility functions that know about the memory layout of the lltypes
# in the simulation

#returns some sort of layout information that is useful for the simulatorptr
def get_layout(TYPE):
    layout = {}
    if isinstance(TYPE, lltype.Primitive):
        try:
            return primitive_to_fmt[TYPE]
        except KeyError:
            from rpython.rtyper.lltypesystem import rffi
            return rffi.sizeof(TYPE)
    elif isinstance(TYPE, lltype.Ptr):
        return "P"
    elif isinstance(TYPE, lltype.Struct):
        curr = 0
        for name in TYPE._names:
            layout[name] = curr
            curr += get_fixed_size(TYPE._flds[name])
        layout["_size"] = curr
        return layout
    elif isinstance(TYPE, lltype.Array):
        return (get_fixed_size(lltype.Signed), get_fixed_size(TYPE.OF))
    elif isinstance(TYPE, lltype.OpaqueType):
        return "i"
    elif isinstance(TYPE, lltype.FuncType):
        return "i"
    else:
        assert 0, "type %s not yet implemented" % (TYPE, )

def get_fixed_size(TYPE):
    if isinstance(TYPE, lltype.Primitive):
        if TYPE == lltype.Void:
            return 0
        try:
            return struct.calcsize(primitive_to_fmt[TYPE])
        except KeyError:
            from rpython.rtyper.lltypesystem import rffi
            return rffi.sizeof(TYPE)
    elif isinstance(TYPE, lltype.Ptr):
        return struct.calcsize("P")
    elif isinstance(TYPE, lltype.Struct):
        return get_layout(TYPE)["_size"]
    elif isinstance(TYPE, lltype.Array):
        return get_fixed_size(lltype.Unsigned)
    elif isinstance(TYPE, lltype.OpaqueType):
        return get_fixed_size(lltype.Unsigned)
    elif isinstance(TYPE, lltype.FuncType):
        return get_fixed_size(lltype.Unsigned)
    assert 0, "not yet implemented"

def get_variable_size(TYPE):
    if isinstance(TYPE, lltype.Array):
        return get_fixed_size(TYPE.OF)
    elif isinstance(TYPE, lltype.Primitive):
        return 0
    elif isinstance(TYPE, lltype.Struct):
        if TYPE._arrayfld is not None:
            return get_variable_size(TYPE._flds[TYPE._arrayfld])
        else:
            return 0
    elif isinstance(TYPE, lltype.OpaqueType):
        return 0
    elif isinstance(TYPE, lltype.FuncType):
        return 0
    elif isinstance(TYPE, lltype.Ptr):
        return 0
    else:
        assert 0, "not yet implemented"

def sizeof(TYPE, i=None):
    fixedsize = get_fixed_size(TYPE)
    varsize = get_variable_size(TYPE)
    if i is None:
        assert varsize == 0
        return fixedsize
    else:
        return fixedsize + i * varsize

def convert_offset_to_int(offset):
    if isinstance(offset, llmemory.FieldOffset):
        layout = get_layout(offset.TYPE)
        return layout[offset.fldname]
    elif isinstance(offset, llmemory.CompositeOffset):
        return sum([convert_offset_to_int(item) for item in offset.offsets])
    elif type(offset) == llmemory.AddressOffset:
        return 0
    elif isinstance(offset, llmemory.ItemOffset):
        return sizeof(offset.TYPE) * offset.repeat
    elif isinstance(offset, llmemory.ArrayItemsOffset):
        if offset.TYPE._hints.get('nolength', None):
            return 0
        return get_fixed_size(lltype.Signed)
    elif isinstance(offset, llmemory.GCHeaderOffset):
        return sizeof(offset.gcheaderbuilder.HDR)
    elif isinstance(offset, llmemory.ArrayLengthOffset):
        return 0
    elif isinstance(offset, llarena.RoundedUpForAllocation):
        basesize = convert_offset_to_int(offset.basesize)
        if isinstance(offset.minsize, llmemory.AddressOffset):
            minsize = convert_offset_to_int(offset.minsize)
            if minsize > basesize:
                basesize = minsize
        mask = memory_alignment - 1
        return (basesize + mask) & ~ mask
    else:
        raise Exception("unknown offset type %r"%offset)