Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -719,6 +719,42 @@ Features.push_back("+long-calls"); } + // Kernel code has more strict alignment requirements. + if (KernelOrKext) + Features.push_back("+strict-align"); + else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) { + if (A->getOption().matches(options::OPT_munaligned_access)) { + // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). + if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) + D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; + } else + Features.push_back("+strict-align"); + } else { + // Assume pre-ARMv6 doesn't support unaligned accesses. + // + // ARMv6 may or may not support unaligned accesses depending on the + // SCTLR.U bit, which is architecture-specific. We assume ARMv6 + // Darwin and NetBSD targets support unaligned accesses, and others don't. + // + // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit + // which raises an alignment fault on unaligned accesses. Linux + // defaults this bit to 0 and handles it as a system-wide (not + // per-process) setting. It is therefore safe to assume that ARMv7+ + // Linux targets support unaligned accesses. The same goes for NaCl. + // + // The above behavior is consistent with GCC. + int VersionNum = getARMSubArchVersionNumber(Triple); + if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { + if (VersionNum < 6) + Features.push_back("+strict-align"); + } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { + if (VersionNum < 7) + Features.push_back("+strict-align"); + } else + Features.push_back("+strict-align"); + } + // llvm does not support reserving registers in general. There is support // for reserving r9 on ARM though (defined as a platform-specific register // in ARM EABI). @@ -799,27 +835,6 @@ CmdArgs.push_back("hard"); } - // Kernel code has more strict alignment requirements. - if (KernelOrKext) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-strict-align"); - } - - // -mkernel implies -mstrict-align; don't add the redundant option. - if (!KernelOrKext) { - if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { - CmdArgs.push_back("-backend-option"); - if (A->getOption().matches(options::OPT_mno_unaligned_access)) - CmdArgs.push_back("-arm-strict-align"); - else { - if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) - D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; - CmdArgs.push_back("-arm-no-strict-align"); - } - } - } - // Forward the -mglobal-merge option for explicit control over the pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { Index: test/Driver/apple-kext-mkernel.c =================================================================== --- test/Driver/apple-kext-mkernel.c +++ test/Driver/apple-kext-mkernel.c @@ -12,8 +12,8 @@ // RUN: FileCheck --check-prefix=CHECK-ARM < %t %s // CHECK-ARM: "-target-feature" "+long-calls" -// CHECK-ARM: "-backend-option" "-arm-strict-align" -// CHECK-ARM-NOT: "-backend-option" "-arm-strict-align" +// CHECK-ARM: "-target-feature" "+strict-align" +// CHECK-ARM-NOT: "-target-feature" "+strict-align" // CHECK-ARM: "-fno-builtin" // CHECK-ARM: "-fno-rtti" // CHECK-ARM: "-fno-common" Index: test/Driver/arm-alignment.c =================================================================== --- test/Driver/arm-alignment.c +++ test/Driver/arm-alignment.c @@ -7,6 +7,18 @@ // RUN: %clang -target arm-none-gnueabi -mno-unaligned-access -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s +// RUN: %clang -target armv6-apple-darwin -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s + +// RUN: %clang -target armv6-netbsd-eabi -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s + +// RUN: %clang -target armv7-unknown-linux -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s + +// RUN: %clang -target armv7-unknown-nacl-gnueabihf -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s + // RUN: %clang -target aarch64-none-gnueabi -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s @@ -16,7 +28,7 @@ // RUN: %clang -target aarch64-none-gnueabi -mno-unaligned-access -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s -// CHECK-UNALIGNED-ARM: "-backend-option" "-arm-no-strict-align" +// CHECK-UNALIGNED-ARM-NOT: "-target-feature" "+strict-align" // CHECK-UNALIGNED-AARCH64: "-backend-option" "-aarch64-no-strict-align" @@ -32,6 +44,21 @@ // RUN: %clang -target arm-none-gnueabi -munaligned-access -mstrict-align -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s +// RUN: %clang -target arm-none-gnueabi -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s + +// RUN: %clang -target armv5-apple-darwin -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s + +// RUN: %clang -target armv5t-netbsd-eabi -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s + +// RUN: %clang -target armv6-unknown-linux -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s + +// RUN: %clang -target armv6-unknown-nacl-gnueabihf -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s + // RUN: %clang -target aarch64-none-gnueabi -mno-unaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s @@ -47,7 +74,7 @@ // RUN: %clang -target aarch64-none-gnueabi -mkernel -mno-unaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s -// CHECK-ALIGNED-ARM: "-backend-option" "-arm-strict-align" +// CHECK-ALIGNED-ARM: "-target-feature" "+strict-align" // CHECK-ALIGNED-AARCH64: "-backend-option" "-aarch64-strict-align" // Make sure that v6M cores always trigger the unsupported aligned accesses error