compiler: T{C -> External}Function, clarify docs [nfc]

This commit is contained in:
David Nadlinger 2020-08-02 13:42:24 +01:00
parent da255bee1b
commit d37503f21d
6 changed files with 34 additions and 23 deletions

View File

@ -334,6 +334,6 @@ def is_allocated(typ):
return not (is_none(typ) or is_bool(typ) or is_int(typ) or return not (is_none(typ) or is_bool(typ) or is_int(typ) or
is_float(typ) or is_range(typ) or is_float(typ) or is_range(typ) or
types._is_pointer(typ) or types.is_function(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_method(typ) or types.is_tuple(typ) or
types.is_value(typ)) types.is_value(typ))

View File

@ -1001,7 +1001,7 @@ class Stitcher:
self.engine.process(diag) self.engine.process(diag)
ret_type = types.TVar() ret_type = types.TVar()
function_type = types.TCFunction(arg_types, ret_type, function_type = types.TExternalFunction(arg_types, ret_type,
name=function.artiq_embedded.syscall, name=function.artiq_embedded.syscall,
flags=function.artiq_embedded.flags) flags=function.artiq_embedded.flags)
self.functions[function] = function_type self.functions[function] = function_type

View File

@ -2137,7 +2137,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
assert None not in args assert None not in args
if self.unwind_target is None or \ 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)) insn = self.append(ir.Call(func, args, arg_exprs))
else: else:
after_invoke = self.add_block("invoke") after_invoke = self.add_block("invoke")

View File

@ -205,7 +205,7 @@ class LLVMIRGenerator:
typ = typ.find() typ = typ.find()
if types.is_tuple(typ): if types.is_tuple(typ):
return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.elts]) 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: if for_return:
return llvoid return llvoid
else: else:
@ -838,7 +838,7 @@ class LLVMIRGenerator:
closure_type = typ.attributes[attr] closure_type = typ.attributes[attr]
assert types.is_constructor(typ) assert types.is_constructor(typ)
assert types.is_function(closure_type) or types.is_rpc(closure_type) 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 return None
llty = self.llty_of_type(typ.attributes[attr]) llty = self.llty_of_type(typ.attributes[attr])
@ -1443,7 +1443,7 @@ class LLVMIRGenerator:
functiontyp, functiontyp,
insn.arguments(), insn.arguments(),
llnormalblock=None, llunwindblock=None) llnormalblock=None, llunwindblock=None)
elif types.is_c_function(functiontyp): elif types.is_external_function(functiontyp):
llfun, llargs = self._prepare_ffi_call(insn) llfun, llargs = self._prepare_ffi_call(insn)
else: else:
llfun, llargs = self._prepare_closure_call(insn) llfun, llargs = self._prepare_closure_call(insn)
@ -1466,7 +1466,7 @@ class LLVMIRGenerator:
# Never add TBAA nowrite metadata to a functon with sret! # Never add TBAA nowrite metadata to a functon with sret!
# This leads to miscompilations. # 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) llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
return llresult return llresult
@ -1480,7 +1480,7 @@ class LLVMIRGenerator:
functiontyp, functiontyp,
insn.arguments(), insn.arguments(),
llnormalblock, llunwindblock) llnormalblock, llunwindblock)
elif types.is_c_function(functiontyp): elif types.is_external_function(functiontyp):
llfun, llargs = self._prepare_ffi_call(insn) llfun, llargs = self._prepare_ffi_call(insn)
else: else:
llfun, llargs = self._prepare_closure_call(insn) llfun, llargs = self._prepare_closure_call(insn)
@ -1530,7 +1530,7 @@ class LLVMIRGenerator:
attrvalue = getattr(value, attr) attrvalue = getattr(value, attr)
is_class_function = (types.is_constructor(typ) and is_class_function = (types.is_constructor(typ) and
types.is_function(typ.attributes[attr]) 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: if is_class_function:
attrvalue = self.embedding_map.specialize_function(typ.instance, attrvalue) attrvalue = self.embedding_map.specialize_function(typ.instance, attrvalue)
if not (types.is_instance(typ) and attr in typ.constant_attributes): 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)]) llelts = [self._quote(v, t, lambda: path() + [str(i)])
for i, (v, t) in enumerate(zip(value, typ.elts))] for i, (v, t) in enumerate(zip(value, typ.elts))]
return ll.Constant(llty, llelts) 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. # RPC, C and builtin functions have no runtime representation.
return ll.Constant(llty, ll.Undefined) return ll.Constant(llty, ll.Undefined)
elif types.is_function(typ): elif types.is_function(typ):

