|
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