[flang][cuda] Add support for derived-type component with managed/unified attributes (#177409)

Derived-type components that have the `ALLOCATABLE` or `POINTER`
attribute as well as the CUDA `MANAGED` or `UNIFIED` attribute need to
have a specific allocator index set in the descriptor so the allocation
is done correctly. Without this, the allocation is done in host memory
and will trigger illegal read or write if the component is used on the
device. The correct allocator index was set some time ago for the
`DEVICE` attribute but the `MANAGED` and `UNIFIED` attribute need the
same mechanism.

Since the `Component::Genre` has quite some room I opted to add specific
genre for allocatable and pointer with both managed or unified
attribute.
@klausler Let me know if you would prefer another solution. I was
thinking about a separate field but I wanted to avoid wasting some
bytes.
This commit is contained in:
Valentin Clement (バレンタイン クレメン) 2026-01-22 14:08:48 -07:00 committed by GitHub
parent 5f6258b255
commit 3d3dd559a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 97 additions and 64 deletions

View File

@ -55,13 +55,19 @@ public:
Data = 1,
Pointer = 2,
Allocatable = 3,
Automatic = 4,
PointerDevice = 5,
AllocatableDevice = 6
Automatic = 4
};
enum class MemorySpace : std::uint8_t {
Host = 0,
Device = 1,
Managed = 2,
Unified = 3
};
RT_API_ATTRS const Descriptor &name() const { return name_.descriptor(); }
RT_API_ATTRS Genre genre() const { return genre_; }
RT_API_ATTRS MemorySpace memorySpace() const { return memorySpace_; }
RT_API_ATTRS TypeCategory category() const {
return static_cast<TypeCategory>(category_);
}
@ -107,6 +113,8 @@ private:
std::uint8_t category_; // common::TypeCategory
std::uint8_t kind_{0};
std::uint8_t rank_{0};
MemorySpace memorySpace_{MemorySpace::Host}; // memory space of the component
[[maybe_unused]] std::uint8_t padding_[3]; // 3 bytes padding
std::uint64_t offset_{0};
Value characterLen_; // for TypeCategory::Character
StaticDescriptor<0, true> derivedType_; // TYPE(DERIVEDTYPE), POINTER

View File

