Author: Manuel Jacob
Branch: llvm-translation-backend
Changeset: r68802:e4ab9d710ba1
Date: 2014-01-21 11:50 +0100
http://bitbucket.org/pypy/pypy/changeset/e4ab9d710ba1/
Log: Instead of marking every llexternal that calls a macro with a macro
flag, we generate call wrappers for external functions by default. A
call wrapper is a short C snippet that just calls the external
function. This way we work on the API level instead of the ABI
level, because the C compiler generates the actual code to call the
external function. These functions are inlined because we use link-
time optimization. One problem is currently that the call wrappers
are not stripped from the binary.
diff --git a/pypy/module/_cffi_backend/misc.py
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -238,7 +238,7 @@
_is_nonnull_longdouble = rffi.llexternal(
"pypy__is_nonnull_longdouble", [rffi.LONGDOUBLE], lltype.Bool,
compilation_info=eci, _nowrapper=True, elidable_function=True,
- sandboxsafe=True, macro=True)
+ sandboxsafe=True)
# split here for JIT backends that don't support floats/longlongs/etc.
def is_nonnull_longdouble(cdata):
diff --git a/rpython/jit/backend/x86/valgrind.py
b/rpython/jit/backend/x86/valgrind.py
--- a/rpython/jit/backend/x86/valgrind.py
+++ b/rpython/jit/backend/x86/valgrind.py
@@ -21,8 +21,7 @@
lltype.Void,
compilation_info=eci,
_nowrapper=True,
- sandboxsafe=True,
- macro=True)
+ sandboxsafe=True)
# ____________________________________________________________
diff --git a/rpython/rlib/longlong2float.py b/rpython/rlib/longlong2float.py
--- a/rpython/rlib/longlong2float.py
+++ b/rpython/rlib/longlong2float.py
@@ -68,14 +68,12 @@
uint2singlefloat = rffi.llexternal(
"pypy__uint2singlefloat", [rffi.UINT], rffi.FLOAT,
_callable=uint2singlefloat_emulator, compilation_info=eci,
- _nowrapper=True, elidable_function=True, sandboxsafe=True,
- llvm_wrapper=True)
+ _nowrapper=True, elidable_function=True, sandboxsafe=True)
singlefloat2uint = rffi.llexternal(
"pypy__singlefloat2uint", [rffi.FLOAT], rffi.UINT,
_callable=singlefloat2uint_emulator, compilation_info=eci,
- _nowrapper=True, elidable_function=True, sandboxsafe=True,
- llvm_wrapper=True)
+ _nowrapper=True, elidable_function=True, sandboxsafe=True)
class Float2LongLongEntry(ExtRegistryEntry):
diff --git a/rpython/rlib/rmd5.py b/rpython/rlib/rmd5.py
--- a/rpython/rlib/rmd5.py
+++ b/rpython/rlib/rmd5.py
@@ -51,7 +51,7 @@
_rotateLeft = rffi.llexternal(
"pypy__rotateLeft", [lltype.Unsigned, lltype.Signed], lltype.Unsigned,
_callable=_rotateLeft_emulator, compilation_info=eci,
- _nowrapper=True, elidable_function=True, llvm_wrapper=True)
+ _nowrapper=True, elidable_function=True)
# we expect the function _rotateLeft to be actually inlined
diff --git a/rpython/rlib/rstack.py b/rpython/rlib/rstack.py
--- a/rpython/rlib/rstack.py
+++ b/rpython/rlib/rstack.py
@@ -20,15 +20,15 @@
includes=['src/stack.h'],
separate_module_files=[srcdir / 'stack.c', srcdir / 'threadlocal.c'])
-def llexternal(name, args, res, _callable=None, macro=None):
+def llexternal(name, args, res, _callable=None):
return rffi.llexternal(name, args, res, compilation_info=compilation_info,
sandboxsafe=True, _nowrapper=True,
- _callable=_callable, macro=macro)
+ _callable=_callable)
_stack_get_end = llexternal('LL_stack_get_end', [], lltype.Signed,
- lambda: 0, True)
+ lambda: 0)
_stack_get_length = llexternal('LL_stack_get_length', [], lltype.Signed,
- lambda: 1, True)
+ lambda: 1)
_stack_set_length_fraction = llexternal('LL_stack_set_length_fraction',
[lltype.Float], lltype.Void,
lambda frac: None)
@@ -36,17 +36,15 @@
[lltype.Signed], lltype.Char,
lambda cur: '\x00')
# the following is used by the JIT
-_stack_get_end_adr = llexternal('LL_stack_get_end_adr', [], lltype.Signed,
- macro=True)
-_stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed,
- macro=True)
+_stack_get_end_adr = llexternal('LL_stack_get_end_adr', [], lltype.Signed)
+_stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed)
# the following is also used by the JIT: "critical code" paths are paths in
# which we should not raise StackOverflow at all, but just ignore the stack
limit
_stack_criticalcode_start = llexternal('LL_stack_criticalcode_start', [],
- lltype.Void, lambda: None, True)
+ lltype.Void, lambda: None)
_stack_criticalcode_stop = llexternal('LL_stack_criticalcode_stop', [],
- lltype.Void, lambda: None, True)
+ lltype.Void, lambda: None)
def stack_check():
if not we_are_translated():
diff --git a/rpython/rtyper/lltypesystem/llarena.py
b/rpython/rtyper/lltypesystem/llarena.py
--- a/rpython/rtyper/lltypesystem/llarena.py
+++ b/rpython/rtyper/lltypesystem/llarena.py
@@ -602,7 +602,6 @@
lltype.Signed,
sandboxsafe=True,
_nowrapper=True,
- macro=True,
compilation_info=_eci)
register_external(_round_up_for_allocation, [int, int], int,
'll_arena.round_up_for_allocation',
diff --git a/rpython/rtyper/lltypesystem/rffi.py
b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -63,8 +63,7 @@
sandboxsafe=False, releasegil='auto',
_nowrapper=False, calling_conv='c',
elidable_function=False, macro=None,
- random_effects_on_gcobjs='auto',
- llvm_wrapper=None):
+ random_effects_on_gcobjs='auto'):
"""Build an external function that will invoke the C function 'name'
with the given 'args' types and 'result' type.
@@ -84,14 +83,9 @@
don't bother releasing the GIL. An explicit True or False
overrides this logic.
macro: whether to write a macro wrapper for this function. This is
- necessary for calling macros in tests or when using the llvm
- translation backend. Setting it to True generates a macro wrapper
- named '_rpy_call_wrapper_{name}'. Setting it to a string
- generates a macro wrapper named '_rpy_call_wrapper_{macro}'.
- llvm_wrapper: same semantics as macro but for calling ordinary functions
- that the llvm translation backend can't handle, for example
- static functions defined in ExternalCompilationInfo's
- post_include_bits or functions with varargs.
+ necessary for calling macros in tests. Setting it to True generates
+ a macro wrapper named '_rpy_call_wrapper_{name}'. Setting it to a
+ string generates a macro wrapper named '_rpy_call_wrapper_{macro}'.
"""
if _callable is not None:
assert callable(_callable)
@@ -130,11 +124,6 @@
invoke_around_handlers or # because it can release the GIL
has_callback) # because the callback can do it
- if llvm_wrapper is None:
- llvm_wrapper = macro
- if llvm_wrapper is not None:
- kwds['llvm_wrapper'] = llvm_wrapper
-
funcptr = lltype.functionptr(ext_type, name, external='C',
compilation_info=compilation_info,
_callable=_callable,
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py
b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -47,7 +47,7 @@
eci = ExternalCompilationInfo(includes=['stuff.h'],
include_dirs=[udir])
- z = llexternal('X', [Signed], Signed, compilation_info=eci, macro=True)
+ z = llexternal('X', [Signed], Signed, compilation_info=eci)
def f():
return z(8)
@@ -298,7 +298,7 @@
STUFFP = COpaquePtr(typedef='stuff_ptr', compilation_info=eci)
ll_get = llexternal('get', [STUFFP], lltype.Signed,
- compilation_info=eci, llvm_wrapper=True)
+ compilation_info=eci)
def f():
return ll_get(lltype.nullptr(STUFFP.TO))
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -22,7 +22,7 @@
from rpython.rtyper.tool import rffi_platform as platform
from rpython.rlib import rposix
from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem.llmemory import itemoffsetof, offsetof,
Address
+from rpython.rtyper.lltypesystem.llmemory import itemoffsetof, offsetof
from rpython.rtyper.lltypesystem.rstr import STR
from rpython.rlib.objectmodel import specialize
@@ -977,8 +977,7 @@
@registering_if(os, 'makedev')
def register_os_makedev(self):
- c_makedev = self.llexternal('makedev', [rffi.INT, rffi.INT], rffi.INT,
- macro=True)
+ c_makedev = self.llexternal('makedev', [rffi.INT, rffi.INT], rffi.INT)
def makedev_llimpl(maj, min):
return c_makedev(maj, min)
return extdef([int, int], int,
@@ -986,7 +985,7 @@
@registering_if(os, 'major')
def register_os_major(self):
- c_major = self.llexternal('major', [rffi.INT], rffi.INT, macro=True)
+ c_major = self.llexternal('major', [rffi.INT], rffi.INT)
def major_llimpl(dev):
return c_major(dev)
return extdef([int], int,
@@ -994,7 +993,7 @@
@registering_if(os, 'minor')
def register_os_minor(self):
- c_minor = self.llexternal('minor', [rffi.INT], rffi.INT, macro=True)
+ c_minor = self.llexternal('minor', [rffi.INT], rffi.INT)
def minor_llimpl(dev):
return c_minor(dev)
return extdef([int], int,
@@ -1030,7 +1029,7 @@
@registering(os.write)
def register_os_write(self):
os_write = self.llexternal(UNDERSCORE_ON_WIN32 + 'write',
- [rffi.INT, Address, rffi.SIZE_T],
+ [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
rffi.SIZE_T)
def os_write_llimpl(fd, data):
@@ -1040,8 +1039,7 @@
try:
written = rffi.cast(lltype.Signed, os_write(
rffi.cast(rffi.INT, fd),
- rffi.cast(Address, buf),
- rffi.cast(rffi.SIZE_T, count)))
+ buf, rffi.cast(rffi.SIZE_T, count)))
if written < 0:
raise OSError(rposix.get_errno(), "os_write failed")
finally:
diff --git a/rpython/translator/llvm/genllvm.py
b/rpython/translator/llvm/genllvm.py
--- a/rpython/translator/llvm/genllvm.py
+++ b/rpython/translator/llvm/genllvm.py
@@ -656,35 +656,18 @@
def repr_ref(self, ptr_type, obj):
if getattr(obj, 'external', None) == 'C':
- if hasattr(obj, 'llvm_wrapper'):
+ if obj._name.startswith('llvm'):
+ name = '@' + obj._name
+ else:
wrapper_name, source = rffi._write_call_wrapper(
- obj._name, obj.llvm_wrapper, obj._TYPE)
+ obj._name, database.unique_name(obj._name, False),
+ obj._TYPE)
name = '@' + wrapper_name
database.genllvm.sources.append(source)
- else:
- name = '@' + obj._name
- # Hack to support functions with different function signatures
- prev_type = database.external_declared.get(name)
- if prev_type is None:
- database.external_declared[name] = self
- elif prev_type is self:
- ptr_type.refs[obj] = name
- return
- else:
- ptr_type.refs[obj] = 'bitcast({}* {} to {}*)'.format(
- prev_type.repr_type(), name, self.repr_type())
- return
ptr_type.refs[obj] = name
- if obj.calling_conv == 'c':
- calling_conv = ''
- elif obj.calling_conv == 'win':
- # assume that x86_stdcallcc implies dllimport
- calling_conv = 'dllimport x86_stdcallcc '
- else:
- raise NotImplementedError
- database.f.write('declare {}{} {}({})\n'.format(
- calling_conv, self.result.repr_type(), name,
+ database.f.write('declare {} {}({})\n'.format(
+ self.result.repr_type(), name,
', '.join(arg.repr_type() for arg in self.args)))
database.genllvm.ecis.append(obj.compilation_info)
else:
@@ -740,7 +723,6 @@
self.f = f
self.names_counter = {}
self.types = PRIMITIVES.copy()
- self.external_declared = {}
self.hashes = []
self.stack_bottoms = []
@@ -764,14 +746,15 @@
.get_gc_fields_lltype() # hint for ll2ctypes
return ret
- def unique_name(self, name):
+ def unique_name(self, name, llvm_name=True):
if name not in self.names_counter:
self.names_counter[name] = 0
- if self.identifier_regex.match(name) is None:
+ if llvm_name and self.identifier_regex.match(name) is None:
return '{}"{}"'.format(name[0], name[1:])
return name
self.names_counter[name] += 1
- return self.unique_name('{}_{}'.format(name, self.names_counter[name]))
+ return self.unique_name('{}_{}'.format(name, self.names_counter[name]),
+ llvm_name)
OPS = {
@@ -1148,19 +1131,13 @@
tmp.append('{arg.TV}'.format(arg=arg))
args = ', '.join(tmp)
- if (isinstance(fn, ConstantRepr) and
- getattr(fn.value._obj, 'calling_conv', None) == 'win'):
- calling_conv = 'x86_stdcallcc '
- else:
- calling_conv = ''
-
if result.type_ is LLVMVoid:
- fmt = 'call {calling_conv}void {fn.V}({args})'
+ fmt = 'call void {fn.V}({args})'
elif (isinstance(result.type_, PtrType) and
isinstance(result.type_.to, FuncType)):
- fmt = '{result.V} = call {calling_conv}{fn.TV}({args})'
+ fmt = '{result.V} = call {fn.TV}({args})'
else:
- fmt = '{result.V} = call {calling_conv}{result.T} {fn.V}({args})'
+ fmt = '{result.V} = call {result.T} {fn.V}({args})'
self.w(fmt.format(**locals()))
op_indirect_call = op_direct_call
@@ -1764,15 +1741,14 @@
exports.clear()
def _compile(self, shared=False):
- self.sources.append(py.code.Source(r'''
+ self.sources.append(str(py.code.Source(r'''
void pypy_debug_catch_fatal_exception(void) {
fprintf(stderr, "Fatal RPython error\n");
abort();
- }
- '''))
+ }''')))
eci = ExternalCompilationInfo(
includes=['stdio.h', 'stdlib.h'],
- separate_module_sources=self.sources,
+ separate_module_sources=['\n'.join(self.sources)],
post_include_bits=['typedef _Bool bool_t;']
).merge(*self.ecis).convert_sources_to_files()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit