diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -84,6 +84,9 @@ /// a recursive struct conversion, set this to true. bool SkippedLayout; + /// True if any instance of long double types are used. + bool LongDoubleReferenced; + /// This map keeps cache of llvm::Types and maps clang::Type to /// corresponding llvm::Type. llvm::DenseMap TypeCache; @@ -289,6 +292,7 @@ /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. bool isZeroInitializable(const RecordDecl *RD); + bool isLongDoubleReferenced() const { return LongDoubleReferenced; } bool isRecordLayoutComplete(const Type *Ty) const; unsigned getTargetAddressSpace(QualType T) const; }; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -34,6 +34,7 @@ Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()), TheABIInfo(cgm.getTargetCodeGenInfo().getABIInfo()) { SkippedLayout = false; + LongDoubleReferenced = false; } CodeGenTypes::~CodeGenTypes() { @@ -406,10 +407,12 @@ Context.getLangOpts().NativeHalfType || !Context.getTargetInfo().useFP16ConversionIntrinsics()); break; + case BuiltinType::LongDouble: + LongDoubleReferenced = true; + LLVM_FALLTHROUGH; case BuiltinType::BFloat16: case BuiltinType::Float: case BuiltinType::Double: - case BuiltinType::LongDouble: case BuiltinType::Float128: case BuiltinType::Ibm128: ResultType = getTypeForFormat(getLLVMContext(), diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -620,6 +620,9 @@ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; + void emitTargetMetadata(CodeGen::CodeGenModule &CGM, + const llvm::MapVector + &MangledDeclNames) const override; }; class PPC64TargetCodeGenInfo : public TargetCodeGenInfo { @@ -940,6 +943,24 @@ /*IsAIX*/ false); } +void PPC64_SVR4_TargetCodeGenInfo::emitTargetMetadata( + CodeGen::CodeGenModule &CGM, + const llvm::MapVector &MangledDeclNames) const { + if (CGM.getTypes().isLongDoubleReferenced()) { + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + const auto *flt = &CGM.getTarget().getLongDoubleFormat(); + if (flt == &llvm::APFloat::PPCDoubleDouble()) + CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi", + llvm::MDString::get(Ctx, "doubledouble")); + else if (flt == &llvm::APFloat::IEEEquad()) + CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi", + llvm::MDString::get(Ctx, "ieeequad")); + else if (flt == &llvm::APFloat::IEEEdouble()) + CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi", + llvm::MDString::get(Ctx, "ieeedouble")); + } +} + bool PPC64TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const { diff --git a/clang/test/CodeGen/ppc64-float-abi-attr.c b/clang/test/CodeGen/ppc64-float-abi-attr.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/ppc64-float-abi-attr.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu %s -emit-llvm -mabi=ieeelongdouble -o - | FileCheck %s --check-prefix=IEEE +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu %s -emit-llvm -mlong-double-64 -o - | FileCheck %s --check-prefix=LDBL64 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu %s -emit-llvm -DNOLDBL -o - | FileCheck %s --check-prefix=NOLDBL + +#ifndef NOLDBL +long double foo(long double a, long double b) { + return a + b; +} +#endif + +int bar() { return 1; } + +// CHECK: ![[#]] = !{i32 1, !"float-abi", !"doubledouble"} +// IEEE: ![[#]] = !{i32 1, !"float-abi", !"ieeequad"} +// LDBL64: ![[#]] = !{i32 1, !"float-abi", !"ieeedouble"} +// NOLDBL-NOT: ![[#]] = !{i32 1, !"float-abi"