Skip to content
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

Experiment: Make size_t/ptrdiff_t match pointer size on 8/16 bit architectures #4466

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kinke
Copy link
Member

@kinke kinke commented Aug 5, 2023

It's currently at least 32 bits, controlled from the frontend.

Motivated by https://forum.dlang.org/thread/ofbvqasfvxylbxxpwhja@forum.dlang.org. FYI @dukc. My thinking was that if we kept the min 32-bit size_t, it'd also mean that a D slice layout would be an odd { uint length; T* ptr; }. And a 32-bit size_t arg might not be passable in a register etc.

@@ -2765,12 +2765,12 @@ class Exception : Throwable
* This constructor does not automatically throw the newly-created
* Exception; the $(D throw) expression should be used for that purpose.
*/
@nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
@nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = cast(size_t) __LINE__, Throwable nextInChain = null)
Copy link
Member Author

Choose a reason for hiding this comment

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

__LINE__ expressions are of type int.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh well, the cast seems to alter the __LINE__ behavior, not using the call site's line anymore, but the line 2768 here in object.d. - I've had to add it to make object.d importable without errors for the added testcase on 16-bit AVR.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is exactly why I'm a suspicious of 16-bit size_ts/ptrdiff_ts being practical. Existing code is probably going to need annoying adaptations almost everywhere, since D code rarely expects to deal with 16-bit size_ts.

@kinke
Copy link
Member Author

kinke commented Aug 5, 2023

FWIW, the current problem described in the forum post is that the frontend has this lower bound, but in various codegen sites, we expect size_t to match the pointer size, based on:

ldc/gen/tollvm.cpp

Lines 334 to 349 in cf32bac

LLIntegerType *DtoSize_t() {
// the type of size_t does not change once set
static LLIntegerType *t = nullptr;
if (t == nullptr) {
if (target.ptrsize == 8) {
t = LLType::getInt64Ty(gIR->context());
} else if (target.ptrsize == 4) {
t = LLType::getInt32Ty(gIR->context());
} else if (target.ptrsize == 2) {
t = LLType::getInt16Ty(gIR->context());
} else {
llvm_unreachable("Unsupported size_t width");
}
}
return t;
}

@dukc
Copy link
Contributor

dukc commented Aug 7, 2023

My thinking was that if we kept the min 32-bit size_t, it'd also mean that a D slice layout would be an odd { uint length; T* ptr; }. And a 32-bit size_t arg might not be passable in a register etc.

Sure - but that tends to be the case with D code anyway on under 32 bits. bytes and shorts get promoted to ints at every corner, so you have to be constantly casting them back if you want optimised code. I don't think 32-bit size_t is different in that regard. Also, since

auto arr = [1,2,3];
auto ptr = &arr.length;

complains "arr.length is not an lvalue and cannot be modified", it means array length can be pointer-sized under the hood, only promoted to size_t on access.

But either way, I'm happy. If size_t is always pointer-sized, it is by the book. If it is always 32 bits or more, it pairs better with integer promotion rules. Choose the way that is easiest to get working and right.

@kinke
Copy link
Member Author

kinke commented Aug 7, 2023

I've quickly checked godbolt for clang behavior: https://cpp.godbolt.org/z/4vKq93d4n

=> int is 16-bit for AVR, so no promotion to 32-bit.

@JohanEngelen
Copy link
Member

@dukc I propose you write a DIP - or something similar - about how 8/16bit D should work, it's much easier to implement things when a decision has been made and that is best done with an overview of all the issues, so an overall design can be made that is coherent for 8/16 bit. Already creating a table of all the issues that one encounters, and solutions in a column next to it (keep empty if you don't have a proposal, and then others can try to fill in those gaps).
Thanks for the effort!

@dukc
Copy link
Contributor

dukc commented Aug 8, 2023

've quickly checked godbolt for clang behavior: https://cpp.godbolt.org/z/4vKq93d4n

=> int is 16-bit for AVR, so no promotion to 32-bit.

This is C++ though, which allows varying int sizes. In D we expect no variance in int sizes, except maybe for those ancient 12/18/36-bit machines if someone were crazy enough to implement a D backend for one. Meaning int probably has to remain 32-bit. Which also means size_t probably wants to follow. Otherwise the compiler is going to complain from things like malloc(array.length + 1) or cString[cString.strlen - 1].

@dukc
Copy link
Contributor

dukc commented Aug 8, 2023

I propose you write a DIP - or something similar - about how 8/16bit D should work

I'm thinking about writing another forum post for that, trying to get an opinion from Walter. I'll try explaining the matter thoroughly. If they say please write a DIP, then maybe.

@kinke
Copy link
Member Author

kinke commented Aug 8, 2023

FWIW, I think we'd need to change the integer promotion rules of D, to work just like C++ does ('promoting to the smaller of int/ptrdiff_t') for these architectures. A 32-bit size_t is just ugly, breaks C[++] interop when using size_t for the C declarations etc. etc. (there might likely be sites in druntime/user libs expecting a slice/delegate to be 2 pointers large...).

@dukc
Copy link
Contributor

dukc commented Aug 8, 2023

Limiting promotion alone doesn't help that much, because literals are still ints. What could work to solve at least these two cases is Adam's proposal for changing value range propagation rules. It doesn't seem Walter is receptive though so we'll probably have to settle for something else.

@JohanEngelen
Copy link
Member

I propose you write a DIP - or something similar - about how 8/16bit D should work

I'm thinking about writing another forum post for that, trying to get an opinion from Walter. I'll try explaining the matter thoroughly. If they say please write a DIP, then maybe.

Please don't write all details in a forum post. It will get lost instantly and there is no way to make edits. It does not have to be a DIP. Please use something like github gist, or some other editable format. Such that it can be improved in-place.

@kinke
Copy link
Member Author

kinke commented Aug 8, 2023

Limiting promotion alone doesn't help that much, because literals are still ints. What could work to solve at least these two cases is Adam's proposal for changing value range propagation rules. It doesn't seem Walter is receptive though so we'll probably have to settle for something else.

Good points! Hmm, obviously always more complex than anticipated. If a nice generic solution like Adam's apparent one was rejected, I guess it'd all come down to estimating how long these pre-32-bit architectures are going to be relevant before becoming ancient history, and whether it makes sense to complicate the language to accommodate for them, now in 2023+. As DMD's backend will probably never target any interesting 16-bit target, Walter's interest might not really be high either.

@dukc
Copy link
Contributor

dukc commented Aug 19, 2023

Got it finally done. Here: https://forum.dlang.org/post/hlcvmxylwzamfdtlknue@forum.dlang.org

I guess it'd all come down to estimating how long these pre-32-bit architectures are going to be relevant before becoming ancient history

Personally I wouldn't assume they are heading for irrelevance. Maybe, just maybe, on hand-solderable microchips. But every time in history when limited-memory environments have became irrelevant in their past domain, they have just resurfaced on smaller and cheaper computers. Before they disappeared from minicomputers, they appeared on desktops. Before they disappeared from desktops, they appeared on handheld devices and so on. When/If 16-bit microchips of normal size cease to exist, we'll probably have 16-bit onboard microbot controllers or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants