In the context of elemental operation a dynamically optional
intrinsic argument must be lowered such that the elemental
designator is generated under isPresent check.
Reviewed By: tblah
Differential Revision: https://reviews.llvm.org/D154897
This patch implements HLFIR lowering for associating an actual
TARGET argument to a dummy POINTER argument.
Reviewed By: tblah, jeanPerier
Differential Revision: https://reviews.llvm.org/D154311
genElementalCall can return a null option when lowering elemental
subroutine calls (as there is no return value). Therefore
std::option::value should not be used as it will cause an
assertion failure.
This fixes uses of the mvbits intrinsic with array arguments, as used in
the gfortran test suite.
Differential Revision: https://reviews.llvm.org/D154340
This adds support for dynamically optional arguments for intrinsics
which do not have their own hlfir operations.
The functions for processing these arguments are mostly the same as the
equivalent functions in ConvertExpr.cpp. I chose not to share
implementations so that HLFIR helpers can be used here. Presumably
ConvertExpr.cpp will go away one day.
Depends on D154236
Differential Revision: https://reviews.llvm.org/D154237
The old code had overgrown itself and become difficult to read and
modify. I've rewritten it and moved it into its own translation unit.
I moved PreparedActualArgument to the header file for the
transformational intrinsic lowering. Logically, it belongs in
ConvertCall.h, but putting it there would create a circular dependency
between HlfirIntrinsics and ConvertCall.
Differential Revision: https://reviews.llvm.org/D154235
Actual argument expressions must be evaluated before the invocation
of the sequence of per-element calls of an impure elemental subprogram.
Otherwise, the side effects of the calls may affect the input for
the consequent elements.
The proposed changes are described by Jean in D154174.
Reviewed By: tblah
Differential Revision: https://reviews.llvm.org/D154263
HLFIR lowering was currently hitting errors like "not yet implemented:
intrinsic: z0$iso_c_binding$c_associated_c_ptr". These error were caused
by HLFIR lowering using the name with the full context instead of
the ultimate one.
I do not want to change proc.GetName() because I think it may be best
if it retains the full context for its usages in semantics, so I fixed
the helper to get the name in lowering to HLFIR.
Differential Revision: https://reviews.llvm.org/D154230
This patch adds 'unordered' attribute handling the HLFIR elementals'
builders and fixes the attribute handling in lowering and transformations.
Depends on D154031, D154032
Reviewed By: jeanPerier, tblah
Differential Revision: https://reviews.llvm.org/D154035
This patch sets `unordered` `fir.do_loop` attribute during lowering
of elemental subroutine calls to HLFIR, when it is safe to do so.
Proper handling of `hlfir.elemental` will be done in a separate patch.
Reviewed By: jeanPerier, tblah
Differential Revision: https://reviews.llvm.org/D154031
This patch implements the lowering for the `hlfir.char_extremum` operation.
Discussion for this patch can be found in the draft patch [here](https://reviews.llvm.org/D143326). The reason
for not promoting this draft to a true patch for review was because I needed to separate the op
definition/codegen and lowering into two separate patches, as preferred by @jeanPerier.
Depends on D152474
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D152475
Lower user defined assignment inside the hlfir.region_assign
"userDefinedAssignment" mlir region.
This is done by adding an entry point to ConvertCall.h in order
to call genUserCall with the region block arguments as arguments.
The codegen for hlfir.region_assign with user defined assignment
will be added in a later patch.
Differential Revision: https://reviews.llvm.org/D153404
Adds a new HLFIR operation for the COUNT intrinsic according to
the design set out in flang/docs/HighLevel.md. This patch includes all
the necessary changes to create a new HLFIR operation and lower it into
the fir runtime call.
Author was @jacob-crawley. Minor adjustments by @tblah
Differential Revision: https://reviews.llvm.org/D152521
Adds a new HLFIR operation for the DOT_PRODUCT intrinsic according to
the design set out in flang/docs/HighLevel.md. This patch includes all
the necessary changes to create a new HLFIR operation and lower it into
the fir runtime call.
Differential Revision: https://reviews.llvm.org/D152252
The copy must made according to the actual type, not the dummy type. In
case the dummy is polymorphic, these types will be different and the
dynamic type of the copy passed in the call should be the one of the
actual.
There is no support for "class(t), value" yet (it is hitting a TODO in
CallInterface that is moot for HLFIR but has not been lifted for lack of
proper testing) so the bug was dormant, but D151271 created a situation
where a copy is needed with polymorphic dummies and exposed the bug.
This led to a compile time assert
"value.isScalar() && fir::isa_trivial(value.getType())" in "hlfir::genAssociateExpr".
Differential Revision: https://reviews.llvm.org/D151413
Even though the constant expression actual argument is not definable,
and the associated dummy argument is not definable, the compiler may produce
implicit copies into the memory storage associated with the constant expression.
For example, a constant expression storage passed by reference to a subprogram
may be used for implicit copy-out:
```
subroutine sub(i, n)
interface
subroutine sub2(i)
integer :: i(*)
end subroutine sub2
end interface
integer :: i(n)
call sub2(i(3::2)) ! copy-out after the call will write to 'i'
end subroutine sub
subroutine test
call sub((/1,2,3,4,5/), 5)
end subroutine test
```
If we pass a reference to constant expression storage to 'sub' directly,
the copy-out inside 'sub' will try to write into readonly memory.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D151271
There are several observations regarding the copy-in/copy-out:
* Actual argument associated with INTENT(OUT) dummy argument that
requires finalization (7.5.6.3 p. 7) may be read by the finalization
function, so a copy-in is required.
* A temporary created for the copy-in/copy-out must be destroyed
without finalization after the call (or after the corresponding copy-out),
otherwise, memory leaks may occur.
* The copy-out assignment must not perform finalization for the LHS.
* The copy-out assignment from the temporary to the actual argument
may or may not need to initialize the LHS.
This change-set introduces new runtime methods: CopyOutAssign and
DestroyWithoutFinalization. They are called by the compiler generated
code to match the behavior described above.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D151135
Reboxing of the actual argument according to the type of the dummy
argument has to be aware of the potential rank mismatch, when
IGNORE_TKR(R) is used. This change only adds support for the mismatching
rank when the dummy argument has unlimited polymorphic type.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D151016
Comments in the recent patch https://reviews.llvm.org/D149964,
mentioned that using hlfir_ExprType in cases where intrinsics
return simple scalars adds unnecessary abstraction that isn't
needed unless an array type is being used.
This patch modifies the HLFIR operations for product, sum and any
so that they only return a hlfir_ExprType when the result is an array,
otherwise they will return just the simple scalar type.
Differential Revision: https://reviews.llvm.org/D150877
Fortran doesn't allow inaccessible procedure bindings to be
overridden, and this needs to apply to generic resolution.
When resolving a type-bound generic procedure from another
module, ensure only that the most extended override from its
module is used if it is PRIVATE, not a later apparent override
from another module.
Differential Revision: https://reviews.llvm.org/D150721
Carries out the initial lowering of the product intrinsic into HLFIR
following a similar method to sum, the --use-hlfir-intrinsic-ops flag
in test/Lower/HLFIR/expr-box is set to false so that the tests will
pass until hlfir.product is lowered into fir.call
Depends on: D147624
Differential Revision: https://reviews.llvm.org/D148719
The `none` type cannot be used for creating AssociateOp for the actual
argument. I think it should be always okay to compute the storage
data type based on the actual argument expression.
c_ptr arguments passed by value need special handling, which was missing
in HLFIR lowering. The lowering has to load the __address component
and pass the loaded value as the actual argument.
Differential Revision: https://reviews.llvm.org/D149307
HLFIR lowering promotes intrinsic results lowered in memory to
hlfir.expr to underline their read-only aspect once they are created.
NULL(MOLD) should not be promoted to an hlfir.expr, it is the NULL
variable (we need to see it as an address).
Reviewed By: clementval
Differential Revision: https://reviews.llvm.org/D149053
Fix invalid op result access. This will trigger
assertion introduced in D147883.
Reviewed By: frgossen
Differential Revision: https://reviews.llvm.org/D147959
Similar to https://reviews.llvm.org/D147487.
TYPE(*) evaluate::ActualArgument wraps a symbol instead of an
expression. This requires special handling, which is limited because
C710 restrict the intrinsics in which TYPE(*) may appear as arguments
(there is for instance no need to deal with dynamic presence aspects).
Differential Revision: https://reviews.llvm.org/D147513
This is related to llvm-project#61074.
In general, it is undefined behavior if user subprogram is declared
with a name that matches a name of function from any runtime library
that Flang is using (e.g. FortranRuntime, libm, etc.). With this change-set
we avoid ICE for invalid calls generated during math lowering by
type casing the function before the call. This happens when a user function
call is lowered before the math function call with the same name.
To detect the name clash in cases when the math function call is lowered
before the user function call we set fir.runtime attribute for the math
functions and check it when we lower the user function call.
The warnings are currently emitted only in debug compiler and
under llvm debug options. I think they should be reported
in the same way as regular Flang warnings.
Note that this change-set does not resolve issues with the conversion
passes that might introduce libm calls after the lowering.
Differential Revision: https://reviews.llvm.org/D145653
The Destroy runtime function does free the memory so do not do it
inlined when we use Destroy. This avoid a double free execution error.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D145372
Optional character function arguments were not being lowered
properly. As they are passed as a tuple, containing the (boxed)
function address and the character length, it is not possible for
fir.absent to handle it directly. Instead, a tuple needs to be
created and filled with an absent function address and a dummy
character length.
Fixes#60225
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D144743
Intrinsic module procedures are a bit different from intrinsic
procedures: they are defined in intrinsic module files, but their
signature and representation in semantics is the same as user
procedures.
The code to lower them in lowering (when they are not implemented in
Fortran) is the same as for intrinsic procedures
(Optimizer/Builder/IntrinsicCall.cpp).
The dispatching in in HLFIR procedure reference lowering must be
slightly modified so that these evaluate::ProcRef that have a
semantics::Symbol instead of an evaluate::SpecificIntrinsic can
be dispatched as evaluate::SpecificIntrinsic:
- move isIntrinsicModuleProcedure to detect them
- in the helpers dealing with intrinsics, make evaluate::SpecificIntrinsic
a pointer argument that can be null for intrinsic module procedures.
- add getProcedureName() to call context to avoid relying on the
evaluate::SpecificIntrinsic when it is not know to be null.
Differential Revision: https://reviews.llvm.org/D145360
There is a lot of Fortran code that takes advantage of F77 implicit
interface to pass arguments with a different type than those from
the subprogram definition (which is well defined if the storage
and passing convention are the same or compatible).
When the definition and calls are in different files, there is nothing
special to do: the actual arguments are already used to compute the
call interface.
The trouble for lowering comes when the definition is in the same
compilation unit (Semantics raises warning). Then, lowering will
be provided with the interface from the definition to prepare the
argument, and this leads to many ad-hoc handling (see
builder.convertWithSemantics) in the current lowering to cope
with the dummy/actual mismatches on a case by case basis. The
current lowering to FIR is not even complete for all mismatch cases that
can be found in the wild (see https://github.com/llvm/llvm-project/issues/60550),
it is crashing or hitting asserts for many of the added tests.
For HLFIR, instead of coping on a case by case basis, the call
interface will be recomputed according to the actual arguments when
calling an external procedure that can be called with an explicit
interface.
One extra case still has to be handled manually because it may happen
in calls with explicit interfaces: passing a character procedure
designator to a non character procedure dummy (and vice-versa) is widely
accepted even with explicit interfaces (and flang semantic accepts it).
Yet, this "mismatch" cannot be dealt with a simple fir.convert because
character dummy procedure are passed with a different passing
convention: an extra argument is hoisted for the result length (in FIR,
there is no extra argument yet, but the MLIR func argument is a
tuple<fir.boxproc, len>).
Differential Revision: https://reviews.llvm.org/D143636
- Add a convertProcedureDesignatorToHLFIR that converts the
fir::ExtendedValue from the current lowering to a
fir.boxproc/tuple<fir.boxproc, len> mlir::Value.
- Allow fir.boxproc/tuple<fir.boxproc, len> as hlfir::Entity values
(a function is an address, but from a Fortran entity point of view,
procedure that are not procedure pointers cannot be assigned to, so
it makes a lot more sense to consider those as values).
- Modify symbol association to not generate an hlfir.declare for dummy
procedures. They are not needed and allowing hlfir.declare to declare
function values would make its verifier and handling overly complex
for little benefits (maybe an hlfir.declare_proc could be added if it
turnout out useful later for debug info and attributes storing
purposes).
- Allow translation from hlfir::Entity to fir::ExtendedValue.
convertToBox return type had to be relaxed because some intrinsics
handles both object and procedure arguments and need to lower their
object arguments "asBox". fir::BoxValue is not intended to carry
dummy procedures (all its member functions would make little sense
and its verifier does not accept such type).
Note that AsAddr, AsValue and AsBox will always return the same MLIR
value for procedure designators because they are always handled the
same way in FIR.
Differential Revision: https://reviews.llvm.org/D143585
Implement the TODO. Be careful to use and propagate the expression
type to create the temporary since the mlir value may have been computed
with a different value type (e.g., i1 for logical) that should not be
used for in memory values that must have Fortran types.
Co-authored-by: Tom Eccles <tom.eccles@arm.com>
Differential Revision: https://reviews.llvm.org/D143421
HLFIR requires mapping symbol to a single mlir::Value (produced
by a fir::FortranVariableOpInterface), while the current lowering
maps the value to a fir::ExtdendedValue.
So far, the HLFIR symbol query was a special one. Hence, all the code
directly using symMap.lookupSymbol and symMap.addSymbol did not work
with the lowering to HLFIR.
Refactor the code so that symbol lookup and add symbol go through
the converter in a centralize place that handles the HLFIR case
(translate fir::FortranVariableOpInterface to fir::ExtdendedValue
in lookups, and generate hlfir.declare when adding symbols).
In the refactoring, fir::FortranVariableOpInterface is added as
a symbolBox variant to avoid special casing all lookups (shallowLookup...).
Remove some unused SymbolBox member function instead of updating
them.
Differential Revision: https://reviews.llvm.org/D143395
This will allow IntrinsicCall to be used in passes to implement hlfir
transformational intrinsic operations.
Differential Revision: https://reviews.llvm.org/D143084
This gets rid of a special case with CHAR() intrinsic and BIND(C) results.
I tested this has no impact on the LLVM assembly when LLVM opt -01 or
more is run.
See comment in the patch for more details.
Differential Revision: https://reviews.llvm.org/D143270
The code did not propagate the result optionality for subroutine.
Make the result of genIntrinsicRef optional.
Differential Revision: https://reviews.llvm.org/D143251
According to 7.5.6.3 point 5, only nonpointer function result
need to be finalized. Update the condition to exclude pointer
function result.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D143156
In lowering to HLFIR, deal with user calls involving a mix of:
- dummy with VALUE
- Polymorphism
- contiguous dummy
- assumed shape dummy
- OPTIONAL arguments
- NULL() passed to OPTIONAL arguments.
- elemental calls
Does not deal with assumed ranked dummy arguments.
This patch unifies the preparation of all arguments that must be passed
in memory and are not passed as allocatable/pointers.
For optionals, the same argument preparation is done, except the utility
that generates the IR for the argument preparation is called inside a
fir.if.
The addressing of array arguments in elemental calls is delayed so that
it can also happen during this argument preparation, and be placed in
the fir.if when the array may be absent.
Structure helpers are added to convey a prepared dummy argument and the
data that may be needed to do the clean-up after the call (temporary
storage deallocation or copy-out). And a utility is added to wrap
the preparation code inside a fir.if and convey these values through
the fir.if.
Certain aspects of this patch brings the HLFIR lowering support beyond
what the current lowering to FIR supports (e.g. handling of NULL(), handling
of optional in elemental calls, handling of copy-in/copy-out involving
polymorphic entities).
Differential Revision: https://reviews.llvm.org/D142695
This patch implements the derived-type finalization for
monomorphic and polymorphic derived-type.
The finalization is done through a call to the `Destroy`
runtime function so the allocatable component object are also
finalized correctly when needed. It would be possible to finalize
monomorphic derived-type with non finalizable component with a
direct call to their finalize subroutine.
7.5.6.3 point 1: LHS nonallocatable object and LHS allocatable
object finalization. Done with call to `Destroy` for monomorphic
derived-type and through `Assign` for polymorphic entities.
7.5.6.3 point 2: Done within the deallocation calls.
7.5.6.3 point 3: A function context is added to the bridge to
attach finalization that need to happen on function/subroutine
exit.
7.5.6.3 point 4: BLOCK construct not yet implemented.
7.5.6.3 point 5/6: Finalization attach to the stmtCtx in a
similar way than 9.7.3.2 point 4.
7.5.6.3 point 7: INTENT(OUT) finalization done with a
call to `Destroy` runtime function call.
This patch passes 9/10 tests in the proposed test-suite
https://github.com/llvm/llvm-test-suite/pull/13
- The case with BLOCK construct will be implemented later when
BLOCK are implemented upstream.
- Automatic deallocation is not yet implemented. Finalization triggered
by automatic deallocation is then not triggered.
Reviewed By: jeanPerier, PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D142707