Skip to content

[ARM] __ARM_ARCH macro definition fix #81493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ X86 Support
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

- Fixed the incorrect definition of the __ARM_ARCH macro for architectures greater than or equal to v8.1.

Android Support
^^^^^^^^^^^^^^^

Expand Down
16 changes: 14 additions & 2 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,20 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,

// ACLE predefines. Many can only have one possible value on v8 AArch64.
Builder.defineMacro("__ARM_ACLE", "200");
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor()));

// __ARM_ARCH is defined as an integer value indicating the current ARM ISA.
// For ISAs up to and including v8, __ARM_ARCH is equal to the major version
// number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the
// minor version number, e.g. for ARM architecture ARMvX.Y:
// __ARM_ARCH = X * 100 + Y.
if (ArchInfo->Version.getMajor() == 8 && ArchInfo->Version.getMinor() == 0)
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor()));
else
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor() * 100 +
ArchInfo->Version.getMinor().value()));

Builder.defineMacro("__ARM_ARCH_PROFILE",
std::string("'") + (char)ArchInfo->Profile + "'");

Expand Down
14 changes: 11 additions & 3 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
SubArch = llvm::ARM::getSubArch(ArchKind);
ArchProfile = llvm::ARM::parseArchProfile(SubArch);
ArchVersion = llvm::ARM::parseArchVersion(SubArch);
ArchMinorVersion = llvm::ARM::parseArchMinorVersion(SubArch);

// cache CPU related strings
CPUAttr = getCPUAttr();
Expand Down Expand Up @@ -736,9 +737,16 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
if (!CPUAttr.empty())
Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");

// ACLE 6.4.1 ARM/Thumb instruction set architecture
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA.
// For ISAs up to and including v8, __ARM_ARCH is equal to the major version
// number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the
// minor version number, e.g. for ARM architecture ARMvX.Y:
// __ARM_ARCH = X * 100 + Y.
if (ArchVersion >= 9 || ArchMinorVersion != 0)
Builder.defineMacro("__ARM_ARCH",
Twine(ArchVersion * 100 + ArchMinorVersion));
else
Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));

