[flang] Add struct passing target rewrite hooks and partial X86-64 impl (#74829)
commit27d9a479c09632db4fef8eac204764de97d52925
authorjeanPerier <jperier@nvidia.com>
Tue, 12 Dec 2023 10:52:39 +0000 (12 11:52 +0100)
committerGitHub <noreply@github.com>
Tue, 12 Dec 2023 10:52:39 +0000 (12 11:52 +0100)
tree9fbb239375c0860d7bef85f463208e51a87216d2
parent2bab0e01676ce7c9609a60bf86cb07c17f6080f0
[flang] Add struct passing target rewrite hooks and partial X86-64 impl (#74829)

In the context of C/Fortran interoperability (BIND(C)), it is possible
to give the VALUE attribute to a BIND(C) derived type dummy, which
according to Fortran 2018 18.3.6 - 2. (4) implies that it must be passed
like the equivalent C structure value. The way C structure value are
passed is ABI dependent.

LLVM does not implement the C struct ABI passing for LLVM aggregate type
arguments. It is up to the front-end, like clang is doing, to split the
struct into registers or pass the struct on the stack (llvm "byval") as
required by the target ABI.
So the logic for C struct passing sits in clang. Using it from flang
requires setting up a lot of clang context and to bridge FIR/MLIR
representation to clang AST representation for function signatures (in
both directions). It is a non trivial task.
See
https://stackoverflow.com/questions/39438033/passing-structs-by-value-in-llvm-ir/75002581#75002581.

Since BIND(C) struct are rather limited as opposed to generic C struct
(e.g. no bit fields). It is easier to provide a limited implementation
of it for the case that matter to Fortran.

This patch:
- Updates the generic target rewrite pass to keep track of both the new
argument type and attributes. The motivation for this is to be able to
tell if a previously marshalled argument is passed in memory (it is a C
pointer), or if it is being passed on the stack (has the byval llvm
attributes).
- Adds an entry point in the target specific codegen to marshal struct
arguments, and use it in the generic target rewrite pass.
- Implements limited support for the X86-64 case. So far, the support
allows telling if a struct must be passed in register or on the stack,
and to deal with the stack case. The register case is left TODO in this
patch.

The X86-64 ABI implemented is the System V ABI for AMD64 version 1.0
13 files changed:
flang/include/flang/Optimizer/CodeGen/CGPasses.td
flang/include/flang/Optimizer/CodeGen/Target.h
flang/include/flang/Optimizer/CodeGen/TypeConverter.h
flang/include/flang/Optimizer/Dialect/FIRTypes.td
flang/include/flang/Optimizer/Support/DataLayout.h
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/lib/Optimizer/CodeGen/Target.cpp
flang/lib/Optimizer/CodeGen/TargetRewrite.cpp
flang/lib/Optimizer/CodeGen/TypeConverter.cpp
flang/lib/Optimizer/Dialect/FIRType.cpp
flang/lib/Optimizer/Support/DataLayout.cpp
flang/test/Fir/recursive-type-tco.fir
flang/test/Fir/struct-passing-x86-64-byval.fir [new file with mode: 0644]