[pypy-svn] r14325 - in pypy/branch/dist-2.4.1/pypy: objspace/std objspace/std/test translator/llvm2 translator/llvm2/test

arigo at codespeak.net arigo at codespeak.net
Wed Jul 6 13:30:32 CEST 2005


Author: arigo
Date: Wed Jul  6 13:30:32 2005
New Revision: 14325

Added:
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/extfunctions.py
      - copied unchanged from r14324, pypy/dist/pypy/translator/llvm2/extfunctions.py
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/pickleformat.txt
      - copied unchanged from r14324, pypy/dist/pypy/translator/llvm2/pickleformat.txt
Modified:
   pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py
   pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py
   pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py
Log:
svn merge -r14306:14324 http://codespeak.net/svn/pypy/dist



Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py	Wed Jul  6 13:30:32 2005
@@ -63,7 +63,7 @@
 
     def _setshort(self, index, short):
         a = self.digits[index // 2]
-        ##!!assert isinstance(short, r_uint)
+        assert isinstance(short, r_uint)
         assert short & SHORT_MASK == short
         if index % 2 == 0:
             self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short
@@ -135,8 +135,8 @@
         raise OperationError(space.w_OverflowError,
                              space.wrap("long int too large to convert to float"))
 
-def long__Float(space, w_floatobj): #YYYYYY
-    return W_LongObject(space, *args_from_long(long(w_floatobj.floatval)))
+def long__Float(space, w_floatobj):
+    return _FromDouble(space, w_floatobj.floatval)
 
 def int_w__Long(space, w_value):
     if len(w_value.digits) == 1:
@@ -156,11 +156,11 @@
     raise OperationError(space.w_OverflowError,
                          space.wrap("long int too large to convert to unsigned int"))    
 
-def repr__Long(space, w_long): #YYYYYY
-    return space.wrap(repr(w_long.longval()))
+def repr__Long(space, w_long):
+    return space.wrap(_format(w_long, 10, True))
 
-def str__Long(space, w_long): #YYYYYY
-    return space.wrap(str(w_long.longval()))
+def str__Long(space, w_long):
+    return space.wrap(_format(w_long, 10, False))
 
 def eq__Long_Long(space, w_long1, w_long2):
     if (w_long1.sign != w_long2.sign or
@@ -435,31 +435,20 @@
     w_result._normalize()
     return w_result
 
-def and__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a & b
-    return W_LongObject(space, *args_from_long(res))
-
-def xor__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a ^ b
-    return W_LongObject(space, *args_from_long(res))
-
-def or__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a | b
-    return W_LongObject(space, *args_from_long(res))
-
-def oct__Long(space, w_long1): #YYYYYY
-    x = w_long1.longval()
-    return space.wrap(oct(x))
-
-def hex__Long(space, w_long1): #YYYYYY
-    x = w_long1.longval()
-    return space.wrap(hex(x))
+def and__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '&', w_long2)
+
+def xor__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '^', w_long2)
+
+def or__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '|', w_long2)
+
+def oct__Long(space, w_long1):
+    return space.wrap(_format(w_long1, 8, True))
+
+def hex__Long(space, w_long1):
+    return space.wrap(_format(w_long1, 16, True))
 
 def getnewargs__Long(space, w_long1):
     return space.newtuple([W_LongObject(space, w_long1.digits, w_long1.sign)])
@@ -617,14 +606,16 @@
     z._normalize()
     return z
 
-def _inplace_divrem1(pout, pin, n):
+def _inplace_divrem1(pout, pin, n, size=0):
     """
     Divide long pin by non-zero digit n, storing quotient
     in pout, and returning the remainder. It's OK for pin == pout on entry.
     """
     rem = r_uint(0)
     assert n > 0 and n <= SHORT_MASK
-    size = len(pin.digits) * 2 - 1
+    if not size:
+        size = len(pin.digits) * 2
+    size -= 1
     while size >= 0:
         rem = (rem << SHORT_BIT) + pin._getshort(size)
         hi = rem // n
@@ -774,7 +765,7 @@
             vj = r_uint(0)
         else:
             vj = v._getshort(j)
-        carry = r_suint(0) # note: this must hold two digits and sign!
+        carry = r_suint(0) # note: this must hold two digits and a sign!
 
         if vj == w._getshort(size_w-1):
             q = r_uint(SHORT_MASK)
@@ -792,7 +783,6 @@
                                 ) << SHORT_BIT)
                 + v._getshort(j-2)):
             q -= 1
-
         i = 0
         while i < size_w and i+k < size_v:
             z = w._getshort(i) * q
@@ -809,10 +799,10 @@
             v._setshort(i+k, r_uint(0))
 
         if carry == 0:
-            a._setshort(k, q)
+            a._setshort(k, q & SHORT_MASK)
         else:
             assert carry == -1
-            a._setshort(k, q-1)
+            a._setshort(k, (q-1) & SHORT_MASK)
 
             carry = r_suint(0)
             i = 0
@@ -999,3 +989,227 @@
         one = W_LongObject(space, [r_uint(1)], 1)
         div = sub__Long_Long(space, div, one)
     return div, mod
+
+
+def _format(a, base, addL):
+    """
+    Convert a long int object to a string, using a given conversion base.
+    Return a string object.
+    If base is 8 or 16, add the proper prefix '0' or '0x'.
+    """
+    size_a = len(a.digits) * 2
+    if a._getshort(size_a-1) == 0:
+        size_a -= 1
+
+    assert base >= 2 and base <= 36
+
+    sign = False
+
+    # Compute a rough upper bound for the length of the string
+    i = base
+    bits = 0
+    while i > 1:
+        bits += 1
+        i >>= 1
+    i = 5 + int(bool(addL)) + (size_a*LONG_BIT + bits-1) // bits
+    s = [chr(0)] * i
+    p = i
+    if addL:
+        p -= 1
+        s[p] = 'L'
+    if a.sign < 0:
+        sign = True
+
+    if a.sign == 0:
+        p -= 1
+        s[p] = '0'
+    elif (base & (base - 1)) == 0:
+        # JRH: special case for power-of-2 bases
+        accum = r_uint(0)
+        accumbits = 0  # # of bits in accum 
+        basebits = 1   # # of bits in base-1
+        i = base
+        while 1:
+            i >>= 1
+            if i <= 1:
+                break
+            basebits += 1
+
+        for i in range(size_a):
+            accum |= a._getshort(i) << accumbits
+            accumbits += SHORT_BIT
+            assert accumbits >= basebits
+            while 1:
+                cdigit = accum & (base - 1)
+                if cdigit < 10:
+                    cdigit += ord('0')
+                else:
+                    cdigit += ord('A') - 10
+                assert p > 0
+                p -= 1
+                s[p] = chr(cdigit)
+                accumbits -= basebits
+                accum >>= basebits
+                if i < size_a - 1:
+                    if accumbits < basebits:
+                        break
+                else:
+                    if accum <= 0:
+                        break
+    else:
+        # Not 0, and base not a power of 2.  Divide repeatedly by
+        # base, but for speed use the highest power of base that
+        # fits in a digit.
+        size = size_a
+        pin = a # just for similarity to C source which uses the array
+        # powbasw <- largest power of base that fits in a digit.
+        powbase = base  # powbase == base ** power
+        power = 1
+        while 1:
+            newpow = powbase * r_uint(base)
+            if newpow >> SHORT_BIT:  # doesn't fit in a digit
+                break
+            powbase = newpow
+            power += 1
+
+        # Get a scratch area for repeated division.
+        digitpairs = (size + 1) // 2
+        scratch = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1)
+
+        # Repeatedly divide by powbase.
+        while 1:
+            ntostore = power
+            rem = _inplace_divrem1(scratch, pin, powbase, size)
+            pin = scratch  # no need to use a again
+            if pin._getshort(size - 1) == 0:
+                size -= 1
+
+            # Break rem into digits.
+            assert ntostore > 0
+            while 1:
+                nextrem = rem // base
+                c = rem - nextrem * base
+                assert p > 0
+                if c < 10:
+                    c += ord('0')
+                else:
+                    c += ord('A') - 10
+                p -= 1
+                s[p] = chr(c)
+                rem = nextrem
+                ntostore -= 1
+                # Termination is a bit delicate:  must not
+                # store leading zeroes, so must get out if
+                # remaining quotient and rem are both 0.
+                if not (ntostore and (size or rem)):
+                    break
+            if size == 0:
+                break
+
+    if base == 8:
+        if size_a != 0:
+            p -= 1
+            s[p] = '0'
+    elif base == 16:
+        p -= 1
+        s[p] ='x'
+        p -= 1
+        s[p] = '0'
+    elif base != 10:
+        p -= 1
+        s[p] = '#'
+        p -= 1
+        s[p] = chr(ord('0') + base % 10)
+        if base > 10:
+            p -= 1
+            s[p] = chr(ord('0') + base // 10)
+    if sign:
+        p -= 1
+        s[p] = '-'
+
+    if p == 0:
+        return ''.join(s)
+    else:
+        return ''.join(s[p:])
+
+
+def _bitwise(a, op, n): # '&', '|', '^'
+    """ Bitwise and/xor/or operations """
+
+    if a.sign < 0:
+        a = invert__Long(a.space, a)
+        maska = r_uint(SHORT_MASK)
+    else:
+        maska = r_uint(0)
+    if b.sign < 0:
+        b = invert__Long(b.space, b)
+        maskb = r_uint(SHORT_MASK)
+    else:
+        maskb = r_uint(0)
+
+    negz = 0
+    if op == '^':
+        if maska != maskb:
+            maska ^= SHORT_MASK
+            negz = -1
+    elif op == '&':
+        if maska and maskb:
+            op = '|'
+            maska ^= SHORT_MASK
+            maskb ^= SHORT_MASK
+            negz = -1
+    elif op == '|':
+        if maska or maskb:
+            op = '&'
+            maska ^= SHORT_MASK
+            maskb ^= SHORT_MASK
+            negz = -1
+
+    # JRH: The original logic here was to allocate the result value (z)
+    # as the longer of the two operands.  However, there are some cases
+    # where the result is guaranteed to be shorter than that: AND of two
+    # positives, OR of two negatives: use the shorter number.  AND with
+    # mixed signs: use the positive number.  OR with mixed signs: use the
+    # negative number.  After the transformations above, op will be '&'
+    # iff one of these cases applies, and mask will be non-0 for operands
+    # whose length should be ignored.
+
+    size_a = len(a.digits) * 2
+    if a._getshort(size_a - 1) == 0:
+        size_a -= 1
+    if b._getshort(size_b - 1) == 0:
+        size_b -= 1
+    if op == '&':
+        if maska:
+            size_z = size_b
+        else:
+            if maskb:
+                size_z = size_a
+            else:
+                size_z = min(size_a, size_b)
+    else:
+        size_z = max(size_a, size_b)
+
+    digitpairs = (size_z + 1) // 2
+    z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1)
+
+    for i in range(size_z):
+        if i < size_a:
+            diga = a._getshort(i) ^ maska
+        else:
+            diga = maska
+        if i < size_b:
+            digb = b._getshort(i) ^ maskb
+        else:
+            digb = maskb
+        if op == '&':
+            z._setshort(i, diga & digb)
+        elif op == '|':
+            z._setshort(i, diga | digb)
+        elif op == '^':
+            z._setshort(i, diga ^ digb)
+
+    z_normalize()
+    if negz == 0:
+        return z
+    return invert__Long(z)

Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py	Wed Jul  6 13:30:32 2005
@@ -161,7 +161,7 @@
 
     def test_conversions(self):
         space = self.space
