Skip to content

[clang][aarch64] Add support for the MSVC qualifiers __ptr32, __ptr64, __sptr, __uptr for AArch64 #111879

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 1 commit into from
Oct 15, 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
22 changes: 16 additions & 6 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
IntMaxType = SignedLong;
}

AddrSpaceMap = &ARM64AddrSpaceMap;

// All AArch64 implementations support ARMv8 FP, which makes half a legal type.
HasLegalHalfType = true;
HalfArgsAndReturns = true;
Expand Down Expand Up @@ -1533,11 +1535,16 @@ AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
void AArch64leTargetInfo::setDataLayout() {
if (getTriple().isOSBinFormatMachO()) {
if(getTriple().isArch32Bit())
resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32", "_");
resetDataLayout("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-"
"i128:128-n32:64-S128-Fn32",
"_");
else
resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128-Fn32", "_");
resetDataLayout("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-"
"n32:64-S128-Fn32",
"_");
} else
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32");
resetDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-"
"i64:64-i128:128-n32:64-S128-Fn32");
}

void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
Expand All @@ -1560,7 +1567,8 @@ void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,

void AArch64beTargetInfo::setDataLayout() {
assert(!getTriple().isOSBinFormatMachO());
resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32");
resetDataLayout("E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-"
"i64:64-i128:128-n32:64-S128-Fn32");
}

WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
Expand All @@ -1583,8 +1591,10 @@ WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,

void WindowsARM64TargetInfo::setDataLayout() {
resetDataLayout(Triple.isOSBinFormatMachO()
? "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32",
? "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:"
"128-n32:64-S128-Fn32"
: "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-"
"i64:64-i128:128-n32:64-S128-Fn32",
Triple.isOSBinFormatMachO() ? "_" : "");
}

Expand Down
40 changes: 40 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@
namespace clang {
namespace targets {

enum AArch64AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 };

static const unsigned ARM64AddrSpaceMap[] = {
0, // Default
0, // opencl_global
0, // opencl_local
0, // opencl_constant
0, // opencl_private
0, // opencl_generic
0, // opencl_global_device
0, // opencl_global_host
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
0, // sycl_global
0, // sycl_global_device
0, // sycl_global_host
0, // sycl_local
0, // sycl_private
static_cast<unsigned>(AArch64AddrSpace::ptr32_sptr),
static_cast<unsigned>(AArch64AddrSpace::ptr32_uptr),
static_cast<unsigned>(AArch64AddrSpace::ptr64),
0, // hlsl_groupshared
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
};

class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
virtual void setDataLayout() = 0;
static const TargetInfo::GCCRegAlias GCCRegAliases[];
Expand Down Expand Up @@ -207,6 +235,18 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {

bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
bool &HasSizeMismatch) const override;

uint64_t getPointerWidthV(LangAS AddrSpace) const override {
if (AddrSpace == LangAS::ptr32_sptr || AddrSpace == LangAS::ptr32_uptr)
return 32;
if (AddrSpace == LangAS::ptr64)
return 64;
return PointerWidth;
}

uint64_t getPointerAlignV(LangAS AddrSpace) const override {
return getPointerWidthV(AddrSpace);
}
};

class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/aarch64-type-sizes.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple aarch64_be-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s
// char by definition has size 1

// CHECK: target datalayout = "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
// CHECK: target datalayout = "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"

int check_short(void) {
return sizeof(short);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/coff-aarch64-type-sizes.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple aarch64-windows -emit-llvm -w -o - %s | FileCheck %s

// CHECK: target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
// CHECK: target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
// CHECK: target triple = "aarch64-unknown-windows-msvc"

int check_short(void) {
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CodeGen/ms-mixed-ptr-sizes.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 < %s | FileCheck %s --check-prefixes=X64,ALL
// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 < %s | FileCheck %s --check-prefixes=X86,ALL
// RUN: %clang_cc1 -triple aarch64-windows-msvc -fms-extensions -emit-llvm -O2 < %s | FileCheck %s --check-prefixes=AARCH64,ALL
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need some tests in the backend? I guess most things likely work because we already did most of the work for the aarch64_32 ABI, but I'd like to see some tests that the basics work (load/store/arguments/return values).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend hasn't been implemented yet - I'll have a follow up PR with the changes and tests.


struct Foo {
int * __ptr32 p32;
Expand All @@ -9,41 +10,51 @@ void use_foo(struct Foo *f);
void test_sign_ext(struct Foo *f, int * __ptr32 __sptr i) {
// X64-LABEL: define dso_local void @test_sign_ext({{.*}}ptr addrspace(270) noundef %i)
// X86-LABEL: define dso_local void @test_sign_ext(ptr noundef %f, ptr noundef %i)
// AARCH64-LABEL: define dso_local void @test_sign_ext({{.*}}ptr addrspace(270) noundef %i) local_unnamed_addr #0
// X64: %{{.+}} = addrspacecast ptr addrspace(270) %i to ptr
// X86: %{{.+}} = addrspacecast ptr %i to ptr addrspace(272)
// AARCH64: %{{.+}} = addrspacecast ptr addrspace(270) %i to ptr
f->p64 = i;
use_foo(f);
}
void test_zero_ext(struct Foo *f, int * __ptr32 __uptr i) {
// X64-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i)
// X86-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i)
// AARCH64-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i) local_unnamed_addr #0
// X64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr
// X86: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr addrspace(272)
// AARCH64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr
f->p64 = i;
use_foo(f);
}
void test_trunc(struct Foo *f, int * __ptr64 i) {
// X64-LABEL: define dso_local void @test_trunc(ptr noundef %f, ptr noundef %i)
// X86-LABEL: define dso_local void @test_trunc({{.*}}ptr addrspace(272) noundef %i)
// AARCH64-LABEL: define dso_local void @test_trunc(ptr noundef %f, ptr noundef %i) local_unnamed_addr #0
// X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(270)
// X86: %{{.+}} = addrspacecast ptr addrspace(272) %i to ptr
// AARCH64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(270)
f->p32 = i;
use_foo(f);
}
void test_noop(struct Foo *f, int * __ptr32 i) {
// X64-LABEL: define dso_local void @test_noop({{.*}}ptr addrspace(270) noundef %i)
// X86-LABEL: define dso_local void @test_noop({{.*}}ptr noundef %i)
// AARCH64-LABEL: define dso_local void @test_noop({{.*}}ptr addrspace(270) noundef %i) local_unnamed_addr #0
// X64-NOT: addrspacecast
// X86-NOT: addrspacecast
// AARCH64-NOT: addrspacecast
f->p32 = i;
use_foo(f);
}

void test_other(struct Foo *f, __attribute__((address_space(10))) int *i) {
// X64-LABEL: define dso_local void @test_other({{.*}}ptr addrspace(10) noundef %i)
// X86-LABEL: define dso_local void @test_other({{.*}}ptr addrspace(10) noundef %i)
// AARCH64-LABEL: define dso_local void @test_other({{.*}}ptr addrspace(10) noundef %i) local_unnamed_addr #0
// X64: %{{.+}} = addrspacecast ptr addrspace(10) %i to ptr addrspace(270)
// X86: %{{.+}} = addrspacecast ptr addrspace(10) %i to ptr
// AARCH64: %{{.+}} = addrspacecast ptr addrspace(10) %i to ptr addrspace(270)
f->p32 = (int * __ptr32)i;
use_foo(f);
}
Expand All @@ -54,6 +65,8 @@ int test_compare1(int *__ptr32 __uptr i, int *__ptr64 j) {
// X64: %cmp = icmp eq ptr addrspace(271) %i, %{{.+}}
// X86: %{{.+}} = addrspacecast ptr addrspace(272) %j to ptr addrspace(271)
// X86: %cmp = icmp eq ptr addrspace(271) %i, %{{.+}}
// AARCH64: %{{.+}} = addrspacecast ptr %j to ptr addrspace(271)
// AARCH64: %cmp = icmp eq ptr addrspace(271) %i, %{{.+}}
return (i == j);
}

Expand All @@ -63,6 +76,8 @@ int test_compare2(int *__ptr32 __sptr i, int *__ptr64 j) {
// X64: %cmp = icmp eq ptr addrspace(270) %i, %{{.+}}
// X86: %{{.+}} = addrspacecast ptr addrspace(272) %j to ptr
// X86: %cmp = icmp eq ptr %i, %{{.+}}
// AARCH64: %{{.+}} = addrspacecast ptr %j to ptr addrspace(270)
// AARCH64: %cmp = icmp eq ptr addrspace(270) %i, %{{.+}}
return (i == j);
}

Expand All @@ -72,6 +87,8 @@ int test_compare3(int *__ptr32 __uptr i, int *__ptr64 j) {
// X64: %cmp = icmp eq ptr %j, %{{.+}}
// X86: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr addrspace(272)
// X86: %cmp = icmp eq ptr addrspace(272) %j, %{{.+}}
// AARCH64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr
// AARCH64: %cmp = icmp eq ptr %j, %{{.+}}
return (j == i);
}

Expand All @@ -81,5 +98,7 @@ int test_compare4(int *__ptr32 __sptr i, int *__ptr64 j) {
// X64: %cmp = icmp eq ptr %j, %{{.+}}
// X86: %{{.+}} = addrspacecast ptr %i to ptr addrspace(272)
// X86: %cmp = icmp eq ptr addrspace(272) %j, %{{.+}}
// AARCH64: %{{.+}} = addrspacecast ptr addrspace(270) %i to ptr
// AARCH64: %cmp = icmp eq ptr %j, %{{.+}}
return (j == i);
}
6 changes: 3 additions & 3 deletions clang/test/CodeGen/target-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,15 @@

// RUN: %clang_cc1 -triple arm64-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64
// AARCH64: target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
// AARCH64: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"

// RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64-ILP32
// AARCH64-ILP32: target datalayout = "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32"
// AARCH64-ILP32: target datalayout = "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"

// RUN: %clang_cc1 -triple arm64-pc-win32-macho -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64-WIN32-MACHO
// AARCH64-WIN32-MACHO: target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
// AARCH64-WIN32-MACHO: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"

// RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=THUMB
Expand Down
23 changes: 14 additions & 9 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5565,11 +5565,24 @@ std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) {
return Res;
}

auto AddPtr32Ptr64AddrSpaces = [&DL, &Res]() {
// If the datalayout matches the expected format, add pointer size address
// spaces to the datalayout.
StringRef AddrSpaces{"-p270:32:32-p271:32:32-p272:64:64"};
if (!DL.contains(AddrSpaces)) {
SmallVector<StringRef, 4> Groups;
Regex R("^([Ee]-m:[a-z](-p:32:32)?)(-.*)$");
if (R.match(Res, &Groups))
Res = (Groups[1] + AddrSpaces + Groups[3]).str();
}
};

// AArch64 data layout upgrades.
if (T.isAArch64()) {
// Add "-Fn32"
if (!DL.empty() && !DL.contains("-Fn32"))
Res.append("-Fn32");
AddPtr32Ptr64AddrSpaces();
return Res;
}

Expand All @@ -5588,15 +5601,7 @@ std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) {
if (!T.isX86())
return Res;

// If the datalayout matches the expected format, add pointer size address
// spaces to the datalayout.
std::string AddrSpaces = "-p270:32:32-p271:32:32-p272:64:64";
if (StringRef Ref = Res; !Ref.contains(AddrSpaces)) {
SmallVector<StringRef, 4> Groups;
Regex R("(e-m:[a-z](-p:32:32)?)(-[if]64:.*$)");
if (R.match(Res, &Groups))
Res = (Groups[1] + AddrSpaces + Groups[3]).str();
}
AddPtr32Ptr64AddrSpaces();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely recall that the autoupgrade was somewhat painful for x86 usage, but I don't have anything specific, and we're just doing exactly the same stuff. @efriedma-quic are there any lessons learned there that we should keep in mind?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there isn't any existing code using the new address-spaces, autoupgrading like this should work smoothly, I think? Need to make sure the autoupgraded string matches the new string, but otherwise should be fine. (I remember last time we made major changes for x86, the 128-bit integer alignment change, it was sort of tricky, but the issue mostly wasn't the layout string itself.)


Having a dedicated address-space for __ptr64 is a little strange, but I guess if that's what we did on x86, there isn't really a reason to deviate.


// i128 values need to be 16-byte-aligned. LLVM already called into libgcc
// for i128 operations prior to this being reflected in the data layout, and
Expand Down
12 changes: 8 additions & 4 deletions llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,15 +290,19 @@ static std::string computeDataLayout(const Triple &TT,
bool LittleEndian) {
if (TT.isOSBinFormatMachO()) {
if (TT.getArch() == Triple::aarch64_32)
return "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32";
return "e-m:o-i64:64-i128:128-n32:64-S128-Fn32";
return "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-"
"n32:64-S128-Fn32";
return "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-"
"Fn32";
}
if (TT.isOSBinFormatCOFF())
return "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32";
return "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:"
"128-n32:64-S128-Fn32";
std::string Endian = LittleEndian ? "e" : "E";
std::string Ptr32 = TT.getEnvironment() == Triple::GNUILP32 ? "-p:32:32" : "";
return Endian + "-m:e" + Ptr32 +
"-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32";
"-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-"
"n32:64-S128-Fn32";
}

static StringRef computeDefaultCPU(const Triple &TT, StringRef CPU) {
Expand Down
13 changes: 10 additions & 3 deletions llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ TEST(DataLayoutUpgradeTest, ValidDataLayoutUpgrade) {
"e-m:o-i64:64-f80:128-n8:16:32:64-S128", "x86_64-apple-macosx");
std::string DL4 =
UpgradeDataLayoutString("e-m:o-i64:64-i128:128-n32:64-S128", "aarch64--");
std::string DL5 = UpgradeDataLayoutString(
"e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", "aarch64--");
EXPECT_EQ(DL1,
"e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128"
"-f80:128-n8:16:32:64-S128");
Expand All @@ -31,7 +33,10 @@ TEST(DataLayoutUpgradeTest, ValidDataLayoutUpgrade) {
"-f80:128-n8:16:32-S32");
EXPECT_EQ(DL3, "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:"
"128-n8:16:32:64-S128");
EXPECT_EQ(DL4, "e-m:o-i64:64-i128:128-n32:64-S128-Fn32");
EXPECT_EQ(DL4, "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:"
"64-S128-Fn32");
EXPECT_EQ(DL5, "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:"
"64-i128:128-n32:64-S128-Fn32");

// Check that AMDGPU targets add -G1 if it's not present.
EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32", "r600"), "e-p:32:32-G1");
Expand Down Expand Up @@ -94,14 +99,16 @@ TEST(DataLayoutUpgradeTest, NoDataLayoutUpgrade) {
std::string DL2 = UpgradeDataLayoutString("e-m:e-i64:64-n32:64",
"powerpc64le-unknown-linux-gnu");
std::string DL3 = UpgradeDataLayoutString(
"e-m:o-i64:64-i128:128-n32:64-S128-Fn32", "aarch64--");
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32",
"aarch64--");
EXPECT_EQ(
DL1,
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128"
"-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64"
"-f80:128:128-n8:16:32:64-S128");
EXPECT_EQ(DL2, "e-m:e-i64:64-n32:64");
EXPECT_EQ(DL3, "e-m:o-i64:64-i128:128-n32:64-S128-Fn32");
EXPECT_EQ(DL3, "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:"
"64-S128-Fn32");

// Check that AMDGPU targets don't add -G1 if there is already a -G flag.
EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32-G2", "r600"), "e-p:32:32-G2");
Expand Down
Loading