C++: Reduce code duplication by moving shared code into a module.

This commit is contained in:
Mathias Vorreiter Pedersen
2023-11-16 09:51:30 +00:00
parent 5a7cb8f25a
commit d25c24b64d

View File

@@ -1273,49 +1273,90 @@ abstract private class IndirectExprNodeBase extends Node {
} }
} }
bindingset[e, indirectionIndex] /** A signature for converting an indirect node to an expression. */
private predicate adjustForReference( private signature module IndirectNodeToIndirectExprSig {
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex /** The indirect node class to be converted to an expression */
) { class IndirectNode;
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1 /**
or * Holds if the indirect expression at indirection index `indirectionIndex`
not conv instanceof ReferenceDereferenceExpr and * of `node` is `e`. The integer `n` specifies how many conversions has been
conv = e and * applied to `node`.
adjustedIndirectionIndex = indirectionIndex */
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
} }
/**
* A module that implements the logic for deciding whether an indirect node
* should be an `IndirectExprNode`.
*/
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
import Sig
/**
* This predicate shifts the indirection index by one when `conv` is a
* `ReferenceDereferenceExpr`.
*
* This is necessary because `ReferenceDereferenceExpr` is a conversion
* in the AST, but appears as a `LoadInstruction` in the IR.
*/
bindingset[e, indirectionIndex]
private predicate adjustForReference(
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
) {
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1
or
not conv instanceof ReferenceDereferenceExpr and
conv = e and
adjustedIndirectionIndex = indirectionIndex
}
/** Holds if `node` should be an `IndirectExprNode`. */
predicate charpred(IndirectNode node) {
exists(Expr e, int n, int indirectionIndex |
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
)
)
}
}
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
}
module IndirectOperandToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{ {
IndirectOperandIndirectExprNode() { IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectOperand(this, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectExprNodeShouldBeIndirectOperand(_, conv, n + 1, adjustedIndirectionIndex)
)
)
}
final override Expr getConvertedExpr(int n, int index) { final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectOperand(this, result, n, index) IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
} }
} }
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectInstruction;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
}
module IndirectInstructionToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{ {
IndirectInstructionIndirectExprNode() { IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectInstruction(this, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
not indirectExprNodeShouldBeIndirectInstruction(_, conv, n + 1, adjustedIndirectionIndex)
)
)
}
final override Expr getConvertedExpr(int n, int index) { final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectInstruction(this, result, n, index) IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
} }
} }