Skip to content

[flang][runtime][NFC] Allow different memmove function in assign #114301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions flang/include/flang/Runtime/assign.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,35 @@
#define FORTRAN_RUNTIME_ASSIGN_H_

#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/freestanding-tools.h"

namespace Fortran::runtime {
class Descriptor;
class Terminator;

enum AssignFlags {
NoAssignFlags = 0,
MaybeReallocate = 1 << 0,
NeedFinalization = 1 << 1,
CanBeDefinedAssignment = 1 << 2,
ComponentCanBeDefinedAssignment = 1 << 3,
ExplicitLengthCharacterLHS = 1 << 4,
PolymorphicLHS = 1 << 5,
DeallocateLHS = 1 << 6
};

using MemmoveFct = void *(*)(void *, const void *, std::size_t);

static RT_API_ATTRS void *MemmoveWrapper(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the wrapper necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When building on the device the compiler is complaining when we address directly std:: function. Same was done in the allocator-registry

static RT_API_ATTRS void *MallocWrapper(std::size_t size) {
return std::malloc(size);
}
static RT_API_ATTRS void FreeWrapper(void *p) { return std::free(p); }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one that landed 7792dbe. Wrapper is not used on the host build.

void *dest, const void *src, std::size_t count) {
return Fortran::runtime::memmove(dest, src, count);
}

RT_API_ATTRS void Assign(Descriptor &to, const Descriptor &from,
Terminator &terminator, int flags, MemmoveFct memmoveFct = &MemmoveWrapper);

extern "C" {

// API for lowering assignment
void RTDECL(Assign)(Descriptor &to, const Descriptor &from,
const char *sourceFile = nullptr, int sourceLine = 0);
Expand Down
27 changes: 8 additions & 19 deletions flang/runtime/assign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@

namespace Fortran::runtime {

enum AssignFlags {
NoAssignFlags = 0,
MaybeReallocate = 1 << 0,
NeedFinalization = 1 << 1,
CanBeDefinedAssignment = 1 << 2,
ComponentCanBeDefinedAssignment = 1 << 3,
ExplicitLengthCharacterLHS = 1 << 4,
PolymorphicLHS = 1 << 5,
DeallocateLHS = 1 << 6
};

// Predicate: is the left-hand side of an assignment an allocated allocatable
// that must be deallocated?
static inline RT_API_ATTRS bool MustDeallocateLHS(
Expand Down Expand Up @@ -250,8 +239,8 @@ static RT_API_ATTRS void BlankPadCharacterAssignment(Descriptor &to,
// of elements, but their shape need not to conform (the assignment is done in
// element sequence order). This facilitates some internal usages, like when
// dealing with array constructors.
RT_API_ATTRS static void Assign(
Descriptor &to, const Descriptor &from, Terminator &terminator, int flags) {
RT_API_ATTRS void Assign(Descriptor &to, const Descriptor &from,
Terminator &terminator, int flags, MemmoveFct memmoveFct) {
bool mustDeallocateLHS{(flags & DeallocateLHS) ||
MustDeallocateLHS(to, from, terminator, flags)};
DescriptorAddendum *toAddendum{to.Addendum()};
Expand Down Expand Up @@ -423,14 +412,14 @@ RT_API_ATTRS static void Assign(
Assign(toCompDesc, fromCompDesc, terminator, nestedFlags);
} else { // Component has intrinsic type; simply copy raw bytes
std::size_t componentByteSize{comp.SizeInBytes(to)};
Fortran::runtime::memmove(to.Element<char>(toAt) + comp.offset(),
memmoveFct(to.Element<char>(toAt) + comp.offset(),
from.Element<const char>(fromAt) + comp.offset(),
componentByteSize);
}
break;
case typeInfo::Component::Genre::Pointer: {
std::size_t componentByteSize{comp.SizeInBytes(to)};
Fortran::runtime::memmove(to.Element<char>(toAt) + comp.offset(),
memmoveFct(to.Element<char>(toAt) + comp.offset(),
from.Element<const char>(fromAt) + comp.offset(),
componentByteSize);
} break;
Expand Down Expand Up @@ -476,14 +465,14 @@ RT_API_ATTRS static void Assign(
const auto &procPtr{
*procPtrDesc.ZeroBasedIndexedElement<typeInfo::ProcPtrComponent>(
k)};
Fortran::runtime::memmove(to.Element<char>(toAt) + procPtr.offset,
memmoveFct(to.Element<char>(toAt) + procPtr.offset,
from.Element<const char>(fromAt) + procPtr.offset,
sizeof(typeInfo::ProcedurePointer));
}
}
} else { // intrinsic type, intrinsic assignment
if (isSimpleMemmove()) {
Fortran::runtime::memmove(to.raw().base_addr, from.raw().base_addr,
memmoveFct(to.raw().base_addr, from.raw().base_addr,
toElements * toElementBytes);
} else if (toElementBytes > fromElementBytes) { // blank padding
switch (to.type().raw()) {
Expand All @@ -507,8 +496,8 @@ RT_API_ATTRS static void Assign(
} else { // elemental copies, possibly with character truncation
for (std::size_t n{toElements}; n-- > 0;
to.IncrementSubscripts(toAt), from.IncrementSubscripts(fromAt)) {
Fortran::runtime::memmove(to.Element<char>(toAt),
from.Element<const char>(fromAt), toElementBytes);
memmoveFct(to.Element<char>(toAt), from.Element<const char>(fromAt),
toElementBytes);
}
}
}
Expand Down
Loading