Name mangling is invoked for a bind(C) procedure contained in a block in
a context that does not have access to block ID mapping. Relaxing an
assert to account for this.
Fixes#79408
1. Deal with BIND(C,NAME="")
BIND(C,NAME="") is different from BIND(C). The latter implies that there
us a binding label which is the Fortran symbol name (no Fortran mangling
must be added like underscores). The former implies there is no binding
label (the name in the object file must be the same as if it there was
no BIND(C) attribute at all).
This is correctly implemented in the front-end, but lowering mistakenly
overrode this in the code dealing with the case where BIND(C) is
inherited from a procedure interface. Handling of this last case is moved into name
resolution.
2. Deal with BIND(C) internal procedure
Also according to 18.10.2, BIND(C) does not give a p prevent name
resolution from adding a label to them, otherwise,
bindc_internal_proc.f90 was not going through semantics (bogus error
about conflicting global names). Nothing TODO in lowering other than
removing the TODO.
It is possible for a derived type extending a type with private
components to define components with the same name as the private
components.
This was not properly handled by lowering where several fir.record type
component names could end-up being the same, leading to bad generated
code (only the first component was accessed via fir.field_index, leading
to bad generated code).
This patch handles the situation by adding the derived type mangled name
to private component.
This patch changes how common blocks are aggregated and named in
lowering in order to:
* fix one obvious issue where BIND(C) and non BIND(C) with the same
Fortran name were "merged"
* go further and deal with a derivative where the BIND(C) C name matches
the assembly name of a Fortran common block. This is a bit unspecified
IMHO, but gfortran, ifort, and nvfortran "merge" the common block
without complaints as a linker would have done. This required getting
rid of all the common block mangling early in FIR (\_QC) instead of
leaving that to the phase that emits LLVM from FIR because BIND(C)
common blocks did not have mangled names. Care has to be taken to deal
with the underscoring option of flang-new.
See added flang/test/Lower/HLFIR/common-block-bindc-conflicts.f90 for an
illustration.
Unlike other executable constructs with associating selectors, the
selector of a SELECT RANK construct can have the ALLOCATABLE or POINTER
attribute, and will work as an allocatable or object pointer within
each rank case, so long as there is no RANK(*) case.
Getting this right exposed a correctness risk with the popular
predicate IsAllocatableOrPointer() -- it will be true for procedure
pointers as well as object pointers, and in many contexts, a procedure
pointer should not be acceptable. So this patch adds the new predicate
IsAllocatableOrObjectPointer(), and updates some call sites of the original
function to use the new one.
Differential Revision: https://reviews.llvm.org/D159043
Accept "module procedure" (as well as module function/subroutine)
in a separate module procedure definition, such as "bb1" in:
module mm
interface
module subroutine mm1
end subroutine
end interface
end module
submodule(mm) bb
interface
module subroutine bb1
end subroutine
end interface
contains
module procedure mm1
call bb1
end procedure
module procedure bb1
print*, 'bb1'
end procedure
end submodule
use mm
call mm1
end
Name mangling may be invoked for an interface procedure contained in
a block in a context that does not have access to block ID mapping.
Procedures can't be defined inside a block, so name mangling doesn't
need a block map. Relax an assert to account for this.
block
interface
subroutine ss(n) bind(c)
integer :: n
end subroutine
end interface
call ss(5)
end block
end
Generate supporting data structures and calls to new runtime IO functions
for defined IO that accesses non-type-bound procedures, such as `wft` in:
module m1
type t
integer n
end type
interface write(formatted)
module procedure wft
end interface
contains
subroutine wft(dtv, unit, iotype, v_list, iostat, iomsg)
class(t), intent(in) :: dtv
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, intent(in) :: v_list(:)
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
iostat = 0
write(unit,*,iostat=iostat,iomsg=iomsg) 'wft was called: ', dtv%n
end subroutine
end module
module m2
contains
subroutine test1
use m1
print *, 'test1, should call wft: ', t(1)
end subroutine
subroutine test2
use m1, only: t
print *, 'test2, should not call wft: ', t(2)
end subroutine
end module
use m1
use m2
call test1
call test2
print *, 'main, should call wft: ', t(3)
end
The global names were created using a hash based on the address
of std::vector::data address. Since the memory may be reused
by different std::vector's, this may cause non-equivalent
constant expressions to map to the same name. This is what is happening
in the modified flang/test/Lower/constant-literal-mangling.f90 test.
I changed the name creation to use a map between the constant expressions
and corresponding unique names. The uniquing is done using a name counter
in FirConverter. The effect of this change is that the equivalent
constant expressions are now mapped to the same global, and the naming
is "stable" (i.e. it does not change from compilation to compilation).
Though, the issue is not HLFIR specific it was affecting several tests
when using HLFIR lowering.
Differential Revision: https://reviews.llvm.org/D150380
A block construct is an execution control construct that supports
declaration scopes contained within a parent subprogram scope or another
block scope. (blocks may be nested.) This is implemented by applying
basic scope processing to the block level.
Name uniquing/mangling is extended to support this. The term "block" is
heavily overloaded in Fortran standards. Prior name uniquing used tag `B`
for common block objects. Existing tag choices were modified to free up `B`
for block construct entities, and `C` for common blocks, and resolve
additional issues with other tags. The "old tag -> new tag" changes can
be summarized as:
-> B -- block construct -> new
B -> C -- common block
C -> YI -- intrinsic type descriptor; not currently generated
CT -> Y -- nonintrinsic type descriptor; not currently generated
G -> N -- namelist group
L -> -- block data; not needed -> deleted
Existing name uniquing components consist of a tag followed by a name
from user source code, such as a module, subprogram, or variable name.
Block constructs are different in that they may be anonymous. (Like other
constructs, a block may have a `block-construct-name` that can be used
in exit statements, but this name is optional.) So blocks are given a
numeric compiler-generated preorder index starting with `B1`, `B2`,
and so on, on a per-procedure basis.
Name uniquing is also modified to include component names for all
containing procedures rather than for just the immediate host. This
fixes an existing name clash bug with same-named entities in same-named
host subprograms contained in different-named containing subprograms,
and variations of the bug involving modules and submodules.
F18 clause 9.7.3.1 (Deallocation of allocatable variables) paragraph 1
has a requirement that an allocated, unsaved allocatable local variable
must be deallocated on procedure exit. The following paragraph 2 states:
When a BLOCK construct terminates, any unsaved allocated allocatable
local variable of the construct is deallocated.
Similarly, F18 clause 7.5.6.3 (When finalization occurs) paragraph 3
has a requirement that a nonpointer, nonallocatable object must be
finalized on procedure exit. The following paragraph 4 states:
A nonpointer nonallocatable local variable of a BLOCK construct
is finalized immediately before it would become undefined due to
termination of the BLOCK construct.
These deallocation and finalization requirements, along with stack
restoration requirements, require knowledge of block exits. In addition
to normal block termination at an end-block-stmt, a block may be
terminated by executing a branching statement that targets a statement
outside of the block. This includes
Single-target branch statements:
- goto
- exit
- cycle
- return
Bounded multiple-target branch statements:
- arithmetic goto
- IO statement with END, EOR, or ERR specifiers
Unbounded multiple-target branch statements:
- call with alternate return specs
- computed goto
- assigned goto
Lowering code is extended to determine if one of these branches exits
one or more relevant blocks or other constructs, and adds a mechanism to
insert any necessary deallocation, finalization, or stack restoration
code at the source of the branch. For a single-target branch it suffices
to generate the exit code just prior to taking the indicated branch.
Each target of a multiple-target branch must be analyzed individually.
Where necessary, the code must first branch to an intermediate basic
block that contains exit code, followed by a branch to the original target
statement.
This patch implements an `activeConstructStack` construct exit mechanism
that queries a new `activeConstruct` PFT bit to insert stack restoration
code at block exits. It ties in to existing code in ConvertVariable.cpp
routine `instantiateLocal` which has code for finalization, making block
exit finalization on par with subprogram exit finalization. Deallocation
is as yet unimplemented for subprograms or blocks. This may result in
memory leaks for affected objects at either the subprogram or block level.
Deallocation cases can be addressed uniformly for both scopes in a future
patch, presumably with code insertion in routine `instantiateLocal`.
The exit code mechanism is not limited to block construct exits. It is
also available for use with other constructs. In particular, it is used
to replace custom deallocation code for a select case construct character
selector expression where applicable. This functionality is also added
to select type and associate constructs. It is available for use with
other constructs, such as select rank and image control constructs,
if that turns out to be necessary.
Overlapping nonfunctional changes include eliminating "FIR" from some
routine names and eliminating obsolete spaces in comments.
- always use genExprAddr when lowering to HLFIR: it does not create
temporary for array sections without vector subscripts, so there is
no need to have custom logic.
- update mangling to deal with AssocDetailsEntity. Their name is
required in HLFIR so that it can be added to the hlfir.declare
that is created for the selector once it is lowered. This should
allow getting debug info for selector when debug info are generated
from hlfir.declare.
The rest of associate construct lowering is unchanged and shared with
the current lowering.
This patch also enables select type lowering to work properly, but some
other todos (mainly about parent component references) prevents porting
the tests for now, so this will be done later.
Differential Revision: https://reviews.llvm.org/D144740
This removes another dependency of IntrinsicCall upon flang/lib/Lower:
making it possible to move IntrinsicCall into flang/lib/Optimizer.
Differential Revision: https://reviews.llvm.org/D143083
A previous patch (https://reviews.llvm.org/D136955) already refactored
intrinsic constant lowering to place in its own file and allow using it from
both the current lowering and the new lowering to HLFIR.
This patch does the same for derived types. The core function
"genStructComponentInInitializer" is moved from ConvertExpr.cpp and
renamed "genInlinedStructureCtorLitImpl" into ConvertConstant.cpp
without significant logic change.
Then, genScalarLit, genArrayLit (and genInlinedArrayLit/genOutlinedArrayLit)
are updated to support derived types.
The core aspect of derived type constant lowering that differs between
the current lowering and the HLFIR update is the way
addresses/initial target descriptors are built when part of a derived
type constant. This part happens in ConvertVariable.cpp (since the
address of a variable is taken in an initializer and is left TODO).
The mangling of derived type global literal constant is fixed: it did not embed
the derived type name and could cause "conflicts" between unrelated
derived types containing the same data. However, the hash remains
unstable between two compilation of the same file. This is not a
correctness issue and would require a lot of work to hash the derived
type constant data without hashing some irrelevant (but not out of bound)
data in the compile time data structure that holds derived type
constants (Constant<SomeDerived>). This may have to be revisited later.
Differential Revision: https://reviews.llvm.org/D140986
A submodule is a program unit that may contain the implementions of procedures
declared in an ancestor module or submodule.
Processing for the equivalence groups and variables declared in a submodule
scope is similar to existing processing for the equivalence groups and
variables in module and procedure scopes. However, module and procedure scopes
are tied directly to code in the Pre-FIR Tree (PFT), whereas processing for a
submodule must have access to an ancestor module scope that is guaranteed
to be present in a .mod file, but is not guaranteed to be in the PFT. This
difference is accommodated by tying processing directly to a front end scope.
Function scopes that can be processed on the fly are done that way; the
resulting variable information is never stored. Module and submodule scopes
whose symbol information may be needed during lowering of any number of module
procedures are instead cached on first use, and reused as needed.
These changes are a direct extension of current code. All module and submodule
variables in scope are processed, whether referenced or not. A possible
alternative would be to instead process symbols only when first used. While
this could ultimately be beneficial, such an approach must account for the
presence of equivalence groups. That information is not currently available
for on-the-fly variable processing.
Some additional changes are needed to include submodules in places where
modules must be considered, and to include separate module procedures in
places where other subprogram variants are considered. There is also a fix
for a bug involving the use of variables in an equivalence group in a
namelist group, which also involves scope processing code.
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated. The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.
This is part of an effort to migrate from llvm::Optional to
std::optional:
https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
Lower call with polymorphic entities to fir.dispatch operation. This patch only
focus one lowering with simple scalar polymorphic entities. A follow-up patch
will deal with allocatble, pointer and array of polymorphic entities as they
require box manipulation for the passed-object.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D135649
This patch replaces some `auto` with proper type. This was done in fir-dev
but not upstreamed yet.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: klausler
Differential Revision: https://reviews.llvm.org/D128350
- BIND(C) was ignored in lowering for objects (it can be used on
module and common blocks): use the bind name as the fir.global name.
- When an procedure is declared BIND(C) indirectly via an interface,
it should have a BIND(C) name. This was not the case because
GetBindName()/bindingName() return nothing in this case: detect this
case in mangler.cpp and use the symbol name.
Add TODOs for corner cases:
- BIND(C) module variables may be initialized on the C side. This does
not fit well with the current linkage strategy. Add a TODO until this
is revisited.
- BIND(C) internal procedures should not have a binding label (see
Fortran 2018 section 18.10.2 point 2), yet we currently lower them as
if they were BIND(C) external procedure.
I think this and the indirect interface case should really be
handled by symbol.GetBindName instead of adding more logic in
lowering to deal with this case: add a TODO.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: klausler
Differential Revision: https://reviews.llvm.org/D128340
Co-authored-by: Jean Perier <jperier@nvidia.com>
Remove a backwards dependence from Optimizer -> Lower by moving Todo.h
to the optimizer and out of lowering.
This patch is part of the upstreaming effort from fir-dev branch.
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D127292
This patch adds more lowering and tests for character array assignment/copy.
This patch is part of the upstreaming effort from fir-dev branch.
Depends on D121300
Reviewed By: PeteSteinfeld, schweitz
Differential Revision: https://reviews.llvm.org/D121301
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This patch lowers the `associate` construct.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D121239
Co-authored-by: V Donaldson <vdonaldson@nvidia.com>
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This patch hanlde lowering of simple scalar assignment.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D120058
Co-authored-by: Jean Perier <jperier@nvidia.com>
For "USE, INTRINSIC", search only for intrinsic modules;
for "USE, NON_INTRINSIC", do not recognize intrinsic modules.
Allow modules of both kinds with the same name to be used in
the same source file (but not in the same scoping unit, a
constraint of the standard that is now enforced).
The symbol table's scope tree now has a single instance of
a scope with a new kind, IntrinsicModules, whose children are
the USE'd intrinsic modules (explicit or not). This separate
"top-level" scope is a child of the single global scope and
it allows both intrinsic and non-intrinsic modules of the same
name to exist in the symbol table. Intrinsic modules' scopes'
symbols now have the INTRINSIC attribute set.
The search path directories need to make a distinction between
regular directories and the one(s) that point(s) to intrinsic
modules. I allow for multiple intrinsic module directories in
the second search path, although only one is needed today.
Differential Revision: https://reviews.llvm.org/D118631
Add support to create unique name for namelist group and be able to
deconstruct them.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D110331
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Add support to create unique name for namelist group and be able to
deconstruct them.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D110331
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Call static functions using the class name (fir::NameUniquer).
Add function for mangling derivedTypes.
All the name mangling functions that are ultimately called are
tested in unittests/Optimizer/InternalNamesTest.cpp.
Differential Revision: https://reviews.llvm.org/D99967
This module implements the lowering of Fortran intrinsics to the
corresponding calls in support libraries (the Fortran runtime, math
libraries, etc.)
This revision is a tad larger because there are a large number of Fortran
intrinsics and this adds lowering for a fair number of them.
Differential revision: https://reviews.llvm.org/D83355
This upstreams the internal name mangling used in the bridge to generate
unique names from symbols.
Replace InternalNamesTest with the actual, functional unittest.
Differential revision: https://reviews.llvm.org/D81764