diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -109,6 +109,23 @@ namespace { +enum { + // GNU attribute tags for PowerPC ABI + Tag_GNU_Power_ABI_FP = 4, + Tag_GNU_Power_ABI_Vector = 8, + Tag_GNU_Power_ABI_Struct_Return = 12, + + // GNU attribute values for PowerPC float ABI, as combination of two parts + Val_GNU_Power_ABI_NoFloat = 0b00, + Val_GNU_Power_ABI_HardFloat_DP = 0b01, + Val_GNU_Power_ABI_SoftFloat_DP = 0b10, + Val_GNU_Power_ABI_HardFloat_SP = 0b11, + + Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100, + Val_GNU_Power_ABI_LDBL_64 = 0b1000, + Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100, +}; + class PPCAsmPrinter : public AsmPrinter { protected: // For TLS on AIX, we need to be able to identify TOC entries of specific @@ -178,6 +195,8 @@ return "Linux PPC Assembly Printer"; } + void emitGNUAttributes(Module &M); + void emitStartOfAsmFile(Module &M) override; void emitEndOfAsmFile(Module &) override; @@ -1388,6 +1407,28 @@ EmitToStreamer(*OutStreamer, TmpInst); } +void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) { + // Emit float ABI into GNU attribute + Metadata *MD = M.getModuleFlag("float-abi"); + MDString *FloatABI = dyn_cast_or_null(MD); + if (!FloatABI) + return; + StringRef flt = FloatABI->getString(); + // TODO: Support emitting soft-fp and hard double/single attributes. + if (flt == "doubledouble") + OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP, + Val_GNU_Power_ABI_HardFloat_DP | + Val_GNU_Power_ABI_LDBL_IBM128); + else if (flt == "ieeequad") + OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP, + Val_GNU_Power_ABI_HardFloat_DP | + Val_GNU_Power_ABI_LDBL_IEEE128); + else if (flt == "ieeedouble") + OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP, + Val_GNU_Power_ABI_HardFloat_DP | + Val_GNU_Power_ABI_LDBL_64); +} + void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) { if (!Subtarget->isPPC64()) return PPCAsmPrinter::emitInstruction(MI); @@ -1642,6 +1683,8 @@ PPCTargetStreamer *TS = static_cast(OutStreamer->getTargetStreamer()); + emitGNUAttributes(M); + if (!TOC.empty()) { const char *Name = isPPC64 ? ".toc" : ".got2"; MCSectionELF *Section = OutContext.getELFSection( diff --git a/llvm/test/CodeGen/PowerPC/gnu-attribute.ll b/llvm/test/CodeGen/PowerPC/gnu-attribute.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/gnu-attribute.ll @@ -0,0 +1,15 @@ +; RUN: sed -e 's/FLTABI/ieeequad/' %s | llc -mtriple=powerpc64le | FileCheck %s --check-prefix=IEEE +; RUN: sed -e 's/FLTABI/doubledouble/' %s | llc -mtriple=powerpc64le | FileCheck %s --check-prefix=IBM +; RUN: sed -e 's/FLTABI/ieeedouble/' %s | llc -mtriple=powerpc64le | FileCheck %s --check-prefix=DBL +; RUN: sed -e 's/FLTABI//' %s | llc -mtriple=powerpc64le | FileCheck %s --check-prefix=NONE + +; IEEE: .gnu_attribute 4, 13 +; IBM: .gnu_attribute 4, 5 +; DBL: .gnu_attribute 4, 9 +; NONE-NOT: .gnu_attribute 4, + +!llvm.module.flags = !{!0, !1, !2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"uwtable", i32 1} +!2 = !{i32 1, !"float-abi", !"FLTABI"}