forked from M-Labs/artiq
compiler: T{C -> External}Function, clarify docs [nfc]
This commit is contained in:
parent
da255bee1b
commit
d37503f21d
|
@ -334,6 +334,6 @@ def is_allocated(typ):
|
|||
return not (is_none(typ) or is_bool(typ) or is_int(typ) or
|
||||
is_float(typ) or is_range(typ) or
|
||||
types._is_pointer(typ) or types.is_function(typ) or
|
||||
types.is_c_function(typ) or types.is_rpc(typ) or
|
||||
types.is_external_function(typ) or types.is_rpc(typ) or
|
||||
types.is_method(typ) or types.is_tuple(typ) or
|
||||
types.is_value(typ))
|
||||
|
|
|
@ -1001,9 +1001,9 @@ class Stitcher:
|
|||
self.engine.process(diag)
|
||||
ret_type = types.TVar()
|
||||
|
||||
function_type = types.TCFunction(arg_types, ret_type,
|
||||
name=function.artiq_embedded.syscall,
|
||||
flags=function.artiq_embedded.flags)
|
||||
function_type = types.TExternalFunction(arg_types, ret_type,
|
||||
name=function.artiq_embedded.syscall,
|
||||
flags=function.artiq_embedded.flags)
|
||||
self.functions[function] = function_type
|
||||
return function_type
|
||||
|
||||
|
|
|
@ -2137,7 +2137,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
assert None not in args
|
||||
|
||||
if self.unwind_target is None or \
|
||||
types.is_c_function(callee.type) and "nounwind" in callee.type.flags:
|
||||
types.is_external_function(callee.type) and "nounwind" in callee.type.flags:
|
||||
insn = self.append(ir.Call(func, args, arg_exprs))
|
||||
else:
|
||||
after_invoke = self.add_block("invoke")
|
||||
|
|
|
@ -205,7 +205,7 @@ class LLVMIRGenerator:
|
|||
typ = typ.find()
|
||||
if types.is_tuple(typ):
|
||||
return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.elts])
|
||||
elif types.is_rpc(typ) or types.is_c_function(typ):
|
||||
elif types.is_rpc(typ) or types.is_external_function(typ):
|
||||
if for_return:
|
||||
return llvoid
|
||||
else:
|
||||
|
@ -838,7 +838,7 @@ class LLVMIRGenerator:
|
|||
closure_type = typ.attributes[attr]
|
||||
assert types.is_constructor(typ)
|
||||
assert types.is_function(closure_type) or types.is_rpc(closure_type)
|
||||
if types.is_c_function(closure_type) or types.is_rpc(closure_type):
|
||||
if types.is_external_function(closure_type) or types.is_rpc(closure_type):
|
||||
return None
|
||||
|
||||
llty = self.llty_of_type(typ.attributes[attr])
|
||||
|
@ -1443,7 +1443,7 @@ class LLVMIRGenerator:
|
|||
functiontyp,
|
||||
insn.arguments(),
|
||||
llnormalblock=None, llunwindblock=None)
|
||||
elif types.is_c_function(functiontyp):
|
||||
elif types.is_external_function(functiontyp):
|
||||
llfun, llargs = self._prepare_ffi_call(insn)
|
||||
else:
|
||||
llfun, llargs = self._prepare_closure_call(insn)
|
||||
|
@ -1466,7 +1466,7 @@ class LLVMIRGenerator:
|
|||
|
||||
# Never add TBAA nowrite metadata to a functon with sret!
|
||||
# This leads to miscompilations.
|
||||
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
||||
if types.is_external_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
||||
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
|
||||
|
||||
return llresult
|
||||
|
@ -1480,7 +1480,7 @@ class LLVMIRGenerator:
|
|||
functiontyp,
|
||||
insn.arguments(),
|
||||
llnormalblock, llunwindblock)
|
||||
elif types.is_c_function(functiontyp):
|
||||
elif types.is_external_function(functiontyp):
|
||||
llfun, llargs = self._prepare_ffi_call(insn)
|
||||
else:
|
||||
llfun, llargs = self._prepare_closure_call(insn)
|
||||
|
@ -1530,7 +1530,7 @@ class LLVMIRGenerator:
|
|||
attrvalue = getattr(value, attr)
|
||||
is_class_function = (types.is_constructor(typ) and
|
||||
types.is_function(typ.attributes[attr]) and
|
||||
not types.is_c_function(typ.attributes[attr]))
|
||||
not types.is_external_function(typ.attributes[attr]))
|
||||
if is_class_function:
|
||||
attrvalue = self.embedding_map.specialize_function(typ.instance, attrvalue)
|
||||
if not (types.is_instance(typ) and attr in typ.constant_attributes):
|
||||
|
@ -1600,7 +1600,7 @@ class LLVMIRGenerator:
|
|||
llelts = [self._quote(v, t, lambda: path() + [str(i)])
|
||||
for i, (v, t) in enumerate(zip(value, typ.elts))]
|
||||
return ll.Constant(llty, llelts)
|
||||
elif types.is_rpc(typ) or types.is_c_function(typ) or types.is_builtin_function(typ):
|
||||
elif types.is_rpc(typ) or types.is_external_function(typ) or types.is_builtin_function(typ):
|
||||
# RPC, C and builtin functions have no runtime representation.
|
||||
return ll.Constant(llty, ll.Undefined)
|
||||
elif types.is_function(typ):
|
||||
|
|
|
@ -283,12 +283,18 @@ class TFunction(Type):
|
|||
def __hash__(self):
|
||||
return hash((_freeze(self.args), _freeze(self.optargs), self.ret))
|
||||
|
||||
class TCFunction(TFunction):
|
||||
class TExternalFunction(TFunction):
|
||||
"""
|
||||
A function type of a runtime-provided C function.
|
||||
A type of an externally-provided function.
|
||||
|
||||
:ivar name: (str) C function name
|
||||
:ivar flags: (set of str) C function flags.
|
||||
This can be any function following the C ABI, such as provided by the
|
||||
C/Rust runtime, or a compiler backend intrinsic. The mangled name to link
|
||||
against is encoded as part of the type.
|
||||
|
||||
:ivar name: (str) external symbol name.
|
||||
This will be the symbol linked against (following any extra C name
|
||||
mangling rules).
|
||||
:ivar flags: (set of str) function flags.
|
||||
Flag ``nounwind`` means the function never raises an exception.
|
||||
Flag ``nowrite`` means the function never writes any memory
|
||||
that the ARTIQ Python code can observe.
|
||||
|
@ -308,7 +314,7 @@ class TCFunction(TFunction):
|
|||
def unify(self, other):
|
||||
if other is self:
|
||||
return
|
||||
if isinstance(other, TCFunction) and \
|
||||
if isinstance(other, TExternalFunction) and \
|
||||
self.name == other.name:
|
||||
super().unify(other)
|
||||
elif isinstance(other, TVar):
|
||||
|
@ -404,6 +410,11 @@ class TBuiltin(Type):
|
|||
class TBuiltinFunction(TBuiltin):
|
||||
"""
|
||||
A type of a builtin function.
|
||||
|
||||
Builtin functions are treated specially throughout all stages of the
|
||||
compilation process according to their name (e.g. calls may not actually
|
||||
lower to a function call). See :class:`TExternalFunction` for externally
|
||||
defined functions that are otherwise regular.
|
||||
"""
|
||||
|
||||
class TConstructor(TBuiltin):
|
||||
|
@ -609,12 +620,12 @@ def is_function(typ):
|
|||
def is_rpc(typ):
|
||||
return isinstance(typ.find(), TRPC)
|
||||
|
||||
def is_c_function(typ, name=None):
|
||||
def is_external_function(typ, name=None):
|
||||
typ = typ.find()
|
||||
if name is None:
|
||||
return isinstance(typ, TCFunction)
|
||||
return isinstance(typ, TExternalFunction)
|
||||
else:
|
||||
return isinstance(typ, TCFunction) and \
|
||||
return isinstance(typ, TExternalFunction) and \
|
||||
typ.name == name
|
||||
|
||||
def is_builtin(typ, name=None):
|
||||
|
@ -744,7 +755,7 @@ class TypePrinter(object):
|
|||
return "(%s,)" % self.name(typ.elts[0], depth + 1)
|
||||
else:
|
||||
return "(%s)" % ", ".join([self.name(typ, depth + 1) for typ in typ.elts])
|
||||
elif isinstance(typ, (TFunction, TCFunction)):
|
||||
elif isinstance(typ, (TFunction, TExternalFunction)):
|
||||
args = []
|
||||
args += [ "%s:%s" % (arg, self.name(typ.args[arg], depth + 1))
|
||||
for arg in typ.args]
|
||||
|
@ -758,7 +769,7 @@ class TypePrinter(object):
|
|||
elif not (delay.is_fixed() and iodelay.is_zero(delay.duration)):
|
||||
signature += " " + self.name(delay, depth + 1)
|
||||
|
||||
if isinstance(typ, TCFunction):
|
||||
if isinstance(typ, TExternalFunction):
|
||||
return "[ffi {}]{}".format(repr(typ.name), signature)
|
||||
elif isinstance(typ, TFunction):
|
||||
return signature
|
||||
|
|
|
@ -99,7 +99,7 @@ class RegionOf(algorithm.Visitor):
|
|||
visit_BinOpT = visit_sometimes_allocating
|
||||
|
||||
def visit_CallT(self, node):
|
||||
if types.is_c_function(node.func.type, "cache_get"):
|
||||
if types.is_external_function(node.func.type, "cache_get"):
|
||||
# The cache is borrow checked dynamically
|
||||
return Global()
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue