[flang] Fix APFloat conversion cases

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D128935

Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Co-authored-by: Peter Steinfeld <psteinfeld@nvidia.com>
This commit is contained in:
Valentin Clement 2022-07-01 08:29:19 +02:00
parent 39fe49aa57
commit 39377d5227
No known key found for this signature in database
GPG Key ID: 086D54783C928776
9 changed files with 72 additions and 58 deletions

View File

@ -462,13 +462,13 @@ private:
}
void genSourceAllocation(const Allocation &, const fir::MutableBoxValue &) {
TODO(loc, "SOURCE allocation lowering");
TODO(loc, "SOURCE allocation");
}
void genMoldAllocation(const Allocation &, const fir::MutableBoxValue &) {
TODO(loc, "MOLD allocation lowering");
TODO(loc, "MOLD allocation");
}
void genSetType(const Allocation &, const fir::MutableBoxValue &) {
TODO(loc, "polymorphic entity allocation lowering");
TODO(loc, "polymorphic entity allocation");
}
/// Returns a pointer to the DeclTypeSpec if a type-spec is provided in the

View File

@ -773,7 +773,7 @@ private:
Fortran::lower::SymbolBox resultSymBox = lookupSymbol(resultSym);
mlir::Location loc = toLocation();
if (!resultSymBox) {
mlir::emitError(loc, "failed lowering function return");
mlir::emitError(loc, "internal error when processing function return");
return;
}
mlir::Value resultVal = resultSymBox.match(
@ -1857,56 +1857,56 @@ private:
void genFIR(const Fortran::parser::BlockConstruct &blockConstruct) {
setCurrentPositionAt(blockConstruct);
TODO(toLocation(), "BlockConstruct lowering");
TODO(toLocation(), "BlockConstruct implementation");
}
void genFIR(const Fortran::parser::BlockStmt &) {
TODO(toLocation(), "BlockStmt lowering");
TODO(toLocation(), "BlockStmt implementation");
}
void genFIR(const Fortran::parser::EndBlockStmt &) {
TODO(toLocation(), "EndBlockStmt lowering");
TODO(toLocation(), "EndBlockStmt implementation");
}
void genFIR(const Fortran::parser::ChangeTeamConstruct &construct) {
TODO(toLocation(), "ChangeTeamConstruct lowering");
TODO(toLocation(), "ChangeTeamConstruct implementation");
}
void genFIR(const Fortran::parser::ChangeTeamStmt &stmt) {
TODO(toLocation(), "ChangeTeamStmt lowering");
TODO(toLocation(), "ChangeTeamStmt implementation");
}
void genFIR(const Fortran::parser::EndChangeTeamStmt &stmt) {
TODO(toLocation(), "EndChangeTeamStmt lowering");
TODO(toLocation(), "EndChangeTeamStmt implementation");
}
void genFIR(const Fortran::parser::CriticalConstruct &criticalConstruct) {
setCurrentPositionAt(criticalConstruct);
TODO(toLocation(), "CriticalConstruct lowering");
TODO(toLocation(), "CriticalConstruct implementation");
}
void genFIR(const Fortran::parser::CriticalStmt &) {
TODO(toLocation(), "CriticalStmt lowering");
TODO(toLocation(), "CriticalStmt implementation");
}
void genFIR(const Fortran::parser::EndCriticalStmt &) {
TODO(toLocation(), "EndCriticalStmt lowering");
TODO(toLocation(), "EndCriticalStmt implementation");
}
void genFIR(const Fortran::parser::SelectRankConstruct &selectRankConstruct) {
setCurrentPositionAt(selectRankConstruct);
TODO(toLocation(), "SelectRankConstruct lowering");
TODO(toLocation(), "SelectRankConstruct implementation");
}
void genFIR(const Fortran::parser::SelectRankStmt &) {
TODO(toLocation(), "SelectRankStmt lowering");
TODO(toLocation(), "SelectRankStmt implementation");
}
void genFIR(const Fortran::parser::SelectRankCaseStmt &) {
TODO(toLocation(), "SelectRankCaseStmt lowering");
TODO(toLocation(), "SelectRankCaseStmt implementation");
}
void genFIR(const Fortran::parser::SelectTypeConstruct &selectTypeConstruct) {
setCurrentPositionAt(selectTypeConstruct);
TODO(toLocation(), "SelectTypeConstruct lowering");
TODO(toLocation(), "SelectTypeConstruct implementation");
}
void genFIR(const Fortran::parser::SelectTypeStmt &) {
TODO(toLocation(), "SelectTypeStmt lowering");
TODO(toLocation(), "SelectTypeStmt implementation");
}
void genFIR(const Fortran::parser::TypeGuardStmt &) {
TODO(toLocation(), "TypeGuardStmt lowering");
TODO(toLocation(), "TypeGuardStmt implementation");
}
//===--------------------------------------------------------------------===//

View File

@ -792,7 +792,7 @@ private:
if (cat == Fortran::common::TypeCategory::Derived) {
if (dynamicType.IsPolymorphic())
TODO(interface.converter.getCurrentLocation(),
"[translateDynamicType] polymorphic types");
"support for polymorphic types");
return getConverter().genType(dynamicType.GetDerivedTypeSpec());
}
// CHARACTER with compile time constant length.

