Skip to content

Commit

Permalink
[Flang][NFC] Split runtime headers in preparation for cross-compilati…
Browse files Browse the repository at this point in the history
…on. (#112188)

Split some headers into headers for public and private declarations in
preparation for #110217. Moving the runtime-private headers in
runtime-private include directory will occur in #110298.

* Do not use `sizeof(Descriptor)` in the compiler. The size of the
descriptor is target-dependent while `sizeof(Descriptor)` is the size of
the Descriptor for the host platform which might be too small when
cross-compiling to a different platform. Another problem is that the
emitted assembly ((cross-)compiling to the same target) is not identical
between Flang's running on different systems. Moving the declaration of
`class Descriptor` out of the included header will also reduce the
amount of #included sources.

* Do not use `sizeof(ArrayConstructorVector)` and
`alignof(ArrayConstructorVector)` in the compiler. Same reason as with
`Descriptor`.

* Compute the descriptor's extra flags without instantiating a
Descriptor. `Fortran::runtime::Descriptor` is defined in the runtime
source, but not the compiler source.

* Move `InquiryKeywordHashDecode` into runtime-private header. The
function is defined in the runtime sources and trying to call it in the
compiler would lead to a link-error.

* Move allocator-kind magic numbers into common header. They are the
only declarations out of `allocator-registry.h` in the compiler as well.
 
This does not make Flang cross-compile ready yet, the main goal is to
avoid transitive header dependencies from Flang to clang-rt. There are
more assumptions that host platform is the same as the target platform.
  • Loading branch information
Meinersbur authored Dec 6, 2024
1 parent 1801fb4 commit c91ba04
Show file tree
Hide file tree
Showing 41 changed files with 728 additions and 567 deletions.
2 changes: 1 addition & 1 deletion flang/include/flang/Lower/Allocatable.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#include "flang/Lower/AbstractConverter.h"
#include "flang/Optimizer/Builder/MutableBox.h"
#include "flang/Runtime/allocator-registry.h"
#include "flang/Runtime/allocator-registry-consts.h"
#include "llvm/ADT/StringRef.h"

namespace mlir {
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "flang/Optimizer/Builder/Runtime/Numeric.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/iostat.h"
#include "flang/Runtime/iostat-consts.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Math/IR/Math.h"
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/MutableBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#define FORTRAN_OPTIMIZER_BUILDER_MUTABLEBOX_H

#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Runtime/allocator-registry.h"
#include "flang/Runtime/allocator-registry-consts.h"
#include "llvm/ADT/StringRef.h"

namespace mlir {
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/CodeGen/DescriptorModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define OPTIMIZER_DESCRIPTOR_MODEL_H

#include "flang/ISO_Fortran_binding_wrapper.h"
#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/CUDA/allocatable.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef FORTRAN_RUNTIME_CUDA_ALLOCATABLE_H_
#define FORTRAN_RUNTIME_CUDA_ALLOCATABLE_H_

#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"

namespace Fortran::runtime::cuda {
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/CUDA/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#define FORTRAN_RUNTIME_CUDA_ALLOCATOR_H_

#include "common.h"
#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"

namespace Fortran::runtime::cuda {
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/CUDA/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef FORTRAN_RUNTIME_CUDA_COMMON_H_
#define FORTRAN_RUNTIME_CUDA_COMMON_H_

#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"

/// Type of memory for allocation/deallocation
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/CUDA/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef FORTRAN_RUNTIME_CUDA_DESCRIPTOR_H_
#define FORTRAN_RUNTIME_CUDA_DESCRIPTOR_H_

#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"
#include <cstddef>

Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/CUDA/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef FORTRAN_RUNTIME_CUDA_MEMORY_H_
#define FORTRAN_RUNTIME_CUDA_MEMORY_H_

#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"
#include <cstddef>

Expand Down
20 changes: 20 additions & 0 deletions flang/include/flang/Runtime/allocator-registry-consts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- include/flang/Runtime/allocator-registry-consts.h -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_
#define FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_

static constexpr unsigned kDefaultAllocator = 0;

// Allocator used for CUF
static constexpr unsigned kPinnedAllocatorPos = 1;
static constexpr unsigned kDeviceAllocatorPos = 2;
static constexpr unsigned kManagedAllocatorPos = 3;
static constexpr unsigned kUnifiedAllocatorPos = 4;

#endif /* FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_ */
9 changes: 1 addition & 8 deletions flang/include/flang/Runtime/allocator-registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,11 @@
#define FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_H_

#include "flang/Common/api-attrs.h"
#include "flang/Runtime/allocator-registry-consts.h"
#include <cstdint>
#include <cstdlib>
#include <vector>

static constexpr unsigned kDefaultAllocator = 0;

// Allocator used for CUF
static constexpr unsigned kPinnedAllocatorPos = 1;
static constexpr unsigned kDeviceAllocatorPos = 2;
static constexpr unsigned kManagedAllocatorPos = 3;
static constexpr unsigned kUnifiedAllocatorPos = 4;

#define MAX_ALLOCATOR 7 // 3 bits are reserved in the descriptor.

namespace Fortran::runtime {
Expand Down
97 changes: 97 additions & 0 deletions flang/include/flang/Runtime/array-constructor-consts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===-- include/flang/Runtime/array-constructor-consts.h --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_RUNTIME_ARRAY_CONSTRUCTOR_CONSTS_H_
#define FORTRAN_RUNTIME_ARRAY_CONSTRUCTOR_CONSTS_H_

#include "flang/Runtime/descriptor-consts.h"
#include "flang/Runtime/entry-names.h"
#include <cstdint>

namespace Fortran::runtime {
struct ArrayConstructorVector;

// Max sizeof(ArrayConstructorVector) and sizeof(ArrayConstructorVector) for any
// target.
// TODO: Use target-specific size/alignment instead of overapproximation.
constexpr std::size_t MaxArrayConstructorVectorSizeInBytes = 2 * 40;
constexpr std::size_t MaxArrayConstructorVectorAlignInBytes = 8;

// This file defines an API to "push" an evaluated array constructor value
// "from" into some storage "to" of an array constructor. It can be seen as a
// form of std::vector::push_back() implementation for Fortran array
// constructors. In the APIs and ArrayConstructorVector struct above:
//
// - "to" is a ranked-1 descriptor whose declared type is already set to the
// array constructor derived type. It may be already allocated, even before the
// first call to this API, or it may be unallocated. "to" extent is increased
// every time a "from" is pushed past its current extent. At this end of the
// API calls, its extent is the extent of the array constructor. If "to" is
// unallocated and its extent is not null, it is assumed this is the final array
// constructor extent value, and the first allocation already "reserves" storage
// space accordingly to avoid reallocations.
// - "from" is a scalar or array descriptor for the evaluated array
// constructor value that must be copied into the storage of "to" at
// "nextValuePosition".
// - "useValueLengthParameters" must be set to true if the array constructor
// has length parameters and no type spec. If it is true and "to" is
// unallocated, "to" will take the length parameters of "from". If it is true
// and "to" is an allocated character array constructor, it will be checked
// that "from" length matches the one from "to". When it is false, the
// character length must already be set in "to" before the first call to this
// API and "from" character lengths are allowed to mismatch from "to".
// - "nextValuePosition" is the zero based sequence position of "from" in the
// array constructor. It is updated after this call by the number of "from"
// elements. It should be set to zero by the caller of this API before the first
// call.
// - "actualAllocationSize" is the current allocation size of "to" storage. It
// may be bigger than "to" extent for reallocation optimization purposes, but
// should never be smaller, unless this is the first call and "to" is
// unallocated. It is updated by the runtime after each successful allocation or
// reallocation. It should be set to "to" extent if "to" is allocated before the
// first call of this API, and can be left undefined otherwise.
//
// Note that this API can be used with "to" being a variable (that can be
// discontiguous). This can be done when the variable is the left hand side of
// an assignment from an array constructor as long as:
// - none of the ac-value overlaps with the variable,
// - this is an intrinsic assignment that is not a whole allocatable
// assignment, *and* for a type that has no components requiring user defined
// assignments,
// - the variable is properly finalized before using this API if its need to,
// - "useValueLengthParameters" should be set to false in this case, even if
// the array constructor has no type-spec, since the variable may have a
// different character length than the array constructor values.

extern "C" {
// API to initialize an ArrayConstructorVector before any values are pushed to
// it. Inlined code is only expected to allocate the "ArrayConstructorVector"
// class instance storage with sufficient size
// (MaxArrayConstructorVectorSizeInBytes is expected to be large enough for all
// supported targets). This avoids the need for the runtime to maintain a state,
// or to use dynamic allocation for it.
void RTDECL(InitArrayConstructorVector)(ArrayConstructorVector &vector,
Descriptor &to, bool useValueLengthParameters,
const char *sourceFile = nullptr, int sourceLine = 0);

// Generic API to push any kind of entity into the array constructor (any
// Fortran type and any rank).
void RTDECL(PushArrayConstructorValue)(
ArrayConstructorVector &vector, const Descriptor &from);

// API to push scalar array constructor value of:
// - a numerical or logical type,
// - or a derived type that has no length parameters, and no allocatable
// component (that would require deep copies).
// It requires no descriptor for the value that is passed via its base address.
void RTDECL(PushArrayConstructorSimpleScalar)(
ArrayConstructorVector &vector, void *from);
} // extern "C"
} // namespace Fortran::runtime

#endif /* FORTRAN_RUNTIME_ARRAY_CONSTRUCTOR_CONSTS_H_ */
79 changes: 9 additions & 70 deletions flang/include/flang/Runtime/array-constructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#ifndef FORTRAN_RUNTIME_ARRAYCONSTRUCTOR_H_
#define FORTRAN_RUNTIME_ARRAYCONSTRUCTOR_H_

#include "flang/Runtime/array-constructor-consts.h"
#include "flang/Runtime/descriptor.h"
#include "flang/Runtime/entry-names.h"
#include <cstdint>
Expand Down Expand Up @@ -43,76 +44,14 @@ struct ArrayConstructorVector {
unsigned char useValueLengthParameters_ : 1;
};

// This file defines an API to "push" an evaluated array constructor value
// "from" into some storage "to" of an array constructor. It can be seen as a
// form of std::vector::push_back() implementation for Fortran array
// constructors. In the APIs and ArrayConstructorVector struct above:
//
// - "to" is a ranked-1 descriptor whose declared type is already set to the
// array constructor derived type. It may be already allocated, even before the
// first call to this API, or it may be unallocated. "to" extent is increased
// every time a "from" is pushed past its current extent. At this end of the
// API calls, its extent is the extent of the array constructor. If "to" is
// unallocated and its extent is not null, it is assumed this is the final array
// constructor extent value, and the first allocation already "reserves" storage
// space accordingly to avoid reallocations.
// - "from" is a scalar or array descriptor for the evaluated array
// constructor value that must be copied into the storage of "to" at
// "nextValuePosition".
// - "useValueLengthParameters" must be set to true if the array constructor
// has length parameters and no type spec. If it is true and "to" is
// unallocated, "to" will take the length parameters of "from". If it is true
// and "to" is an allocated character array constructor, it will be checked
// that "from" length matches the one from "to". When it is false, the
// character length must already be set in "to" before the first call to this
// API and "from" character lengths are allowed to mismatch from "to".
// - "nextValuePosition" is the zero based sequence position of "from" in the
// array constructor. It is updated after this call by the number of "from"
// elements. It should be set to zero by the caller of this API before the first
// call.
// - "actualAllocationSize" is the current allocation size of "to" storage. It
// may be bigger than "to" extent for reallocation optimization purposes, but
// should never be smaller, unless this is the first call and "to" is
// unallocated. It is updated by the runtime after each successful allocation or
// reallocation. It should be set to "to" extent if "to" is allocated before the
// first call of this API, and can be left undefined otherwise.
//
// Note that this API can be used with "to" being a variable (that can be
// discontiguous). This can be done when the variable is the left hand side of
// an assignment from an array constructor as long as:
// - none of the ac-value overlaps with the variable,
// - this is an intrinsic assignment that is not a whole allocatable
// assignment, *and* for a type that has no components requiring user defined
// assignments,
// - the variable is properly finalized before using this API if its need to,
// - "useValueLengthParameters" should be set to false in this case, even if
// the array constructor has no type-spec, since the variable may have a
// different character length than the array constructor values.

extern "C" {
// API to initialize an ArrayConstructorVector before any values are pushed to
// it. Inlined code is only expected to allocate the "ArrayConstructorVector"
// class instance storage with sufficient size (using
// "2*sizeof(ArrayConstructorVector)" on the host should be safe regardless of
// the target the runtime is compiled for). This avoids the need for the runtime
// to maintain a state, or to use dynamic allocation for it. "vectorClassSize"
// is used to validate that lowering allocated enough space for it.
void RTDECL(InitArrayConstructorVector)(ArrayConstructorVector &vector,
Descriptor &to, bool useValueLengthParameters, int vectorClassSize,
const char *sourceFile = nullptr, int sourceLine = 0);

// Generic API to push any kind of entity into the array constructor (any
// Fortran type and any rank).
void RTDECL(PushArrayConstructorValue)(
ArrayConstructorVector &vector, const Descriptor &from);
static_assert(sizeof(Fortran::runtime::ArrayConstructorVector) <=
MaxArrayConstructorVectorSizeInBytes,
"ABI requires sizeof(ArrayConstructorVector) to be smaller than "
"MaxArrayConstructorVectorSizeInBytes");
static_assert(alignof(Fortran::runtime::ArrayConstructorVector) <=
MaxArrayConstructorVectorAlignInBytes,
"ABI requires alignof(ArrayConstructorVector) to be smaller than "
"MaxArrayConstructorVectorAlignInBytes");

// API to push scalar array constructor value of:
// - a numerical or logical type,
// - or a derived type that has no length parameters, and no allocatable
// component (that would require deep copies).
// It requires no descriptor for the value that is passed via its base address.
void RTDECL(PushArrayConstructorSimpleScalar)(
ArrayConstructorVector &vector, void *from);
} // extern "C"
} // namespace Fortran::runtime
#endif // FORTRAN_RUNTIME_ARRAYCONSTRUCTOR_H_
74 changes: 74 additions & 0 deletions flang/include/flang/Runtime/descriptor-consts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===-- include/flang/Runtime/descriptor-consts.h ---------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_RUNTIME_DESCRIPTOR_CONSTS_H_
#define FORTRAN_RUNTIME_DESCRIPTOR_CONSTS_H_

#include "flang/Common/api-attrs.h"
#include "flang/ISO_Fortran_binding_wrapper.h"
#include <cstddef>
#include <cstdint>

// Value of the addendum presence flag.
#define _CFI_ADDENDUM_FLAG 1
// Number of bits needed to be shifted when manipulating the allocator index.
#define _CFI_ALLOCATOR_IDX_SHIFT 1
// Allocator index mask.
#define _CFI_ALLOCATOR_IDX_MASK 0b00001110

namespace Fortran::runtime::typeInfo {
using TypeParameterValue = std::int64_t;
class DerivedType;
} // namespace Fortran::runtime::typeInfo

namespace Fortran::runtime {
class Descriptor;
using SubscriptValue = ISO::CFI_index_t;

/// Returns size in bytes of the descriptor (not the data)
/// This must be at least as large as the largest descriptor of any target
/// triple.
static constexpr RT_API_ATTRS std::size_t MaxDescriptorSizeInBytes(
int rank, bool addendum = false, int lengthTypeParameters = 0) {
// Layout:
//
// fortran::runtime::Descriptor {
// ISO::CFI_cdesc_t {
// void *base_addr; (pointer -> up to 8 bytes)
// size_t elem_len; (up to 8 bytes)
// int version; (up to 4 bytes)
// CFI_rank_t rank; (unsigned char -> 1 byte)
// CFI_type_t type; (signed char -> 1 byte)
// CFI_attribute_t attribute; (unsigned char -> 1 byte)
// unsigned char extra; (1 byte)
// }
// }
// fortran::runtime::Dimension[rank] {
// ISO::CFI_dim_t {
// CFI_index_t lower_bound; (ptrdiff_t -> up to 8 bytes)
// CFI_index_t extent; (ptrdiff_t -> up to 8 bytes)
// CFI_index_t sm; (ptrdiff_t -> up to 8 bytes)
// }
// }
// fortran::runtime::DescriptorAddendum {
// const typeInfo::DerivedType *derivedType_; (pointer -> up to 8
// bytes) typeInfo::TypeParameterValue len_[lenParameters]; (int64_t -> 8
// bytes)
// }
std::size_t bytes{24u + rank * 24u};
if (addendum || lengthTypeParameters > 0) {
if (lengthTypeParameters < 1)
lengthTypeParameters = 1;
bytes += 8u + static_cast<std::size_t>(lengthTypeParameters) * 8u;
}
return bytes;
}

} // namespace Fortran::runtime

#endif /* FORTRAN_RUNTIME_DESCRIPTOR_CONSTS_H_ */
Loading

0 comments on commit c91ba04

Please sign in to comment.