text: from rpython.flowspace.operation import op
  from rpython.rlib import debug
  from rpython.rlib.rarithmetic import is_valid_int
  from rpython.rtyper.lltypesystem import lltype, llmemory
  from rpython.tool.sourcetools import func_with_new_name
  
  # ____________________________________________________________
  # Implementation of the 'canfold' operations
  
  
  # implementations of ops from flow.operation
  ops_returning_a_bool = {'gt': True, 'ge': True,
                          'lt': True, 'le': True,
                          'eq': True, 'ne': True,
                          'bool': True, 'is_true':True}
  
  # global synonyms for some types
  from rpython.rlib.rarithmetic import intmask
  from rpython.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong, r_longlonglong
  from rpython.rtyper.lltypesystem.llmemory import AddressAsInt
  
  if r_longlong is r_int:
      r_longlong_arg = (r_longlong, int, long)
      r_longlong_result = long # XXX was int
  else:
      r_longlong_arg = r_longlong
      r_longlong_result = r_longlong
  
  
  r_longlonglong_arg = r_longlonglong
  r_longlonglong_result = r_longlonglong
  
  argtype_by_name = {
      'int': (int, long),
      'float': float,
      'uint': r_uint,
      'llong': r_longlong_arg,
      'ullong': r_ulonglong,
      'lllong': r_longlonglong,
      }
  
  def no_op(x):
      return x
  
  def get_primitive_op_src(fullopname):
      assert '_' in fullopname, "%s: not a primitive op" % (fullopname,)
      typname, opname = fullopname.split('_', 1)
      if hasattr(op, opname):
          oper = getattr(op, opname)
      elif hasattr(op, opname + '_'):
          oper = getattr(op, opname + '_')   # or_, and_
      else:
          raise ValueError("%s: not a primitive op" % (fullopname,))
      func = oper.pyfunc
  
      if typname == 'char':
          # char_lt, char_eq, ...
          def op_function(x, y):
              if not isinstance(x, str) or len(x) != 1:
                  raise TypeError("%r arg must be a char, got %r instead" % (
                      fullopname, typname, type(x).__name__))
              if not isinstance(y, str) or len(y) != 1:
                  raise TypeError("%r arg must be a char, got %r instead" % (
                      fullopname, typname, type(y).__name__))
              return func(x, y)
  
      else:
          if typname == 'int' and opname not in ops_returning_a_bool:
              adjust_result = intmask
          else:
              adjust_result = no_op
          assert typname in argtype_by_name, "%s: not a primitive op" % (
              fullopname,)
          argtype = argtype_by_name[typname]
  
          if oper.arity == 1:
              def op_function(x):
                  if not isinstance(x, argtype):
                      raise TypeError("%r arg must be %s, got %r instead" % (
                          fullopname, typname, type(x).__name__))
                  return adjust_result(func(x))
          else:
              def op_function(x, y):
                  if not isinstance(x, argtype):
                      raise TypeError("%r arg 1 must be %s, got %r instead"% (
                          fullopname, typname, type(x).__name__))
                  if not isinstance(y, argtype):
                      raise TypeError("%r arg 2 must be %s, got %r instead"% (
                          fullopname, typname, type(y).__name__))
                  return adjust_result(func(x, y))
  
      return func_with_new_name(op_function, 'op_' + fullopname)
  
  def checkptr(ptr):
      if not isinstance(lltype.typeOf(ptr), lltype.Ptr):
          raise TypeError("arg must be a pointer, got %r instead" % (
              lltype.typeOf(ptr),))
  
  def checkadr(adr):
      if lltype.typeOf(adr) is not llmemory.Address:
          raise TypeError("arg must be an address, got %r instead" % (
              lltype.typeOf(adr),))
  
  
  def op_int_eq(x, y):
      if not isinstance(x, (int, long)):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic), (
              "'int_eq' arg 1 must be int-like, got %r instead" % (
                  type(x).__name__,))
      if not isinstance(y, (int, long)):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(y, llgroup.CombinedSymbolic), (
              "'int_eq' arg 2 must be int-like, got %r instead" % (
                  type(y).__name__,))
      return x == y
  
  def op_ptr_eq(ptr1, ptr2):
      checkptr(ptr1)
      checkptr(ptr2)
      return ptr1 == ptr2
  
  def op_ptr_ne(ptr1, ptr2):
      checkptr(ptr1)
      checkptr(ptr2)
      return ptr1 != ptr2
  
  def op_ptr_nonzero(ptr1):
      checkptr(ptr1)
      return bool(ptr1)
  
  def op_ptr_iszero(ptr1):
      checkptr(ptr1)
      return not bool(ptr1)
  
  def op_getsubstruct(obj, field):
      checkptr(obj)
      # check the difference between op_getfield and op_getsubstruct:
      assert isinstance(getattr(lltype.typeOf(obj).TO, field),
                        lltype.ContainerType)
      return getattr(obj, field)
  
  def op_getarraysubstruct(array, index):
      checkptr(array)
      result = array[index]
      return result
      # the diff between op_getarrayitem and op_getarraysubstruct
      # is the same as between op_getfield and op_getsubstruct
  
  def op_getinteriorarraysize(obj, *offsets):
      checkptr(obj)
      ob = obj
      for o in offsets:
          if isinstance(o, str):
              ob = getattr(ob, o)
          else:
              ob = ob[o]
      return len(ob)
  
  def op_getinteriorfield(obj, *offsets):
      checkptr(obj)
      ob = obj
      for o in offsets:
          innermostcontainer = ob
          if isinstance(o, str):
              ob = getattr(ob, o)
          else:
              ob = ob[o]
      # we can constant-fold this if the innermost structure from which we
      # read the final field is immutable.
      T = lltype.typeOf(innermostcontainer).TO
      if not T._immutable_field(offsets[-1]):
          raise TypeError("cannot fold getinteriorfield on mutable struct")
      assert not isinstance(ob, lltype._interior_ptr)
      return ob
  
  def op_getarraysize(array):
      checkptr(array)
      return len(array)
  
  def op_direct_fieldptr(obj, field):
      checkptr(obj)
      assert isinstance(field, str)
      return lltype.direct_fieldptr(obj, field)
  
  def op_direct_arrayitems(obj):
      checkptr(obj)
      return lltype.direct_arrayitems(obj)
  
  def op_direct_ptradd(obj, index):
      checkptr(obj)
      assert is_valid_int(index)
      if not obj:
          raise AssertionError("direct_ptradd on null pointer")
          ## assert isinstance(index, int)
          ## assert not (0 <= index < 4096)
          ## from rpython.rtyper.lltypesystem import rffi
          ## return rffi.cast(lltype.typeOf(obj), index)
      return lltype.direct_ptradd(obj, index)
  
  
  def op_bool_not(b):
      assert type(b) is bool
      return not b
  
  def op_int_add(x, y):
      if not isinstance(x, (int, long, llmemory.AddressOffset)):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic)
      assert isinstance(y, (int, long, llmemory.AddressOffset))
      return intmask(x + y)
  
  def op_int_sub(x, y):
      if not is_valid_int(x):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic)
      assert is_valid_int(y)
      return intmask(x - y)
  
  def op_int_ge(x, y):
      # special case for 'AddressOffset >= 0'
      assert isinstance(x, (int, long, llmemory.AddressOffset))
      assert is_valid_int(y)
      return x >= y
  
  def op_int_lt(x, y):
      # special case for 'AddressOffset < 0'
      # hack for win64
      assert isinstance(x, (int, long, llmemory.AddressOffset))
      assert is_valid_int(y)
      return x < y
  
  def op_int_between(a, b, c):
      assert lltype.typeOf(a) is lltype.Signed
      assert lltype.typeOf(b) is lltype.Signed
      assert lltype.typeOf(c) is lltype.Signed
      return a <= b < c
  
  def op_int_force_ge_zero(a):
      assert lltype.typeOf(a) is lltype.Signed
      if a < 0:
          return 0
      return a
  
  def op_int_and(x, y):
      if not is_valid_int(x):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic)
      assert is_valid_int(y)
      return x & y
  
  def op_int_or(x, y):
      if not is_valid_int(x):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic)
      assert is_valid_int(y)
      return x | y
  
  def op_int_xor(x, y):
      # used in computing hashes
      if isinstance(x, AddressAsInt): x = llmemory.cast_adr_to_int(x.adr)
      if isinstance(y, AddressAsInt): y = llmemory.cast_adr_to_int(y.adr)
      assert is_valid_int(x)
      assert is_valid_int(y)
      return x ^ y
  
  def op_int_mul(x, y):
      assert isinstance(x, (int, long, llmemory.AddressOffset))
      assert isinstance(y, (int, long, llmemory.AddressOffset))
      return intmask(x * y)
  
  def op_int_rshift(x, y):
      if not is_valid_int(x):
          from rpython.rtyper.lltypesystem import llgroup
          assert isinstance(x, llgroup.CombinedSymbolic)
      assert is_valid_int(y)
      return x >> y
  
  def op_int_floordiv(x, y):
      # hack for win64
      assert isinstance(x, (int, long, llmemory.AddressOffset))
      assert isinstance(y, (int, long, llmemory.AddressOffset))
      r = x//y
      if x^y < 0 and x%y != 0:
          r += 1
      return r
  
  def op_int_mod(x, y):
      assert isinstance(x, (int, long, llmemory.AddressOffset))
      assert isinstance(y, (int, long, llmemory.AddressOffset))
      r = x%y
      if x^y < 0 and x%y != 0:
          r -= y
      return r
  
  def op_llong_floordiv(x, y):
      assert isinstance(x, r_longlong_arg)
      assert isinstance(y, r_longlong_arg)
      r = x//y
      if x^y < 0 and x%y != 0:
          r += 1
      return r
  
  def op_llong_mod(x, y):
      assert isinstance(x, r_longlong_arg)
      assert isinstance(y, r_longlong_arg)
      r = x%y
      if x^y < 0 and x%y != 0:
          r -= y
      return r
  
  def op_lllong_floordiv(x, y):
      assert isinstance(x, r_longlonglong_arg)
      assert isinstance(y, r_longlonglong_arg)
      r = x//y
      if x^y < 0 and x%y != 0:
          r += 1
      return r
  
  def op_lllong_mod(x, y):
      assert isinstance(x, r_longlonglong_arg)
      assert isinstance(y, r_longlonglong_arg)
      r = x%y
      if x^y < 0 and x%y != 0:
          r -= y
      return r
  
  def op_uint_lshift(x, y):
      assert isinstance(x, r_uint)
      assert is_valid_int(y)
      return r_uint(x << y)
  
  def op_uint_rshift(x, y):
      assert isinstance(x, r_uint)
      assert is_valid_int(y)
      return r_uint(x >> y)
  
  def op_llong_lshift(x, y):
      assert isinstance(x, r_longlong_arg)
      assert is_valid_int(y)
      return r_longlong_result(x << y)
  
  def op_llong_rshift(x, y):
      assert isinstance(x, r_longlong_arg)
      assert is_valid_int(y)
      return r_longlong_result(x >> y)
  
  def op_lllong_lshift(x, y):
      assert isinstance(x, r_longlonglong_arg)
      assert is_valid_int(y)
      return r_longlonglong_result(x << y)
  
  def op_lllong_rshift(x, y):
      assert isinstance(x, r_longlonglong_arg)
      assert is_valid_int(y)
      return r_longlonglong_result(x >> y)
  
  def op_ullong_lshift(x, y):
      assert isinstance(x, r_ulonglong)
      assert isinstance(y, int)
      return r_ulonglong(x << y)
  
  def op_ullong_rshift(x, y):
      assert isinstance(x, r_ulonglong)
      assert is_valid_int(y)
      return r_ulonglong(x >> y)
  
  def op_same_as(x):
      return x
  
  def op_cast_primitive(TYPE, value):
      assert isinstance(lltype.typeOf(value), lltype.Primitive)
      return lltype.cast_primitive(TYPE, value)
  op_cast_primitive.need_result_type = True
  
  def op_cast_int_to_float(i):
      # assert type(i) is int
      assert is_valid_int(i)
      return float(i)
  
  def op_cast_uint_to_float(u):
      assert type(u) is r_uint
      return float(u)
  
  def op_cast_longlong_to_float(i):
      assert isinstance(i, r_longlong_arg)
      # take first 31 bits
      li = float(int(i & r_longlong(0x7fffffff)))
      ui = float(int(i >> 31)) * float(0x80000000)
      return ui + li
  
  def op_cast_ulonglong_to_float(i):
      assert isinstance(i, r_ulonglong)
      # take first 32 bits
      li = float(int(i & r_ulonglong(0xffffffff)))
      ui = float(int(i >> 32)) * float(0x100000000)
      return ui + li
  
  def op_cast_int_to_char(b):
      #assert type(b) is int
      assert is_valid_int(b)
      return chr(b)
  
  def op_cast_bool_to_int(b):
      assert type(b) is bool
      return int(b)
  
  def op_cast_bool_to_uint(b):
      assert type(b) is bool
      return r_uint(int(b))
  
  def op_cast_bool_to_float(b):
      assert type(b) is bool
      return float(b)
  
  def op_cast_float_to_int(f):
      assert type(f) is float
      return intmask(int(f))
  
  def op_cast_float_to_uint(f):
      assert type(f) is float
      return r_uint(long(f))
  
  def op_cast_float_to_longlong(f):
      assert type(f) is float
      r = float(0x100000000)
      small = f / r
      high = int(small)
      truncated = int((small - high) * r)
      return r_longlong_result(high) * 0x100000000 + truncated
  
  def op_cast_float_to_ulonglong(f):
      assert type(f) is float
      return r_ulonglong(long(f))
  
  def op_cast_char_to_int(b):
      assert type(b) is str and len(b) == 1
      return ord(b)
  
  def op_cast_unichar_to_int(b):
      assert type(b) is unicode and len(b) == 1
      return ord(b)
  
  def op_cast_int_to_unichar(b):
      assert is_valid_int(b)
      return unichr(b)
  
  def op_cast_int_to_uint(b):
      # assert type(b) is int
      assert is_valid_int(b)
      return r_uint(b)
  
  def op_cast_uint_to_int(b):
      assert type(b) is r_uint
      return intmask(b)
  
  def op_cast_int_to_longlong(b):
      assert is_valid_int(b)
      return r_longlong_result(b)
  
  def op_truncate_longlong_to_int(b):
      assert isinstance(b, r_longlong_arg)
      return intmask(b)
  
  def op_cast_pointer(RESTYPE, obj):
      checkptr(obj)
      return lltype.cast_pointer(RESTYPE, obj)
  op_cast_pointer.need_result_type = True
  
  def op_cast_adr_to_ptr(TYPE, adr):
      checkadr(adr)
      return llmemory.cast_adr_to_ptr(adr, TYPE)
  op_cast_adr_to_ptr.need_result_type = True
  
  def op_cast_int_to_adr(int):
      return llmemory.cast_int_to_adr(int)
  
  def op_convert_float_bytes_to_longlong(a):
      from rpython.rlib.longlong2float import float2longlong
      return float2longlong(a)
  
  def op_convert_longlong_bytes_to_float(a):
      from rpython.rlib.longlong2float import longlong2float
      return longlong2float(a)
  
  
  def op_unichar_eq(x, y):
      assert isinstance(x, unicode) and len(x) == 1
      assert isinstance(y, unicode) and len(y) == 1
      return x == y
  
  def op_unichar_ne(x, y):
      assert isinstance(x, unicode) and len(x) == 1
      assert isinstance(y, unicode) and len(y) == 1
      return x != y
  
  
  def op_adr_lt(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 < addr2
  
  def op_adr_le(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 <= addr2
  
  def op_adr_eq(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 == addr2
  
  def op_adr_ne(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 != addr2
  
  def op_adr_gt(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 > addr2
  
  def op_adr_ge(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 >= addr2
  
  def op_adr_add(addr, offset):
      checkadr(addr)
      assert lltype.typeOf(offset) is lltype.Signed
      return addr + offset
  
  def op_adr_sub(addr, offset):
      checkadr(addr)
      assert lltype.typeOf(offset) is lltype.Signed
      return addr - offset
  
  def op_adr_delta(addr1, addr2):
      checkadr(addr1)
      checkadr(addr2)
      return addr1 - addr2
  
  def op_gc_writebarrier_before_copy(source, dest,
                                     source_start, dest_start, length):
      A = lltype.typeOf(source)
      assert A == lltype.typeOf(dest)
      if isinstance(A.TO, lltype.GcArray):
          if isinstance(A.TO.OF, lltype.Ptr):
              assert A.TO.OF.TO._gckind == 'gc'
          else:
              assert isinstance(A.TO.OF, lltype.Struct)
      else:
          assert isinstance(A.TO, lltype.GcStruct)
          assert A.TO._arrayfld is not None
      assert type(source_start) is int
      assert type(dest_start) is int
      assert type(length) is int
      return True
  
  def op_getfield(p, name):
      checkptr(p)
      TYPE = lltype.typeOf(p).TO
      if not TYPE._immutable_field(name):
          raise TypeError("cannot fold getfield on mutable struct")
      return getattr(p, name)
  
  def op_getarrayitem(p, index):
      checkptr(p)
      ARRAY = lltype.typeOf(p).TO
      if not ARRAY._immutable_field(index):
          raise TypeError("cannot fold getarrayitem on mutable array")
      return p[index]
  
  def _normalize(x):
      if not isinstance(x, str):
          TYPE = lltype.typeOf(x)
          if isinstance(TYPE, lltype.Ptr) and TYPE.TO._name == 'rpy_string':
              from rpython.rtyper.annlowlevel import hlstr
              return hlstr(x)
      return x
  
  def op_debug_print(*args):
      debug.debug_print(*map(_normalize, args))
  
  def op_debug_start(category):
      debug.debug_start(_normalize(category))
  
  def op_debug_stop(category):
      debug.debug_stop(_normalize(category))
  
  def op_debug_offset():
      return debug.debug_offset()
  
  def op_debug_flush():
      pass
  
  def op_have_debug_prints():
      return debug.have_debug_prints()
  
  def op_have_debug_prints_for(prefix):
      return True
  
  def op_debug_nonnull_pointer(x):
      assert x
  
  def op_gc_stack_bottom():
      pass       # marker for trackgcroot.py
  
  def op_jit_force_virtualizable(*args):
      pass
  
  def op_jit_force_virtual(x):
      return x
  
  def op_jit_is_virtual(x):
      return False
  
  def op_jit_force_quasi_immutable(*args):
      pass
  
  def op_jit_record_known_class(x, y):
      pass
  
  def op_jit_ffi_save_result(*args):
      pass
  
  def op_get_group_member(TYPE, grpptr, memberoffset):
      from rpython.rtyper.lltypesystem import llgroup
      assert isinstance(memberoffset, llgroup.GroupMemberOffset)
      member = memberoffset._get_group_member(grpptr)
      return lltype.cast_pointer(TYPE, member)
  op_get_group_member.need_result_type = True
  
  def op_get_next_group_member(TYPE, grpptr, memberoffset, skipoffset):
      from rpython.rtyper.lltypesystem import llgroup
      assert isinstance(memberoffset, llgroup.GroupMemberOffset)
      member = memberoffset._get_next_group_member(grpptr, skipoffset)
      return lltype.cast_pointer(TYPE, member)
  op_get_next_group_member.need_result_type = True
  
  def op_is_group_member_nonzero(memberoffset):
      from rpython.rtyper.lltypesystem import llgroup
      if isinstance(memberoffset, llgroup.GroupMemberOffset):
          return memberoffset.index != 0
      else:
          assert is_valid_int(memberoffset)
          return memberoffset != 0
  
  def op_extract_ushort(combinedoffset):
      from rpython.rtyper.lltypesystem import llgroup
      assert isinstance(combinedoffset, llgroup.CombinedSymbolic)
      return combinedoffset.lowpart
  
  def op_combine_ushort(ushort, rest):
      from rpython.rtyper.lltypesystem import llgroup
      return llgroup.CombinedSymbolic(ushort, rest)
  
  def op_gc_gettypeptr_group(TYPE, obj, grpptr, skipoffset, vtableinfo):
      HDR            = vtableinfo[0]
      size_gc_header = vtableinfo[1]
      fieldname      = vtableinfo[2]
      objaddr = llmemory.cast_ptr_to_adr(obj)
      hdraddr = objaddr - size_gc_header
      hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
      typeid = getattr(hdr, fieldname)
      if lltype.typeOf(typeid) == lltype.Signed:
          typeid = op_extract_ushort(typeid)
      return op_get_next_group_member(TYPE, grpptr, typeid, skipoffset)
  op_gc_gettypeptr_group.need_result_type = True
  
  def op_get_member_index(memberoffset):
      raise NotImplementedError
  
  def op_gc_writebarrier(addr):
      pass
  
  def op_shrink_array(array, smallersize):
      return False
  
  def op_ll_read_timestamp():
      from rpython.rlib.rtimer import read_timestamp
      return read_timestamp()
  
  def op_debug_fatalerror(ll_msg):
      from rpython.rtyper.lltypesystem import lltype, rstr
      from rpython.rtyper.llinterp import LLFatalError
      assert lltype.typeOf(ll_msg) == lltype.Ptr(rstr.STR)
      msg = ''.join(ll_msg.chars)
      raise LLFatalError(msg)
  
  def op_raw_store(p, ofs, newvalue):
      from rpython.rtyper.lltypesystem import rffi
      p = rffi.cast(llmemory.Address, p)
      TVAL = lltype.typeOf(newvalue)
      p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
      p[0] = newvalue
  
  def op_raw_load(TVAL, p, ofs):
      from rpython.rtyper.lltypesystem import rffi
      p = rffi.cast(llmemory.Address, p)
      p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
      return p[0]
  op_raw_load.need_result_type = True
  
  def op_likely(x):
      assert isinstance(x, bool)
      return x
  
  def op_unlikely(x):
      assert isinstance(x, bool)
      return x
  
  # ____________________________________________________________
  
  def get_op_impl(opname):
      # get the op_xxx() function from the globals above
      try:
          return globals()['op_' + opname]
      except KeyError:
          return get_primitive_op_src(opname)
  