View File

@ -283,12 +283,18 @@ class TFunction(Type):
def __hash__(self): def __hash__(self):
return hash((_freeze(self.args), _freeze(self.optargs), self.ret)) 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 This can be any function following the C ABI, such as provided by the
:ivar flags: (set of str) C function flags. 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 ``nounwind`` means the function never raises an exception.
Flag ``nowrite`` means the function never writes any memory Flag ``nowrite`` means the function never writes any memory
that the ARTIQ Python code can observe. that the ARTIQ Python code can observe.
@ -308,7 +314,7 @@ class TCFunction(TFunction):
def unify(self, other): def unify(self, other):
if other is self: if other is self:
return return
if isinstance(other, TCFunction) and \ if isinstance(other, TExternalFunction) and \
self.name == other.name: self.name == other.name:
super().unify(other) super().unify(other)
elif isinstance(other, TVar): elif isinstance(other, TVar):
@ -404,6 +410,11 @@ class TBuiltin(Type):
class TBuiltinFunction(TBuiltin): class TBuiltinFunction(TBuiltin):
""" """
A type of a builtin function. 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): class TConstructor(TBuiltin):
@ -609,12 +620,12 @@ def is_function(typ):
def is_rpc(typ): def is_rpc(typ):
return isinstance(typ.find(), TRPC) return isinstance(typ.find(), TRPC)
def is_c_function(typ, name=None): def is_external_function(typ, name=None):
typ = typ.find() typ = typ.find()
if name is None: if name is None:
return isinstance(typ, TCFunction) return isinstance(typ, TExternalFunction)
else: else:
return isinstance(typ, TCFunction) and \ return isinstance(typ, TExternalFunction) and \
typ.name == name typ.name == name
def is_builtin(typ, name=None): def is_builtin(typ, name=None):
@ -744,7 +755,7 @@ class TypePrinter(object):
return "(%s,)" % self.name(typ.elts[0], depth + 1) return "(%s,)" % self.name(typ.elts[0], depth + 1)
else: else:
return "(%s)" % ", ".join([self.name(typ, depth + 1) for typ in typ.elts]) 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 = []
args += [ "%s:%s" % (arg, self.name(typ.args[arg], depth + 1)) args += [ "%s:%s" % (arg, self.name(typ.args[arg], depth + 1))
for arg in typ.args] for arg in typ.args]
@ -758,7 +769,7 @@ class TypePrinter(object):
elif not (delay.is_fixed() and iodelay.is_zero(delay.duration)): elif not (delay.is_fixed() and iodelay.is_zero(delay.duration)):
signature += " " + self.name(delay, depth + 1) signature += " " + self.name(delay, depth + 1)
if isinstance(typ, TCFunction): if isinstance(typ, TExternalFunction):
return "[ffi {}]{}".format(repr(typ.name), signature) return "[ffi {}]{}".format(repr(typ.name), signature)
elif isinstance(typ, TFunction): elif isinstance(typ, TFunction):
return signature return signature

View File

@ -99,7 +99,7 @@ class RegionOf(algorithm.Visitor):
visit_BinOpT = visit_sometimes_allocating visit_BinOpT = visit_sometimes_allocating
def visit_CallT(self, node): 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 # The cache is borrow checked dynamically
return Global() return Global()
else: else: