WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit 16f38115 authored by John Zhang's avatar John Zhang
Browse files

merge from mu-rewrite branch

parents 0df391a2 3673a935
image: johnjz/mu-client-pypy-ci-image
variables:
MU_HOLSTEIN: "$CI_PROJECT_DIR/mu-impl-ref2"
PYTHONPATH: $CI_PROJECT_DIR
PYTEST: "python -m pytest -v"
MU_TEST_DIR: "$CI_PROJECT_DIR/rpython/translator/mu/test"
CC: "clang"
before_script:
- git apply pypy.patch
mu:test_typesystem:
script:
- cd $MU_TEST_DIR
- $PYTEST test_mutype.py test_layout.py
mu:test_other:
script:
- cd $MU_TEST_DIR
- $PYTEST test_exctran.py
mu:test_impl_dep:
script:
- git clone https://gitlab.anu.edu.au/mu/mu-impl-ref2 && cd mu-impl-ref2
- git checkout issuemir2-uptr-hack
- sbt compile && cd cbinding && make
- cd $MU_TEST_DIR
# tests that depend on mu-impl-ref2 go here
- $PYTEST test_ll2mu.py test_mutyper.py test_database.py test_genmu.py
\ No newline at end of file
=====================================
PyPy: Python in Python Implementation
=====================================
==============================
PyPy-Mu: A Mu Backend for PyPy
==============================
Welcome to PyPy!
Welcome to PyPy-Mu!
PyPy is both an implementation of the Python programming language, and
an extensive compiler framework for dynamic language implementations.
You can build self-contained Python implementations which execute
independently from CPython.
PyPy-Mu is a fork of `PyPy <http://pypy.org>`__ that aims to
add a `Mu Micro Virtual Machine <http://microvm.org>`__ backend for it.
The home page is:
This project is currently under active development,
right now we can compile PyPy interpreter with `--no-allworkingmodules` option.
http://pypy.org/
Building
========
If you want to help developing PyPy, this document might help you:
Obtaining a Mu implementation
-----------------------------
http://doc.pypy.org/
The reference implementation (Holstein) for Mu can be found `here <https://gitlab.anu.edu.au/mu/mu-impl-ref2>`__.
Build the Mu implementation, make sure to build the C binding as well.
The fast implementation (Zebu) for Mu can be found `here <https://gitlab.anu.edu.au/mu/mu-impl-fast>`__.
This implementation is still in progress.
It will also point you to the rest of the documentation which is generated
from files in the pypy/doc directory within the source repositories. Enjoy
and send us feedback!
Reference implementation is targetted by default.
You can specify which implementation to target using the flag ``--mu-impl=<impl>`` to RPython.
the pypy-dev team <pypy-dev@python.org>
Setting up environment variable
-------------------------------
.. role:: bash(code)
:language: bash
Building
========
RPython Mu API binding requires ``$MU_HOLSTEIN`` and/or ``$MU_ZEBU`` environment variable to be set.
You need to set them to point to the cloned Mu implementation repository.
Apply Patch to PyPy/RPython Source Code
---------------------------------------
You may need to also apply the patch to PyPy/RPython source code in fixing some problems.
Some of these changes are acknowledged and committed on the PyPy upstream, some are yet resolved.
::
$ git apply pypy.patch
Compiling & Executing RPython Target
------------------------------------
Specify :bash:`-b mu` option to compile using the Mu backend:
::
$ rpython/bin/rpython -b mu <target>
This builds the program bundle and dumpts out a boot image as ``<target>-mu`` in the current directory.
The nature of the boot image is implementation defined.
Currently for Holstein, it is a zip file; for Zebu, it is a binary executable.
Note the default Mu code generation backend is API (building bundle through API calls).
This back-end can be slow for compiling larger RPython programs.
An alternative is caching the calls into C sources, and run from there (remove the overhead of RPython FFI).
To specify the code generation back-end, use the flag ``--mu-codegen=<backend>``, which takes ``c`` or ``api``.
To run the dumped boot image under Holstein, use the `runmu.sh` shell script.
::
$ $MU_HOLSTEIN/tools/runmu.sh <mu-flags> <bootimage> <program-args>
build with:
--------------------------
.. code-block:: console
Why not try compiling the PyPy interpreter (currently with some limitations)?
$ rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py
::
This ends up with ``pypy-c`` binary in the main pypy directory. We suggest
to use virtualenv with the resulting pypy-c as the interpreter; you can
find more details about various installation schemes here:
$ PYTHONPATH=$PYPY_MU pypy rpython/bin/rpython -O3 -b mu --mu-vmargs='sosSize=780M\nlosSize=780M' --mu-codegen=c --no-shared $PYPY_MU/pypy/goal/targetpypystandalone.py --no-allworkingmodules
$ $MU/tools/runmu.sh --staticCheck=false --sourceInfo=false --vmLog=ERROR --sosSize=780M --losSize=780M $PYPY_MU/pypy/bin/pypy-mu
http://doc.pypy.org/en/latest/install.html
Note: when building the pypy interpreter, put the boot image under pypy/bin, so that PyPy can initialise the path correctly.
\ No newline at end of file
......@@ -56,6 +56,44 @@ index f35e2b7..6aad4b8 100644
@replace_os_function('makedev')
@jit.dont_look_inside
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
index cf9fecf..ca5fa64 100644
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -381,17 +381,18 @@ class ThreadLocalReference(ThreadLocalField):
def __init__(self, Cls, loop_invariant=False):
"NOT_RPYTHON: must be prebuilt"
+ from rpython.rtyper import rclass
self.Cls = Cls
unique_id = ThreadLocalReference._COUNT
ThreadLocalReference._COUNT += 1
- ThreadLocalField.__init__(self, lltype.Signed, 'tlref%d' % unique_id,
+ ThreadLocalField.__init__(self, rclass.OBJECTPTR, 'tlref%d' % unique_id,
loop_invariant=loop_invariant)
setraw = self.setraw
offset = self._offset
def get():
if we_are_translated():
- from rpython.rtyper import rclass
+ # from rpython.rtyper import rclass
from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
_threadlocalref_seeme(self)
ptr = llop.threadlocalref_get(rclass.OBJECTPTR, offset)
@@ -403,9 +404,10 @@ class ThreadLocalReference(ThreadLocalField):
def set(value):
assert isinstance(value, Cls) or value is None
if we_are_translated():
- from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+ from rpython.rtyper.annlowlevel import cast_instance_to_gcref, cast_instance_to_base_ptr
gcref = cast_instance_to_gcref(value)
- value = lltype.cast_ptr_to_int(gcref)
+ # value = lltype.cast_ptr_to_int(gcref)
+ value = cast_instance_to_base_ptr(value)
setraw(value)
rgc.register_custom_trace_hook(TRACETLREF, _lambda_trace_tlref)
rgc.ll_writebarrier(_tracetlref_obj)
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
index b3bc6ed..4edfcaa 100644
--- a/rpython/rlib/test/test_rposix.py
......
......@@ -298,8 +298,9 @@ translation_optiondescription = OptionDescription(
default='', cmdline="--mu-vmargs"),
BoolOption("no_ovf", "Assume all arithematic operations never overflow, "
"thus eliminating the demand for binop with status flag feature on Zebu.",
requires=[('translation.mu.impl', 'zebu')],
default=False, cmdline="--mu-zebu-no-ovf")
default=False, cmdline="--mu-no-ovf"),
BoolOption("verbtypename", "Use more verbose version of type names.",
default=False, cmdline="--mu-verbose-type-name")
]),
])
......
......@@ -568,14 +568,14 @@ LL_OPERATIONS = {
'instrument_count': LLOp(),
# __________ Mu backend _________
'mu_binop': LLOp(),
'mu_binop': LLOp(canraise=(OverflowError,)), # set canraise for raise analyser
'mu_cmpop': LLOp(),
'mu_convop': LLOp(),
'mu_select': LLOp(),
'mu_branch': LLOp(),
'mu_branch2': LLOp(),
'mu_switch': LLOp(),
'mu_call': LLOp(),
'mu_call': LLOp(canraise=(Exception,)),
'mu_tailcall': LLOp(),
'mu_ret': LLOp(),
'mu_throw': LLOp(),
......
......@@ -340,6 +340,12 @@ class MuNameManager:
self._assigned_names = set()
self._conflict_ctr = {}
# verbose struct name?
from rpython.config.translationoption import get_translation_config
config = get_translation_config()
if config:
self.verbose_type_name = config.translation.mu.verbtypename
def assign(self, obj):
if isinstance(obj, mutype.MuType):
name = self.get_type_name(obj)
......@@ -366,16 +372,40 @@ class MuNameManager:
name = 'i%d' % MuT.BITS
if isinstance(MuT, mutype.MuStruct):
name = 'stt%d' % self._counter['stt']
self._counter['stt'] += 1
if getattr(self, 'verbose_type_name', False):
name = 'stt' + MuT._name
if name in self._counter:
self._counter[name] += 1
name = name + str(self._counter[name])
else:
self._counter[name] = 1
else:
name = 'stt%d' % self._counter['stt']
self._counter['stt'] += 1
if isinstance(MuT, mutype.MuHybrid):
name = 'hyb%d' % self._counter['hyb']
self._counter['hyb'] += 1
if getattr(self, 'verbose_type_name', False):
name = 'hyb' + MuT._name
if name in self._counter:
self._counter[name] += 1
name = name + str(self._counter[name])
else:
self._counter[name] = 1
else:
name = 'hyb%d' % self._counter['hyb']
self._counter['hyb'] += 1
if isinstance(MuT, mutype.MuArray):
name = 'arr%d' % self._counter['arr']
self._counter['arr'] += 1
if getattr(self, 'verbose_type_name', False):
name = 'arr%d%s' % (MuT.length, self.get_type_name(MuT.OF)[1:])
if name in self._counter:
self._counter[name] += 1
name = name + str(self._counter[name])
else:
self._counter[name] = 1
else:
name = 'arr%d' % self._counter['arr']
self._counter['arr'] += 1
if isinstance(MuT, mutype.MuReferenceType):
prefix_map = {
......
......@@ -27,6 +27,10 @@ class MuBundleGen:
self.db = db
self.idmap = {}
self.rmu = get_rmu()
if hasattr(self.rmu, 'get_global_apilogger'):
self.rmu.get_global_apilogger().clear() # clear API logger over continuous test runs
self.mu_config = get_translation_config().translation.mu
self.mu = self.rmu.MuVM(self.get_config_str())
self.ctx = self.mu.new_context()
......@@ -191,7 +195,7 @@ class MuBundleGen:
platform.execute_makefile(mf)
exec 'from rpython.rlib.rmu.%s import eci as rmu_eci' % self.mu_config.impl
log_platform.execute(exe)
r = platform.execute(exe, env={'LD_LIBRARY_PATH': locals()['rmu_eci'].library_dirs[0]})
r = platform.execute(exe, compilation_info=locals()['rmu_eci'])
if r.returncode != 0:
raise CompilationError(r.out, r.err)
......
......@@ -149,13 +149,12 @@ class LL2MuMapper:
lltype.Char: mutype.MU_INT8,
lltype.Bool: mutype.MU_INT8,
lltype.Void: mutype.MU_VOID,
lltype.UniChar: mutype.MU_INT16,
lltype.UniChar: mutype.MU_INT32, # wchar_t is 32-bits on OS X and Linux 64-bit machines
}
try:
return type_map[LLT]
except KeyError:
if isinstance(LLT, lltype.Number) and \
LLT._type in rarithmetic._inttypes.values():
if isinstance(LLT, lltype.Number) and issubclass(LLT._type, rarithmetic.base_int): # integer type
b = LLT._type.BITS
if hasattr(mutype, "MU_INT%d" % b):
return getattr(mutype, "MU_INT%d" % b)
......@@ -944,6 +943,10 @@ class LL2MuMapper:
return ops
def map_op_setarrayitem(self, llop):
if len(llop.args) < 3:
MuT = llop.args[0].concretetype.TO
assert isinstance(MuT, mutype.MuStruct) and 'Void' in llop.args[0].concretetype.TO._name
return [] # setting Void type values to array of Voids; translate as no-op
var, idx_vc, val_vc = llop.args
iref_itm, ops = self._getarrayitemiref(var, idx_vc)
ops.append(self.gen_mu_store(iref_itm, val_vc, llop.result))
......@@ -1032,30 +1035,6 @@ class LL2MuMapper:
ops.extend(self.map_op(SpaceOperation('getarraysize', [iref], llop.result)))
return ops
def map_op_cast_pointer(self, llop):
if isinstance(llop.args[0], Constant) and isinstance(llop.args[0].value, mutype.MuType):
DST = llop.args[0].value
assert DST == llop.result.concretetype, \
'cast destination type %s does not match result type %s' % (DST, llop.result.concretetype)
var = llop.args[1]
else:
var = llop.args[0]
DST = llop.result.concretetype
assert var.concretetype.__class__ == llop.result.concretetype.__class__, \
'cannot cast from %s to %s' % (var.concretetype, llop.result.concretetype)
if isinstance(DST, (mutype.MuUPtr, mutype.MuUFuncPtr)):
optr = 'PTRCAST'
else:
optr = 'REFCAST'
return [self.gen_mu_convop(optr, DST, var, llop.result)]
def map_op_cast_opaque_ptr(self, llop):
llop.__init__('cast_pointer', [llop.args[0]], llop.result)
return self.map_op_cast_pointer(llop)
def map_op_ptr_nonzero(self, llop):
Ptr = llop.args[0].concretetype
NULL_c = Constant(Ptr._null(), Ptr)
......@@ -1201,6 +1180,8 @@ class LL2MuMapper:
map_op_raw_memcopy = _map_rawmemop
map_op_raw_memmove = _map_rawmemop
map_op_raw_malloc_usage = _rename_to_same_as
def map_op_free(self, llop):
llop.opname = 'raw_free'
return self.map_op_raw_free(llop)
......@@ -1212,7 +1193,7 @@ class LL2MuMapper:
def map_op_raw_load(self, llop):
ops = []
adr_v, ofs_c = llop.args
assert isinstance(adr_v.concretetype, mutype.MuIntType)
assert adr_v.concretetype == self.map_type(llmemory.Address)
loc_adr = varof(adr_v.concretetype, 'loc_adr')
ops.extend(self.map_op(SpaceOperation('adr_add', [adr_v, ofs_c], loc_adr)))
......@@ -1225,7 +1206,7 @@ class LL2MuMapper:
def map_op_raw_store(self, llop):
ops = []
adr_v, ofs_c, val_vc = llop.args
assert isinstance(adr_v.concretetype, mutype.MuIntType)
assert adr_v.concretetype == self.map_type(llmemory.Address)
loc_adr = varof(adr_v.concretetype, 'loc_adr')
ops.extend(self.map_op(SpaceOperation('adr_add', [adr_v, ofs_c], loc_adr)))
......@@ -1235,6 +1216,36 @@ class LL2MuMapper:
ops.append(self.gen_mu_store(loc_ptr, val_vc, llop.result))
return ops
def map_op_cast_pointer(self, llop):
if isinstance(llop.args[0], Constant) and isinstance(llop.args[0].value, mutype.MuType):
DST = llop.args[0].value
assert DST == llop.result.concretetype, \
'cast destination type %s does not match result type %s' % (DST, llop.result.concretetype)
var = llop.args[1]
else:
var = llop.args[0]
DST = llop.result.concretetype
SRC = var.concretetype
assert not (isinstance(SRC, (mutype.MuUPtr, mutype.MuUFuncPtr)) and
isinstance(DST, (mutype.MuRef, mutype.MuFuncRef))), 'cannot cast from %s to %s' % (SRC, DST)
if type(SRC) == type(DST):
if isinstance(DST, (mutype.MuUPtr, mutype.MuUFuncPtr)):
optr = 'PTRCAST'
else:
optr = 'REFCAST'
return [self.gen_mu_convop(optr, DST, var, llop.result)]
else:
assert isinstance(SRC, mutype.MuRef) and isinstance(DST, mutype.MuUPtr)
# allowing ref -> uptr through pinning
ops = self.map_op_cast_ptr_to_adr(SpaceOperation('cast_ptr_to_adr', [var], llop.result))
return ops
def map_op_cast_opaque_ptr(self, llop):
llop.__init__('cast_pointer', [llop.args[0]], llop.result)
return self.map_op_cast_pointer(llop)
def map_op_cast_ptr_to_adr(self, llop):
ops = []
if isinstance(llop.args[0].concretetype, mutype.MuRef):
......@@ -1263,6 +1274,7 @@ class LL2MuMapper:
map_op_cast_int_to_adr = map_op_cast_adr_to_ptr
def map_op_force_cast(self, llop):
from rpython.rlib.rarithmetic import is_signed_integer_type
SRC = llop.args[0].concretetype
RES = llop.result.concretetype
......@@ -1281,7 +1293,6 @@ class LL2MuMapper:
elif isinstance(SRC, mutype.MuIntType) and isinstance(RES, mutype.MuIntType):
if SRC.BITS < RES.BITS:
if hasattr(llop, '_src_llt'):
from rpython.rlib.rarithmetic import is_signed_integer_type
SRC_LLT = llop._src_llt
use_sext = is_signed_integer_type(SRC_LLT)
else:
......@@ -1294,16 +1305,20 @@ class LL2MuMapper:
return [self.gen_mu_convop(optr, RES, llop.args[0], llop.result)]
elif isinstance(SRC, mutype.MuFloatType) and isinstance(RES, mutype.MuIntType):
if not ((SRC == mutype.MU_DOUBLE and RES == mutype.MU_INT64) or
(SRC == mutype.MU_FLOAT and RES == mutype.MU_INT32)):
raise TypeError("wrong length when casting floating point bytes to integer: %s -> %s" % (SRC, RES))
return [self.gen_mu_convop('BITCAST', RES, llop.args[0], llop.result)]
if hasattr(llop, '_res_llt'):
RES_LLT = llop._res_llt
opcode = 'FPTOSI' if is_signed_integer_type(RES_LLT) else 'FPTOUI'
else:
opcode = 'FPTOSI' # by default
return [self.gen_mu_convop(opcode, RES, llop.args[0], llop.result)]
elif isinstance(SRC, mutype.MuIntType) and isinstance(RES, mutype.MuFloatType):
if not ((RES == mutype.MU_DOUBLE and SRC == mutype.MU_INT64) or
(RES == mutype.MU_FLOAT and SRC == mutype.MU_INT32)):
raise TypeError("wrong length when casting integer bytes to floating point: %s -> %s" % (SRC, RES))
return [self.gen_mu_convop('BITCAST', RES, llop.args[0], llop.result)]
if hasattr(llop, '_src_llt'):
SRC_LLT = llop._src_llt
opcode = 'SITOFP' if is_signed_integer_type(SRC_LLT) else 'UITOFP'
else:
opcode = 'SITOFP' # by default
return [self.gen_mu_convop(opcode, RES, llop.args[0], llop.result)]
elif isinstance(SRC, mutype.MuFloatType) and isinstance(RES, mutype.MuFloatType):
if SRC == mutype.MU_FLOAT and RES == mutype.MU_DOUBLE:
......@@ -1338,8 +1353,8 @@ class LL2MuMapper:
def map_op_gc_load_indexed(self, llop):
ops = []
buf, idx_c, scale_c, base_ofs_c, = llop.args
adr = varof(mutype.MU_INT64)
base_adr = varof(mutype.MU_INT64)
adr = varof(self.map_type(llmemory.Address))
base_adr = varof(self.map_type(llmemory.Address))
ofs = varof(scale_c.concretetype)
llops = [
SpaceOperation('cast_ptr_to_adr', [buf], adr),
......
from rpython.flowspace.model import Variable, Constant, c_last_exception
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.translator.backendopt.removenoops import remove_unaryops
from rpython.translator.backendopt.canraise import RaiseAnalyzer
from rpython.translator.mu import mutype
from rpython.translator.mu.ll2mu import LL2MuMapper, varof
from rpython.rlib.objectmodel import CDefinedIntSymbolic
......@@ -18,6 +19,7 @@ class MuTyper:
self.tlc = tlc
self.ll2mu = LL2MuMapper(tlc.rtyper)
self._objrefid2gcl_dic = {}
self.raise_analyser = RaiseAnalyzer(None) # translator argument not needed I think
def init_threadlocal_struct_type(self):
# determine thread local struct type
......@@ -106,26 +108,34 @@ class MuTyper:
e.exitcase = self.specialise_arg(Constant(e.llexitcase, lltype.typeOf(e.llexitcase)))
defl_exit = next((e for e in blk.exits if e.exitcase == 'default'), cases[-1])
muops.append(self.ll2mu.gen_mu_switch(blk.exitswitch, defl_exit, cases))
elif muops[-1].opname == 'mu_ccall':
# NOTE: CCALL will NEVER throw a Mu exception.
# still not sure why calling a native C library function will throw an RPython exception...
# So in this case just branch the normal case
muops.append(self.ll2mu.gen_mu_branch(blk.exits[0]))
elif muops[-1].opname == 'mu_binop': # binop overflow
from rpython.config.translationoption import get_translation_config
config = get_translation_config()
if config.translation.mu.no_ovf:
# NOTE: if no_ovf flag is set, assume no overflow will happen, always take the default exit
else:
last_op = muops[-1]
try:
assert self.raise_analyser.can_raise(last_op)
if last_op.opname == 'mu_binop':
from rpython.config.translationoption import get_translation_config
config = get_translation_config()
if config.translation.mu.no_ovf:
# NOTE: if no_ovf flag is set, assume no overflow will happen, always take the default exit
muops.append(self.ll2mu.gen_mu_branch(blk.exits[0]))
else:
metainfo = muops[-1].args[-1].value
statres_V = metainfo['status'][1][0] # only V is used at this moment
blk.exitswitch = statres_V
muops.append(self.ll2mu.gen_mu_branch2(blk.exitswitch, blk.exits[1], blk.exits[0]))
else:
# exceptional branching for mu_call
metainfo = muops[-1].args[-1].value
metainfo['excclause'] = self.ll2mu.exc_clause(blk.exits[0], blk.exits[1])
except AssertionError:
# the last operation can't raise exception
# in this case the exception branching is dropped
# (see exceptiontransform.py:271 corresponding behaviour)
# NOTE: in Mu, CCALL will NEVER throw a Mu exception.
# still not sure why calling a native C library function will throw an RPython exception...
# so this case follows dropping the exception branching
assert last_op.opname != 'mu_comminst' # why is COMMINST the last operation?
muops.append(self.ll2mu.gen_mu_branch(blk.exits[0]))
else:
metainfo = muops[-1].args[-1].value
statres_V = metainfo['status'][1][0] # only V is used at this moment
blk.exitswitch = statres_V
muops.append(self.ll2mu.gen_mu_branch2(blk.exitswitch, blk.exits[1], blk.exits[0]))
else: # exceptional branching for mu_call, mu_comminst
metainfo = muops[-1].args[-1].value
metainfo['excclause'] = self.ll2mu.exc_clause(blk.exits[0], blk.exits[1])
muops = muops[:-1] + ldgcell_ops + [muops[-1]]
blk.operations = muops
......
......@@ -24,7 +24,7 @@ def test_collect_global_defs():
assert {Constant(mutype.mu_int64(0), mutype.MU_INT64),
Constant(mutype.mu_int64(3), mutype.MU_INT64)}.issubset(db.consts)
assert len(db.types) == 9 # void, i1, i8, i64, ref<i64>, hyb, ref<hyb>, iref<hyb>, (i64) -> (i64)
assert len(db.types) > 0 # caught some types...
assert len(db.gcells) == 1
assert len(db.objtracer.heap_objs) == 1
......@@ -78,12 +78,11 @@ def exported_symbol_in_dylib(sym_name, libpath):
# use nm program to get a list of symbols in shared library,
# then check if the symbol name is in the list with 'T' (exported symbol)
import subprocess
from rpython.translator.platform import platform
output = str(subprocess.check_output('nm %(flag)s %(libpath)s' % {
'flag': '-D' if platform.name.startswith('linux') else '',
'libpath': libpath
}, shell=True))
return 'T _%(sym_name)s' % locals() in output # exported symbol
from rpython.translator.platform import platform, linux
output = str(subprocess.check_output('nm ' + str(libpath), shell=True))
expected = 'T %s' % '' if isinstance(platform, linux.BaseLinux) else '_'
expected += sym_name
return expected in output # exported symbol
def test_extern_funcs_macro_wrapper():
......@@ -155,6 +154,13 @@ def test_get_type_name():
Point = mutype.MuStruct('Point', ('x', mutype.MU_INT64), ('y', mutype.MU_INT64))
assert man.get_type_name(mutype.MuUPtr(Point)) == '@ptrstt0'
man = MuNameManager() # a new instance to clear cache
man.verbose_type_name = True # manually set it to true
assert man.get_type_name(mutype.MuUPtr(Point)) == '@ptrsttPoint'
String = mutype.MuHybrid('String', ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8))
assert man.get_type_name(String) == '@hybString'
Points = mutype.MuArray(Point, 5)
assert man.get_type_name(Points) == '@arr5sttPoint'
def test_get_const_name():
man = MuNameManager()
......@@ -181,4 +187,8 @@ def test_assign_mu_name():
assert '@fnrsig_i64_i64' in names
assert '@fac_0' in names
assert '@fac_0.blk0' in names
assert '@fac_0.blk0.n_0' in names
g = graph_of(fac, t)
n = db.mu_name_map.get(g.startblock.inputargs[0])
assert n
assert n.startswith('@fac_0.blk0.n')
......@@ -71,8 +71,7 @@ def test_no_ovf_flag():
except OverflowError:
raise MemoryError
t = Translation(f, [int, int],
backend='mu', impl='zebu', no_ovf=True)
t = Translation(f, [int, int], backend='mu', no_ovf=True)
t.compile_mu()
graph_f = graph_of(f, t)
# graph_f.view()
......@@ -270,3 +269,45 @@ def test_debug():