Commits

Christian Tismer committed 97ab57d Merge

Merge with default

Comments (0)

Files changed (21)

pypy/annotation/classdef.py

                 "the attribute here; the list of read locations is:\n" +
                 '\n'.join([str(loc[0]) for loc in self.read_locations]))
 
-
 class ClassDef(object):
     "Wraps a user class."
 

pypy/jit/backend/test/runner_test.py

 from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.llinterp import LLException
 from pypy.jit.codewriter import heaptracker, longlong
+from pypy.rlib import longlong2float
 from pypy.rlib.rarithmetic import intmask, is_valid_int
 from pypy.jit.backend.detect_cpu import autodetect_main_model_and_size
 
+
 def boxfloat(x):
     return BoxFloat(longlong.getfloatstorage(x))
 
                                      [BoxPtr(x)], 'int').value
         assert res == -19
 
+    def test_convert_float_bytes(self):
+        t = 'int' if longlong.is_64_bit else 'float'
+        res = self.execute_operation(rop.CONVERT_FLOAT_BYTES_TO_LONGLONG,
+                                     [boxfloat(2.5)], t).value
+        assert res == longlong2float.float2longlong(2.5)
+
     def test_ooops_non_gc(self):
         x = lltype.malloc(lltype.Struct('x'), flavor='raw')
         v = heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))

pypy/jit/backend/test/test_random.py

 
 OPERATIONS.append(CastFloatToIntOperation(rop.CAST_FLOAT_TO_INT))
 OPERATIONS.append(CastIntToFloatOperation(rop.CAST_INT_TO_FLOAT))
+OPERATIONS.append(CastFloatToIntOperation(rop.CONVERT_FLOAT_BYTES_TO_LONGLONG))
 
 OperationBuilder.OPERATIONS = OPERATIONS
 
     else:
         assert 0, "unknown backend %r" % pytest.config.option.backend
 
-# ____________________________________________________________    
+# ____________________________________________________________
 
 class RandomLoop(object):
     dont_generate_more = False
-    
+
     def __init__(self, cpu, builder_factory, r, startvars=None):
         self.cpu = cpu
         if startvars is None:

pypy/jit/backend/x86/assembler.py

         else:
             assert token
             struct.number = compute_unique_id(token)
-        self.loop_run_counters.append(struct)            
+        self.loop_run_counters.append(struct)
         return struct
 
     def _find_failure_recovery_bytecode(self, faildescr):
                ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
                             None, descr=self.debug_counter_descr)]
         operations.extend(ops)
-        
+
     @specialize.argtype(1)
     def _inject_debugging_code(self, looptoken, operations, tp, number):
         if self._debug:
         self.mc.MOVD_xr(resloc.value, loc0.value)
         self.mc.CVTSS2SD_xx(resloc.value, resloc.value)
 
+    def genop_convert_float_bytes_to_longlong(self, op, arglocs, resloc):
+        loc0, = arglocs
+        if longlong.is_64_bit:
+            assert isinstance(resloc, RegLoc)
+            assert isinstance(loc0, RegLoc)
+            self.mc.MOVD(resloc, loc0)
+        else:
+            self.mov(loc0, resloc)
+
     def genop_guard_int_is_true(self, op, guard_op, guard_token, arglocs, resloc):
         guard_opnum = guard_op.getopnum()
         self.mc.CMP(arglocs[0], imm0)

pypy/jit/backend/x86/regalloc.py

 
     consider_cast_singlefloat_to_float = consider_cast_int_to_float
 
+    def consider_convert_float_bytes_to_longlong(self, op):
+        if longlong.is_64_bit:
+            loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0))
+            loc1 = self.rm.force_allocate_reg(op.result)
+            self.Perform(op, [loc0], loc1)
+            self.xrm.possibly_free_var(op.getarg(0))
+        else:
+            loc0 = self.xrm.loc(op.getarg(0))
+            loc1 = self.xrm.force_allocate_reg(op.result)
+            self.Perform(op, [loc0], loc1)
+            self.xrm.possibly_free_var(op.getarg(0))
+
     def _consider_llong_binop_xx(self, op):
         # must force both arguments into xmm registers, because we don't
         # know if they will be suitably aligned.  Exception: if the second

