This is an archive of the discontinued LLVM Phabricator instance.

[StreamExecutor] Add error handling library
ClosedPublic

Authored by jhen on Jul 22 2016, 9:53 AM.

Details

Summary

Error handling in StreamExecutor is based on llvm::Error and llvm::Expected. This CL sets up the StreamExecutor wrapper classes in the streamexecutor namespace.

All the other StreamExecutor code makes use of this error handling code, so this is the first CL for checking in StreamExecutor.

Diff Detail

Repository
rL LLVM

Event Timeline

jhen updated this revision to Diff 65093.Jul 22 2016, 9:53 AM
jhen retitled this revision from to [StreamExecutor] Add utility library.
jhen updated this object.
jhen added reviewers: jlebar, tra.
jhen added a subscriber: parallel_libs-commits.
jlebar added inline comments.Jul 22 2016, 3:50 PM
streamexecutor/include/streamexecutor/Utils/Demangle.h
23 ↗(On Diff #65093)

I would be pretty surprised if we didn't already have a function for this in llvm. I think you can call LLVMSymbolizer::DemangleName with a null ModInfo?

streamexecutor/include/streamexecutor/Utils/Error.h
1 ↗(On Diff #65093)

We already have support/Error.h, which I think is our idiom, subsuming this, Status, and StatusOr. This is the first time I've looked at these facilities, so I don't know e.g. whether we want to use ErrorOr<> or Expected<>.

If we end up keeping this, it seems like we probably don't need many of these error codes? But we can cross that bridge.

streamexecutor/include/streamexecutor/Utils/Macros.h
24 ↗(On Diff #65093)

Surely we have one of these in LLVM.

39 ↗(On Diff #65093)

LLVM_ATTRIBUTE_UNUSED_RESULT

53 ↗(On Diff #65093)

Hm. This is un-llvm-ish. I'd rather not introduce this idiom into LLVM, since nobody else is using it.

Is this used all over the place?

streamexecutor/include/streamexecutor/Utils/Mutex.h
50 ↗(On Diff #65093)

LLVM has a Mutex class.

streamexecutor/include/streamexecutor/Utils/PtrUtil.h
60 ↗(On Diff #65093)

This already exists in STLExtras.h.

streamexecutor/lib/Utils/StrUtil.cpp
1 ↗(On Diff #65093)

I am not sure we need these utils.

StringRef has lower(), upper(), startswith(), and endswith(), and StringExtras.h has SplitString. The only one I'm not sure about is stripSuffixString. That one seems less general-purpose, but if we use it a lot, maybe we can move it to StringExtras.h?

jhen updated this revision to Diff 65848.Jul 27 2016, 6:16 PM
jhen marked 7 inline comments as done.
  • Fixes based on jlebar's suggestions
jhen added a comment.Jul 27 2016, 6:16 PM

I followed most of jlebar's suggestions to use standard LLVM utilities and this patch is now much smaller.

streamexecutor/include/streamexecutor/Utils/Demangle.h
23 ↗(On Diff #65093)

You're right, LLVMSymbolizer::DemangleName seems to work. So, I got rid of all the SE custom "Demangle" stuff.

streamexecutor/include/streamexecutor/Utils/Error.h
1 ↗(On Diff #65093)

I did a lot of experiments and Expected<> looks like it does what we want, so I removed Status and StatusOr and replaced them with Error.h which wraps llvm::Error and llvm::Expected.

streamexecutor/include/streamexecutor/Utils/Macros.h
24 ↗(On Diff #65093)

I searched but couldn't find one. I even grepped in include/llvm using grep -R '\<sizeof(.*)[[:space:]]*/[[:space:]]*sizeof(' and it only showed up some unrelated stuff in Support/MachO.h.

39 ↗(On Diff #65093)

Now that Status has been deleted, this is not needed anymore anyway, so I got rid of it.

53 ↗(On Diff #65093)

This isn't widely used and it's easy to replace. It's gone now.

streamexecutor/include/streamexecutor/Utils/Mutex.h
50 ↗(On Diff #65093)

Cool, I got rid of this file and I'll switch to using LLVM's RWMutex when I want a shared_mutex.

streamexecutor/include/streamexecutor/Utils/PtrUtil.h
60 ↗(On Diff #65093)

Great! I switched to using the STLExtras version and removed this.

streamexecutor/lib/Utils/StrUtil.cpp
1 ↗(On Diff #65093)

You're right, they're not needed. I switch to using the StringRef stuff now and removed StrUtil.

(somewhat of a drive-by comment below, sorry for that, but just wanted to try and push comments and documentation in a small way)

streamexecutor/include/streamexecutor/Utils/Error.h
25–27 ↗(On Diff #65848)

If I were a naive reader, I might not understand the context that leads you to specifically pull these types into the streamexecutor namespace.

I think it would be really useful to expand the comments in the code to include more rationale behind the design the code is following. As an example, the file comment above might talk about the fact that these aren't just internal utilities of streamexecutor, but types that will in some cases appear on the user-facing side of the streamexecutor APIs, and thus form some of the building blocks for streamexecutor's user-facing API. As a consequence, while they are implemented in terms of the LLVM primitives, they are specialized and provided under that namespace to make things more clear for users, blah blalh blah.

Anyways, a very meta comment, and not even necessarily something you want to address in this patch vs. other patches, and probably this is just one place where it might be relevant.

jlebar added inline comments.Jul 27 2016, 6:50 PM
streamexecutor/include/streamexecutor/Utils/Error.h
30 ↗(On Diff #65848)

It looks like most subclasses are named FooError, rather than FooErrorInfo. Maybe SEError?

32 ↗(On Diff #65848)

Nit, if you take the string by value, probably better to std::move it. But better still would be to take an llvm::StringRef, I think, and stringify it here. Then we can create errors from Twines or whatever.

38 ↗(On Diff #65848)

Looking through existing code, this is usually called getErrorMessage.

45 ↗(On Diff #65848)

nit, capital E

50 ↗(On Diff #65848)

Given that there's only one constructor, I'm not sure we need a full-blown forwarding constructor.

But would it be so bad to just do "return make_error<SEError>("foo")" everywhere? That is, do we need this wrapper? "Explicit is better than implicit."

58 ↗(On Diff #65848)

Should probably note that Error must be success or an SEError.

Kind of weird that we have no type-safety...

59 ↗(On Diff #65848)

This seems like a strange name, because we're not really consuming the message. consumeAndGetMessage? Or is that too verbose?

79 ↗(On Diff #65848)

What if we didn't have this, and all callsites did

consumeAndGetMessage(Exp.takeError());

AIUI you don't need the if (Exp) branch because takeError returns Error::success() if there's no error.

To me that would be more explicit, and it's not a ton more complicated. But you have the context about the rest of the code.

94 ↗(On Diff #65848)

Hm, why would we sometimes want to std::move the error and sometimes not? You don't want to std::move all the time because then we defeat rvo (and, I suppose, potentially get a warning about a pessimizing move)?

Do we really need these three macros? On other projects I've worked on, they are widely viewed as a mistake, and in particular the distinction between the first two is mega-confusing. And the precedent in llvm, such as it is, is to do without. Maybe we can sit down and see whether the code becomes really ugly without them?

streamexecutor/include/streamexecutor/Utils/Macros.h
25 ↗(On Diff #65848)

Found it: STLExtras.h array_lengthof.

40 ↗(On Diff #65848)

Maybe you forgot to update this file?

54 ↗(On Diff #65848)

Same for this one.

streamexecutor/include/streamexecutor/Utils/ThreadAnnotations.h
28 ↗(On Diff #65848)

Would rather not pollute the global namespace with SE_THREAD_ANNOTATION_ATTRIBUTE if we can help it. (That is, would rather declare this with one macro rather than two.)

But this also seems like something that would be better in e.g. mutex.h.

jhen updated this revision to Diff 65967.Jul 28 2016, 12:16 PM
jhen marked 14 inline comments as done.
  • More changes from jlebar and chandlerc
streamexecutor/include/streamexecutor/Utils/Error.h
25–27 ↗(On Diff #65848)

Great point. I've added a ton of comments now.

50 ↗(On Diff #65848)

I've refactored so that "SEError" is not present in the header. This makes my original intention clear, that the user should not know about StreamExecutor's custom llvm::ErrorInfo class. I've retained the make_error function, but now it's not templated, but instead just takes a StringRef.

58 ↗(On Diff #65848)

I've added a few comments that talk about how only the public functions should be used to deal with these types. It is weird that there's no type safety, but if people stick to the public interface in namespace streamexecutor, I don't think they can go wrong.

59 ↗(On Diff #65848)

It's not too verbose. I changed the name as you suggested.

94 ↗(On Diff #65848)

We don't really need these macros. They just came from emulating Google internal StreamExecutor. I have removed them now.

I'll say why I had move and non-move versions here, but feel free to skip as they are gone now. The move version was for functions that returned Expected<T>. Expected<T> has a constructor that takes an rvalue ref to Error, so we would have to return a moved temporary error in order to be able to call that constructor.

streamexecutor/include/streamexecutor/Utils/Macros.h
25 ↗(On Diff #65848)

Awesome! Thanks. Now I can get rid of this whole macros file.

40 ↗(On Diff #65848)

Yep, I just forgot to update it. The whole file should be gone now.

streamexecutor/include/streamexecutor/Utils/ThreadAnnotations.h
28 ↗(On Diff #65848)

Consolidated to one macro and moved to Mutex.h.

jlebar edited edge metadata.Jul 28 2016, 12:28 PM

I'll look over the changes to error.h after I get some food (and finally make my way into the office), but here are a few quick things.

streamexecutor/CMakeLists.txt
50 ↗(On Diff #65848)

FWIW I have studiously avoided learning CMake. If this isn't just copy/pasted from somewhere, maybe Art can sign off on it. But if you're happy with it, that's good enough for me.

streamexecutor/include/streamexecutor/Utils/ThreadAnnotations.h
28 ↗(On Diff #65848)

Ah, sorry, I meant, it seems that this belongs in LLVM's mutex.h (as a separate patch).

jlebar added inline comments.Jul 28 2016, 2:14 PM
streamexecutor/include/streamexecutor/Utils/Error.h
27 ↗(On Diff #65967)

Probably worth capitalizing "Error" when we're talking about the class.

31 ↗(On Diff #65967)

from an Error object

78 ↗(On Diff #65967)

Nit, ", where"

82 ↗(On Diff #65967)

suggest s/the * pointer dereference operator/operator*/. Similarly below for ->

121 ↗(On Diff #65967)

Maybe we should say

"You can also write the same code if doTask3() returns an Expected<U> instead of an Error." One less example, and it calls out the equivalence of the code rather than asking the reader to figure out that it's the same.

On another note, could I do

return ExpectedInt;

instead of

return ExpectedInt.takeError();

I think so based on the rules above. Not sure if that's worth mentioning, or if we have a preference between these two ways of doing it.

180 ↗(On Diff #65967)

I wonder if we need this one. It may encourage people to do string comparisons to check whether a function returned success, and that's kind of lame.

What do you think, based on the code you haven't released yet?

streamexecutor/lib/Utils/Error.cpp
17 ↗(On Diff #65967)

Why <> instead of ""? Same in the header. llvm and clang don't contain the string "#include <llvm".

25 ↗(On Diff #65967)

Nit, suggest Message.str() -- a bit simpler.

jhen updated this revision to Diff 66056.Jul 28 2016, 4:41 PM
jhen marked 8 inline comments as done.
jhen edited edge metadata.
  • More comments from jlebar
streamexecutor/include/streamexecutor/Utils/Error.h
121 ↗(On Diff #65967)

I combined the task3 and task4 examples to show a few different ways of passing errors up the stack.

180 ↗(On Diff #65967)

I'm fine to get rid of it.

This looks great to me except it looks like the changes to mutex.h are still there.

jhen updated this revision to Diff 66061.Jul 28 2016, 4:55 PM
  • Remove mutex stuff
jhen added a comment.Jul 28 2016, 4:56 PM

Ah yes, the mutex stuff. It turns out there is a whole story to deal with there. I'll do it in another CL.

jlebar accepted this revision.Jul 28 2016, 5:00 PM
jlebar edited edge metadata.

lgtm!

This revision is now accepted and ready to land.Jul 28 2016, 5:00 PM
jhen retitled this revision from [StreamExecutor] Add utility library to [StreamExecutor] Add error handling library.Jul 29 2016, 1:41 PM
jhen updated this object.
jhen edited edge metadata.
This revision was automatically updated to reflect the committed changes.