forked from OSchip/llvm-project
[Driver] Incorporate -mfloat-abi in the computed triple on ARM
LLVM assumes that when it creates a call to a C library function it can use the C calling convention. On ARM the effective calling convention is determined from the target triple, however using -mfloat-abi=hard on ARM means that calls to (and definitions of) C library functions use the arm_aapcs_vfpcc calling convention which can result in a mismatch. Fix this by incorporating -mfloat-abi into the target triple, similar to how -mbig-endian and -march/-mcpu are. This only works for EABI targets and not Android or iOS, but there the float abi is fixed so instead give an error. Fixes PR45524 Differential Revision: https://reviews.llvm.org/D89573
This commit is contained in:
parent
a6336eab0c
commit
0c66606230
|
@ -787,6 +787,37 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
|
|||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
|
|||
// 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 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
|
|||
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 @@ arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
|
|||
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)
|
||||
ABI = arm::getDefaultFloatABI(Triple);
|
||||
|
||||
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:
|
||||
// Assume "soft", but warn the user we are guessing.
|
||||
if (Triple.isOSBinFormatMachO() &&
|
||||
Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
|
||||
ABI = FloatABI::Hard;
|
||||
break;
|
||||
else
|
||||
ABI = FloatABI::Soft;
|
||||
|
||||
// FIXME: this is invalid for WindowsCE
|
||||
case llvm::Triple::Win32:
|
||||
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;
|
||||
|
||||
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");
|
||||
|
|
|
@ -47,6 +47,7 @@ enum class FloatABI {
|
|||
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);
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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'
|
||||
|
||||
|
|
Loading…
Reference in New Issue