pypy/jit/backend/x86/rx86.py

     CVTSS2SD_xb = xmminsn('\xF3', rex_nw, '\x0F\x5A',
                           register(1, 8), stack_bp(2))
 
-    MOVD_rx = xmminsn('\x66', rex_nw, '\x0F\x7E', register(2, 8), register(1), '\xC0')
-    MOVD_xr = xmminsn('\x66', rex_nw, '\x0F\x6E', register(1, 8), register(2), '\xC0')
-    MOVD_xb = xmminsn('\x66', rex_nw, '\x0F\x6E', register(1, 8), stack_bp(2))
+    # These work on machine sized registers.
+    MOVD_rx = xmminsn('\x66', rex_w, '\x0F\x7E', register(2, 8), register(1), '\xC0')
+    MOVD_xr = xmminsn('\x66', rex_w, '\x0F\x6E', register(1, 8), register(2), '\xC0')
+    MOVD_xb = xmminsn('\x66', rex_w, '\x0F\x6E', register(1, 8), stack_bp(2))
 
     PSRAD_xi = xmminsn('\x66', rex_nw, '\x0F\x72', register(1), '\xE0', immediate(2, 'b'))
 

pypy/jit/codewriter/jtransform.py

         op1 = SpaceOperation('-live-', [], None)
         return [op, op1]
 
+    def _noop_rewrite(self, op):
+        return op
+
+    rewrite_op_convert_float_bytes_to_longlong = _noop_rewrite
+
     # ----------
     # Various kinds of calls
 

