Christian Sigg fac349a169
Reapply "[mlir] Mark isa/dyn_cast/cast/... member functions depreca… (#90406)
…ted. (#89998)" (#90250)

This partially reverts commit 7aedd7dc754c74a49fe84ed2640e269c25414087.

This change removes calls to the deprecated member functions. It does
not mark the functions deprecated yet and does not disable the
deprecation warning in TypeSwitch. This seems to cause problems with
MSVC.
2024-04-28 22:01:42 +02:00

320 lines
14 KiB
C++

//===-- Intrinsics.cpp ----------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/Runtime/Intrinsics.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Runtime/extensions.h"
#include "flang/Runtime/misc-intrinsic.h"
#include "flang/Runtime/pointer.h"
#include "flang/Runtime/random.h"
#include "flang/Runtime/stop.h"
#include "flang/Runtime/time-intrinsic.h"
#include "flang/Semantics/tools.h"
#include "llvm/Support/Debug.h"
#include <optional>
#include <signal.h>
#define DEBUG_TYPE "flang-lower-runtime"
using namespace Fortran::runtime;
namespace {
/// Placeholder for real*16 version of RandomNumber Intrinsic
struct ForcedRandomNumberReal16 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RandomNumber16));
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto boxTy =
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
auto strTy = fir::runtime::getModel<const char *>()(ctx);
auto intTy = fir::runtime::getModel<int>()(ctx);
;
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy},
mlir::NoneType::get(ctx));
};
}
};
} // namespace
mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value pointer,
mlir::Value target) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(PointerIsAssociatedWith)>(loc,
builder);
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, func.getFunctionType(), pointer, target);
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
mlir::Value fir::runtime::genCpuTime(fir::FirOpBuilder &builder,
mlir::Location loc) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(CpuTime)>(loc, builder);
return builder.create<fir::CallOp>(loc, func, std::nullopt).getResult(0);
}
void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder,
mlir::Location loc,
std::optional<fir::CharBoxValue> date,
std::optional<fir::CharBoxValue> time,
std::optional<fir::CharBoxValue> zone,
mlir::Value values) {
mlir::func::FuncOp callee =
fir::runtime::getRuntimeFunc<mkRTKey(DateAndTime)>(loc, builder);
mlir::FunctionType funcTy = callee.getFunctionType();
mlir::Type idxTy = builder.getIndexType();
mlir::Value zero;
auto splitArg = [&](std::optional<fir::CharBoxValue> arg, mlir::Value &buffer,
mlir::Value &len) {
if (arg) {
buffer = arg->getBuffer();
len = arg->getLen();
} else {
if (!zero)
zero = builder.createIntegerConstant(loc, idxTy, 0);
buffer = zero;
len = zero;
}
};
mlir::Value dateBuffer;
mlir::Value dateLen;
splitArg(date, dateBuffer, dateLen);
mlir::Value timeBuffer;
mlir::Value timeLen;
splitArg(time, timeBuffer, timeLen);
mlir::Value zoneBuffer;
mlir::Value zoneLen;
splitArg(zone, zoneBuffer, zoneLen);
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7));
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen,
zoneBuffer, zoneLen, sourceFile, sourceLine, values);
builder.create<fir::CallOp>(loc, callee, args);
}
void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value repeatable,
mlir::Value imageDistinct) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, func.getFunctionType(), repeatable, imageDistinct);
builder.create<fir::CallOp>(loc, func, args);
}
void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value harvest) {
mlir::func::FuncOp func;
auto boxEleTy = fir::dyn_cast_ptrOrBoxEleTy(harvest.getType());
auto eleTy = fir::unwrapSequenceType(boxEleTy);
if (eleTy.isF128()) {
func = fir::runtime::getRuntimeFunc<ForcedRandomNumberReal16>(loc, builder);
} else {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
}
mlir::FunctionType funcTy = func.getFunctionType();
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, funcTy, harvest, sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, func, args);
}
void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value size, mlir::Value put,
mlir::Value get) {
bool sizeIsPresent =
!mlir::isa_and_nonnull<fir::AbsentOp>(size.getDefiningOp());
bool putIsPresent =
!mlir::isa_and_nonnull<fir::AbsentOp>(put.getDefiningOp());
bool getIsPresent =
!mlir::isa_and_nonnull<fir::AbsentOp>(get.getDefiningOp());
mlir::func::FuncOp func;
int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent;
if (staticArgCount == 0) {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
builder);
builder.create<fir::CallOp>(loc, func);
return;
}
mlir::FunctionType funcTy;
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine;
mlir::Value argBox;
llvm::SmallVector<mlir::Value> args;
if (staticArgCount > 1) {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeed)>(loc, builder);
funcTy = func.getFunctionType();
sourceLine =
fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4));
args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get,
sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, func, args);
return;
}
if (sizeIsPresent) {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
argBox = size;
} else if (putIsPresent) {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
argBox = put;
} else {
func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
argBox = get;
}
funcTy = func.getFunctionType();
sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile,
sourceLine);
builder.create<fir::CallOp>(loc, func, args);
}
/// generate runtime call to transfer intrinsic with no size argument
void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value sourceBox,
mlir::Value moldBox) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(Transfer)>(loc, builder);
mlir::FunctionType fTy = func.getFunctionType();
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, func, args);
}
/// generate runtime call to transfer intrinsic with size argument
void fir::runtime::genTransferSize(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value resultBox,
mlir::Value sourceBox, mlir::Value moldBox,
mlir::Value size) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(TransferSize)>(loc, builder);
mlir::FunctionType fTy = func.getFunctionType();
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
llvm::SmallVector<mlir::Value> args =
fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
moldBox, sourceFile, sourceLine, size);
builder.create<fir::CallOp>(loc, func, args);
}
/// generate system_clock runtime call/s
/// all intrinsic arguments are optional and may appear here as mlir::Value{}
void fir::runtime::genSystemClock(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value count,
mlir::Value rate, mlir::Value max) {
auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) {
mlir::Type type = arg.getType();
fir::IfOp ifOp{};
const bool isOptionalArg =
fir::valueHasFirAttribute(arg, fir::getOptionalAttrName());
if (mlir::dyn_cast<fir::PointerType>(type) ||
mlir::dyn_cast<fir::HeapType>(type)) {
// Check for a disassociated pointer or an unallocated allocatable.
assert(!isOptionalArg && "invalid optional argument");
ifOp = builder.create<fir::IfOp>(loc, builder.genIsNotNullAddr(loc, arg),
/*withElseRegion=*/false);
} else if (isOptionalArg) {
ifOp = builder.create<fir::IfOp>(
loc, builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), arg),
/*withElseRegion=*/false);
}
if (ifOp)
builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
mlir::Type kindTy = func.getFunctionType().getInput(0);
int integerKind = 8;
if (auto intType =
mlir::dyn_cast<mlir::IntegerType>(fir::unwrapRefType(type)))
integerKind = intType.getWidth() / 8;
mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind);
mlir::Value res =
builder.create<fir::CallOp>(loc, func, mlir::ValueRange{kind})
.getResult(0);
mlir::Value castRes =
builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res);
builder.create<fir::StoreOp>(loc, castRes, arg);
if (ifOp)
builder.setInsertionPointAfter(ifOp);
};
using fir::runtime::getRuntimeFunc;
if (count)
makeCall(getRuntimeFunc<mkRTKey(SystemClockCount)>(loc, builder), count);
if (rate)
makeCall(getRuntimeFunc<mkRTKey(SystemClockCountRate)>(loc, builder), rate);
if (max)
makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
}
// CALL SIGNAL(NUMBER, HANDLER [, STATUS])
// The definition of the SIGNAL intrinsic allows HANDLER to be a function
// pointer or an integer. STATUS can be dynamically optional
void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value number, mlir::Value handler,
mlir::Value status) {
assert(mlir::isa<mlir::IntegerType>(number.getType()));
mlir::Type int64 = builder.getIntegerType(64);
number = builder.create<fir::ConvertOp>(loc, int64, number);
mlir::Type handlerUnwrappedTy = fir::unwrapRefType(handler.getType());
if (mlir::isa_and_nonnull<mlir::IntegerType>(handlerUnwrappedTy)) {
// pass the integer as a function pointer like one would to signal(2)
handler = builder.create<fir::LoadOp>(loc, handler);
mlir::Type fnPtrTy = fir::LLVMPointerType::get(
mlir::FunctionType::get(handler.getContext(), {}, {}));
handler = builder.create<fir::ConvertOp>(loc, fnPtrTy, handler);
} else {
assert(mlir::isa<fir::BoxProcType>(handler.getType()));
handler = builder.create<fir::BoxAddrOp>(loc, handler);
}
mlir::func::FuncOp func{
fir::runtime::getRuntimeFunc<mkRTKey(Signal)>(loc, builder)};
mlir::Value stat =
builder.create<fir::CallOp>(loc, func, mlir::ValueRange{number, handler})
->getResult(0);
// return status code via status argument (if present)
if (status) {
assert(mlir::isa<mlir::IntegerType>(fir::unwrapRefType(status.getType())));
// status might be dynamically optional, so test if it is present
mlir::Value isPresent =
builder.create<IsPresentOp>(loc, builder.getI1Type(), status);
builder.genIfOp(loc, /*results=*/{}, isPresent, /*withElseRegion=*/false)
.genThen([&]() {
stat = builder.create<fir::ConvertOp>(
loc, fir::unwrapRefType(status.getType()), stat);
builder.create<fir::StoreOp>(loc, stat, status);
})
.end();
}
}
void fir::runtime::genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value seconds) {
mlir::Type int64 = builder.getIntegerType(64);
seconds = builder.create<fir::ConvertOp>(loc, int64, seconds);
mlir::func::FuncOp func{
fir::runtime::getRuntimeFunc<mkRTKey(Sleep)>(loc, builder)};
builder.create<fir::CallOp>(loc, func, seconds);
}