This is an archive of the discontinued LLVM Phabricator instance.

[MC/AsmParser] Avoid setting MCSymbol.IsUsed
ClosedPublic

Authored by vsk on Aug 25 2015, 5:04 PM.

Details

Summary

Avoid marking MCSymbols as used in MC/AsmParser.cpp when no uses exist. This fixes a bug in parseAssignmentExpression() where we accidentally set IsUsed, thereby triggering:

"invalid re-assignment of non-absolute variable"

on otherwise valid code. No other functionality change is intended.

Diff Detail

Repository
rL LLVM

Event Timeline

vsk updated this revision to Diff 33154.Aug 25 2015, 5:04 PM
vsk retitled this revision from to [MC/AsmParser] Avoid setting MCSymbol.IsUsed.
vsk updated this object.
vsk added reviewers: rafael, ddunbar.
vsk updated this object.
vsk added a subscriber: llvm-commits.
vsk updated this object.Aug 25 2015, 5:16 PM

The various false parameters slightly muddle the code IMO, since they are for value accessors.

test/MC/AsmParser/reassign.s
1 ↗(On Diff #33154)

Can you add a CHECK, or in your case, a CHECK-NOT here please?

vsk added a comment.Aug 25 2015, 9:08 PM

The various false parameters slightly muddle the code IMO, since they are for value accessors.

We could save the IsUsed state and restore it before the MCSymbol leaves scope. E.g;

bool IsUsed = Sym->isUsed();
if (expect_defined)
  TheCondState.CondMet = (Sym && !Sym->isUndefined());
else
  TheCondState.CondMet = (!Sym || Sym->isUndefined());
Sym->setUsed(IsUsed);

Alternatively we could make a separate set of read-only accessors: isUndefinedRO, getVariableValueRO, ... (with a better name).

Is there an approach you'd prefer?

rafael edited edge metadata.Aug 26 2015, 1:10 PM
rafael added a subscriber: rafael.

What we normally do is:

foo(/*SetUsed*/ false);

vsk updated this revision to Diff 33241.Aug 26 2015, 1:38 PM
vsk edited edge metadata.
  • Added /*SetUsed*/ annotations
  • Added a CHECK-NOT line, made sure we don't pass the test on master

It is unfortunate that these accessors mutate the symbol. Personally, I think I prefer the alternate approach of a RAII helper that would restore the state. However, if you are planning some follow up work and this blocks forward progress, then committing this as is to make forward progress would be acceptable (thanks to the annotations).

Thanks for fixing up the test.

vsk added a comment.Aug 27 2015, 10:24 AM

I tried the RAII helper object approach. It improves readability in some areas, but IMHO also leads to brittle code.

For one, some spots remain more readable with the /*SetUsed*/ annotations. E.g, we would need to put the first conditional in its own scope to use the helper object here:

else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() && !Sym->isVariable()) { ... }
else if (Sym->isVariable() && !Sym->isUsed() && allow_redef) { ... }

Secondly, you need to remember to create new helper objects every time a mutating accessor is invoked so that you don't accidentally grab an incorrect IsUsed state.

I'd prefer to stick with this revision. As a followup, I can work on (1) identifying the call sites which intend to mutate IsUsed, (2) forcing those call sites to be explicit with Sym->setUsed(), and (3) making the MCSymbol accessors read-only w.r.t IsUsed.

Let me know what you think!

compnerd accepted this revision.Aug 27 2015, 10:24 PM
compnerd added a reviewer: compnerd.

The follow up approach is definitely better. Lets go with that.

This revision is now accepted and ready to land.Aug 27 2015, 10:24 PM
This revision was automatically updated to reflect the committed changes.