View File

@ -387,8 +387,7 @@ static fir::ExtendedValue genLoad(fir::FirOpBuilder &builder,
[&](const fir::BoxValue &box) -> fir::ExtendedValue {
if (box.isUnlimitedPolymorphic())
fir::emitFatalError(
loc,
"lowering attempting to load an unlimited polymorphic entity");
loc, "attempting to load an unlimited polymorphic entity");
return genLoad(builder, loc,
fir::factory::readBoxValue(builder, loc, box));
},
@ -1398,23 +1397,24 @@ public:
} else if constexpr (TC == Fortran::common::TypeCategory::Real) {
std::string str = value.DumpHexadecimal();
if constexpr (KIND == 2) {
llvm::APFloat floatVal{llvm::APFloatBase::IEEEhalf(), str};
auto floatVal = consAPFloat(llvm::APFloatBase::IEEEhalf(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
} else if constexpr (KIND == 3) {
llvm::APFloat floatVal{llvm::APFloatBase::BFloat(), str};
auto floatVal = consAPFloat(llvm::APFloatBase::BFloat(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
} else if constexpr (KIND == 4) {
llvm::APFloat floatVal{llvm::APFloatBase::IEEEsingle(), str};
auto floatVal = consAPFloat(llvm::APFloatBase::IEEEsingle(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
} else if constexpr (KIND == 10) {
llvm::APFloat floatVal{llvm::APFloatBase::x87DoubleExtended(), str};
auto floatVal =
consAPFloat(llvm::APFloatBase::x87DoubleExtended(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
} else if constexpr (KIND == 16) {
llvm::APFloat floatVal{llvm::APFloatBase::IEEEquad(), str};
auto floatVal = consAPFloat(llvm::APFloatBase::IEEEquad(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
} else {
// convert everything else to double
llvm::APFloat floatVal{llvm::APFloatBase::IEEEdouble(), str};
auto floatVal = consAPFloat(llvm::APFloatBase::IEEEdouble(), str);
return genRealConstant<KIND>(builder.getContext(), floatVal);
}
} else if constexpr (TC == Fortran::common::TypeCategory::Complex) {
@ -1431,6 +1431,23 @@ public:
}
}
/// Convert string, \p s, to an APFloat value. Recognize and handle Inf and
/// NaN strings as well. \p s is assumed to not contain any spaces.
static llvm::APFloat consAPFloat(const llvm::fltSemantics &fsem,
llvm::StringRef s) {
assert(s.find(' ') == llvm::StringRef::npos);
if (s.compare_insensitive("-inf") == 0)
return llvm::APFloat::getInf(fsem, /*negative=*/true);
if (s.compare_insensitive("inf") == 0 || s.compare_insensitive("+inf") == 0)
return llvm::APFloat::getInf(fsem);
// TODO: Add support for quiet and signaling NaNs.
if (s.compare_insensitive("-nan") == 0)
return llvm::APFloat::getNaN(fsem, /*negative=*/true);
if (s.compare_insensitive("nan") == 0 || s.compare_insensitive("+nan") == 0)
return llvm::APFloat::getNaN(fsem);
return {fsem, s};
}
/// Generate a raw literal value and store it in the rawVals vector.
template <Fortran::common::TypeCategory TC, int KIND>
void
@ -1448,18 +1465,19 @@ public:
} else if constexpr (TC == Fortran::common::TypeCategory::Real) {
std::string str = value.DumpHexadecimal();
inInitializer->rawType = converter.genType(TC, KIND);
llvm::APFloat floatVal{builder.getKindMap().getFloatSemantics(KIND), str};
auto floatVal =
consAPFloat(builder.getKindMap().getFloatSemantics(KIND), str);
val = builder.getFloatAttr(inInitializer->rawType, floatVal);
} else if constexpr (TC == Fortran::common::TypeCategory::Complex) {
std::string strReal = value.REAL().DumpHexadecimal();
std::string strImg = value.AIMAG().DumpHexadecimal();
inInitializer->rawType = converter.genType(TC, KIND);
llvm::APFloat realVal{builder.getKindMap().getFloatSemantics(KIND),
strReal};
auto realVal =
consAPFloat(builder.getKindMap().getFloatSemantics(KIND), strReal);
val = builder.getFloatAttr(inInitializer->rawType, realVal);
inInitializer->rawVals.push_back(val);
llvm::APFloat imgVal{builder.getKindMap().getFloatSemantics(KIND),
strImg};
auto imgVal =
consAPFloat(builder.getKindMap().getFloatSemantics(KIND), strImg);
val = builder.getFloatAttr(inInitializer->rawType, imgVal);
}
inInitializer->rawVals.push_back(val);
@ -1685,8 +1703,7 @@ public:
template <typename A>
ExtValue genval(const Fortran::evaluate::ArrayConstructor<A> &) {
fir::emitFatalError(getLoc(),
"array constructor: lowering should not reach here");
fir::emitFatalError(getLoc(), "array constructor: should not reach here");
}
ExtValue gen(const Fortran::evaluate::ComplexPart &x) {
@ -1867,7 +1884,7 @@ public:
return genval(*sub);
return genIntegerConstant<8>(builder.getContext(), 1);
}
TODO(getLoc(), "non explicit semantics::Bound lowering");
TODO(getLoc(), "non explicit semantics::Bound implementation");
}
static bool isSlice(const Fortran::evaluate::ArrayRef &aref) {
@ -1997,7 +2014,7 @@ public:
loc, "internal: BoxValue in dim-collapsed fir.coordinate_of");
},
[&](const auto &) -> ExtValue {
fir::emitFatalError(loc, "internal: array lowering failed");
fir::emitFatalError(loc, "internal: array processing failed");
});
}
@ -2579,9 +2596,9 @@ public:
bool callingImplicitInterface = caller.canBeCalledViaImplicitInterface();
for (auto [fst, snd] :
llvm::zip(caller.getInputs(), funcType.getInputs())) {
// When passing arguments to a procedure that can be called an implicit
// interface, allow character actual arguments to be passed to dummy
// arguments of any type and vice versa
// When passing arguments to a procedure that can be called by implicit
// interface, allow any character actual arguments to be passed to dummy
// arguments of any type and vice versa.
mlir::Value cast;
auto *context = builder.getContext();
if (snd.isa<fir::BoxProcType>() &&
@ -2994,7 +3011,7 @@ public:
}
const auto *expr = actual->UnwrapExpr();
if (!expr)
TODO(loc, "assumed type actual argument lowering");
TODO(loc, "assumed type actual argument");
if (arg.passBy == PassBy::Value) {
ExtValue argVal = genval(*expr);
@ -4832,7 +4849,7 @@ private:
// a potentially absent argument to something else than a value (apart
// from character MAX/MIN that are handled elsewhere.)
if (argRules.lowerAs != Fortran::lower::LowerIntrinsicArgAs::Value)
TODO(loc, "lowering non trivial optional elemental intrinsic array "
TODO(loc, "non trivial optional elemental intrinsic array "
"argument");
PushSemantics(ConstituentSemantics::RefTransparent);
operands.emplace_back(genarrForwardOptionalArgumentToCall(*expr));
@ -4905,7 +4922,7 @@ private:
}
const auto *expr = actual->UnwrapExpr();
if (!expr)
TODO(loc, "assumed type actual argument lowering");
TODO(loc, "assumed type actual argument");
LLVM_DEBUG(expr->AsFortran(llvm::dbgs()
<< "argument: " << arg.firArgument << " = [")

View File

@ -160,8 +160,7 @@ struct TypeBuilder {
// Use unknown extents.
int rank = expr.Rank();
if (rank < 0)
TODO(converter.getCurrentLocation(),
"assumed rank expression type lowering");
TODO(converter.getCurrentLocation(), "assumed rank expression types");
for (int dim = 0; dim < rank; ++dim)
shape.emplace_back(fir::SequenceType::getUnknownExtent());
}
@ -207,7 +206,7 @@ struct TypeBuilder {
using T = std::decay_t<decltype(x)>;
static_assert(!Fortran::common::HasMember<
T, Fortran::evaluate::TypelessExpression>,
"missing typeless expr handling in type lowering");
"missing typeless expr handling");
llvm::report_fatal_error("not a typeless expression");
},
},
@ -235,7 +234,7 @@ struct TypeBuilder {
translateLenParameters(params, tySpec->category(), ultimate);
ty = genFIRType(context, tySpec->category(), kind, params);
} else if (type->IsPolymorphic()) {
TODO(loc, "[genSymbolType] polymorphic types");
TODO(loc, "support for polymorphic types");
} else if (const Fortran::semantics::DerivedTypeSpec *tySpec =
type->AsDerived()) {
ty = genDerivedType(*tySpec);
@ -249,7 +248,7 @@ struct TypeBuilder {
auto shapeExpr = Fortran::evaluate::GetShapeHelper{
converter.getFoldingContext()}(ultimate);
if (!shapeExpr)
TODO(loc, "assumed rank symbol type lowering");
TODO(loc, "assumed rank symbol type");
fir::SequenceType::Shape shape;
translateShape(shape, std::move(*shapeExpr));
ty = fir::SequenceType::get(shape, ty);
@ -302,7 +301,7 @@ struct TypeBuilder {
// Catch any situations where this is not true for now.
if (componentHasNonDefaultLowerBounds(field))
TODO(converter.genLocation(field.name()),
"lowering derived type components with non default lower bounds");
"derived type components with non default lower bounds");
if (IsProcedure(field))
TODO(converter.genLocation(field.name()), "procedure components");
mlir::Type ty = genSymbolType(field);
@ -328,7 +327,7 @@ struct TypeBuilder {
if (!ps.empty()) {
// This type is a PDT (parametric derived type). Create the functions to
// use for allocation, dereferencing, and address arithmetic here.
TODO(loc, "parameterized derived types lowering");
TODO(loc, "parameterized derived types");
}
LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec << '\n');
@ -364,8 +363,7 @@ struct TypeBuilder {
if (category == Fortran::common::TypeCategory::Character)
params.push_back(getCharacterLength(exprOrSym));
else if (category == Fortran::common::TypeCategory::Derived)
TODO(converter.getCurrentLocation(),
"lowering derived type length parameters");
TODO(converter.getCurrentLocation(), "derived type length parameters");
return;
}
Fortran::lower::LenParameterTy

View File

@ -123,7 +123,7 @@ static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
const Fortran::semantics::Symbol &ultimate = sym.GetUltimate();
if (!ultimate.has<Fortran::semantics::ObjectEntityDetails>() &&
!Fortran::semantics::IsProcedurePointer(ultimate))
mlir::emitError(loc, "lowering global declaration: symbol '")
mlir::emitError(loc, "processing global declaration: symbol '")
<< toStringRef(sym.name()) << "' has unexpected details\n";
return builder.createGlobal(loc, converter.genType(var), globalName, linkage,
mlir::Attribute{}, isConstant(ultimate));
@ -1410,7 +1410,7 @@ void Fortran::lower::mapSymbolAttributes(
auto expr = Fortran::lower::SomeExpr{*low};
lb = builder.createConvert(loc, idxTy, genValue(expr));
} else {
TODO(loc, "assumed rank lowering");
TODO(loc, "support for assumed rank entities");
}
lbounds.emplace_back(lb);

View File

@ -92,8 +92,7 @@ static void prepareMinOrMaxArguments(
mlir::Type resultType = *retTy;
mlir::Location loc = converter.getCurrentLocation();
if (fir::isa_char(resultType))
TODO(loc,
"CHARACTER MIN and MAX lowering with dynamically optional arguments");
TODO(loc, "CHARACTER MIN and MAX with dynamically optional arguments");
for (auto arg : llvm::enumerate(procRef.arguments())) {
const auto *expr =
Fortran::evaluate::UnwrapExpr<Fortran::lower::SomeExpr>(arg.value());

View File

@ -1538,7 +1538,7 @@ getBuffer(Fortran::lower::AbstractConverter &converter, mlir::Location loc,
if (auto *var = std::get_if<Fortran::parser::Variable>(&iounit->u))
if (auto *expr = Fortran::semantics::GetExpr(*var))
return genBuffer(converter, loc, *expr, strTy, lenTy, stmtCtx);
llvm::report_fatal_error("failed to get IoUnit expr in lowering");
llvm::report_fatal_error("failed to get IoUnit expr");
}
static mlir::Value genIOUnitNumber(Fortran::lower::AbstractConverter &converter,

View File

@ -119,7 +119,7 @@ public:
auto m = specifics->complexReturnType(loc, ty.getElementType());
// Currently targets mandate COMPLEX is a single aggregate or packed
// scalar, including the sret case.
assert(m.size() == 1 && "target lowering of complex return not supported");
assert(m.size() == 1 && "target of complex return not supported");
auto resTy = std::get<mlir::Type>(m[0]);
auto attr = std::get<fir::CodeGenSpecifics::Attributes>(m[0]);
if (attr.isSRet()) {