forked from OSchip/llvm-project
[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:
parent
39fe49aa57
commit
39377d5227
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 << " = [")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue