[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