Function¶
A function or a subroutine, with or without a body.
Declaration¶
Syntax¶
Function(symbol_table symtab, identifier name,
ttype function_signature, identifier* dependencies, expr* args,
stmt* body, expr? return_var, access access, bool deterministic,
bool side_effect_free, string? module_file, gpu_kernel_layout? gpu,
location start_name, location end_name)
Arguments¶
Argument |
Description |
|---|---|
|
the symbol table of the procedure: its dummy arguments, its result variable and its local variables. |
|
the name of the procedure. |
|
a FunctionType giving the argument types, the result type ( |
|
the names of the symbols the body refers to. |
|
the dummy arguments, as Var expressions pointing into |
|
the statements of the procedure. Empty for an interface ( |
|
the result variable of a function, as a |
|
|
|
|
|
|
|
the module file the procedure was loaded from, when it was; |
|
the finalized GPU kernel layout, or |
|
the source span of the name in the |
|
the source span of the name in the matching |
Return values¶
None.
Description¶
One constructor represents both Fortran functions and Fortran subroutines. A
subroutine is a Function whose return_var is nil and whose
function_signature has no return_var_type; it is called by
SubroutineCall rather than by
FunctionCall.
The dummy arguments appear twice: in symtab, which owns the
Variable symbols, and in args, which fixes their order. The
result variable of a function is likewise owned by symtab, with
intent=ReturnVar, and referenced by return_var.
A nonallocatable, nonpointer character dummy (a scalar, or an explicit-shape
or assumed-size array) of a procedure without BIND(C) is passed as a pointer
to its data, with the length of the actual (the element length of an array)
passed by value in a hidden argument, as gfortran does. The
string_length_arguments pass makes this explicit: it gives each such dummy an
integer(8), value, intent(in) dummy after all the other dummies, in the order
of the character dummies, makes it the len of an assumed-length dummy, and
appends the lengths of the actuals to every call. Afterwards ASR verification
requires every such dummy to have its hidden dummy and every call to pass it.
ASRUtils::is_string_dummy_with_hidden_length() says which dummies these are;
a code generator passes them as their data pointer alone.
deterministic and side_effect_free are declarations about the procedure,
not consequences of its body. A frontend that cannot prove them must leave
them false.
Only a kernel may own gpu metadata. It is produced after shared array and
procedure lowering, before host launch expansion. Runtime workspace extents
are expressions over the original kernel arguments; the host evaluates each
once and passes the result in an additional scalar argument. The device uses
that same scalar for its workspace slice. Buffer order and device-procedure
identity are explicit rather than inferred from generated names.
ASR verification checks binding identities, ranks, workspace slots, extent dependencies and the ordered device-call closure. Absent optional aggregate metadata is omitted from readable ASR, so ordinary procedures retain their existing text representation.
Examples¶
An ASR text document that uses it:
(TranslationUnit
:symtab (SymbolTable
:id 0
:symbols {
"m" (Module
:symtab (SymbolTable
:id 1
:symbols {
"add" (Function
:symtab (SymbolTable
:id 2
:symbols {
"a" (Variable
:parent_symtab 2
:name "a"
:dependencies []
:intent :In
:symbolic_value nil
:value nil
:storage :Default
:type (Integer
:kind 4
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"b" (Variable
:parent_symtab 2
:name "b"
:dependencies []
:intent :In
:symbolic_value nil
:value nil
:storage :Default
:type (Integer
:kind 4
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
"c" (Variable
:parent_symtab 2
:name "c"
:dependencies []
:intent :ReturnVar
:symbolic_value nil
:value nil
:storage :Default
:type (Integer
:kind 4
)
:type_declaration nil
:abi :Source
:access :Public
:presence :Required
:value_attr false
:target_attr false
:contiguous_attr false
:bindc_name nil
:is_volatile false
:is_protected false
:pass_attr :NotMethod
:self_argument nil
:codims []
:common_block nil
)
}
)
:name "add"
:function_signature (FunctionType
:arg_types [
(Integer
:kind 4
)
(Integer
:kind 4
)
]
:return_var_type (Integer
:kind 4
)
:abi :Source
:deftype :Implementation
:bindc_name nil
:elemental false
:pure false
:module false
:inline false
:static false
:restrictions []
:is_restriction false
:exec_space :Host
)
:dependencies []
:args [
(Var
:v (SymbolRef 2 "a")
)
(Var
:v (SymbolRef 2 "b")
)
]
:body [
(Assignment
:target (Var
:v (SymbolRef 2 "c")
)
:value (IntegerBinOp
:left (Var
:v (SymbolRef 2 "a")
)
:op :Add
:right (Var
:v (SymbolRef 2 "b")
)
:type (Integer
:kind 4
)
:value nil
)
:overloaded nil
:realloc_lhs false
:move_allocation false
)
]
:return_var (Var
:v (SymbolRef 2 "c")
)
:access :Public
:deterministic false
:side_effect_free false
:module_file nil
)
}
)
:name "m"
:parent_module nil
:dependencies []
:loaded_from_mod false
:intrinsic false
:has_submodules false
:global_init nil
)
"main" (Program
:symtab (SymbolTable
:id 3
:symbols {}
)
:name "main"
:dependencies []
:body []
:global_init nil
)
}
)
:items []
:global_init nil
)
See Also¶
Module, Variable, FunctionCall, SubroutineCall, FunctionType