This is an archive of the discontinued LLVM Phabricator instance.

[TableGen] Add new operator !exists
ClosedPublic

Authored by pcwang-thead on Jun 16 2022, 2:43 AM.

Details

Summary

We can cast a string to a record via !cast, but we have no mechanism
to check if it is valid and TableGen will raise an error if failed to
cast. Besides, we have no semantic null in TableGen (we have ? but
different backends handle uninitialized value differently), so operator
like dyn_cast<> is hard to implement.

In this patch, we add a new operator !exists<T>(s) to check whether
a record with type T and name s exists. Self-references are allowed
just like !cast.

By doing these, we can write code like:

class dyn_cast_to_record<string name> {
  R value = !if(!exists<R>(name), !cast<R>(name), default_value);
}
defvar v = dyn_cast_to_record<"R0">.value; // R0 or default_value.

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptJun 16 2022, 2:43 AM
pcwang-thead requested review of this revision.Jun 16 2022, 2:43 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 16 2022, 2:43 AM

Fix test errors.

I think this change makes sense and it looks good to me, except for one thing: if I were to see an !instanceof without context, I would expect that it is also able to take a record/def as operand. That kind of use is likely to come up eventually, and people shouldn't have to artificial convert the record/def to its name first. So I'm in favor of this change, except I'd ask you to change the implementation (and tests) to support both kinds of use.

Hmm, I now saw the earlier discussion and @tra's very good points in it. If !instanceof accepts defs, then it becomes somewhat redundant with !isa, which I hadn't considered. Can you improve the error checking so that if a record is provided as an argument, the message advises that !isa should be used instead?

FWIW, I'm not 100% happy about the name "instanceof", but I can't think of anything better right now that isn't super verbose. And I don't want to bikeshed this change to death either :)

  • Guide users to use !isa when argument is a record.
  • Make position of error reporting correct.

Thank you. One more thought after sleeping on it: What do you think about !exists? I think !exists<T>("foo") reads nicely as "does there exist a record of type T with name 'foo'?". It's not perfect, but I like that there's less confusion with "instanceof" or "isinstance" operators that some programming languages have.

tra added a comment.Jun 21 2022, 2:28 PM

Thank you. One more thought after sleeping on it: What do you think about !exists? I think !exists<T>("foo") reads nicely as "does there exist a record of type T with name 'foo'?". It's not perfect, but I like that there's less confusion with "instanceof" or "isinstance" operators that some programming languages have.

I like it. !instanceof sounded like something that assumes that its input is an object, while we're actually giving it an object's name.
!exists seems to be a better match.

tra added inline comments.Jun 21 2022, 4:49 PM
llvm/test/TableGen/instanceof.td
4–10 ↗(On Diff #438363)

This test is rather hard to read as checks are placed all over the place, usually away from where the respective records are defined.
Alas, we don't have CHECK-DAG-NEXT we could use to do sequential matches in out of order chunks.

I guess the best we could do here is to have the tablegen source at the top of the file, and all the checks below, in order they are emitted by the tablegen, possibly with the comments referring to the relevant source code, if it's not obvious what exactly, and why, particular check statement tests for.
E.g. right now it's not obvious why the value of B1 is 0 and B0 is 1. See the other suggestion which may make the checks self-explanatory.

19–20 ↗(On Diff #438363)

These could use more descriptive names, possibly reflecting expected result.
E.g.

def A0 : A;

class A_check<string name>{
  int exists = !instanceof<A>(name);
}

def A0_exists : A_check<"A0">;
def A1_missing : A_check<"A1">;
  • Change operator name to !exists.
  • Make tests more self-explanatory.
pcwang-thead retitled this revision from [TableGen] Add new operator !instanceof to [TableGen] Add new operator !exists.Jun 22 2022, 6:11 AM
pcwang-thead edited the summary of this revision. (Show Details)
pcwang-thead edited the summary of this revision. (Show Details)
nhaehnle accepted this revision.Jun 22 2022, 8:11 AM

Awesome, LGTM

llvm/lib/TableGen/TGParser.cpp
2407

Why did you move the comment?

This revision is now accepted and ready to land.Jun 22 2022, 8:11 AM
tra accepted this revision.Jun 22 2022, 10:15 AM

Very nice. LGTM.

Do not touch comment in ParseSimpleValue.

pcwang-thead marked an inline comment as done.Jun 22 2022, 8:10 PM
pcwang-thead added inline comments.
llvm/lib/TableGen/TGParser.cpp
2407

Hmm, that's because I tried to extend UnOpInit before and found it not suitable, but I forgot to move the case. Fixed.

This revision was landed with ongoing or failed builds.Jun 22 2022, 8:13 PM
This revision was automatically updated to reflect the committed changes.
pcwang-thead marked an inline comment as done.