def decorate_function(self, fn, args, fe_argtypes, noalias=False):
        """
        Set names of function arguments, and add useful attributes to them.
        """
        arginfo = self._get_arg_packer(fe_argtypes)
        arginfo.assign_names(self.get_arguments(fn),
                             ['arg.' + a for a in args])
        retarg = self._get_return_argument(fn)
        retarg.name = "retptr"
        retarg.add_attribute("nocapture")
        retarg.add_attribute("noalias")
        excarg = self._get_excinfo_argument(fn)
        excarg.name = "excinfo"
        excarg.add_attribute("nocapture")
        excarg.add_attribute("noalias")

        if noalias:
            args = self.get_arguments(fn)
            for a in args:
                if isinstance(a.type, ir.PointerType):
                    a.add_attribute("nocapture")
                    a.add_attribute("noalias")

        # Add metadata to mark functions that may need NRT
        # thus disabling aggressive refct pruning in removerefctpass.py
        def type_may_always_need_nrt(ty):
            # Returns True if it's a non-Array type that is contains MemInfo
            if not isinstance(ty, types.Array):
                dmm = self.context.data_model_manager
                if dmm[ty].contains_nrt_meminfo():
                    return True
            return False

        args_may_always_need_nrt = any(
            map(type_may_always_need_nrt, fe_argtypes)
        )

        if args_may_always_need_nrt:
            nmd = fn.module.add_named_metadata(
                'numba_args_may_always_need_nrt',
            )
            nmd.add(fn.module.add_metadata([fn]))

        Set names of function arguments, and add useful attributes to them.
        
numba/core/callconv.py