if (ArchVersion >= 8) {
// ACLE 6.5.7 Crypto Extension
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T;
llvm::ARM::ProfileKind ArchProfile;
unsigned ArchVersion;
unsigned ArchMinorVersion;

LLVM_PREFERRED_TYPE(FPUMode)
unsigned FPU : 5;
Expand Down
34 changes: 17 additions & 17 deletions clang/test/Preprocessor/arm-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@

// Test whether predefines are as expected when targeting cortex-m55 (softfp FP ABI as default).
// RUN: %clang -target arm-eabi -mcpu=cortex-m55 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M55 %s
// M55: #define __ARM_ARCH 8
// M55: #define __ARM_ARCH 801
// M55: #define __ARM_ARCH_8_1M_MAIN__ 1
// M55: #define __ARM_ARCH_EXT_IDIV__ 1
// M55-NOT: __ARM_ARCH_ISA_ARM
Expand All @@ -764,7 +764,7 @@
// KRAIT-ALLOW-FP-INSTR:#define __ARM_VFPV4__ 1

// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M %s
// CHECK-V81M: #define __ARM_ARCH 8
// CHECK-V81M: #define __ARM_ARCH 801
// CHECK-V81M: #define __ARM_ARCH_8_1M_MAIN__ 1
// CHECK-V81M: #define __ARM_ARCH_ISA_THUMB 2
// CHECK-V81M: #define __ARM_ARCH_PROFILE 'M'
Expand Down Expand Up @@ -821,14 +821,14 @@
// CHECK-V8M-CDE-MASK2: #define __ARM_FEATURE_CDE_COPROC 0xff

// RUN: %clang -target armv8.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81A %s
// CHECK-V81A: #define __ARM_ARCH 8
// CHECK-V81A: #define __ARM_ARCH 801
// CHECK-V81A: #define __ARM_ARCH_8_1A__ 1
// CHECK-V81A: #define __ARM_ARCH_PROFILE 'A'
// CHECK-V81A: #define __ARM_FEATURE_QRDMX 1
// CHECK-V81A: #define __ARM_FP 0xe

// RUN: %clang -target armv8.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V82A %s
// CHECK-V82A: #define __ARM_ARCH 8
// CHECK-V82A: #define __ARM_ARCH 802
// CHECK-V82A: #define __ARM_ARCH_8_2A__ 1
// CHECK-V82A: #define __ARM_ARCH_PROFILE 'A'
// CHECK-V82A: #define __ARM_FEATURE_QRDMX 1
Expand All @@ -838,67 +838,67 @@
// CHECK-DRIVERKIT-NOT: #define __ARM_PCS_VFP 1

// RUN: %clang -target armv8.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V83A %s
// CHECK-V83A: #define __ARM_ARCH 8
// CHECK-V83A: #define __ARM_ARCH 803
// CHECK-V83A: #define __ARM_ARCH_8_3A__ 1
// CHECK-V83A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V84A %s
// CHECK-V84A: #define __ARM_ARCH 8
// CHECK-V84A: #define __ARM_ARCH 804
// CHECK-V84A: #define __ARM_ARCH_8_4A__ 1
// CHECK-V84A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V85A %s
// CHECK-V85A: #define __ARM_ARCH 8
// CHECK-V85A: #define __ARM_ARCH 805
// CHECK-V85A: #define __ARM_ARCH_8_5A__ 1
// CHECK-V85A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.6a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V86A %s
// CHECK-V86A: #define __ARM_ARCH 8
// CHECK-V86A: #define __ARM_ARCH 806
// CHECK-V86A: #define __ARM_ARCH_8_6A__ 1
// CHECK-V86A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.7a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V87A %s
// CHECK-V87A: #define __ARM_ARCH 8
// CHECK-V87A: #define __ARM_ARCH 807
// CHECK-V87A: #define __ARM_ARCH_8_7A__ 1
// CHECK-V87A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.8a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V88A %s
// CHECK-V88A: #define __ARM_ARCH 8
// CHECK-V88A: #define __ARM_ARCH 808
// CHECK-V88A: #define __ARM_ARCH_8_8A__ 1
// CHECK-V88A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V89A %s
// CHECK-V89A: #define __ARM_ARCH 8
// CHECK-V89A: #define __ARM_ARCH 809
// CHECK-V89A: #define __ARM_ARCH_8_9A__ 1
// CHECK-V89A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V9A %s
// CHECK-V9A: #define __ARM_ARCH 9
// CHECK-V9A: #define __ARM_ARCH 900
// CHECK-V9A: #define __ARM_ARCH_9A__ 1
// CHECK-V9A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V91A %s
// CHECK-V91A: #define __ARM_ARCH 9
// CHECK-V91A: #define __ARM_ARCH 901
// CHECK-V91A: #define __ARM_ARCH_9_1A__ 1
// CHECK-V91A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V92A %s
// CHECK-V92A: #define __ARM_ARCH 9
// CHECK-V92A: #define __ARM_ARCH 902
// CHECK-V92A: #define __ARM_ARCH_9_2A__ 1
// CHECK-V92A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V93A %s
// CHECK-V93A: #define __ARM_ARCH 9
// CHECK-V93A: #define __ARM_ARCH 903
// CHECK-V93A: #define __ARM_ARCH_9_3A__ 1
// CHECK-V93A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V94A %s
// CHECK-V94A: #define __ARM_ARCH 9
// CHECK-V94A: #define __ARM_ARCH 904
// CHECK-V94A: #define __ARM_ARCH_9_4A__ 1
// CHECK-V94A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V95A %s
// CHECK-V95A: #define __ARM_ARCH 9
// CHECK-V95A: #define __ARM_ARCH 905
// CHECK-V95A: #define __ARM_ARCH_9_5A__ 1
// CHECK-V95A: #define __ARM_ARCH_PROFILE 'A'

Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/TargetParser/ARMTargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ uint64_t parseArchExt(StringRef ArchExt);
ArchKind parseCPUArch(StringRef CPU);
ProfileKind parseArchProfile(StringRef Arch);
unsigned parseArchVersion(StringRef Arch);
unsigned parseArchMinorVersion(StringRef Arch);

void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
Expand Down
58 changes: 58 additions & 0 deletions llvm/lib/TargetParser/ARMTargetParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,64 @@ unsigned ARM::parseArchVersion(StringRef Arch) {
llvm_unreachable("Unhandled architecture");
}

unsigned ARM::parseArchMinorVersion(StringRef Arch) {
Arch = getCanonicalArchName(Arch);
switch (parseArch(Arch)) {
case ArchKind::ARMV4:
case ArchKind::ARMV4T:
case ArchKind::ARMV5T:
case ArchKind::ARMV5TE:
case ArchKind::IWMMXT:
case ArchKind::IWMMXT2:
case ArchKind::XSCALE:
case ArchKind::ARMV5TEJ:
case ArchKind::ARMV6:
case ArchKind::ARMV6K:
case ArchKind::ARMV6T2:
case ArchKind::ARMV6KZ:
case ArchKind::ARMV6M:
case ArchKind::ARMV7A:
case ArchKind::ARMV7VE:
case ArchKind::ARMV7R:
case ArchKind::ARMV7M:
case ArchKind::ARMV7S:
case ArchKind::ARMV7EM:
case ArchKind::ARMV7K:
case ArchKind::ARMV8A:
case ArchKind::ARMV8R:
case ArchKind::ARMV8MBaseline:
case ArchKind::ARMV8MMainline:
case ArchKind::ARMV9A:
case ArchKind::INVALID:
return 0;
case ArchKind::ARMV8_1A:
case ArchKind::ARMV8_1MMainline:
case ArchKind::ARMV9_1A:
return 1;
case ArchKind::ARMV8_2A:
case ArchKind::ARMV9_2A:
return 2;
case ArchKind::ARMV8_3A:
case ArchKind::ARMV9_3A:
return 3;
case ArchKind::ARMV8_4A:
case ArchKind::ARMV9_4A:
return 4;
case ArchKind::ARMV8_5A:
case ArchKind::ARMV9_5A:
return 5;
case ArchKind::ARMV8_6A:
return 6;
case ArchKind::ARMV8_7A:
return 7;
case ArchKind::ARMV8_8A:
return 8;
case ArchKind::ARMV8_9A:
return 9;
}
llvm_unreachable("Unhandled architecture");
}

static ARM::ProfileKind getProfileKind(ARM::ArchKind AK) {
switch (AK) {
case ARM::ArchKind::ARMV6M:
Expand Down
8 changes: 8 additions & 0 deletions llvm/unittests/TargetParser/TargetParserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,14 @@ TEST(TargetParserTest, ARMparseArchVersion) {
EXPECT_EQ(5u, ARM::parseArchVersion(ARMArch[i]));
}

TEST(TargetParserTest, ARMparseArchMinorVersion) {
for (unsigned i = 0; i < std::size(ARMArch); i++)
if (((std::string)ARMArch[i]).find(".") == 5)
EXPECT_EQ((ARMArch[i][6] - 48u), ARM::parseArchMinorVersion(ARMArch[i]));
else
EXPECT_EQ(0u, ARM::parseArchMinorVersion(ARMArch[i]));
}

TEST(TargetParserTest, getARMCPUForArch) {
// Platform specific defaults.
{
Expand Down