Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
- Build Status
Buildable 41980 Build 42324: arc lint + arc unit
Event Timeline
libc/config/linux/api.td | ||
---|---|---|
33 | We don't use extern for other function definitions in other header files so I don't think we should here | |
libc/spec/stdc.td | ||
176 | Are adding the errno macros out of the scope of this patch? | |
libc/src/errno/errno_test.cpp | ||
13 | Something like Basic seems more conventional than Smoke for a test name. What is it supposed to mean? | |
libc/src/errno/llvmlibc_errno.h | ||
12 | Internally we could use a thread_local int & instead of relying on a macro, I believe. It seems nicer, what do you think? |
libc/config/linux/api.td | ||
---|---|---|
34 | () Otherwise errno[0] is incorrect. |
libc/config/linux/api.td | ||
---|---|---|
33 | You need __attribute__((const)) in __GNUC__ mode, otherwise common subexpression elimination does not apply: think errno+errno. |
libc/config/linux/api.td | ||
---|---|---|
34 | We don't want to put it in parenthesis because we want to error on uses like errno[0]. errno is supposed to be an lvalue of int type and allowing errno[0] actually amounts to leaking implementation detail. | |
libc/spec/stdc.td | ||
176 | The generated header is not coming out pretty (though syntactically correct) with a large number of macros added (the order seems messed up ). I had wanted to first fix that up and then add the remaining macros. But, after reading your comment, it occurs to me that it is better to fix the problem than to hedge it. So, I have added the remaining macros now. Will improve the look of the generated file with a different patch. | |
libc/src/errno/errno_test.cpp | ||
13 | Smoke for https://en.wikipedia.org/wiki/Smoke_testing_(software). | |
libc/src/errno/llvmlibc_errno.h | ||
12 | That's a good idea so I have done it now. |
libc/spec/stdc.td | ||
---|---|---|
176 | Also, I am not sure if a libc should provide these macros or if we should fallback to the ones provided by the Linux headers. Glibc seems to be preferring to use the Linux headers, while musl seems to be providing them itself. May be @stanshebs can throw some light here. |
libc/spec/stdc.td | ||
---|---|---|
176 | I took a closer look at the numbers used by musl. They are just a copy of the linux numbers. Also, ISTM that if Linux provides them, we should use them. Will discuss with @stanshebs and update the patch. |
libc/config/linux/api.td | ||
---|---|---|
34 | I know errno[0] will be an error anyway. However, this breaks grouping: *__errno_location()[0] You also don't want 3 errno to be treated as 3*__errno_location(), do you? | |
libc/src/errno/llvmlibc_errno.h | ||
15 | I don't think this will work. In the test translation unit, the compiler does not know that llvmlibc_errno is bound to a thread-local variable. Even in the definition site, it's not clear to me that a reference to a thread-local variable will guarantee to work. |
libc/src/errno/errno_location.cpp | ||
---|---|---|
15 | If we do end up keeping this reference we could also put it behind namespace __llvm_libc and call it something less verbose, perhaps. | |
libc/src/errno/llvmlibc_errno.h | ||
15 | Right, it must be thread_local int &. I've tested it only briefly, if the reference isn't thread_local it doesn't work. As far as I can tell thread_local int & works. |
libc/src/errno/llvmlibc_errno.h | ||
---|---|---|
15 | Sigh yes. This declaration has to include thread_local for everything to work correctly. Will update in the next round. |
libc/src/errno/errno_location.cpp | ||
---|---|---|
15 | I did consider __llvm_libc::errno. But, now since errno is a token by itself, it interferes with the public macro errno when used along with other libraries, and even gtest. Will update in the next round. |
libc/src/errno/llvmlibc_errno.h | ||
---|---|---|
15 | But why do we need a thread_local reference in the first place? It is represented as a thread_local pointer that is initialized to the return address of a TLS wrapper function under the hood. You can check the codegen. The performance is bad. |
libc/config/linux/api.td | ||
---|---|---|
34 | To be clear here, I do not really have an opinion and I am OK to put it in parenthesis. Other libcs have chosen not to enclose in parenthesis which I thought was to prevent some form of abuse. But, I do see your point that either way it can be abused. If @stanshebs does not tell us anything interesting, I will put it in parenthesis. |
libc/config/linux/api.td | ||
---|---|---|
33 | I don't have a Windows machine to test this, but from godbolt, __attribute__'s seem to be unrecognized by MSVC or at least const was not a known one. I see other libcs conditionally defining (on __GNUC__ according to @MaskRay) an __attribute_const or something like that. FWIW I don't favor adding this attribute. How useful will this even be really? |
libc/src/errno/llvmlibc_errno.h | ||
---|---|---|
15 |
Yup I didn't realize it would be much worse. I agree that it is not worth the performance overhead and we should just go back to the macro. |
For posterity, #define errno *__errno_location() breaks C11 7.1.2p5:
Any definition of an object-like macro described in this clause shall expand to code that is fully protected by parentheses where necessary, so that it groups in an arbitrary expression as if it were a single identifier.
It will fail to diagnose code like 3 errno[0] (false positive), and incorrectly flag (false negative):
const char *blah[] = { [EILSEQ] = "asdf" }; errno = EILSEQ; puts(errno[blah]);
and errno++
libc/config/linux/api.td | ||
---|---|---|
33 | Using unprotected __attribute__ will break cross compilability. MSVC does not accept it. Or you can say llvm-libc doesn't support MSVC. I'm totally fine with it.
This matters when you run lots of functions that may potentially modify errno in a function. foo(); if (errno) ... foo(); if (errno) ... foo(); if (errno) ... |
libc/config/linux/api.td | ||
---|---|---|
105 | This comment may give a false impression that these constants are defined by POSIX but they are not. On FreeBSD, the values are entirely different. Apparently this will soon be a Linux only project after more Linux specific things are unconsciously baked in. |
libc/config/linux/api.td | ||
---|---|---|
33 |
Like @sivachandra said earlier, this is just the config file for Linux, if we support Windows later then it will not use this attribute in its config file.
Hmm. I'm not trying to argue, this is purely out of curiosity at this point, because a lot of libcs use this attribute. If I'm understanding correctly, that code will call __errno_location() once and use the first value each time after. But can't different calls to foo set errno differently? | |
105 | Like above, this is just the Linux config file, thee FreeBSD one will have different values. |
libc/spec/posix.td | ||
---|---|---|
1 ↗ | (On Diff #232621) | Is this expected to be definitive for what POSIX specifies? EHWPOISON is Linux-only I think. |
libc/src/errno/errno_location.cpp | ||
16 | One bit of handiness that glibc does is to alias it its version of __errno with plain "errno", so you see it as "errno" in a debugger, object file dumps, etc. (In theory, getting errno through macro expansion and function call should be possible in debugger, but is much less straightforward and more likely to fail, as with core dumps.) |
Split the error macros in two POSIX and Linux based on https://pubs.opengroup.org/onlinepubs/9699919799/
libc/spec/posix.td | ||
---|---|---|
1 ↗ | (On Diff #232621) | I do not know if https://pubs.opengroup.org/onlinepubs/9699919799/ is a definitive guide, but I have now split this list up into POSIX and Linux based on that link. |
libc/src/errno/errno_location.cpp | ||
16 | Aliases in C++ code will require mangled names. One can use the same section trick, but prefer to do it in a later pass iff required. |
libc/src/errno/llvmlibc_errno.h | ||
---|---|---|
19 | Mark locally defined libc symbols hidden __attribute__((visibility("hidden"))) in internal headers. When the library is built with -fPIC (for shared objects), the codegen will not create unnecessary PLT or GOT relocations. See musl/src/include/errno.h for an example. |
libc/config/linux/api.td | ||
---|---|---|
33 | You have a valid point and I have to confess I do not really know how the const attribute works in general. My homework showed me that glibc and musl both use the const attribute and I was not really sure if it is only useful in cases like errno + errno, so I left it out initially. Also, I am of the opinion that adding attributes like this should be driven by some implementation standards backed by some tooling. As you feel, even I do not want to argue over these things especially when they are correct in way. Considering musl and glibc use the const attribute, I think there is no harm using it but I am open to being proven wrong for accepting this suggestion. | |
libc/src/errno/llvmlibc_errno.h | ||
19 | That's a good suggestion. I think its not yet decided if items like these are really internal. I understand musl treats in a particular way and glibc treats it in a slightly different way. In general, I like your suggestion. However, I would like to keep this open for now as we need to make a decision about what exactly do we mean by internal (For example, we want this libc to work along with other libcs. So, overridability of some form is probably desirable.). After we make a decision, we should probably drive this more cleanly using some set acceptable patterns backed by some tooling to verify adherence. |
libc/config/linux/api.td | ||
---|---|---|
34 | Remove the ; | |
97 | 'depend on the linux/errno.h' -> 'depend on linux/errno.h' | |
libc/include/errno.h.def | ||
15 | glibc has an ifdef block around the C definitions to exclude them if ASSEMBLER is defined so that only the E* macros are exposed to assembly files which want them. I would imagine no one is including C's errno.h instead of linux/errno.hin assembly source, but I figured I would bring it up. https://code.woboq.org/userspace/glibc/stdlib/errno.h.html#32 |
libc/include/errno.h.def | ||
---|---|---|
15 | I prefer to add anything like that on an "as needed" basis. |
errno is a fundamental component baked in almost every component of a libc and contributors/reviewers should really be on the same page. Both abrachet and stanshebs accepted the patch and they were the initially-added reviewers. I feel a bit lonely to be the only one in the "Request Changes" camp, but I hope you do not commit the patch with these open issues not resolved. To reiterate, I feel strong about my suggested items:
- __attribute__((visibility("hidden"))) in the internal header.
- __attribute__((const)) in the public header.
They are adopted by both glibc and musl.
You are reluctant to add hidden visibility because you feel that it may make overlaying llvm-libc on top of system libc harder? Can you discuss more about the details somewhere, e.g. libc-dev or llvm-dev?
@abrachet It seems you have more comments that cannot be simply categorized as minor updates after you accepted the patch (within 40 minutes.after the patch was posted) Phabricator just simply marks the patch "green" unless another person marks it "Request Changes". There are some controversial parts that may give rise to public disagreement. For such cases, it might be better waiting a bit. (For this patch, I feel that if I did not click "Request Changes" in time, it would be committed and it would be more difficult to improve the situation later.)
To be clarify here, I have added the const attribute as soon as I have seen your suggestion.
They are adopted by both glibc and musl.
You are reluctant to add hidden visibility because you feel that it may make overlaying llvm-libc on top of system libc harder? Can you discuss more about the details somewhere, e.g. libc-dev or llvm-dev?
As I have said previously, we want to add visibility attributes in a more principled manner. I have also said previously that your suggestion is very valid, and that it was considered even before putting this patch out.
A discussion on libc-dev or llvm-dev will definitely be started when I am prepared with all the details I want to bring up. Or, if someone wants to champion the whole area of interop with other libcs, I would be glad to lean on their help. I do not see why such a discussion should block this patch. FWIW, this patch helps me add more of the library, which I think is of greater importance to keep the development of this library running.
I appreciate that you and @abrachet have volunteered to do the reviews here. At the same time, I find the tone of the above comment unfriendly. AFAICT, @abrachet is doing this voluntarily out of his own interest. An unfriendly tone for actions, which I view as "friendly community citizenship", definitely is uncalled for.
My reason to accept this now is that secondary issues like visibility are almost certainly going to need revisiting later, when we have more content to work with. For instance, do we do it by adding attributes everywhere in sight, or do we build some kind of script or other automation? Given that this is being developed incrementally from zero, we are just making extra unnecessary work by insisting that the defacto prototype solve all the problems that might need solving in the future. So let's get the core of the system figured out now, and not worry about secondary issues until more of the system is in place.
Sorry about that there ended up being many more changes than I anticipated here when I accepted. I'll be more careful next time.
I think @sivachandra and I are on the same page here that things are bound to change later and currently the ground work is being laid so that development can truly start. I think its worth starting a thread on the libc list of how reviews should go and what we have in mind for these current revisions.
FWIW I don't find @MaskRay's comments to be unfriendly, and I value his opinion a lot, he has helped me on my patches quite a bit in the past. He simply pointed out something I could do better, and I'm glad he did.
If it can make you feel better, apart from the minor nits, the "major" changes between the latest version and the version you have accepted is the addition of the const attribute and the new error macros. We have explored the idea of making errno a reference for internal use, but @MaskRay thankfully pointed out to the fact that it leads to a lot more code gen.
I think @sivachandra and I are on the same page here that things are bound to change later and currently the ground work is being laid so that development can truly start. I think its worth starting a thread on the libc list of how reviews should go and what we have in mind for these current revisions.
I also would like to point out that I have addressed each every comment on this review. I did not accept one suggestion, but I have backed it up with some reasoning.
For the sake of progress, I will submit this change soon and move on to other patches.
About, "how reviews should go ... " -- We do not want to be different from any other LLVM code review. I have picked reviewers based on who I feel might have the best feedback for a particular change. I would think that it is the normal practice, which for me personally, has been reinforced with my past experience in the LLVM community.
About, "and what we have in mind for these current revisions." -- If I can come up with something worth while, I will definitely post it to list. If a major design decision has to be made, we should of course have a discussion on the dev list. We have done this for the header generation idea, and going forward I am sure we will have many more such discussions. I do not think it is practical to discuss each and every patch on the list.
Apologize if you feel that my comments were not friendly. I did not intend that.
My reason to accept this now is that secondary issues like visibility are almost certainly going to need revisiting later, when we have more content to work with. For instance, do we do it by adding attributes everywhere in sight, or do we build some kind of script or other automation? Given that this is being developed incrementally from zero, we are just making extra unnecessary work by insisting that the defacto prototype solve all the problems that might need solving in the future. So let's get the core of the system figured out now, and not worry about secondary issues until more of the system is in place.
My feeling is that making the attribute change part of the patch is preferable. It makes the intention clear what symbols are public and what symbols and internal implementation details. Adding errno in an incremental step looks great to me. But making attribute changes separate is not. From the comments, it seems that __errno_location may be overlayed on top of an existing libc? I am a bit more concerned about the approach that will be used to do the overlay work. The design choice made here needs to account for standalone libc mode + overlay mode. I think we need to make the two modes clear.
A higher level point I have been trying to make is that the design is open. I have not spent enough time on it to write to any list and make a case. Under such circumstances, we do not want to commit to any particular thing.
libc/config/linux/api.td | ||
---|---|---|
33 | Is there a reason for implementing errno as a function call? It's only needed on platforms where the compiler doens't support TLS (and those, I would expect, support emutls with clang?). In FreeBSD libc, we use this formulation for legacy reasons, but we have moved to using TLS for other errno-like things. Why not declare it as _Thread_local int errno? (In FreeBSD's cdefs.h, we don't define _Thread_local in C11 mode (where it's a keyword, in all other modes it's a reserved identifier), to thread_local in C++11 mode, and to __thread in any other GNU modes. We could define it to declspec(thread) for MSVC and add the dllimport if required. C99 permitted this to be the entire definition, C11 requires you to also #define errno errno. | |
105 | I'm also somewhat concerned at the lack of layering here. Other parts of libc depend heavily on the definition of errno and on many of these values. If I understand correctly, the list in the POSIX spec file enumerates all of the ones that are required for POSIX, so we should be able to report any missing ones. It's not clear to me how the two files are layered so that targeting POSIX on Linux will hide the Linux-only definitions. The #include of the Linux file also makes it difficult to determine when compiling on Linux whether other code is accidentally depending on non-POSIX values. Ideally, if we're going to include the Linux file, we'd conditionally #undef the values that aren't part of POSIX when targeting POSIX. | |
111 | This file appears to be missing a definition of errno_t when compiling for a C11 target | |
libc/spec/stdc.td | ||
181 | I believe this is where errno_t should live, though it should be conditionally exposed for C11 or later. |
libc/config/linux/api.td | ||
---|---|---|
33 | You are correct and I going to change this. What you have suggested is present in modern glibc versions and I agree it is the best approach. The reasons I have not done it in this patch is this: 1. I wanted to move on to implementing mmap and friends which require errno. If we have an implementation of errno, it is easy to swap it out later. 2. We do not have a build rule yet to compile data only C++ files. I did not want to block on that. It was a personal choice. But if you tell me it was a bad one, I am OK to go work on the build rules first and make errno a public _Thread_local value. | |
105 | About being able to check the missing ones: About hiding Linux only definitions on a POSIX platform, or vice-versa: Did I understand and address everything your brought up here? | |
111 | TBH, only the errno macro was supposed to be in the scope of this patch. I added the other macros in response to a review comment, and because I thought it was straightforward to add them. | |
libc/spec/stdc.td | ||
181 | Acknowledged. Conditional exposure is still up for discussion which I will bring up separately. |
We don't use extern for other function definitions in other header files so I don't think we should here