text: from pypy.rpython.lltypesystem import lltype, rffi, rstr
  from pypy.jit.backend.llsupport.descr import *
  from pypy.jit.backend.llsupport import symbolic
  from pypy.rlib.objectmodel import Symbolic
  from pypy.rpython.annlowlevel import llhelper
  from pypy.jit.metainterp import history
  from pypy.jit.codewriter import longlong
  import sys, struct, py
  
  def test_get_size_descr():
      c0 = GcCache(False)
      c1 = GcCache(True)
      T = lltype.GcStruct('T')
      S = lltype.GcStruct('S', ('x', lltype.Char),
                               ('y', lltype.Ptr(T)))
      descr_s = get_size_descr(c0, S)
      descr_t = get_size_descr(c0, T)
      assert descr_s.size == symbolic.get_size(S, False)
      assert descr_t.size == symbolic.get_size(T, False)
      assert descr_s.count_fields_if_immutable() == -1
      assert descr_t.count_fields_if_immutable() == -1
      assert descr_s == get_size_descr(c0, S)
      assert descr_s != get_size_descr(c1, S)
      #
      descr_s = get_size_descr(c1, S)
      assert isinstance(descr_s.size, Symbolic)
      assert descr_s.count_fields_if_immutable() == -1
  
  def test_get_size_descr_immut():
      S = lltype.GcStruct('S', hints={'immutable': True})
      T = lltype.GcStruct('T', ('parent', S),
                          ('x', lltype.Char),
                          hints={'immutable': True})
      U = lltype.GcStruct('U', ('parent', T),
                          ('u', lltype.Ptr(T)),
                          ('v', lltype.Signed),
                          hints={'immutable': True})
      V = lltype.GcStruct('V', ('parent', U),
                          ('miss1', lltype.Void),
                          ('miss2', lltype.Void),
                          hints={'immutable': True})
      for STRUCT, expected in [(S, 0), (T, 1), (U, 3), (V, 3)]:
          for translated in [False, True]:
              c0 = GcCache(translated)
              descr_s = get_size_descr(c0, STRUCT)
              assert descr_s.count_fields_if_immutable() == expected
  
  def test_get_field_descr():
      U = lltype.Struct('U')
      T = lltype.GcStruct('T')
      S = lltype.GcStruct('S', ('x', lltype.Char),
                               ('y', lltype.Ptr(T)),
                               ('z', lltype.Ptr(U)),
                               ('f', lltype.Float),
                               ('s', lltype.SingleFloat))
      #
      c0 = GcCache(False)
      c1 = GcCache(True)
      assert get_field_descr(c0, S, 'y') == get_field_descr(c0, S, 'y')
      assert get_field_descr(c0, S, 'y') != get_field_descr(c1, S, 'y')
      for tsc in [False, True]:
          c2 = GcCache(tsc)
          descr_x = get_field_descr(c2, S, 'x')
          descr_y = get_field_descr(c2, S, 'y')
          descr_z = get_field_descr(c2, S, 'z')
          descr_f = get_field_descr(c2, S, 'f')
          descr_s = get_field_descr(c2, S, 's')
          assert isinstance(descr_x, FieldDescr)
          assert descr_x.name == 'S.x'
          assert descr_y.name == 'S.y'
          assert descr_z.name == 'S.z'
          assert descr_f.name == 'S.f'
          assert descr_s.name == 'S.s'
          if not tsc:
              assert descr_x.offset < descr_y.offset < descr_z.offset
              assert descr_x.sort_key() < descr_y.sort_key() < descr_z.sort_key()
              assert descr_x.field_size == rffi.sizeof(lltype.Char)
              assert descr_y.field_size == rffi.sizeof(lltype.Ptr(T))
              assert descr_z.field_size == rffi.sizeof(lltype.Ptr(U))
              assert descr_f.field_size == rffi.sizeof(lltype.Float)
              assert descr_s.field_size == rffi.sizeof(lltype.SingleFloat)
          else:
              assert isinstance(descr_x.offset, Symbolic)
              assert isinstance(descr_y.offset, Symbolic)
              assert isinstance(descr_z.offset, Symbolic)
              assert isinstance(descr_f.offset, Symbolic)
              assert isinstance(descr_s.offset, Symbolic)
              assert isinstance(descr_x.field_size, Symbolic)
              assert isinstance(descr_y.field_size, Symbolic)
              assert isinstance(descr_z.field_size, Symbolic)
              assert isinstance(descr_f.field_size, Symbolic)
              assert isinstance(descr_s.field_size, Symbolic)
          assert descr_x.flag == FLAG_UNSIGNED
          assert descr_y.flag == FLAG_POINTER
          assert descr_z.flag == FLAG_UNSIGNED
          assert descr_f.flag == FLAG_FLOAT
          assert descr_s.flag == FLAG_UNSIGNED
  
  
  def test_get_field_descr_sign():
      for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
                              (rffi.SHORT,      True), (rffi.USHORT, False),
                              (rffi.INT,        True), (rffi.UINT,   False),
                              (rffi.LONG,       True), (rffi.ULONG,  False)]:
          S = lltype.GcStruct('S', ('x', RESTYPE))
          for tsc in [False, True]:
              c2 = GcCache(tsc)
              descr_x = get_field_descr(c2, S, 'x')
              assert descr_x.flag == {False: FLAG_UNSIGNED,
                                      True:  FLAG_SIGNED  }[signed]
  
  def test_get_field_descr_longlong():
      if sys.maxint > 2147483647:
          py.test.skip("long long: for 32-bit only")
      c0 = GcCache(False)
      S = lltype.GcStruct('S', ('y', lltype.UnsignedLongLong))
      descr = get_field_descr(c0, S, 'y')
      assert descr.flag == FLAG_FLOAT
      assert descr.field_size == 8
  
  
  def test_get_array_descr():
      U = lltype.Struct('U')
      T = lltype.GcStruct('T')
      A1 = lltype.GcArray(lltype.Char)
      A2 = lltype.GcArray(lltype.Ptr(T))
      A3 = lltype.GcArray(lltype.Ptr(U))
      A4 = lltype.GcArray(lltype.Float)
      A5 = lltype.GcArray(lltype.Struct('x', ('v', lltype.Signed),
                                             ('k', lltype.Signed)))
      A6 = lltype.GcArray(lltype.SingleFloat)
      #
      c0 = GcCache(False)
      descr1 = get_array_descr(c0, A1)
      descr2 = get_array_descr(c0, A2)
      descr3 = get_array_descr(c0, A3)
      descr4 = get_array_descr(c0, A4)
      descr5 = get_array_descr(c0, A5)
      descr6 = get_array_descr(c0, A6)
      assert isinstance(descr1, ArrayDescr)
      assert descr1 == get_array_descr(c0, lltype.GcArray(lltype.Char))
      assert descr1.flag == FLAG_UNSIGNED
      assert descr2.flag == FLAG_POINTER
      assert descr3.flag == FLAG_UNSIGNED
      assert descr4.flag == FLAG_FLOAT
      assert descr5.flag == FLAG_STRUCT
      assert descr6.flag == FLAG_UNSIGNED
      #
      def get_alignment(code):
          # Retrieve default alignment for the compiler/platform
          return struct.calcsize(lltype.SignedFmt + code) - struct.calcsize(code)
      assert descr1.basesize == get_alignment('c')
      assert descr2.basesize == get_alignment('p')
      assert descr3.basesize == get_alignment('p')
      assert descr4.basesize == get_alignment('d')
      assert descr5.basesize == get_alignment('f')
      assert descr1.lendescr.offset == 0
      assert descr2.lendescr.offset == 0
      assert descr3.lendescr.offset == 0
      assert descr4.lendescr.offset == 0
      assert descr5.lendescr.offset == 0
      assert descr1.itemsize == rffi.sizeof(lltype.Char)
      assert descr2.itemsize == rffi.sizeof(lltype.Ptr(T))
      assert descr3.itemsize == rffi.sizeof(lltype.Ptr(U))
      assert descr4.itemsize == rffi.sizeof(lltype.Float)
      assert descr5.itemsize == rffi.sizeof(lltype.Signed) * 2
      assert descr6.itemsize == rffi.sizeof(lltype.SingleFloat)
      #
      CA = rffi.CArray(lltype.Signed)
      descr = get_array_descr(c0, CA)
      assert descr.flag == FLAG_SIGNED
      assert descr.basesize == 0
      assert descr.lendescr is None
      CA = rffi.CArray(lltype.Ptr(lltype.GcStruct('S')))
      descr = get_array_descr(c0, CA)
      assert descr.flag == FLAG_POINTER
      assert descr.basesize == 0
      assert descr.lendescr is None
      CA = rffi.CArray(lltype.Ptr(lltype.Struct('S')))
      descr = get_array_descr(c0, CA)
      assert descr.flag == FLAG_UNSIGNED
      assert descr.basesize == 0
      assert descr.lendescr is None
      CA = rffi.CArray(lltype.Float)
      descr = get_array_descr(c0, CA)
      assert descr.flag == FLAG_FLOAT
      assert descr.basesize == 0
      assert descr.lendescr is None
      CA = rffi.CArray(rffi.FLOAT)
      descr = get_array_descr(c0, CA)
      assert descr.flag == FLAG_UNSIGNED
      assert descr.basesize == 0
      assert descr.itemsize == rffi.sizeof(lltype.SingleFloat)
      assert descr.lendescr is None
  
  
  def test_get_array_descr_sign():
      for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
                              (rffi.SHORT,      True), (rffi.USHORT, False),
                              (rffi.INT,        True), (rffi.UINT,   False),
                              (rffi.LONG,       True), (rffi.ULONG,  False)]:
          A = lltype.GcArray(RESTYPE)
          for tsc in [False, True]:
              c2 = GcCache(tsc)
              arraydescr = get_array_descr(c2, A)
              assert arraydescr.flag == {False: FLAG_UNSIGNED,
                                         True:  FLAG_SIGNED  }[signed]
          #
          RA = rffi.CArray(RESTYPE)
          for tsc in [False, True]:
              c2 = GcCache(tsc)
              arraydescr = get_array_descr(c2, RA)
              assert arraydescr.flag == {False: FLAG_UNSIGNED,
                                         True:  FLAG_SIGNED  }[signed]
  
  
  def test_get_array_descr_str():
      c0 = GcCache(False)
      descr1 = get_array_descr(c0, rstr.STR)
      assert descr1.itemsize == rffi.sizeof(lltype.Char)
      assert descr1.flag == FLAG_UNSIGNED
  
  
  def test_get_call_descr_not_translated():
      c0 = GcCache(False)
      descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char)
      assert descr1.get_result_size() == rffi.sizeof(lltype.Char)
      assert descr1.get_result_type() == history.INT
      assert descr1.arg_classes == "ii"
      #
      T = lltype.GcStruct('T')
      descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T))
      assert descr2.get_result_size() == rffi.sizeof(lltype.Ptr(T))
      assert descr2.get_result_type() == history.REF
      assert descr2.arg_classes == "r"
      #
      U = lltype.GcStruct('U', ('x', lltype.Signed))
      assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U))
      #
      V = lltype.Struct('V', ('x', lltype.Signed))
      assert (get_call_descr(c0, [], lltype.Ptr(V)).get_result_type() ==
              history.INT)
      #
      assert (get_call_descr(c0, [], lltype.Void).get_result_type() ==
              history.VOID)
      #
      descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float)
      assert descr4.get_result_size() == rffi.sizeof(lltype.Float)
      assert descr4.get_result_type() == history.FLOAT
      assert descr4.arg_classes == "ff"
      #
      descr5 = get_call_descr(c0, [lltype.SingleFloat], lltype.SingleFloat)
      assert descr5.get_result_size() == rffi.sizeof(lltype.SingleFloat)
      assert descr5.get_result_type() == "S"
      assert descr5.arg_classes == "S"
  
  def test_get_call_descr_not_translated_longlong():
      if sys.maxint > 2147483647:
          py.test.skip("long long: for 32-bit only")
      c0 = GcCache(False)
      #
      descr5 = get_call_descr(c0, [lltype.SignedLongLong], lltype.Signed)
      assert descr5.get_result_size() == 4
      assert descr5.get_result_type() == history.INT
      assert descr5.arg_classes == "L"
      #
      descr6 = get_call_descr(c0, [lltype.Signed], lltype.SignedLongLong)
      assert descr6.get_result_size() == 8
      assert descr6.get_result_type() == "L"
      assert descr6.arg_classes == "i"
  
  def test_get_call_descr_translated():
      c1 = GcCache(True)
      T = lltype.GcStruct('T')
      U = lltype.GcStruct('U', ('x', lltype.Signed))
      descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U))
      assert isinstance(descr3.get_result_size(), Symbolic)
      assert descr3.get_result_type() == history.REF
      assert descr3.arg_classes == "r"
      #
      descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float)
      assert isinstance(descr4.get_result_size(), Symbolic)
      assert descr4.get_result_type() == history.FLOAT
      assert descr4.arg_classes == "ff"
      #
      descr5 = get_call_descr(c1, [lltype.SingleFloat], lltype.SingleFloat)
      assert isinstance(descr5.get_result_size(), Symbolic)
      assert descr5.get_result_type() == "S"
      assert descr5.arg_classes == "S"
  
  def test_call_descr_extra_info():
      c1 = GcCache(True)
      T = lltype.GcStruct('T')
      U = lltype.GcStruct('U', ('x', lltype.Signed))
      descr1 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U), "hello")
      extrainfo = descr1.get_extra_info()
      assert extrainfo == "hello"
      descr2 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U), "hello")
      assert descr1 is descr2
      descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U))
      extrainfo = descr3.get_extra_info()
      assert extrainfo is None
  
  def test_get_call_descr_sign():
      for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
                              (rffi.SHORT,      True), (rffi.USHORT, False),
                              (rffi.INT,        True), (rffi.UINT,   False),
                              (rffi.LONG,       True), (rffi.ULONG,  False)]:
          for tsc in [False, True]:
              c2 = GcCache(tsc)
              descr1 = get_call_descr(c2, [], RESTYPE)
              assert descr1.is_result_signed() == signed
  
  
  def test_repr_of_descr():
      def repr_of_descr(descr):
          s = descr.repr_of_descr()
          assert ',' not in s  # makes the life easier for pypy.tool.jitlogparser
          return s
      c0 = GcCache(False)
      T = lltype.GcStruct('T')
      S = lltype.GcStruct('S', ('x', lltype.Char),
                               ('y', lltype.Ptr(T)),
                               ('z', lltype.Ptr(T)))
      descr1 = get_size_descr(c0, S)
      s = symbolic.get_size(S, False)
      assert repr_of_descr(descr1) == '<SizeDescr %d>' % s
      #
      descr2 = get_field_descr(c0, S, 'y')
      o, _ = symbolic.get_field_token(S, 'y', False)
      assert repr_of_descr(descr2) == '<FieldP S.y %d>' % o
      #
      descr2i = get_field_descr(c0, S, 'x')
      o, _ = symbolic.get_field_token(S, 'x', False)
      assert repr_of_descr(descr2i) == '<FieldU S.x %d>' % o
      #
      descr3 = get_array_descr(c0, lltype.GcArray(lltype.Ptr(S)))
      o = symbolic.get_size(lltype.Ptr(S), False)
      assert repr_of_descr(descr3) == '<ArrayP %d>' % o
      #
      descr3i = get_array_descr(c0, lltype.GcArray(lltype.Char))
      assert repr_of_descr(descr3i) == '<ArrayU 1>'
      #
      descr4 = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Ptr(S))
      assert repr_of_descr(descr4) == '<Callr %d ir>' % o
      #
      descr4i = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Char)
      assert repr_of_descr(descr4i) == '<Calli 1 ir>'
      #
      descr4f = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Float)
      assert repr_of_descr(descr4f) == '<Callf 8 ir>'
      #
      descr5f = get_call_descr(c0, [lltype.Char], lltype.SingleFloat)
      assert repr_of_descr(descr5f) == '<CallS 4 i>'
  
  def test_call_stubs_1():
      c0 = GcCache(False)
      ARGS = [lltype.Char, lltype.Signed]
      RES = lltype.Char
      descr1 = get_call_descr(c0, ARGS, RES)
      def f(a, b):
          return 'c'
  
      fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
  
      res = descr1.call_stub_i(rffi.cast(lltype.Signed, fnptr),
                               [1, 2], None, None)
      assert res == ord('c')
  
  def test_call_stubs_2():
      c0 = GcCache(False)
      ARRAY = lltype.GcArray(lltype.Signed)
      ARGS = [lltype.Float, lltype.Ptr(ARRAY)]
      RES = lltype.Float
  
      def f2(a, b):
          return float(b[0]) + a
  
      fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f2)
      descr2 = get_call_descr(c0, ARGS, RES)
      a = lltype.malloc(ARRAY, 3)
      opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a)
      a[0] = 1
      res = descr2.call_stub_f(rffi.cast(lltype.Signed, fnptr),
                               [], [opaquea], [longlong.getfloatstorage(3.5)])
      assert longlong.getrealfloat(res) == 4.5
  
  def test_call_stubs_single_float():
      from pypy.rlib.longlong2float import uint2singlefloat, singlefloat2uint
      from pypy.rlib.rarithmetic import r_singlefloat, intmask
      #
      c0 = GcCache(False)
      ARGS = [lltype.SingleFloat, lltype.SingleFloat, lltype.SingleFloat]
      RES = lltype.SingleFloat
  
      def f(a, b, c):
          a = float(a)
          b = float(b)
          c = float(c)
          x = a - (b / c)
          return r_singlefloat(x)
  
      fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
      descr2 = get_call_descr(c0, ARGS, RES)
      a = intmask(singlefloat2uint(r_singlefloat(-10.0)))
      b = intmask(singlefloat2uint(r_singlefloat(3.0)))
      c = intmask(singlefloat2uint(r_singlefloat(2.0)))
      res = descr2.call_stub_i(rffi.cast(lltype.Signed, fnptr),
                               [a, b, c], [], [])
      assert float(uint2singlefloat(rffi.r_uint(res))) == -11.5
  
  def test_field_arraylen_descr():
      c0 = GcCache(True)
      A1 = lltype.GcArray(lltype.Signed)
      fielddescr = get_field_arraylen_descr(c0, A1)
      assert isinstance(fielddescr, FieldDescr)
      ofs = fielddescr.offset
      assert repr(ofs) == '< ArrayLengthOffset <GcArray of Signed > >'
      #
      fielddescr = get_field_arraylen_descr(c0, rstr.STR)
      ofs = fielddescr.offset
      assert repr(ofs) == ("< <FieldOffset <GcStruct rpy_string { hash, chars }>"
                           " 'chars'> + < ArrayLengthOffset"
                           " <Array of Char > > >")
      # caching:
      assert fielddescr is get_field_arraylen_descr(c0, rstr.STR)
  