C++: Introduce BaseSourceVariableInstruction.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-12-02 10:56:09 +00:00
parent e71fbb1def
commit 589f7bdbcc
3 changed files with 83 additions and 150 deletions

View File

@@ -19,12 +19,6 @@ private module SourceVariables {
)
}
class BaseSourceVariable = SsaInternals0::BaseSourceVariable;
class BaseIRVariable = SsaInternals0::BaseIRVariable;
class BaseCallVariable = SsaInternals0::BaseCallVariable;
cached
private newtype TSourceVariable =
TSourceIRVariable(BaseIRVariable baseVar, int ind) {
@@ -159,15 +153,10 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
* Gets the instruction that computes the base of this definition or use.
* This is always a `VariableAddressInstruction` or an `AllocationInstruction`.
*/
abstract Instruction getBase();
abstract BaseSourceVariableInstruction getBase();
final BaseSourceVariable getBaseSourceVariable() {
exists(IRVariable var |
result.(BaseIRVariable).getIRVariable() = var and
instructionHasIRVariable(this.getBase(), var)
)
or
result.(BaseCallVariable).getCallInstruction() = this.getBase()
this.getBase().getBaseSourceVariable() = result
}
/** Gets the variable that is defined or used. */
@@ -179,11 +168,6 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
}
}
pragma[noinline]
private predicate instructionHasIRVariable(VariableAddressInstruction vai, IRVariable var) {
vai.getIRVariable() = var
}
private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv, int ind) {
defHasSourceVariable(defOrUse, bv, ind)
or
@@ -214,7 +198,7 @@ class DefImpl extends DefOrUseImpl, TDefImpl {
DefImpl() { this = TDefImpl(address, ind) }
override Instruction getBase() { isDef(_, _, address, result, _, _) }
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
Operand getAddressOperand() { result = address }
@@ -259,7 +243,7 @@ class UseImpl extends DefOrUseImpl, TUseImpl {
override int getIndirectionIndex() { result = ind }
override Instruction getBase() { isUse(_, operand, result, _, ind) }
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) }
predicate isCertain() { isUse(true, operand, _, _, ind) }
}
@@ -415,14 +399,6 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
)
}
private SsaInternals0::SourceVariable getOldSourceVariable(SourceVariable v) {
v.getBaseVariable().(BaseIRVariable).getIRVariable() =
result.getBaseVariable().(SsaInternals0::BaseIRVariable).getIRVariable()
or
v.getBaseVariable().(BaseCallVariable).getCallInstruction() =
result.getBaseVariable().(SsaInternals0::BaseCallVariable).getCallInstruction()
}
/**
* Holds if there is a write at index `i` in basic block `bb` to variable `v` that's
* subsequently read (as determined by the SSA pruning stage).
@@ -430,7 +406,7 @@ private SsaInternals0::SourceVariable getOldSourceVariable(SourceVariable v) {
private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
exists(SsaInternals0::Def def, SsaInternals0::SourceVariable v0 |
def.asDefOrUse().hasIndexInBlock(bb, i, v0) and
v0 = getOldSourceVariable(v)
v0 = v.getBaseVariable()
)
}

View File

@@ -152,6 +152,50 @@ predicate isWrite(Node0Impl value, Operand address, boolean certain) {
)
}
predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo)
}
predicate ignoreSourceVariableBase(BaseSourceVariableInstruction base, Node0Impl value) {
any(Indirection ind).ignoreSourceVariableBase(base, value)
}
newtype TBaseSourceVariable =
// Each IR variable gets its own source variable
TBaseIRVariable(IRVariable var) or
// Each allocation gets its own source variable
TBaseCallVariable(AllocationInstruction call)
abstract class BaseSourceVariable extends TBaseSourceVariable {
abstract string toString();
abstract DataFlowType getType();
}
class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable {
IRVariable var;
IRVariable getIRVariable() { result = var }
BaseIRVariable() { this = TBaseIRVariable(var) }
override string toString() { result = var.toString() }
override DataFlowType getType() { result = var.getType() }
}
class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable {
AllocationInstruction call;
BaseCallVariable() { this = TBaseCallVariable(call) }
AllocationInstruction getCallInstruction() { result = call }
override string toString() { result = call.toString() }
override DataFlowType getType() { result = call.getResultType() }
}
/**
* Holds if the value pointed to by `operand` can potentially be
* modified be the caller.
@@ -199,6 +243,19 @@ predicate isModifiableByCall(ArgumentOperand operand) {
)
}
abstract class BaseSourceVariableInstruction extends Instruction {
abstract BaseSourceVariable getBaseSourceVariable();
}
private class BaseIRVariableInstruction extends BaseSourceVariableInstruction,
VariableAddressInstruction {
override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() }
}
private class BaseAllocationInstruction extends BaseSourceVariableInstruction, AllocationInstruction {
override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this }
}
cached
private module Cached {
/**
@@ -209,7 +266,9 @@ private module Cached {
* `indirectionIndex` specifies the number of loads required to read the variable.
*/
cached
predicate isUse(boolean certain, Operand op, Instruction base, int ind, int indirectionIndex) {
predicate isUse(
boolean certain, Operand op, BaseSourceVariableInstruction base, int ind, int indirectionIndex
) {
not ignoreOperand(op) and
certain = true and
exists(LanguageType type, int upper, int ind0 |
@@ -257,11 +316,10 @@ private module Cached {
* Holds if `operand` is a use of an SSA variable rooted at `base`, and the
* path from `base` to `operand` passes through `ind` load-like instructions.
*/
private predicate isUseImpl(Operand operand, Instruction base, int ind) {
private predicate isUseImpl(Operand operand, BaseSourceVariableInstruction base, int ind) {
DataFlowImplCommon::forceCachingInSameStage() and
ind = 0 and
operand.getDef() = base and
isSourceVariableBase(base)
operand = base.getAUse()
or
exists(Operand mid, Instruction instr |
isUseImpl(mid, base, ind) and
@@ -278,17 +336,6 @@ private module Cached {
)
}
/**
* Holds if `i` is a base instruction that starts a sequence of uses
* of some variable that SSA can handle.
*
* This is either when `i` is a `VariableAddressInstruction` or when
* `i` is a fresh allocation produced by an `AllocationInstruction`.
*/
private predicate isSourceVariableBase(Instruction i) {
i instanceof VariableAddressInstruction or i instanceof AllocationInstruction
}
/**
* Holds if `address` is an address of an SSA variable rooted at `base`,
* and `instr` is a definition of the SSA variable with `ind` number of indirections.
@@ -299,7 +346,7 @@ private module Cached {
*/
cached
predicate isDef(
boolean certain, Node0Impl value, Operand address, Instruction base, int ind,
boolean certain, Node0Impl value, Operand address, BaseSourceVariableInstruction base, int ind,
int indirectionIndex
) {
exists(int ind0, CppType type, int lower, int upper |
@@ -320,11 +367,10 @@ private module Cached {
* Note: Unlike `isUseImpl`, this predicate recurses through pointer-arithmetic
* instructions.
*/
private predicate isDefImpl(Operand address, Instruction base, int ind) {
private predicate isDefImpl(Operand address, BaseSourceVariableInstruction base, int ind) {
DataFlowImplCommon::forceCachingInSameStage() and
ind = 0 and
address.getDef() = base and
isSourceVariableBase(base)
address = base.getAUse()
or
exists(Operand mid, Instruction instr |
isDefImpl(mid, base, ind) and

View File

@@ -15,75 +15,15 @@ private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon
private module SourceVariables {
newtype TBaseSourceVariable =
// Each IR variable gets its own source variable
TBaseIRVariable(IRVariable var) or
// Each allocation gets its own source variable
TBaseCallVariable(AllocationInstruction call)
class SourceVariable instanceof BaseSourceVariable {
string toString() { result = BaseSourceVariable.super.toString() }
abstract class BaseSourceVariable extends TBaseSourceVariable {
abstract string toString();
abstract DataFlowType getType();
BaseSourceVariable getBaseVariable() { result = this }
}
class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable {
IRVariable var;
class SourceIRVariable = BaseIRVariable;
IRVariable getIRVariable() { result = var }
BaseIRVariable() { this = TBaseIRVariable(var) }
override string toString() { result = var.toString() }
override DataFlowType getType() { result = var.getType() }
}
class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable {
AllocationInstruction call;
BaseCallVariable() { this = TBaseCallVariable(call) }
AllocationInstruction getCallInstruction() { result = call }
override string toString() { result = call.toString() }
override DataFlowType getType() { result = call.getResultType() }
}
private newtype TSourceVariable =
TSourceIRVariable(BaseIRVariable baseVar) or
TCallVariable(AllocationInstruction call)
abstract class SourceVariable extends TSourceVariable {
abstract string toString();
abstract BaseSourceVariable getBaseVariable();
}
class SourceIRVariable extends SourceVariable, TSourceIRVariable {
BaseIRVariable var;
SourceIRVariable() { this = TSourceIRVariable(var) }
IRVariable getIRVariable() { result = var.getIRVariable() }
override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() }
override string toString() { result = this.getIRVariable().toString() }
}
class CallVariable extends SourceVariable, TCallVariable {
AllocationInstruction call;
CallVariable() { this = TCallVariable(call) }
AllocationInstruction getCall() { result = call }
override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call }
override string toString() { result = "Call" }
}
class CallVariable = BaseCallVariable;
}
import SourceVariables
@@ -113,58 +53,27 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
/** Gets the location of this element. */
abstract Cpp::Location getLocation();
abstract Instruction getBase();
abstract BaseSourceVariableInstruction getBase();
final BaseSourceVariable getBaseSourceVariable() {
exists(IRVariable var |
result.(BaseIRVariable).getIRVariable() = var and
instructionHasIRVariable(this.getBase(), var)
)
or
result.(BaseCallVariable).getCallInstruction() = this.getBase()
result = this.getBase().getBaseSourceVariable()
}
/** Gets the variable that is defined or used. */
final SourceVariable getSourceVariable() {
exists(BaseSourceVariable v |
sourceVariableHasBaseAndIndex(result, v) and
defOrUseHasSourceVariable(this, v)
result.getBaseVariable() = v and
this.getBaseSourceVariable() = v
)
}
}
pragma[noinline]
private predicate instructionHasIRVariable(VariableAddressInstruction vai, IRVariable var) {
vai.getIRVariable() = var
}
private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv) {
defHasSourceVariable(defOrUse, bv)
or
useHasSourceVariable(defOrUse, bv)
}
pragma[noinline]
private predicate defHasSourceVariable(DefImpl def, BaseSourceVariable bv) {
bv = def.getBaseSourceVariable()
}
pragma[noinline]
private predicate useHasSourceVariable(UseImpl use, BaseSourceVariable bv) {
bv = use.getBaseSourceVariable()
}
pragma[noinline]
private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVariable bv) {
v.getBaseVariable() = bv
}
class DefImpl extends DefOrUseImpl, TDefImpl {
Operand address;
DefImpl() { this = TDefImpl(address) }
override Instruction getBase() { isDef(_, _, address, result, _, _) }
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
Operand getAddressOperand() { result = address }
@@ -200,7 +109,7 @@ class UseImpl extends DefOrUseImpl, TUseImpl {
final override Cpp::Location getLocation() { result = operand.getLocation() }
override Instruction getBase() { isUse(_, operand, result, _, _) }
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, _) }
predicate isCertain() { isUse(true, operand, _, _, _) }
}
@@ -305,6 +214,8 @@ class Def extends DefOrUse {
Node0Impl getValue() { result = defOrUse.getValue() }
override string toString() { result = this.asDefOrUse().toString() }
BaseSourceVariableInstruction getBase() { result = defOrUse.getBase() }
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;