|
50 | 50 | #include "llvm/Support/Debug.h"
|
51 | 51 | #include "llvm/Support/MathExtras.h"
|
52 | 52 | #include "llvm/Support/raw_ostream.h"
|
| 53 | +#include <cfenv> // temporary -- only used in genIeeeGetOrSetModesOrStatus |
53 | 54 | #include <mlir/IR/Value.h>
|
54 | 55 | #include <optional>
|
55 | 56 |
|
@@ -318,13 +319,15 @@ static constexpr IntrinsicHandler handlers[]{
|
318 | 319 | {"ieee_get_halting_mode",
|
319 | 320 | &I::genIeeeGetHaltingMode,
|
320 | 321 | {{{"flag", asValue}, {"halting", asAddr}}}},
|
321 |
| - {"ieee_get_modes", &I::genIeeeGetOrSetModes</*isGet=*/true>}, |
| 322 | + {"ieee_get_modes", |
| 323 | + &I::genIeeeGetOrSetModesOrStatus</*isGet=*/true, /*isModes=*/true>}, |
322 | 324 | {"ieee_get_rounding_mode",
|
323 | 325 | &I::genIeeeGetRoundingMode,
|
324 | 326 | {{{"round_value", asAddr, handleDynamicOptional},
|
325 | 327 | {"radix", asValue, handleDynamicOptional}}},
|
326 | 328 | /*isElemental=*/false},
|
327 |
| - {"ieee_get_status", &I::genIeeeGetOrSetStatus</*isGet=*/true>}, |
| 329 | + {"ieee_get_status", |
| 330 | + &I::genIeeeGetOrSetModesOrStatus</*isGet=*/true, /*isModes=*/false>}, |
328 | 331 | {"ieee_get_underflow_mode",
|
329 | 332 | &I::genIeeeGetUnderflowMode,
|
330 | 333 | {{{"gradual", asAddr}}},
|
@@ -368,13 +371,15 @@ static constexpr IntrinsicHandler handlers[]{
|
368 | 371 | {"ieee_set_flag", &I::genIeeeSetFlagOrHaltingMode</*isFlag=*/true>},
|
369 | 372 | {"ieee_set_halting_mode",
|
370 | 373 | &I::genIeeeSetFlagOrHaltingMode</*isFlag=*/false>},
|
371 |
| - {"ieee_set_modes", &I::genIeeeGetOrSetModes</*isGet=*/false>}, |
| 374 | + {"ieee_set_modes", |
| 375 | + &I::genIeeeGetOrSetModesOrStatus</*isGet=*/false, /*isModes=*/true>}, |
372 | 376 | {"ieee_set_rounding_mode",
|
373 | 377 | &I::genIeeeSetRoundingMode,
|
374 | 378 | {{{"round_value", asValue, handleDynamicOptional},
|
375 | 379 | {"radix", asValue, handleDynamicOptional}}},
|
376 | 380 | /*isElemental=*/false},
|
377 |
| - {"ieee_set_status", &I::genIeeeGetOrSetStatus</*isGet=*/false>}, |
| 381 | + {"ieee_set_status", |
| 382 | + &I::genIeeeGetOrSetModesOrStatus</*isGet=*/false, /*isModes=*/false>}, |
378 | 383 | {"ieee_set_underflow_mode", &I::genIeeeSetUnderflowMode},
|
379 | 384 | {"ieee_signaling_eq",
|
380 | 385 | &I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::OEQ>},
|
@@ -4108,11 +4113,12 @@ void IntrinsicLibrary::genRaiseExcept(int excepts, mlir::Value cond) {
|
4108 | 4113 | // Return a reference to the contents of a derived type with one field.
|
4109 | 4114 | // Also return the field type.
|
4110 | 4115 | 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) { |
4112 | 4118 | auto recType =
|
4113 | 4119 | 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]; |
4116 | 4122 | mlir::Value field = builder.create<fir::FieldIndexOp>(
|
4117 | 4123 | loc, fir::FieldType::get(recType.getContext()), fieldName, recType,
|
4118 | 4124 | fir::getTypeParams(rec));
|
@@ -4502,15 +4508,60 @@ void IntrinsicLibrary::genIeeeGetHaltingMode(
|
4502 | 4508 | }
|
4503 | 4509 |
|
4504 | 4510 | // 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( |
4507 | 4514 | llvm::ArrayRef<fir::ExtendedValue> args) {
|
4508 | 4515 | 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 |
4510 | 4523 | 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 |
4514 | 4565 | }
|
4515 | 4566 |
|
4516 | 4567 | // Check that an explicit ieee_[get|set]_rounding_mode call radix value is 2.
|
@@ -4543,18 +4594,6 @@ void IntrinsicLibrary::genIeeeGetRoundingMode(
|
4543 | 4594 | builder.create<fir::StoreOp>(loc, mode, fieldRef);
|
4544 | 4595 | }
|
4545 | 4596 |
|
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 |
| - |
4558 | 4597 | // IEEE_GET_UNDERFLOW_MODE
|
4559 | 4598 | void IntrinsicLibrary::genIeeeGetUnderflowMode(
|
4560 | 4599 | llvm::ArrayRef<fir::ExtendedValue> args) {
|
|
0 commit comments