Index: flang/include/flang/ISO_Fortran_binding.h =================================================================== --- flang/include/flang/ISO_Fortran_binding.h +++ flang/include/flang/ISO_Fortran_binding.h @@ -43,8 +43,7 @@ typedef signed char CFI_type_t; /* These codes are required to be macros (i.e., #ifdef will work). * They are not required to be distinct, but neither are they required - * to have had their synonyms combined. Codes marked as extensions may be - * place holders for as yet unimplemented types. + * to have had their synonyms combined. */ #define CFI_type_signed_char 1 #define CFI_type_short 2 @@ -56,7 +55,7 @@ #define CFI_type_int16_t 8 #define CFI_type_int32_t 9 #define CFI_type_int64_t 10 -#define CFI_type_int128_t 11 /* extension */ +#define CFI_type_int128_t 11 /* extension kind=16 */ #define CFI_type_int_least8_t 12 #define CFI_type_int_least16_t 13 #define CFI_type_int_least32_t 14 @@ -88,8 +87,8 @@ #define CFI_type_char 40 #define CFI_type_cptr 41 #define CFI_type_struct 42 -#define CFI_type_char16_t 43 /* extension */ -#define CFI_type_char32_t 44 /* extension */ +#define CFI_type_char16_t 43 /* extension kind=2 */ +#define CFI_type_char32_t 44 /* extension kind=4 */ #define CFI_TYPE_LAST CFI_type_char32_t #define CFI_type_other (-1) // must be negative Index: flang/include/flang/Optimizer/Dialect/FIRType.h =================================================================== --- flang/include/flang/Optimizer/Dialect/FIRType.h +++ flang/include/flang/Optimizer/Dialect/FIRType.h @@ -359,6 +359,8 @@ mlir::Type fromRealTypeID(mlir::MLIRContext *context, llvm::Type::TypeID typeID, fir::KindTy kind); +int getTypeCode(mlir::Type ty, KindMapping &kindMap); + inline bool BaseBoxType::classof(mlir::Type type) { return type.isa(); } Index: flang/lib/Optimizer/CodeGen/CodeGen.cpp =================================================================== --- flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -1272,119 +1272,42 @@ mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, mlir::Type boxEleTy, mlir::ValueRange lenParams = {}) const { auto i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64); - auto getKindMap = [&]() -> fir::KindMapping & { - return this->lowerTy().getKindMap(); - }; - auto doInteger = - [&](mlir::Type type, - unsigned width) -> std::tuple { - int typeCode = fir::integerBitsToTypeCode(width); - return { - genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), - this->genConstantOffset(loc, rewriter, typeCode)}; - }; - auto doLogical = - [&](mlir::Type type, - unsigned width) -> std::tuple { - int typeCode = fir::logicalBitsToTypeCode(width); - return { - genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), - this->genConstantOffset(loc, rewriter, typeCode)}; - }; - auto doFloat = [&](mlir::Type type, - unsigned width) -> std::tuple { - int typeCode = fir::realBitsToTypeCode(width); - return { - genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), - this->genConstantOffset(loc, rewriter, typeCode)}; - }; - auto doComplex = - [&](mlir::Type type, - unsigned width) -> std::tuple { - auto typeCode = fir::complexBitsToTypeCode(width); - return { - genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), - this->genConstantOffset(loc, rewriter, typeCode)}; - }; - auto doCharacter = [&](fir::CharacterType type, mlir::ValueRange lenParams) - -> std::tuple { - unsigned bitWidth = getKindMap().getCharacterBitsize(type.getFKind()); - auto typeCode = fir::characterBitsToTypeCode(bitWidth); - auto typeCodeVal = this->genConstantOffset(loc, rewriter, typeCode); - - bool lengthIsConst = (type.getLen() != fir::CharacterType::unknownLen()); - mlir::Value eleSize = - genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)); - - if (!lengthIsConst) { - // If length is constant, then the fir::CharacterType will be - // represented as an array of known size of elements having - // the corresponding LLVM type. In this case eleSize already - // holds correct memory size. If length is not constant, then - // the fir::CharacterType will decay to a scalar type, - // so we have to multiply it by the non-constant length - // to get its size in memory. + if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy)) + boxEleTy = eleTy; + if (auto seqTy = boxEleTy.dyn_cast()) + return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams); + if (boxEleTy.isa()) // unlimited polymorphic or assumed type + return {rewriter.create(loc, i64Ty, 0), + this->genConstantOffset(loc, rewriter, CFI_type_other)}; + mlir::Value typeCodeVal = this->genConstantOffset( + loc, rewriter, + fir::getTypeCode(boxEleTy, this->lowerTy().getKindMap())); + if (fir::isa_integer(boxEleTy) || boxEleTy.dyn_cast() || + fir::isa_real(boxEleTy) || fir::isa_complex(boxEleTy)) + return {genTypeStrideInBytes(loc, i64Ty, rewriter, + this->convertType(boxEleTy)), + typeCodeVal}; + if (auto charTy = boxEleTy.dyn_cast()) { + mlir::Value size = + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(charTy)); + if (charTy.getLen() == fir::CharacterType::unknownLen()) { + // Multiply the single character size by the length. assert(!lenParams.empty()); auto len64 = FIROpConversion::integerCast(loc, rewriter, i64Ty, lenParams.back()); - eleSize = - rewriter.create(loc, i64Ty, eleSize, len64); + size = rewriter.create(loc, i64Ty, size, len64); } - return {eleSize, typeCodeVal}; + return {size, typeCodeVal}; }; - // Pointer-like types. - if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy)) - boxEleTy = eleTy; - // Integer types. - if (fir::isa_integer(boxEleTy)) { - if (auto ty = boxEleTy.dyn_cast()) - return doInteger(ty, ty.getWidth()); - auto ty = boxEleTy.cast(); - return doInteger(ty, getKindMap().getIntegerBitsize(ty.getFKind())); - } - // Floating point types. - if (fir::isa_real(boxEleTy)) { - if (auto ty = boxEleTy.dyn_cast()) - return doFloat(ty, ty.getWidth()); - auto ty = boxEleTy.cast(); - return doFloat(ty, getKindMap().getRealBitsize(ty.getFKind())); - } - // Complex types. - if (fir::isa_complex(boxEleTy)) { - if (auto ty = boxEleTy.dyn_cast()) - return doComplex( - ty, ty.getElementType().cast().getWidth()); - auto ty = boxEleTy.cast(); - return doComplex(ty, getKindMap().getRealBitsize(ty.getFKind())); - } - // Character types. - if (auto ty = boxEleTy.dyn_cast()) - return doCharacter(ty, lenParams); - // Logical type. - if (auto ty = boxEleTy.dyn_cast()) - return doLogical(ty, getKindMap().getLogicalBitsize(ty.getFKind())); - // Array types. - if (auto seqTy = boxEleTy.dyn_cast()) - return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams); - // Derived-type types. - if (boxEleTy.isa()) { - auto eleSize = genTypeStrideInBytes(loc, i64Ty, rewriter, - this->convertType(boxEleTy)); - return {eleSize, - this->genConstantOffset(loc, rewriter, fir::derivedToTypeCode())}; - } - // Reference type. if (fir::isa_ref_type(boxEleTy)) { auto ptrTy = mlir::LLVM::LLVMPointerType::get( mlir::LLVM::LLVMVoidType::get(rewriter.getContext())); - mlir::Value size = genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy); - return {size, this->genConstantOffset(loc, rewriter, CFI_type_cptr)}; + return {genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy), typeCodeVal}; } - // Unlimited polymorphic or assumed type. Use 0 and CFI_type_other since the - // information is not none at this point. - if (boxEleTy.isa()) - return {rewriter.create(loc, i64Ty, 0), - this->genConstantOffset(loc, rewriter, CFI_type_other)}; + if (boxEleTy.isa()) + return {genTypeStrideInBytes(loc, i64Ty, rewriter, + this->convertType(boxEleTy)), + typeCodeVal}; fir::emitFatalError(loc, "unhandled type in fir.box code generation"); } Index: flang/lib/Optimizer/Dialect/FIRType.cpp =================================================================== --- flang/lib/Optimizer/Dialect/FIRType.cpp +++ flang/lib/Optimizer/Dialect/FIRType.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/ISO_Fortran_binding.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/Support/KindMapping.h" #include "flang/Tools/PointerModels.h" @@ -381,6 +382,97 @@ return ty; } +/// Return the ISO_C_BINDING intrinsic module value of type \p ty. +int getTypeCode(mlir::Type ty, fir::KindMapping &kindMap) { + unsigned width = 0; + if (mlir::IntegerType intTy = ty.dyn_cast()) { + switch (intTy.getWidth()) { + case 8: + return CFI_type_int8_t; + case 16: + return CFI_type_int16_t; + case 32: + return CFI_type_int32_t; + case 64: + return CFI_type_int64_t; + case 128: + return CFI_type_int128_t; + } + llvm_unreachable("unsupported integer type"); + } + if (fir::LogicalType logicalTy = ty.dyn_cast()) { + switch (kindMap.getLogicalBitsize(logicalTy.getFKind())) { + case 8: + return CFI_type_Bool; + case 16: + return CFI_type_int_least16_t; + case 32: + return CFI_type_int_least32_t; + case 64: + return CFI_type_int_least64_t; + } + llvm_unreachable("unsupported logical type"); + } + if (mlir::FloatType floatTy = ty.dyn_cast()) { + switch (floatTy.getWidth()) { + case 16: + return floatTy.isBF16() ? CFI_type_bfloat : CFI_type_half_float; + case 32: + return CFI_type_float; + case 64: + return CFI_type_double; + case 80: + return CFI_type_extended_double; + case 128: + return CFI_type_float128; + } + llvm_unreachable("unsupported real type"); + } + if (fir::isa_complex(ty)) { + if (mlir::ComplexType complexTy = ty.dyn_cast()) { + mlir::FloatType floatTy = + complexTy.getElementType().cast(); + if (floatTy.isBF16()) + return CFI_type_bfloat_Complex; + width = floatTy.getWidth(); + } else if (fir::ComplexType complexTy = ty.dyn_cast()) { + auto FKind = complexTy.getFKind(); + if (FKind == 3) + return CFI_type_bfloat_Complex; + width = kindMap.getRealBitsize(FKind); + } + switch (width) { + case 16: + return CFI_type_half_float_Complex; + case 32: + return CFI_type_float_Complex; + case 64: + return CFI_type_double_Complex; + case 80: + return CFI_type_extended_double_Complex; + case 128: + return CFI_type_float128_Complex; + } + llvm_unreachable("unsupported complex size"); + } + if (fir::CharacterType charTy = ty.dyn_cast()) { + switch (kindMap.getCharacterBitsize(charTy.getFKind())) { + case 8: + return CFI_type_char; + case 16: + return CFI_type_char16_t; + case 32: + return CFI_type_char32_t; + } + llvm_unreachable("unsupported character type"); + } + if (fir::isa_ref_type(ty)) + return CFI_type_cptr; + if (ty.isa()) + return CFI_type_struct; + llvm_unreachable("unsupported type"); +} + } // namespace fir namespace { Index: flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp =================================================================== --- flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp +++ flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp @@ -62,8 +62,6 @@ mlir::Type ty, mlir::ModuleOp mod, mlir::PatternRewriter &rewriter) const; - static int getTypeCode(mlir::Type ty, fir::KindMapping &kindMap); - mlir::LogicalResult genTypeLadderStep(mlir::Location loc, mlir::Value selector, mlir::Attribute attr, mlir::Block *dest, @@ -362,7 +360,7 @@ a.getType().isa()) { // For type guard statement with Intrinsic type spec the type code of // the descriptor is compared. - int code = getTypeCode(a.getType(), kindMap); + int code = fir::getTypeCode(a.getType(), kindMap); if (code == 0) return mlir::emitError(loc) << "type code unavailable for " << a.getType(); @@ -461,28 +459,6 @@ loc, mlir::arith::CmpIPredicate::eq, typeDescInt, selectorTdescInt); } -int SelectTypeConv::getTypeCode(mlir::Type ty, fir::KindMapping &kindMap) { - if (auto intTy = ty.dyn_cast()) - return fir::integerBitsToTypeCode(intTy.getWidth()); - if (auto floatTy = ty.dyn_cast()) - return fir::realBitsToTypeCode(floatTy.getWidth()); - if (auto logicalTy = ty.dyn_cast()) - return fir::logicalBitsToTypeCode( - kindMap.getLogicalBitsize(logicalTy.getFKind())); - if (fir::isa_complex(ty)) { - if (auto cmplxTy = ty.dyn_cast()) - return fir::complexBitsToTypeCode( - cmplxTy.getElementType().cast().getWidth()); - auto cmplxTy = ty.cast(); - return fir::complexBitsToTypeCode( - kindMap.getRealBitsize(cmplxTy.getFKind())); - } - if (auto charTy = ty.dyn_cast()) - return fir::characterBitsToTypeCode( - kindMap.getCharacterBitsize(charTy.getFKind())); - return 0; -} - llvm::SmallSet SelectTypeConv::collectAncestors(fir::DispatchTableOp dt, mlir::ModuleOp mod) const { Index: flang/test/Fir/convert-to-llvm.fir =================================================================== --- flang/test/Fir/convert-to-llvm.fir +++ flang/test/Fir/convert-to-llvm.fir @@ -1563,10 +1563,10 @@ // CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr> // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>> +// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] // CHECK: %[[I64_ELEM_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 -// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[I64_ELEM_SIZE]], %[[DESC]][1] : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> // CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -1786,10 +1786,10 @@ // CHECK: %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>> // CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK: %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] // CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 -// CHECK: %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -1885,10 +1885,10 @@ // CHECK: %[[ARR_SIZE_TMP1:.*]] = llvm.mul %[[C1_0]], %[[N1]] : i64 // CHECK: %[[ARR_SIZE:.*]] = llvm.mul %[[ARR_SIZE_TMP1]], %[[N2]] : i64 // CHECK: %[[ARR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr", in_type = !fir.array, operand_segment_sizes = array, uniq_name = "_QFsbEarr"} : (i64) -> !llvm.ptr +// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32 // CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] // CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 -// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32 // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -1964,10 +1964,10 @@ // CHECK: %[[V:.*]] = llvm.alloca %[[ALLOCA_SIZE_V]] x i32 {bindc_name = "v", in_type = i32, operand_segment_sizes = array, uniq_name = "_QFtest_dt_sliceEv"} : (i64) -> !llvm.ptr // CHECK: %[[ALLOCA_SIZE_X:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[X:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x", in_type = !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>, operand_segment_sizes = array, uniq_name = "_QFtest_dt_sliceEx"} : (i64) -> !llvm.ptr>> +// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] // CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 -// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -2240,10 +2240,10 @@ //CHECK: %[[FIVE:.*]] = llvm.mlir.constant(5 : index) : i64 //CHECK: %[[SIX:.*]] = llvm.mlir.constant(6 : index) : i64 //CHECK: %[[EIGHTY:.*]] = llvm.mlir.constant(80 : index) : i64 +//CHECK: %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32 //CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr //CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] //CHECK: %[[ELEM_SIZE_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 -//CHECK: %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32 //CHECK: %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> //CHECK: %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE_I64]], %[[RBOX]][1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> //CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 Index: flang/test/Lower/real-descriptors.f90 =================================================================== --- /dev/null +++ flang/test/Lower/real-descriptors.f90 @@ -0,0 +1,98 @@ +! RUN: bbc %s -o - | tco | FileCheck %s + +! CHECK-LABEL: define void @_QQmain() +program p + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8 + ! CHECK-DAG: alloca { x86_fp80, x86_fp80 }, i64 1, align 16 + ! CHECK-DAG: alloca { fp128, fp128 }, i64 1, align 16 + ! CHECK-DAG: alloca { half, half }, i64 1, align 8 + ! CHECK-DAG: alloca { bfloat, bfloat }, i64 1, align 8 + ! CHECK-DAG: alloca { float, float }, i64 1, align 8 + ! CHECK-DAG: alloca { double, double }, i64 1, align 8 + ! CHECK-DAG: alloca x86_fp80, i64 1, align 16 + ! CHECK-DAG: alloca fp128, i64 1, align 16 + ! CHECK-DAG: alloca half, i64 1, align 2 + ! CHECK-DAG: alloca bfloat, i64 1, align 2 + ! CHECK-DAG: alloca float, i64 1, align 4 + ! CHECK-DAG: alloca double, i64 1, align 8 + + character(10) :: in = 'NaN NaN' + + real(kind=2) :: x2 + real(kind=3) :: x3 + real(kind=4) :: x4 + real(kind=8) :: x8 + real(kind=10) :: x10 + real(kind=16) :: x16 + + complex(kind=2) :: c2 + complex(kind=3) :: c3 + complex(kind=4) :: c4 + complex(kind=8) :: c8 + complex(kind=10) :: c10 + complex(kind=16) :: c16 + + read(in,*) x2 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr (half, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 25, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z4)", x2 + + read(in,*) x3 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr (bfloat, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 26, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z4)", x3 + + read(in,*) x4 + ! CHECK: call i1 @_FortranAioOutputReal32(ptr %{{[0-9]*}}, float %{{[0-9]*}}) + print "(z8)", x4 + + read(in,*) x8 + ! CHECK: call i1 @_FortranAioOutputReal64(ptr %{{[0-9]*}}, double %{{[0-9]*}}) + print "(z16)", x8 + + read(in,*) x10 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr (x86_fp80, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 29, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z20)", x10 + + read(in,*) x16 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr (fp128, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 31, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z32)", x16 + + print* + read(in,*) c2 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr ({ half, half }, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 32, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z4,' ',z4)", c2 + + read(in,*) c3 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr ({ bfloat, bfloat }, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 33, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z4,' ',z4)", c3 + + read(in,*) c4 + ! CHECK: call i1 @_FortranAioOutputComplex32(ptr %{{[0-9]*}}, float %{{[0-9]*}}, float %{{[0-9]*}}) + print "(z8,' ',z8)", c4 + + read(in,*) c8 + ! CHECK: call i1 @_FortranAioOutputComplex64(ptr %{{[0-9]*}}, double %{{[0-9]*}}, double %{{[0-9]*}}) + print "(z16,' ',z16)", c8 + + read(in,*) c10 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr ({ x86_fp80, x86_fp80 }, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 36, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z20,' ',z20)", c10 + + read(in,*) c16 + ! CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8 } { ptr undef, i64 ptrtoint (ptr getelementptr ({ fp128, fp128 }, ptr null, i32 1) to i64), i32 {{[0-9]*}}, i8 0, i8 38, i8 0, i8 0 }, ptr %{{[0-9]*}}, 0 + ! CHECK: call i1 @_FortranAioOutputDescriptor(ptr %{{[0-9]*}}, ptr %{{[0-9]*}}) + print "(z32,' ',z32)", c16 +end