-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[DataLayout] Introduce DataLayout::getPointerAddressSize(AS) #137412
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3147,14 +3147,27 @@ as follows: | |
``A<address space>`` | ||
Specifies the address space of objects created by '``alloca``'. | ||
Defaults to the default address space of 0. | ||
``p[n]:<size>:<abi>[:<pref>][:<idx>]`` | ||
This specifies the *size* of a pointer and its ``<abi>`` and | ||
``<pref>``\erred alignments for address space ``n``. | ||
The fourth parameter ``<idx>`` is the size of the | ||
index that used for address calculation, which must be less than or equal | ||
to the pointer size. If not | ||
specified, the default index size is equal to the pointer size. All sizes | ||
are in bits. The address space, ``n``, is optional, and if not specified, | ||
``p[n]:<size>:<abi>[:<pref>[:<idx>[:<addr>]]]`` | ||
This specifies the properties of a pointer in address space ``n``. | ||
The ``<size>`` parameter specifies the size of the bitwise representation. | ||
For :ref:`non-integral pointers <nointptrtype>` the representation size may | ||
be larger than the address width of the underlying address space (e.g. to | ||
accommodate additional metadata). | ||
The alignment requirements are specified via the ``<abi>`` and | ||
``<pref>``\erred alignments parameters. | ||
The fourth parameter ``<idx>`` is the size of the index that used for | ||
address calculations such as :ref:`getelementptr <i_getelementptr>`. | ||
It must be less than or equal to the pointer size. If not specified, the | ||
default index size is equal to the pointer size. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be useful to explicitly document and enforce a constraint of the form There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good - If we ever end up supporting a target where that does not hold we can always adjust it again. E.g. some hypothetical target where addresses are 64 bits but the pointer representation is a 32-bit offset relative to some base address. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... Isn't that the AMDGPU stack pointer in some of its implementations, even though you're not supposed to think of it like that? (Opinions have varied over the generations on if it's "32-bit offset from buffer resource the compiler creates" to "32-bit offset from implicit scratch base" and so on)? Though I'd need more consensus from AMDGPU forks on if we ever want to expose the lie There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I imagine that within the stack address space you have 32-bit range and the 32-bit offset from the fixed base uniquely identifies the underlying address? I'm not sure if there is any advantage in exposing the 48-bit (?) final address, but if you think there is we can definitely relax this restriction. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think there's much virtue to it, I'm just asking annoying questions |
||
The fifth parameter ``<addr>`` specifies the width of addresses in this | ||
address space. If not specified, the default address size is equal to the | ||
index size. The address size may be wider than the index size as it could be | ||
calculated relative to a base address. For example AMDGPU buffer fat | ||
pointers use a 48-bit address range, but only allow for 32 bits of indexing. | ||
All sizes are in bits. | ||
The following relationship is assumed to be true: | ||
``representation size >= address size >= index size``. | ||
The address space, ``n``, is optional, and if not specified, | ||
denotes the default address space 0. The value of ``n`` must be | ||
in the range [1,2^24). | ||
``i<size>:<abi>[:<pref>]`` | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -312,12 +312,12 @@ TEST(DataLayout, ParsePointerSpec) { | |||||
"p16777215:32:32:64:8", "p16777215:16777215:32768:32768:16777215"}) | ||||||
EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); | ||||||
|
||||||
for (StringRef Str : | ||||||
{"p", "p0", "p:32", "p0:32", "p:32:32:32:32:32", "p0:32:32:32:32:32"}) | ||||||
for (StringRef Str : {"p", "p0", "p:32", "p0:32", "p:32:32:32:32:32:32", | ||||||
"p0:32:32:32:32:32:32"}) | ||||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse(Str), | ||||||
FailedWithMessage("malformed specification, must be of the form " | ||||||
"\"p[<n>]:<size>:<abi>[:<pref>[:<idx>]]\"")); | ||||||
"\"p[<n>]:<size>:<abi>[:<pref>[:<idx>[:<addr>]]]\"")); | ||||||
arichardson marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
// address space | ||||||
for (StringRef Str : {"p0x0:32:32", "px:32:32:32", "p16777216:32:32:32:32"}) | ||||||
|
@@ -401,6 +401,31 @@ TEST(DataLayout, ParsePointerSpec) { | |||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse(Str), | ||||||
FailedWithMessage("index size cannot be larger than the pointer size")); | ||||||
|
||||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse("p:64:64:64:48:32"), | ||||||
FailedWithMessage("index size cannot be larger than the address size")); | ||||||
|
||||||
// address size | ||||||
for (StringRef Str : {"p:64:32:32:64:", "p0:64:32:32:64:"}) | ||||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse(Str), | ||||||
FailedWithMessage("address size component cannot be empty")); | ||||||
|
||||||
// Note: in the future we might allow 0 for address size to indicate pointers | ||||||
// that do not have a meaning full address (e.g. relocatable GC pointers). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
for (StringRef Str : | ||||||
{"p:32:32:32:32:0", "p0:32:32:32:32:0x20", "p42:32:32:32:32:16777216"}) | ||||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse(Str), | ||||||
FailedWithMessage("address size must be a non-zero 24-bit integer")); | ||||||
|
||||||
for (StringRef Str : | ||||||
{"p:16:16:16:16:17", "p0:32:64:64:32:64", "p42:16:64:64:16:32"}) | ||||||
EXPECT_THAT_EXPECTED( | ||||||
DataLayout::parse(Str), | ||||||
FailedWithMessage( | ||||||
"address size cannot be larger than the pointer size")); | ||||||
} | ||||||
|
||||||
TEST(DataLayoutTest, ParseNativeIntegersSpec) { | ||||||
|
@@ -523,6 +548,40 @@ TEST(DataLayout, GetIndexSize) { | |||||
} | ||||||
} | ||||||
|
||||||
TEST(DataLayout, GetAddressSizeInBits) { | ||||||
// Address size defaults to index size | ||||||
std::tuple<StringRef, unsigned, unsigned, unsigned> Cases[] = { | ||||||
{"", 64, 64, 64}, | ||||||
{"p:16:32", 16, 16, 16}, | ||||||
{"p0:32:64", 32, 32, 32}, | ||||||
{"p1:16:32:32:10", 64, 10, 64}, | ||||||
{"p1:31:32:64:10:20-p2:17:16:16:15:15", 64, 20, 15}, | ||||||
}; | ||||||
for (auto [Layout, V0, V1, V2] : Cases) { | ||||||
DataLayout DL = cantFail(DataLayout::parse(Layout)); | ||||||
EXPECT_EQ(DL.getPointerAddressSizeInBits(0), V0) << Layout; | ||||||
EXPECT_EQ(DL.getPointerAddressSizeInBits(1), V1) << Layout; | ||||||
EXPECT_EQ(DL.getPointerAddressSizeInBits(2), V2) << Layout; | ||||||
} | ||||||
} | ||||||
|
||||||
TEST(DataLayout, GetAddressSize) { | ||||||
// Address size defaults to index size | ||||||
std::tuple<StringRef, unsigned, unsigned, unsigned> Cases[] = { | ||||||
{"", 8, 8, 8}, | ||||||
{"p:16:32", 2, 2, 2}, | ||||||
{"p0:27:64", 4, 4, 4}, | ||||||
{"p1:19:32:64:2:5", 8, 1, 8}, | ||||||
{"p1:33:32:64:10:23-p2:21:8:16:10:13", 8, 3, 2}, | ||||||
}; | ||||||
for (auto [Layout, V0, V1, V2] : Cases) { | ||||||
DataLayout DL = cantFail(DataLayout::parse(Layout)); | ||||||
EXPECT_EQ(DL.getPointerAddressSize(0), V0) << Layout; | ||||||
EXPECT_EQ(DL.getPointerAddressSize(1), V1) << Layout; | ||||||
EXPECT_EQ(DL.getPointerAddressSize(2), V2) << Layout; | ||||||
} | ||||||
} | ||||||
|
||||||
TEST(DataLayout, GetPointerABIAlignment) { | ||||||
std::tuple<StringRef, unsigned, unsigned, unsigned> Cases[] = { | ||||||
{"", 8, 8, 8}, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to get too bikeshed-y on this, but I find the pointer size vs address size terminology confusing at a glance, and I worry that we'll end up with a lot of pieces in the code base inadvertently using the wrong one.
If you feel strongly that this is the best terminology, I won't hold it up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this could be confusing but I haven't been able to come up with a better name. Maybe pointer size should be "representation size"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally used pointer range in CHERI LLVM, but I wasn't happy with it because it's actually log2(pointer range). Address size is more correct, at least.