Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -787,6 +787,37 @@ } Triple.setArchName(ArchName + Suffix.str()); + bool isHardFloat = + (arm::getARMFloatABI(getDriver(), Triple, Args) == arm::FloatABI::Hard); + switch (Triple.getEnvironment()) { + case Triple::GNUEABI: + case Triple::GNUEABIHF: + Triple.setEnvironment(isHardFloat ? Triple::GNUEABIHF : Triple::GNUEABI); + break; + case Triple::EABI: + case Triple::EABIHF: + Triple.setEnvironment(isHardFloat ? Triple::EABIHF : Triple::EABI); + break; + case Triple::MuslEABI: + case Triple::MuslEABIHF: + Triple.setEnvironment(isHardFloat ? Triple::MuslEABIHF + : Triple::MuslEABI); + break; + default: { + arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple); + if (DefaultABI != arm::FloatABI::Invalid && + isHardFloat != (DefaultABI == arm::FloatABI::Hard)) { + Arg *ABIArg = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ); + assert(ABIArg && "Non-default float abi expected to be from arg"); + D.Diag(diag::err_drv_unsupported_opt_for_target) + << ABIArg->getAsString(Args) << Triple.getTriple(); + } + break; + } + } + return Triple.getTriple(); } } Index: clang/lib/Driver/ToolChains/Arch/ARM.h =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.h +++ clang/lib/Driver/ToolChains/Arch/ARM.h @@ -47,6 +47,7 @@ Hard, }; +FloatABI getDefaultFloatABI(const llvm::Triple &Triple); FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args); FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -134,6 +134,7 @@ // The backend is hardwired to assume AAPCS for M-class processors, ensure // the frontend matches that. return T.getEnvironment() == llvm::Triple::EABI || + T.getEnvironment() == llvm::Triple::EABIHF || T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); } @@ -160,11 +161,73 @@ return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args); } +arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) { + auto SubArch = getARMSubArchVersionNumber(Triple); + switch (Triple.getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + // Darwin defaults to "softfp" for v6 and v7. + if (Triple.isWatchABI()) + return FloatABI::Hard; + else + return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; + + case llvm::Triple::WatchOS: + return FloatABI::Hard; + + // FIXME: this is invalid for WindowsCE + case llvm::Triple::Win32: + return FloatABI::Hard; + + case llvm::Triple::NetBSD: + switch (Triple.getEnvironment()) { + case llvm::Triple::EABIHF: + case llvm::Triple::GNUEABIHF: + return FloatABI::Hard; + default: + return FloatABI::Soft; + } + break; + + case llvm::Triple::FreeBSD: + switch (Triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + return FloatABI::Hard; + default: + // FreeBSD defaults to soft float + return FloatABI::Soft; + } + break; + + case llvm::Triple::OpenBSD: + return FloatABI::SoftFP; + + default: + switch (Triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + case llvm::Triple::MuslEABIHF: + case llvm::Triple::EABIHF: + return FloatABI::Hard; + case llvm::Triple::GNUEABI: + case llvm::Triple::MuslEABI: + case llvm::Triple::EABI: + // EABI is always AAPCS, and if it was not marked 'hard', it's softfp + return FloatABI::SoftFP; + case llvm::Triple::Android: + return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft; + default: + return FloatABI::Invalid; + } + } + return FloatABI::Invalid; +} + // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) { - auto SubArch = getARMSubArchVersionNumber(Triple); arm::FloatABI ABI = FloatABI::Invalid; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -184,95 +247,23 @@ ABI = FloatABI::Soft; } } - - // It is incorrect to select hard float ABI on MachO platforms if the ABI is - // "apcs-gnu". - if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) && - ABI == FloatABI::Hard) { - D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) - << Triple.getArchName(); - } } // If unspecified, choose the default based on the platform. - if (ABI == FloatABI::Invalid) { - switch (Triple.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: { - // Darwin defaults to "softfp" for v6 and v7. - ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; - ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI; - break; - } - case llvm::Triple::WatchOS: - ABI = FloatABI::Hard; - break; + if (ABI == FloatABI::Invalid) + ABI = arm::getDefaultFloatABI(Triple); - // FIXME: this is invalid for WindowsCE - case llvm::Triple::Win32: + if (ABI == FloatABI::Invalid) { + // Assume "soft", but warn the user we are guessing. + if (Triple.isOSBinFormatMachO() && + Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) ABI = FloatABI::Hard; - break; - - case llvm::Triple::NetBSD: - switch (Triple.getEnvironment()) { - case llvm::Triple::EABIHF: - case llvm::Triple::GNUEABIHF: - ABI = FloatABI::Hard; - break; - default: - ABI = FloatABI::Soft; - break; - } - break; - - case llvm::Triple::FreeBSD: - switch (Triple.getEnvironment()) { - case llvm::Triple::GNUEABIHF: - ABI = FloatABI::Hard; - break; - default: - // FreeBSD defaults to soft float - ABI = FloatABI::Soft; - break; - } - break; - - case llvm::Triple::OpenBSD: - ABI = FloatABI::SoftFP; - break; + else + ABI = FloatABI::Soft; - default: - switch (Triple.getEnvironment()) { - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABIHF: - case llvm::Triple::EABIHF: - ABI = FloatABI::Hard; - break; - case llvm::Triple::GNUEABI: - case llvm::Triple::MuslEABI: - case llvm::Triple::EABI: - // EABI is always AAPCS, and if it was not marked 'hard', it's softfp - ABI = FloatABI::SoftFP; - break; - case llvm::Triple::Android: - ABI = (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft; - break; - default: - // Assume "soft", but warn the user we are guessing. - if (Triple.isOSBinFormatMachO() && - Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) - ABI = FloatABI::Hard; - else - ABI = FloatABI::Soft; - - if (Triple.getOS() != llvm::Triple::UnknownOS || - !Triple.isOSBinFormatMachO()) - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; - break; - } - } + if (Triple.getOS() != llvm::Triple::UnknownOS || + !Triple.isOSBinFormatMachO()) + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; } assert(ABI != FloatABI::Invalid && "must select an ABI"); Index: clang/test/Driver/arm-float-abi-lto.c =================================================================== --- /dev/null +++ clang/test/Driver/arm-float-abi-lto.c @@ -0,0 +1,63 @@ +// REQUIRES: arm-registered-target + +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -S -o - -emit-llvm -DCALL_LIB -DDEFINE_LIB | FileCheck %s + +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.call_full.bc -DCALL_LIB +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.define_full.bc -DDEFINE_LIB +// RUN: llvm-lto2 run -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \ +// RUN: -r %t.call_full.bc,fn,px \ +// RUN: -r %t.call_full.bc,fwrite,l \ +// RUN: -r %t.call_full.bc,putchar,l \ +// RUN: -r %t.call_full.bc,stdout,px \ +// RUN: -r %t.define_full.bc,fwrite,px \ +// RUN: -r %t.define_full.bc,putchar,px \ +// RUN: -r %t.define_full.bc,otherfn,px +// RUN: llvm-dis %t.lto_full.0.4.opt.bc -o - | FileCheck %s + +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.call_thin.bc -DCALL_LIB +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB +// RUN: llvm-lto2 run -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \ +// RUN: -r %t.call_thin.bc,fn,px \ +// RUN: -r %t.call_thin.bc,fwrite,l \ +// RUN: -r %t.call_thin.bc,putchar,l \ +// RUN: -r %t.call_thin.bc,stdout,px \ +// RUN: -r %t.define_thin.bc,fwrite,px \ +// RUN: -r %t.define_thin.bc,putchar,px \ +// RUN: -r %t.define_thin.bc,otherfn,px +// RUN: llvm-dis %t.lto_thin.1.4.opt.bc -o - | FileCheck %s + +// We expect that the fprintf is optimised to fwrite, and the printf is +// optimised to putchar. Check that we don't have a mismatch in calling +// conventions causing the call to be replaced by a trap. +// CHECK-LABEL: define{{.*}}void @fn() +// CHECK-NOT: call void @llvm.trap() + +typedef struct FILE FILE; +typedef unsigned int size_t; +extern FILE *stdout; +extern int fprintf(FILE *, const char *, ...); +extern int printf(const char *, ...); +extern void otherfn(const void *); + +#ifdef CALL_LIB + +void fn() { + fprintf(stdout, "hello world"); + printf("a"); +} + +#endif + +#ifdef DEFINE_LIB + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { + otherfn(ptr); + return 0; +} + +int putchar(int c) { + otherfn(&c); + return 0; +} + +#endif Index: clang/test/Driver/arm-float-abi.c =================================================================== --- clang/test/Driver/arm-float-abi.c +++ clang/test/Driver/arm-float-abi.c @@ -2,7 +2,7 @@ // RUN: %clang %s -target armv7-apple-ios -mfloat-abi=softfp -### 2>&1 | FileCheck -check-prefix=NOERROR %s // RUN: %clang %s -arch armv7 -target thumbv7-apple-darwin-eabi -mfloat-abi=hard -### 2>&1 | FileCheck -check-prefix=NOERROR %s -// ARMV7-ERROR: unsupported option '-mfloat-abi=hard' for target 'thumbv7' +// ARMV7-ERROR: unsupported option '-mfloat-abi=hard' for target 'thumbv7-apple-ios' // NOERROR-NOT: unsupported option // RUN: %clang -target armv7-linux-androideabi21 %s -### -c 2>&1 \ @@ -14,3 +14,25 @@ // RUN: | FileCheck --check-prefix=CHECK-ARM8-ANDROID %s // CHECK-ARM8-ANDROID-NOT: "-target-feature" "+soft-float" // CHECK-ARM8-ANDROID: "-target-feature" "+soft-float-abi" + +// RUN: not %clang -target armv7-linux-androideabi21 %s -S -o - -mfloat-abi=hard 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ERROR %s +// CHECK-ANDROID-ERROR: unsupported option '-mfloat-abi=hard' for target 'armv7-unknown-linux-android21' + +// RUN: %clang -target armv7-linux-androideabi21 %s -S -o - -mfloat-abi=soft 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-NOERROR %s +// RUN: %clang -target armv7-linux-androideabi21 %s -S -o - -mfloat-abi=softfp 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-NOERROR %s +// CHECK-ANDROID-NOERROR-NOT: unsupported option + +// RUN: not %clang -target armv7-apple-watchos4 %s -S -o - -mfloat-abi=soft 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-WATCHOS-ERROR1 %s +// CHECK-WATCHOS-ERROR1: unsupported option '-mfloat-abi=soft' for target 'thumbv7-apple-watchos4' + +// RUN: not %clang -target armv7-apple-watchos4 %s -S -o - -mfloat-abi=softfp 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-WATCHOS-ERROR2 %s +// CHECK-WATCHOS-ERROR2: unsupported option '-mfloat-abi=softfp' for target 'thumbv7-apple-watchos4' + +// RUN: %clang -target armv7-apple-watchos4 %s -S -o - -mfloat-abi=hard 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-WATCHOS-NOERROR %s +// CHECK-WATCHOS-NOERROR-NOT: unsupported option Index: clang/test/Driver/arm-triple.c =================================================================== --- /dev/null +++ clang/test/Driver/arm-triple.c @@ -0,0 +1,48 @@ +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi \ +// RUN: | FileCheck %s --check-prefix=CHECK-DEFAULT +// RUN: %clang -print-effective-triple \ +// RUN: --target=armeb-none-eabi -mlittle-endian \ +// RUN: | FileCheck %s --check-prefix=CHECK-DEFAULT +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabihf -march=armv4t -mfloat-abi=softfp \ +// RUN: | FileCheck %s --check-prefix=CHECK-DEFAULT +// CHECK-DEFAULT: armv4t-none-unknown-eabi + +// RUN: %clang -print-effective-triple \ +// RUN: --target=armeb-none-eabi \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi -mbig-endian \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB +// CHECK-EB: armebv4t-none-unknown-eabi + +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabihf -march=armv4t \ +// RUN: | FileCheck %s --check-prefix=CHECK-HF +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi -mfloat-abi=hard \ +// RUN: | FileCheck %s --check-prefix=CHECK-HF +// CHECK-HF: armv4t-none-unknown-eabihf + +// RUN: %clang -print-effective-triple \ +// RUN: --target=armeb-none-eabihf -march=armv4t \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB-HF +// RUN: %clang -print-effective-triple \ +// RUN: --target=armeb-none-eabi -mfloat-abi=hard \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB-HF +// RUN: %clang -print-effective-triple -march=armv4t \ +// RUN: --target=arm-none-eabihf -mbig-endian \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB-HF +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi -mbig-endian -mfloat-abi=hard \ +// RUN: | FileCheck %s --check-prefix=CHECK-EB-HF +// CHECK-EB-HF: armebv4t-none-unknown-eabihf + +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi -march=armv8m.main -mbig-endian -mfloat-abi=hard \ +// RUN: | FileCheck %s --check-prefix=CHECK-V8M-EB-HF +// RUN: %clang -print-effective-triple \ +// RUN: --target=arm-none-eabi -mcpu=cortex-m33 -mbig-endian -mfloat-abi=hard \ +// RUN: | FileCheck %s --check-prefix=CHECK-V8M-EB-HF +// CHECK-V8M-EB-HF: thumbebv8m.main-none-unknown-eabihf Index: clang/test/Driver/windows-thumbv7em.cpp =================================================================== --- clang/test/Driver/windows-thumbv7em.cpp +++ clang/test/Driver/windows-thumbv7em.cpp @@ -1,8 +1,8 @@ // RUN: %clang -target thumb-none-windows-eabi-coff -mcpu=cortex-m7 -### -c %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-V7 -// CHECK-V7-NOT: error: the target architecture 'thumbv7em' is not supported by the target 'thumbv7em-none-windows-eabi' +// CHECK-V7-NOT: error: the target architecture 'thumbv7em' is not supported by the target 'thumbv7em-none-windows-eabihf' // RUN: %clang -target thumb-none-windows-eabi-coff -mcpu=cortex-m1 -### -c %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-V6 -// CHECK-V6: error: the target architecture 'thumbv6m' is not supported by the target 'thumbv6m-none-windows-eabi' +// CHECK-V6: error: the target architecture 'thumbv6m' is not supported by the target 'thumbv6m-none-windows-eabihf'