Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
'''
Creates a Fortran routine to set the arguments of the OpenCL
version of this kernel.
:param parent: Parent node of the set-kernel-arguments routine
:type parent: :py:class:`psyclone.f2pygen.moduleGen`
'''
from psyclone.f2pygen import SubroutineGen, UseGen, DeclGen, \
CommentGen, AssignGen, CallGen
# The arg_setter code is in a subroutine, so we create a new scope
argsetter_st = SymbolTable()
# Currently literal arguments are checked for and rejected by
# the OpenCL transformation.
kobj = argsetter_st.new_symbol_name("kernel_obj")
argsetter_st.add(Symbol(kobj))
args = [kobj] + [arg.name for arg in self._arguments.args]
# Declare the subroutine in the Invoke SymbolTable and the argsetter
# subroutine SymbolTable.
sub_name = self.root.symbol_table.new_symbol_name(
self.name + "_set_args")
sub_symbol = Symbol(sub_name)
self.root.symbol_table.add(sub_symbol, tag=sub_name)
argsetter_st.add(sub_symbol)
sub = SubroutineGen(parent, name=sub_name, args=args)
parent.add(sub)
sub.add(UseGen(sub, name="ocl_utils_mod", only=True,
funcnames=["check_status"]))
sub.add(UseGen(sub, name="iso_c_binding", only=True,
funcnames=["c_sizeof", "c_loc", "c_intptr_t"]))
sub.add(UseGen(sub, name="clfortran", only=True,
# Create a set of all of the symbol names in the fparser2 parse
# tree so that we can find any clashes. We go as far back up the tree
# as we can before searching for all instances of Fortran2003.Name.
# We can't just rely on looking in our symbol tables because there
# may be CodeBlocks that access symbols that are e.g. imported from
# modules without being explicitly named.
name_list = walk(node.get_root(), Fortran2003.Name)
for name_obj in name_list:
name = str(name_obj)
if name not in symbol_table:
# TODO #630 some of these symbols will be put in the wrong
# symbol table. We need support for creating a unique symbol
# within a hierarchy of symbol tables. However, until we are
# generating code from the PSyIR Fortran backend
# (#435) this doesn't matter.
symbol_table.add(Symbol(name))
integer_type = default_integer_type()
# Now create a loop nest of depth `rank`
new_parent = parent
for idx in range(rank, 0, -1):
# TODO #630 this creation of a new symbol really needs to account
# for all of the symbols in the hierarchy of symbol tables. Since
# we don't yet have that functionality we just add everything to
# the top-level symbol table.
loop_vars[idx-1] = symbol_table.new_symbol_name(
"widx{0}".format(idx))
symbol_table.add(DataSymbol(loop_vars[idx-1], integer_type))
loop = Loop(parent=new_parent, variable_name=loop_vars[idx-1],
def __init__(self, symbol, parent=None):
if not isinstance(symbol, Symbol):
raise TypeError("In Reference initialisation expecting a symbol "
"but found '{0}'.".format(type(symbol).__name__))
super(Reference, self).__init__(parent=parent)
self._symbol = symbol
all_vars = list(set(input_list).union(set(output_list)))
all_vars.sort()
module_name, region_name = self.region_identifier
module = ModuleGen(name=module_name)
prog = SubroutineGen(parent=module, name=module_name+"_code",
implicitnone=True)
module.add(prog)
use = UseGen(prog, self.add_psydata_class_prefix("psy_data_mod"),
only=True,
funcnames=[self.add_psydata_class_prefix("PSyDataType")])
prog.add(use)
# Use a symbol table to make sure all variable names are unique
sym_table = GOSymbolTable()
sym = Symbol("PSyDataType")
sym_table.add(sym)
psy_data = sym_table.new_symbol_name(self.add_psydata_class_prefix
("psy_data"))
sym_table.add(Symbol(psy_data))
var_decl = TypeDeclGen(prog, datatype=self.add_psydata_class_prefix
("PSyDataType"),
entity_decls=[psy_data])
prog.add(var_decl)
call = CallGen(prog,
"{0}%OpenRead(\"{1}\", \"{2}\")"
.format(psy_data, module_name, region_name))
prog.add(call)
post_suffix = self._post_name
from psyclone.f2pygen import SubroutineGen, UseGen, DeclGen, \
CommentGen, AssignGen, CallGen
# The arg_setter code is in a subroutine, so we create a new scope
argsetter_st = SymbolTable()
# Currently literal arguments are checked for and rejected by
# the OpenCL transformation.
kobj = argsetter_st.new_symbol_name("kernel_obj")
argsetter_st.add(Symbol(kobj))
args = [kobj] + [arg.name for arg in self._arguments.args]
# Declare the subroutine in the Invoke SymbolTable and the argsetter
# subroutine SymbolTable.
sub_name = self.root.symbol_table.new_symbol_name(
self.name + "_set_args")
sub_symbol = Symbol(sub_name)
self.root.symbol_table.add(sub_symbol, tag=sub_name)
argsetter_st.add(sub_symbol)
sub = SubroutineGen(parent, name=sub_name, args=args)
parent.add(sub)
sub.add(UseGen(sub, name="ocl_utils_mod", only=True,
funcnames=["check_status"]))
sub.add(UseGen(sub, name="iso_c_binding", only=True,
funcnames=["c_sizeof", "c_loc", "c_intptr_t"]))
sub.add(UseGen(sub, name="clfortran", only=True,
funcnames=["clSetKernelArg"]))
# Declare arguments
sub.add(DeclGen(sub, datatype="integer", kind="c_intptr_t",
target=True, entity_decls=[kobj]))
# Get all Grid property arguments
grid_prop_args = args_filter(self._arguments.args,
"a defined interface ({1}).".format(
sym_name, str(sym.interface)))
sym.interface = interface
# Check for symbols named in an access statement but not explicitly
# declared. These must then refer to symbols that have been brought
# into scope by an unqualified use statement. As we have no idea
# whether they represent data or a routine we use the Symbol base
# class.
for name in (list(explicit_public_symbols) +
list(explicit_private_symbols)):
if name not in parent.symbol_table:
if name in explicit_public_symbols:
vis = Symbol.Visibility.PUBLIC
else:
vis = Symbol.Visibility.PRIVATE
# TODO 736 Ideally we would use parent.find_or_create_symbol()
# here since that checks that there is a possible source for
# this previously-unseen symbol. However, we cannot yet do this
# because we don't capture symbols for routine names so
# that, e.g.:
# module my_mod
# public my_routine
# contains
# subroutine my_routine()
# would cause us to raise an exception.
parent.symbol_table.add(Symbol(name, visibility=vis))
try:
arg_symbols = []
# Ensure each associated symbol has the correct interface info.
for arg_name in [x.string.lower() for x in arg_list]:
:raises KeyError: if the given name is not in the Symbol Table.
'''
try:
symbol = self._symbols[self._normalize(name)]
if visibility:
if not isinstance(visibility, list):
vis_list = [visibility]
else:
vis_list = visibility
if symbol.visibility not in vis_list:
vis_names = []
# Take care here in case the 'visibility' argument
# is of the wrong type
for vis in vis_list:
if not isinstance(vis, Symbol.Visibility):
raise TypeError(
"the 'visibility' argument to lookup() must be"
" an instance (or list of instances) of "
"Symbol.Visibility but got '{0}' when "
"searching for symbol '{1}'".format(
type(vis).__name__, name))
vis_names.append(vis.name)
raise SymbolError(
"Symbol '{0}' exists in the Symbol Table but has "
"visibility '{1}' which does not match with the "
"requested visibility: {2}".format(
name, symbol.visibility.name, vis_names))
return symbol
except KeyError:
raise KeyError("Could not find '{0}' in the Symbol Table."
"".format(name))
def __init__(self, name, visibility=Symbol.DEFAULT_VISIBILITY):
super(ContainerSymbol, self).__init__(name, visibility)
self._reference = None
# At the moment we just have one ContainerSymbol interface, so we
# always assign this interface to all ContainerSymbols, we may want
# to pass the interface as a parameter when we have more than one.
self._interface = FortranModuleInterface
# Whether or not there is a wildcard import of all public symbols
# from this container (e.g. an unqualified USE of a module in Fortran).
self._has_wildcard_import = False
if name not in parent.symbol_table:
if name in explicit_public_symbols:
vis = Symbol.Visibility.PUBLIC
else:
vis = Symbol.Visibility.PRIVATE
# TODO 736 Ideally we would use parent.find_or_create_symbol()
# here since that checks that there is a possible source for
# this previously-unseen symbol. However, we cannot yet do this
# because we don't capture symbols for routine names so
# that, e.g.:
# module my_mod
# public my_routine
# contains
# subroutine my_routine()
# would cause us to raise an exception.
parent.symbol_table.add(Symbol(name, visibility=vis))
try:
arg_symbols = []
# Ensure each associated symbol has the correct interface info.
for arg_name in [x.string.lower() for x in arg_list]:
symbol = parent.symbol_table.lookup(arg_name)
if symbol.is_local:
# We didn't previously know that this Symbol was an
# argument (as it had no 'intent' qualifier). Mark
# that it is an argument by specifying its interface.
# A Fortran argument has intent(inout) by default
symbol.interface = ArgumentInterface(
ArgumentInterface.Access.READWRITE)
arg_symbols.append(symbol)
# Now that we've updated the Symbols themselves, set the
# argument list