-        for v in (0,1,-1,sys.maxint,-sys.maxint-1):
+        for v in (0, 1, -1, sys.maxint, -sys.maxint-1):
             assert lobj.W_LongObject(self.space, *lobj.args_from_long(v)).longval() == v
             w_v = space.newint(v)
             for w_lv in (lobj.long__Int(space, w_v), lobj.delegate_Int2Long(w_v)):
@@ -319,4 +319,15 @@
             for y in [-105566530L, -1L, 1L, 1034522340L]:
                 print "checking division for %s, %s" % (x, y)
                 check_division(x, y)
-            raises(ZeroDivisionError, "x // 0L")
+        # special case from python tests:
+        x = 16565645174462751485571442763871865344588923363439663038777355323778298703228675004033774331442052275771343018700586987657790981527457655176938756028872904152013524821759375058141439
+        y = 10953035502453784575
+        print "special case"
+        check_division(x, y)
+        raises(ZeroDivisionError, "x // 0L")
+
+    def test_format(self):
+        assert repr(12345678901234567890) == '12345678901234567890L'
+        assert str(12345678901234567890) == '12345678901234567890'
+        assert hex(0x1234567890ABCDEFL) == '0x1234567890ABCDEFL'
+        assert oct(01234567012345670L) == '01234567012345670L'

Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py	Wed Jul  6 13:30:32 2005
@@ -76,7 +76,10 @@
                 ct = ct.TO
             
             if isinstance(ct, lltype.FuncType):
