diff --git a/config/identical-files.json b/config/identical-files.json index 829837ceed40..1a7813948ce5 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -19,10 +19,10 @@ "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/FunctionIR.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/FunctionIR.qll" ], - "C++ IR OperandTag": [ - "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/OperandTag.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/OperandTag.qll", - "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/OperandTag.qll" + "C++ IR Operand": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll" ], "C++ IR IRImpl": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll", diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll index 2fdc6050ae4a..6cfa61861ff8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll @@ -16,7 +16,7 @@ class MemoryAccessKind extends TMemoryAccessKind { /** * The operand or result accesses memory at the address specified by the - * `LoadStoreAddressOperand` on the same instruction. + * `AddressOperand` on the same instruction. */ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess { override string toString() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll index 5e84762e7eb8..3fc7e0691258 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll @@ -2,7 +2,7 @@ import FunctionIR import Instruction import IRBlock import IRVariable -import OperandTag +import Operand import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 4603cf498481..c95cb23814e6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -2,12 +2,13 @@ private import internal.IRInternal import FunctionIR import IRBlock import IRVariable -import OperandTag +import Operand import cpp import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind import semmle.code.cpp.ir.implementation.Opcode private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag class InstructionTag = Construction::InstructionTagType; @@ -22,21 +23,21 @@ module InstructionSanity { exists(Opcode opcode | opcode = instr.getOpcode() and ( - opcode instanceof UnaryOpcode and tag instanceof UnaryOperand or + opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag or ( opcode instanceof BinaryOpcode and ( - tag instanceof LeftOperand or - tag instanceof RightOperand + tag instanceof LeftOperandTag or + tag instanceof RightOperandTag ) ) or - opcode instanceof CopyOpcode and tag instanceof CopySourceOperand or - opcode instanceof MemoryAccessOpcode and tag instanceof LoadStoreAddressOperand or - opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperand or - opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperand or - opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperand or - opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperand or - opcode instanceof Opcode::Call and tag instanceof CallTargetOperand + opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or + opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or + opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or + opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or + opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or + opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or + opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag ) ) } @@ -45,26 +46,34 @@ module InstructionSanity { * Holds if instruction `instr` is missing an expected operand with tag `tag`. */ query predicate missingOperand(Instruction instr, OperandTag tag) { - expectsOperand(instr, tag) and not exists(instr.getOperand(tag)) + expectsOperand(instr, tag) and + not exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) } /** * Holds if instruction `instr` has an unexpected operand with tag `tag`. */ query predicate unexpectedOperand(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and + exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag) and not expectsOperand(instr, tag) and - not (instr instanceof CallInstruction and tag instanceof ArgumentOperand) and - not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperand) and - not (instr instanceof PhiInstruction and tag instanceof PhiOperand) + not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and + not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) } /** * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - strictcount(instr.getOperand(tag)) > 1 and - not tag instanceof UnmodeledUseOperand + strictcount(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) > 1 and + not tag instanceof UnmodeledUseOperandTag } /** @@ -74,7 +83,7 @@ module InstructionSanity { query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) { pred = instr.getBlock().getAPredecessor() and not exists(PhiOperand operand | - exists(instr.getOperand(operand)) and + operand = instr.getAnOperand() and operand.getPredecessorBlock() = pred ) } @@ -98,14 +107,13 @@ module InstructionSanity { } /** - * Holds if instruction `op` consumes an operand `operand` that was defined in + * Holds if operand `operand` consumes a value that was defined in * a different function. */ - query predicate operandAcrossFunctions( - Instruction op, Instruction operand, OperandTag tag - ) { - operand = op.getOperand(tag) and - operand.getFunctionIR() != op.getFunctionIR() + query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) { + operand.getInstruction() = instr and + operand.getDefinitionInstruction() = defInstr and + instr.getFunctionIR() != defInstr.getFunctionIR() } /** @@ -246,20 +254,6 @@ class Instruction extends Construction::TInstruction { result = getResultId() + "(" + getResultTypeString() + ")" } - /** - * Gets a string describing the specified operand, suitable for display in IR - * dumps. This consists of the result ID of the instruction consumed by the - * operand, plus a label identifying the operand kind. - * - * For example: `this:r3_5` - */ - string getOperandString(OperandTag tag) { - exists(Instruction operand | - operand = getOperand(tag) and - result = tag.getLabel() + operand.getResultId() - ) - } - /** * Gets a string describing the operands of this instruction, suitable for * display in IR dumps. @@ -267,9 +261,9 @@ class Instruction extends Construction::TInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - result = concat(OperandTag tag, Instruction operand | - operand = getOperand(tag) | - tag.getLabel() + operand.getResultId(), ", " order by tag.getSortOrder() + result = concat(Operand operand | + operand = getAnOperand() | + operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) } @@ -333,7 +327,6 @@ class Instruction extends Construction::TInstruction { result = Construction::getInstructionUnconvertedResultExpression(this) } - /** * Gets the type of the result produced by this instruction. If the * instruction does not produce a result, its result type will be `VoidType`. @@ -397,35 +390,19 @@ class Instruction extends Construction::TInstruction { } /** - * Gets the instruction that produced the value of the specified source - * operand. - */ - final Instruction getOperand(OperandTag tag) { - result = Construction::getInstructionOperand(this, tag) - } - - /** - * Gets all instructions consumed by this instruction's operands. + * Gets all direct uses of the result of this instruction. */ - final Instruction getAnOperand() { - result = getOperand(_) + final Operand getAUse() { + result.getDefinitionInstruction() = this } /** - * Holds if this instruction has a memory operand with the specified tag. + * Gets all of this instruction's operands. */ - final predicate isMemoryOperand(OperandTag tag) { - exists(getOperandMemoryAccess(tag)) + final Operand getAnOperand() { + result.getInstruction() = this } - /** - * Gets the kind of memory access performed by the specified operand. Holds - * only for memory operands. - */ - MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - none() - } - /** * Holds if this instruction produces a memory result. */ @@ -461,9 +438,7 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(Instruction useInstr, UnmodeledUseOperand useTag | - this = useInstr.getOperand(useTag) - ) + not (getAUse() instanceof UnmodeledUseOperand) } /** @@ -602,7 +577,7 @@ class FieldAddressInstruction extends FieldInstruction { } final Instruction getObjectAddress() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -640,12 +615,7 @@ class ReturnValueInstruction extends ReturnInstruction { } final Instruction getReturnValue() { - result = getOperand(returnValueOperand()) - } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ReturnValueOperand))) and - result instanceof IndirectMemoryAccess + result = getAnOperand().(ReturnValueOperand).getDefinitionInstruction() } } @@ -655,7 +625,7 @@ class CopyInstruction extends Instruction { } final Instruction getSourceValue() { - result = getOperand(copySourceOperand()) + result = getAnOperand().(CopySourceOperand).getDefinitionInstruction() } } @@ -670,13 +640,8 @@ class LoadInstruction extends CopyInstruction { opcode instanceof Opcode::Load } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(CopySourceOperand))) and - result instanceof IndirectMemoryAccess - } - final Instruction getSourceAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -690,7 +655,7 @@ class StoreInstruction extends CopyInstruction { } final Instruction getDestinationAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -700,7 +665,7 @@ class ConditionalBranchInstruction extends Instruction { } final Instruction getCondition() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getTrueSuccessor() { @@ -758,11 +723,11 @@ class BinaryInstruction extends Instruction { } final Instruction getLeftOperand() { - result = getOperand(leftOperand()) + result = getAnOperand().(LeftOperand).getDefinitionInstruction() } final Instruction getRightOperand() { - result = getOperand(rightOperand()) + result = getAnOperand().(RightOperand).getDefinitionInstruction() } } @@ -873,7 +838,7 @@ class UnaryInstruction extends Instruction { } final Instruction getOperand() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -992,6 +957,7 @@ class RelationalInstruction extends CompareInstruction { RelationalInstruction() { opcode instanceof RelationalOpcode } + /** * Gets the operand on the "greater" (or "greater-or-equal") side * of this relational instruction, that is, the side that is larger @@ -1011,6 +977,7 @@ class RelationalInstruction extends CompareInstruction { Instruction getLesserOperand() { none() } + /** * Holds if this relational instruction is strict (is not an "or-equal" instruction). */ @@ -1097,7 +1064,7 @@ class SwitchInstruction extends Instruction { } final Instruction getExpression() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getACaseSuccessor() { @@ -1117,7 +1084,7 @@ class CallInstruction extends Instruction { } final Instruction getCallTarget() { - result = getOperand(callTargetOperand()) + result = getAnOperand().(CallTargetOperand).getDefinitionInstruction() } } @@ -1138,24 +1105,18 @@ class ThrowValueInstruction extends ThrowInstruction { opcode instanceof Opcode::ThrowValue } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ExceptionOperand))) and - result instanceof IndirectMemoryAccess - } - - /** * Gets the address of the exception thrown by this instruction. */ final Instruction getExceptionAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } /** * Gets the exception thrown by this instruction. */ final Instruction getException() { - result = getOperand(exceptionOperand()) + result = getAnOperand().(ExceptionOperand).getDefinitionInstruction() } } @@ -1236,11 +1197,6 @@ class UnmodeledUseInstruction extends Instruction { override string getOperandsString() { result = "mu*" } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(UnmodeledUseOperand))) and - result instanceof UnmodeledMemoryAccess - } } class PhiInstruction extends Instruction { @@ -1248,11 +1204,6 @@ class PhiInstruction extends Instruction { opcode instanceof Opcode::Phi } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(PhiOperand))) and - result instanceof PhiMemoryAccess - } - override final MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll new file mode 100644 index 000000000000..4cc82d0906ca --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -0,0 +1,360 @@ +private import internal.IRInternal +import Instruction +import IRBlock +import cpp +import semmle.code.cpp.ir.implementation.MemoryAccessKind +private import semmle.code.cpp.ir.internal.OperandTag + +private newtype TOperand = + TNonPhiOperand(Instruction instr, OperandTag tag, Instruction defInstr) { + defInstr = Construction::getInstructionOperandDefinition(instr, tag) + } or + TPhiOperand(PhiInstruction instr, Instruction defInstr, IRBlock predecessorBlock) { + defInstr = Construction::getPhiInstructionOperandDefinition(instr, predecessorBlock) + } + +/** + * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + */ +class Operand extends TOperand { + string toString() { + result = "Operand" + } + + /** + * Gets the `Instruction` that consumes this operand. + */ + Instruction getInstruction() { + none() + } + + /** + * Gets the `Instruction` whose result is the value of the operand. + */ + Instruction getDefinitionInstruction() { + none() + } + + /** + * Gets a prefix to use when dumping the operand in an operand list. + */ + string getDumpLabel() { + result = "" + } + + /** + * Gets a string describing this operand, suitable for display in IR dumps. This consists of the + * result ID of the instruction consumed by the operand, plus a label identifying the operand + * kind. + * + * For example: `this:r3_5` + */ + final string getDumpString() { + result = getDumpLabel() + getDefinitionInstruction().getResultId() + } + + /** + * Get the order in which the operand should be sorted in the operand list. + */ + int getDumpSortOrder() { + result = -1 + } + + /** + * Gets the kind of memory access performed by the operand. Holds only for memory operands. + */ + MemoryAccessKind getMemoryAccess() { + none() + } + + /** + * Returns the operand that holds the memory address from which the current operand loads its + * value, if any. For example, in `r3 = Load r1, m2`, the result of `getAddressOperand()` for `m2` + * is `r1`. + */ + final AddressOperand getAddressOperand() { + getMemoryAccess() instanceof IndirectMemoryAccess and + result.getInstruction() = getInstruction() + } +} + +/** + * An operand that is not an operand of a `PhiInstruction`. + */ +class NonPhiOperand extends Operand, TNonPhiOperand { + Instruction instr; + Instruction defInstr; + OperandTag tag; + + NonPhiOperand() { + this = TNonPhiOperand(instr, tag, defInstr) + } + + override final Instruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final string getDumpLabel() { + result = tag.getLabel() + } + + override final int getDumpSortOrder() { + result = tag.getSortOrder() + } + + final OperandTag getOperandTag() { + result = tag + } +} + +/** + * The address operand of an instruction that loads or stores a value from + * memory (e.g. `Load`, `Store`). + */ +class AddressOperand extends NonPhiOperand { + AddressOperand() { + this = TNonPhiOperand(_, addressOperand(), _) + } + + override string toString() { + result = "Address" + } +} + +/** + * The source value operand of an instruction that copies this value to its + * result (e.g. `Copy`, `Load`, `Store`). + */ +class CopySourceOperand extends NonPhiOperand { + CopySourceOperand() { + this = TNonPhiOperand(_, copySourceOperand(), _) + } + + override string toString() { + result = "CopySource" + } + + override final MemoryAccessKind getMemoryAccess() { + instr.getOpcode() instanceof Opcode::Load and + result instanceof IndirectMemoryAccess + } +} + +/** + * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). + */ +class UnaryOperand extends NonPhiOperand { + UnaryOperand() { + this = TNonPhiOperand(_, unaryOperand(), _) + } + + override string toString() { + result = "Unary" + } +} + +/** + * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class LeftOperand extends NonPhiOperand { + LeftOperand() { + this = TNonPhiOperand(_, leftOperand(), _) + } + + override string toString() { + result = "Left" + } +} + +/** + * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class RightOperand extends NonPhiOperand { + RightOperand() { + this = TNonPhiOperand(_, rightOperand(), _) + } + + override string toString() { + result = "Right" + } +} + +/** + * The return value operand of a `ReturnValue` instruction. + */ +class ReturnValueOperand extends NonPhiOperand { + ReturnValueOperand() { + this = TNonPhiOperand(_, returnValueOperand(), _) + } + + override string toString() { + result = "ReturnValue" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The exception thrown by a `ThrowValue` instruction. + */ +class ExceptionOperand extends NonPhiOperand { + ExceptionOperand() { + this = TNonPhiOperand(_, exceptionOperand(), _) + } + + override string toString() { + result = "Exception" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The condition operand of a `ConditionalBranch` or `Switch` instruction. + */ +class ConditionOperand extends NonPhiOperand { + ConditionOperand() { + this = TNonPhiOperand(_, conditionOperand(), _) + } + + override string toString() { + result = "Condition" + } +} + +/** + * An operand of the special `UnmodeledUse` instruction, representing a value + * whose set of uses is unknown. + */ +class UnmodeledUseOperand extends NonPhiOperand { + UnmodeledUseOperand() { + this = TNonPhiOperand(_, unmodeledUseOperand(), _) + } + + override string toString() { + result = "UnmodeledUse" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof UnmodeledMemoryAccess + } +} + +/** + * The operand representing the target function of an `Call` instruction. + */ +class CallTargetOperand extends NonPhiOperand { + CallTargetOperand() { + this = TNonPhiOperand(_, callTargetOperand(), _) + } + + override string toString() { + result = "CallTarget" + } +} + +/** + * An operand representing an argument to a function call. This includes both + * positional arguments (represented by `PositionalArgumentOperand`) and the + * implicit `this` argument, if any (represented by `ThisArgumentOperand`). + */ +class ArgumentOperand extends NonPhiOperand { + ArgumentOperand() { + exists(ArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) + ) + } +} + +/** + * An operand representing the implicit 'this' argument to a member function + * call. + */ +class ThisArgumentOperand extends ArgumentOperand { + ThisArgumentOperand() { + this = TNonPhiOperand(_, thisArgumentOperand(), _) + } + + override string toString() { + result = "ThisArgument" + } +} + +/** + * An operand representing an argument to a function call. + */ +class PositionalArgumentOperand extends ArgumentOperand { + int argIndex; + + PositionalArgumentOperand() { + exists(PositionalArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) and + argIndex = argTag.getArgIndex() + ) + } + + override string toString() { + result = "Arg(" + argIndex + ")" + } +} + +/** + * An operand of a `PhiInstruction`. + */ +class PhiOperand extends Operand, TPhiOperand { + PhiInstruction instr; + Instruction defInstr; + IRBlock predecessorBlock; + + PhiOperand() { + this = TPhiOperand(instr, defInstr, predecessorBlock) + } + + override string toString() { + result = "Phi" + } + + override final PhiInstruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final int getDumpSortOrder() { + result = 11 + getPredecessorBlock().getDisplayIndex() + } + + override final string getDumpLabel() { + result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + /** + * Gets the predecessor block from which this value comes. + */ + final IRBlock getPredecessorBlock() { + result = predecessorBlock + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof PhiMemoryAccess + } +} + +/** + * An operand that reads a value from memory. + */ +class MemoryOperand extends Operand { + MemoryOperand() { + exists(getMemoryAccess()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index f3be51b63d2d..fb897afa58d6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -46,18 +46,20 @@ private IntValue getFieldBitOffset(Field field) { * not result in any address held in that operand from escaping beyond the * instruction. */ -predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - ( - // The source/destination address of a Load/Store does not escape (but the - // loaded/stored value could). - tag instanceof LoadStoreAddressOperand or - // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or - // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or - // Converting an address to a `bool` does not escape the address. - instr.(ConvertInstruction).getResultType() instanceof BoolType +predicate operandIsConsumedWithoutEscaping(Operand operand) { + // The source/destination address of a Load/Store does not escape (but the + // loaded/stored value could). + operand instanceof AddressOperand or + exists (Instruction instr | + instr = operand.getInstruction() and + ( + // Neither operand of a Compare escapes. + instr instanceof CompareInstruction or + // Neither operand of a PointerDiff escapes. + instr instanceof PointerDiffInstruction or + // Converting an address to a `bool` does not escape the address. + instr.(ConvertInstruction).getResultType() instanceof BoolType + ) ) } @@ -96,43 +98,44 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { * `bitOffset`. If the address is propagated, but the offset is not known to be * a constant, then `bitOffset` is unknown. */ -predicate operandIsPropagated(Instruction instr, OperandTag tag, - IntValue bitOffset) { - exists(instr.getOperand(tag)) and - ( - // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | - convert = instr and - bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or - // Converting to a derived class subtracts the offset of the base class. - exists(ConvertToDerivedInstruction convert | - convert = instr and - bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or - // Converting to a virtual base class adds an unknown offset. +predicate operandIsPropagated(Operand operand, IntValue bitOffset) { + exists(Instruction instr | + instr = operand.getInstruction() and ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or - // Conversion to another pointer type propagates the source address. - exists(ConvertInstruction convert, Type resultType | - convert = instr and - resultType = convert.getResultType() and + // Converting to a non-virtual base class adds the offset of the base class. + exists(ConvertToBaseInstruction convert | + convert = instr and + bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) + ) or + // Converting to a derived class subtracts the offset of the base class. + exists(ConvertToDerivedInstruction convert | + convert = instr and + bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) + ) or + // Converting to a virtual base class adds an unknown offset. ( - resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers - ) and - bitOffset = 0 - ) or - // Adding an integer to or subtracting an integer from a pointer propagates - // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or - // Computing a field address from a pointer propagates the address plus the - // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or - // A copy propagates the source value. - tag instanceof CopySourceOperand and bitOffset = 0 + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + ) or + // Conversion to another pointer type propagates the source address. + exists(ConvertInstruction convert, Type resultType | + convert = instr and + resultType = convert.getResultType() and + ( + resultType instanceof PointerType or + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + ) and + bitOffset = 0 + ) or + // Adding an integer to or subtracting an integer from a pointer propagates + // the address with an offset. + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + // Computing a field address from a pointer propagates the address plus the + // offset of the field. + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + // A copy propagates the source value. + operand instanceof CopySourceOperand and bitOffset = 0 + ) ) } @@ -140,16 +143,15 @@ predicate operandIsPropagated(Instruction instr, OperandTag tag, * Holds if any address held in operand number `tag` of instruction `instr` * escapes outside the domain of the analysis. */ -predicate operandEscapes(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and +predicate operandEscapes(Operand operand) { // Conservatively assume that the address escapes unless one of the following // holds: not ( // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(instr, tag) or + operandIsConsumedWithoutEscaping(operand) or // The address is propagated to the result of the instruction, but that // result does not itself escape. - operandIsPropagated(instr, tag, _) and not resultEscapes(instr) + operandIsPropagated(operand, _) and not resultEscapes(operand.getInstruction()) ) } @@ -159,10 +161,7 @@ predicate operandEscapes(Instruction instr, OperandTag tag) { */ predicate resultEscapes(Instruction instr) { // The result escapes if it has at least one use that escapes. - exists(Instruction useInstr, OperandTag useOperandTag | - useInstr.getOperand(useOperandTag) = instr and - operandEscapes(useInstr, useOperandTag) - ) + operandEscapes(instr.getAUse()) } /** @@ -203,12 +202,12 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getVariable() = var and bitOffset = 0 ) or - exists(OperandTag operandTag, IntValue originalBitOffset, - IntValue propagatedBitOffset | + exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | + operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, // offset by the bit offset from the propagation. - resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and - operandIsPropagated(instr, operandTag, propagatedBitOffset) and + resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and + operandIsPropagated(operand, propagatedBitOffset) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 70af6ce64138..5dbf34cb6c32 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -1,30 +1,13 @@ import SSAConstructionInternal import cpp private import semmle.code.cpp.ir.implementation.Opcode -import NewIR +private import semmle.code.cpp.ir.internal.OperandTag +private import NewIR import IRBlockConstruction as BlockConstruction import Cached cached private module Cached { - private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { - newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or - newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or - newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or - newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or - newTag instanceof RightOperand and result instanceof OldIR::RightOperand or - newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or - newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or - newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or - newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or - newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or - newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or - exists(PositionalArgumentOperand newArg | - newArg = newTag and - result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() - ) - } - private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) } @@ -49,14 +32,6 @@ cached private module Cached { ) } - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(OldIR::PositionalArgumentOperand oldOperand | - argIndex = oldOperand.getArgIndex() - ) - ) - } - cached OldIR::Instruction getOldInstruction(Instruction instr) { instr.getTag() = WrappedInstructionTag(result) } @@ -135,18 +110,19 @@ cached private module Cached { instruction instanceof PhiInstruction // Phis always have modeled results } - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { - exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | - oldUse = getOldInstruction(instruction) and - oldTag = getOldOperandTag(tag) and - if oldUse.isMemoryOperand(oldTag) then ( + cached Instruction getInstructionOperandDefinition(Instruction instruction, OperandTag tag) { + exists(OldIR::Instruction oldInstruction, OldIR::NonPhiOperand oldOperand | + oldInstruction = getOldInstruction(instruction) and + oldOperand = oldInstruction.getAnOperand() and + tag = oldOperand.getOperandTag() and + if oldOperand instanceof OldIR::MemoryOperand then ( ( - if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( + if exists(Alias::getOperandMemoryAccess(oldOperand)) then ( exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, int defIndex | - vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and + vvar = Alias::getOperandMemoryAccess(oldOperand).getVirtualVariable() and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - hasUseAtRank(vvar, useBlock, useRank, oldUse) and + hasUseAtRank(vvar, useBlock, useRank, oldInstruction) and definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and if defIndex >= 0 then result = getNewInstruction(defBlock.getInstruction(defIndex)) @@ -162,25 +138,25 @@ cached private module Cached { // `UnmodeledUse` instruction. exists(OldIR::Instruction oldDefinition | instruction instanceof UnmodeledUseInstruction and - tag instanceof UnmodeledUseOperand and - oldDefinition = oldUse.getOperand(oldTag) and + tag instanceof UnmodeledUseOperandTag and + oldDefinition = oldOperand.getDefinitionInstruction() and not exists(Alias::getResultMemoryAccess(oldDefinition)) and result = getNewInstruction(oldDefinition) ) ) else - result = getNewInstruction(oldUse.getOperand(oldTag)) - ) or - result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) + result = getNewInstruction(oldOperand.getDefinitionInstruction()) + ) } - cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { + cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr, + IRBlock newPredecessorBlock) { exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | hasPhiNode(vvar, phiBlock) and predBlock = phiBlock.getAPredecessor() and instr.getTag() = PhiTag(vvar, phiBlock) and - tag.getPredecessorBlock() = getNewBlock(predBlock) and + newPredecessorBlock = getNewBlock(predBlock) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and if defIndex >= 0 then @@ -277,7 +253,7 @@ cached private module Cached { private predicate hasUse(Alias::VirtualVariable vvar, OldIR::Instruction use, OldIR::IRBlock block, int index) { exists(Alias::MemoryAccess access | - access = Alias::getOperandMemoryAccess(use, _) and + access = Alias::getOperandMemoryAccess(use.getAnOperand()) and block.getInstruction(index) = use and vvar = access.getVirtualVariable() ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll index a2d8f3532ac7..fdf596267a90 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll @@ -2,7 +2,8 @@ import SimpleSSAInternal import cpp import Alias private import InputIR -import semmle.code.cpp.ir.internal.Overlap +private import semmle.code.cpp.ir.internal.OperandTag +private import semmle.code.cpp.ir.internal.Overlap private newtype TVirtualVariable = MkVirtualVariable(IRVariable var) { @@ -69,15 +70,15 @@ Overlap getOverlap(MemoryAccess def, MemoryAccess use) { MemoryAccess getResultMemoryAccess(Instruction instr) { exists(IRVariable var | instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), + var, 0) and result = getMemoryAccess(var) ) } -MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { +MemoryAccess getOperandMemoryAccess(Operand operand) { exists(IRVariable var | - instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, 0) and result = getMemoryAccess(var) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll index 5e84762e7eb8..3fc7e0691258 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll @@ -2,7 +2,7 @@ import FunctionIR import Instruction import IRBlock import IRVariable -import OperandTag +import Operand import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 4603cf498481..c95cb23814e6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -2,12 +2,13 @@ private import internal.IRInternal import FunctionIR import IRBlock import IRVariable -import OperandTag +import Operand import cpp import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind import semmle.code.cpp.ir.implementation.Opcode private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag class InstructionTag = Construction::InstructionTagType; @@ -22,21 +23,21 @@ module InstructionSanity { exists(Opcode opcode | opcode = instr.getOpcode() and ( - opcode instanceof UnaryOpcode and tag instanceof UnaryOperand or + opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag or ( opcode instanceof BinaryOpcode and ( - tag instanceof LeftOperand or - tag instanceof RightOperand + tag instanceof LeftOperandTag or + tag instanceof RightOperandTag ) ) or - opcode instanceof CopyOpcode and tag instanceof CopySourceOperand or - opcode instanceof MemoryAccessOpcode and tag instanceof LoadStoreAddressOperand or - opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperand or - opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperand or - opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperand or - opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperand or - opcode instanceof Opcode::Call and tag instanceof CallTargetOperand + opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or + opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or + opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or + opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or + opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or + opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or + opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag ) ) } @@ -45,26 +46,34 @@ module InstructionSanity { * Holds if instruction `instr` is missing an expected operand with tag `tag`. */ query predicate missingOperand(Instruction instr, OperandTag tag) { - expectsOperand(instr, tag) and not exists(instr.getOperand(tag)) + expectsOperand(instr, tag) and + not exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) } /** * Holds if instruction `instr` has an unexpected operand with tag `tag`. */ query predicate unexpectedOperand(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and + exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag) and not expectsOperand(instr, tag) and - not (instr instanceof CallInstruction and tag instanceof ArgumentOperand) and - not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperand) and - not (instr instanceof PhiInstruction and tag instanceof PhiOperand) + not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and + not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) } /** * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - strictcount(instr.getOperand(tag)) > 1 and - not tag instanceof UnmodeledUseOperand + strictcount(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) > 1 and + not tag instanceof UnmodeledUseOperandTag } /** @@ -74,7 +83,7 @@ module InstructionSanity { query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) { pred = instr.getBlock().getAPredecessor() and not exists(PhiOperand operand | - exists(instr.getOperand(operand)) and + operand = instr.getAnOperand() and operand.getPredecessorBlock() = pred ) } @@ -98,14 +107,13 @@ module InstructionSanity { } /** - * Holds if instruction `op` consumes an operand `operand` that was defined in + * Holds if operand `operand` consumes a value that was defined in * a different function. */ - query predicate operandAcrossFunctions( - Instruction op, Instruction operand, OperandTag tag - ) { - operand = op.getOperand(tag) and - operand.getFunctionIR() != op.getFunctionIR() + query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) { + operand.getInstruction() = instr and + operand.getDefinitionInstruction() = defInstr and + instr.getFunctionIR() != defInstr.getFunctionIR() } /** @@ -246,20 +254,6 @@ class Instruction extends Construction::TInstruction { result = getResultId() + "(" + getResultTypeString() + ")" } - /** - * Gets a string describing the specified operand, suitable for display in IR - * dumps. This consists of the result ID of the instruction consumed by the - * operand, plus a label identifying the operand kind. - * - * For example: `this:r3_5` - */ - string getOperandString(OperandTag tag) { - exists(Instruction operand | - operand = getOperand(tag) and - result = tag.getLabel() + operand.getResultId() - ) - } - /** * Gets a string describing the operands of this instruction, suitable for * display in IR dumps. @@ -267,9 +261,9 @@ class Instruction extends Construction::TInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - result = concat(OperandTag tag, Instruction operand | - operand = getOperand(tag) | - tag.getLabel() + operand.getResultId(), ", " order by tag.getSortOrder() + result = concat(Operand operand | + operand = getAnOperand() | + operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) } @@ -333,7 +327,6 @@ class Instruction extends Construction::TInstruction { result = Construction::getInstructionUnconvertedResultExpression(this) } - /** * Gets the type of the result produced by this instruction. If the * instruction does not produce a result, its result type will be `VoidType`. @@ -397,35 +390,19 @@ class Instruction extends Construction::TInstruction { } /** - * Gets the instruction that produced the value of the specified source - * operand. - */ - final Instruction getOperand(OperandTag tag) { - result = Construction::getInstructionOperand(this, tag) - } - - /** - * Gets all instructions consumed by this instruction's operands. + * Gets all direct uses of the result of this instruction. */ - final Instruction getAnOperand() { - result = getOperand(_) + final Operand getAUse() { + result.getDefinitionInstruction() = this } /** - * Holds if this instruction has a memory operand with the specified tag. + * Gets all of this instruction's operands. */ - final predicate isMemoryOperand(OperandTag tag) { - exists(getOperandMemoryAccess(tag)) + final Operand getAnOperand() { + result.getInstruction() = this } - /** - * Gets the kind of memory access performed by the specified operand. Holds - * only for memory operands. - */ - MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - none() - } - /** * Holds if this instruction produces a memory result. */ @@ -461,9 +438,7 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(Instruction useInstr, UnmodeledUseOperand useTag | - this = useInstr.getOperand(useTag) - ) + not (getAUse() instanceof UnmodeledUseOperand) } /** @@ -602,7 +577,7 @@ class FieldAddressInstruction extends FieldInstruction { } final Instruction getObjectAddress() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -640,12 +615,7 @@ class ReturnValueInstruction extends ReturnInstruction { } final Instruction getReturnValue() { - result = getOperand(returnValueOperand()) - } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ReturnValueOperand))) and - result instanceof IndirectMemoryAccess + result = getAnOperand().(ReturnValueOperand).getDefinitionInstruction() } } @@ -655,7 +625,7 @@ class CopyInstruction extends Instruction { } final Instruction getSourceValue() { - result = getOperand(copySourceOperand()) + result = getAnOperand().(CopySourceOperand).getDefinitionInstruction() } } @@ -670,13 +640,8 @@ class LoadInstruction extends CopyInstruction { opcode instanceof Opcode::Load } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(CopySourceOperand))) and - result instanceof IndirectMemoryAccess - } - final Instruction getSourceAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -690,7 +655,7 @@ class StoreInstruction extends CopyInstruction { } final Instruction getDestinationAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -700,7 +665,7 @@ class ConditionalBranchInstruction extends Instruction { } final Instruction getCondition() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getTrueSuccessor() { @@ -758,11 +723,11 @@ class BinaryInstruction extends Instruction { } final Instruction getLeftOperand() { - result = getOperand(leftOperand()) + result = getAnOperand().(LeftOperand).getDefinitionInstruction() } final Instruction getRightOperand() { - result = getOperand(rightOperand()) + result = getAnOperand().(RightOperand).getDefinitionInstruction() } } @@ -873,7 +838,7 @@ class UnaryInstruction extends Instruction { } final Instruction getOperand() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -992,6 +957,7 @@ class RelationalInstruction extends CompareInstruction { RelationalInstruction() { opcode instanceof RelationalOpcode } + /** * Gets the operand on the "greater" (or "greater-or-equal") side * of this relational instruction, that is, the side that is larger @@ -1011,6 +977,7 @@ class RelationalInstruction extends CompareInstruction { Instruction getLesserOperand() { none() } + /** * Holds if this relational instruction is strict (is not an "or-equal" instruction). */ @@ -1097,7 +1064,7 @@ class SwitchInstruction extends Instruction { } final Instruction getExpression() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getACaseSuccessor() { @@ -1117,7 +1084,7 @@ class CallInstruction extends Instruction { } final Instruction getCallTarget() { - result = getOperand(callTargetOperand()) + result = getAnOperand().(CallTargetOperand).getDefinitionInstruction() } } @@ -1138,24 +1105,18 @@ class ThrowValueInstruction extends ThrowInstruction { opcode instanceof Opcode::ThrowValue } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ExceptionOperand))) and - result instanceof IndirectMemoryAccess - } - - /** * Gets the address of the exception thrown by this instruction. */ final Instruction getExceptionAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } /** * Gets the exception thrown by this instruction. */ final Instruction getException() { - result = getOperand(exceptionOperand()) + result = getAnOperand().(ExceptionOperand).getDefinitionInstruction() } } @@ -1236,11 +1197,6 @@ class UnmodeledUseInstruction extends Instruction { override string getOperandsString() { result = "mu*" } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(UnmodeledUseOperand))) and - result instanceof UnmodeledMemoryAccess - } } class PhiInstruction extends Instruction { @@ -1248,11 +1204,6 @@ class PhiInstruction extends Instruction { opcode instanceof Opcode::Phi } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(PhiOperand))) and - result instanceof PhiMemoryAccess - } - override final MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll new file mode 100644 index 000000000000..4cc82d0906ca --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -0,0 +1,360 @@ +private import internal.IRInternal +import Instruction +import IRBlock +import cpp +import semmle.code.cpp.ir.implementation.MemoryAccessKind +private import semmle.code.cpp.ir.internal.OperandTag + +private newtype TOperand = + TNonPhiOperand(Instruction instr, OperandTag tag, Instruction defInstr) { + defInstr = Construction::getInstructionOperandDefinition(instr, tag) + } or + TPhiOperand(PhiInstruction instr, Instruction defInstr, IRBlock predecessorBlock) { + defInstr = Construction::getPhiInstructionOperandDefinition(instr, predecessorBlock) + } + +/** + * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + */ +class Operand extends TOperand { + string toString() { + result = "Operand" + } + + /** + * Gets the `Instruction` that consumes this operand. + */ + Instruction getInstruction() { + none() + } + + /** + * Gets the `Instruction` whose result is the value of the operand. + */ + Instruction getDefinitionInstruction() { + none() + } + + /** + * Gets a prefix to use when dumping the operand in an operand list. + */ + string getDumpLabel() { + result = "" + } + + /** + * Gets a string describing this operand, suitable for display in IR dumps. This consists of the + * result ID of the instruction consumed by the operand, plus a label identifying the operand + * kind. + * + * For example: `this:r3_5` + */ + final string getDumpString() { + result = getDumpLabel() + getDefinitionInstruction().getResultId() + } + + /** + * Get the order in which the operand should be sorted in the operand list. + */ + int getDumpSortOrder() { + result = -1 + } + + /** + * Gets the kind of memory access performed by the operand. Holds only for memory operands. + */ + MemoryAccessKind getMemoryAccess() { + none() + } + + /** + * Returns the operand that holds the memory address from which the current operand loads its + * value, if any. For example, in `r3 = Load r1, m2`, the result of `getAddressOperand()` for `m2` + * is `r1`. + */ + final AddressOperand getAddressOperand() { + getMemoryAccess() instanceof IndirectMemoryAccess and + result.getInstruction() = getInstruction() + } +} + +/** + * An operand that is not an operand of a `PhiInstruction`. + */ +class NonPhiOperand extends Operand, TNonPhiOperand { + Instruction instr; + Instruction defInstr; + OperandTag tag; + + NonPhiOperand() { + this = TNonPhiOperand(instr, tag, defInstr) + } + + override final Instruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final string getDumpLabel() { + result = tag.getLabel() + } + + override final int getDumpSortOrder() { + result = tag.getSortOrder() + } + + final OperandTag getOperandTag() { + result = tag + } +} + +/** + * The address operand of an instruction that loads or stores a value from + * memory (e.g. `Load`, `Store`). + */ +class AddressOperand extends NonPhiOperand { + AddressOperand() { + this = TNonPhiOperand(_, addressOperand(), _) + } + + override string toString() { + result = "Address" + } +} + +/** + * The source value operand of an instruction that copies this value to its + * result (e.g. `Copy`, `Load`, `Store`). + */ +class CopySourceOperand extends NonPhiOperand { + CopySourceOperand() { + this = TNonPhiOperand(_, copySourceOperand(), _) + } + + override string toString() { + result = "CopySource" + } + + override final MemoryAccessKind getMemoryAccess() { + instr.getOpcode() instanceof Opcode::Load and + result instanceof IndirectMemoryAccess + } +} + +/** + * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). + */ +class UnaryOperand extends NonPhiOperand { + UnaryOperand() { + this = TNonPhiOperand(_, unaryOperand(), _) + } + + override string toString() { + result = "Unary" + } +} + +/** + * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class LeftOperand extends NonPhiOperand { + LeftOperand() { + this = TNonPhiOperand(_, leftOperand(), _) + } + + override string toString() { + result = "Left" + } +} + +/** + * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class RightOperand extends NonPhiOperand { + RightOperand() { + this = TNonPhiOperand(_, rightOperand(), _) + } + + override string toString() { + result = "Right" + } +} + +/** + * The return value operand of a `ReturnValue` instruction. + */ +class ReturnValueOperand extends NonPhiOperand { + ReturnValueOperand() { + this = TNonPhiOperand(_, returnValueOperand(), _) + } + + override string toString() { + result = "ReturnValue" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The exception thrown by a `ThrowValue` instruction. + */ +class ExceptionOperand extends NonPhiOperand { + ExceptionOperand() { + this = TNonPhiOperand(_, exceptionOperand(), _) + } + + override string toString() { + result = "Exception" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The condition operand of a `ConditionalBranch` or `Switch` instruction. + */ +class ConditionOperand extends NonPhiOperand { + ConditionOperand() { + this = TNonPhiOperand(_, conditionOperand(), _) + } + + override string toString() { + result = "Condition" + } +} + +/** + * An operand of the special `UnmodeledUse` instruction, representing a value + * whose set of uses is unknown. + */ +class UnmodeledUseOperand extends NonPhiOperand { + UnmodeledUseOperand() { + this = TNonPhiOperand(_, unmodeledUseOperand(), _) + } + + override string toString() { + result = "UnmodeledUse" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof UnmodeledMemoryAccess + } +} + +/** + * The operand representing the target function of an `Call` instruction. + */ +class CallTargetOperand extends NonPhiOperand { + CallTargetOperand() { + this = TNonPhiOperand(_, callTargetOperand(), _) + } + + override string toString() { + result = "CallTarget" + } +} + +/** + * An operand representing an argument to a function call. This includes both + * positional arguments (represented by `PositionalArgumentOperand`) and the + * implicit `this` argument, if any (represented by `ThisArgumentOperand`). + */ +class ArgumentOperand extends NonPhiOperand { + ArgumentOperand() { + exists(ArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) + ) + } +} + +/** + * An operand representing the implicit 'this' argument to a member function + * call. + */ +class ThisArgumentOperand extends ArgumentOperand { + ThisArgumentOperand() { + this = TNonPhiOperand(_, thisArgumentOperand(), _) + } + + override string toString() { + result = "ThisArgument" + } +} + +/** + * An operand representing an argument to a function call. + */ +class PositionalArgumentOperand extends ArgumentOperand { + int argIndex; + + PositionalArgumentOperand() { + exists(PositionalArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) and + argIndex = argTag.getArgIndex() + ) + } + + override string toString() { + result = "Arg(" + argIndex + ")" + } +} + +/** + * An operand of a `PhiInstruction`. + */ +class PhiOperand extends Operand, TPhiOperand { + PhiInstruction instr; + Instruction defInstr; + IRBlock predecessorBlock; + + PhiOperand() { + this = TPhiOperand(instr, defInstr, predecessorBlock) + } + + override string toString() { + result = "Phi" + } + + override final PhiInstruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final int getDumpSortOrder() { + result = 11 + getPredecessorBlock().getDisplayIndex() + } + + override final string getDumpLabel() { + result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + /** + * Gets the predecessor block from which this value comes. + */ + final IRBlock getPredecessorBlock() { + result = predecessorBlock + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof PhiMemoryAccess + } +} + +/** + * An operand that reads a value from memory. + */ +class MemoryOperand extends Operand { + MemoryOperand() { + exists(getMemoryAccess()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/OperandTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/OperandTag.qll deleted file mode 100644 index df78fd90cd96..000000000000 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/OperandTag.qll +++ /dev/null @@ -1,312 +0,0 @@ -private import internal.IRInternal -import Instruction -import IRBlock -import cpp - -private newtype TOperandTag = - TLoadStoreAddressOperand() or - TCopySourceOperand() or - TUnaryOperand() or - TLeftOperand() or - TRightOperand() or - TReturnValueOperand() or - TExceptionOperand() or - TConditionOperand() or - TUnmodeledUseOperand() or - TCallTargetOperand() or - TThisArgumentOperand() or - TPositionalArgumentOperand(int argIndex) { - argIndex in [0..Construction::getMaxCallArgIndex()] or - exists(BuiltInOperation op | - exists(op.getChild(argIndex)) - ) - } or - TPhiOperand(IRBlock predecessorBlock) { - exists(PhiInstruction phi | - predecessorBlock = Construction::getPhiInstructionBlockStart(phi).getBlock().getAPredecessor() - ) - } - -/** - * Identifies the kind of operand on an instruction. Each `Instruction` has at - * most one operand of any single `OperandTag`. The set of `OperandTag`s used by - * an `Instruction` is determined by the instruction's opcode. - */ -abstract class OperandTag extends TOperandTag { - abstract string toString(); - - abstract int getSortOrder(); - - string getLabel() { - result = "" - } -} - -// Note: individual subtypes are listed in the order that the operands should -// appear in the operand list of the instruction when printing. - -/** - * The address operand of an instruction that loads or stores a value from - * memory (e.g. `Load`, `Store`). - */ -class LoadStoreAddressOperand extends OperandTag, TLoadStoreAddressOperand { - override final string toString() { - result = "LoadStoreAddress" - } - - override final int getSortOrder() { - result = 0 - } -} - -LoadStoreAddressOperand loadStoreAddressOperand() { - result = TLoadStoreAddressOperand() -} - -/** - * The source value operand of an instruction that copies this value to its - * result (e.g. `Copy`, `Load`, `Store`). - */ -class CopySourceOperand extends OperandTag, TCopySourceOperand { - override final string toString() { - result = "CopySource" - } - - override final int getSortOrder() { - result = 1 - } -} - -CopySourceOperand copySourceOperand() { - result = TCopySourceOperand() -} - -/** - * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). - */ -class UnaryOperand extends OperandTag, TUnaryOperand { - override final string toString() { - result = "Unary" - } - - override final int getSortOrder() { - result = 2 - } -} - -UnaryOperand unaryOperand() { - result = TUnaryOperand() -} - -/** - * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). - */ -class LeftOperand extends OperandTag, TLeftOperand { - override final string toString() { - result = "Left" - } - - override final int getSortOrder() { - result = 3 - } -} - -LeftOperand leftOperand() { - result = TLeftOperand() -} - -/** - * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). - */ -class RightOperand extends OperandTag, TRightOperand { - override final string toString() { - result = "Right" - } - - override final int getSortOrder() { - result = 4 - } -} - -RightOperand rightOperand() { - result = TRightOperand() -} - -/** - * The return value operand of a `ReturnValue` instruction. - */ -class ReturnValueOperand extends OperandTag, TReturnValueOperand { - override final string toString() { - result = "ReturnValue" - } - - override final int getSortOrder() { - result = 5 - } -} - -ReturnValueOperand returnValueOperand() { - result = TReturnValueOperand() -} - -/** - * The exception thrown by a `ThrowValue` instruction. - */ -class ExceptionOperand extends OperandTag, TExceptionOperand { - override final string toString() { - result = "Exception" - } - - override final int getSortOrder() { - result = 6 - } -} - -ExceptionOperand exceptionOperand() { - result = TExceptionOperand() -} - -/** - * The condition operand of a `ConditionalBranch` or `Switch` instruction. - */ -class ConditionOperand extends OperandTag, TConditionOperand { - override final string toString() { - result = "Condition" - } - - override final int getSortOrder() { - result = 7 - } -} - -ConditionOperand conditionOperand() { - result = TConditionOperand() -} - -/** - * An operand of the special `UnmodeledUse` instruction, representing a value - * whose set of uses is unknown. - */ -class UnmodeledUseOperand extends OperandTag, TUnmodeledUseOperand { - override final string toString() { - result = "UnmodeledUse" - } - - override final int getSortOrder() { - result = 8 - } -} - -UnmodeledUseOperand unmodeledUseOperand() { - result = TUnmodeledUseOperand() -} - -/** - * The operand representing the target function of an `Call` instruction. - */ -class CallTargetOperand extends OperandTag, TCallTargetOperand { - override final string toString() { - result = "CallTarget" - } - - override final int getSortOrder() { - result = 9 - } -} - -CallTargetOperand callTargetOperand() { - result = TCallTargetOperand() -} - -/** - * An operand representing an argument to a function call. This includes both - * positional arguments (represented by `PositionalArgumentOperand`) and the - * implicit `this` argument, if any (represented by `ThisArgumentOperand`). - */ -abstract class ArgumentOperand extends OperandTag { -} - -/** - * An operand representing the implicit 'this' argument to a member function - * call. - */ -class ThisArgumentOperand extends ArgumentOperand, TThisArgumentOperand { - ThisArgumentOperand() { - this = TThisArgumentOperand() - } - - override final string toString() { - result = "Arg(this)" - } - - override final int getSortOrder() { - result = 10 - } - - override final string getLabel() { - result = "this:" - } -} - -ThisArgumentOperand thisArgumentOperand() { - result = TThisArgumentOperand() -} - -/** - * An operand representing an argument to a function call. - */ -class PositionalArgumentOperand extends ArgumentOperand, - TPositionalArgumentOperand { - int argIndex; - - PositionalArgumentOperand() { - this = TPositionalArgumentOperand(argIndex) - } - - override final string toString() { - result = "Arg(" + argIndex + ")" - } - - override final int getSortOrder() { - result = 11 + argIndex - } - - final int getArgIndex() { - result = argIndex - } -} - -PositionalArgumentOperand positionalArgumentOperand(int argIndex) { - result = TPositionalArgumentOperand(argIndex) -} - -/** - * An operand of an SSA `Phi` instruction. - */ -class PhiOperand extends OperandTag, TPhiOperand { - IRBlock predecessorBlock; - - PhiOperand() { - this = TPhiOperand(predecessorBlock) - } - - override final string toString() { - result = "Phi" - } - - override final int getSortOrder() { - result = 11 + getPredecessorBlock().getDisplayIndex() - } - - override final string getLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" - } - - final IRBlock getPredecessorBlock() { - result = predecessorBlock - } -} - -PhiOperand phiOperand(IRBlock predecessorBlock) { - result = TPhiOperand(predecessorBlock) -} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index d8c14c0f9508..9fdece58e41e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -1,6 +1,7 @@ import cpp import semmle.code.cpp.ir.implementation.raw.IR import IRBlockConstruction as BlockConstruction +private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedElement @@ -37,14 +38,6 @@ cached private module Cached { exists(getTranslatedFunction(func)) } - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(FunctionCall call | - exists(call.getArgument(argIndex)) - ) - ) - } - cached newtype TInstruction = MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, InstructionTag tag, Type resultType, boolean isGLValue) { @@ -93,11 +86,16 @@ cached private module Cached { ) } - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { + cached Instruction getInstructionOperandDefinition(Instruction instruction, OperandTag tag) { result = getInstructionTranslatedElement(instruction).getInstructionOperand( instruction.getTag(), tag) } + cached Instruction getPhiInstructionOperandDefinition(Instruction instruction, + IRBlock predecessorBlock) { + none() + } + cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll index 9e30772e5a2c..25959a23473a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll @@ -1,5 +1,6 @@ import cpp private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr @@ -209,7 +210,7 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { } class TranslatedValueCondition extends TranslatedCondition, - TTranslatedValueCondition { + TTranslatedValueCondition { TranslatedValueCondition() { this = TTranslatedValueCondition(expr) } @@ -223,7 +224,7 @@ class TranslatedValueCondition extends TranslatedCondition, } override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + Type resultType, boolean isGLValue) { tag = ValueConditionConditionalBranchTag() and opcode instanceof Opcode::ConditionalBranch and resultType instanceof VoidType and @@ -236,7 +237,7 @@ class TranslatedValueCondition extends TranslatedCondition, } override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + EdgeKind kind) { tag = ValueConditionConditionalBranchTag() and ( ( @@ -251,9 +252,9 @@ class TranslatedValueCondition extends TranslatedCondition, } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = ValueConditionConditionalBranchTag() and - operandTag instanceof ConditionOperand and + operandTag instanceof ConditionOperandTag and result = getValueExpr().getResult() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index a6b605046330..cbddf84c8904 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -1,5 +1,6 @@ import cpp private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr @@ -157,7 +158,7 @@ class TranslatedUninitializedVariable extends tag = InitializerStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(InitializerVariableAddressTag()) ) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 580dbe0f725e..1be620d12062 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -1,6 +1,7 @@ import cpp import semmle.code.cpp.ir.implementation.raw.IR private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 8fc3fd706d07..de70d44d17c7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1,5 +1,6 @@ import cpp private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedCondition @@ -209,16 +210,16 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { ( tag = ConditionValueTrueStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueTrueTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(ConditionValueTrueConstantTag()) ) ) @@ -227,11 +228,11 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueFalseStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueFalseTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(ConditionValueFalseConstantTag()) ) ) @@ -240,11 +241,11 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, tag = ConditionValueResultLoadTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueResultTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -315,7 +316,7 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { } override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + Type resultType, boolean isGLValue) { tag = LoadTag() and opcode instanceof Opcode::Load and resultType = expr.getType().getUnspecifiedType() and @@ -326,7 +327,7 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { } override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + EdgeKind kind) { tag = LoadTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -345,11 +346,11 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { tag = LoadTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -404,7 +405,7 @@ class TranslatedCommaExpr extends TranslatedNonConstantExpr { } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { none() } @@ -478,16 +479,16 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { ( tag = CrementLoadTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -496,11 +497,11 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { tag = CrementOpTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getInstruction(CrementLoadTag()) ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getInstruction(CrementConstantTag()) ) ) @@ -509,11 +510,11 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { tag = CrementStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(CrementOpTag()) ) ) @@ -670,11 +671,11 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr { tag = OnlyInstructionTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getBaseOperand().getResult() ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getOffsetOperand().getResult() ) ) @@ -722,7 +723,7 @@ abstract class TranslatedTransparentExpr extends TranslatedNonConstantExpr { } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { none() } @@ -804,7 +805,7 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr { override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInitializeThisInstruction() } @@ -857,7 +858,7 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { none() } @@ -891,7 +892,7 @@ class TranslatedFieldAccess extends TranslatedVariableAccess { override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getQualifier().getResult() } @@ -987,7 +988,7 @@ abstract class TranslatedConstantExpr extends TranslatedCoreExpr { } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { none() } @@ -1100,13 +1101,13 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = OnlyInstructionTag() and result = getOperand().getResult() and if getOpcode() instanceof Opcode::CopyValue then - operandTag instanceof CopySourceOperand + operandTag instanceof CopySourceOperandTag else - operandTag instanceof UnaryOperand + operandTag instanceof UnaryOperandTag } override final Opcode getOpcode() { @@ -1172,9 +1173,9 @@ abstract class TranslatedSingleInstructionConversion extends TranslatedConversio } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getOperand().getResult() } @@ -1313,11 +1314,11 @@ class TranslatedBoolConversion extends TranslatedConversion { tag = BoolConversionCompareTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getOperand().getResult() ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getInstruction(BoolConversionConstantTag()) ) ) @@ -1381,21 +1382,21 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { tag = OnlyInstructionTag() and if swapOperandsOnOp() then ( ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getLeftOperand().getResult() ) or ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getRightOperand().getResult() ) ) else ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getLeftOperand().getResult() ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getRightOperand().getResult() ) ) @@ -1551,11 +1552,11 @@ class TranslatedAssignExpr extends TranslatedAssignment { tag = AssignmentStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getLeftOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getRightOperand().getResult() ) ) @@ -1714,11 +1715,11 @@ class TranslatedAssignOperation extends TranslatedAssignment { tag = AssignOperationLoadTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getLeftOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -1726,21 +1727,21 @@ class TranslatedAssignOperation extends TranslatedAssignment { ( leftOperandNeedsConversion() and tag = AssignOperationConvertLeftTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getInstruction(AssignOperationLoadTag()) ) or ( tag = AssignOperationOpTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and if leftOperandNeedsConversion() then result = getInstruction(AssignOperationConvertLeftTag()) else result = getInstruction(AssignOperationLoadTag()) ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getRightOperand().getResult() ) ) @@ -1748,18 +1749,18 @@ class TranslatedAssignOperation extends TranslatedAssignment { ( leftOperandNeedsConversion() and tag = AssignOperationConvertResultTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getInstruction(AssignOperationOpTag()) ) or ( tag = AssignmentStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getLeftOperand().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getStoredValue() ) ) @@ -1828,14 +1829,14 @@ abstract class TranslatedCall extends TranslatedExpr { tag = CallTag() and ( ( - operandTag instanceof CallTargetOperand and + operandTag instanceof CallTargetOperandTag and result = getCallTargetResult() ) or ( - operandTag instanceof ThisArgumentOperand and + operandTag instanceof ThisArgumentOperandTag and result = getQualifierResult() ) or - exists(PositionalArgumentOperand argTag | + exists(PositionalArgumentOperandTag argTag | argTag = operandTag and result = getArgument(argTag.getArgIndex()).getResult() ) @@ -2071,13 +2072,13 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { ( tag = AllocationSizeTag() and ( - operandTag instanceof LeftOperand and result = getInstruction(AllocationExtentConvertTag()) or - operandTag instanceof RightOperand and result = getInstruction(AllocationElementSizeTag()) + operandTag instanceof LeftOperandTag and result = getInstruction(AllocationExtentConvertTag()) or + operandTag instanceof RightOperandTag and result = getInstruction(AllocationElementSizeTag()) ) ) or ( tag = AllocationExtentConvertTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getExtent().getResult() ) } @@ -2322,7 +2323,7 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getTranslatedFunction(destruction.getEnclosingFunction()).getInitializeThisInstruction() } @@ -2433,7 +2434,7 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { not resultIsVoid() and ( ( @@ -2441,11 +2442,11 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, tag = ConditionValueTrueStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueTrueTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getThen().getResult() ) ) @@ -2455,11 +2456,11 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, tag = ConditionValueFalseStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueFalseTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getElse().getResult() ) ) @@ -2468,11 +2469,11 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, tag = ConditionValueResultLoadTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ConditionValueResultTempAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -2648,11 +2649,11 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, tag = ThrowTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(InitializerVariableAddressTag()) ) or ( - operandTag instanceof ExceptionOperand and + operandTag instanceof ExceptionOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -2864,7 +2865,7 @@ abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getAllocatorCall().getResult() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index a6f30acee4fa..be1c3a606d99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -1,6 +1,7 @@ import cpp import semmle.code.cpp.ir.implementation.raw.IR private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import semmle.code.cpp.ir.internal.TempVariableTag private import InstructionTag private import TranslatedElement @@ -210,10 +211,10 @@ class TranslatedFunction extends TranslatedElement, } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { ( tag = UnmodeledUseTag() and - operandTag instanceof UnmodeledUseOperand and + operandTag instanceof UnmodeledUseOperandTag and result.getFunction() = func and result.hasMemoryResult() ) or @@ -222,11 +223,11 @@ class TranslatedFunction extends TranslatedElement, not getReturnType() instanceof VoidType and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ReturnValueAddressTag()) ) or ( - operandTag instanceof ReturnValueOperand and + operandTag instanceof ReturnValueOperandTag and result = getUnmodeledDefinitionInstruction() ) ) @@ -374,11 +375,11 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = InitializerStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(InitializerVariableAddressTag()) ) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 43c5b826e230..49194bd176be 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -1,5 +1,6 @@ import cpp private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag private import InstructionTag private import TranslatedElement private import TranslatedExpr @@ -205,15 +206,15 @@ class TranslatedSimpleDirectInitialization extends } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = InitializerStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getContext().getTargetAddress() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInitializer().getResult() ) ) @@ -332,11 +333,11 @@ class TranslatedStringLiteralInitialization extends tag = InitializerLoadStringTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInitializer().getResult() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) @@ -345,11 +346,11 @@ class TranslatedStringLiteralInitialization extends tag = InitializerStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getContext().getTargetAddress() ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(InitializerLoadStringTag()) ) ) @@ -358,11 +359,11 @@ class TranslatedStringLiteralInitialization extends tag = ZeroPadStringElementAddressTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getContext().getTargetAddress() ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getInstruction(ZeroPadStringElementIndexTag()) ) ) @@ -371,11 +372,11 @@ class TranslatedStringLiteralInitialization extends tag = ZeroPadStringStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(ZeroPadStringElementAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(ZeroPadStringConstantTag()) ) ) @@ -450,7 +451,7 @@ class TranslatedConstructorInitialization extends } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { none() } @@ -514,9 +515,9 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = getFieldAddressTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getParent().(InitializationContext).getTargetAddress() } @@ -633,17 +634,17 @@ class TranslatedFieldValueInitialization extends } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { result = TranslatedFieldInitialization.super.getInstructionOperand(tag, operandTag) or ( tag = getFieldDefaultValueStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(getFieldAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(getFieldDefaultValueTag()) ) ) @@ -723,15 +724,15 @@ abstract class TranslatedElementInitialization extends TranslatedElement { } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = getElementAddressTag() and ( ( - operandTag instanceof LeftOperand and + operandTag instanceof LeftOperandTag and result = getParent().(InitializationContext).getTargetAddress() ) or ( - operandTag instanceof RightOperand and + operandTag instanceof RightOperandTag and result = getInstruction(getElementIndexTag()) ) ) @@ -882,17 +883,17 @@ class TranslatedElementValueInitialization extends } override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { result = TranslatedElementInitialization.super.getInstructionOperand(tag, operandTag) or ( tag = getElementDefaultValueStoreTag() and ( ( - operandTag instanceof LoadStoreAddressOperand and + operandTag instanceof AddressOperandTag and result = getInstruction(getElementAddressTag()) ) or ( - operandTag instanceof CopySourceOperand and + operandTag instanceof CopySourceOperandTag and result = getInstruction(getElementDefaultValueTag()) ) ) @@ -981,9 +982,9 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru } override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + OperandTag operandTag) { tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and + operandTag instanceof UnaryOperandTag and result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index 81d6ac541ab0..6e4bb2c6d1e2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -1,5 +1,6 @@ import cpp private import semmle.code.cpp.ir.internal.TempVariableTag +private import semmle.code.cpp.ir.internal.OperandTag private import InstructionTag private import TranslatedCondition private import TranslatedDeclarationEntry @@ -732,7 +733,7 @@ class TranslatedSwitchStmt extends TranslatedStmt { override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = SwitchBranchTag() and - operandTag instanceof ConditionOperand and + operandTag instanceof ConditionOperandTag and result = getExpr().getResult() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll index 5e84762e7eb8..3fc7e0691258 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll @@ -2,7 +2,7 @@ import FunctionIR import Instruction import IRBlock import IRVariable -import OperandTag +import Operand import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 4603cf498481..c95cb23814e6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -2,12 +2,13 @@ private import internal.IRInternal import FunctionIR import IRBlock import IRVariable -import OperandTag +import Operand import cpp import semmle.code.cpp.ir.implementation.EdgeKind import semmle.code.cpp.ir.implementation.MemoryAccessKind import semmle.code.cpp.ir.implementation.Opcode private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.internal.OperandTag class InstructionTag = Construction::InstructionTagType; @@ -22,21 +23,21 @@ module InstructionSanity { exists(Opcode opcode | opcode = instr.getOpcode() and ( - opcode instanceof UnaryOpcode and tag instanceof UnaryOperand or + opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag or ( opcode instanceof BinaryOpcode and ( - tag instanceof LeftOperand or - tag instanceof RightOperand + tag instanceof LeftOperandTag or + tag instanceof RightOperandTag ) ) or - opcode instanceof CopyOpcode and tag instanceof CopySourceOperand or - opcode instanceof MemoryAccessOpcode and tag instanceof LoadStoreAddressOperand or - opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperand or - opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperand or - opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperand or - opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperand or - opcode instanceof Opcode::Call and tag instanceof CallTargetOperand + opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or + opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or + opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or + opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or + opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or + opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or + opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag ) ) } @@ -45,26 +46,34 @@ module InstructionSanity { * Holds if instruction `instr` is missing an expected operand with tag `tag`. */ query predicate missingOperand(Instruction instr, OperandTag tag) { - expectsOperand(instr, tag) and not exists(instr.getOperand(tag)) + expectsOperand(instr, tag) and + not exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) } /** * Holds if instruction `instr` has an unexpected operand with tag `tag`. */ query predicate unexpectedOperand(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and + exists(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag) and not expectsOperand(instr, tag) and - not (instr instanceof CallInstruction and tag instanceof ArgumentOperand) and - not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperand) and - not (instr instanceof PhiInstruction and tag instanceof PhiOperand) + not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and + not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) } /** * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - strictcount(instr.getOperand(tag)) > 1 and - not tag instanceof UnmodeledUseOperand + strictcount(NonPhiOperand operand | + operand = instr.getAnOperand() and + operand.getOperandTag() = tag + ) > 1 and + not tag instanceof UnmodeledUseOperandTag } /** @@ -74,7 +83,7 @@ module InstructionSanity { query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) { pred = instr.getBlock().getAPredecessor() and not exists(PhiOperand operand | - exists(instr.getOperand(operand)) and + operand = instr.getAnOperand() and operand.getPredecessorBlock() = pred ) } @@ -98,14 +107,13 @@ module InstructionSanity { } /** - * Holds if instruction `op` consumes an operand `operand` that was defined in + * Holds if operand `operand` consumes a value that was defined in * a different function. */ - query predicate operandAcrossFunctions( - Instruction op, Instruction operand, OperandTag tag - ) { - operand = op.getOperand(tag) and - operand.getFunctionIR() != op.getFunctionIR() + query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) { + operand.getInstruction() = instr and + operand.getDefinitionInstruction() = defInstr and + instr.getFunctionIR() != defInstr.getFunctionIR() } /** @@ -246,20 +254,6 @@ class Instruction extends Construction::TInstruction { result = getResultId() + "(" + getResultTypeString() + ")" } - /** - * Gets a string describing the specified operand, suitable for display in IR - * dumps. This consists of the result ID of the instruction consumed by the - * operand, plus a label identifying the operand kind. - * - * For example: `this:r3_5` - */ - string getOperandString(OperandTag tag) { - exists(Instruction operand | - operand = getOperand(tag) and - result = tag.getLabel() + operand.getResultId() - ) - } - /** * Gets a string describing the operands of this instruction, suitable for * display in IR dumps. @@ -267,9 +261,9 @@ class Instruction extends Construction::TInstruction { * Example: `func:r3_4, this:r3_5` */ string getOperandsString() { - result = concat(OperandTag tag, Instruction operand | - operand = getOperand(tag) | - tag.getLabel() + operand.getResultId(), ", " order by tag.getSortOrder() + result = concat(Operand operand | + operand = getAnOperand() | + operand.getDumpString(), ", " order by operand.getDumpSortOrder() ) } @@ -333,7 +327,6 @@ class Instruction extends Construction::TInstruction { result = Construction::getInstructionUnconvertedResultExpression(this) } - /** * Gets the type of the result produced by this instruction. If the * instruction does not produce a result, its result type will be `VoidType`. @@ -397,35 +390,19 @@ class Instruction extends Construction::TInstruction { } /** - * Gets the instruction that produced the value of the specified source - * operand. - */ - final Instruction getOperand(OperandTag tag) { - result = Construction::getInstructionOperand(this, tag) - } - - /** - * Gets all instructions consumed by this instruction's operands. + * Gets all direct uses of the result of this instruction. */ - final Instruction getAnOperand() { - result = getOperand(_) + final Operand getAUse() { + result.getDefinitionInstruction() = this } /** - * Holds if this instruction has a memory operand with the specified tag. + * Gets all of this instruction's operands. */ - final predicate isMemoryOperand(OperandTag tag) { - exists(getOperandMemoryAccess(tag)) + final Operand getAnOperand() { + result.getInstruction() = this } - /** - * Gets the kind of memory access performed by the specified operand. Holds - * only for memory operands. - */ - MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - none() - } - /** * Holds if this instruction produces a memory result. */ @@ -461,9 +438,7 @@ class Instruction extends Construction::TInstruction { // Register results are always in SSA form. not hasMemoryResult() or // An unmodeled result will have a use on the `UnmodeledUse` instruction. - not exists(Instruction useInstr, UnmodeledUseOperand useTag | - this = useInstr.getOperand(useTag) - ) + not (getAUse() instanceof UnmodeledUseOperand) } /** @@ -602,7 +577,7 @@ class FieldAddressInstruction extends FieldInstruction { } final Instruction getObjectAddress() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -640,12 +615,7 @@ class ReturnValueInstruction extends ReturnInstruction { } final Instruction getReturnValue() { - result = getOperand(returnValueOperand()) - } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ReturnValueOperand))) and - result instanceof IndirectMemoryAccess + result = getAnOperand().(ReturnValueOperand).getDefinitionInstruction() } } @@ -655,7 +625,7 @@ class CopyInstruction extends Instruction { } final Instruction getSourceValue() { - result = getOperand(copySourceOperand()) + result = getAnOperand().(CopySourceOperand).getDefinitionInstruction() } } @@ -670,13 +640,8 @@ class LoadInstruction extends CopyInstruction { opcode instanceof Opcode::Load } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(CopySourceOperand))) and - result instanceof IndirectMemoryAccess - } - final Instruction getSourceAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -690,7 +655,7 @@ class StoreInstruction extends CopyInstruction { } final Instruction getDestinationAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } } @@ -700,7 +665,7 @@ class ConditionalBranchInstruction extends Instruction { } final Instruction getCondition() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getTrueSuccessor() { @@ -758,11 +723,11 @@ class BinaryInstruction extends Instruction { } final Instruction getLeftOperand() { - result = getOperand(leftOperand()) + result = getAnOperand().(LeftOperand).getDefinitionInstruction() } final Instruction getRightOperand() { - result = getOperand(rightOperand()) + result = getAnOperand().(RightOperand).getDefinitionInstruction() } } @@ -873,7 +838,7 @@ class UnaryInstruction extends Instruction { } final Instruction getOperand() { - result = getOperand(unaryOperand()) + result = getAnOperand().(UnaryOperand).getDefinitionInstruction() } } @@ -992,6 +957,7 @@ class RelationalInstruction extends CompareInstruction { RelationalInstruction() { opcode instanceof RelationalOpcode } + /** * Gets the operand on the "greater" (or "greater-or-equal") side * of this relational instruction, that is, the side that is larger @@ -1011,6 +977,7 @@ class RelationalInstruction extends CompareInstruction { Instruction getLesserOperand() { none() } + /** * Holds if this relational instruction is strict (is not an "or-equal" instruction). */ @@ -1097,7 +1064,7 @@ class SwitchInstruction extends Instruction { } final Instruction getExpression() { - result = getOperand(conditionOperand()) + result = getAnOperand().(ConditionOperand).getDefinitionInstruction() } final Instruction getACaseSuccessor() { @@ -1117,7 +1084,7 @@ class CallInstruction extends Instruction { } final Instruction getCallTarget() { - result = getOperand(callTargetOperand()) + result = getAnOperand().(CallTargetOperand).getDefinitionInstruction() } } @@ -1138,24 +1105,18 @@ class ThrowValueInstruction extends ThrowInstruction { opcode instanceof Opcode::ThrowValue } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(ExceptionOperand))) and - result instanceof IndirectMemoryAccess - } - - /** * Gets the address of the exception thrown by this instruction. */ final Instruction getExceptionAddress() { - result = getOperand(loadStoreAddressOperand()) + result = getAnOperand().(AddressOperand).getDefinitionInstruction() } /** * Gets the exception thrown by this instruction. */ final Instruction getException() { - result = getOperand(exceptionOperand()) + result = getAnOperand().(ExceptionOperand).getDefinitionInstruction() } } @@ -1236,11 +1197,6 @@ class UnmodeledUseInstruction extends Instruction { override string getOperandsString() { result = "mu*" } - - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(UnmodeledUseOperand))) and - result instanceof UnmodeledMemoryAccess - } } class PhiInstruction extends Instruction { @@ -1248,11 +1204,6 @@ class PhiInstruction extends Instruction { opcode instanceof Opcode::Phi } - override final MemoryAccessKind getOperandMemoryAccess(OperandTag tag) { - exists(this.getOperand(tag.(PhiOperand))) and - result instanceof PhiMemoryAccess - } - override final MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll new file mode 100644 index 000000000000..4cc82d0906ca --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -0,0 +1,360 @@ +private import internal.IRInternal +import Instruction +import IRBlock +import cpp +import semmle.code.cpp.ir.implementation.MemoryAccessKind +private import semmle.code.cpp.ir.internal.OperandTag + +private newtype TOperand = + TNonPhiOperand(Instruction instr, OperandTag tag, Instruction defInstr) { + defInstr = Construction::getInstructionOperandDefinition(instr, tag) + } or + TPhiOperand(PhiInstruction instr, Instruction defInstr, IRBlock predecessorBlock) { + defInstr = Construction::getPhiInstructionOperandDefinition(instr, predecessorBlock) + } + +/** + * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + */ +class Operand extends TOperand { + string toString() { + result = "Operand" + } + + /** + * Gets the `Instruction` that consumes this operand. + */ + Instruction getInstruction() { + none() + } + + /** + * Gets the `Instruction` whose result is the value of the operand. + */ + Instruction getDefinitionInstruction() { + none() + } + + /** + * Gets a prefix to use when dumping the operand in an operand list. + */ + string getDumpLabel() { + result = "" + } + + /** + * Gets a string describing this operand, suitable for display in IR dumps. This consists of the + * result ID of the instruction consumed by the operand, plus a label identifying the operand + * kind. + * + * For example: `this:r3_5` + */ + final string getDumpString() { + result = getDumpLabel() + getDefinitionInstruction().getResultId() + } + + /** + * Get the order in which the operand should be sorted in the operand list. + */ + int getDumpSortOrder() { + result = -1 + } + + /** + * Gets the kind of memory access performed by the operand. Holds only for memory operands. + */ + MemoryAccessKind getMemoryAccess() { + none() + } + + /** + * Returns the operand that holds the memory address from which the current operand loads its + * value, if any. For example, in `r3 = Load r1, m2`, the result of `getAddressOperand()` for `m2` + * is `r1`. + */ + final AddressOperand getAddressOperand() { + getMemoryAccess() instanceof IndirectMemoryAccess and + result.getInstruction() = getInstruction() + } +} + +/** + * An operand that is not an operand of a `PhiInstruction`. + */ +class NonPhiOperand extends Operand, TNonPhiOperand { + Instruction instr; + Instruction defInstr; + OperandTag tag; + + NonPhiOperand() { + this = TNonPhiOperand(instr, tag, defInstr) + } + + override final Instruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final string getDumpLabel() { + result = tag.getLabel() + } + + override final int getDumpSortOrder() { + result = tag.getSortOrder() + } + + final OperandTag getOperandTag() { + result = tag + } +} + +/** + * The address operand of an instruction that loads or stores a value from + * memory (e.g. `Load`, `Store`). + */ +class AddressOperand extends NonPhiOperand { + AddressOperand() { + this = TNonPhiOperand(_, addressOperand(), _) + } + + override string toString() { + result = "Address" + } +} + +/** + * The source value operand of an instruction that copies this value to its + * result (e.g. `Copy`, `Load`, `Store`). + */ +class CopySourceOperand extends NonPhiOperand { + CopySourceOperand() { + this = TNonPhiOperand(_, copySourceOperand(), _) + } + + override string toString() { + result = "CopySource" + } + + override final MemoryAccessKind getMemoryAccess() { + instr.getOpcode() instanceof Opcode::Load and + result instanceof IndirectMemoryAccess + } +} + +/** + * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). + */ +class UnaryOperand extends NonPhiOperand { + UnaryOperand() { + this = TNonPhiOperand(_, unaryOperand(), _) + } + + override string toString() { + result = "Unary" + } +} + +/** + * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class LeftOperand extends NonPhiOperand { + LeftOperand() { + this = TNonPhiOperand(_, leftOperand(), _) + } + + override string toString() { + result = "Left" + } +} + +/** + * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). + */ +class RightOperand extends NonPhiOperand { + RightOperand() { + this = TNonPhiOperand(_, rightOperand(), _) + } + + override string toString() { + result = "Right" + } +} + +/** + * The return value operand of a `ReturnValue` instruction. + */ +class ReturnValueOperand extends NonPhiOperand { + ReturnValueOperand() { + this = TNonPhiOperand(_, returnValueOperand(), _) + } + + override string toString() { + result = "ReturnValue" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The exception thrown by a `ThrowValue` instruction. + */ +class ExceptionOperand extends NonPhiOperand { + ExceptionOperand() { + this = TNonPhiOperand(_, exceptionOperand(), _) + } + + override string toString() { + result = "Exception" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof IndirectMemoryAccess + } +} + +/** + * The condition operand of a `ConditionalBranch` or `Switch` instruction. + */ +class ConditionOperand extends NonPhiOperand { + ConditionOperand() { + this = TNonPhiOperand(_, conditionOperand(), _) + } + + override string toString() { + result = "Condition" + } +} + +/** + * An operand of the special `UnmodeledUse` instruction, representing a value + * whose set of uses is unknown. + */ +class UnmodeledUseOperand extends NonPhiOperand { + UnmodeledUseOperand() { + this = TNonPhiOperand(_, unmodeledUseOperand(), _) + } + + override string toString() { + result = "UnmodeledUse" + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof UnmodeledMemoryAccess + } +} + +/** + * The operand representing the target function of an `Call` instruction. + */ +class CallTargetOperand extends NonPhiOperand { + CallTargetOperand() { + this = TNonPhiOperand(_, callTargetOperand(), _) + } + + override string toString() { + result = "CallTarget" + } +} + +/** + * An operand representing an argument to a function call. This includes both + * positional arguments (represented by `PositionalArgumentOperand`) and the + * implicit `this` argument, if any (represented by `ThisArgumentOperand`). + */ +class ArgumentOperand extends NonPhiOperand { + ArgumentOperand() { + exists(ArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) + ) + } +} + +/** + * An operand representing the implicit 'this' argument to a member function + * call. + */ +class ThisArgumentOperand extends ArgumentOperand { + ThisArgumentOperand() { + this = TNonPhiOperand(_, thisArgumentOperand(), _) + } + + override string toString() { + result = "ThisArgument" + } +} + +/** + * An operand representing an argument to a function call. + */ +class PositionalArgumentOperand extends ArgumentOperand { + int argIndex; + + PositionalArgumentOperand() { + exists(PositionalArgumentOperandTag argTag | + this = TNonPhiOperand(_, argTag, _) and + argIndex = argTag.getArgIndex() + ) + } + + override string toString() { + result = "Arg(" + argIndex + ")" + } +} + +/** + * An operand of a `PhiInstruction`. + */ +class PhiOperand extends Operand, TPhiOperand { + PhiInstruction instr; + Instruction defInstr; + IRBlock predecessorBlock; + + PhiOperand() { + this = TPhiOperand(instr, defInstr, predecessorBlock) + } + + override string toString() { + result = "Phi" + } + + override final PhiInstruction getInstruction() { + result = instr + } + + override final Instruction getDefinitionInstruction() { + result = defInstr + } + + override final int getDumpSortOrder() { + result = 11 + getPredecessorBlock().getDisplayIndex() + } + + override final string getDumpLabel() { + result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" + } + + /** + * Gets the predecessor block from which this value comes. + */ + final IRBlock getPredecessorBlock() { + result = predecessorBlock + } + + override final MemoryAccessKind getMemoryAccess() { + result instanceof PhiMemoryAccess + } +} + +/** + * An operand that reads a value from memory. + */ +class MemoryOperand extends Operand { + MemoryOperand() { + exists(getMemoryAccess()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/OperandTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/OperandTag.qll deleted file mode 100644 index df78fd90cd96..000000000000 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/OperandTag.qll +++ /dev/null @@ -1,312 +0,0 @@ -private import internal.IRInternal -import Instruction -import IRBlock -import cpp - -private newtype TOperandTag = - TLoadStoreAddressOperand() or - TCopySourceOperand() or - TUnaryOperand() or - TLeftOperand() or - TRightOperand() or - TReturnValueOperand() or - TExceptionOperand() or - TConditionOperand() or - TUnmodeledUseOperand() or - TCallTargetOperand() or - TThisArgumentOperand() or - TPositionalArgumentOperand(int argIndex) { - argIndex in [0..Construction::getMaxCallArgIndex()] or - exists(BuiltInOperation op | - exists(op.getChild(argIndex)) - ) - } or - TPhiOperand(IRBlock predecessorBlock) { - exists(PhiInstruction phi | - predecessorBlock = Construction::getPhiInstructionBlockStart(phi).getBlock().getAPredecessor() - ) - } - -/** - * Identifies the kind of operand on an instruction. Each `Instruction` has at - * most one operand of any single `OperandTag`. The set of `OperandTag`s used by - * an `Instruction` is determined by the instruction's opcode. - */ -abstract class OperandTag extends TOperandTag { - abstract string toString(); - - abstract int getSortOrder(); - - string getLabel() { - result = "" - } -} - -// Note: individual subtypes are listed in the order that the operands should -// appear in the operand list of the instruction when printing. - -/** - * The address operand of an instruction that loads or stores a value from - * memory (e.g. `Load`, `Store`). - */ -class LoadStoreAddressOperand extends OperandTag, TLoadStoreAddressOperand { - override final string toString() { - result = "LoadStoreAddress" - } - - override final int getSortOrder() { - result = 0 - } -} - -LoadStoreAddressOperand loadStoreAddressOperand() { - result = TLoadStoreAddressOperand() -} - -/** - * The source value operand of an instruction that copies this value to its - * result (e.g. `Copy`, `Load`, `Store`). - */ -class CopySourceOperand extends OperandTag, TCopySourceOperand { - override final string toString() { - result = "CopySource" - } - - override final int getSortOrder() { - result = 1 - } -} - -CopySourceOperand copySourceOperand() { - result = TCopySourceOperand() -} - -/** - * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). - */ -class UnaryOperand extends OperandTag, TUnaryOperand { - override final string toString() { - result = "Unary" - } - - override final int getSortOrder() { - result = 2 - } -} - -UnaryOperand unaryOperand() { - result = TUnaryOperand() -} - -/** - * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). - */ -class LeftOperand extends OperandTag, TLeftOperand { - override final string toString() { - result = "Left" - } - - override final int getSortOrder() { - result = 3 - } -} - -LeftOperand leftOperand() { - result = TLeftOperand() -} - -/** - * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). - */ -class RightOperand extends OperandTag, TRightOperand { - override final string toString() { - result = "Right" - } - - override final int getSortOrder() { - result = 4 - } -} - -RightOperand rightOperand() { - result = TRightOperand() -} - -/** - * The return value operand of a `ReturnValue` instruction. - */ -class ReturnValueOperand extends OperandTag, TReturnValueOperand { - override final string toString() { - result = "ReturnValue" - } - - override final int getSortOrder() { - result = 5 - } -} - -ReturnValueOperand returnValueOperand() { - result = TReturnValueOperand() -} - -/** - * The exception thrown by a `ThrowValue` instruction. - */ -class ExceptionOperand extends OperandTag, TExceptionOperand { - override final string toString() { - result = "Exception" - } - - override final int getSortOrder() { - result = 6 - } -} - -ExceptionOperand exceptionOperand() { - result = TExceptionOperand() -} - -/** - * The condition operand of a `ConditionalBranch` or `Switch` instruction. - */ -class ConditionOperand extends OperandTag, TConditionOperand { - override final string toString() { - result = "Condition" - } - - override final int getSortOrder() { - result = 7 - } -} - -ConditionOperand conditionOperand() { - result = TConditionOperand() -} - -/** - * An operand of the special `UnmodeledUse` instruction, representing a value - * whose set of uses is unknown. - */ -class UnmodeledUseOperand extends OperandTag, TUnmodeledUseOperand { - override final string toString() { - result = "UnmodeledUse" - } - - override final int getSortOrder() { - result = 8 - } -} - -UnmodeledUseOperand unmodeledUseOperand() { - result = TUnmodeledUseOperand() -} - -/** - * The operand representing the target function of an `Call` instruction. - */ -class CallTargetOperand extends OperandTag, TCallTargetOperand { - override final string toString() { - result = "CallTarget" - } - - override final int getSortOrder() { - result = 9 - } -} - -CallTargetOperand callTargetOperand() { - result = TCallTargetOperand() -} - -/** - * An operand representing an argument to a function call. This includes both - * positional arguments (represented by `PositionalArgumentOperand`) and the - * implicit `this` argument, if any (represented by `ThisArgumentOperand`). - */ -abstract class ArgumentOperand extends OperandTag { -} - -/** - * An operand representing the implicit 'this' argument to a member function - * call. - */ -class ThisArgumentOperand extends ArgumentOperand, TThisArgumentOperand { - ThisArgumentOperand() { - this = TThisArgumentOperand() - } - - override final string toString() { - result = "Arg(this)" - } - - override final int getSortOrder() { - result = 10 - } - - override final string getLabel() { - result = "this:" - } -} - -ThisArgumentOperand thisArgumentOperand() { - result = TThisArgumentOperand() -} - -/** - * An operand representing an argument to a function call. - */ -class PositionalArgumentOperand extends ArgumentOperand, - TPositionalArgumentOperand { - int argIndex; - - PositionalArgumentOperand() { - this = TPositionalArgumentOperand(argIndex) - } - - override final string toString() { - result = "Arg(" + argIndex + ")" - } - - override final int getSortOrder() { - result = 11 + argIndex - } - - final int getArgIndex() { - result = argIndex - } -} - -PositionalArgumentOperand positionalArgumentOperand(int argIndex) { - result = TPositionalArgumentOperand(argIndex) -} - -/** - * An operand of an SSA `Phi` instruction. - */ -class PhiOperand extends OperandTag, TPhiOperand { - IRBlock predecessorBlock; - - PhiOperand() { - this = TPhiOperand(predecessorBlock) - } - - override final string toString() { - result = "Phi" - } - - override final int getSortOrder() { - result = 11 + getPredecessorBlock().getDisplayIndex() - } - - override final string getLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" - } - - final IRBlock getPredecessorBlock() { - result = predecessorBlock - } -} - -PhiOperand phiOperand(IRBlock predecessorBlock) { - result = TPhiOperand(predecessorBlock) -} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index f3be51b63d2d..fb897afa58d6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -46,18 +46,20 @@ private IntValue getFieldBitOffset(Field field) { * not result in any address held in that operand from escaping beyond the * instruction. */ -predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - ( - // The source/destination address of a Load/Store does not escape (but the - // loaded/stored value could). - tag instanceof LoadStoreAddressOperand or - // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or - // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or - // Converting an address to a `bool` does not escape the address. - instr.(ConvertInstruction).getResultType() instanceof BoolType +predicate operandIsConsumedWithoutEscaping(Operand operand) { + // The source/destination address of a Load/Store does not escape (but the + // loaded/stored value could). + operand instanceof AddressOperand or + exists (Instruction instr | + instr = operand.getInstruction() and + ( + // Neither operand of a Compare escapes. + instr instanceof CompareInstruction or + // Neither operand of a PointerDiff escapes. + instr instanceof PointerDiffInstruction or + // Converting an address to a `bool` does not escape the address. + instr.(ConvertInstruction).getResultType() instanceof BoolType + ) ) } @@ -96,43 +98,44 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { * `bitOffset`. If the address is propagated, but the offset is not known to be * a constant, then `bitOffset` is unknown. */ -predicate operandIsPropagated(Instruction instr, OperandTag tag, - IntValue bitOffset) { - exists(instr.getOperand(tag)) and - ( - // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | - convert = instr and - bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or - // Converting to a derived class subtracts the offset of the base class. - exists(ConvertToDerivedInstruction convert | - convert = instr and - bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or - // Converting to a virtual base class adds an unknown offset. +predicate operandIsPropagated(Operand operand, IntValue bitOffset) { + exists(Instruction instr | + instr = operand.getInstruction() and ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or - // Conversion to another pointer type propagates the source address. - exists(ConvertInstruction convert, Type resultType | - convert = instr and - resultType = convert.getResultType() and + // Converting to a non-virtual base class adds the offset of the base class. + exists(ConvertToBaseInstruction convert | + convert = instr and + bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) + ) or + // Converting to a derived class subtracts the offset of the base class. + exists(ConvertToDerivedInstruction convert | + convert = instr and + bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) + ) or + // Converting to a virtual base class adds an unknown offset. ( - resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers - ) and - bitOffset = 0 - ) or - // Adding an integer to or subtracting an integer from a pointer propagates - // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or - // Computing a field address from a pointer propagates the address plus the - // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or - // A copy propagates the source value. - tag instanceof CopySourceOperand and bitOffset = 0 + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + ) or + // Conversion to another pointer type propagates the source address. + exists(ConvertInstruction convert, Type resultType | + convert = instr and + resultType = convert.getResultType() and + ( + resultType instanceof PointerType or + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + ) and + bitOffset = 0 + ) or + // Adding an integer to or subtracting an integer from a pointer propagates + // the address with an offset. + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + // Computing a field address from a pointer propagates the address plus the + // offset of the field. + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + // A copy propagates the source value. + operand instanceof CopySourceOperand and bitOffset = 0 + ) ) } @@ -140,16 +143,15 @@ predicate operandIsPropagated(Instruction instr, OperandTag tag, * Holds if any address held in operand number `tag` of instruction `instr` * escapes outside the domain of the analysis. */ -predicate operandEscapes(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and +predicate operandEscapes(Operand operand) { // Conservatively assume that the address escapes unless one of the following // holds: not ( // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(instr, tag) or + operandIsConsumedWithoutEscaping(operand) or // The address is propagated to the result of the instruction, but that // result does not itself escape. - operandIsPropagated(instr, tag, _) and not resultEscapes(instr) + operandIsPropagated(operand, _) and not resultEscapes(operand.getInstruction()) ) } @@ -159,10 +161,7 @@ predicate operandEscapes(Instruction instr, OperandTag tag) { */ predicate resultEscapes(Instruction instr) { // The result escapes if it has at least one use that escapes. - exists(Instruction useInstr, OperandTag useOperandTag | - useInstr.getOperand(useOperandTag) = instr and - operandEscapes(useInstr, useOperandTag) - ) + operandEscapes(instr.getAUse()) } /** @@ -203,12 +202,12 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getVariable() = var and bitOffset = 0 ) or - exists(OperandTag operandTag, IntValue originalBitOffset, - IntValue propagatedBitOffset | + exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | + operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, // offset by the bit offset from the propagation. - resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and - operandIsPropagated(instr, operandTag, propagatedBitOffset) and + resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and + operandIsPropagated(operand, propagatedBitOffset) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 70af6ce64138..5dbf34cb6c32 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -1,30 +1,13 @@ import SSAConstructionInternal import cpp private import semmle.code.cpp.ir.implementation.Opcode -import NewIR +private import semmle.code.cpp.ir.internal.OperandTag +private import NewIR import IRBlockConstruction as BlockConstruction import Cached cached private module Cached { - private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { - newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or - newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or - newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or - newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or - newTag instanceof RightOperand and result instanceof OldIR::RightOperand or - newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or - newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or - newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or - newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or - newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or - newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or - exists(PositionalArgumentOperand newArg | - newArg = newTag and - result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() - ) - } - private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) } @@ -49,14 +32,6 @@ cached private module Cached { ) } - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(OldIR::PositionalArgumentOperand oldOperand | - argIndex = oldOperand.getArgIndex() - ) - ) - } - cached OldIR::Instruction getOldInstruction(Instruction instr) { instr.getTag() = WrappedInstructionTag(result) } @@ -135,18 +110,19 @@ cached private module Cached { instruction instanceof PhiInstruction // Phis always have modeled results } - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { - exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | - oldUse = getOldInstruction(instruction) and - oldTag = getOldOperandTag(tag) and - if oldUse.isMemoryOperand(oldTag) then ( + cached Instruction getInstructionOperandDefinition(Instruction instruction, OperandTag tag) { + exists(OldIR::Instruction oldInstruction, OldIR::NonPhiOperand oldOperand | + oldInstruction = getOldInstruction(instruction) and + oldOperand = oldInstruction.getAnOperand() and + tag = oldOperand.getOperandTag() and + if oldOperand instanceof OldIR::MemoryOperand then ( ( - if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( + if exists(Alias::getOperandMemoryAccess(oldOperand)) then ( exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, int defIndex | - vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and + vvar = Alias::getOperandMemoryAccess(oldOperand).getVirtualVariable() and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - hasUseAtRank(vvar, useBlock, useRank, oldUse) and + hasUseAtRank(vvar, useBlock, useRank, oldInstruction) and definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and if defIndex >= 0 then result = getNewInstruction(defBlock.getInstruction(defIndex)) @@ -162,25 +138,25 @@ cached private module Cached { // `UnmodeledUse` instruction. exists(OldIR::Instruction oldDefinition | instruction instanceof UnmodeledUseInstruction and - tag instanceof UnmodeledUseOperand and - oldDefinition = oldUse.getOperand(oldTag) and + tag instanceof UnmodeledUseOperandTag and + oldDefinition = oldOperand.getDefinitionInstruction() and not exists(Alias::getResultMemoryAccess(oldDefinition)) and result = getNewInstruction(oldDefinition) ) ) else - result = getNewInstruction(oldUse.getOperand(oldTag)) - ) or - result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) + result = getNewInstruction(oldOperand.getDefinitionInstruction()) + ) } - cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { + cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr, + IRBlock newPredecessorBlock) { exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | hasPhiNode(vvar, phiBlock) and predBlock = phiBlock.getAPredecessor() and instr.getTag() = PhiTag(vvar, phiBlock) and - tag.getPredecessorBlock() = getNewBlock(predBlock) and + newPredecessorBlock = getNewBlock(predBlock) and hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and if defIndex >= 0 then @@ -277,7 +253,7 @@ cached private module Cached { private predicate hasUse(Alias::VirtualVariable vvar, OldIR::Instruction use, OldIR::IRBlock block, int index) { exists(Alias::MemoryAccess access | - access = Alias::getOperandMemoryAccess(use, _) and + access = Alias::getOperandMemoryAccess(use.getAnOperand()) and block.getInstruction(index) = use and vvar = access.getVirtualVariable() ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index a2d8f3532ac7..fdf596267a90 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -2,7 +2,8 @@ import SimpleSSAInternal import cpp import Alias private import InputIR -import semmle.code.cpp.ir.internal.Overlap +private import semmle.code.cpp.ir.internal.OperandTag +private import semmle.code.cpp.ir.internal.Overlap private newtype TVirtualVariable = MkVirtualVariable(IRVariable var) { @@ -69,15 +70,15 @@ Overlap getOverlap(MemoryAccess def, MemoryAccess use) { MemoryAccess getResultMemoryAccess(Instruction instr) { exists(IRVariable var | instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), + var, 0) and result = getMemoryAccess(var) ) } -MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { +MemoryAccess getOperandMemoryAccess(Operand operand) { exists(IRVariable var | - instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, 0) and result = getMemoryAccess(var) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/OperandTag.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/OperandTag.qll similarity index 64% rename from cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/OperandTag.qll rename to cpp/ql/src/semmle/code/cpp/ir/internal/OperandTag.qll index df78fd90cd96..a8063aaaf9de 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/OperandTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/OperandTag.qll @@ -1,10 +1,15 @@ -private import internal.IRInternal -import Instruction -import IRBlock import cpp +private int getMaxCallArgIndex() { + result = max(int argIndex | + exists(FunctionCall call | + exists(call.getArgument(argIndex)) + ) + ) +} + private newtype TOperandTag = - TLoadStoreAddressOperand() or + TAddressOperand() or TCopySourceOperand() or TUnaryOperand() or TLeftOperand() or @@ -16,15 +21,10 @@ private newtype TOperandTag = TCallTargetOperand() or TThisArgumentOperand() or TPositionalArgumentOperand(int argIndex) { - argIndex in [0..Construction::getMaxCallArgIndex()] or + argIndex in [0..getMaxCallArgIndex()] or exists(BuiltInOperation op | exists(op.getChild(argIndex)) ) - } or - TPhiOperand(IRBlock predecessorBlock) { - exists(PhiInstruction phi | - predecessorBlock = Construction::getPhiInstructionBlockStart(phi).getBlock().getAPredecessor() - ) } /** @@ -49,9 +49,9 @@ abstract class OperandTag extends TOperandTag { * The address operand of an instruction that loads or stores a value from * memory (e.g. `Load`, `Store`). */ -class LoadStoreAddressOperand extends OperandTag, TLoadStoreAddressOperand { +class AddressOperandTag extends OperandTag, TAddressOperand { override final string toString() { - result = "LoadStoreAddress" + result = "Address" } override final int getSortOrder() { @@ -59,15 +59,15 @@ class LoadStoreAddressOperand extends OperandTag, TLoadStoreAddressOperand { } } -LoadStoreAddressOperand loadStoreAddressOperand() { - result = TLoadStoreAddressOperand() +AddressOperandTag addressOperand() { + result = TAddressOperand() } /** * The source value operand of an instruction that copies this value to its * result (e.g. `Copy`, `Load`, `Store`). */ -class CopySourceOperand extends OperandTag, TCopySourceOperand { +class CopySourceOperandTag extends OperandTag, TCopySourceOperand { override final string toString() { result = "CopySource" } @@ -77,14 +77,14 @@ class CopySourceOperand extends OperandTag, TCopySourceOperand { } } -CopySourceOperand copySourceOperand() { +CopySourceOperandTag copySourceOperand() { result = TCopySourceOperand() } /** * The sole operand of a unary instruction (e.g. `Convert`, `Negate`). */ -class UnaryOperand extends OperandTag, TUnaryOperand { +class UnaryOperandTag extends OperandTag, TUnaryOperand { override final string toString() { result = "Unary" } @@ -94,14 +94,14 @@ class UnaryOperand extends OperandTag, TUnaryOperand { } } -UnaryOperand unaryOperand() { +UnaryOperandTag unaryOperand() { result = TUnaryOperand() } /** * The left operand of a binary instruction (e.g. `Add`, `CompareEQ`). */ -class LeftOperand extends OperandTag, TLeftOperand { +class LeftOperandTag extends OperandTag, TLeftOperand { override final string toString() { result = "Left" } @@ -111,14 +111,14 @@ class LeftOperand extends OperandTag, TLeftOperand { } } -LeftOperand leftOperand() { +LeftOperandTag leftOperand() { result = TLeftOperand() } /** * The right operand of a binary instruction (e.g. `Add`, `CompareEQ`). */ -class RightOperand extends OperandTag, TRightOperand { +class RightOperandTag extends OperandTag, TRightOperand { override final string toString() { result = "Right" } @@ -128,14 +128,14 @@ class RightOperand extends OperandTag, TRightOperand { } } -RightOperand rightOperand() { +RightOperandTag rightOperand() { result = TRightOperand() } /** * The return value operand of a `ReturnValue` instruction. */ -class ReturnValueOperand extends OperandTag, TReturnValueOperand { +class ReturnValueOperandTag extends OperandTag, TReturnValueOperand { override final string toString() { result = "ReturnValue" } @@ -145,14 +145,14 @@ class ReturnValueOperand extends OperandTag, TReturnValueOperand { } } -ReturnValueOperand returnValueOperand() { +ReturnValueOperandTag returnValueOperand() { result = TReturnValueOperand() } /** * The exception thrown by a `ThrowValue` instruction. */ -class ExceptionOperand extends OperandTag, TExceptionOperand { +class ExceptionOperandTag extends OperandTag, TExceptionOperand { override final string toString() { result = "Exception" } @@ -162,14 +162,14 @@ class ExceptionOperand extends OperandTag, TExceptionOperand { } } -ExceptionOperand exceptionOperand() { +ExceptionOperandTag exceptionOperand() { result = TExceptionOperand() } /** * The condition operand of a `ConditionalBranch` or `Switch` instruction. */ -class ConditionOperand extends OperandTag, TConditionOperand { +class ConditionOperandTag extends OperandTag, TConditionOperand { override final string toString() { result = "Condition" } @@ -179,7 +179,7 @@ class ConditionOperand extends OperandTag, TConditionOperand { } } -ConditionOperand conditionOperand() { +ConditionOperandTag conditionOperand() { result = TConditionOperand() } @@ -187,7 +187,7 @@ ConditionOperand conditionOperand() { * An operand of the special `UnmodeledUse` instruction, representing a value * whose set of uses is unknown. */ -class UnmodeledUseOperand extends OperandTag, TUnmodeledUseOperand { +class UnmodeledUseOperandTag extends OperandTag, TUnmodeledUseOperand { override final string toString() { result = "UnmodeledUse" } @@ -197,14 +197,14 @@ class UnmodeledUseOperand extends OperandTag, TUnmodeledUseOperand { } } -UnmodeledUseOperand unmodeledUseOperand() { +UnmodeledUseOperandTag unmodeledUseOperand() { result = TUnmodeledUseOperand() } /** * The operand representing the target function of an `Call` instruction. */ -class CallTargetOperand extends OperandTag, TCallTargetOperand { +class CallTargetOperandTag extends OperandTag, TCallTargetOperand { override final string toString() { result = "CallTarget" } @@ -214,7 +214,7 @@ class CallTargetOperand extends OperandTag, TCallTargetOperand { } } -CallTargetOperand callTargetOperand() { +CallTargetOperandTag callTargetOperand() { result = TCallTargetOperand() } @@ -223,15 +223,15 @@ CallTargetOperand callTargetOperand() { * positional arguments (represented by `PositionalArgumentOperand`) and the * implicit `this` argument, if any (represented by `ThisArgumentOperand`). */ -abstract class ArgumentOperand extends OperandTag { +abstract class ArgumentOperandTag extends OperandTag { } /** * An operand representing the implicit 'this' argument to a member function * call. */ -class ThisArgumentOperand extends ArgumentOperand, TThisArgumentOperand { - ThisArgumentOperand() { +class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand { + ThisArgumentOperandTag() { this = TThisArgumentOperand() } @@ -248,18 +248,18 @@ class ThisArgumentOperand extends ArgumentOperand, TThisArgumentOperand { } } -ThisArgumentOperand thisArgumentOperand() { +ThisArgumentOperandTag thisArgumentOperand() { result = TThisArgumentOperand() } /** * An operand representing an argument to a function call. */ -class PositionalArgumentOperand extends ArgumentOperand, +class PositionalArgumentOperandTag extends ArgumentOperandTag, TPositionalArgumentOperand { int argIndex; - PositionalArgumentOperand() { + PositionalArgumentOperandTag() { this = TPositionalArgumentOperand(argIndex) } @@ -276,37 +276,6 @@ class PositionalArgumentOperand extends ArgumentOperand, } } -PositionalArgumentOperand positionalArgumentOperand(int argIndex) { +PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) { result = TPositionalArgumentOperand(argIndex) } - -/** - * An operand of an SSA `Phi` instruction. - */ -class PhiOperand extends OperandTag, TPhiOperand { - IRBlock predecessorBlock; - - PhiOperand() { - this = TPhiOperand(predecessorBlock) - } - - override final string toString() { - result = "Phi" - } - - override final int getSortOrder() { - result = 11 + getPredecessorBlock().getDisplayIndex() - } - - override final string getLabel() { - result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":" - } - - final IRBlock getPredecessorBlock() { - result = predecessorBlock - } -} - -PhiOperand phiOperand(IRBlock predecessorBlock) { - result = TPhiOperand(predecessorBlock) -} diff --git a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql index 1cd4a523a3c1..54d29000fdd2 100644 --- a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql +++ b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql @@ -19,8 +19,8 @@ IntValue getConstantValue(Instruction instr) { result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or exists(PhiInstruction phi | phi = instr and - result = max(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) and - result = min(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) + result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and + result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) ) }