Tablegen problem populating TSFlags

It seems like this code should work with Tablegen, but it generates the error:

"error:Invalid TSFlags bit in ADD"

Here's the code:

My brief investigation seems to point at this having to do with the
let altering the base class, which prevents the usual resolution from
occurring (presumably the resolution has already happened for the
base). I'll dig into this tomorrow.

-- Sean Silva

An extra call to resolveReferences after setting the value in the
`let` does fix this, but I'm not sure that it is the right fix. The
attached hackish patch seems to fix up a reduced version of the test
case you gave here (I haven't run a full battery of tests on it, so it
might cause other failures).

Jakob, any idea about what the "right" fix is here?

-- Sean Silva

resolveReferencesAfterSet.patch (563 Bytes)

Sorry, no.

I do recall seeing similar problems in the past where the ternary operators weren't properly evaluated, but left as TernOpInits in the final Records.

I don't know of any use case where that would make sense, particularly since other operators get evaluated. Are they even in use in the tree?


Jakob, I think this exactly what's happening. I debugged the
resolveReferences for the ADD down into the resolve of TSFlags. It
calls VarInit::getFieldInit for the "Val" field of "foo". The code is:

Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
                            const std::string &FieldName) const {
  if (isa<RecordRecTy>(getType()))
    if (const RecordVal *Val = R.getValue(VarName)) {
      if (RV != Val && (RV || isa<UnsetInit>(Val->getValue())))
        return 0;
      Init *TheInit = Val->getValue();
      assert(TheInit != this && "Infinite loop detected!");
      if (Init *I = TheInit->getFieldInit(R, RV, FieldName)) // ***
        return I;
        return 0;
  return 0;

The line marked with *** doesn't evaluate TheInit as a TernOpInit
correctly. It goes to the Init base class of getFieldInit and returns

Do we need to add a getFieldInit method on TernOpInit to evaluate the
!if() and return the requested field of the result ("Val" in this
case) ?

What do you think of the following patch? It's a very small change and
fixes the problem. I think it's innocuous since resolveReferences()
should nominally return (*this) if there's nothing to resolve, so
there's no reason not to run it at the start of

When it runs, NewRec != Rec and we return a new FieldInit. Subsequent
calls resolve the OpInit and eventually we get the Bits we want.


resolveFieldInit.patch (509 Bytes)

That sounds like the right path, although there might be an issue if
the condition of the `!if` still needs to be resolved (not sure if
this is impossible or not).

-- Sean Silva