mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 11:02:04 +08:00
[Flang][OpenMP][Runtime] Minor Flang runtime for OpenMP AMDGPU modifications (#152631)
We have some modifications downstream to compile the flang runtime for amdgpu using clang OpenMP, some more hacky than others to workaround (hopefully temporary) compiler issues. The additions here are the non-hacky alterations. Main changes: * Create freestanding versions of memcpy, strlen and memmove, and replace std:: references with these so that we can default to std:: when it's available, or our own Flang implementation when it's not. * Wrap more bits and pieces of the library in declare target wrappers (RT_* macros). * Fix some warnings that'll pose issues with werror on, in this case having the namespace infront of variables passed to templates. Another minor issues that'll likely still pop up depending on the program you're linking with is that abort will be undefined, it is perhaps possible to solve it with a freestanding implementation as with memcpy etc. but we end up with multiple definitions in this case. An alternative is to create an empty extern "c" version (which can be empty or forwrd on to the builtin). Co-author: Dan Palermo Dan.Palermo@amd.com
This commit is contained in:
@@ -158,8 +158,8 @@ private:
|
||||
// Avoid passing a null pointer, since it would result in an undefined
|
||||
// behavior.
|
||||
if (old != nullptr) {
|
||||
std::memcpy(buffer_, old + start_, chunk);
|
||||
std::memcpy(buffer_ + chunk, old, length_ - chunk);
|
||||
runtime::memcpy(buffer_, old + start_, chunk);
|
||||
runtime::memcpy(buffer_ + chunk, old, length_ - chunk);
|
||||
FreeMemory(old);
|
||||
}
|
||||
start_ = 0;
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
/// Value used for asyncObject when no specific stream is specified.
|
||||
static constexpr std::int64_t *kNoAsyncObject = nullptr;
|
||||
RT_OFFLOAD_VAR_GROUP_END
|
||||
|
||||
namespace Fortran::runtime {
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ RT_API_ATTRS FormatControl<CONTEXT>::FormatControl(const Terminator &terminator,
|
||||
SubscriptValue at[maxRank];
|
||||
formatDescriptor->GetLowerBounds(at);
|
||||
for (std::size_t j{0}; j < elements; ++j) {
|
||||
std::memcpy(p, formatDescriptor->Element<char>(at), elementBytes);
|
||||
runtime::memcpy(p, formatDescriptor->Element<char>(at), elementBytes);
|
||||
p += elementBytes;
|
||||
formatDescriptor->IncrementSubscripts(at);
|
||||
}
|
||||
|
||||
@@ -560,9 +560,9 @@ RT_API_ATTRS void CopyAndPad(
|
||||
to[j] = static_cast<TO>(' ');
|
||||
}
|
||||
} else if (toChars <= fromChars) {
|
||||
std::memcpy(to, from, toChars * sizeof(TO));
|
||||
runtime::memcpy(to, from, toChars * sizeof(TO));
|
||||
} else {
|
||||
std::memcpy(to, from, std::min(toChars, fromChars) * sizeof(TO));
|
||||
runtime::memcpy(to, from, std::min(toChars, fromChars) * sizeof(TO));
|
||||
for (std::size_t j{fromChars}; j < toChars; ++j) {
|
||||
to[j] = static_cast<TO>(' ');
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ void RTDEF(PushArrayConstructorSimpleScalar)(
|
||||
AllocateOrReallocateVectorIfNeeded(vector, terminator, to.Elements(), 1);
|
||||
SubscriptValue subscript[1]{
|
||||
to.GetDimension(0).LowerBound() + vector.nextValuePosition};
|
||||
std::memcpy(to.Element<char>(subscript), from, to.ElementBytes());
|
||||
runtime::memcpy(to.Element<char>(subscript), from, to.ElementBytes());
|
||||
++vector.nextValuePosition;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ RT_API_ATTRS int AssignTicket::Begin(WorkQueue &workQueue) {
|
||||
if (mustDeallocateLHS) {
|
||||
// Convert the LHS into a temporary, then make it look deallocated.
|
||||
toDeallocate_ = &tempDescriptor_.descriptor();
|
||||
std::memcpy(
|
||||
runtime::memcpy(
|
||||
reinterpret_cast<void *>(toDeallocate_), &to_, to_.SizeInBytes());
|
||||
to_.set_base_addr(nullptr);
|
||||
if (toDerived_ && (flags_ & NeedFinalization)) {
|
||||
@@ -307,7 +307,7 @@ RT_API_ATTRS int AssignTicket::Begin(WorkQueue &workQueue) {
|
||||
auto descBytes{from_->SizeInBytes()};
|
||||
Descriptor &newFrom{tempDescriptor_.descriptor()};
|
||||
persist_ = true; // tempDescriptor_ state must outlive child tickets
|
||||
std::memcpy(reinterpret_cast<void *>(&newFrom), from_, descBytes);
|
||||
runtime::memcpy(reinterpret_cast<void *>(&newFrom), from_, descBytes);
|
||||
// Pretend the temporary descriptor is for an ALLOCATABLE
|
||||
// entity, otherwise, the Deallocate() below will not
|
||||
// free the descriptor memory.
|
||||
|
||||
@@ -616,8 +616,8 @@ void RTDEF(CharacterConcatenate)(Descriptor &accumulator,
|
||||
from.GetLowerBounds(fromAt);
|
||||
for (; elements-- > 0;
|
||||
to += newBytes, p += oldBytes, from.IncrementSubscripts(fromAt)) {
|
||||
std::memcpy(to, p, oldBytes);
|
||||
std::memcpy(to + oldBytes, from.Element<char>(fromAt), fromBytes);
|
||||
runtime::memcpy(to, p, oldBytes);
|
||||
runtime::memcpy(to + oldBytes, from.Element<char>(fromAt), fromBytes);
|
||||
}
|
||||
FreeMemory(old);
|
||||
}
|
||||
@@ -698,7 +698,7 @@ void RTDEF(CharacterCompare)(
|
||||
std::size_t RTDEF(CharacterAppend1)(char *lhs, std::size_t lhsBytes,
|
||||
std::size_t offset, const char *rhs, std::size_t rhsBytes) {
|
||||
if (auto n{std::min(lhsBytes - offset, rhsBytes)}) {
|
||||
std::memcpy(lhs + offset, rhs, n);
|
||||
runtime::memcpy(lhs + offset, rhs, n);
|
||||
offset += n;
|
||||
}
|
||||
return offset;
|
||||
@@ -706,7 +706,7 @@ std::size_t RTDEF(CharacterAppend1)(char *lhs, std::size_t lhsBytes,
|
||||
|
||||
void RTDEF(CharacterPad1)(char *lhs, std::size_t bytes, std::size_t offset) {
|
||||
if (bytes > offset) {
|
||||
std::memset(lhs + offset, ' ', bytes - offset);
|
||||
runtime::memset(lhs + offset, ' ', bytes - offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,7 +838,7 @@ void RTDEF(Repeat)(Descriptor &result, const Descriptor &string,
|
||||
}
|
||||
const char *from{string.OffsetElement()};
|
||||
for (char *to{result.OffsetElement()}; ncopies-- > 0; to += origBytes) {
|
||||
std::memcpy(to, from, origBytes);
|
||||
runtime::memcpy(to, from, origBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ static std::int64_t StringLength(const char *string) {
|
||||
|
||||
static void FillWithSpaces(const Descriptor &value, std::size_t offset = 0) {
|
||||
if (offset < value.ElementBytes()) {
|
||||
std::memset(
|
||||
runtime::memset(
|
||||
value.OffsetElement(offset), ' ', value.ElementBytes() - offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "flang-rt/runtime/terminator.h"
|
||||
#include "flang-rt/runtime/type-info.h"
|
||||
#include "flang/Runtime/allocatable.h"
|
||||
#include "flang/Runtime/freestanding-tools.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Fortran::runtime {
|
||||
@@ -101,7 +103,7 @@ RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[],
|
||||
char *toPtr{to.Element<char>(toAt)};
|
||||
char *fromPtr{from.Element<char>(fromAt)};
|
||||
RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes());
|
||||
std::memcpy(toPtr, fromPtr, to.ElementBytes());
|
||||
runtime::memcpy(toPtr, fromPtr, to.ElementBytes());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -148,7 +150,7 @@ RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[],
|
||||
// Moreover, if we came here from an Component::Genre::Data component,
|
||||
// all the per-element copies are redundant, because the parent
|
||||
// has already been copied as a whole.
|
||||
std::memcpy(toPtr, fromPtr, curTo.ElementBytes());
|
||||
runtime::memcpy(toPtr, fromPtr, curTo.ElementBytes());
|
||||
--elements;
|
||||
if (elements != 0) {
|
||||
currentCopy.IncrementSubscripts(terminator);
|
||||
|
||||
@@ -71,7 +71,7 @@ RT_API_ATTRS int InitializeTicket::Continue(WorkQueue &workQueue) {
|
||||
// Explicit initialization of data pointers and
|
||||
// non-allocatable non-automatic components
|
||||
std::size_t bytes{component_->SizeInBytes(instance_)};
|
||||
std::memcpy(rawComponent, init, bytes);
|
||||
runtime::memcpy(rawComponent, init, bytes);
|
||||
} 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
|
||||
@@ -108,20 +108,20 @@ RT_API_ATTRS int InitializeTicket::Continue(WorkQueue &workQueue) {
|
||||
chunk = done;
|
||||
}
|
||||
char *uninitialized{rawInstance + done * *stride};
|
||||
std::memcpy(uninitialized, rawInstance, chunk * *stride);
|
||||
runtime::memcpy(uninitialized, rawInstance, chunk * *stride);
|
||||
done += chunk;
|
||||
}
|
||||
} else {
|
||||
for (std::size_t done{1}; done < elements_; ++done) {
|
||||
char *uninitialized{rawInstance + done * *stride};
|
||||
std::memcpy(uninitialized, rawInstance, elementBytes);
|
||||
runtime::memcpy(uninitialized, rawInstance, elementBytes);
|
||||
}
|
||||
}
|
||||
} else { // one at a time with subscription
|
||||
for (Elementwise::Advance(); !Elementwise::IsComplete();
|
||||
Elementwise::Advance()) {
|
||||
char *element{instance_.Element<char>(subscripts_)};
|
||||
std::memcpy(element, rawInstance, elementBytes);
|
||||
runtime::memcpy(element, rawInstance, elementBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ static RT_API_ATTRS common::optional<bool> DefinedFormattedIo(
|
||||
if (edit.descriptor == DataEdit::DefinedDerivedType) {
|
||||
ioType[0] = 'D';
|
||||
ioType[1] = 'T';
|
||||
std::memcpy(ioType + 2, edit.ioType, edit.ioTypeChars);
|
||||
runtime::memcpy(ioType + 2, edit.ioType, edit.ioTypeChars);
|
||||
} else {
|
||||
runtime::strcpy(
|
||||
ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED");
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "flang-rt/runtime/terminator.h"
|
||||
#include "flang-rt/runtime/type-info.h"
|
||||
#include "flang/Common/type-kinds.h"
|
||||
#include "flang/Runtime/freestanding-tools.h"
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -26,7 +27,7 @@ RT_OFFLOAD_API_GROUP_BEGIN
|
||||
RT_API_ATTRS Descriptor::Descriptor(const Descriptor &that) { *this = that; }
|
||||
|
||||
RT_API_ATTRS Descriptor &Descriptor::operator=(const Descriptor &that) {
|
||||
std::memcpy(reinterpret_cast<void *>(this), &that, that.SizeInBytes());
|
||||
runtime::memcpy(this, &that, that.SizeInBytes());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ static RT_API_ATTRS bool EditBOZInput(
|
||||
io.HandleAbsolutePosition(start);
|
||||
remaining.reset();
|
||||
// Make a second pass now that the digit count is known
|
||||
std::memset(n, 0, bytes);
|
||||
runtime::memset(n, 0, bytes);
|
||||
int increment{isHostLittleEndian ? -1 : 1};
|
||||
auto *data{reinterpret_cast<unsigned char *>(n) +
|
||||
(isHostLittleEndian ? significantBytes - 1 : bytes - significantBytes)};
|
||||
@@ -283,18 +283,18 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit,
|
||||
auto shft{static_cast<int>(sizeof value - kind)};
|
||||
if (!isHostLittleEndian && shft >= 0) {
|
||||
auto shifted{value << (8 * shft)};
|
||||
std::memcpy(n, &shifted, kind);
|
||||
runtime::memcpy(n, &shifted, kind);
|
||||
} else {
|
||||
std::memcpy(n, &value, kind); // a blank field means zero
|
||||
runtime::memcpy(n, &value, kind); // a blank field means zero
|
||||
}
|
||||
#else
|
||||
auto shft{static_cast<int>(sizeof(value.low())) - kind};
|
||||
// For kind==8 (i.e. shft==0), the value is stored in low_ in big endian.
|
||||
if (!isHostLittleEndian && shft >= 0) {
|
||||
auto l{value.low() << (8 * shft)};
|
||||
std::memcpy(n, &l, kind);
|
||||
runtime::memcpy(n, &l, kind);
|
||||
} else {
|
||||
std::memcpy(n, &value, kind); // a blank field means zero
|
||||
runtime::memcpy(n, &value, kind); // a blank field means zero
|
||||
}
|
||||
#endif
|
||||
io.GotChar(fastField.got());
|
||||
@@ -1121,7 +1121,7 @@ RT_API_ATTRS bool EditCharacterInput(IoStatementState &io, const DataEdit &edit,
|
||||
--skipChars;
|
||||
} else {
|
||||
char32_t buffer{0};
|
||||
std::memcpy(&buffer, input, chunkBytes);
|
||||
runtime::memcpy(&buffer, input, chunkBytes);
|
||||
if ((sizeof *x == 1 && buffer > 0xff) ||
|
||||
(sizeof *x == 2 && buffer > 0xffff)) {
|
||||
*x++ = '?';
|
||||
@@ -1148,7 +1148,7 @@ RT_API_ATTRS bool EditCharacterInput(IoStatementState &io, const DataEdit &edit,
|
||||
chunkBytes = std::min<std::size_t>(remainingChars, readyBytes);
|
||||
chunkBytes = std::min<std::size_t>(lengthChars, chunkBytes);
|
||||
chunkChars = chunkBytes;
|
||||
std::memcpy(x, input, chunkBytes);
|
||||
runtime::memcpy(x, input, chunkBytes);
|
||||
x += chunkBytes;
|
||||
lengthChars -= chunkChars;
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ uid_t RTNAME(GetUID)() {
|
||||
|
||||
void GetUsernameEnvVar(const char *envName, char *arg, std::int64_t length) {
|
||||
Descriptor name{*Descriptor::Create(
|
||||
1, std::strlen(envName) + 1, const_cast<char *>(envName), 0)};
|
||||
1, runtime::strlen(envName) + 1, const_cast<char *>(envName), 0)};
|
||||
Descriptor value{*Descriptor::Create(1, length, arg, 0)};
|
||||
|
||||
RTNAME(GetEnvVariable)
|
||||
@@ -172,7 +172,7 @@ void FORTRAN_PROCEDURE_NAME(fdate)(char *arg, std::int64_t length) {
|
||||
char str[26];
|
||||
// Insufficient space, fill with spaces and return.
|
||||
if (length < 24) {
|
||||
std::memset(arg, ' ', length);
|
||||
runtime::memset(arg, ' ', length);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -204,8 +204,8 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
|
||||
void FORTRAN_PROCEDURE_NAME(getlog)(char *arg, std::int64_t length) {
|
||||
#if _REENTRANT || _POSIX_C_SOURCE >= 199506L
|
||||
if (length >= 1 && getlogin_r(arg, length) == 0) {
|
||||
auto loginLen{std::strlen(arg)};
|
||||
std::memset(
|
||||
auto loginLen{runtime::strlen(arg)};
|
||||
runtime::memset(
|
||||
arg + loginLen, ' ', static_cast<std::size_t>(length) - loginLen);
|
||||
return;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name,
|
||||
char *newName{nullptr};
|
||||
if (name[nameLength - 1] != '\0') {
|
||||
newName = static_cast<char *>(std::malloc(nameLength + 1));
|
||||
std::memcpy(newName, name, nameLength);
|
||||
runtime::memcpy(newName, name, nameLength);
|
||||
newName[nameLength] = '\0';
|
||||
name = newName;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ bool ExternalFileUnit::OpenUnit(common::optional<OpenStatus> status,
|
||||
bool impliedClose{false};
|
||||
if (IsConnected()) {
|
||||
bool isSamePath{newPath.get() && path() && pathLength() == newPathLength &&
|
||||
std::memcmp(path(), newPath.get(), newPathLength) == 0};
|
||||
runtime::memcmp(path(), newPath.get(), newPathLength) == 0};
|
||||
if (status && *status != OpenStatus::Old && isSamePath) {
|
||||
handler.SignalError("OPEN statement for connected unit may not have "
|
||||
"explicit STATUS= other than 'OLD'");
|
||||
@@ -202,8 +202,8 @@ bool ExternalFileUnit::OpenAnonymousUnit(common::optional<OpenStatus> status,
|
||||
std::size_t pathMaxLen{32};
|
||||
auto path{SizedNew<char>{handler}(pathMaxLen)};
|
||||
std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_);
|
||||
OpenUnit(status, action, position, std::move(path), std::strlen(path.get()),
|
||||
convert, handler);
|
||||
OpenUnit(status, action, position, std::move(path),
|
||||
runtime::strlen(path.get()), convert, handler);
|
||||
return IsConnected();
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ inline RT_API_ATTRS void TypedPartialMaxOrMinLoc(const char *intrinsic,
|
||||
CreatePartialReductionResult(result, x,
|
||||
Descriptor::BytesFor(TypeCategory::Integer, kind), dim, terminator,
|
||||
intrinsic, TypeCode{TypeCategory::Integer, kind});
|
||||
std::memset(
|
||||
runtime::memset(
|
||||
result.OffsetElement(), 0, result.Elements() * result.ElementBytes());
|
||||
return;
|
||||
}
|
||||
@@ -584,11 +584,11 @@ public:
|
||||
static_assert(std::is_same_v<A, Type>);
|
||||
std::size_t byteSize{array_.ElementBytes()};
|
||||
if (extremum_) {
|
||||
std::memcpy(p, extremum_, byteSize);
|
||||
runtime::memcpy(p, extremum_, byteSize);
|
||||
} else {
|
||||
// Empty array; fill with character 0 for MAXVAL.
|
||||
// For MINVAL, set all of the bits.
|
||||
std::memset(p, IS_MAXVAL ? 0 : 255, byteSize);
|
||||
runtime::memset(p, IS_MAXVAL ? 0 : 255, byteSize);
|
||||
}
|
||||
}
|
||||
RT_API_ATTRS bool Accumulate(const Type *x) {
|
||||
|
||||
@@ -72,7 +72,7 @@ RT_API_ATTRS bool InternalDescriptorUnit<DIR>::Emit(
|
||||
BlankFill(record + furthestPositionInRecord,
|
||||
positionInRecord - furthestPositionInRecord);
|
||||
}
|
||||
std::memcpy(record + positionInRecord, data, bytes);
|
||||
runtime::memcpy(record + positionInRecord, data, bytes);
|
||||
positionInRecord += bytes;
|
||||
furthestPositionInRecord = furthestAfter;
|
||||
return ok;
|
||||
|
||||
@@ -153,7 +153,7 @@ bool IoErrorHandler::GetIoMsg(char *buffer, std::size_t bufferLength) {
|
||||
} else if (ok) {
|
||||
std::size_t copied{Fortran::runtime::strlen(buffer)};
|
||||
if (copied < bufferLength) {
|
||||
std::memset(buffer + copied, ' ', bufferLength - copied);
|
||||
runtime::memset(buffer + copied, ' ', bufferLength - copied);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -62,7 +62,7 @@ inline static RT_API_ATTRS void MatrixTransposedTimesMatrix(
|
||||
std::size_t yColumnByteStride = 0) {
|
||||
using ResultType = CppTypeFor<RCAT, RKIND>;
|
||||
|
||||
std::memset(product, 0, rows * cols * sizeof *product);
|
||||
Fortran::runtime::memset(product, 0, rows * cols * sizeof *product);
|
||||
for (SubscriptValue j{0}; j < cols; ++j) {
|
||||
for (SubscriptValue i{0}; i < rows; ++i) {
|
||||
for (SubscriptValue k{0}; k < n; ++k) {
|
||||
@@ -132,7 +132,7 @@ inline static RT_API_ATTRS void MatrixTransposedTimesVector(
|
||||
SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y,
|
||||
std::size_t xColumnByteStride = 0) {
|
||||
using ResultType = CppTypeFor<RCAT, RKIND>;
|
||||
std::memset(product, 0, rows * sizeof *product);
|
||||
Fortran::runtime::memset(product, 0, rows * sizeof *product);
|
||||
for (SubscriptValue i{0}; i < rows; ++i) {
|
||||
for (SubscriptValue k{0}; k < n; ++k) {
|
||||
ResultType x_ki;
|
||||
|
||||
@@ -81,7 +81,7 @@ inline RT_API_ATTRS void MatrixTimesMatrix(
|
||||
SubscriptValue n, std::size_t xColumnByteStride = 0,
|
||||
std::size_t yColumnByteStride = 0) {
|
||||
using ResultType = CppTypeFor<RCAT, RKIND>;
|
||||
std::memset(product, 0, rows * cols * sizeof *product);
|
||||
Fortran::runtime::memset(product, 0, rows * cols * sizeof *product);
|
||||
const XT *RESTRICT xp0{x};
|
||||
for (SubscriptValue k{0}; k < n; ++k) {
|
||||
ResultType *RESTRICT p{product};
|
||||
@@ -153,7 +153,7 @@ inline RT_API_ATTRS void MatrixTimesVector(
|
||||
SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y,
|
||||
std::size_t xColumnByteStride = 0) {
|
||||
using ResultType = CppTypeFor<RCAT, RKIND>;
|
||||
std::memset(product, 0, rows * sizeof *product);
|
||||
Fortran::runtime::memset(product, 0, rows * sizeof *product);
|
||||
[[maybe_unused]] const XT *RESTRICT xp0{x};
|
||||
for (SubscriptValue k{0}; k < n; ++k) {
|
||||
ResultType *RESTRICT p{product};
|
||||
@@ -203,7 +203,7 @@ inline RT_API_ATTRS void VectorTimesMatrix(
|
||||
SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y,
|
||||
std::size_t yColumnByteStride = 0) {
|
||||
using ResultType = CppTypeFor<RCAT, RKIND>;
|
||||
std::memset(product, 0, cols * sizeof *product);
|
||||
Fortran::runtime::memset(product, 0, cols * sizeof *product);
|
||||
for (SubscriptValue k{0}; k < n; ++k) {
|
||||
ResultType *RESTRICT p{product};
|
||||
auto xv{static_cast<ResultType>(*x++)};
|
||||
|
||||
@@ -42,14 +42,14 @@ static RT_API_ATTRS void TransferImpl(Descriptor &result,
|
||||
source.GetLowerBounds(sourceAt);
|
||||
while (resultBytes > 0 && sourceElements > 0) {
|
||||
std::size_t toMove{std::min(resultBytes, sourceElementBytes)};
|
||||
std::memcpy(to, source.Element<char>(sourceAt), toMove);
|
||||
runtime::memcpy(to, source.Element<char>(sourceAt), toMove);
|
||||
to += toMove;
|
||||
resultBytes -= toMove;
|
||||
--sourceElements;
|
||||
source.IncrementSubscripts(sourceAt);
|
||||
}
|
||||
if (resultBytes > 0) {
|
||||
std::memset(to, 0, resultBytes);
|
||||
runtime::memset(to, 0, resultBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ std::size_t PseudoOpenFile::Write(FileOffset at, const char *buffer,
|
||||
// TODO: use persistent string buffer that can be reallocated
|
||||
// as needed, and only freed at destruction of *this.
|
||||
auto string{SizedNew<char>{handler}(bytes + 1)};
|
||||
std::memcpy(string.get(), buffer, bytes);
|
||||
runtime::memcpy(string.get(), buffer, bytes);
|
||||
string.get()[bytes] = '\0';
|
||||
std::printf("%s", string.get());
|
||||
return bytes;
|
||||
|
||||
@@ -40,7 +40,7 @@ RT_API_ATTRS RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header,
|
||||
std::size_t bytes{static_cast<std::size_t>(elementSize * size)};
|
||||
header->bufferPointer = AllocateMemoryOrCrash(terminator, bytes);
|
||||
if (header->bufferPointer) {
|
||||
std::memset(header->bufferPointer, 0, bytes);
|
||||
runtime::memset(header->bufferPointer, 0, bytes);
|
||||
}
|
||||
return header;
|
||||
} else {
|
||||
|
||||
@@ -79,16 +79,16 @@ public:
|
||||
activeTemp_ = 1 - activeTemp_;
|
||||
} else {
|
||||
activeTemp_ = 0;
|
||||
std::memcpy(&*temp_[activeTemp_], operand, elementBytes_);
|
||||
runtime::memcpy(&*temp_[activeTemp_], operand, elementBytes_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <typename A>
|
||||
RT_API_ATTRS void GetResult(A *to, int /*zeroBasedDim*/ = -1) {
|
||||
if (activeTemp_ >= 0) {
|
||||
std::memcpy(to, &*temp_[activeTemp_], elementBytes_);
|
||||
runtime::memcpy(to, &*temp_[activeTemp_], elementBytes_);
|
||||
} else if (identity_) {
|
||||
std::memcpy(to, identity_, elementBytes_);
|
||||
runtime::memcpy(to, identity_, elementBytes_);
|
||||
} else {
|
||||
terminator_.Crash("REDUCE() without IDENTITY= has no result");
|
||||
}
|
||||
|
||||
@@ -84,10 +84,10 @@ RT_API_ATTRS int ToErrmsg(const Descriptor *errmsg, int stat) {
|
||||
std::size_t bufferLength{errmsg->ElementBytes()};
|
||||
std::size_t msgLength{Fortran::runtime::strlen(msg)};
|
||||
if (msgLength >= bufferLength) {
|
||||
std::memcpy(buffer, msg, bufferLength);
|
||||
runtime::memcpy(buffer, msg, bufferLength);
|
||||
} else {
|
||||
std::memcpy(buffer, msg, msgLength);
|
||||
std::memset(buffer + msgLength, ' ', bufferLength - msgLength);
|
||||
runtime::memcpy(buffer, msg, msgLength);
|
||||
runtime::memset(buffer + msgLength, ' ', bufferLength - msgLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#include "flang/Common/ISO_Fortran_binding_wrapper.h"
|
||||
#include "flang/Runtime/assign.h"
|
||||
|
||||
RT_OFFLOAD_API_GROUP_BEGIN
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace Fortran;
|
||||
using namespace Fortran::runtime;
|
||||
|
||||
// the number of elements to allocate when first creating the vector
|
||||
@@ -97,7 +100,7 @@ void DescriptorStorage<COPY_VALUES>::resize(size_type newCapacity) {
|
||||
// Avoid passing a null pointer, since it would result in an undefined
|
||||
// behavior.
|
||||
if (data_ != nullptr) {
|
||||
memcpy(newData, data_, capacity_ * sizeof(Descriptor *));
|
||||
runtime::memcpy(newData, data_, capacity_ * sizeof(Descriptor *));
|
||||
FreeMemory(data_);
|
||||
}
|
||||
data_ = newData;
|
||||
@@ -181,8 +184,11 @@ inline static DescriptorStack *getDescriptorStorage(void *opaquePtr) {
|
||||
return static_cast<DescriptorStack *>(opaquePtr);
|
||||
}
|
||||
|
||||
RT_OFFLOAD_API_GROUP_END
|
||||
|
||||
namespace Fortran::runtime {
|
||||
extern "C" {
|
||||
RT_EXT_API_GROUP_BEGIN
|
||||
void *RTNAME(CreateValueStack)(const char *sourceFile, int line) {
|
||||
return ValueStack::allocate(sourceFile, line);
|
||||
}
|
||||
@@ -222,6 +228,6 @@ void RTNAME(DescriptorAt)(void *opaquePtr, uint64_t i, Descriptor &value) {
|
||||
void RTNAME(DestroyDescriptorStack)(void *opaquePtr) {
|
||||
DescriptorStack::destroy(getDescriptorStorage(opaquePtr));
|
||||
}
|
||||
|
||||
RT_EXT_API_GROUP_END
|
||||
} // extern "C"
|
||||
} // namespace Fortran::runtime
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
// should be preferred. Any other parameters required for SFINAE should have
|
||||
// default values provided.
|
||||
namespace {
|
||||
|
||||
using namespace Fortran;
|
||||
|
||||
// Types for the dummy parameter indicating the priority of a given overload.
|
||||
// We will invoke our helper with an integer literal argument, so the overload
|
||||
// with the highest priority should have the type int.
|
||||
@@ -276,13 +279,13 @@ static void DateAndTimeUnavailable(Fortran::runtime::Terminator &terminator,
|
||||
char *zone, std::size_t zoneChars,
|
||||
const Fortran::runtime::Descriptor *values) {
|
||||
if (date) {
|
||||
std::memset(date, static_cast<int>(' '), dateChars);
|
||||
runtime::memset(date, static_cast<int>(' '), dateChars);
|
||||
}
|
||||
if (time) {
|
||||
std::memset(time, static_cast<int>(' '), timeChars);
|
||||
runtime::memset(time, static_cast<int>(' '), timeChars);
|
||||
}
|
||||
if (zone) {
|
||||
std::memset(zone, static_cast<int>(' '), zoneChars);
|
||||
runtime::memset(zone, static_cast<int>(' '), zoneChars);
|
||||
}
|
||||
if (values) {
|
||||
auto typeCode{values->type().GetCategoryAndKind()};
|
||||
@@ -420,7 +423,7 @@ static void GetDateAndTime(Fortran::runtime::Terminator &terminator, char *date,
|
||||
auto copyBufferAndPad{
|
||||
[&](char *dest, std::size_t destChars, std::size_t len) {
|
||||
auto copyLen{std::min(len, destChars)};
|
||||
std::memcpy(dest, buffer, copyLen);
|
||||
runtime::memcpy(dest, buffer, copyLen);
|
||||
for (auto i{copyLen}; i < destChars; ++i) {
|
||||
dest[i] = ' ';
|
||||
}
|
||||
@@ -525,8 +528,8 @@ void RTNAME(Etime)(const Descriptor *values, const Descriptor *time,
|
||||
ULARGE_INTEGER userSystemTime;
|
||||
ULARGE_INTEGER kernelSystemTime;
|
||||
|
||||
memcpy(&userSystemTime, &userTime, sizeof(FILETIME));
|
||||
memcpy(&kernelSystemTime, &kernelTime, sizeof(FILETIME));
|
||||
runtime::memcpy(&userSystemTime, &userTime, sizeof(FILETIME));
|
||||
runtime::memcpy(&kernelSystemTime, &kernelTime, sizeof(FILETIME));
|
||||
|
||||
usrTime = ((double)(userSystemTime.QuadPart)) / 10000000.0;
|
||||
sysTime = ((double)(kernelSystemTime.QuadPart)) / 10000000.0;
|
||||
|
||||
@@ -28,7 +28,7 @@ RT_API_ATTRS OwningPtr<char> SaveDefaultCharacter(
|
||||
const char *s, std::size_t length, const Terminator &terminator) {
|
||||
if (s) {
|
||||
auto *p{static_cast<char *>(AllocateMemoryOrCrash(terminator, length + 1))};
|
||||
std::memcpy(p, s, length);
|
||||
runtime::memcpy(p, s, length);
|
||||
p[length] = '\0';
|
||||
return OwningPtr<char>{p};
|
||||
} else {
|
||||
@@ -75,10 +75,10 @@ RT_API_ATTRS void ToFortranDefaultCharacter(
|
||||
char *to, std::size_t toLength, const char *from) {
|
||||
std::size_t len{Fortran::runtime::strlen(from)};
|
||||
if (len < toLength) {
|
||||
std::memcpy(to, from, len);
|
||||
std::memset(to + len, ' ', toLength - len);
|
||||
runtime::memcpy(to, from, len);
|
||||
runtime::memset(to + len, ' ', toLength - len);
|
||||
} else {
|
||||
std::memcpy(to, from, toLength);
|
||||
runtime::memcpy(to, from, toLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,10 +127,10 @@ RT_API_ATTRS void ShallowCopyDiscontiguousToDiscontiguous(
|
||||
toIt.Advance(), fromIt.Advance()) {
|
||||
// typeElementBytes == 1 when P is a char - the non-specialised case
|
||||
if constexpr (typeElementBytes != 1) {
|
||||
std::memcpy(
|
||||
runtime::memcpy(
|
||||
toIt.template Get<P>(), fromIt.template Get<P>(), typeElementBytes);
|
||||
} else {
|
||||
std::memcpy(
|
||||
runtime::memcpy(
|
||||
toIt.template Get<P>(), fromIt.template Get<P>(), elementBytes);
|
||||
}
|
||||
}
|
||||
@@ -150,9 +150,9 @@ RT_API_ATTRS void ShallowCopyDiscontiguousToContiguous(
|
||||
for (std::size_t n{to.Elements()}; n-- > 0;
|
||||
toAt += elementBytes, fromIt.Advance()) {
|
||||
if constexpr (typeElementBytes != 1) {
|
||||
std::memcpy(toAt, fromIt.template Get<P>(), typeElementBytes);
|
||||
runtime::memcpy(toAt, fromIt.template Get<P>(), typeElementBytes);
|
||||
} else {
|
||||
std::memcpy(toAt, fromIt.template Get<P>(), elementBytes);
|
||||
runtime::memcpy(toAt, fromIt.template Get<P>(), elementBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,9 +170,9 @@ RT_API_ATTRS void ShallowCopyContiguousToDiscontiguous(
|
||||
for (std::size_t n{to.Elements()}; n-- > 0;
|
||||
toIt.Advance(), fromAt += elementBytes) {
|
||||
if constexpr (typeElementBytes != 1) {
|
||||
std::memcpy(toIt.template Get<P>(), fromAt, typeElementBytes);
|
||||
runtime::memcpy(toIt.template Get<P>(), fromAt, typeElementBytes);
|
||||
} else {
|
||||
std::memcpy(toIt.template Get<P>(), fromAt, elementBytes);
|
||||
runtime::memcpy(toIt.template Get<P>(), fromAt, elementBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ RT_API_ATTRS void ShallowCopyInner(const Descriptor &to, const Descriptor &from,
|
||||
bool toIsContiguous, bool fromIsContiguous) {
|
||||
if (toIsContiguous) {
|
||||
if (fromIsContiguous) {
|
||||
std::memcpy(to.OffsetElement(), from.OffsetElement(),
|
||||
runtime::memcpy(to.OffsetElement(), from.OffsetElement(),
|
||||
to.Elements() * to.ElementBytes());
|
||||
} else {
|
||||
ShallowCopyDiscontiguousToContiguous<P, RANK>(to, from);
|
||||
@@ -277,7 +277,7 @@ RT_API_ATTRS char *EnsureNullTerminated(
|
||||
char *str, std::size_t length, Terminator &terminator) {
|
||||
if (runtime::memchr(str, '\0', length) == nullptr) {
|
||||
char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
|
||||
std::memcpy(newCmd, str, length);
|
||||
runtime::memcpy(newCmd, str, length);
|
||||
newCmd[length] = '\0';
|
||||
return newCmd;
|
||||
} else {
|
||||
@@ -309,7 +309,7 @@ RT_API_ATTRS std::int32_t CopyCharsToDescriptor(const Descriptor &value,
|
||||
return ToErrmsg(errmsg, StatValueTooShort);
|
||||
}
|
||||
|
||||
std::memcpy(value.OffsetElement(offset), rawValue, toCopy);
|
||||
runtime::memcpy(value.OffsetElement(offset), rawValue, toCopy);
|
||||
|
||||
if (static_cast<std::int64_t>(rawValueLength) > toCopy) {
|
||||
return ToErrmsg(errmsg, StatValueTooShort);
|
||||
|
||||
@@ -115,7 +115,7 @@ static RT_API_ATTRS void DefaultInitialize(
|
||||
"not yet implemented: CHARACTER(KIND=%d) in EOSHIFT intrinsic", kind);
|
||||
}
|
||||
} else {
|
||||
std::memset(result.raw().base_addr, 0, bytes);
|
||||
runtime::memset(result.raw().base_addr, 0, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ ExternalFileUnit *UnitMap::Find(const char *path, std::size_t pathLen) {
|
||||
for (int j{0}; j < buckets_; ++j) {
|
||||
for (Chain *p{bucket_[j].get()}; p; p = p->next.get()) {
|
||||
if (p->unit.path() && p->unit.pathLength() == pathLen &&
|
||||
std::memcmp(p->unit.path(), path, pathLen) == 0) {
|
||||
runtime::memcmp(p->unit.path(), path, pathLen) == 0) {
|
||||
return &p->unit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,11 +90,11 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
|
||||
CheckDirectAccess(handler);
|
||||
WriteFrame(frameOffsetInFile_, recordOffsetInFrame_ + furthestAfter, handler);
|
||||
if (positionInRecord > furthestPositionInRecord) {
|
||||
std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord, ' ',
|
||||
positionInRecord - furthestPositionInRecord);
|
||||
runtime::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
|
||||
' ', positionInRecord - furthestPositionInRecord);
|
||||
}
|
||||
char *to{Frame() + recordOffsetInFrame_ + positionInRecord};
|
||||
std::memcpy(to, data, bytes);
|
||||
runtime::memcpy(to, data, bytes);
|
||||
if (swapEndianness_) {
|
||||
SwapEndianness(to, bytes, elementBytes);
|
||||
}
|
||||
@@ -119,7 +119,8 @@ bool ExternalFileUnit::Receive(char *data, std::size_t bytes,
|
||||
auto need{recordOffsetInFrame_ + furthestAfter};
|
||||
auto got{ReadFrame(frameOffsetInFile_, need, handler)};
|
||||
if (got >= need) {
|
||||
std::memcpy(data, Frame() + recordOffsetInFrame_ + positionInRecord, bytes);
|
||||
runtime::memcpy(
|
||||
data, Frame() + recordOffsetInFrame_ + positionInRecord, bytes);
|
||||
if (swapEndianness_) {
|
||||
SwapEndianness(data, bytes, elementBytes);
|
||||
}
|
||||
@@ -310,7 +311,8 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
|
||||
// Pad remainder of fixed length record
|
||||
WriteFrame(
|
||||
frameOffsetInFile_, recordOffsetInFrame_ + *openRecl, handler);
|
||||
std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
|
||||
runtime::memset(
|
||||
Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
|
||||
isUnformatted.value_or(false) ? 0 : ' ',
|
||||
*openRecl - furthestPositionInRecord);
|
||||
furthestPositionInRecord = *openRecl;
|
||||
@@ -839,7 +841,7 @@ void ExternalFileUnit::PopChildIo(ChildIo &child) {
|
||||
std::uint32_t ExternalFileUnit::ReadHeaderOrFooter(std::int64_t frameOffset) {
|
||||
std::uint32_t word;
|
||||
char *wordPtr{reinterpret_cast<char *>(&word)};
|
||||
std::memcpy(wordPtr, Frame() + frameOffset, sizeof word);
|
||||
runtime::memcpy(wordPtr, Frame() + frameOffset, sizeof word);
|
||||
if (swapEndianness_) {
|
||||
SwapEndianness(wordPtr, sizeof word, sizeof word);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
namespace Fortran::runtime {
|
||||
|
||||
#if !defined(RT_DEVICE_COMPILATION)
|
||||
#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)
|
||||
// FLANG_RT_DEBUG code is disabled when false.
|
||||
static constexpr bool enableDebugOutput{false};
|
||||
#endif
|
||||
@@ -79,7 +79,7 @@ RT_API_ATTRS Ticket &WorkQueue::StartTicket() {
|
||||
last_ = newTicket;
|
||||
}
|
||||
newTicket->ticket.begun = false;
|
||||
#if !defined(RT_DEVICE_COMPILATION)
|
||||
#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)
|
||||
if (enableDebugOutput &&
|
||||
(executionEnvironment.internalDebugging &
|
||||
ExecutionEnvironment::WorkQueue)) {
|
||||
@@ -93,7 +93,7 @@ RT_API_ATTRS int WorkQueue::Run() {
|
||||
while (last_) {
|
||||
TicketList *at{last_};
|
||||
insertAfter_ = last_;
|
||||
#if !defined(RT_DEVICE_COMPILATION)
|
||||
#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)
|
||||
if (enableDebugOutput &&
|
||||
(executionEnvironment.internalDebugging &
|
||||
ExecutionEnvironment::WorkQueue)) {
|
||||
@@ -102,7 +102,7 @@ RT_API_ATTRS int WorkQueue::Run() {
|
||||
}
|
||||
#endif
|
||||
int stat{at->ticket.Continue(*this)};
|
||||
#if !defined(RT_DEVICE_COMPILATION)
|
||||
#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)
|
||||
if (enableDebugOutput &&
|
||||
(executionEnvironment.internalDebugging &
|
||||
ExecutionEnvironment::WorkQueue)) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef FORTRAN_COMMON_FORTRAN_CONSTS_H_
|
||||
#define FORTRAN_COMMON_FORTRAN_CONSTS_H_
|
||||
|
||||
#include "api-attrs.h"
|
||||
#include "enum-class.h"
|
||||
#include <cstdint>
|
||||
|
||||
@@ -27,8 +28,10 @@ ENUM_CLASS(IoStmtKind, None, Backspace, Close, Endfile, Flush, Inquire, Open,
|
||||
ENUM_CLASS(
|
||||
DefinedIo, ReadFormatted, ReadUnformatted, WriteFormatted, WriteUnformatted)
|
||||
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
// Fortran arrays may have up to 15 dimensions (See Fortran 2018 section 5.4.6).
|
||||
static constexpr int maxRank{15};
|
||||
RT_OFFLOAD_VAR_GROUP_END
|
||||
|
||||
// Floating-point rounding modes; these are packed into a byte to save
|
||||
// room in the runtime's format processing context structure. These
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace Fortran::common {
|
||||
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
template <int BITS> class BitSet {
|
||||
static_assert(BITS > 0 && BITS <= 128);
|
||||
using Word = HostUnsignedIntType<(BITS <= 32 ? 32 : BITS)>;
|
||||
@@ -143,5 +143,6 @@ public:
|
||||
private:
|
||||
Word bits_{0};
|
||||
};
|
||||
RT_OFFLOAD_VAR_GROUP_END
|
||||
} // namespace Fortran::common
|
||||
#endif // FORTRAN_COMMON_CONSTEXPR_BITSET_H_
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "flang/Common/api-attrs.h"
|
||||
#include "flang/Common/real.h"
|
||||
#include "flang/Common/uint128.h"
|
||||
#include "flang/Runtime/freestanding-tools.h"
|
||||
#include <cinttypes>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
@@ -32,6 +33,7 @@ enum FortranRounding {
|
||||
|
||||
template <int BINARY_PRECISION> class BinaryFloatingPointNumber {
|
||||
public:
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
static constexpr common::RealCharacteristics realChars{BINARY_PRECISION};
|
||||
static constexpr int binaryPrecision{BINARY_PRECISION};
|
||||
static constexpr int bits{realChars.bits};
|
||||
@@ -47,7 +49,6 @@ public:
|
||||
|
||||
using RawType = common::HostUnsignedIntType<bits>;
|
||||
static_assert(CHAR_BIT * sizeof(RawType) >= bits);
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
static constexpr RawType significandMask{(RawType{1} << significandBits) - 1};
|
||||
|
||||
constexpr RT_API_ATTRS BinaryFloatingPointNumber() {} // zero
|
||||
@@ -68,7 +69,7 @@ public:
|
||||
template <typename A>
|
||||
explicit constexpr RT_API_ATTRS BinaryFloatingPointNumber(A x) {
|
||||
static_assert(sizeof raw_ <= sizeof x);
|
||||
std::memcpy(reinterpret_cast<void *>(&raw_),
|
||||
runtime::memcpy(reinterpret_cast<void *>(&raw_),
|
||||
reinterpret_cast<const void *>(&x), sizeof raw_);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#ifndef FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_
|
||||
#define FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_
|
||||
|
||||
RT_OFFLOAD_VAR_GROUP_BEGIN
|
||||
|
||||
static constexpr unsigned kDefaultAllocator = 0;
|
||||
|
||||
// Allocator used for CUF
|
||||
@@ -17,4 +19,6 @@ static constexpr unsigned kDeviceAllocatorPos = 2;
|
||||
static constexpr unsigned kManagedAllocatorPos = 3;
|
||||
static constexpr unsigned kUnifiedAllocatorPos = 4;
|
||||
|
||||
RT_OFFLOAD_VAR_GROUP_END
|
||||
|
||||
#endif /* FORTRAN_RUNTIME_ALLOCATOR_REGISTRY_CONSTS_H_ */
|
||||
|
||||
@@ -63,6 +63,25 @@
|
||||
#define STD_TOUPPER_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
#if defined(OMP_OFFLOAD_BUILD) && defined(OMP_NOHOST_BUILD) && \
|
||||
defined(__clang__)
|
||||
#define STD_FILL_N_UNSUPPORTED 1
|
||||
#define STD_MEMSET_USE_BUILTIN 1
|
||||
#define STD_MEMSET_UNSUPPORTED 1
|
||||
#define STD_MEMCPY_USE_BUILTIN 1
|
||||
#define STD_MEMCPY_UNSUPPORTED 1
|
||||
#define STD_MEMMOVE_UNSUPPORTED 1
|
||||
#define STD_STRLEN_UNSUPPORTED 1
|
||||
#define STD_MEMCMP_UNSUPPORTED 1
|
||||
#define STD_REALLOC_UNSUPPORTED 1
|
||||
#define STD_MEMCHR_UNSUPPORTED 1
|
||||
#define STD_STRCPY_UNSUPPORTED 1
|
||||
#define STD_STRCMP_UNSUPPORTED 1
|
||||
#define STD_TOUPPER_UNSUPPORTED 1
|
||||
#define STD_ABORT_USE_BUILTIN 1
|
||||
#define STD_ABORT_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
namespace Fortran::runtime {
|
||||
|
||||
#if STD_FILL_N_UNSUPPORTED
|
||||
@@ -79,7 +98,51 @@ fill_n(A *start, std::size_t count, const B &value) {
|
||||
using std::fill_n;
|
||||
#endif // !STD_FILL_N_UNSUPPORTED
|
||||
|
||||
#if STD_MEMMOVE_UNSUPPORTED
|
||||
#if STD_MEMSET_USE_BUILTIN
|
||||
static inline RT_API_ATTRS void memset(
|
||||
void *dest, unsigned char value, std::size_t count) {
|
||||
__builtin_memset(dest, value, count);
|
||||
}
|
||||
#elif STD_MEMSET_UNSUPPORTED
|
||||
static inline RT_API_ATTRS void memset(
|
||||
void *dest, unsigned char value, std::size_t count) {
|
||||
char *to{reinterpret_cast<char *>(dest)};
|
||||
while (count--) {
|
||||
*to++ = value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
using std::memset;
|
||||
#endif
|
||||
|
||||
#if STD_MEMCPY_USE_BUILTIN
|
||||
static inline RT_API_ATTRS void memcpy(
|
||||
void *dest, const void *src, std::size_t count) {
|
||||
__builtin_memcpy(dest, src, count);
|
||||
}
|
||||
#elif STD_MEMCPY_UNSUPPORTED
|
||||
static inline RT_API_ATTRS void memcpy(
|
||||
void *dest, const void *src, std::size_t count) {
|
||||
char *to{reinterpret_cast<char *>(dest)};
|
||||
const char *from{reinterpret_cast<const char *>(src)};
|
||||
if (to == from) {
|
||||
return;
|
||||
}
|
||||
while (count--) {
|
||||
*to++ = *from++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
using std::memcpy;
|
||||
#endif
|
||||
|
||||
#if STD_MEMMOVE_USE_BUILTIN
|
||||
static inline RT_API_ATTRS void memmove(
|
||||
void *dest, const void *src, std::size_t count) {
|
||||
__builtin_memmove(dest, src, count);
|
||||
}
|
||||
#elif STD_MEMMOVE_UNSUPPORTED
|
||||
// Provides alternative implementation for std::memmove(), if
|
||||
// it is not supported.
|
||||
static inline RT_API_ATTRS void *memmove(
|
||||
@@ -91,7 +154,7 @@ static inline RT_API_ATTRS void *memmove(
|
||||
return dest;
|
||||
}
|
||||
if (to + count <= from || from + count <= to) {
|
||||
std::memcpy(dest, src, count);
|
||||
memcpy(dest, src, count);
|
||||
} else if (to < from) {
|
||||
while (count--) {
|
||||
*to++ = *from++;
|
||||
@@ -112,13 +175,17 @@ using std::memmove;
|
||||
using MemmoveFct = void *(*)(void *, const void *, std::size_t);
|
||||
|
||||
#ifdef RT_DEVICE_COMPILATION
|
||||
static RT_API_ATTRS void *MemmoveWrapper(
|
||||
[[maybe_unused]] static RT_API_ATTRS void *MemmoveWrapper(
|
||||
void *dest, const void *src, std::size_t count) {
|
||||
return Fortran::runtime::memmove(dest, src, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if STD_STRLEN_UNSUPPORTED
|
||||
#if STD_STRLEN_USE_BUILTIN
|
||||
static inline RT_API_ATTRS std::size_t strlen(const char *str) {
|
||||
return __builtin_strlen(str);
|
||||
}
|
||||
#elif STD_STRLEN_UNSUPPORTED
|
||||
// Provides alternative implementation for std::strlen(), if
|
||||
// it is not supported.
|
||||
static inline RT_API_ATTRS std::size_t strlen(const char *str) {
|
||||
|
||||
@@ -30,7 +30,9 @@ NORETURN void RTNAME(ProgramEndStatement)(NO_ARGUMENTS);
|
||||
|
||||
// Extensions
|
||||
NORETURN void RTNAME(Exit)(int status DEFAULT_VALUE(EXIT_SUCCESS));
|
||||
RT_OFFLOAD_API_GROUP_BEGIN
|
||||
NORETURN void RTNAME(Abort)(NO_ARGUMENTS);
|
||||
RT_OFFLOAD_API_GROUP_END
|
||||
void FORTRAN_PROCEDURE_NAME(backtrace)(NO_ARGUMENTS);
|
||||
|
||||
// Crash with an error message when the program dynamically violates a Fortran
|
||||
|
||||
Reference in New Issue
Block a user