-                self.addpending(const_or_var, FuncNode(self, const_or_var))
+                if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'):
+                    log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj)))
+                else:
+                    self.addpending(const_or_var, FuncNode(self, const_or_var))
             else:
                 value = const_or_var.value
                 while hasattr(value, "_obj"):

Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py	Wed Jul  6 13:30:32 2005
@@ -7,6 +7,7 @@
 from pypy.translator.llvm2.node import LLVMNode
 from pypy.translator.llvm2.atomic import is_atomic
 from pypy.translator.llvm2.log import log 
+from pypy.rpython.extfunctable import table as extfunctable
 nextnum = py.std.itertools.count().next
 log = log.funcnode
 
@@ -38,6 +39,7 @@
 
     def __init__(self, db, const_ptr_func):
         self.db = db
+        self.const_ptr_func = const_ptr_func
         self.ref = "%" + const_ptr_func.value._obj._name
         self.graph = const_ptr_func.value._obj.graph 
         remove_same_as(self.graph) 
@@ -65,6 +67,12 @@
         codewriter.declare(self.getdecl())
 
     def writeimpl(self, codewriter):
+        _callable = self.const_ptr_func.value._obj._callable
+        for func, extfuncinfo in extfunctable.iteritems():  # precompute a dict?
+            if _callable is extfuncinfo.ll_function:
+                log('skipped output of external function %s' % self.const_ptr_func.value._obj._name)
+                return
+
         assert self._issetup 
         graph = self.graph
         log.writeimpl(graph.name)

Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py	Wed Jul  6 13:30:32 2005
@@ -12,6 +12,7 @@
 from pypy.tool.udir import udir
 from pypy.translator.llvm2.codewriter import CodeWriter
 from pypy.translator.backendoptimization import remove_void
+from pypy.translator.llvm2.extfunctions import extdeclarations, extfunctions
 
 function_count = {}
 
@@ -39,6 +40,8 @@
         typ_decl.writeglobalconstants(codewriter)
 
     nl(); comment("Function Prototypes") ; nl()
+    for extdecl in extdeclarations.split('\n'):
+        codewriter.append(extdecl)
     if use_boehm_gc: 
         codewriter.declare('sbyte* %GC_malloc(uint)')
         codewriter.declare('sbyte* %GC_malloc_atomic(uint)')
@@ -49,6 +52,8 @@
     #import pdb ; pdb.set_trace()
     nl(); comment("Function Implementation") 
     codewriter.startimpl()
+    for extfunc in extfunctions.split('\n'):
+        codewriter.append(extfunc)
     for typ_decl in db.getobjects():
         typ_decl.writeimpl(codewriter)
 

Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py
==============================================================================
--- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py	(original)
+++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py	Wed Jul  6 13:30:32 2005
@@ -37,6 +37,13 @@
     f = getattr(mod, function.func_name + "_wrapper")
     return mod, f
 
+def test_external_function():
+    import os
+    def fn():
+        return os.dup(0)
+    f = compile_function(fn, [], view=False)
+    assert os.path.sameopenfile(f(), fn())
+
 def test_GC_malloc(): 
     if not use_boehm_gc:
         py.test.skip("test_GC_malloc skipped because Boehm collector library was not found")
@@ -324,7 +331,7 @@
     l = "Hello, World"
     def string_getitem1(i): 
         return l[i]
-    f = compile_function(string_getitem1, [int], view=True)
+    f = compile_function(string_getitem1, [int], view=False)
     assert f(0) == ord("H")
 
 def DONOT_test_string_getitem2():



More information about the Pypy-commit mailing list