Page MenuHomePhabricator

[clang/DIVar] Emit flag for params that have unchanged values
Needs ReviewPublic

Authored by djtodoro on Feb 11 2019, 3:21 AM.

Details

Summary

Emit debug info flag that indicates that a parameter has unchanged value through the course of a function.

This info will be used for emitting DW_OP_entry_value expressions for the parameter.

Authors: @asowda, @NikolaPrica, @djtodoro, @ivanbaev

Diff Detail

Event Timeline

djtodoro created this revision.Feb 11 2019, 3:21 AM
djtodoro added a project: debug-info.
djtodoro added a subscriber: petarj.
djtodoro updated this revision to Diff 186611.Feb 13 2019, 2:42 AM
  • Rename: VariableNotChanged ===> ArgumentNotModified
  • Refactor a test case
probinson added inline comments.Feb 21 2019, 10:36 AM
include/clang/AST/Decl.h
1482

There should be a comment here.
The style in this class appears to omit the 'get' word from the name of the getter, so isArgumentModified for the method name would look more consistent.

lib/Sema/SemaExpr.cpp
11282

Does this fit on one line if you use const auto *LHSDeclRef ...? Given you have the dyn_cast on the RHS there's no real need to give the type name twice.

+ rsmith, + bricci for review.

I was under the impression that space inside VarDecl was quite constrained. Pardon the likely naive question, but: is there any way to make the representation more compact (maybe sneak a bit into ParmVarDeclBitfields)?

riccibruno edited reviewers, added: riccibruno; removed: bricci.Feb 21 2019, 1:04 PM

If this bit is relevant to function parameters, why is getIsArgumentModified in VarDecl and not in ParamVarDecl ? What you can do is move the relevant methods to ParamVarDecl, and stash the bit in ParmVarDeclBitfields.

include/clang/AST/Decl.h
843

Yeah, please don't waste a whole pointer just to store a bit.

Oh and I think that you will also have to update the serialization code/de-serialization code in ASTReaderDecl.cpp / ASTWriterDecl.cpp. You might also have to update TreeTransform but I am less familiar with this.

I am wondering about the semantics of this bit. I don't think that you can know for sure within clang whether a variable has been modified. The best you can do is know for sure that some variable has been modified, but I don't think you can prove that it has not been modified.

Consequently I am wondering if you should change the name of this flag to something like IsArgumentKnownToBeModified.

Orthogonal to this you need to also add tests for templates.

djtodoro marked 2 inline comments as done.Feb 22 2019, 6:22 AM

I was under the impression that space inside VarDecl was quite constrained. Pardon the likely naive question, but: is there any way to make the representation more compact (maybe sneak a bit into ParmVarDeclBitfields)?

@vsk Thanks for the comment! Sure, it is better idea. Initially, we thought this could be used even for local variables, but since we are using it only for parameters it makes more sense.

lib/Sema/SemaExpr.cpp
11282

Does this fit on one line if you use const auto *LHSDeclRef ...? Given you have the dyn_cast on the RHS there's no real need to give the type name twice.

@probinson Thanks for the comment! Sure, it will be refactored.

djtodoro marked an inline comment as done.Feb 22 2019, 6:27 AM

@riccibruno Thanks for your comments!

Oh and I think that you will also have to update the serialization code/de-serialization code in ASTReaderDecl.cpp / ASTWriterDecl.cpp. You might also have to update TreeTransform but I am less familiar with this.

I've added ASTReaderDecl.cpp / ASTWriterDecl.cpp, but looking at TreeTransform I'm not sure if there is a place for adding something regarding this.

I am wondering about the semantics of this bit. I don't think that you can know for sure within clang whether a variable has been modified. The best you can do is know for sure that some variable has been modified, but I don't think you can prove that it has not been modified.

Consequently I am wondering if you should change the name of this flag to something like IsArgumentKnownToBeModified.

Orthogonal to this you need to also add tests for templates.

I agree! You are right, good idea!

djtodoro updated this revision to Diff 187931.Feb 22 2019, 6:31 AM
  • Add a field in ParmVarDecl instead of VarDecl
  • Use a bit in ParmVarDeclBitfields to indicate parameter modification
  • Add support for the bit in ASTReaderDecl.cpp / ASTWriterDecl.cpp
  • Add test case for templates
riccibruno added inline comments.Feb 22 2019, 6:51 AM
lib/Sema/SemaExpr.cpp
11306

