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
|
"""
Native type codes.
The table 'native_fmttable' is also used by pypy.module.array.interp_array.
"""
import struct
from rpython.rlib import jit, longlong2float
from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import r_singlefloat, widen
from rpython.rlib.rstruct import standardfmttable as std
from rpython.rlib.rstruct.standardfmttable import native_is_bigendian
from rpython.rlib.rstruct.error import StructError
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.tool import rffi_platform
from rpython.translator.tool.cbuild import ExternalCompilationInfo
native_fmttable = {
'x': std.standard_fmttable['x'],
'c': std.standard_fmttable['c'],
's': std.standard_fmttable['s'],
'p': std.standard_fmttable['p'],
}
# ____________________________________________________________
range_8_unroll = unrolling_iterable(list(reversed(range(8))))
range_4_unroll = unrolling_iterable(list(reversed(range(4))))
def pack_double(fmtiter):
doubleval = fmtiter.accept_float_arg()
value = longlong2float.float2longlong(doubleval)
if fmtiter.bigendian:
for i in range_8_unroll:
x = (value >> (8*i)) & 0xff
fmtiter.result.append(chr(x))
else:
for i in range_8_unroll:
fmtiter.result.append(chr(value & 0xff))
value >>= 8
def pack_float(fmtiter):
doubleval = fmtiter.accept_float_arg()
floatval = r_singlefloat(doubleval)
value = longlong2float.singlefloat2uint(floatval)
value = widen(value)
if fmtiter.bigendian:
for i in range_4_unroll:
x = (value >> (8*i)) & 0xff
fmtiter.result.append(chr(x))
else:
for i in range_4_unroll:
fmtiter.result.append(chr(value & 0xff))
value >>= 8
# ____________________________________________________________
#
# Use rffi_platform to get the native sizes and alignments from the C compiler
def setup():
INSPECT = {'b': 'signed char',
'h': 'signed short',
'i': 'signed int',
'l': 'signed long',
'q': 'signed long long',
'n': 'ssize_t',
'B': 'unsigned char',
'H': 'unsigned short',
'I': 'unsigned int',
'L': 'unsigned long',
'Q': 'unsigned long long',
'N': 'size_t',
'P': 'char *',
'f': 'float',
'd': 'double',
'?': '_Bool',
}
pre_include_bits = ["""
#include <sys/types.h>
#ifdef _MSC_VER
#define _Bool char
typedef int ssize_t; /* XXX fixme for 64 bit*/
typedef unsigned int size_t; /* XXX fixme for 64 bit*/
#endif"""]
field_names = dict.fromkeys(INSPECT)
for fmtchar, ctype in INSPECT.iteritems():
field_name = ctype.replace(" ", "_").replace("*", "star")
field_names[fmtchar] = field_name
pre_include_bits.append("""
struct about_%s {
char pad;
%s field;
};
""" % (field_name, ctype))
class CConfig:
_compilation_info_ = ExternalCompilationInfo(
pre_include_bits = pre_include_bits
)
for fmtchar, ctype in INSPECT.items():
setattr(CConfig, field_names[fmtchar], rffi_platform.Struct(
"struct about_%s" % (field_names[fmtchar],),
[('field', lltype.FixedSizeArray(rffi.CHAR, 1))]))
cConfig = rffi_platform.configure(CConfig)
for fmtchar, ctype in INSPECT.items():
S = cConfig[field_names[fmtchar]]
alignment = rffi.offsetof(S, 'c_field')
size = rffi.sizeof(S.c_field)
signed = 'a' <= fmtchar <= 'z'
if fmtchar == 'f':
pack = pack_float
unpack = std.unpack_float
elif fmtchar == 'd':
pack = pack_double
unpack = std.unpack_double
elif fmtchar == '?':
pack = std.pack_bool
unpack = std.unpack_bool
else:
pack = std.make_int_packer(size, signed)
unpack = std.make_int_unpacker(size, signed)
native_fmttable[fmtchar] = {'size': size,
'alignment': alignment,
'pack': pack,
'unpack': unpack}
setup()
sizeof_double = native_fmttable['d']['size']
sizeof_float = native_fmttable['f']['size']
# ____________________________________________________________
#
# A PyPy extension: accepts the 'u' format character in native mode,
# just like the array module does. (This is actually used in the
# implementation of our interp-level array module.)
from rpython.rlib.rstruct import unichar
def pack_unichar(fmtiter):
unistr = fmtiter.accept_unicode_arg()
if len(unistr) != 1:
raise StructError("expected a unicode string of length 1")
c = unistr[0] # string->char conversion for the annotator
unichar.pack_unichar(c, fmtiter.result)
@specialize.argtype(0)
def unpack_unichar(fmtiter):
data = fmtiter.read(unichar.UNICODE_SIZE)
fmtiter.appendobj(unichar.unpack_unichar(data))
native_fmttable['u'] = {'size': unichar.UNICODE_SIZE,
'alignment': unichar.UNICODE_SIZE,
'pack': pack_unichar,
'unpack': unpack_unichar,
}
|