raw_ostream behavior

Hi,

When I run the below example, it results in :-

hello
world
LLVM ERROR: IO failure on output stream.

Testcase :-

#include <llvm/Support/raw_ostream.h>

int fn() {
   std::string errorInfo;
   llvm::raw_fd_ostream out("-", errorInfo);
   out << "world\n";
   return 0;
}
int main(int argc, char **argv) {
   llvm::outs() << "hello\n";
   fn();
   return 0;
}

I tried to fix this by making llvm::outs(), not close the stdout
descriptor, but I think its wrong. Recommendations ?

Thanks

Shankar Easwaran

The high-level answer is that library code shouldn’t hardcode output paths, including “-” and including using llvm::outs(). Library code should (in general) instead accept an ostream in its API and write to wherever it is being asked to write. If this is followed, the only place in any program using llvm::outs() is code which is not part of a “library” – i.e. it is the “main” code, and it should only do so if it is a program which doesn’t open file names which could be “-”.

Do you have a use-case where this restriction is too restrictive?

As a random aside, a more aggressive answer could be that “-” is a kind of hack, and that it would be a better approach to use /dev/stdout and /dev/stdin instead of “-”, because they wouldn’t require special-case logic. Unfortunately, this may not be sufficiently portable.

Dan

Hi Dan,

lld takes a -emit-yaml option, which emits the intermediate representation(atoms) in YAML form.

By default output goes to stdout, the user can control it by using the -o option too.

The way its handled is, similiar to this piece of pseudo-code

if (dash_o_option)
     outputFile = dash_o_option->value()
else
    outputFile = "-"

When lld tries to mix things that go to stdout using llvm::outs() and -emit-yaml, it starts to get this error.

If there is a restriction like this, possibly it has to be mentioned somewhere for usecases (or) raw_fd_ostream should not be accepting a '-' in the argument.

What do you think ?

Thanks

Shankar Easwaran

Would it be appropriate for lld’s other output to go to standard error instead of standard output, since standard output may be used for YAML output?

Hi Dan,

The other messages, need to go to stdout as well. Using stderr to output for a switch like --verbose is wrong in my opinion.

Shankar,

What is the other output going to stdout? Seems like it could get mixed into the yaml output, causing problems.

If -o is not supplied, the linker normally writes to a file called “a.out”. If this is for the core linker when running test suites, may would should have the core linker create a temp file or string buffer to write to (if -o not supplied) and then at the end read from that file and write to stdout.

-Nick

logInputFiles() controlled using the -t option.

Thanks

Shankar Easwaran

Standard error is what many tools, including clang for example, use for their --verbose output. This is appropriate because it leaves standard output available for regular output data, which the user may wish to capture in a file or a pipe.

Dan

Then possibly lld also should start using stderr for the options controlled by user for verbose outputs.

Do you think it should be mentioned in the API usage for users mixing usage of raw_fd_ostream and llvm::outs() ?

Thanks

Shankar Easwaran

Standard error is what many tools, including clang for example, use for their --verbose output. This is appropriate because it leaves standard output available for regular output data, which the user may wish to capture in a file or a pipe.

Well, at least with the darwin linker, the linker main output goes to a file (specified by -o or “a.out”). So, since there is normally nothing going to stdout, -v and -t output goes to stdout.

Shankar, although not quite as convenient, we could change the core linker test cases from:
lld … | FileCheck
to:
lld … -o %t && FileCheck < %t
Then change the core linker to not use “-“, but error if -o is not supplied.

-Nick

It's a very common lit test pattern to do 'clang/llc %s ... -o - |
FileCheck %s ', and lld should probably support that. It should be just a
matter of avoiding outs().