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

Add checks to annotation getters. #5052

Merged
merged 3 commits into from
Dec 12, 2024
Merged

Conversation

fruffy
Copy link
Collaborator

@fruffy fruffy commented Dec 5, 2024

Provide more useful feedback when trying to retrieve content from an annotation the wrong way.

@fruffy fruffy added the core Topics concerning the core segments of the compiler (frontend, midend, parser) label Dec 5, 2024
@fruffy fruffy requested a review from asl December 5, 2024 00:25
ir/base.def Outdated
inline auto &getKV() { return std::get<KVAnnotation>(body); }
inline const auto &getKV() const { return std::get<KVAnnotation>(body); }
inline auto &getKV() {
BUG_CHECK(annotationKind() == Kind::StructuredKVList, "Annotation does not contain a key-value list.");
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the annotation is an unstructured kv-list (an unstructured annotation with PARSE_KV_LIST)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will add this. Are these all possible combinations?

Copy link
Contributor

Choose a reason for hiding this comment

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

When an unstructured annotation is parsed, it might be parsed into either the expr field or the kv field, or into something else, though I don't think we've run into that yet. The original intent was that a backend that needed such an annotation would define a subclass of Annotation to store the parsed version of the annotation.

Copy link
Collaborator Author

@fruffy fruffy Dec 5, 2024

Choose a reason for hiding this comment

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

When do we generate a structured annotation? I have been looking at

IR::Annotation::Kind annotationKind() const {
    if (needsParsing())
        return Kind::Unparsed;
    if (!structured)
        return Kind::Unstructured;
    if (std::holds_alternative<ExpressionAnnotation>(body))
        return Kind::StructuredExpressionList;
    if (std::holds_alternative<KVAnnotation>(body))
        return Kind::StructuredKVList;

    BUG("Invalid annotation kind");
}

and it is a little misleading because an annotation can be both a Kind::StructuredKVList/Kind::StructuredExpressionList and a Kind::Unstructured. We just let unstructured dominate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Looking at https://p4.org/p4-spec/docs/P4-16-working-spec.html#sec-annotations it is possible that a compiler developers tries to parse an unstructured annotation as a KV-annotation. We do not restrict that, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like with Anton's change, one needs to check std::holds_alternative to check that it has the right kind (or does using std::get throw an exception if the wrong kind is present? That would probably be ok).

Copy link
Contributor

Choose a reason for hiding this comment

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

The structured flag is set if the code uses @foo [ ... ] or @foo { ... } and not set if it uses @foo( ... ). That's all it really tells you.

Copy link
Contributor

Choose a reason for hiding this comment

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

and it is a little misleading because an annotation can be both a

Yes, I was pretty confused by this distinction. Even more, it seems to be used just in one place – somewhere around p4 control plane. Overall, the things are multimensional:

  • Annotation could be parsed and unparsed
  • Parsed annotations could be structured and unstructured (1 dimension)
  • Parsed annotations could be expression lists and kv-lists (2 dimension)

I think it would be better to factor out everything in such way. I just do not know if there are any out of tree uses of structured annotations to get rid of annotationKind.

@ChrisDodd
Copy link
Contributor

Might it be better to write these as

try {
    return std::get<...>(body);
} catch (std::bad_variant_access) {
    BUG("Annotation contains incorrect type");
}

Not a style we currently use, but perhaps we should go that way?

@fruffy fruffy linked an issue Dec 5, 2024 that may be closed by this pull request
@fruffy
Copy link
Collaborator Author

fruffy commented Dec 5, 2024

Might it be better to write these as

try {
    return std::get<...>(body);
} catch (std::bad_variant_access) {
    BUG("Annotation contains incorrect type");
}

Not a style we currently use, but perhaps we should go that way?

Not opposed to it... is the hope better performance?

ir/base.def Outdated
inline auto &getExpr() { return std::get<ExpressionAnnotation>(body); }
inline const auto &getExpr() const { return std::get<ExpressionAnnotation>(body); }
inline auto &getUnparsed() {
BUG_CHECK(annotationKind() == Kind::Unparsed, "Annotation has been parsed already.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BUG_CHECK(annotationKind() == Kind::Unparsed, "Annotation has been parsed already.");
BUG_CHECK(needsParsing(), "Annotation has been parsed already.");

ir/base.def Outdated
return std::get<UnparsedAnnotation>(body);
}
inline const auto &getUnparsed() const {
BUG_CHECK(annotationKind() == Kind::Unparsed, "Annotation has been parsed already.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BUG_CHECK(annotationKind() == Kind::Unparsed, "Annotation has been parsed already.");
BUG_CHECK(needsParsing(), "Annotation has been parsed already.");

ir/base.def Outdated
return std::get<UnparsedAnnotation>(body);
}
inline auto &getExpr() {
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
BUG_CHECK(std::holds_alternative<ExpressionAnnotation>(body) "Annotation does not contain an expression list.");

ir/base.def Outdated
return std::get<ExpressionAnnotation>(body);
}
inline const auto &getExpr() const {
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
BUG_CHECK(std::holds_alternative<ExpressionAnnotation>(body), "Annotation does not contain an expression list.");

ir/base.def Outdated
inline Expression getExpr(size_t idx) const {
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BUG_CHECK(annotationKind() == Kind::Unstructured || annotationKind() == Kind::StructuredExpressionList, "Annotation does not contain an expression list.");
BUG_CHECK(std::holds_alternative<ExpressionAnnotation>(body), "Annotation does not contain an expression list.");

@fruffy fruffy marked this pull request as ready for review December 11, 2024 14:19
Signed-off-by: fruffy <fruffy@nyu.edu>
Signed-off-by: fruffy <fruffy@nyu.edu>
@fruffy fruffy force-pushed the fruffy/annotation_error_messages branch from df09a6a to 8390080 Compare December 11, 2024 14:19
@fruffy fruffy requested a review from asl December 12, 2024 11:10
Copy link
Contributor

@asl asl left a comment

Choose a reason for hiding this comment

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

Thanks!

@fruffy fruffy added this pull request to the merge queue Dec 12, 2024
Merged via the queue into main with commit b0f775c Dec 12, 2024
19 checks passed
@fruffy fruffy deleted the fruffy/annotation_error_messages branch December 12, 2024 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Topics concerning the core segments of the compiler (frontend, midend, parser)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

std::get is not guarded in the IR::Annotation getters
3 participants