This is an archive of the discontinued LLVM Phabricator instance.

[libc] Add very basic stdio FILE and fwrite
ClosedPublic

Authored by abrachet on Apr 6 2020, 8:37 PM.

Details

Summary

This patch adds a very basic FILE type and basic fwrite.

It also removes snprintf from StdIO's function spec because VarArgType was causing the generation to fail.

Diff Detail

Event Timeline

abrachet created this revision.Apr 6 2020, 8:37 PM

I have been busy looking into the ARM math test setup. I will review this before the end of the week.

Did a highlevel pass and dropped a couple of questions. Will do a more fine grained review later in the day.

libc/src/stdio/fwrite.h
18

Asking for my own knowledge: when/where would an internal unlock version be useful?

libc/test/config/linux/x86_64/syscall_test.cpp
12 ↗(On Diff #255574)

Does it make sense to move it utils/CPP? It is incomplete right now, but may be utils/CPP is a more appropriate place.

sivachandra marked an inline comment as done.Apr 10 2020, 10:39 PM
sivachandra added inline comments.
libc/config/linux/api.td
23

I understand all public API deals with FILE*. But, would an empty struct trigger an incorrect optimization in user code somewhere? I have no idea, but just checking since such a thought comes to my mind.

165

I added this as an example long time back and never checked if it works presently.

libc/src/stdio/FILE.h
21

May be this struct is scalable. As in, this structure can handle all kinds of FILE objects. But, few questions below.

24

For a simple use like this, a name like cookie seems alright. But, would it make sense to call it write_ptr?

25

Should we actually specify the type of the writing function? Let it be set by the FILE creation function to the appropriate writer type?

libc/test/config/linux/x86_64/syscall_test.cpp
1 ↗(On Diff #255574)

Can you move the changes in this file to a separate patch?

abrachet marked 5 inline comments as done.Apr 11 2020, 12:39 AM
abrachet added inline comments.
libc/src/stdio/FILE.h
21

Yes I think we could have internal types which inherit from this base __llvm_libc::FILE.

24

I think the name isn't great either but its from [[ http://man7.org/linux/man-pages/man3/fopencookie.3.html | fopencookie ]] which is a GNU extension, I think is worthwhile to support. Wether we do ever export fopencookie or not it is a good internal scheme.

25

What do you mean? Templatize it for internal use?

libc/src/stdio/fwrite.h
18

Possibly in functions like printf which might have separated writes but the stream would need to remain locked to make sure it is written continuously. This may not be ever called internally though. Should I remove its prototype from the internal header?

libc/test/config/linux/x86_64/syscall_test.cpp
12 ↗(On Diff #255574)

Possibly, I just have this here for the type checking. All it really needs is an operator() and it would be pretty similar to std::function, so we could put it there.

Also, while we are talking about it. Would utils/CPP be an appropriate place to add an analog to std::unique_lock for internal use around mtx_t?

abrachet updated this revision to Diff 256932.Apr 12 2020, 11:53 PM
  • Change FILE's external definition from empty struct to void
  • Remove change to syscall_test.cpp
abrachet marked 2 inline comments as done.Apr 13 2020, 12:06 AM
abrachet added inline comments.
libc/config/linux/api.td
23

Actually it turns out that empty struct is undefined behavior in C. I've used void here, which will of course fail if someone does FILE f. Which I think is preferable, but we can make it a complete object type like int if thats better.

MaskRay added inline comments.Apr 13 2020, 8:42 AM
libc/config/linux/api.td
23

You can just use the real underlying type typedef struct _IO_FILE FILE;

It is not required to be complete.

libc/src/stdio/FILE.h
20

FILE needs to be a typedef to a struct.

24

fopencookie is a use case. The type does not need to mention cookie_*.

abrachet updated this revision to Diff 257013.Apr 13 2020, 10:04 AM
abrachet marked an inline comment as done.
  • Use incomplete struct FILE as FILE's definition not void
  • Remove cookie from write_function_t
abrachet marked 6 inline comments as done.Apr 13 2020, 10:07 AM
abrachet added inline comments.
libc/config/linux/api.td
23

I've gone with typedef struct FILE FILE

libc/src/stdio/FILE.h
20

This is an internal (C++) header.

24

cookie_write_function_t is a type which must be exposed for fopencookie. That doesn't mean we need to refer to the internal type by that name though so I have just called it write_function_t

sivachandra added inline comments.Apr 13 2020, 12:27 PM
libc/src/stdio/FILE.h
18

We probably want to avoid dependence on sys/types.h here to keep the definition of FILE platform independent. See my other comment below.

24

I think having the cookie pointer is also a bit confusing. For example, it feels like you are saying all FILE objects should follow the cookie protocol (so to say). What do you think about this:

struct FILE {
  lock
  functions for file operations on FILE* objects
};

For each specific kind of stream we will have a derived class of FILE which will contain stream specific data (For example, cookie in your case). Also, the stream creation functions like fopen will install the appropriate file operation functions in the FILE object. An operation function, say seek, will look like:

class MyFileType : public File {
   ....
};

int seek(FILE *f, long offset, ...) {
  // This seek function is specific to MyFileType objects so the static down cast is safe.
  MyFileType *myFile = static_cast<MyFileType *>(f):
  ...
}

As for fopencookie, I think you can wrap the cookie_io_functions_t functions in other functions which match the signature in the base struct FILE and avoid any type mismatch issues.

abrachet updated this revision to Diff 257110.Apr 13 2020, 2:05 PM
abrachet marked 3 inline comments as done.

Remove cookie from the base FILE type

abrachet marked 4 inline comments as done.Apr 13 2020, 2:08 PM
abrachet added inline comments.
libc/src/stdio/FILE.h
18

ssize_t is what cookie_write_function_t returns and this is defined in sys/types.h. The idea is that write(2) returns that I believe. I've removed that TODO for now.

24

This is what I was planning, so you're right cookie isn't necessary in the base FILE type. Also it makes more sense for the functions to take FILE I was thinking I would need to put that in the cookie which would have been a pain. Much better :)

sivachandra accepted this revision.Apr 13 2020, 10:42 PM
sivachandra marked an inline comment as done.
sivachandra added inline comments.
libc/src/stdio/FILE.h
18

SG. AFAIK, write is not a std C function so handling all such functions outside of this common struct SGTM.

libc/src/stdio/fwrite.h
18

Sorry, I missed this previously. Going by the spirit of "unless required", probably a good idea to take this and the implementation off?

This revision is now accepted and ready to land.Apr 13 2020, 10:42 PM
abrachet updated this revision to Diff 257220.Apr 14 2020, 1:01 AM
abrachet marked 2 inline comments as done.
abrachet edited the summary of this revision. (Show Details)

Remove fwrite_unlocked from internal header
Internally refer to FILE by its fully qualified name __llvm_libc::FILE NFC

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2020, 1:33 AM