pypy/jit/codewriter/test/test_flatten.py

             int_return %i2
         """, transform=True)
 
+    def test_convert_float_bytes_to_int(self):
+        from pypy.rlib.longlong2float import float2longlong
+        def f(x):
+            return float2longlong(x)
+        self.encoding_test(f, [25.0], """
+            convert_float_bytes_to_longlong %f0 -> %i0
+            int_return %i0
+        """)
+
 
 def check_force_cast(FROM, TO, operations, value):
     """Check that the test is correctly written..."""

pypy/jit/metainterp/blackhole.py

+from pypy.jit.codewriter import heaptracker, longlong
+from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
+from pypy.jit.metainterp.compile import ResumeAtPositionDescr
+from pypy.jit.metainterp.jitexc import JitException, get_llexception, reraise
+from pypy.rlib import longlong2float
+from pypy.rlib.debug import debug_start, debug_stop, ll_assert, make_sure_not_resized
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck
+from pypy.rlib.rtimer import read_timestamp
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.rtimer import read_timestamp
-from pypy.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.debug import debug_start, debug_stop, ll_assert
-from pypy.rlib.debug import make_sure_not_resized
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
-from pypy.jit.codewriter import heaptracker, longlong
-from pypy.jit.metainterp.jitexc import JitException, get_llexception, reraise
-from pypy.jit.metainterp.compile import ResumeAtPositionDescr
+
 
 def arguments(*argtypes, **kwds):
     resulttype = kwds.pop('returns', None)
         return function
     return decorate
 
+LONGLONG_TYPECODE = 'i' if longlong.is_64_bit else 'f'
+
+
 class LeaveFrame(JitException):
     pass
 
         a = float(a)
         return longlong.getfloatstorage(a)
 
+    @arguments("f", returns=LONGLONG_TYPECODE)
+    def bhimpl_convert_float_bytes_to_longlong(a):
+        a = longlong.getrealfloat(a)
+        return longlong2float.float2longlong(a)
+
     # ----------
     # control flow operations
 
     def bhimpl_copyunicodecontent(cpu, src, dst, srcstart, dststart, length):
         cpu.bh_copyunicodecontent(src, dst, srcstart, dststart, length)
 
-    @arguments(returns=(longlong.is_64_bit and "i" or "f"))
+    @arguments(returns=LONGLONG_TYPECODE)
     def bhimpl_ll_read_timestamp():
         return read_timestamp()
 

pypy/jit/metainterp/pyjitpl.py

                     'cast_float_to_singlefloat', 'cast_singlefloat_to_float',
                     'float_neg', 'float_abs',
                     'cast_ptr_to_int', 'cast_int_to_ptr',
+                    'convert_float_bytes_to_longlong',
                     ]:
         exec py.code.Source('''
             @arguments("box")

pypy/jit/metainterp/resoperation.py

     'CAST_INT_TO_FLOAT/1',          # need some messy code in the backend
     'CAST_FLOAT_TO_SINGLEFLOAT/1',
     'CAST_SINGLEFLOAT_TO_FLOAT/1',
+    'CONVERT_FLOAT_BYTES_TO_LONGLONG/1',
     #
     'INT_LT/2b',
     'INT_LE/2b',

pypy/jit/metainterp/test/test_ajit.py

 import py
 
 from pypy import conftest
+from pypy.jit.codewriter import longlong
 from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
 from pypy.jit.metainterp import pyjitpl, history
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
     loop_invariant, elidable, promote, jit_debug, assert_green,
     AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
     isconstant, isvirtual, promote_string, set_param, record_known_class)
+from pypy.rlib.longlong2float import float2longlong
 from pypy.rlib.rarithmetic import ovfcheck, is_valid_int
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.ootypesystem import ootype
         assert res == f(6, sys.maxint, 32, 48)
         res = self.meta_interp(f, [sys.maxint, 6, 32, 48])
         assert res == f(sys.maxint, 6, 32, 48)
-        
+
 
     def test_loop_invariant_intbox(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         self.meta_interp(f, [20], repeat=7)
         # the loop and the entry path as a single trace
         self.check_jitcell_token_count(1)
-        
+
         # we get:
         #    ENTER             - compile the new loop and the entry bridge
         #    ENTER             - compile the leaving path
         assert res == f(299)
         self.check_resops(guard_class=0, guard_nonnull=4,
                           guard_nonnull_class=4, guard_isnull=2)
-        
+
 
     def test_merge_guardnonnull_guardvalue(self):
         from pypy.rlib.objectmodel import instantiate
         assert res == f(299)
         self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4,
                           guard_nonnull_class=0, guard_isnull=2)
-        
+
 
     def test_merge_guardnonnull_guardvalue_2(self):
         from pypy.rlib.objectmodel import instantiate
         assert res == f(299)
         self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4,
                           guard_nonnull_class=0, guard_isnull=2)
-        
+
 
     def test_merge_guardnonnull_guardclass_guardvalue(self):
         from pypy.rlib.objectmodel import instantiate
             return sa
         assert self.meta_interp(f, [20]) == f(20)
         self.check_resops(int_lt=6, int_le=2, int_ge=4, int_gt=3)
-        
+
 
     def test_intbounds_not_generalized2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'node'])
         assert self.meta_interp(f, [20, 3]) == f(20, 3)
         self.check_jitcell_token_count(1)
         self.check_target_token_count(5)
-        
+
     def test_max_retrace_guards(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
 
         for cell in get_stats().get_all_jitcell_tokens():
             # Initialal trace with two labels and 5 retraces
             assert len(cell.target_tokens) <= 7
-            
+
     def test_nested_retrace(self):
 
         myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'a', 'i', 'j', 'sa'])
         res = self.interp_operations(g, [1])
         assert res == 3
 
+    def test_float2longlong(self):
+        def f(n):
+            return float2longlong(n)
+
+        for x in [2.5, float("nan"), -2.5, float("inf")]:
+            # There are tests elsewhere to verify the correctness of this.
+            expected = float2longlong(x)
+            res = self.interp_operations(f, [x])
+            assert longlong.getfloatstorage(res) == expected
+
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     def test_tagged(self):

pypy/module/micronumpy/types.py

     return dispatcher
 
 class BaseType(object):
+    _attrs_ = ()
+    
     def _unimplemented_ufunc(self, *args):
         raise NotImplementedError
 
     _mixin_ = True
     
     def _read(self, storage, width, i, offset):
-        return byteswap(Primitive._read(self, storage, width, i, offset))
+        if we_are_translated():
+            res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+                                        width, storage, i, offset)
+        else:
+            res = libffi.array_getitem_T(self.T, width, storage, i, offset)
+        return byteswap(res)
 
     def _write(self, storage, width, i, offset, value):
-        Primitive._write(self, storage, width, i, offset, byteswap(value))
+        value = byteswap(value)
+        if we_are_translated():
+            libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+                                 width, storage, i, offset, value)
+        else:
+            libffi.array_setitem_T(self.T, width, storage, i, offset, value)
 
     def pack_str(self, box):
         return struct.pack(self.format_code, byteswap(self.unbox(box)))
 
 class Bool(BaseType, Primitive):
+    _attrs_ = ()
+
     T = lltype.Bool
     BoxType = interp_boxes.W_BoolBox
     format_code = "?"
     _mixin_ = True
 
 class Int8(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.SIGNEDCHAR
     BoxType = interp_boxes.W_Int8Box
     format_code = "b"
 NonNativeInt8 = Int8
 
 class UInt8(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.UCHAR
     BoxType = interp_boxes.W_UInt8Box
     format_code = "B"
 NonNativeUInt8 = UInt8
 
 class Int16(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.SHORT
     BoxType = interp_boxes.W_Int16Box
     format_code = "h"
 
 class NonNativeInt16(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.SHORT
     BoxType = interp_boxes.W_Int16Box
     format_code = "h"
 
 class UInt16(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.USHORT
     BoxType = interp_boxes.W_UInt16Box
     format_code = "H"
 
 class NonNativeUInt16(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.USHORT
     BoxType = interp_boxes.W_UInt16Box
     format_code = "H"
 
 class Int32(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.INT
     BoxType = interp_boxes.W_Int32Box
     format_code = "i"
 
 class NonNativeInt32(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.INT
     BoxType = interp_boxes.W_Int32Box
     format_code = "i"
 
 class UInt32(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.UINT
     BoxType = interp_boxes.W_UInt32Box
     format_code = "I"
 
 class NonNativeUInt32(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.UINT
     BoxType = interp_boxes.W_UInt32Box
     format_code = "I"
 
 class Long(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.LONG
     BoxType = interp_boxes.W_LongBox
     format_code = "l"
 
 class NonNativeLong(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.LONG
     BoxType = interp_boxes.W_LongBox
     format_code = "l"
 
 class ULong(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.ULONG
     BoxType = interp_boxes.W_ULongBox
     format_code = "L"
 
 class NonNativeULong(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.ULONG
     BoxType = interp_boxes.W_ULongBox
     format_code = "L"
 
 class Int64(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.LONGLONG
     BoxType = interp_boxes.W_Int64Box
     format_code = "q"
 
 class NonNativeInt64(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.LONGLONG
     BoxType = interp_boxes.W_Int64Box
     format_code = "q"    
     return self.box(value)
 
 class UInt64(BaseType, Integer):
+    _attrs_ = ()
+
     T = rffi.ULONGLONG
     BoxType = interp_boxes.W_UInt64Box
     format_code = "Q"
     _coerce = func_with_new_name(_uint64_coerce, '_coerce')
 
 class NonNativeUInt64(BaseType, NonNativeInteger):
+    _attrs_ = ()
+
     T = rffi.ULONGLONG
     BoxType = interp_boxes.W_UInt64Box
     format_code = "Q"
 class NonNativeFloat(NonNativePrimitive, Float):
     _mixin_ = True
 
+    def _read(self, storage, width, i, offset):
+        if we_are_translated():
+            res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+                                        width, storage, i, offset)
+        else:
+            res = libffi.array_getitem_T(self.T, width, storage, i, offset)
+        #return byteswap(res)
+        return res
+
+    def _write(self, storage, width, i, offset, value):
+        #value = byteswap(value) XXX
+        if we_are_translated():
+            libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+                                 width, storage, i, offset, value)
+        else:
+            libffi.array_setitem_T(self.T, width, storage, i, offset, value)
+
+    def pack_str(self, box):
+        # XXX byteswap
+        return struct.pack(self.format_code, self.unbox(box))
+
+
 class Float32(BaseType, Float):
+    _attrs_ = ()
+
     T = rffi.FLOAT
     BoxType = interp_boxes.W_Float32Box
     format_code = "f"
 
 class NonNativeFloat32(BaseType, NonNativeFloat):
+    _attrs_ = ()
+
     T = rffi.FLOAT
     BoxType = interp_boxes.W_Float32Box
     format_code = "f"    
 
 class Float64(BaseType, Float):
+    _attrs_ = ()
+
     T = rffi.DOUBLE
     BoxType = interp_boxes.W_Float64Box
     format_code = "d"
 
 class NonNativeFloat64(BaseType, NonNativeFloat):
+    _attrs_ = ()
+
     T = rffi.DOUBLE
     BoxType = interp_boxes.W_Float64Box
     format_code = "d"
 
-class CompositeType(BaseType):
-    def __init__(self, offsets_and_fields, size):
-        self.offsets_and_fields = offsets_and_fields
-        self.size = size
-
-    def get_element_size(self):
-        return self.size
-
 class BaseStringType(object):
     _mixin_ = True
     
 
 NonNativeUnicodeType = UnicodeType
 
-class RecordType(CompositeType):
+class RecordType(BaseType):
+
     T = lltype.Char
+
+    def __init__(self, offsets_and_fields, size):
+        self.offsets_and_fields = offsets_and_fields
+        self.size = size
+
+    def get_element_size(self):
+        return self.size
     
     def read(self, arr, width, i, offset, dtype=None):
         if dtype is None:

pypy/objspace/std/iterobject.py

         index = self.index
         w_length = space.len(self.w_seq)
         w_len = space.sub(w_length, space.wrap(index))
-        if space.is_true(space.lt(w_len,space.wrap(0))):
+        if space.is_true(space.lt(w_len, space.wrap(0))):
             w_len = space.wrap(0)
         return w_len
 
     """Sequence iterator implementation for general sequences."""
 
 class W_FastListIterObject(W_AbstractSeqIterObject):
-    """Sequence iterator specialized for lists, accessing
-    directly their RPython-level list of wrapped objects.
+    """Sequence iterator specialized for lists, accessing directly their
+    RPython-level list of wrapped objects.
     """
 
 class W_FastTupleIterObject(W_AbstractSeqIterObject):
-   """Sequence iterator specialized for tuples, accessing
-   directly their RPython-level list of wrapped objects.
-   """ 
-   def __init__(w_self, w_seq, wrappeditems):
+    """Sequence iterator specialized for tuples, accessing directly
+    their RPython-level list of wrapped objects.
+    """
+    def __init__(w_self, w_seq, wrappeditems):
         W_AbstractSeqIterObject.__init__(w_self, w_seq)
         w_self.tupleitems = wrappeditems
 
 class W_ReverseSeqIterObject(W_Object):
     from pypy.objspace.std.itertype import reverse_iter_typedef as typedef
-    
+
     def __init__(w_self, space, w_seq, index=-1):
         w_self.w_seq = w_seq
         w_self.w_len = space.len(w_seq)
 
 def next__SeqIter(space, w_seqiter):
     if w_seqiter.w_seq is None:
-        raise OperationError(space.w_StopIteration, space.w_None) 
+        raise OperationError(space.w_StopIteration, space.w_None)
     try:
         w_item = space.getitem(w_seqiter.w_seq, space.wrap(w_seqiter.index))
     except OperationError, e:
         w_seqiter.w_seq = None
         if not e.match(space, space.w_IndexError):
             raise
-        raise OperationError(space.w_StopIteration, space.w_None) 
-    w_seqiter.index += 1 
+        raise OperationError(space.w_StopIteration, space.w_None)
+    w_seqiter.index += 1
     return w_item
 
 # XXX __length_hint__()
     except IndexError:
         w_seqiter.tupleitems = None
         w_seqiter.w_seq = None
-        raise OperationError(space.w_StopIteration, space.w_None) 
+        raise OperationError(space.w_StopIteration, space.w_None)
     w_seqiter.index = index + 1
     return w_item
 
         w_item = w_seq.getitem(index)
     except IndexError:
         w_seqiter.w_seq = None
-        raise OperationError(space.w_StopIteration, space.w_None) 
+        raise OperationError(space.w_StopIteration, space.w_None)
     w_seqiter.index = index + 1
     return w_item
 
 
 def next__ReverseSeqIter(space, w_seqiter):
     if w_seqiter.w_seq is None or w_seqiter.index < 0:
-        raise OperationError(space.w_StopIteration, space.w_None) 
+        raise OperationError(space.w_StopIteration, space.w_None)
     try:
         w_item = space.getitem(w_seqiter.w_seq, space.wrap(w_seqiter.index))
-        w_seqiter.index -= 1 
+        w_seqiter.index -= 1
     except OperationError, e:
         w_seqiter.w_seq = None
         if not e.match(space, space.w_IndexError):
             raise
-        raise OperationError(space.w_StopIteration, space.w_None) 
+        raise OperationError(space.w_StopIteration, space.w_None)
     return w_item
 
 # XXX __length_hint__()

pypy/rlib/bitmanipulation.py

 from pypy.rlib import unroll
 
+
 class BitSplitter(dict):
     def __getitem__(self, lengths):
         if isinstance(lengths, int):

pypy/rlib/longlong2float.py

 long long to a float and back to a long long.  There are corner cases
 in which it does not work.
 """
+
+from pypy.annotation import model as annmodel
+from pypy.rlib.rarithmetic import r_int64
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
 
 # -------- implement longlong2float and float2longlong --------
 
 # these definitions are used only in tests, when not translated
 def longlong2float_emulator(llval):
-    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
-    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
-    ll_array[0] = llval
-    floatval = d_array[0]
-    lltype.free(d_array, flavor='raw')
-    return floatval
+    with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array:
+        ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+        ll_array[0] = llval
+        floatval = d_array[0]
+        return floatval
 
-def float2longlong_emulator(floatval):
-    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
-    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
-    d_array[0] = floatval
-    llval = ll_array[0]
-    lltype.free(d_array, flavor='raw')
-    return llval
+def float2longlong(floatval):
+    with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array:
+        ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+        d_array[0] = floatval
+        llval = ll_array[0]
+        return llval
 
 def uint2singlefloat_emulator(ival):
-    f_array = lltype.malloc(FLOAT_ARRAY_PTR.TO, 1, flavor='raw')
-    i_array = rffi.cast(UINT_ARRAY_PTR, f_array)
-    i_array[0] = ival
-    singlefloatval = f_array[0]
-    lltype.free(f_array, flavor='raw')
-    return singlefloatval
+    with lltype.scoped_alloc(FLOAT_ARRAY_PTR.TO, 1) as f_array:
+        i_array = rffi.cast(UINT_ARRAY_PTR, f_array)
+        i_array[0] = ival
+        singlefloatval = f_array[0]
+        return singlefloatval
 
 def singlefloat2uint_emulator(singlefloatval):
-    f_array = lltype.malloc(FLOAT_ARRAY_PTR.TO, 1, flavor='raw')
-    i_array = rffi.cast(UINT_ARRAY_PTR, f_array)
-    f_array[0] = singlefloatval
-    ival = i_array[0]
-    lltype.free(f_array, flavor='raw')
-    return ival
+    with lltype.scoped_alloc(FLOAT_ARRAY_PTR.TO, 1) as f_array:
+        i_array = rffi.cast(UINT_ARRAY_PTR, f_array)
+        f_array[0] = singlefloatval
+        ival = i_array[0]
+        return ival
 
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
 eci = ExternalCompilationInfo(includes=['string.h', 'assert.h'],
                               post_include_bits=["""
 static double pypy__longlong2float(long long x) {
     memcpy(&dd, &x, 8);
     return dd;
 }
-static long long pypy__float2longlong(double x) {
-    long long ll;
-    assert(sizeof(double) == 8 && sizeof(long long) == 8);
-    memcpy(&ll, &x, 8);
-    return ll;
-}
 static float pypy__uint2singlefloat(unsigned int x) {
     float ff;
     assert(sizeof(float) == 4 && sizeof(unsigned int) == 4);
     _nowrapper=True, elidable_function=True, sandboxsafe=True,
     oo_primitive="pypy__longlong2float")
 
-float2longlong = rffi.llexternal(
-    "pypy__float2longlong", [rffi.DOUBLE], rffi.LONGLONG,
-    _callable=float2longlong_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True, sandboxsafe=True,
-    oo_primitive="pypy__float2longlong")
-
 uint2singlefloat = rffi.llexternal(
     "pypy__uint2singlefloat", [rffi.UINT], rffi.FLOAT,
     _callable=uint2singlefloat_emulator, compilation_info=eci,
     _callable=singlefloat2uint_emulator, compilation_info=eci,
     _nowrapper=True, elidable_function=True, sandboxsafe=True,
     oo_primitive="pypy__singlefloat2uint")
+
+
+class Float2LongLongEntry(ExtRegistryEntry):
+    _about_ = float2longlong
+
+    def compute_result_annotation(self, s_float):
+        assert annmodel.SomeFloat().contains(s_float)
+        return annmodel.SomeInteger(knowntype=r_int64)
+
+    def specialize_call(self, hop):
+        [v_float] = hop.inputargs(lltype.Float)
+        return hop.genop("convert_float_bytes_to_longlong", [v_float], resulttype=hop.r_result)

pypy/rlib/rarithmetic.py

     
     T = lltype.typeOf(arg)
     # XXX we cannot do arithmetics on small ints
-    arg = widen(arg)
+    if isinstance(arg, base_int):
+        arg = widen(arg)
     if rffi.sizeof(T) == 1:
         res = arg
     elif rffi.sizeof(T) == 2:
         a, b = arg & 0xFF, arg & 0xFF00
         res = (a << 8) | (b >> 8)
     elif rffi.sizeof(T) == 4:
-        a, b, c, d = arg & 0xFF, arg & 0xFF00, arg & 0xFF0000, arg & r_uint(0xFF000000)
+        FF = r_uint(0xFF)
+        arg = r_uint(arg)
+        a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16),
+                      arg & (FF << 24))
         res = (a << 24) | (b << 8) | (c >> 8) | (d >> 24)
     elif rffi.sizeof(T) == 8:
-        a, b, c, d = (arg & 0xFF, arg & 0xFF00, arg & 0xFF0000,
-                      arg & r_uint(0xFF000000))
-        e, f, g, h = (arg & (r_ulonglong(0xFF) << 32),
-                      arg & (r_ulonglong(0xFF) << 40),
-                      arg & (r_ulonglong(0xFF) << 48),
-                      arg & (r_ulonglong(0xFF) << 56))
+        FF = r_ulonglong(0xFF)
+        arg = r_ulonglong(arg)
+        a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16),
+                      arg & (FF << 24))
+        e, f, g, h = (arg & (FF << 32), arg & (FF << 40), arg & (FF << 48),
+                      arg & (FF << 56))
         res = ((a << 56) | (b << 40) | (c << 24) | (d << 8) | (e >> 8) |
                (f >> 24) | (g >> 40) | (h >> 56))
     else:
 """Float constants"""
 
 import math