Comments:

  1. Shouldn't you mark the variable to be modified only if CheckForModifiableLvalue returns true ?
  1. I think that you need to handle way more than just member expressions. For example are you handling (x, y) (comma operator) ? But hard-coding every cases here is probably not ideal. It would be nice if there was already some code somewhere that could help you do this.
  1. I believe that a MemberExpr has always a base. Similarly DeclRefExprs always have a referenced declaration (so you can omit the if).
lebedev.ri added inline comments.
lib/Sema/SemaExpr.cpp
11306

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

Alternatively perhaps you could re-use getMemoryLocation() from D57660. It would handle for you members, references, structured bindings +more in a relatively self-contained code.

djtodoro marked an inline comment as done.Feb 25 2019, 2:23 AM

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

Alternatively perhaps you could re-use getMemoryLocation() from D57660. It would handle for you members, references, structured bindings +more in a relatively self-contained code.

@lebedev.ri, @riccibruno Thanks for your advices! We'll check this also.

lib/Sema/SemaExpr.cpp
11306

@riccibruno Please find inlined replies:

  1. Shouldn't you mark the variable to be modified only if CheckForModifiableLvalue returns true ?

Hmm, we should avoid marking variables modification if this emits an error. But, we should emit it if CheckForModifiableLvalue returns false, since in the case of returning true an error will be emitted.

  1. I think that you need to handle way more than just member expressions. For example are you handling (x, y) (comma operator) ? But hard-coding every cases here is probably not ideal. It would be nice if there was already some code somewhere that could help you do this.

Hard coding all cases is not good idea. I agree. Since we are only looking for declaration references, we could make just a function that traverses any Expr and find declaration ref.

  1. I believe that a MemberExpr has always a base. Similarly DeclRefExprs always have a referenced declaration (so you can omit the if).

I think you are right. Thanks!

djtodoro updated this revision to Diff 188110.Feb 25 2019, 2:40 AM
  • Handle all kinds of expressions when mark a param's modification
riccibruno added inline comments.Feb 25 2019, 7:05 AM
lib/Sema/SemaExpr.cpp
11292

Hmm, I don't think that this will work. Suppose that you have an expression like (a, b) += c You want to mark b as modified, but not a. What is needed I believe is:

Given an expression E find the variable that this expression designate if any, and if it is a function parameter mark it "known to be modified".

Visiting all of the children just looking for DeclRefExprs is a bit too blunt I believe.

11312

Hmm, we should avoid marking variables modification if this emits an error. But, we should emit it if CheckForModifiableLvalue returns false, since in the case of returning true an error will be emitted.

You are right, I believed for a moment that CheckForModifiableLvalue returned false on error.

djtodoro marked an inline comment as done.Feb 26 2019, 7:11 AM
djtodoro added inline comments.
lib/Sema/SemaExpr.cpp
11292

You are right. We thought it is possible implementing this with some basic analysis (with low overhead), but in order to support all cases it would take much time and it is not good idea.

I tried to use ExprMutationAnalyzer (that @lebedev.ri mentioned) and it seems to be useful for this. It seems that it can be used a little bit later than in this phase, because it takes ASTContext, but in this stage we have ASTContext finished up to node we are currently observing (an expression from which we are extracting DeclRef). But, even using it in the right time, it seems that ExprMutationAnalyzer does not have support for comma operator. I'm trying to extend this analyzer in order to add support for that. ASAP I will post new changes.
For the other cases I tried, it works.

djtodoro updated this revision to Diff 195192.Mon, Apr 15, 8:31 AM

-Rebase
-Use ExprMutationAnalyzer for parameter's modification check

aprantl added inline comments.Mon, Apr 15, 8:38 PM
lib/CodeGen/CGDebugInfo.cpp
4516

Just looking at the type declarations in CGDebugInfo.h: Why not iterate over the SPCache directly? Shouldn't that contain all Function declarations only?

4520

clang-format please

4525

Could this be a cast<>?

djtodoro marked 3 inline comments as done.Tue, Apr 16, 5:41 AM
djtodoro added inline comments.
lib/CodeGen/CGDebugInfo.cpp
4516

I tried it, but SPCache is empty at this point.

djtodoro updated this revision to Diff 195359.Tue, Apr 16, 5:44 AM

-Run clang-format
-Use cast instead of 'dyn_cast'