File: support.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 (166 lines) | stat: -rw-r--r-- 5,243 bytes parent folder | download | duplicates (3)
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

from rpython.jit.codewriter import longlong
from rpython.jit.codewriter import heaptracker

from rpython.jit.metainterp.history import getkind

from rpython.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
from rpython.rtyper.lltypesystem import lltype, rffi, llmemory

IS_32_BIT = r_ulonglong is not r_uint

kind2TYPE = {
    'i': lltype.Signed,
    'f': lltype.Float,
    'L': lltype.SignedLongLong,
    'S': lltype.SingleFloat,
    'v': lltype.Void,
    }

def cast_to_int(x):
    TP = lltype.typeOf(x)
    if isinstance(TP, lltype.Ptr):
        return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))
    if TP == llmemory.Address:
        return heaptracker.adr2int(x)
    if TP is lltype.SingleFloat:
        return longlong.singlefloat2int(x)
    return lltype.cast_primitive(lltype.Signed, x)

def cast_to_ptr(x):
    assert isinstance(lltype.typeOf(x), lltype.Ptr)
    return lltype.cast_opaque_ptr(llmemory.GCREF, x)

def cast_to_floatstorage(x):
    if isinstance(x, float):
        return longlong.getfloatstorage(x)      # common case
    if IS_32_BIT:
        assert longlong.supports_longlong
        if isinstance(x, r_longlong):
            return x
        if isinstance(x, r_ulonglong):
            return rffi.cast(lltype.SignedLongLong, x)
    raise TypeError(type(x))

def cast_result(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_to_int(x)
    elif kind == 'ref':
        return cast_to_ptr(x)
    elif kind == 'float':
        return cast_to_floatstorage(x)
    else:
        assert kind == 'void'
        assert x is None
        return None

def cast_from_floatstorage(TYPE, x):
    assert isinstance(x, longlong.r_float_storage)
    if TYPE is lltype.Float:
        return longlong.getrealfloat(x)
    if longlong.is_longlong(TYPE):
        return rffi.cast(TYPE, x)
    raise TypeError(TYPE)

def cast_from_int(TYPE, x):
    if isinstance(TYPE, lltype.Ptr):
        if isinstance(x, (int, long, llmemory.AddressAsInt)):
            x = llmemory.cast_int_to_adr(x)
        try:   # pom pom pom
            return llmemory.cast_adr_to_ptr(x, TYPE)
        except Exception:
            # assume that we want a "C-style" cast, without typechecking the value
            return rffi.cast(TYPE, x)
    elif TYPE == llmemory.Address:
        if isinstance(x, (int, long, llmemory.AddressAsInt)):
            x = llmemory.cast_int_to_adr(x)
        assert lltype.typeOf(x) == llmemory.Address
        return x
    elif TYPE is lltype.SingleFloat:
        assert lltype.typeOf(x) is lltype.Signed
        return longlong.int2singlefloat(x)
    else:
        if lltype.typeOf(x) == llmemory.Address:
            x = heaptracker.adr2int(x)
        return lltype.cast_primitive(TYPE, x)

def cast_from_ptr(TYPE, x):
    if lltype.typeOf(x) == TYPE:
        return x
    return lltype.cast_opaque_ptr(TYPE, x)

def cast_arg(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_from_int(TP, x)
    elif kind == 'ref':
        return cast_from_ptr(TP, x)
    else:
        assert kind == 'float'
        return cast_from_floatstorage(TP, x)

def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None):
    argsiter_i = iter(args_i or [])
    argsiter_r = iter(args_r or [])
    argsiter_f = iter(args_f or [])
    if args_in_order is not None:
        orderiter = iter(args_in_order)
    args = []
    for TYPE in ARGS:
        if TYPE is lltype.Void:
            x = None
        else:
            if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'r'
                x = argsiter_r.next()
                x = cast_from_ptr(TYPE, x)
            elif TYPE is lltype.Float or longlong.is_longlong(TYPE):
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'f'
                x = argsiter_f.next()
                x = cast_from_floatstorage(TYPE, x)
            else:
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'i'
                x = argsiter_i.next()
                x = cast_from_int(TYPE, x)
        args.append(x)
    assert list(argsiter_i) == []
    assert list(argsiter_r) == []
    assert list(argsiter_f) == []
    return args

def cast_call_args_in_order(ARGS, args):
    call_args = []
    i = 0
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == 'int':
            n = cast_from_int(ARG, args[i])
            i += 1
        elif kind == 'ref':
            n = cast_from_ptr(ARG, args[i])
            i += 1
        elif kind == 'float':
            n = cast_from_floatstorage(ARG, args[i])
            i += 1
        elif kind == 'void':
            n = None
        else:
            raise AssertionError(kind)
        call_args.append(n)
    assert i == len(args)
    return call_args

def addr_add_bytes(addr, ofs):
    if (isinstance(ofs, int) and
            getattr(addr.adr.ptr._TYPE.TO, 'OF', None) == lltype.Char):
        return addr + ofs
    ptr = rffi.cast(rffi.CCHARP, addr.adr)
    ptr = lltype.direct_ptradd(ptr, ofs)
    return cast_to_int(ptr)