@@ -82,7 +82,25 @@ void PreorderAST::Create(Expr *E, Node *Parent) {
82
82
83
83
E = Lex.IgnoreValuePreservingOperations (Ctx, E->IgnoreParens ());
84
84
85
- if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
85
+ if (!Parent) {
86
+ // The invariant is that the root node must be a BinaryNode with an
87
+ // addition operator. So for expressions like "if (*p)", we don't have a
88
+ // BinaryOperator. So when we enter this function there is no root and the
89
+ // parent is null. So we create a new BinaryNode with + as the operator and
90
+ // add 0 as a LeafNodeExpr child of this BinaryNode. This helps us compare
91
+ // expressions like "p" and "p + 1" by normalizing "p" to "p + 0".
92
+
93
+ auto *N = new BinaryNode (BO_Add, Parent);
94
+ AddNode (N, Parent);
95
+
96
+ llvm::APInt Zero (Ctx.getTargetInfo ().getIntWidth (), 0 );
97
+ auto *ZeroLiteral = new (Ctx) IntegerLiteral (Ctx, Zero, Ctx.IntTy ,
98
+ SourceLocation ());
99
+ auto *L = new LeafExprNode (ZeroLiteral, N);
100
+ AddNode (L, /* Parent*/ N);
101
+ Create (E, /* Parent*/ N);
102
+
103
+ } else if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
86
104
BinaryOperator::Opcode BinOp = BO->getOpcode ();
87
105
Expr *LHS = BO->getLHS ();
88
106
Expr *RHS = BO->getRHS ();
@@ -130,19 +148,6 @@ void PreorderAST::Create(Expr *E, Node *Parent) {
130
148
Create (LHS, /* Parent*/ N);
131
149
Create (RHS, /* Parent*/ N);
132
150
133
- } else if (!Parent) {
134
- // The invariant is that the root node must be a BinaryNode. So for
135
- // expressions like "if (*p)", we don't have a BinaryOperator. So when we
136
- // enter this function there is no root and the parent is null. So we
137
- // create a new BinaryNode with + as the operator and add "p" as a
138
- // LeafNodeExpr child of this BinaryNode. Later, in the function
139
- // NormalizeExprsWithoutConst we normalize "p" to "p + 0" by adding 0 as a
140
- // sibling of "p".
141
-
142
- auto *N = new BinaryNode (BO_Add, Parent);
143
- AddNode (N, Parent);
144
- Create (E, /* Parent*/ N);
145
-
146
151
} else {
147
152
auto *N = new LeafExprNode (E, Parent);
148
153
AddNode (N, Parent);
@@ -331,50 +336,80 @@ void PreorderAST::ConstantFold(Node *N, bool &Changed) {
331
336
Changed = true ;
332
337
}
333
338
334
- void PreorderAST::NormalizeExprsWithoutConst (Node *N) {
335
- // Consider the following case:
336
- // Upper bound expr: p
337
- // Deref expr: p + 1
338
- // In this case, we would not able able to extract the offset from the deref
339
- // expression because the upper bound expression does not contain a constant.
340
- // This is because the node-by-node comparison of the two expressions would
341
- // fail. So we require that expressions be of the form "(variable + constant)".
342
- // So, we normalize expressions by adding an integer constant to expressions
343
- // which do not have one. For example:
344
- // p ==> (p + 0)
345
- // (p + i) ==> (p + i + 0)
346
- // (p * i) ==> (p * i * 1)
339
+ bool PreorderAST::GetDerefOffset (Node *UpperNode, Node *DerefNode,
340
+ llvm::APSInt &Offset) {
341
+ // Extract the offset by which a pointer is dereferenced. For the pointer we
342
+ // compare the dereference expr with the declared upper bound expr. If the
343
+ // non-integer parts of the two exprs are not equal we say that a valid
344
+ // offset does not exist and return false. If the non-integer parts of the
345
+ // two exprs are equal the offset is calculated as:
346
+ // (integer part of deref expr - integer part of upper bound expr).
347
+
348
+ // Since we have already normalized exprs like "*p" to "*(p + 0)" we require
349
+ // that the root of the preorder AST is a BinaryNode.
350
+ auto *B1 = dyn_cast_or_null<BinaryNode>(UpperNode);
351
+ auto *B2 = dyn_cast_or_null<BinaryNode>(DerefNode);
352
+
353
+ if (!B1 || !B2)
354
+ return false ;
347
355
348
- auto *B = dyn_cast_or_null<BinaryNode>(N);
349
- if (!B )
350
- return ;
356
+ // If the opcodes mismatch we cannot have a valid offset.
357
+ if (B1-> Opc != B2-> Opc )
358
+ return false ;
351
359
352
- for ( auto *Child : B-> Children ) {
353
- // Recursively normalize constants in the children of a BinaryNode .
354
- if (isa<BinaryNode>(Child ))
355
- NormalizeExprsWithoutConst (Child) ;
360
+ // We have already constant folded the constants. So return false if the
361
+ // number of children mismatch .
362
+ if (B1-> Children . size () != B2-> Children . size ( ))
363
+ return false ;
356
364
357
- else if (auto *ChildLeafNode = dyn_cast<LeafExprNode>(Child)) {
358
- if (ChildLeafNode->E ->isIntegerConstantExpr (Ctx))
359
- return ;
360
- }
361
- }
365
+ // Check if the children are equivalent.
366
+ for (size_t I = 0 ; I != B1->Children .size (); ++I) {
367
+ auto *Child1 = B1->Children [I];
368
+ auto *Child2 = B2->Children [I];
362
369
363
- llvm::APInt IntConst;
364
- switch (B->Opc ) {
365
- default : return ;
366
- case BO_Add:
367
- IntConst = llvm::APInt (Ctx.getTargetInfo ().getIntWidth (), 0 );
368
- break ;
369
- case BO_Mul:
370
- IntConst = llvm::APInt (Ctx.getTargetInfo ().getIntWidth (), 1 );
371
- break ;
370
+ if (IsEqual (Child1, Child2))
371
+ continue ;
372
+
373
+ // If the children are not equal we require that they be integer constant
374
+ // leaf nodes. Otherwise we cannot have a valid offset.
375
+ auto *L1 = dyn_cast_or_null<LeafExprNode>(Child1);
376
+ auto *L2 = dyn_cast_or_null<LeafExprNode>(Child2);
377
+
378
+ if (!L1 || !L2)
379
+ return false ;
380
+
381
+ // Return false if either of the leaf nodes is not an integer constant.
382
+ llvm::APSInt UpperOffset;
383
+ if (!L1->E ->isIntegerConstantExpr (UpperOffset, Ctx))
384
+ return false ;
385
+
386
+ llvm::APSInt DerefOffset;
387
+ if (!L2->E ->isIntegerConstantExpr (DerefOffset, Ctx))
388
+ return false ;
389
+
390
+ // Offset should always be of the form (ptr + offset). So we check for
391
+ // addition.
392
+ // Note: We have already converted (ptr - offset) to (ptr + -offset). So
393
+ // its okay to only check for addition.
394
+ if (B1->Opc != BO_Add)
395
+ return false ;
396
+
397
+ // This guards us from a case where the constants were not folded for
398
+ // some reason. In theory this should never happen. But we are adding this
399
+ // check just in case.
400
+ llvm::APSInt Zero (Ctx.getTargetInfo ().getIntWidth (), 0 );
401
+ if (llvm::APSInt::compareValues (Offset, Zero) != 0 )
402
+ return false ;
403
+
404
+ // offset = deref offset - declared upper bound offset.
405
+ // Return false if we encounter an overflow.
406
+ bool Overflow;
407
+ Offset = DerefOffset.ssub_ov (UpperOffset, Overflow);
408
+ if (Overflow)
409
+ return false ;
372
410
}
373
411
374
- auto *IntLiteral = new (Ctx) IntegerLiteral (Ctx, IntConst, Ctx.IntTy ,
375
- SourceLocation ());
376
- auto *L = new LeafExprNode (IntLiteral, B);
377
- AddNode (L, B);
412
+ return true ;
378
413
}
379
414
380
415
bool PreorderAST::IsEqual (Node *N1, Node *N2) {
@@ -438,7 +473,6 @@ void PreorderAST::Normalize() {
438
473
ConstantFold (Root, Changed);
439
474
if (Error)
440
475
break ;
441
- NormalizeExprsWithoutConst (Root);
442
476
}
443
477
444
478
if (Ctx.getLangOpts ().DumpPreorderAST ) {
0 commit comments