@ -648,8 +648,7 @@ RT_API_ATTRS int DerivedAssignTicket<IS_COMPONENTWISE>::Continue(
}
}
break;
case typeInfo::Component::Genre::Pointer:
case typeInfo::Component::Genre::PointerDevice: {
case typeInfo::Component::Genre::Pointer: {
std::size_t componentByteSize{
this->component_->SizeInBytes(this->instance_)};
if (IS_COMPONENTWISE && toIsContiguous_ && fromIsContiguous_) {
@ -681,7 +680,6 @@ RT_API_ATTRS int DerivedAssignTicket<IS_COMPONENTWISE>::Continue(
}
} break;
case typeInfo::Component::Genre::Allocatable:
case typeInfo::Component::Genre::AllocatableDevice:
case typeInfo::Component::Genre::Automatic: {
auto *toDesc{reinterpret_cast<Descriptor *>(
this->instance_.template Element<char>(this->subscripts_) +

View File

@ -168,8 +168,6 @@ RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[],
std::size_t nComponents{componentDesc.Elements()};
for (std::size_t j{0}; j < nComponents; ++j, ++component) {
if (component->genre() == typeInfo::Component::Genre::Allocatable ||
component->genre() ==
typeInfo::Component::Genre::AllocatableDevice ||
component->genre() == typeInfo::Component::Genre::Automatic) {
Descriptor &toDesc{
*reinterpret_cast<Descriptor *>(toPtr + component->offset())};

View File

@ -64,8 +64,7 @@ RT_API_ATTRS int InitializeTicket::Continue(WorkQueue &workQueue) {
char *rawInstance{instance_.OffsetElement<char>()};
for (; !Componentwise::IsComplete(); SkipToNextComponent()) {
char *rawComponent{rawInstance + component_->offset()};
if (component_->genre() == typeInfo::Component::Genre::Allocatable ||
component_->genre() == typeInfo::Component::Genre::AllocatableDevice) {
if (component_->genre() == typeInfo::Component::Genre::Allocatable) {
Descriptor &allocDesc{*reinterpret_cast<Descriptor *>(rawComponent)};
component_->EstablishDescriptor(
allocDesc, instance_, workQueue.terminator());
@ -78,8 +77,7 @@ RT_API_ATTRS int InitializeTicket::Continue(WorkQueue &workQueue) {
} else {
Fortran::runtime::memcpy(rawComponent, init, bytes);
}
} else if (component_->genre() == typeInfo::Component::Genre::Pointer ||
component_->genre() == typeInfo::Component::Genre::PointerDevice) {
} else if (component_->genre() == typeInfo::Component::Genre::Pointer) {
// Data pointers without explicit initialization are established
// so that they are valid right-hand side targets of pointer
// assignment statements.
@ -163,8 +161,7 @@ RT_API_ATTRS int InitializeClone(const Descriptor &clone,
RT_API_ATTRS int InitializeCloneTicket::Continue(WorkQueue &workQueue) {
while (!IsComplete()) {
if (component_->genre() == typeInfo::Component::Genre::Allocatable ||
component_->genre() == typeInfo::Component::Genre::AllocatableDevice) {
if (component_->genre() == typeInfo::Component::Genre::Allocatable) {
Descriptor &origDesc{*instance_.ElementComponent<Descriptor>(
subscripts_, component_->offset())};
if (origDesc.IsAllocated()) {
@ -341,9 +338,7 @@ RT_API_ATTRS int FinalizeTicket::Begin(WorkQueue &workQueue) {
RT_API_ATTRS int FinalizeTicket::Continue(WorkQueue &workQueue) {
while (!IsComplete()) {
if ((component_->genre() == typeInfo::Component::Genre::Allocatable ||
component_->genre() ==
typeInfo::Component::Genre::AllocatableDevice) &&
if (component_->genre() == typeInfo::Component::Genre::Allocatable &&
component_->category() == TypeCategory::Derived) {
// Component may be polymorphic or unlimited polymorphic. Need to use the
// dynamic type to check whether finalization is needed.
@ -365,7 +360,6 @@ RT_API_ATTRS int FinalizeTicket::Continue(WorkQueue &workQueue) {
}
}
} else if (component_->genre() == typeInfo::Component::Genre::Allocatable ||
component_->genre() == typeInfo::Component::Genre::AllocatableDevice ||
component_->genre() == typeInfo::Component::Genre::Automatic) {
if (const typeInfo::DerivedType *compType{component_->derivedType()};
compType && !compType->noFinalizationNeeded()) {
@ -448,8 +442,7 @@ RT_API_ATTRS int DestroyTicket::Continue(WorkQueue &workQueue) {
// Contrary to finalization, the order of deallocation does not matter.
while (!IsComplete()) {
const auto *componentDerived{component_->derivedType()};
if (component_->genre() == typeInfo::Component::Genre::Allocatable ||
component_->genre() == typeInfo::Component::Genre::AllocatableDevice) {
if (component_->genre() == typeInfo::Component::Genre::Allocatable) {
if (fixedStride_ &&
(!componentDerived || componentDerived->noDestructionNeeded())) {
// common fast path, just deallocate in every element

View File

@ -95,16 +95,18 @@ RT_API_ATTRS std::size_t Component::SizeInBytes(
RT_API_ATTRS void Component::EstablishDescriptor(Descriptor &descriptor,
const Descriptor &container, Terminator &terminator) const {
ISO::CFI_attribute_t attribute{static_cast<ISO::CFI_attribute_t>(
genre_ == Genre::Allocatable || genre_ == Genre::AllocatableDevice
? CFI_attribute_allocatable
: genre_ == Genre::Pointer || genre_ == Genre::PointerDevice
? CFI_attribute_pointer
: CFI_attribute_other)};
genre_ == Genre::Allocatable ? CFI_attribute_allocatable
: genre_ == Genre::Pointer ? CFI_attribute_pointer
: CFI_attribute_other)};
TypeCategory cat{category()};
unsigned allocatorIdx{
genre_ == Genre::AllocatableDevice || genre_ == Genre::PointerDevice
? kDeviceAllocatorPos
: kDefaultAllocator};
unsigned allocatorIdx{kDefaultAllocator};
if (memorySpace_ == MemorySpace::Device) {
allocatorIdx = kDeviceAllocatorPos;
} else if (memorySpace_ == MemorySpace::Managed) {
allocatorIdx = kManagedAllocatorPos;
} else if (memorySpace_ == MemorySpace::Unified) {
allocatorIdx = kUnifiedAllocatorPos;
}
if (cat == TypeCategory::Character) {
std::size_t lengthInChars{0};
if (auto length{characterLen_.GetValue(&container)}) {
@ -127,8 +129,7 @@ RT_API_ATTRS void Component::EstablishDescriptor(Descriptor &descriptor,
descriptor.Establish(
cat, kind_, nullptr, rank_, nullptr, attribute, false, allocatorIdx);
}
if (rank_ && genre_ != Genre::Allocatable && genre_ != Genre::Pointer &&
genre_ != Genre::AllocatableDevice && genre_ != Genre::PointerDevice) {
if (rank_ && genre_ != Genre::Allocatable && genre_ != Genre::Pointer) {
const typeInfo::Value *boundValues{bounds()};
RUNTIME_CHECK(terminator, boundValues != nullptr);
auto byteStride{static_cast<SubscriptValue>(descriptor.ElementBytes())};
@ -279,17 +280,14 @@ FILE *Component::Dump(FILE *f) const {
std::fputs(" Data ", f);
} else if (genre_ == Genre::Pointer) {
std::fputs(" Pointer ", f);
} else if (genre_ == Genre::PointerDevice) {
std::fputs(" PointerDevice ", f);
} else if (genre_ == Genre::Allocatable) {
std::fputs(" Allocatable. ", f);
} else if (genre_ == Genre::AllocatableDevice) {
std::fputs(" AllocatableDevice", f);
} else if (genre_ == Genre::Automatic) {
std::fputs(" Automatic ", f);
} else {
std::fprintf(f, " (bad genre 0x%x)", static_cast<int>(genre_));
}
// TODO: valentin
std::fprintf(f, " category %d kind %d rank %d offset 0x%zx\n", category_,
kind_, rank_, static_cast<std::size_t>(offset_));
const auto &dtDesc{derivedType_.descriptor()};

View File

@ -773,6 +773,10 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
symbol, foldingContext)};
bool isDevice{object.cudaDataAttr() &&
*object.cudaDataAttr() == common::CUDADataAttr::Device};
bool isManaged{object.cudaDataAttr() &&
*object.cudaDataAttr() == common::CUDADataAttr::Managed};
bool isUnified{object.cudaDataAttr() &&
*object.cudaDataAttr() == common::CUDADataAttr::Unified};
CHECK(typeAndShape.has_value());
auto dyType{typeAndShape->type()};
int rank{typeAndShape->Rank()};
@ -885,19 +889,9 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
// Default component initialization
bool hasDataInit{false};
if (IsAllocatable(symbol)) {
if (isDevice) {
AddValue(values, componentSchema_, "genre"s,
GetEnumValue("allocatabledevice"));
} else {
AddValue(values, componentSchema_, "genre"s, GetEnumValue("allocatable"));
}
AddValue(values, componentSchema_, "genre"s, GetEnumValue("allocatable"));
} else if (IsPointer(symbol)) {
if (isDevice) {
AddValue(
values, componentSchema_, "genre"s, GetEnumValue("pointerdevice"));
} else {
AddValue(values, componentSchema_, "genre"s, GetEnumValue("pointer"));
}
AddValue(values, componentSchema_, "genre"s, GetEnumValue("pointer"));
hasDataInit = InitializeDataPointer(
values, symbol, object, scope, dtScope, distinctName);
} else if (IsAutomatic(symbol)) {
@ -914,6 +908,15 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
object));
}
}
if (isDevice) {
AddValue(values, componentSchema_, "memoryspace"s, GetEnumValue("device"));
} else if (isManaged) {
AddValue(values, componentSchema_, "memoryspace"s, GetEnumValue("managed"));
} else if (isUnified) {
AddValue(values, componentSchema_, "memoryspace"s, GetEnumValue("unified"));
} else {
AddValue(values, componentSchema_, "memoryspace"s, GetEnumValue("host"));
}
if (!hasDataInit) {
AddValue(values, componentSchema_, "initialization"s,
SomeExpr{evaluate::NullPointer{}});

View File

@ -75,7 +75,11 @@ module __fortran_type_info
end type
enum, bind(c) ! Component::Genre
enumerator :: Data = 1, Pointer = 2, Allocatable = 3, Automatic = 4, PointerDevice = 5, AllocatableDevice = 6
enumerator :: Data = 1, Pointer = 2, Allocatable = 3, Automatic = 4
end enum
enum, bind(c) ! Component::MemorySpace
enumerator :: Host = 0, Device = 1, Managed = 2, Unified = 3
end enum
enum, bind(c) ! common::TypeCategory
@ -90,7 +94,8 @@ module __fortran_type_info
integer(1) :: category
integer(1) :: kind
integer(1) :: rank
integer(1) :: __padding0(4)
integer(1) :: memorySpace ! Component::MemorySpace
integer(1) :: __padding0(3)
integer(kind=int64) :: offset
type(Value) :: characterLen ! for category == Character
type(DerivedType), pointer :: derived ! for category == Derived

View File

@ -1,22 +1,52 @@
! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s
! RUN: bbc --dump-symbols -fcuda %s -o - | FileCheck %s --check-prefix=SYMBOLS
module m
! SYMBOLS-LABEL: Module scope: m
type device_array
real(kind=8), allocatable, dimension(:), device :: ad
real(kind=8), pointer, dimension(:), device :: pd
end type
! SYMBOLS: .c.device_array, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:1_8 init:[component::component(name=.n.ad,genre=3_1,category=2_1,kind=8_1,rank=1_1,memoryspace=1_1,offset=0_8
type managed_array
real(kind=8), allocatable, dimension(:), managed :: ad
real(kind=8), pointer, dimension(:), managed :: pd
end type
! SYMBOLS: .c.managed_array, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:1_8 init:[component::component(name=.n.ad,genre=3_1,category=2_1,kind=8_1,rank=1_1,memoryspace=2_1,offset=0_8
type unified_array
real(kind=8), allocatable, dimension(:), unified :: ad
real(kind=8), pointer, dimension(:), unified :: pd
end type
! SYMBOLS: .c.unified_array, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:1_8 init:[component::component(name=.n.ad,genre=3_1,category=2_1,kind=8_1,rank=1_1,memoryspace=3_1
type(device_array), allocatable :: da(:)
type(managed_array), allocatable :: ma(:)
type(unified_array), allocatable :: ua(:)
end module
! CHECK-LABEL: fir.global linkonce_odr @_QMmE.c.device_array
! CHECK: fir.insert_value %{{.*}}, %c6{{.*}}, ["genre"
! CHECK: fir.insert_value %{{.*}}, %c5{{.*}}, ["genre"
! CHECK: fir.insert_value %{{.*}}, %c1{{.*}}, ["memoryspace"
! CHECK-LABEL: fir.global linkonce_odr @_QMmE.c.managed_array
! CHECK: fir.insert_value %{{.*}}, %c2{{.*}}, ["memoryspace"
! CHECK-LABEL: fir.global linkonce_odr @_QMmE.c.unified_array
! CHECK: fir.insert_value %{{.*}}, %c3{{.*}}, ["memoryspace"
program main
use m
type(device_array) :: local
type(managed_array) :: local_ma
type(unified_array) :: local_ua
end
! CHECK-LABEL: func.func @_QQmain()
! CHECK: fir.call @_FortranAInitialize
! CHECK-COUNT-3: fir.call @_FortranAInitialize

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@ module m01
integer :: n
end type
!CHECK: Module scope: m01
!CHECK: .c.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.n,genre=1_1,category=0_1,kind=4_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.n,genre=1_1,category=0_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t1,sizeinbytes=4_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t1,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
!CHECK: .n.n, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: CHARACTER(1_8,1) init:"n"
!CHECK: .n.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: CHARACTER(2_8,1) init:"t1"
@ -21,8 +21,8 @@ module m02
type, extends(parent) :: child
integer :: cn
end type
!CHECK: .c.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:1_8 init:[component::component(name=.n.parent,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.parent,lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.cn,genre=1_1,category=0_1,kind=4_1,rank=0_1,offset=4_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.parent, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.pn,genre=1_1,category=0_1,kind=4_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:1_8 init:[component::component(name=.n.parent,genre=1_1,category=6_1,kind=0_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.parent,lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.cn,genre=1_1,category=0_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=4_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.parent, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.pn,genre=1_1,category=0_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.child,sizeinbytes=8_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.child,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=1_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
!CHECK: .dt.parent, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.parent,sizeinbytes=4_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.parent,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
end module
@ -33,7 +33,7 @@ module m03
real(kind=k) :: a
end type
type(kpdt(4)) :: x
!CHECK: .c.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.a,genre=1_1,category=2_1,kind=4_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.a,genre=1_1,category=2_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.kpdt, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(name=.n.kpdt,uninstantiated=NULL(),kindparameter=.kp.kpdt,lenparameterkind=NULL())
!CHECK: .dt.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.kpdt,sizeinbytes=4_8,uninstantiated=.dt.kpdt,kindparameter=.kp.kpdt.4,lenparameterkind=NULL(),component=.c.kpdt.4,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
!CHECK: .kp.kpdt.4, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: INTEGER(8) shape: 0_8:0_8 init:[INTEGER(8)::4_8]
@ -84,7 +84,7 @@ module m06
class(t2), intent(out) :: x
class(t), intent(in) :: y
end subroutine
!CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=2_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1)
!CHECK: .dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t2,name=.n.t2,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t2,procptr=NULL(),special=.s.t2,specialbitset=2_4,hasparent=1_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1)
!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s1)]
@ -112,7 +112,7 @@ module m06a
class(t), intent(out) :: x
class(t2), intent(in) :: y
end subroutine
!CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=2_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1)
!CHECK: .dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t2,name=.n.t2,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t2,procptr=NULL(),special=.s.t2,specialbitset=2_4,hasparent=1_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1)
!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s1)]
@ -260,7 +260,7 @@ module m11
real :: automatic(len)
end type
!CHECK: .b.t.automatic, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(value) shape: 0_8:1_8,0_8:0_8 init:reshape([value::value(genre=2_1,value=1_8),value(genre=3_1,value=0_8)],shape=[2,1])
!CHECK: .c.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:3_8 init:[component::component(name=.n.allocatable,genre=3_1,category=2_1,kind=4_1,rank=1_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.pointer,genre=2_1,category=2_1,kind=4_1,rank=0_1,offset=48_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=.di.t.pointer),component(name=.n.chauto,genre=4_1,category=4_1,kind=1_1,rank=0_1,offset=72_8,characterlen=value(genre=3_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.automatic,genre=4_1,category=2_1,kind=4_1,rank=1_1,offset=96_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.automatic,initialization=NULL())]
!CHECK: .c.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:3_8 init:[component::component(name=.n.allocatable,genre=3_1,category=2_1,kind=4_1,rank=1_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.pointer,genre=2_1,category=2_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=48_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=.di.t.pointer),component(name=.n.chauto,genre=4_1,category=4_1,kind=1_1,rank=0_1,memoryspace=0_1,offset=72_8,characterlen=value(genre=3_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL()),component(name=.n.automatic,genre=4_1,category=2_1,kind=4_1,rank=1_1,memoryspace=0_1,offset=96_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=.b.t.automatic,initialization=NULL())]
!CHECK: .di.t.pointer, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(.dp.t.pointer) init:.dp.t.pointer(pointer=target)
!CHECK: .dp.t.pointer (CompilerCreated): DerivedType components: pointer
!CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=144_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=.lpk.t,component=.c.t,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=0_1,nodestructionneeded=0_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)

View File

@ -12,7 +12,7 @@ module m
end module
!CHECK: Module scope: m size=0 alignment=1 sourceRange=113 bytes
!CHECK: .c.s, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t1,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .c.s, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t1,genre=1_1,category=6_1,kind=0_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
!CHECK: .dt.s, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.s,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=.lpk.s,component=.c.s,procptr=NULL(),special=NULL(),specialbitset=0_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
!CHECK: .lpk.s, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: INTEGER(1) shape: 0_8:0_8 init:[INTEGER(1)::4_1]
!CHECK: .n.s, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: CHARACTER(1_8,1) init:"s"