+
+from pypy.annotation.model import SomeString
+from pypy.rlib import objectmodel
+from pypy.rpython.extfunc import register_external
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.rlib import objectmodel
-from pypy.rpython.extfunc import register_external
-from pypy.annotation.model import SomeString
+
 
 USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
 
         while i < len(s) and s[i] in '0123456789':
             after_point += s[i]
             i += 1
-            
+
         if i == len(s):
             return sign, before_point, after_point, exponent
 
 
     if i == len(s):
         raise ValueError
-    
+
     while i < len(s) and s[i] in '0123456789':
         exponent += s[i]
         i += 1

pypy/rlib/rstruct/nativefmttable.py

 The table 'native_fmttable' is also used by pypy.module.array.interp_array.
 """
 import struct
-from pypy.rlib import jit
+
+from pypy.rlib import jit, longlong2float
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import r_singlefloat, widen
 from pypy.rlib.rstruct import standardfmttable as std
 from pypy.rlib.rstruct.error import StructError
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.tool import rffi_platform
-from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.rarithmetic import r_singlefloat
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.rlib.objectmodel import specialize
+
 
 native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1)
 
 
 # ____________________________________________________________
 
+
 double_buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', immortal=True)
 float_buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw', immortal=True)
 
-@jit.dont_look_inside
-def double_to_ccharp(doubleval):
-    double_buf[0] = doubleval
-    return rffi.cast(rffi.CCHARP, double_buf)
+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()
-    p = double_to_ccharp(doubleval)
-    fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.DOUBLE))
+    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
 
 @specialize.argtype(0)
 def unpack_double(fmtiter):
     doubleval = double_buf[0]
     fmtiter.appendobj(doubleval)
 
-@jit.dont_look_inside
-def float_to_ccharp(floatval):
-    float_buf[0] = floatval
-    return rffi.cast(rffi.CCHARP, float_buf)
-
 def pack_float(fmtiter):
     doubleval = fmtiter.accept_float_arg()
     floatval = r_singlefloat(doubleval)
-    p = float_to_ccharp(floatval)
-    fmtiter.result.append_charpsize(p, rffi.sizeof(rffi.FLOAT))
+    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
 
 @specialize.argtype(0)
 def unpack_float(fmtiter):

pypy/rlib/rstruct/standardfmttable.py

 # values when packing.
 
 import struct
+
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong
+from pypy.rlib.rstruct import ieee
 from pypy.rlib.rstruct.error import StructError, StructOverflowError
-from pypy.rlib.rstruct import ieee
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong
-from pypy.rlib.objectmodel import specialize
 
 # In the CPython struct module, pack() unconsistently accepts inputs
 # that are out-of-range or floats instead of ints.  Should we emulate

pypy/translator/c/src/float.h

 #define OP_FLOAT_SUB(x,y,r)     r = x - y
 #define OP_FLOAT_MUL(x,y,r)     r = x * y
 #define OP_FLOAT_TRUEDIV(x,y,r) r = x / y
-#define OP_FLOAT_POW(x,y,r)     r = pow(x, y) 
+#define OP_FLOAT_POW(x,y,r)     r = pow(x, y)
 
 /*** conversions ***/
 
 #ifdef HAVE_LONG_LONG
 #define OP_CAST_FLOAT_TO_LONGLONG(x,r) r = (long long)(x)
 #define OP_CAST_FLOAT_TO_ULONGLONG(x,r) r = (unsigned long long)(x)
+#define OP_CONVERT_FLOAT_BYTES_TO_LONGLONG(x,r) memcpy(&r, &x, sizeof(double))
 #endif