MCPcopy Create free account
hub / github.com/NVIDIA/cuda-quantum / visit_FunctionDef

Method visit_FunctionDef

python/cudaq/kernel/ast_bridge.py:1787–1928  ·  view source on GitHub ↗

Create an MLIR `func.FuncOp` for the given FunctionDef AST node. For the top-level FunctionDef, this will add the `FuncOp` to the `ModuleOp` body, annotate the `FuncOp` with `cudaq-entrypoint` if it is an Entry Point CUDA-Q kernel, and visit the rest of the FunctionDef body.

(self, node)

Source from the content-addressed store, hash-verified

1785
1786 @trace.traced("ast_bridge.visit_function_def")
1787 def visit_FunctionDef(self, node):
1788 """Create an MLIR `func.FuncOp` for the given FunctionDef AST node. For
1789 the top-level FunctionDef, this will add the `FuncOp` to the `ModuleOp`
1790 body, annotate the `FuncOp` with `cudaq-entrypoint` if it is an Entry
1791 Point CUDA-Q kernel, and visit the rest of the FunctionDef body. If this
1792 is an inner FunctionDef, this will treat the function as a CC lambda
1793 function and add the cc.callable-typed value to the symbol table, keyed
1794 on the FunctionDef name.
1795
1796 We keep track of the top-level function name as well as its internal
1797 MLIR name, prefixed with the __nvqpp__mlirgen__ prefix.
1798 """
1799
1800 if self.buildingFunctionBody:
1801 for decorator in getattr(node, 'decorator_list', []):
1802 qname = _get_qualified_name(decorator)
1803 if qname == 'kernel' or (
1804 qname is not None and qname.endswith('.kernel') and
1805 self.isCudaqName(qname[:qname.rfind('.kernel')])):
1806 self.emitFatalError(
1807 "nested @cudaq.kernel definitions are not allowed",
1808 node)
1809
1810 # This is an inner function def, we will treat it as a cc.callable
1811 # (cc.create_lambda)
1812 self.debug_msg(lambda: f'Visiting inner FunctionDef {node.name}')
1813 lambdaFct = self.__createFunctionWithinKernel(
1814 node.args.args, node.body)
1815 assignNode = ast.Assign()
1816 assignNode.targets = [ast.Name(node.name)]
1817 assignNode.value = lambdaFct
1818 assignNode.lineno = node.lineno
1819 self.visit_Assign(assignNode)
1820 return
1821
1822 with self.ctx, InsertionPoint(self.module.body), self.loc:
1823
1824 # Get the potential documentation string
1825 self.docstring = ast.get_docstring(node)
1826
1827 # Add uniqueness. In MLIR, we require unique symbols (`bijective`
1828 # function between symbols and artifacts) even if Python allows
1829 # hiding symbols and replacing symbols (dynamic `injective` function
1830 # between scoped symbols and artifacts).
1831 self.name = node.name + ".." + hex(self.uniqueId)
1832
1833 # the full function name in MLIR is `__nvqpp__mlirgen__` + the
1834 # function name
1835 fullName = nvqppPrefix + self.name
1836
1837 # Determine whether this kernel will be an entry point (no quantum
1838 # types in the signature). Run this check before creating the
1839 # `FuncOp` so a rejection does not leave an orphaned op in the module.
1840 anyQuantumType = any(
1841 self.isQuantumType(ty) for ty in self.signature.arg_types)
1842 if not anyQuantumType:
1843 # `cudaq::measure_handle` is device-only and must not appear
1844 # either directly or transitively in the parameter or return

Callers

nothing calls this directly

Calls 15

isCudaqNameMethod · 0.95
emitFatalErrorMethod · 0.95
debug_msgMethod · 0.95
visit_AssignMethod · 0.95
isQuantumTypeMethod · 0.95
visitMethod · 0.95
hasTerminatorMethod · 0.95
_get_qualified_nameFunction · 0.85
get_lifted_typeMethod · 0.80
__setitem__Method · 0.80
pushScopeMethod · 0.80

Tested by

no test coverage detected