// Constructs a simple expression from the given Cetus expression protected SimpleExpression(Expression e) { this(); if (e instanceof UnaryExpression) parse((UnaryExpression) e); else if (e instanceof BinaryExpression) parse((BinaryExpression) e); else if (e.getChildren() != null && !e.getChildren().isEmpty()) parseTree(e); else parseLeaf(e); }
// Parses a generic expression and returns true if it contains side effect. private void parseTree(Expression e) { if (e instanceof MinMaxExpression) { MinMaxExpression mme = (MinMaxExpression) e; sop = (mme.isMin()) ? MIN : MAX; } else { sop = TREE; expr = e; order = TREE_ORDER; if (e instanceof FunctionCall || e instanceof VaArgExpression) contains_side_effect = true; } if (e instanceof StatementExpression) // parsing stops here. return; for (Object o : e.getChildren()) { if (o instanceof Expression) { SimpleExpression child = new SimpleExpression((Expression) o); contains_side_effect |= child.contains_side_effect; add(child); } else Tools.exit("[SimpleExpression] unable to parse a generic expression"); } }
/** Normalization for points-to analysis. */ private static Expression normalize(Expression arg, Symbol param) { Expression ret = arg.clone(); // default behavior. // Converts array accesses to address-of expressions. if (ret instanceof ArrayAccess) { ArrayAccess array = (ArrayAccess) ret; // Normalize the array name. Expression name = normalize(array.getArrayName(), null); Symbol base = SymbolTools.getSymbolOf(name); if (base != null && param != null && SymbolTools.isPointerParameter(param)) { // case 1: the base symbol has an array specifier. // --> - keeps the array indices while adding trailing [0]. // - converts to address-of expression. // - adds dereference operator if base is a formal parameter if (SymbolTools.isArray(base)) { // Adds a trailing subscript "[0]" intentionally. array.addIndex(new IntegerLiteral(0)); ret = new UnaryExpression(UnaryOperator.ADDRESS_OF, ret); // Formal parameter is normalized: a[10] to (*a)[10]. // This conversion is used only internally (not legal in C). if (SymbolTools.isPointerParameter(base)) { array .getArrayName() .swapWith(new UnaryExpression(UnaryOperator.DEREFERENCE, name.clone())); } // case 2: the base symbol does not have an array specifier. // --> just take the base object while converting a subscript // to a dereference. } else { ret = name; for (int i = 0; i < array.getNumIndices(); i++) { ret = new UnaryExpression(UnaryOperator.DEREFERENCE, ret.clone()); } } } else { // just normalizes the array name. array.getArrayName().swapWith(name); } // Removes pointer access and adds trailing dummy index for pointer // type. } else if (ret instanceof AccessExpression) { AccessExpression access = (AccessExpression) ret; // POINTER_ACCESS to MEMBER_ACCESS if (access.getOperator() == AccessOperator.POINTER_ACCESS) { // Normalize the LHS. Expression lhs = normalize(access.getLHS(), null); ret = new AccessExpression( new UnaryExpression(UnaryOperator.DEREFERENCE, lhs.clone()), AccessOperator.MEMBER_ACCESS, access.getRHS().clone()); } // Pointer type to address-of expression. if (param != null && SymbolTools.isPointerParameter(param)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(ret.clone(), new IntegerLiteral(0))); } // Just normalize the expression child. } else if (ret instanceof UnaryExpression) { UnaryExpression ue = (UnaryExpression) ret; ue.setExpression(normalize(ue.getExpression(), null)); // Tries to convert simple pointer arithmetic to array access. } else if (ret instanceof BinaryExpression) { BinaryExpression be = (BinaryExpression) ret; Expression lhs = normalize(be.getLHS(), null); Expression rhs = normalize(be.getRHS(), null); if (param != null && SymbolTools.isPointerParameter(param) && be.getOperator() == BinaryOperator.ADD) { if (isPointerArithmeticOperand(lhs, rhs)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(rhs.clone(), lhs.clone())); } else if (isPointerArithmeticOperand(rhs, lhs)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(lhs.clone(), rhs.clone())); } } else { ret = new BinaryExpression(lhs.clone(), be.getOperator(), rhs.clone()); } // Type cast is discarded. } else if (ret instanceof Typecast) { ret = (Expression) ret.getChildren().get(0); } return ret; }