Skip to content

Commit ff862d6

Browse files
authored
[flang] Modifications to ieee floating point environment procedures (#121949)
Intrinsic module procedures ieee_get_modes, ieee_set_modes, ieee_get_status, and ieee_set_status store and retrieve opaque data values whose size varies by machine and OS environment. These data values are usually, but not always small. Their sizes are not directly known in a cross compilation environment. Address this issue by implementing two mechanisms for processing these data values. Environments that use typical small data sizes can access storage defined at compile time. When this is not valid, data storage of any size can be allocated at runtime.
1 parent 44ba43a commit ff862d6

File tree

13 files changed

+125
-259
lines changed

13 files changed

+125
-259
lines changed

flang/include/flang/Evaluate/target.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ class TargetCharacteristics {
112112
bool isPPC() const { return isPPC_; }
113113
void set_isPPC(bool isPPC = false);
114114

115+
bool isSPARC() const { return isSPARC_; }
116+
void set_isSPARC(bool isSPARC = false);
117+
115118
bool isOSWindows() const { return isOSWindows_; }
116119
void set_isOSWindows(bool isOSWindows = false) {
117120
isOSWindows_ = isOSWindows;
@@ -126,6 +129,7 @@ class TargetCharacteristics {
126129
std::uint8_t align_[common::TypeCategory_enumSize][maxKind + 1]{};
127130
bool isBigEndian_{false};
128131
bool isPPC_{false};
132+
bool isSPARC_{false};
129133
bool isOSWindows_{false};
130134
bool haltingSupportIsUnknownAtCompileTime_{false};
131135
bool areSubnormalsFlushedToZero_{false};

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,8 @@ struct IntrinsicLibrary {
269269
mlir::Value genIeeeCopySign(mlir::Type, llvm::ArrayRef<mlir::Value>);
270270
void genIeeeGetFlag(llvm::ArrayRef<fir::ExtendedValue>);
271271
void genIeeeGetHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
272-
template <bool isGet>
273-
void genIeeeGetOrSetModes(llvm::ArrayRef<fir::ExtendedValue>);
274-
template <bool isGet>
275-
void genIeeeGetOrSetStatus(llvm::ArrayRef<fir::ExtendedValue>);
272+
template <bool isGet, bool isModes>
273+
void genIeeeGetOrSetModesOrStatus(llvm::ArrayRef<fir::ExtendedValue>);
276274
void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
277275
void genIeeeGetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
278276
mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);

flang/include/flang/Optimizer/Builder/Runtime/Exceptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ mlir::Value genGetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc);
3333
void genSetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc,
3434
mlir::Value bit);
3535

36+
mlir::Value genGetModesTypeSize(fir::FirOpBuilder &builder, mlir::Location loc);
37+
mlir::Value genGetStatusTypeSize(fir::FirOpBuilder &builder,
38+
mlir::Location loc);
39+
3640
} // namespace fir::runtime
3741
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_EXCEPTIONS_H

flang/include/flang/Runtime/exceptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "flang/Runtime/entry-names.h"
1515
#include <cinttypes>
16+
#include <cstddef>
1617

1718
namespace Fortran::runtime {
1819

@@ -32,6 +33,10 @@ bool RTNAME(SupportHalting)(uint32_t except);
3233
bool RTNAME(GetUnderflowMode)(void);
3334
void RTNAME(SetUnderflowMode)(bool flag);
3435

36+
// Get the byte size of ieee_modes_type and ieee_status_type data.
37+
std::size_t RTNAME(GetModesTypeSize)(void);
38+
std::size_t RTNAME(GetStatusTypeSize)(void);
39+
3540
} // extern "C"
3641
} // namespace Fortran::runtime
3742
#endif // FORTRAN_RUNTIME_EXCEPTIONS_H_

flang/include/flang/Runtime/magic-numbers.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ ieee_arithmetic module rounding procedures.
118118
#define _FORTRAN_RUNTIME_IEEE_OTHER 5
119119

120120
#if 0
121-
The size of derived types ieee_modes_type and ieee_status_type from intrinsic
122-
module ieee_exceptions must be large enough to hold an fenv.h object of type
123-
femode_t and fenv_t, respectively. These types have members that are declared
124-
as int arrays with the following extents to allow build time validation of
125-
these sizes in cross compilation environments.
121+
INTEGER(kind=4) extents for ieee_exceptions module types ieee_modes_type and
122+
ieee_status_type. These extent values are large enough to hold femode_t and
123+
fenv_t data in many environments. An environment that does not meet these
124+
size constraints may allocate memory with runtime size values.
126125
#endif
127126
#define _FORTRAN_RUNTIME_IEEE_FEMODE_T_EXTENT 2
128127
#define _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT 8

flang/include/flang/Tools/TargetSetup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ namespace Fortran::tools {
7171
if (targetTriple.isPPC())
7272
targetCharacteristics.set_isPPC(true);
7373

74+
if (targetTriple.isSPARC())
75+
targetCharacteristics.set_isSPARC(true);
76+
7477
if (targetTriple.isOSWindows())
7578
targetCharacteristics.set_isOSWindows(true);
7679

flang/lib/Evaluate/target.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ void TargetCharacteristics::set_isBigEndian(bool isBig) {
104104
}
105105

106106
void TargetCharacteristics::set_isPPC(bool isPowerPC) { isPPC_ = isPowerPC; }
107+
void TargetCharacteristics::set_isSPARC(bool isSPARC) { isSPARC_ = isSPARC; }
107108

108109
void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
109110
areSubnormalsFlushedToZero_ = yes;

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "llvm/Support/Debug.h"
5151
#include "llvm/Support/MathExtras.h"
5252
#include "llvm/Support/raw_ostream.h"
53+
#include <cfenv> // temporary -- only used in genIeeeGetOrSetModesOrStatus
5354
#include <mlir/IR/Value.h>
5455
#include <optional>
5556

@@ -318,13 +319,15 @@ static constexpr IntrinsicHandler handlers[]{
318319
{"ieee_get_halting_mode",
319320
&I::genIeeeGetHaltingMode,
320321
{{{"flag", asValue}, {"halting", asAddr}}}},
321-
{"ieee_get_modes", &I::genIeeeGetOrSetModes</*isGet=*/true>},
322+
{"ieee_get_modes",
323+
&I::genIeeeGetOrSetModesOrStatus</*isGet=*/true, /*isModes=*/true>},
322324
{"ieee_get_rounding_mode",
323325
&I::genIeeeGetRoundingMode,
324326
{{{"round_value", asAddr, handleDynamicOptional},
325327
{"radix", asValue, handleDynamicOptional}}},
326328
/*isElemental=*/false},
327-
{"ieee_get_status", &I::genIeeeGetOrSetStatus</*isGet=*/true>},
329+
{"ieee_get_status",
330+
&I::genIeeeGetOrSetModesOrStatus</*isGet=*/true, /*isModes=*/false>},
328331
{"ieee_get_underflow_mode",
329332
&I::genIeeeGetUnderflowMode,
330333
{{{"gradual", asAddr}}},
@@ -368,13 +371,15 @@ static constexpr IntrinsicHandler handlers[]{
368371
{"ieee_set_flag", &I::genIeeeSetFlagOrHaltingMode</*isFlag=*/true>},
369372
{"ieee_set_halting_mode",
370373
&I::genIeeeSetFlagOrHaltingMode</*isFlag=*/false>},
371-
{"ieee_set_modes", &I::genIeeeGetOrSetModes</*isGet=*/false>},
374+
{"ieee_set_modes",
375+
&I::genIeeeGetOrSetModesOrStatus</*isGet=*/false, /*isModes=*/true>},
372376
{"ieee_set_rounding_mode",
373377
&I::genIeeeSetRoundingMode,
374378
{{{"round_value", asValue, handleDynamicOptional},
375379
{"radix", asValue, handleDynamicOptional}}},
376380
/*isElemental=*/false},
377-
{"ieee_set_status", &I::genIeeeGetOrSetStatus</*isGet=*/false>},
381+
{"ieee_set_status",
382+
&I::genIeeeGetOrSetModesOrStatus</*isGet=*/false, /*isModes=*/false>},
378383
{"ieee_set_underflow_mode", &I::genIeeeSetUnderflowMode},
379384
{"ieee_signaling_eq",
380385
&I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::OEQ>},
@@ -4108,11 +4113,12 @@ void IntrinsicLibrary::genRaiseExcept(int excepts, mlir::Value cond) {
41084113
// Return a reference to the contents of a derived type with one field.
41094114
// Also return the field type.
41104115
static std::pair<mlir::Value, mlir::Type>
4111-
getFieldRef(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value rec) {
4116+
getFieldRef(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value rec,
4117+
unsigned index = 0) {
41124118
auto recType =
41134119
mlir::dyn_cast<fir::RecordType>(fir::unwrapPassByRefType(rec.getType()));
4114-
assert(recType.getTypeList().size() == 1 && "expected exactly one component");
4115-
auto [fieldName, fieldTy] = recType.getTypeList().front();
4120+
assert(index < recType.getTypeList().size() && "not enough components");
4121+
auto [fieldName, fieldTy] = recType.getTypeList()[index];
41164122
mlir::Value field = builder.create<fir::FieldIndexOp>(
41174123
loc, fir::FieldType::get(recType.getContext()), fieldName, recType,
41184124
fir::getTypeParams(rec));
@@ -4502,15 +4508,60 @@ void IntrinsicLibrary::genIeeeGetHaltingMode(
45024508
}
45034509

45044510
// IEEE_GET_MODES, IEEE_SET_MODES
4505-
template <bool isGet>
4506-
void IntrinsicLibrary::genIeeeGetOrSetModes(
4511+
// IEEE_GET_STATUS, IEEE_SET_STATUS
4512+
template <bool isGet, bool isModes>
4513+
void IntrinsicLibrary::genIeeeGetOrSetModesOrStatus(
45074514
llvm::ArrayRef<fir::ExtendedValue> args) {
45084515
assert(args.size() == 1);
4509-
mlir::Type ptrTy = builder.getRefType(builder.getIntegerType(32));
4516+
#ifndef __GLIBC_USE_IEC_60559_BFP_EXT // only use of "#include <cfenv>"
4517+
// No definitions of fegetmode, fesetmode
4518+
llvm::StringRef func = isModes
4519+
? (isGet ? "ieee_get_modes" : "ieee_set_modes")
4520+
: (isGet ? "ieee_get_status" : "ieee_set_status");
4521+
TODO(loc, "intrinsic module procedure: " + func);
4522+
#else
45104523
mlir::Type i32Ty = builder.getIntegerType(32);
4511-
mlir::Value addr =
4512-
builder.create<fir::ConvertOp>(loc, ptrTy, getBase(args[0]));
4513-
genRuntimeCall(isGet ? "fegetmode" : "fesetmode", i32Ty, addr);
4524+
mlir::Type i64Ty = builder.getIntegerType(64);
4525+
mlir::Type ptrTy = builder.getRefType(i32Ty);
4526+
mlir::Value addr;
4527+
if (fir::getTargetTriple(builder.getModule()).isSPARC()) {
4528+
// Floating point environment data is larger than the __data field
4529+
// allotment. Allocate data space from the heap.
4530+
auto [fieldRef, fieldTy] =
4531+
getFieldRef(builder, loc, fir::getBase(args[0]), 1);
4532+
addr = builder.create<fir::BoxAddrOp>(
4533+
loc, builder.create<fir::LoadOp>(loc, fieldRef));
4534+
mlir::Type heapTy = addr.getType();
4535+
mlir::Value allocated = builder.create<mlir::arith::CmpIOp>(
4536+
loc, mlir::arith::CmpIPredicate::ne,
4537+
builder.createConvert(loc, i64Ty, addr),
4538+
builder.createIntegerConstant(loc, i64Ty, 0));
4539+
auto ifOp = builder.create<fir::IfOp>(loc, heapTy, allocated,
4540+
/*withElseRegion=*/true);
4541+
builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
4542+
builder.create<fir::ResultOp>(loc, addr);
4543+
builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
4544+
mlir::Value byteSize =
4545+
isModes ? fir::runtime::genGetModesTypeSize(builder, loc)
4546+
: fir::runtime::genGetStatusTypeSize(builder, loc);
4547+
byteSize = builder.createConvert(loc, builder.getIndexType(), byteSize);
4548+
addr =
4549+
builder.create<fir::AllocMemOp>(loc, extractSequenceType(heapTy),
4550+
/*typeparams=*/std::nullopt, byteSize);
4551+
mlir::Value shape = builder.create<fir::ShapeOp>(loc, byteSize);
4552+
builder.create<fir::StoreOp>(
4553+
loc, builder.create<fir::EmboxOp>(loc, fieldTy, addr, shape), fieldRef);
4554+
builder.create<fir::ResultOp>(loc, addr);
4555+
builder.setInsertionPointAfter(ifOp);
4556+
addr = builder.create<fir::ConvertOp>(loc, ptrTy, ifOp.getResult(0));
4557+
} else {
4558+
// Place floating point environment data in __data storage.
4559+
addr = builder.create<fir::ConvertOp>(loc, ptrTy, getBase(args[0]));
4560+
}
4561+
llvm::StringRef func = isModes ? (isGet ? "fegetmode" : "fesetmode")
4562+
: (isGet ? "fegetenv" : "fesetenv");
4563+
genRuntimeCall(func, i32Ty, addr);
4564+
#endif
45144565
}
45154566

45164567
// Check that an explicit ieee_[get|set]_rounding_mode call radix value is 2.
@@ -4543,18 +4594,6 @@ void IntrinsicLibrary::genIeeeGetRoundingMode(
45434594
builder.create<fir::StoreOp>(loc, mode, fieldRef);
45444595
}
45454596

4546-
// IEEE_GET_STATUS, IEEE_SET_STATUS
4547-
template <bool isGet>
4548-
void IntrinsicLibrary::genIeeeGetOrSetStatus(
4549-
llvm::ArrayRef<fir::ExtendedValue> args) {
4550-
assert(args.size() == 1);
4551-
mlir::Type ptrTy = builder.getRefType(builder.getIntegerType(32));
4552-
mlir::Type i32Ty = builder.getIntegerType(32);
4553-
mlir::Value addr =
4554-
builder.create<fir::ConvertOp>(loc, ptrTy, getBase(args[0]));
4555-
genRuntimeCall(isGet ? "fegetenv" : "fesetenv", i32Ty, addr);
4556-
}
4557-
45584597
// IEEE_GET_UNDERFLOW_MODE
45594598
void IntrinsicLibrary::genIeeeGetUnderflowMode(
45604599
llvm::ArrayRef<fir::ExtendedValue> args) {

flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,17 @@ void fir::runtime::genSetUnderflowMode(fir::FirOpBuilder &builder,
4242
fir::runtime::getRuntimeFunc<mkRTKey(SetUnderflowMode)>(loc, builder)};
4343
builder.create<fir::CallOp>(loc, func, flag);
4444
}
45+
46+
mlir::Value fir::runtime::genGetModesTypeSize(fir::FirOpBuilder &builder,
47+
mlir::Location loc) {
48+
mlir::func::FuncOp func{
49+
fir::runtime::getRuntimeFunc<mkRTKey(GetModesTypeSize)>(loc, builder)};
50+
return builder.create<fir::CallOp>(loc, func).getResult(0);
51+
}
52+
53+
mlir::Value fir::runtime::genGetStatusTypeSize(fir::FirOpBuilder &builder,
54+
mlir::Location loc) {
55+
mlir::func::FuncOp func{
56+
fir::runtime::getRuntimeFunc<mkRTKey(GetStatusTypeSize)>(loc, builder)};
57+
return builder.create<fir::CallOp>(loc, func).getResult(0);
58+
}

flang/module/__fortran_ieee_exceptions.f90

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@
3636
ieee_all(*) = [ ieee_usual, ieee_underflow, ieee_inexact ]
3737

3838
type, public :: ieee_modes_type ! Fortran 2018, 17.7
39-
private ! opaque fenv.h femode_t data
39+
private ! opaque fenv.h femode_t data; code will access only one component
4040
integer(kind=4) :: __data(_FORTRAN_RUNTIME_IEEE_FEMODE_T_EXTENT)
41+
integer(kind=1), allocatable :: __allocatable_data(:)
4142
end type ieee_modes_type
4243

4344
type, public :: ieee_status_type ! Fortran 2018, 17.7
44-
private ! opaque fenv.h fenv_t data
45+
private ! opaque fenv.h fenv_t data; code will access only one component
4546
integer(kind=4) :: __data(_FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT)
47+
integer(kind=1), allocatable :: __allocatable_data(:)
4648
end type ieee_status_type
4749

4850
! Define specifics with 1 LOGICAL or REAL argument for generic G.

0 commit comments

Comments
 (0)