Merge pull request #1846 from hvitved/csharp/autoformat

Approved by jbj
This commit is contained in:
semmle-qlci
2019-09-02 08:31:43 +01:00
committed by GitHub
79 changed files with 5198 additions and 8362 deletions

View File

@@ -1,12 +1,13 @@
private import internal.EdgeKindInternal
private newtype TEdgeKind =
TGotoEdge() or // Single successor (including fall-through)
TTrueEdge() or // 'true' edge of conditional branch
TFalseEdge() or // 'false' edge of conditional branch
TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) { // Case label of switch
TGotoEdge() or // Single successor (including fall-through)
TTrueEdge() or // 'true' edge of conditional branch
TFalseEdge() or // 'false' edge of conditional branch
TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) {
// Case label of switch
Language::hasCaseEdge(minValue, maxValue)
}
@@ -24,70 +25,50 @@ abstract class EdgeKind extends TEdgeKind {
* or `IRBlock`.
*/
class GotoEdge extends EdgeKind, TGotoEdge {
override final string toString() {
result = "Goto"
}
final override string toString() { result = "Goto" }
}
GotoEdge gotoEdge() {
result = TGotoEdge()
}
GotoEdge gotoEdge() { result = TGotoEdge() }
/**
* A "true" edge, representing the successor of a conditional branch when the
* condition is non-zero.
*/
class TrueEdge extends EdgeKind, TTrueEdge {
override final string toString() {
result = "True"
}
final override string toString() { result = "True" }
}
TrueEdge trueEdge() {
result = TTrueEdge()
}
TrueEdge trueEdge() { result = TTrueEdge() }
/**
* A "false" edge, representing the successor of a conditional branch when the
* condition is zero.
*/
class FalseEdge extends EdgeKind, TFalseEdge {
override final string toString() {
result = "False"
}
final override string toString() { result = "False" }
}
FalseEdge falseEdge() {
result = TFalseEdge()
}
FalseEdge falseEdge() { result = TFalseEdge() }
/**
* An "exception" edge, representing the successor of an instruction when that
* instruction's evaluation throws an exception.
*/
class ExceptionEdge extends EdgeKind, TExceptionEdge {
override final string toString() {
result = "Exception"
}
final override string toString() { result = "Exception" }
}
ExceptionEdge exceptionEdge() {
result = TExceptionEdge()
}
ExceptionEdge exceptionEdge() { result = TExceptionEdge() }
/**
* A "default" edge, representing the successor of a `Switch` instruction when
* none of the case values matches the condition value.
*/
class DefaultEdge extends EdgeKind, TDefaultEdge {
override final string toString() {
result = "Default"
}
final override string toString() { result = "Default" }
}
DefaultEdge defaultEdge() {
result = TDefaultEdge()
}
DefaultEdge defaultEdge() { result = TDefaultEdge() }
/**
* A "case" edge, representing the successor of a `Switch` instruction when the
@@ -95,28 +76,20 @@ DefaultEdge defaultEdge() {
*/
class CaseEdge extends EdgeKind, TCaseEdge {
string minValue;
string maxValue;
CaseEdge() {
this = TCaseEdge(minValue, maxValue)
CaseEdge() { this = TCaseEdge(minValue, maxValue) }
final override string toString() {
if minValue = maxValue
then result = "Case[" + minValue + "]"
else result = "Case[" + minValue + ".." + maxValue + "]"
}
override final string toString() {
if minValue = maxValue then
result = "Case[" + minValue + "]"
else
result = "Case[" + minValue + ".." + maxValue + "]"
}
string getMinValue() { result = minValue }
string getMinValue() {
result = minValue
}
string getMaxValue() {
result = maxValue
}
string getMaxValue() { result = maxValue }
}
CaseEdge caseEdge(string minValue, string maxValue) {
result = TCaseEdge(minValue, maxValue)
}
CaseEdge caseEdge(string minValue, string maxValue) { result = TCaseEdge(minValue, maxValue) }

View File

@@ -15,17 +15,13 @@ private newtype TMemoryAccessKind =
* memory result.
*/
class MemoryAccessKind extends TMemoryAccessKind {
string toString() {
none()
}
string toString() { none() }
/**
* Holds if the operand or result accesses memory pointed to by the `AddressOperand` on the
* same instruction.
*/
predicate usesAddressOperand() {
none()
}
predicate usesAddressOperand() { none() }
}
/**
@@ -33,13 +29,9 @@ class MemoryAccessKind extends TMemoryAccessKind {
* same instruction.
*/
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
override string toString() {
result = "indirect"
}
override final predicate usesAddressOperand() {
any()
}
override string toString() { result = "indirect" }
final override predicate usesAddressOperand() { any() }
}
/**
@@ -47,13 +39,9 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
* `AddressOperand` on the same instruction.
*/
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
override string toString() {
result = "indirect(may)"
}
override string toString() { result = "indirect(may)" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
@@ -62,13 +50,9 @@ class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess
* `BufferSizeOperand`.
*/
class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
override string toString() {
result = "buffer"
}
override string toString() { result = "buffer" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
@@ -77,31 +61,23 @@ class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
* elements given by the `BufferSizeOperand`.
*/
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
override string toString() {
result = "buffer(may)"
}
override string toString() { result = "buffer(may)" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
* The operand or result accesses all memory whose address has escaped.
*/
class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess {
override string toString() {
result = "escaped"
}
override string toString() { result = "escaped" }
}
/**
* The operand or result may access all memory whose address has escaped.
*/
class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
override string toString() {
result = "escaped(may)"
}
override string toString() { result = "escaped(may)" }
}
/**
@@ -109,9 +85,7 @@ class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
* definition.
*/
class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
override string toString() {
result = "phi"
}
override string toString() { result = "phi" }
}
/**
@@ -119,9 +93,7 @@ class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
* definition.
*/
class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
override string toString() {
result = "chi(total)"
}
override string toString() { result = "chi(total)" }
}
/**
@@ -129,9 +101,7 @@ class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
* definition.
*/
class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
override string toString() {
result = "chi(partial)"
}
override string toString() { result = "chi(partial)" }
}
/**
@@ -139,7 +109,5 @@ class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
* `UnmodeledDefinition` and on the operands of `UnmodeledUse`.
*/
class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess {
override string toString() {
result = "unmodeled"
}
override string toString() { result = "unmodeled" }
}

View File

@@ -77,152 +77,382 @@ private newtype TOpcode =
TNewObj()
class Opcode extends TOpcode {
string toString() {
result = "UnknownOpcode"
}
string toString() { result = "UnknownOpcode" }
}
abstract class UnaryOpcode extends Opcode {}
abstract class UnaryOpcode extends Opcode { }
abstract class BinaryOpcode extends Opcode {}
abstract class BinaryOpcode extends Opcode { }
abstract class PointerArithmeticOpcode extends BinaryOpcode {}
abstract class PointerArithmeticOpcode extends BinaryOpcode { }
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {}
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode { }
abstract class ArithmeticOpcode extends Opcode {}
abstract class ArithmeticOpcode extends Opcode { }
abstract class BinaryArithmeticOpcode extends BinaryOpcode, ArithmeticOpcode {}
abstract class BinaryArithmeticOpcode extends BinaryOpcode, ArithmeticOpcode { }
abstract class UnaryArithmeticOpcode extends UnaryOpcode, ArithmeticOpcode {}
abstract class UnaryArithmeticOpcode extends UnaryOpcode, ArithmeticOpcode { }
abstract class BitwiseOpcode extends Opcode {}
abstract class BitwiseOpcode extends Opcode { }
abstract class BinaryBitwiseOpcode extends BinaryOpcode, BitwiseOpcode {}
abstract class BinaryBitwiseOpcode extends BinaryOpcode, BitwiseOpcode { }
abstract class UnaryBitwiseOpcode extends UnaryOpcode, BitwiseOpcode {}
abstract class UnaryBitwiseOpcode extends UnaryOpcode, BitwiseOpcode { }
abstract class CompareOpcode extends BinaryOpcode {}
abstract class CompareOpcode extends BinaryOpcode { }
abstract class RelationalOpcode extends CompareOpcode {}
abstract class RelationalOpcode extends CompareOpcode { }
abstract class CopyOpcode extends Opcode {}
abstract class CopyOpcode extends Opcode { }
abstract class MemoryAccessOpcode extends Opcode {}
abstract class MemoryAccessOpcode extends Opcode { }
abstract class ReturnOpcode extends Opcode {}
abstract class ReturnOpcode extends Opcode { }
abstract class ThrowOpcode extends Opcode {}
abstract class ThrowOpcode extends Opcode { }
abstract class CatchOpcode extends Opcode {}
abstract class CatchOpcode extends Opcode { }
abstract class OpcodeWithCondition extends Opcode {}
abstract class OpcodeWithCondition extends Opcode { }
abstract class BuiltInOperationOpcode extends Opcode {}
abstract class BuiltInOperationOpcode extends Opcode { }
abstract class SideEffectOpcode extends Opcode {}
abstract class SideEffectOpcode extends Opcode { }
/**
* An opcode that reads a value from memory.
*/
abstract class OpcodeWithLoad extends MemoryAccessOpcode {}
abstract class OpcodeWithLoad extends MemoryAccessOpcode { }
/**
* An opcode that reads from a set of memory locations as a side effect.
*/
abstract class ReadSideEffectOpcode extends SideEffectOpcode {}
abstract class ReadSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that writes to a set of memory locations as a side effect.
*/
abstract class WriteSideEffectOpcode extends SideEffectOpcode {}
abstract class WriteSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that may overwrite some, all, or none of an existing set of memory locations. Modeled
* as a read of the original contents, plus a "may" write of the new contents.
*/
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode {}
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that accesses a buffer via an `AddressOperand` and a `BufferSizeOperand`.
*/
abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
abstract class BufferAccessOpcode extends MemoryAccessOpcode { }
module Opcode {
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
class Error extends Opcode, TError { override final string toString() { result = "Error" } }
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } }
class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } }
class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } }
class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } }
class ReturnValue extends ReturnOpcode, OpcodeWithLoad, TReturnValue { override final string toString() { result = "ReturnValue" } }
class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } }
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } }
class Load extends CopyOpcode, OpcodeWithLoad, TLoad { override final string toString() { result = "Load" } }
class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } }
class Add extends BinaryArithmeticOpcode, TAdd { override final string toString() { result = "Add" } }
class Sub extends BinaryArithmeticOpcode, TSub { override final string toString() { result = "Sub" } }
class Mul extends BinaryArithmeticOpcode, TMul { override final string toString() { result = "Mul" } }
class Div extends BinaryArithmeticOpcode, TDiv { override final string toString() { result = "Div" } }
class Rem extends BinaryArithmeticOpcode, TRem { override final string toString() { result = "Rem" } }
class Negate extends UnaryArithmeticOpcode, TNegate { override final string toString() { result = "Negate" } }
class ShiftLeft extends BinaryBitwiseOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } }
class ShiftRight extends BinaryBitwiseOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } }
class BitAnd extends BinaryBitwiseOpcode, TBitAnd { override final string toString() { result = "BitAnd" } }
class BitOr extends BinaryBitwiseOpcode, TBitOr { override final string toString() { result = "BitOr" } }
class BitXor extends BinaryBitwiseOpcode, TBitXor { override final string toString() { result = "BitXor" } }
class BitComplement extends UnaryBitwiseOpcode, TBitComplement { override final string toString() { result = "BitComplement" } }
class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } }
class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } }
class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } }
class CompareLT extends RelationalOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
class CompareGT extends RelationalOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
class CompareLE extends RelationalOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
class CompareGE extends RelationalOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } }
class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } }
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } }
class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } }
class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } }
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } }
class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } }
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } }
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } }
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } }
class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } }
class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } }
class ElementsAddress extends UnaryOpcode, TElementsAddress { override final string toString() { result = "ElementsAddress" } }
class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } }
class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } }
class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } }
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } }
class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } }
class Call extends Opcode, TCall { override final string toString() { result = "Call" } }
class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } }
class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } }
class ThrowValue extends ThrowOpcode, OpcodeWithLoad, TThrowValue { override final string toString() { result = "ThrowValue" } }
class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } }
class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } }
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } }
class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } }
class AliasedDefinition extends Opcode, TAliasedDefinition { override final string toString() { result = "AliasedDefinition" } }
class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } }
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn { override final string toString() { result = "BuiltIn" } }
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } }
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOperationOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode, TIndirectWriteSideEffect { override final string toString() { result = "IndirectWriteSideEffect" } }
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode, TIndirectMayWriteSideEffect { override final string toString() { result = "IndirectMayWriteSideEffect" } }
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
class Chi extends Opcode, TChi { override final string toString() { result = "Chi" } }
class InlineAsm extends Opcode, TInlineAsm { override final string toString() { result = "InlineAsm" } }
class Unreached extends Opcode, TUnreached { override final string toString() { result = "Unreached" } }
class NewObj extends Opcode, TNewObj { override final string toString() { result = "NewObj" } }
class NoOp extends Opcode, TNoOp {
final override string toString() { result = "NoOp" }
}
class Uninitialized extends MemoryAccessOpcode, TUninitialized {
final override string toString() { result = "Uninitialized" }
}
class Error extends Opcode, TError {
final override string toString() { result = "Error" }
}
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter {
final override string toString() { result = "InitializeParameter" }
}
class InitializeThis extends Opcode, TInitializeThis {
final override string toString() { result = "InitializeThis" }
}
class EnterFunction extends Opcode, TEnterFunction {
final override string toString() { result = "EnterFunction" }
}
class ExitFunction extends Opcode, TExitFunction {
final override string toString() { result = "ExitFunction" }
}
class ReturnValue extends ReturnOpcode, OpcodeWithLoad, TReturnValue {
final override string toString() { result = "ReturnValue" }
}
class ReturnVoid extends ReturnOpcode, TReturnVoid {
final override string toString() { result = "ReturnVoid" }
}
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue {
final override string toString() { result = "CopyValue" }
}
class Load extends CopyOpcode, OpcodeWithLoad, TLoad {
final override string toString() { result = "Load" }
}
class Store extends CopyOpcode, MemoryAccessOpcode, TStore {
final override string toString() { result = "Store" }
}
class Add extends BinaryArithmeticOpcode, TAdd {
final override string toString() { result = "Add" }
}
class Sub extends BinaryArithmeticOpcode, TSub {
final override string toString() { result = "Sub" }
}
class Mul extends BinaryArithmeticOpcode, TMul {
final override string toString() { result = "Mul" }
}
class Div extends BinaryArithmeticOpcode, TDiv {
final override string toString() { result = "Div" }
}
class Rem extends BinaryArithmeticOpcode, TRem {
final override string toString() { result = "Rem" }
}
class Negate extends UnaryArithmeticOpcode, TNegate {
final override string toString() { result = "Negate" }
}
class ShiftLeft extends BinaryBitwiseOpcode, TShiftLeft {
final override string toString() { result = "ShiftLeft" }
}
class ShiftRight extends BinaryBitwiseOpcode, TShiftRight {
final override string toString() { result = "ShiftRight" }
}
class BitAnd extends BinaryBitwiseOpcode, TBitAnd {
final override string toString() { result = "BitAnd" }
}
class BitOr extends BinaryBitwiseOpcode, TBitOr {
final override string toString() { result = "BitOr" }
}
class BitXor extends BinaryBitwiseOpcode, TBitXor {
final override string toString() { result = "BitXor" }
}
class BitComplement extends UnaryBitwiseOpcode, TBitComplement {
final override string toString() { result = "BitComplement" }
}
class LogicalNot extends UnaryOpcode, TLogicalNot {
final override string toString() { result = "LogicalNot" }
}
class CompareEQ extends CompareOpcode, TCompareEQ {
final override string toString() { result = "CompareEQ" }
}
class CompareNE extends CompareOpcode, TCompareNE {
final override string toString() { result = "CompareNE" }
}
class CompareLT extends RelationalOpcode, TCompareLT {
final override string toString() { result = "CompareLT" }
}
class CompareGT extends RelationalOpcode, TCompareGT {
final override string toString() { result = "CompareGT" }
}
class CompareLE extends RelationalOpcode, TCompareLE {
final override string toString() { result = "CompareLE" }
}
class CompareGE extends RelationalOpcode, TCompareGE {
final override string toString() { result = "CompareGE" }
}
class PointerAdd extends PointerOffsetOpcode, TPointerAdd {
final override string toString() { result = "PointerAdd" }
}
class PointerSub extends PointerOffsetOpcode, TPointerSub {
final override string toString() { result = "PointerSub" }
}
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff {
final override string toString() { result = "PointerDiff" }
}
class Convert extends UnaryOpcode, TConvert {
final override string toString() { result = "Convert" }
}
class ConvertToBase extends UnaryOpcode, TConvertToBase {
final override string toString() { result = "ConvertToBase" }
}
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase {
final override string toString() { result = "ConvertToVirtualBase" }
}
class ConvertToDerived extends UnaryOpcode, TConvertToDerived {
final override string toString() { result = "ConvertToDerived" }
}
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull {
final override string toString() { result = "CheckedConvertOrNull" }
}
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow {
final override string toString() { result = "CheckedConvertOrThrow" }
}
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
final override string toString() { result = "DynamicCastToVoid" }
}
class VariableAddress extends Opcode, TVariableAddress {
final override string toString() { result = "VariableAddress" }
}
class FieldAddress extends UnaryOpcode, TFieldAddress {
final override string toString() { result = "FieldAddress" }
}
class ElementsAddress extends UnaryOpcode, TElementsAddress {
final override string toString() { result = "ElementsAddress" }
}
class FunctionAddress extends Opcode, TFunctionAddress {
final override string toString() { result = "FunctionAddress" }
}
class Constant extends Opcode, TConstant {
final override string toString() { result = "Constant" }
}
class StringConstant extends Opcode, TStringConstant {
final override string toString() { result = "StringConstant" }
}
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch {
final override string toString() { result = "ConditionalBranch" }
}
class Switch extends OpcodeWithCondition, TSwitch {
final override string toString() { result = "Switch" }
}
class Call extends Opcode, TCall {
final override string toString() { result = "Call" }
}
class CatchByType extends CatchOpcode, TCatchByType {
final override string toString() { result = "CatchByType" }
}
class CatchAny extends CatchOpcode, TCatchAny {
final override string toString() { result = "CatchAny" }
}
class ThrowValue extends ThrowOpcode, OpcodeWithLoad, TThrowValue {
final override string toString() { result = "ThrowValue" }
}
class ReThrow extends ThrowOpcode, TReThrow {
final override string toString() { result = "ReThrow" }
}
class Unwind extends Opcode, TUnwind {
final override string toString() { result = "Unwind" }
}
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition {
final override string toString() { result = "UnmodeledDefinition" }
}
class UnmodeledUse extends Opcode, TUnmodeledUse {
final override string toString() { result = "UnmodeledUse" }
}
class AliasedDefinition extends Opcode, TAliasedDefinition {
final override string toString() { result = "AliasedDefinition" }
}
class Phi extends Opcode, TPhi {
final override string toString() { result = "Phi" }
}
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn {
final override string toString() { result = "BuiltIn" }
}
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart {
final override string toString() { result = "VarArgsStart" }
}
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd {
final override string toString() { result = "VarArgsEnd" }
}
class VarArg extends BuiltInOperationOpcode, TVarArg {
final override string toString() { result = "VarArg" }
}
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy {
final override string toString() { result = "VarArgCopy" }
}
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect {
final override string toString() { result = "CallSideEffect" }
}
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect {
final override string toString() { result = "CallReadSideEffect" }
}
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode,
TIndirectReadSideEffect {
final override string toString() { result = "IndirectReadSideEffect" }
}
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode,
TIndirectWriteSideEffect {
final override string toString() { result = "IndirectWriteSideEffect" }
}
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode,
TIndirectMayWriteSideEffect {
final override string toString() { result = "IndirectMayWriteSideEffect" }
}
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect {
final override string toString() { result = "BufferReadSideEffect" }
}
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode,
TBufferWriteSideEffect {
final override string toString() { result = "BufferWriteSideEffect" }
}
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode,
TBufferMayWriteSideEffect {
final override string toString() { result = "BufferMayWriteSideEffect" }
}
class Chi extends Opcode, TChi {
final override string toString() { result = "Chi" }
}
class InlineAsm extends Opcode, TInlineAsm {
final override string toString() { result = "InlineAsm" }
}
class Unreached extends Opcode, TUnreached {
final override string toString() { result = "Unreached" }
}
class NewObj extends Opcode, TNewObj {
final override string toString() { result = "NewObj" }
}
}

View File

@@ -2,7 +2,5 @@ private import internal.TempVariableTagInternal
private import Imports::TempVariableTag
class TempVariableTag extends TTempVariableTag {
string toString() {
result = getTempVariableTagId(this)
}
string toString() { result = getTempVariableTagId(this) }
}

View File

@@ -15,21 +15,15 @@ private newtype TIRPropertyProvider = MkIRPropertyProvider()
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
string toString() { result = "IRPropertyProvider" }
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
string getInstructionProperty(Instruction instruction, string key) { none() }
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
string getBlockProperty(IRBlock block, string key) { none() }
}

View File

@@ -16,32 +16,25 @@ private import Cached
* Most consumers should use the class `IRBlock`.
*/
class IRBlockBase extends TIRBlock {
final string toString() {
result = getFirstInstruction(this).toString()
}
final string toString() { result = getFirstInstruction(this).toString() }
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
final string getUniqueId() {
result = getFirstInstruction(this).getUniqueId()
}
/**
* Gets the zero-based index of the block within its function. This is used
* by debugging and printing code only.
*/
int getDisplayIndex() {
this = rank[result + 1](IRBlock funcBlock |
funcBlock.getEnclosingFunction() = getEnclosingFunction() |
funcBlock order by funcBlock.getUniqueId()
)
funcBlock.getEnclosingFunction() = getEnclosingFunction()
|
funcBlock order by funcBlock.getUniqueId()
)
}
final Instruction getInstruction(int index) {
result = getInstruction(this, index)
}
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
@@ -52,17 +45,11 @@ class IRBlockBase extends TIRBlock {
result = getAPhiInstruction()
}
final Instruction getFirstInstruction() {
result = getFirstInstruction(this)
}
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
final Instruction getLastInstruction() {
result = getInstruction(getInstructionCount() - 1)
}
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
final int getInstructionCount() {
result = getInstructionCount(this)
}
final int getInstructionCount() { result = getInstructionCount(this) }
final IRFunction getEnclosingIRFunction() {
result = getFirstInstruction(this).getEnclosingIRFunction()
@@ -79,40 +66,26 @@ class IRBlockBase extends TIRBlock {
* instruction of another block.
*/
class IRBlock extends IRBlockBase {
final IRBlock getASuccessor() {
blockSuccessor(this, result)
}
final IRBlock getASuccessor() { blockSuccessor(this, result) }
final IRBlock getAPredecessor() {
blockSuccessor(result, this)
}
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
final IRBlock getSuccessor(EdgeKind kind) {
blockSuccessor(this, result, kind)
}
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
final IRBlock getBackEdgeSuccessor(EdgeKind kind) {
backEdgeSuccessor(this, result, kind)
}
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
final predicate immediatelyDominates(IRBlock block) {
blockImmediatelyDominates(this, block)
}
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
final predicate strictlyDominates(IRBlock block) {
blockImmediatelyDominates+(this, block)
}
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
final predicate dominates(IRBlock block) {
strictlyDominates(block) or this = block
}
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
pragma[noinline]
final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
@@ -125,22 +98,21 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) or // Incoming edge is not a GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
) // A back edge enters this instruction
)
}
@@ -148,11 +120,10 @@ private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
cached
private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
@@ -165,15 +136,16 @@ private cached module Cached {
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
cached
Instruction getInstruction(TIRBlock block, int index) {
result = getInstructionFromFirst(getFirstInstruction(block), index)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached
int getInstructionCount(TIRBlock block) { result = strictcount(getInstruction(block, _)) }
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
@@ -185,7 +157,8 @@ private cached module Cached {
private predicate blockIdentity(TIRBlock b1, TIRBlock b2) { b1 = b2 }
pragma[noopt]
cached predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
backEdgeSuccessorRaw(pred, succ, kind)
or
// See the QLDoc on `backEdgeSuccessorRaw`.
@@ -226,14 +199,12 @@ private cached module Cached {
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ) { blockSuccessor(pred, succ, _) }
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
cached
predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }

View File

@@ -2,9 +2,7 @@ private import internal.IRInternal
import Instruction
private newtype TIRFunction =
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
MkIRFunction(Language::Function func) { Construction::functionHasIR(func) }
/**
* Represents the IR for a function.
@@ -12,27 +10,19 @@ private newtype TIRFunction =
class IRFunction extends TIRFunction {
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
}
IRFunction() { this = MkIRFunction(func) }
final string toString() {
result = "IR: " + func.toString()
}
final string toString() { result = "IR: " + func.toString() }
/**
* Gets the function whose IR is represented.
*/
final Language::Function getFunction() {
result = func
}
final Language::Function getFunction() { result = func }
/**
* Gets the location of the function.
*/
final Language::Location getLocation() {
result = func.getLocation()
}
final Language::Location getLocation() { result = func.getLocation() }
/**
* Gets the entry point for this function.
@@ -64,38 +54,28 @@ class IRFunction extends TIRFunction {
* Gets the single return instruction for this function.
*/
pragma[noinline]
final ReturnInstruction getReturnInstruction() {
result.getEnclosingIRFunction() = this
}
final ReturnInstruction getReturnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold.
*/
pragma[noinline]
final IRReturnVariable getReturnVariable() {
result.getEnclosingIRFunction() = this
}
final IRReturnVariable getReturnVariable() { result.getEnclosingIRFunction() = this }
/**
* Gets the block containing the entry point of this function.
*/
*/
pragma[noinline]
final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction()
}
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
/**
* Gets all instructions in this function.
*/
final Instruction getAnInstruction() {
result.getEnclosingIRFunction() = this
}
final Instruction getAnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets all blocks in this function.
*/
final IRBlock getABlock() {
result.getEnclosingIRFunction() = this
}
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
}

View File

@@ -1,3 +1,2 @@
private import IR
import InstructionSanity

View File

@@ -37,27 +37,21 @@ abstract class IRVariable extends TIRVariable {
* within the function.
*/
abstract string getUniqueId();
/**
* Gets the source location of this variable.
*/
final Language::Location getLocation() {
result = getAST().getLocation()
}
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() {
result.getFunction() = func
}
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
/**
* Gets the function that references this variable.
*/
final Language::Function getEnclosingFunction() {
result = func
}
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -65,34 +59,25 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
IRUserVariable() { this = TIRUserVariable(var, type, func) }
override final string toString() {
result = getVariable().toString()
}
final override string toString() { result = getVariable().toString() }
override final Language::AST getAST() {
result = var
}
final override Language::AST getAST() { result = var }
override final string getUniqueId() {
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
/**
* Gets the original user-declared variable.
*/
Language::Variable getVariable() {
result = var
}
Language::Variable getVariable() { result = var }
}
/**
@@ -100,31 +85,22 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable {
}
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
Language::isVariableAutomatic(var)
}
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() {
result = var
}
final override Language::AutomaticVariable getVariable() { result = var }
}
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
not Language::isVariableAutomatic(var)
}
IRStaticUserVariable() { not Language::isVariableAutomatic(var) }
final override Language::StaticVariable getVariable() {
result = var
}
final override Language::StaticVariable getVariable() { result = var }
}
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
@@ -134,55 +110,39 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
override final Language::AST getAST() {
result = ast
}
final override Language::AST getAST() { result = ast }
override final string getUniqueId() {
final override string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this)
}
final TempVariableTag getTag() {
result = tag
}
final TempVariableTag getTag() { result = tag }
override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString()
ast.getLocation().getStartColumn().toString()
}
string getBaseString() {
result = "#temp"
}
string getBaseString() { result = "#temp" }
}
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() {
tag = ReturnValueTempVar()
}
IRReturnVariable() { tag = ReturnValueTempVar() }
override final string toString() {
result = "#return"
}
final override string toString() { result = "#return" }
}
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() {
tag = ThrowTempVar()
}
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() {
result = "#throw"
}
override string getBaseString() { result = "#throw" }
}

View File

@@ -12,11 +12,15 @@ private newtype TOperand =
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
@@ -46,24 +50,16 @@ private predicate isInCycle(Instruction instr) {
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
class Operand extends TOperand {
string toString() {
result = "Operand"
}
string toString() { result = "Operand" }
final Language::Location getLocation() {
result = getUse().getLocation()
}
final Language::Location getLocation() { result = getUse().getLocation() }
final IRFunction getEnclosingIRFunction() {
result = getUse().getEnclosingIRFunction()
}
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
/**
* Gets the `Instruction` that consumes this operand.
*/
Instruction getUse() {
none()
}
Instruction getUse() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -71,9 +67,7 @@ class Operand extends TOperand {
* means that the resulting instruction may only _partially_ or _potentially_
* be the value of this operand.
*/
Instruction getAnyDef() {
none()
}
Instruction getAnyDef() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -91,10 +85,7 @@ class Operand extends TOperand {
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated
final Instruction getUseInstruction() {
result = getUse()
}
deprecated final Instruction getUseInstruction() { result = getUse() }
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -103,31 +94,22 @@ class Operand extends TOperand {
*
* Gets the `Instruction` whose result is the value of the operand.
*/
deprecated
final Instruction getDefinitionInstruction() {
result = getAnyDef()
}
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
/**
* Gets the overlap relationship between the operand's definition and its use.
*/
Overlap getDefinitionOverlap() {
none()
}
Overlap getDefinitionOverlap() { none() }
/**
* Holds if the result of the definition instruction does not exactly overlap this use.
*/
final predicate isDefinitionInexact() {
not getDefinitionOverlap() instanceof MustExactlyOverlap
}
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
/**
* Gets a prefix to use when dumping the operand in an operand list.
*/
string getDumpLabel() {
result = ""
}
string getDumpLabel() { result = "" }
/**
* Gets a string describing this operand, suitable for display in IR dumps. This consists of the
@@ -146,18 +128,13 @@ class Operand extends TOperand {
* the empty string.
*/
private string getInexactSpecifier() {
if isDefinitionInexact() then
result = "~"
else
result = ""
if isDefinitionInexact() then result = "~" else result = ""
}
/**
* Get the order in which the operand should be sorted in the operand list.
*/
int getDumpSortOrder() {
result = -1
}
int getDumpSortOrder() { result = -1 }
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
@@ -166,9 +143,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Language::Type getType() {
result = getAnyDef().getResultType()
}
Language::Type getType() { result = getAnyDef().getResultType() }
/**
* Holds if the value consumed by this operand is a glvalue. If this
@@ -177,17 +152,13 @@ class Operand extends TOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getAnyDef().isGLValue()
}
predicate isGLValue() { getAnyDef().isGLValue() }
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = Language::getTypeSize(getType())
}
int getSize() { result = Language::getTypeSize(getType()) }
}
/**
@@ -207,9 +178,7 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() {
none()
}
MemoryAccessKind getMemoryAccess() { none() }
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -227,7 +196,9 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -235,25 +206,15 @@ class NonPhiOperand extends Operand {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
}
override final Instruction getUse() {
result = useInstr
}
final override Instruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final string getDumpLabel() {
result = tag.getLabel()
}
final override string getDumpLabel() { result = tag.getLabel() }
override final int getDumpSortOrder() {
result = tag.getSortOrder()
}
final override int getDumpSortOrder() { result = tag.getSortOrder() }
final OperandTag getOperandTag() {
result = tag
}
final OperandTag getOperandTag() { result = tag }
}
/**
@@ -262,7 +223,7 @@ class NonPhiOperand extends Operand {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
override final Overlap getDefinitionOverlap() {
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
result instanceof MustExactlyOverlap
}
@@ -270,21 +231,18 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
}
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
}
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Language::Type getType() {
final override Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -296,9 +254,7 @@ class TypedOperand extends NonPhiMemoryOperand {
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() {
result = "Address"
}
override string toString() { result = "Address" }
}
/**
@@ -308,13 +264,9 @@ class AddressOperand extends RegisterOperand {
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
}
override string toString() { result = "Load" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof IndirectMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -323,9 +275,7 @@ class LoadOperand extends TypedOperand {
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
}
override string toString() { result = "StoreValue" }
}
/**
@@ -334,9 +284,7 @@ class StoreValueOperand extends RegisterOperand {
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
}
override string toString() { result = "Unary" }
}
/**
@@ -345,9 +293,7 @@ class UnaryOperand extends RegisterOperand {
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() {
result = "Left"
}
override string toString() { result = "Left" }
}
/**
@@ -356,9 +302,7 @@ class LeftOperand extends RegisterOperand {
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() {
result = "Right"
}
override string toString() { result = "Right" }
}
/**
@@ -367,9 +311,7 @@ class RightOperand extends RegisterOperand {
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
}
override string toString() { result = "Condition" }
}
/**
@@ -379,13 +321,9 @@ class ConditionOperand extends RegisterOperand {
class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
}
override string toString() { result = "UnmodeledUse" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -394,9 +332,7 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
}
override string toString() { result = "CallTarget" }
}
/**
@@ -415,9 +351,7 @@ class ArgumentOperand extends RegisterOperand {
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
}
override string toString() { result = "ThisArgument" }
}
/**
@@ -425,32 +359,26 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
argIndex = tag.getArgIndex()
}
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() {
result = "Arg(" + argIndex + ")"
}
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
final int getIndex() { result = argIndex }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = Language::getTypeSize(getType())
final override int getSize() {
if getType() instanceof Language::UnknownType
then result = Construction::getInstructionOperandSize(useInstr, tag)
else result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {
@@ -485,48 +413,35 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() {
this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() {
result = "Phi"
}
override string toString() { result = "Phi" }
override final PhiInstruction getUse() {
result = useInstr
}
final override PhiInstruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
override final int getDumpSortOrder() {
result = 11 + getPredecessorBlock().getDisplayIndex()
}
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
override final string getDumpLabel() {
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
}
/**
* Gets the predecessor block from which this value comes.
*/
final IRBlock getPredecessorBlock() {
result = predecessorBlock
}
final IRBlock getPredecessorBlock() { result = predecessorBlock }
override final MemoryAccessKind getMemoryAccess() {
result instanceof PhiMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof PhiMemoryAccess }
}
/**
@@ -535,27 +450,18 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() {
result = "ChiTotal"
}
override string toString() { result = "ChiTotal" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiTotalMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
/**
* The partial operand of a Chi node, representing the value being written to part of the memory.
*/
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() {
result = "ChiPartial"
}
override string toString() { result = "ChiPartial" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiPartialMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -9,23 +9,17 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
string toString() { result = "PrintIRConfiguration" }
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Function func) {
any()
}
predicate shouldPrintFunction(Language::Function func) { any() }
}
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
/**
@@ -38,27 +32,17 @@ private class FilteredIRConfiguration extends IRConfiguration {
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
exists(IRPropertyProvider provider | result = provider.getBlockProperty(block, key))
}
private newtype TPrintableIRNode =
TPrintableIRFunction(IRFunction irFunc) {
shouldPrintFunction(irFunc.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getEnclosingFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getEnclosingFunction())
}
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
/**
* A node to be emitted in the IR graph.
@@ -85,29 +69,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
* Gets the parent of this node.
*/
abstract PrintableIRNode getParent();
/**
* Gets the kind of graph represented by this node ("graph" or "tree").
*/
string getGraphKind() {
none()
}
string getGraphKind() { none() }
/**
* Holds if this node should always be rendered as text, even in a graphical
* viewer.
*/
predicate forceText() {
none()
}
predicate forceText() { none() }
/**
* Gets the value of the node property with the specified key.
*/
string getProperty(string key) {
key = "semmle.label" and result = getLabel() or
key = "semmle.order" and result = getOrder().toString() or
key = "semmle.graphKind" and result = getGraphKind() or
key = "semmle.label" and result = getLabel()
or
key = "semmle.order" and result = getOrder().toString()
or
key = "semmle.graphKind" and result = getGraphKind()
or
key = "semmle.forceText" and forceText() and result = "true"
}
}
@@ -118,37 +101,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
IRFunction irFunc;
PrintableIRFunction() {
this = TPrintableIRFunction(irFunc)
}
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
override string toString() {
result = irFunc.toString()
}
override string toString() { result = irFunc.toString() }
override Language::Location getLocation() {
result = irFunc.getLocation()
}
override Language::Location getLocation() { result = irFunc.getLocation() }
override string getLabel() {
result = Language::getIdentityString(irFunc.getFunction())
}
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
)
location = orderedFunc.getIRFunction().getLocation()
|
orderedFunc
order by
location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(),
orderedFunc.getLabel()
)
}
override final PrintableIRNode getParent() {
none()
}
final override PrintableIRNode getParent() { none() }
final IRFunction getIRFunction() {
result = irFunc
}
final IRFunction getIRFunction() { result = irFunc }
}
/**
@@ -157,35 +131,21 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
IRBlock block;
PrintableIRBlock() {
this = TPrintableIRBlock(block)
}
PrintableIRBlock() { this = TPrintableIRBlock(block) }
override string toString() {
result = getLabel()
}
override string toString() { result = getLabel() }
override Language::Location getLocation() {
result = block.getLocation()
}
override Language::Location getLocation() { result = block.getLocation() }
override string getLabel() {
result = "Block " + block.getDisplayIndex().toString()
}
override string getLabel() { result = "Block " + block.getDisplayIndex().toString() }
override int getOrder() {
result = block.getDisplayIndex()
}
override int getOrder() { result = block.getDisplayIndex() }
override final string getGraphKind() {
result = "tree"
}
final override string getGraphKind() { result = "tree" }
override final predicate forceText() {
any()
}
final override predicate forceText() { any() }
override final PrintableIRFunction getParent() {
final override PrintableIRFunction getParent() {
result.getIRFunction() = block.getEnclosingIRFunction()
}
@@ -194,9 +154,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
final IRBlock getBlock() { result = block }
}
/**
@@ -205,45 +163,35 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
Instruction instr;
PrintableInstruction() {
this = TPrintableInstruction(instr)
}
PrintableInstruction() { this = TPrintableInstruction(instr) }
override string toString() {
result = instr.toString()
}
override string toString() { result = instr.toString() }
override Language::Location getLocation() {
result = instr.getLocation()
}
override Language::Location getLocation() { result = instr.getLocation() }
override string getLabel() {
exists(IRBlock block |
instr = block.getAnInstruction() and
exists(string resultString, string operationString, string operandsString,
int resultWidth, int operationWidth |
exists(
string resultString, string operationString, string operandsString, int resultWidth,
int operationWidth
|
resultString = instr.getResultString() and
operationString = instr.getOperationString() and
operandsString = instr.getOperandsString() and
columnWidths(block, resultWidth, operationWidth) and
result = resultString + getPaddingString(resultWidth - resultString.length()) +
" = " + operationString + getPaddingString(operationWidth - operationString.length()) +
" : " + operandsString
result = resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
operationString + getPaddingString(operationWidth - operationString.length()) + " : " +
operandsString
)
)
}
override int getOrder() {
result = instr.getDisplayIndexInBlock()
}
override int getOrder() { result = instr.getDisplayIndexInBlock() }
override final PrintableIRBlock getParent() {
result.getBlock() = instr.getBlock()
}
final override PrintableIRBlock getParent() { result.getBlock() = instr.getBlock() }
final Instruction getInstruction() {
result = instr
}
final Instruction getInstruction() { result = instr }
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
@@ -253,19 +201,26 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {
resultWidth = max(Instruction instr | instr.getBlock() = block | instr.getResultString().length()) and
operationWidth = max(Instruction instr | instr.getBlock() = block | instr.getOperationString().length())
operationWidth = max(Instruction instr |
instr.getBlock() = block
|
instr.getOperationString().length()
)
}
private int maxColumnWidth() {
result = max(Instruction instr, int width |
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length() |
width)
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length()
|
width
)
}
private string getPaddingString(int n) {
n = 0 and result = "" or
n = 0 and result = ""
or
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
}
@@ -275,9 +230,10 @@ query predicate nodes(PrintableIRNode node, string key, string value) {
private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
succ = rank[result + 1](IRBlock aSucc, EdgeKind kind |
aSucc = pred.getSuccessor(kind) |
aSucc order by kind.toString()
)
aSucc = pred.getSuccessor(kind)
|
aSucc order by kind.toString()
)
}
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
@@ -291,11 +247,10 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
if predBlock.getBackEdgeSuccessor(kind) = succBlock
then value = kind.toString() + " (back edge)"
else value = kind.toString()
) or
(
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
or
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
)
}

View File

@@ -13,14 +13,10 @@ private newtype TOperandTag =
TUnmodeledUseOperand() or
TCallTargetOperand() or
TThisArgumentOperand() or
TPositionalArgumentOperand(int argIndex) {
Language::hasPositionalArgIndex(argIndex)
} or
TPositionalArgumentOperand(int argIndex) { Language::hasPositionalArgIndex(argIndex) } or
TChiTotalOperand() or
TChiPartialOperand() or
TAsmOperand(int index) {
Language::hasAsmOperandIndex(index)
}
TAsmOperand(int index) { Language::hasAsmOperandIndex(index) }
/**
* Identifies the kind of operand on an instruction. Each `Instruction` has at
@@ -28,291 +24,195 @@ private newtype TOperandTag =
* an `Instruction` is determined by the instruction's opcode.
*/
abstract class OperandTag extends TOperandTag {
abstract string toString();
abstract string toString();
abstract int getSortOrder();
abstract int getSortOrder();
string getLabel() {
result = ""
}
string getLabel() { result = "" }
}
/**
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
abstract class MemoryOperandTag extends OperandTag {
}
abstract class MemoryOperandTag extends OperandTag { }
/**
* An operand that consumes a register (non-memory) result.
*/
abstract class RegisterOperandTag extends OperandTag {
}
abstract class RegisterOperandTag extends OperandTag { }
/**
* A memory operand whose type may be different from the result type of its definition instruction.
*/
abstract class TypedOperandTag extends MemoryOperandTag {
}
abstract class TypedOperandTag extends MemoryOperandTag { }
// 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`, `InitializeParameter`, `IndirectReadSideEffect`).
*/
class AddressOperandTag extends RegisterOperandTag, TAddressOperand {
override final string toString() {
result = "Address"
}
final override string toString() { result = "Address" }
override final int getSortOrder() {
result = 0
}
override final string getLabel() {
result = "&:"
}
final override int getSortOrder() { result = 0 }
final override string getLabel() { result = "&:" }
}
AddressOperandTag addressOperand() {
result = TAddressOperand()
}
AddressOperandTag addressOperand() { result = TAddressOperand() }
/**
* The buffer size operand of an instruction that represents a read or write of
* a buffer.
*/
class BufferSizeOperand extends RegisterOperandTag, TBufferSizeOperand {
override final string toString() {
result = "BufferSize"
}
final override string toString() { result = "BufferSize" }
override final int getSortOrder() {
result = 1
}
final override int getSortOrder() { result = 1 }
}
/**
* The operand representing the read side effect of a `SideEffectInstruction`.
*/
class SideEffectOperandTag extends TypedOperandTag, TSideEffectOperand {
override final string toString() {
result = "SideEffect"
}
final override string toString() { result = "SideEffect" }
override final int getSortOrder() {
result = 2
}
final override int getSortOrder() { result = 2 }
}
SideEffectOperandTag sideEffectOperand() {
result = TSideEffectOperand()
}
SideEffectOperandTag sideEffectOperand() { result = TSideEffectOperand() }
/**
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperandTag extends TypedOperandTag, TLoadOperand {
override final string toString() {
result = "Load"
}
final override string toString() { result = "Load" }
override final int getSortOrder() {
result = 3
}
final override int getSortOrder() { result = 3 }
}
LoadOperandTag loadOperand() {
result = TLoadOperand()
}
LoadOperandTag loadOperand() { result = TLoadOperand() }
/**
* The source value operand of a `Store` instruction.
*/
class StoreValueOperandTag extends RegisterOperandTag, TStoreValueOperand {
override final string toString() {
result = "StoreValue"
}
final override string toString() { result = "StoreValue" }
override final int getSortOrder() {
result = 4
}
final override int getSortOrder() { result = 4 }
}
StoreValueOperandTag storeValueOperand() {
result = TStoreValueOperand()
}
StoreValueOperandTag storeValueOperand() { result = TStoreValueOperand() }
/**
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
*/
class UnaryOperandTag extends RegisterOperandTag, TUnaryOperand {
override final string toString() {
result = "Unary"
}
final override string toString() { result = "Unary" }
override final int getSortOrder() {
result = 5
}
final override int getSortOrder() { result = 5 }
}
UnaryOperandTag unaryOperand() {
result = TUnaryOperand()
}
UnaryOperandTag unaryOperand() { result = TUnaryOperand() }
/**
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class LeftOperandTag extends RegisterOperandTag, TLeftOperand {
override final string toString() {
result = "Left"
}
final override string toString() { result = "Left" }
override final int getSortOrder() {
result = 6
}
final override int getSortOrder() { result = 6 }
}
LeftOperandTag leftOperand() {
result = TLeftOperand()
}
LeftOperandTag leftOperand() { result = TLeftOperand() }
/**
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class RightOperandTag extends RegisterOperandTag, TRightOperand {
override final string toString() {
result = "Right"
}
final override string toString() { result = "Right" }
override final int getSortOrder() {
result = 7
}
final override int getSortOrder() { result = 7 }
}
RightOperandTag rightOperand() {
result = TRightOperand()
}
RightOperandTag rightOperand() { result = TRightOperand() }
/**
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperandTag extends RegisterOperandTag, TConditionOperand {
override final string toString() {
result = "Condition"
}
final override string toString() { result = "Condition" }
override final int getSortOrder() {
result = 8
}
final override int getSortOrder() { result = 8 }
}
ConditionOperandTag conditionOperand() {
result = TConditionOperand()
}
ConditionOperandTag conditionOperand() { result = TConditionOperand() }
/**
* An operand of the special `UnmodeledUse` instruction, representing a value
* whose set of uses is unknown.
*/
class UnmodeledUseOperandTag extends MemoryOperandTag, TUnmodeledUseOperand {
override final string toString() {
result = "UnmodeledUse"
}
final override string toString() { result = "UnmodeledUse" }
override final int getSortOrder() {
result = 9
}
final override int getSortOrder() { result = 9 }
}
UnmodeledUseOperandTag unmodeledUseOperand() {
result = TUnmodeledUseOperand()
}
UnmodeledUseOperandTag unmodeledUseOperand() { result = TUnmodeledUseOperand() }
/**
* The operand representing the target function of an `Call` instruction.
*/
class CallTargetOperandTag extends RegisterOperandTag, TCallTargetOperand {
override final string toString() {
result = "CallTarget"
}
final override string toString() { result = "CallTarget" }
override final int getSortOrder() {
result = 10
}
final override int getSortOrder() { result = 10 }
override final string getLabel() {
result = "func:"
}
final override string getLabel() { result = "func:" }
}
CallTargetOperandTag callTargetOperand() {
result = TCallTargetOperand()
}
CallTargetOperandTag 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 ArgumentOperandTag extends RegisterOperandTag {
}
abstract class ArgumentOperandTag extends RegisterOperandTag { }
/**
* An operand representing the implicit 'this' argument to a member function
* call.
*/
class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
ThisArgumentOperandTag() {
this = TThisArgumentOperand()
}
ThisArgumentOperandTag() { this = TThisArgumentOperand() }
override final string toString() {
result = "Arg(this)"
}
final override string toString() { result = "Arg(this)" }
override final int getSortOrder() {
result = 11
}
final override int getSortOrder() { result = 11 }
override final string getLabel() {
result = "this:"
}
final override string getLabel() { result = "this:" }
}
ThisArgumentOperandTag thisArgumentOperand() {
result = TThisArgumentOperand()
}
ThisArgumentOperandTag thisArgumentOperand() { result = TThisArgumentOperand() }
/**
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperandTag extends ArgumentOperandTag,
TPositionalArgumentOperand {
class PositionalArgumentOperandTag extends ArgumentOperandTag, TPositionalArgumentOperand {
int argIndex;
PositionalArgumentOperandTag() {
this = TPositionalArgumentOperand(argIndex)
}
PositionalArgumentOperandTag() { this = TPositionalArgumentOperand(argIndex) }
override final string toString() {
result = "Arg(" + argIndex + ")"
}
final override string toString() { result = "Arg(" + argIndex + ")" }
override final int getSortOrder() {
result = 12 + argIndex
}
final override int getSortOrder() { result = 12 + argIndex }
override final string getLabel() {
result = argIndex.toString() + ":"
}
final int getArgIndex() {
result = argIndex
}
final override string getLabel() { result = argIndex.toString() + ":" }
final int getArgIndex() { result = argIndex }
}
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
@@ -320,61 +220,35 @@ PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
}
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
override final string toString() {
result = "ChiTotal"
}
final override string toString() { result = "ChiTotal" }
override final int getSortOrder() {
result = 13
}
final override int getSortOrder() { result = 13 }
override final string getLabel() {
result = "total:"
}
final override string getLabel() { result = "total:" }
}
ChiTotalOperandTag chiTotalOperand() {
result = TChiTotalOperand()
}
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
override final string toString() {
result = "ChiPartial"
}
final override string toString() { result = "ChiPartial" }
override final int getSortOrder() {
result = 14
}
final override int getSortOrder() { result = 14 }
override final string getLabel() {
result = "partial:"
}
final override string getLabel() { result = "partial:" }
}
ChiPartialOperandTag chiPartialOperand() {
result = TChiPartialOperand()
}
ChiPartialOperandTag chiPartialOperand() { result = TChiPartialOperand() }
class AsmOperandTag extends RegisterOperandTag, TAsmOperand {
int index;
AsmOperandTag() {
this = TAsmOperand(index)
}
AsmOperandTag() { this = TAsmOperand(index) }
override final string toString() {
result = "AsmOperand(" + index + ")"
}
final override string toString() { result = "AsmOperand(" + index + ")" }
override final int getSortOrder() {
result = 15 + index
}
final override int getSortOrder() { result = 15 + index }
override final string getLabel() {
result = index.toString() + ":"
}
final override string getLabel() { result = index.toString() + ":" }
}
AsmOperandTag asmOperand(int index) {
result = TAsmOperand(index)
}
AsmOperandTag asmOperand(int index) { result = TAsmOperand(index) }

View File

@@ -2,11 +2,11 @@ private import TIRVariableInternal
private import Imports::TempVariableTag
newtype TIRVariable =
TIRUserVariable(Language::Variable var, Language::Type type,
Language::Function func) {
TIRUserVariable(Language::Variable var, Language::Type type, Language::Function func) {
Construction::hasUserVariable(func, var, type)
} or
TIRTempVariable(Language::Function func, Language::AST ast, TempVariableTag tag,
Language::Type type) {
TIRTempVariable(
Language::Function func, Language::AST ast, TempVariableTag tag, Language::Type type
) {
Construction::hasTempVariable(func, ast, tag, type)
}

View File

@@ -15,21 +15,15 @@ private newtype TIRPropertyProvider = MkIRPropertyProvider()
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
string toString() { result = "IRPropertyProvider" }
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
string getInstructionProperty(Instruction instruction, string key) { none() }
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
string getBlockProperty(IRBlock block, string key) { none() }
}

View File

@@ -16,32 +16,25 @@ private import Cached
* Most consumers should use the class `IRBlock`.
*/
class IRBlockBase extends TIRBlock {
final string toString() {
result = getFirstInstruction(this).toString()
}
final string toString() { result = getFirstInstruction(this).toString() }
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
final string getUniqueId() {
result = getFirstInstruction(this).getUniqueId()
}
/**
* Gets the zero-based index of the block within its function. This is used
* by debugging and printing code only.
*/
int getDisplayIndex() {
this = rank[result + 1](IRBlock funcBlock |
funcBlock.getEnclosingFunction() = getEnclosingFunction() |
funcBlock order by funcBlock.getUniqueId()
)
funcBlock.getEnclosingFunction() = getEnclosingFunction()
|
funcBlock order by funcBlock.getUniqueId()
)
}
final Instruction getInstruction(int index) {
result = getInstruction(this, index)
}
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
@@ -52,17 +45,11 @@ class IRBlockBase extends TIRBlock {
result = getAPhiInstruction()
}
final Instruction getFirstInstruction() {
result = getFirstInstruction(this)
}
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
final Instruction getLastInstruction() {
result = getInstruction(getInstructionCount() - 1)
}
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
final int getInstructionCount() {
result = getInstructionCount(this)
}
final int getInstructionCount() { result = getInstructionCount(this) }
final IRFunction getEnclosingIRFunction() {
result = getFirstInstruction(this).getEnclosingIRFunction()
@@ -79,40 +66,26 @@ class IRBlockBase extends TIRBlock {
* instruction of another block.
*/
class IRBlock extends IRBlockBase {
final IRBlock getASuccessor() {
blockSuccessor(this, result)
}
final IRBlock getASuccessor() { blockSuccessor(this, result) }
final IRBlock getAPredecessor() {
blockSuccessor(result, this)
}
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
final IRBlock getSuccessor(EdgeKind kind) {
blockSuccessor(this, result, kind)
}
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
final IRBlock getBackEdgeSuccessor(EdgeKind kind) {
backEdgeSuccessor(this, result, kind)
}
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
final predicate immediatelyDominates(IRBlock block) {
blockImmediatelyDominates(this, block)
}
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
final predicate strictlyDominates(IRBlock block) {
blockImmediatelyDominates+(this, block)
}
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
final predicate dominates(IRBlock block) {
strictlyDominates(block) or this = block
}
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
pragma[noinline]
final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
@@ -125,22 +98,21 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) or // Incoming edge is not a GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
) // A back edge enters this instruction
)
}
@@ -148,11 +120,10 @@ private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
cached
private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
@@ -165,15 +136,16 @@ private cached module Cached {
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
cached
Instruction getInstruction(TIRBlock block, int index) {
result = getInstructionFromFirst(getFirstInstruction(block), index)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached
int getInstructionCount(TIRBlock block) { result = strictcount(getInstruction(block, _)) }
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
@@ -185,7 +157,8 @@ private cached module Cached {
private predicate blockIdentity(TIRBlock b1, TIRBlock b2) { b1 = b2 }
pragma[noopt]
cached predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
backEdgeSuccessorRaw(pred, succ, kind)
or
// See the QLDoc on `backEdgeSuccessorRaw`.
@@ -226,14 +199,12 @@ private cached module Cached {
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ) { blockSuccessor(pred, succ, _) }
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
cached
predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }

View File

@@ -2,9 +2,7 @@ private import internal.IRInternal
import Instruction
private newtype TIRFunction =
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
MkIRFunction(Language::Function func) { Construction::functionHasIR(func) }
/**
* Represents the IR for a function.
@@ -12,27 +10,19 @@ private newtype TIRFunction =
class IRFunction extends TIRFunction {
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
}
IRFunction() { this = MkIRFunction(func) }
final string toString() {
result = "IR: " + func.toString()
}
final string toString() { result = "IR: " + func.toString() }
/**
* Gets the function whose IR is represented.
*/
final Language::Function getFunction() {
result = func
}
final Language::Function getFunction() { result = func }
/**
* Gets the location of the function.
*/
final Language::Location getLocation() {
result = func.getLocation()
}
final Language::Location getLocation() { result = func.getLocation() }
/**
* Gets the entry point for this function.
@@ -64,38 +54,28 @@ class IRFunction extends TIRFunction {
* Gets the single return instruction for this function.
*/
pragma[noinline]
final ReturnInstruction getReturnInstruction() {
result.getEnclosingIRFunction() = this
}
final ReturnInstruction getReturnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold.
*/
pragma[noinline]
final IRReturnVariable getReturnVariable() {
result.getEnclosingIRFunction() = this
}
final IRReturnVariable getReturnVariable() { result.getEnclosingIRFunction() = this }
/**
* Gets the block containing the entry point of this function.
*/
*/
pragma[noinline]
final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction()
}
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
/**
* Gets all instructions in this function.
*/
final Instruction getAnInstruction() {
result.getEnclosingIRFunction() = this
}
final Instruction getAnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets all blocks in this function.
*/
final IRBlock getABlock() {
result.getEnclosingIRFunction() = this
}
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
}

View File

@@ -1,3 +1,2 @@
private import IR
import InstructionSanity

View File

@@ -37,27 +37,21 @@ abstract class IRVariable extends TIRVariable {
* within the function.
*/
abstract string getUniqueId();
/**
* Gets the source location of this variable.
*/
final Language::Location getLocation() {
result = getAST().getLocation()
}
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() {
result.getFunction() = func
}
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
/**
* Gets the function that references this variable.
*/
final Language::Function getEnclosingFunction() {
result = func
}
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -65,34 +59,25 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
IRUserVariable() { this = TIRUserVariable(var, type, func) }
override final string toString() {
result = getVariable().toString()
}
final override string toString() { result = getVariable().toString() }
override final Language::AST getAST() {
result = var
}
final override Language::AST getAST() { result = var }
override final string getUniqueId() {
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
/**
* Gets the original user-declared variable.
*/
Language::Variable getVariable() {
result = var
}
Language::Variable getVariable() { result = var }
}
/**
@@ -100,31 +85,22 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable {
}
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
Language::isVariableAutomatic(var)
}
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() {
result = var
}
final override Language::AutomaticVariable getVariable() { result = var }
}
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
not Language::isVariableAutomatic(var)
}
IRStaticUserVariable() { not Language::isVariableAutomatic(var) }
final override Language::StaticVariable getVariable() {
result = var
}
final override Language::StaticVariable getVariable() { result = var }
}
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
@@ -134,55 +110,39 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
override final Language::AST getAST() {
result = ast
}
final override Language::AST getAST() { result = ast }
override final string getUniqueId() {
final override string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this)
}
final TempVariableTag getTag() {
result = tag
}
final TempVariableTag getTag() { result = tag }
override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString()
ast.getLocation().getStartColumn().toString()
}
string getBaseString() {
result = "#temp"
}
string getBaseString() { result = "#temp" }
}
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() {
tag = ReturnValueTempVar()
}
IRReturnVariable() { tag = ReturnValueTempVar() }
override final string toString() {
result = "#return"
}
final override string toString() { result = "#return" }
}
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() {
tag = ThrowTempVar()
}
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() {
result = "#throw"
}
override string getBaseString() { result = "#throw" }
}

View File

@@ -12,11 +12,15 @@ private newtype TOperand =
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
@@ -46,24 +50,16 @@ private predicate isInCycle(Instruction instr) {
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
class Operand extends TOperand {
string toString() {
result = "Operand"
}
string toString() { result = "Operand" }
final Language::Location getLocation() {
result = getUse().getLocation()
}
final Language::Location getLocation() { result = getUse().getLocation() }
final IRFunction getEnclosingIRFunction() {
result = getUse().getEnclosingIRFunction()
}
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
/**
* Gets the `Instruction` that consumes this operand.
*/
Instruction getUse() {
none()
}
Instruction getUse() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -71,9 +67,7 @@ class Operand extends TOperand {
* means that the resulting instruction may only _partially_ or _potentially_
* be the value of this operand.
*/
Instruction getAnyDef() {
none()
}
Instruction getAnyDef() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -91,10 +85,7 @@ class Operand extends TOperand {
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated
final Instruction getUseInstruction() {
result = getUse()
}
deprecated final Instruction getUseInstruction() { result = getUse() }
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -103,31 +94,22 @@ class Operand extends TOperand {
*
* Gets the `Instruction` whose result is the value of the operand.
*/
deprecated
final Instruction getDefinitionInstruction() {
result = getAnyDef()
}
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
/**
* Gets the overlap relationship between the operand's definition and its use.
*/
Overlap getDefinitionOverlap() {
none()
}
Overlap getDefinitionOverlap() { none() }
/**
* Holds if the result of the definition instruction does not exactly overlap this use.
*/
final predicate isDefinitionInexact() {
not getDefinitionOverlap() instanceof MustExactlyOverlap
}
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
/**
* Gets a prefix to use when dumping the operand in an operand list.
*/
string getDumpLabel() {
result = ""
}
string getDumpLabel() { result = "" }
/**
* Gets a string describing this operand, suitable for display in IR dumps. This consists of the
@@ -146,18 +128,13 @@ class Operand extends TOperand {
* the empty string.
*/
private string getInexactSpecifier() {
if isDefinitionInexact() then
result = "~"
else
result = ""
if isDefinitionInexact() then result = "~" else result = ""
}
/**
* Get the order in which the operand should be sorted in the operand list.
*/
int getDumpSortOrder() {
result = -1
}
int getDumpSortOrder() { result = -1 }
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
@@ -166,9 +143,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Language::Type getType() {
result = getAnyDef().getResultType()
}
Language::Type getType() { result = getAnyDef().getResultType() }
/**
* Holds if the value consumed by this operand is a glvalue. If this
@@ -177,17 +152,13 @@ class Operand extends TOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getAnyDef().isGLValue()
}
predicate isGLValue() { getAnyDef().isGLValue() }
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = Language::getTypeSize(getType())
}
int getSize() { result = Language::getTypeSize(getType()) }
}
/**
@@ -207,9 +178,7 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() {
none()
}
MemoryAccessKind getMemoryAccess() { none() }
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -227,7 +196,9 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -235,25 +206,15 @@ class NonPhiOperand extends Operand {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
}
override final Instruction getUse() {
result = useInstr
}
final override Instruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final string getDumpLabel() {
result = tag.getLabel()
}
final override string getDumpLabel() { result = tag.getLabel() }
override final int getDumpSortOrder() {
result = tag.getSortOrder()
}
final override int getDumpSortOrder() { result = tag.getSortOrder() }
final OperandTag getOperandTag() {
result = tag
}
final OperandTag getOperandTag() { result = tag }
}
/**
@@ -262,7 +223,7 @@ class NonPhiOperand extends Operand {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
override final Overlap getDefinitionOverlap() {
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
result instanceof MustExactlyOverlap
}
@@ -270,21 +231,18 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
}
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
}
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Language::Type getType() {
final override Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -296,9 +254,7 @@ class TypedOperand extends NonPhiMemoryOperand {
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() {
result = "Address"
}
override string toString() { result = "Address" }
}
/**
@@ -308,13 +264,9 @@ class AddressOperand extends RegisterOperand {
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
}
override string toString() { result = "Load" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof IndirectMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -323,9 +275,7 @@ class LoadOperand extends TypedOperand {
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
}
override string toString() { result = "StoreValue" }
}
/**
@@ -334,9 +284,7 @@ class StoreValueOperand extends RegisterOperand {
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
}
override string toString() { result = "Unary" }
}
/**
@@ -345,9 +293,7 @@ class UnaryOperand extends RegisterOperand {
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() {
result = "Left"
}
override string toString() { result = "Left" }
}
/**
@@ -356,9 +302,7 @@ class LeftOperand extends RegisterOperand {
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() {
result = "Right"
}
override string toString() { result = "Right" }
}
/**
@@ -367,9 +311,7 @@ class RightOperand extends RegisterOperand {
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
}
override string toString() { result = "Condition" }
}
/**
@@ -379,13 +321,9 @@ class ConditionOperand extends RegisterOperand {
class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
}
override string toString() { result = "UnmodeledUse" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -394,9 +332,7 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
}
override string toString() { result = "CallTarget" }
}
/**
@@ -415,9 +351,7 @@ class ArgumentOperand extends RegisterOperand {
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
}
override string toString() { result = "ThisArgument" }
}
/**
@@ -425,32 +359,26 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
argIndex = tag.getArgIndex()
}
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() {
result = "Arg(" + argIndex + ")"
}
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
final int getIndex() { result = argIndex }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = Language::getTypeSize(getType())
final override int getSize() {
if getType() instanceof Language::UnknownType
then result = Construction::getInstructionOperandSize(useInstr, tag)
else result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {
@@ -485,48 +413,35 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() {
this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() {
result = "Phi"
}
override string toString() { result = "Phi" }
override final PhiInstruction getUse() {
result = useInstr
}
final override PhiInstruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
override final int getDumpSortOrder() {
result = 11 + getPredecessorBlock().getDisplayIndex()
}
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
override final string getDumpLabel() {
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
}
/**
* Gets the predecessor block from which this value comes.
*/
final IRBlock getPredecessorBlock() {
result = predecessorBlock
}
final IRBlock getPredecessorBlock() { result = predecessorBlock }
override final MemoryAccessKind getMemoryAccess() {
result instanceof PhiMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof PhiMemoryAccess }
}
/**
@@ -535,27 +450,18 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() {
result = "ChiTotal"
}
override string toString() { result = "ChiTotal" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiTotalMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
/**
* The partial operand of a Chi node, representing the value being written to part of the memory.
*/
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() {
result = "ChiPartial"
}
override string toString() { result = "ChiPartial" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiPartialMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -9,23 +9,17 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
string toString() { result = "PrintIRConfiguration" }
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Function func) {
any()
}
predicate shouldPrintFunction(Language::Function func) { any() }
}
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
/**
@@ -38,27 +32,17 @@ private class FilteredIRConfiguration extends IRConfiguration {
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
exists(IRPropertyProvider provider | result = provider.getBlockProperty(block, key))
}
private newtype TPrintableIRNode =
TPrintableIRFunction(IRFunction irFunc) {
shouldPrintFunction(irFunc.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getEnclosingFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getEnclosingFunction())
}
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
/**
* A node to be emitted in the IR graph.
@@ -85,29 +69,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
* Gets the parent of this node.
*/
abstract PrintableIRNode getParent();
/**
* Gets the kind of graph represented by this node ("graph" or "tree").
*/
string getGraphKind() {
none()
}
string getGraphKind() { none() }
/**
* Holds if this node should always be rendered as text, even in a graphical
* viewer.
*/
predicate forceText() {
none()
}
predicate forceText() { none() }
/**
* Gets the value of the node property with the specified key.
*/
string getProperty(string key) {
key = "semmle.label" and result = getLabel() or
key = "semmle.order" and result = getOrder().toString() or
key = "semmle.graphKind" and result = getGraphKind() or
key = "semmle.label" and result = getLabel()
or
key = "semmle.order" and result = getOrder().toString()
or
key = "semmle.graphKind" and result = getGraphKind()
or
key = "semmle.forceText" and forceText() and result = "true"
}
}
@@ -118,37 +101,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
IRFunction irFunc;
PrintableIRFunction() {
this = TPrintableIRFunction(irFunc)
}
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
override string toString() {
result = irFunc.toString()
}
override string toString() { result = irFunc.toString() }
override Language::Location getLocation() {
result = irFunc.getLocation()
}
override Language::Location getLocation() { result = irFunc.getLocation() }
override string getLabel() {
result = Language::getIdentityString(irFunc.getFunction())
}
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
)
location = orderedFunc.getIRFunction().getLocation()
|
orderedFunc
order by
location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(),
orderedFunc.getLabel()
)
}
override final PrintableIRNode getParent() {
none()
}
final override PrintableIRNode getParent() { none() }
final IRFunction getIRFunction() {
result = irFunc
}
final IRFunction getIRFunction() { result = irFunc }
}
/**
@@ -157,35 +131,21 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
IRBlock block;
PrintableIRBlock() {
this = TPrintableIRBlock(block)
}
PrintableIRBlock() { this = TPrintableIRBlock(block) }
override string toString() {
result = getLabel()
}
override string toString() { result = getLabel() }
override Language::Location getLocation() {
result = block.getLocation()
}
override Language::Location getLocation() { result = block.getLocation() }
override string getLabel() {
result = "Block " + block.getDisplayIndex().toString()
}
override string getLabel() { result = "Block " + block.getDisplayIndex().toString() }
override int getOrder() {
result = block.getDisplayIndex()
}
override int getOrder() { result = block.getDisplayIndex() }
override final string getGraphKind() {
result = "tree"
}
final override string getGraphKind() { result = "tree" }
override final predicate forceText() {
any()
}
final override predicate forceText() { any() }
override final PrintableIRFunction getParent() {
final override PrintableIRFunction getParent() {
result.getIRFunction() = block.getEnclosingIRFunction()
}
@@ -194,9 +154,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
final IRBlock getBlock() { result = block }
}
/**
@@ -205,45 +163,35 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
Instruction instr;
PrintableInstruction() {
this = TPrintableInstruction(instr)
}
PrintableInstruction() { this = TPrintableInstruction(instr) }
override string toString() {
result = instr.toString()
}
override string toString() { result = instr.toString() }
override Language::Location getLocation() {
result = instr.getLocation()
}
override Language::Location getLocation() { result = instr.getLocation() }
override string getLabel() {
exists(IRBlock block |
instr = block.getAnInstruction() and
exists(string resultString, string operationString, string operandsString,
int resultWidth, int operationWidth |
exists(
string resultString, string operationString, string operandsString, int resultWidth,
int operationWidth
|
resultString = instr.getResultString() and
operationString = instr.getOperationString() and
operandsString = instr.getOperandsString() and
columnWidths(block, resultWidth, operationWidth) and
result = resultString + getPaddingString(resultWidth - resultString.length()) +
" = " + operationString + getPaddingString(operationWidth - operationString.length()) +
" : " + operandsString
result = resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
operationString + getPaddingString(operationWidth - operationString.length()) + " : " +
operandsString
)
)
}
override int getOrder() {
result = instr.getDisplayIndexInBlock()
}
override int getOrder() { result = instr.getDisplayIndexInBlock() }
override final PrintableIRBlock getParent() {
result.getBlock() = instr.getBlock()
}
final override PrintableIRBlock getParent() { result.getBlock() = instr.getBlock() }
final Instruction getInstruction() {
result = instr
}
final Instruction getInstruction() { result = instr }
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
@@ -253,19 +201,26 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {
resultWidth = max(Instruction instr | instr.getBlock() = block | instr.getResultString().length()) and
operationWidth = max(Instruction instr | instr.getBlock() = block | instr.getOperationString().length())
operationWidth = max(Instruction instr |
instr.getBlock() = block
|
instr.getOperationString().length()
)
}
private int maxColumnWidth() {
result = max(Instruction instr, int width |
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length() |
width)
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length()
|
width
)
}
private string getPaddingString(int n) {
n = 0 and result = "" or
n = 0 and result = ""
or
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
}
@@ -275,9 +230,10 @@ query predicate nodes(PrintableIRNode node, string key, string value) {
private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
succ = rank[result + 1](IRBlock aSucc, EdgeKind kind |
aSucc = pred.getSuccessor(kind) |
aSucc order by kind.toString()
)
aSucc = pred.getSuccessor(kind)
|
aSucc order by kind.toString()
)
}
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
@@ -291,11 +247,10 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
if predBlock.getBackEdgeSuccessor(kind) = succBlock
then value = kind.toString() + " (back edge)"
else value = kind.toString()
) or
(
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
or
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
)
}

View File

@@ -15,21 +15,15 @@ private newtype TIRPropertyProvider = MkIRPropertyProvider()
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
string toString() { result = "IRPropertyProvider" }
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
string getInstructionProperty(Instruction instruction, string key) { none() }
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
string getBlockProperty(IRBlock block, string key) { none() }
}

View File

@@ -16,32 +16,25 @@ private import Cached
* Most consumers should use the class `IRBlock`.
*/
class IRBlockBase extends TIRBlock {
final string toString() {
result = getFirstInstruction(this).toString()
}
final string toString() { result = getFirstInstruction(this).toString() }
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
final string getUniqueId() {
result = getFirstInstruction(this).getUniqueId()
}
/**
* Gets the zero-based index of the block within its function. This is used
* by debugging and printing code only.
*/
int getDisplayIndex() {
this = rank[result + 1](IRBlock funcBlock |
funcBlock.getEnclosingFunction() = getEnclosingFunction() |
funcBlock order by funcBlock.getUniqueId()
)
funcBlock.getEnclosingFunction() = getEnclosingFunction()
|
funcBlock order by funcBlock.getUniqueId()
)
}
final Instruction getInstruction(int index) {
result = getInstruction(this, index)
}
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
@@ -52,17 +45,11 @@ class IRBlockBase extends TIRBlock {
result = getAPhiInstruction()
}
final Instruction getFirstInstruction() {
result = getFirstInstruction(this)
}
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
final Instruction getLastInstruction() {
result = getInstruction(getInstructionCount() - 1)
}
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
final int getInstructionCount() {
result = getInstructionCount(this)
}
final int getInstructionCount() { result = getInstructionCount(this) }
final IRFunction getEnclosingIRFunction() {
result = getFirstInstruction(this).getEnclosingIRFunction()
@@ -79,40 +66,26 @@ class IRBlockBase extends TIRBlock {
* instruction of another block.
*/
class IRBlock extends IRBlockBase {
final IRBlock getASuccessor() {
blockSuccessor(this, result)
}
final IRBlock getASuccessor() { blockSuccessor(this, result) }
final IRBlock getAPredecessor() {
blockSuccessor(result, this)
}
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
final IRBlock getSuccessor(EdgeKind kind) {
blockSuccessor(this, result, kind)
}
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
final IRBlock getBackEdgeSuccessor(EdgeKind kind) {
backEdgeSuccessor(this, result, kind)
}
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
final predicate immediatelyDominates(IRBlock block) {
blockImmediatelyDominates(this, block)
}
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
final predicate strictlyDominates(IRBlock block) {
blockImmediatelyDominates+(this, block)
}
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
final predicate dominates(IRBlock block) {
strictlyDominates(block) or this = block
}
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
pragma[noinline]
final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
@@ -125,22 +98,21 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) or // Incoming edge is not a GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
) // A back edge enters this instruction
)
}
@@ -148,11 +120,10 @@ private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
cached
private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
@@ -165,15 +136,16 @@ private cached module Cached {
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
cached
Instruction getInstruction(TIRBlock block, int index) {
result = getInstructionFromFirst(getFirstInstruction(block), index)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached
int getInstructionCount(TIRBlock block) { result = strictcount(getInstruction(block, _)) }
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
@@ -185,7 +157,8 @@ private cached module Cached {
private predicate blockIdentity(TIRBlock b1, TIRBlock b2) { b1 = b2 }
pragma[noopt]
cached predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
backEdgeSuccessorRaw(pred, succ, kind)
or
// See the QLDoc on `backEdgeSuccessorRaw`.
@@ -226,14 +199,12 @@ private cached module Cached {
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ) { blockSuccessor(pred, succ, _) }
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
cached
predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }

View File

@@ -2,9 +2,7 @@ private import internal.IRInternal
import Instruction
private newtype TIRFunction =
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
MkIRFunction(Language::Function func) { Construction::functionHasIR(func) }
/**
* Represents the IR for a function.
@@ -12,27 +10,19 @@ private newtype TIRFunction =
class IRFunction extends TIRFunction {
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
}
IRFunction() { this = MkIRFunction(func) }
final string toString() {
result = "IR: " + func.toString()
}
final string toString() { result = "IR: " + func.toString() }
/**
* Gets the function whose IR is represented.
*/
final Language::Function getFunction() {
result = func
}
final Language::Function getFunction() { result = func }
/**
* Gets the location of the function.
*/
final Language::Location getLocation() {
result = func.getLocation()
}
final Language::Location getLocation() { result = func.getLocation() }
/**
* Gets the entry point for this function.
@@ -64,38 +54,28 @@ class IRFunction extends TIRFunction {
* Gets the single return instruction for this function.
*/
pragma[noinline]
final ReturnInstruction getReturnInstruction() {
result.getEnclosingIRFunction() = this
}
final ReturnInstruction getReturnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold.
*/
pragma[noinline]
final IRReturnVariable getReturnVariable() {
result.getEnclosingIRFunction() = this
}
final IRReturnVariable getReturnVariable() { result.getEnclosingIRFunction() = this }
/**
* Gets the block containing the entry point of this function.
*/
*/
pragma[noinline]
final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction()
}
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
/**
* Gets all instructions in this function.
*/
final Instruction getAnInstruction() {
result.getEnclosingIRFunction() = this
}
final Instruction getAnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets all blocks in this function.
*/
final IRBlock getABlock() {
result.getEnclosingIRFunction() = this
}
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
}

View File

@@ -1,3 +1,2 @@
private import IR
import InstructionSanity

View File

@@ -37,27 +37,21 @@ abstract class IRVariable extends TIRVariable {
* within the function.
*/
abstract string getUniqueId();
/**
* Gets the source location of this variable.
*/
final Language::Location getLocation() {
result = getAST().getLocation()
}
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() {
result.getFunction() = func
}
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
/**
* Gets the function that references this variable.
*/
final Language::Function getEnclosingFunction() {
result = func
}
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -65,34 +59,25 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
IRUserVariable() { this = TIRUserVariable(var, type, func) }
override final string toString() {
result = getVariable().toString()
}
final override string toString() { result = getVariable().toString() }
override final Language::AST getAST() {
result = var
}
final override Language::AST getAST() { result = var }
override final string getUniqueId() {
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
/**
* Gets the original user-declared variable.
*/
Language::Variable getVariable() {
result = var
}
Language::Variable getVariable() { result = var }
}
/**
@@ -100,31 +85,22 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable {
}
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
Language::isVariableAutomatic(var)
}
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() {
result = var
}
final override Language::AutomaticVariable getVariable() { result = var }
}
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
not Language::isVariableAutomatic(var)
}
IRStaticUserVariable() { not Language::isVariableAutomatic(var) }
final override Language::StaticVariable getVariable() {
result = var
}
final override Language::StaticVariable getVariable() { result = var }
}
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
@@ -134,55 +110,39 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
override final Language::AST getAST() {
result = ast
}
final override Language::AST getAST() { result = ast }
override final string getUniqueId() {
final override string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this)
}
final TempVariableTag getTag() {
result = tag
}
final TempVariableTag getTag() { result = tag }
override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString()
ast.getLocation().getStartColumn().toString()
}
string getBaseString() {
result = "#temp"
}
string getBaseString() { result = "#temp" }
}
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() {
tag = ReturnValueTempVar()
}
IRReturnVariable() { tag = ReturnValueTempVar() }
override final string toString() {
result = "#return"
}
final override string toString() { result = "#return" }
}
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() {
tag = ThrowTempVar()
}
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() {
result = "#throw"
}
override string getBaseString() { result = "#throw" }
}

View File

@@ -12,11 +12,15 @@ private newtype TOperand =
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
@@ -46,24 +50,16 @@ private predicate isInCycle(Instruction instr) {
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
class Operand extends TOperand {
string toString() {
result = "Operand"
}
string toString() { result = "Operand" }
final Language::Location getLocation() {
result = getUse().getLocation()
}
final Language::Location getLocation() { result = getUse().getLocation() }
final IRFunction getEnclosingIRFunction() {
result = getUse().getEnclosingIRFunction()
}
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
/**
* Gets the `Instruction` that consumes this operand.
*/
Instruction getUse() {
none()
}
Instruction getUse() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -71,9 +67,7 @@ class Operand extends TOperand {
* means that the resulting instruction may only _partially_ or _potentially_
* be the value of this operand.
*/
Instruction getAnyDef() {
none()
}
Instruction getAnyDef() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -91,10 +85,7 @@ class Operand extends TOperand {
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated
final Instruction getUseInstruction() {
result = getUse()
}
deprecated final Instruction getUseInstruction() { result = getUse() }
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -103,31 +94,22 @@ class Operand extends TOperand {
*
* Gets the `Instruction` whose result is the value of the operand.
*/
deprecated
final Instruction getDefinitionInstruction() {
result = getAnyDef()
}
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
/**
* Gets the overlap relationship between the operand's definition and its use.
*/
Overlap getDefinitionOverlap() {
none()
}
Overlap getDefinitionOverlap() { none() }
/**
* Holds if the result of the definition instruction does not exactly overlap this use.
*/
final predicate isDefinitionInexact() {
not getDefinitionOverlap() instanceof MustExactlyOverlap
}
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
/**
* Gets a prefix to use when dumping the operand in an operand list.
*/
string getDumpLabel() {
result = ""
}
string getDumpLabel() { result = "" }
/**
* Gets a string describing this operand, suitable for display in IR dumps. This consists of the
@@ -146,18 +128,13 @@ class Operand extends TOperand {
* the empty string.
*/
private string getInexactSpecifier() {
if isDefinitionInexact() then
result = "~"
else
result = ""
if isDefinitionInexact() then result = "~" else result = ""
}
/**
* Get the order in which the operand should be sorted in the operand list.
*/
int getDumpSortOrder() {
result = -1
}
int getDumpSortOrder() { result = -1 }
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
@@ -166,9 +143,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Language::Type getType() {
result = getAnyDef().getResultType()
}
Language::Type getType() { result = getAnyDef().getResultType() }
/**
* Holds if the value consumed by this operand is a glvalue. If this
@@ -177,17 +152,13 @@ class Operand extends TOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getAnyDef().isGLValue()
}
predicate isGLValue() { getAnyDef().isGLValue() }
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = Language::getTypeSize(getType())
}
int getSize() { result = Language::getTypeSize(getType()) }
}
/**
@@ -207,9 +178,7 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() {
none()
}
MemoryAccessKind getMemoryAccess() { none() }
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -227,7 +196,9 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -235,25 +206,15 @@ class NonPhiOperand extends Operand {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
}
override final Instruction getUse() {
result = useInstr
}
final override Instruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final string getDumpLabel() {
result = tag.getLabel()
}
final override string getDumpLabel() { result = tag.getLabel() }
override final int getDumpSortOrder() {
result = tag.getSortOrder()
}
final override int getDumpSortOrder() { result = tag.getSortOrder() }
final OperandTag getOperandTag() {
result = tag
}
final OperandTag getOperandTag() { result = tag }
}
/**
@@ -262,7 +223,7 @@ class NonPhiOperand extends Operand {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
override final Overlap getDefinitionOverlap() {
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
result instanceof MustExactlyOverlap
}
@@ -270,21 +231,18 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
}
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
}
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Language::Type getType() {
final override Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -296,9 +254,7 @@ class TypedOperand extends NonPhiMemoryOperand {
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() {
result = "Address"
}
override string toString() { result = "Address" }
}
/**
@@ -308,13 +264,9 @@ class AddressOperand extends RegisterOperand {
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
}
override string toString() { result = "Load" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof IndirectMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -323,9 +275,7 @@ class LoadOperand extends TypedOperand {
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
}
override string toString() { result = "StoreValue" }
}
/**
@@ -334,9 +284,7 @@ class StoreValueOperand extends RegisterOperand {
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
}
override string toString() { result = "Unary" }
}
/**
@@ -345,9 +293,7 @@ class UnaryOperand extends RegisterOperand {
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() {
result = "Left"
}
override string toString() { result = "Left" }
}
/**
@@ -356,9 +302,7 @@ class LeftOperand extends RegisterOperand {
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() {
result = "Right"
}
override string toString() { result = "Right" }
}
/**
@@ -367,9 +311,7 @@ class RightOperand extends RegisterOperand {
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
}
override string toString() { result = "Condition" }
}
/**
@@ -379,13 +321,9 @@ class ConditionOperand extends RegisterOperand {
class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
}
override string toString() { result = "UnmodeledUse" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -394,9 +332,7 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
}
override string toString() { result = "CallTarget" }
}
/**
@@ -415,9 +351,7 @@ class ArgumentOperand extends RegisterOperand {
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
}
override string toString() { result = "ThisArgument" }
}
/**
@@ -425,32 +359,26 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
argIndex = tag.getArgIndex()
}
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() {
result = "Arg(" + argIndex + ")"
}
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
final int getIndex() { result = argIndex }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = Language::getTypeSize(getType())
final override int getSize() {
if getType() instanceof Language::UnknownType
then result = Construction::getInstructionOperandSize(useInstr, tag)
else result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {
@@ -485,48 +413,35 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() {
this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() {
result = "Phi"
}
override string toString() { result = "Phi" }
override final PhiInstruction getUse() {
result = useInstr
}
final override PhiInstruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
override final int getDumpSortOrder() {
result = 11 + getPredecessorBlock().getDisplayIndex()
}
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
override final string getDumpLabel() {
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
}
/**
* Gets the predecessor block from which this value comes.
*/
final IRBlock getPredecessorBlock() {
result = predecessorBlock
}
final IRBlock getPredecessorBlock() { result = predecessorBlock }
override final MemoryAccessKind getMemoryAccess() {
result instanceof PhiMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof PhiMemoryAccess }
}
/**
@@ -535,27 +450,18 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() {
result = "ChiTotal"
}
override string toString() { result = "ChiTotal" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiTotalMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
/**
* The partial operand of a Chi node, representing the value being written to part of the memory.
*/
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() {
result = "ChiPartial"
}
override string toString() { result = "ChiPartial" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiPartialMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -9,23 +9,17 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
string toString() { result = "PrintIRConfiguration" }
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Function func) {
any()
}
predicate shouldPrintFunction(Language::Function func) { any() }
}
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
/**
@@ -38,27 +32,17 @@ private class FilteredIRConfiguration extends IRConfiguration {
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
exists(IRPropertyProvider provider | result = provider.getBlockProperty(block, key))
}
private newtype TPrintableIRNode =
TPrintableIRFunction(IRFunction irFunc) {
shouldPrintFunction(irFunc.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getEnclosingFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getEnclosingFunction())
}
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
/**
* A node to be emitted in the IR graph.
@@ -85,29 +69,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
* Gets the parent of this node.
*/
abstract PrintableIRNode getParent();
/**
* Gets the kind of graph represented by this node ("graph" or "tree").
*/
string getGraphKind() {
none()
}
string getGraphKind() { none() }
/**
* Holds if this node should always be rendered as text, even in a graphical
* viewer.
*/
predicate forceText() {
none()
}
predicate forceText() { none() }
/**
* Gets the value of the node property with the specified key.
*/
string getProperty(string key) {
key = "semmle.label" and result = getLabel() or
key = "semmle.order" and result = getOrder().toString() or
key = "semmle.graphKind" and result = getGraphKind() or
key = "semmle.label" and result = getLabel()
or
key = "semmle.order" and result = getOrder().toString()
or
key = "semmle.graphKind" and result = getGraphKind()
or
key = "semmle.forceText" and forceText() and result = "true"
}
}
@@ -118,37 +101,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
IRFunction irFunc;
PrintableIRFunction() {
this = TPrintableIRFunction(irFunc)
}
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
override string toString() {
result = irFunc.toString()
}
override string toString() { result = irFunc.toString() }
override Language::Location getLocation() {
result = irFunc.getLocation()
}
override Language::Location getLocation() { result = irFunc.getLocation() }
override string getLabel() {
result = Language::getIdentityString(irFunc.getFunction())
}
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
)
location = orderedFunc.getIRFunction().getLocation()
|
orderedFunc
order by
location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(),
orderedFunc.getLabel()
)
}
override final PrintableIRNode getParent() {
none()
}
final override PrintableIRNode getParent() { none() }
final IRFunction getIRFunction() {
result = irFunc
}
final IRFunction getIRFunction() { result = irFunc }
}
/**
@@ -157,35 +131,21 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
IRBlock block;
PrintableIRBlock() {
this = TPrintableIRBlock(block)
}
PrintableIRBlock() { this = TPrintableIRBlock(block) }
override string toString() {
result = getLabel()
}
override string toString() { result = getLabel() }
override Language::Location getLocation() {
result = block.getLocation()
}
override Language::Location getLocation() { result = block.getLocation() }
override string getLabel() {
result = "Block " + block.getDisplayIndex().toString()
}
override string getLabel() { result = "Block " + block.getDisplayIndex().toString() }
override int getOrder() {
result = block.getDisplayIndex()
}
override int getOrder() { result = block.getDisplayIndex() }
override final string getGraphKind() {
result = "tree"
}
final override string getGraphKind() { result = "tree" }
override final predicate forceText() {
any()
}
final override predicate forceText() { any() }
override final PrintableIRFunction getParent() {
final override PrintableIRFunction getParent() {
result.getIRFunction() = block.getEnclosingIRFunction()
}
@@ -194,9 +154,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
final IRBlock getBlock() { result = block }
}
/**
@@ -205,45 +163,35 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
Instruction instr;
PrintableInstruction() {
this = TPrintableInstruction(instr)
}
PrintableInstruction() { this = TPrintableInstruction(instr) }
override string toString() {
result = instr.toString()
}
override string toString() { result = instr.toString() }
override Language::Location getLocation() {
result = instr.getLocation()
}
override Language::Location getLocation() { result = instr.getLocation() }
override string getLabel() {
exists(IRBlock block |
instr = block.getAnInstruction() and
exists(string resultString, string operationString, string operandsString,
int resultWidth, int operationWidth |
exists(
string resultString, string operationString, string operandsString, int resultWidth,
int operationWidth
|
resultString = instr.getResultString() and
operationString = instr.getOperationString() and
operandsString = instr.getOperandsString() and
columnWidths(block, resultWidth, operationWidth) and
result = resultString + getPaddingString(resultWidth - resultString.length()) +
" = " + operationString + getPaddingString(operationWidth - operationString.length()) +
" : " + operandsString
result = resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
operationString + getPaddingString(operationWidth - operationString.length()) + " : " +
operandsString
)
)
}
override int getOrder() {
result = instr.getDisplayIndexInBlock()
}
override int getOrder() { result = instr.getDisplayIndexInBlock() }
override final PrintableIRBlock getParent() {
result.getBlock() = instr.getBlock()
}
final override PrintableIRBlock getParent() { result.getBlock() = instr.getBlock() }
final Instruction getInstruction() {
result = instr
}
final Instruction getInstruction() { result = instr }
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
@@ -253,19 +201,26 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {
resultWidth = max(Instruction instr | instr.getBlock() = block | instr.getResultString().length()) and
operationWidth = max(Instruction instr | instr.getBlock() = block | instr.getOperationString().length())
operationWidth = max(Instruction instr |
instr.getBlock() = block
|
instr.getOperationString().length()
)
}
private int maxColumnWidth() {
result = max(Instruction instr, int width |
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length() |
width)
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length()
|
width
)
}
private string getPaddingString(int n) {
n = 0 and result = "" or
n = 0 and result = ""
or
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
}
@@ -275,9 +230,10 @@ query predicate nodes(PrintableIRNode node, string key, string value) {
private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
succ = rank[result + 1](IRBlock aSucc, EdgeKind kind |
aSucc = pred.getSuccessor(kind) |
aSucc order by kind.toString()
)
aSucc = pred.getSuccessor(kind)
|
aSucc order by kind.toString()
)
}
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
@@ -291,11 +247,10 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
if predBlock.getBackEdgeSuccessor(kind) = succBlock
then value = kind.toString() + " (back edge)"
else value = kind.toString()
) or
(
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
or
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
)
}

View File

@@ -3,56 +3,42 @@ class IntValue = int;
/**
* Returns the value of the maximum representable integer.
*/
int maxValue() {
result = 2147483647
}
int maxValue() { result = 2147483647 }
/**
* Returns the value of the minimum representable integer.
*/
int minValue() {
result = -2147483647
}
int minValue() { result = -2147483647 }
/**
* Returns a value representing an unknown integer.
*/
IntValue unknown() {
result = -2147483648
}
IntValue unknown() { result = -2147483648 }
/**
* Holds if `n` has a known value.
*/
bindingset[n]
predicate hasValue(IntValue n) {
n != unknown()
}
predicate hasValue(IntValue n) { n != unknown() }
/**
* Returns a string representation of `n`. If `n` does not have a known value, the result is "??".
*/
bindingset[n]
string intValueToString(IntValue n) {
if hasValue(n) then result = n.toString() else result = "??"
}
string intValueToString(IntValue n) { if hasValue(n) then result = n.toString() else result = "??" }
/**
* Holds if the value `f` is within the range of representable integers.
*/
pragma[inline]
bindingset[f]
private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue())
}
pragma[inline]
private predicate isRepresentable(float f) { f >= minValue() and f <= maxValue() }
/**
* Gets the value of `n`. Holds only if `n` has a known value.
*/
bindingset[n]
int getValue(IntValue n) {
hasValue(n) and result = n
}
int getValue(IntValue n) { hasValue(n) and result = n }
/**
* Returns `a + b`. If either input is unknown, or if the addition overflows,
@@ -60,10 +46,9 @@ int getValue(IntValue n) {
*/
bindingset[a, b]
IntValue add(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then
result = a + b
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) + b.(float))
then result = a + b
else result = unknown()
}
/**
@@ -72,10 +57,9 @@ IntValue add(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue sub(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then
result = a - b
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) - b.(float))
then result = a - b
else result = unknown()
}
/**
@@ -85,12 +69,12 @@ IntValue sub(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue mul(IntValue a, IntValue b) {
if (a = 0) or (b = 0) then
result = 0
else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then
result = a * b
if a = 0 or b = 0
then result = 0
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) * b.(float))
then result = a * b
else result = unknown()
}
/**
@@ -102,10 +86,7 @@ IntValue div(IntValue a, IntValue b) {
// Normally, integer division has to worry about overflow for INT_MIN/-1.
// However, since we use INT_MIN to represent an unknown value anyway, we only
// have to worry about division by zero.
if hasValue(a) and hasValue(b) and (b != 0) then
result = a / b
else
result = unknown()
if hasValue(a) and hasValue(b) and b != 0 then result = a / b else result = unknown()
}
/**
@@ -113,14 +94,9 @@ IntValue div(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareEQ(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a = b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a = b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -128,14 +104,9 @@ IntValue compareEQ(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareNE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a != b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a != b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -143,14 +114,9 @@ IntValue compareNE(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareLT(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a < b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a < b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -158,14 +124,9 @@ IntValue compareLT(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareGT(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a > b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a > b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -173,14 +134,9 @@ IntValue compareGT(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareLE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a <= b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a <= b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -188,14 +144,9 @@ IntValue compareLE(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareGE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a >= b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a >= b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -203,53 +154,41 @@ IntValue compareGE(IntValue a, IntValue b) {
*/
bindingset[a]
IntValue neg(IntValue a) {
result = -a // -INT_MIN = INT_MIN, so this preserves unknown
result = -a // -INT_MIN = INT_MIN, so this preserves unknown
}
/**
* Holds if `a` is equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isEQ(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a = b
}
predicate isEQ(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a = b }
/**
* Holds if `a` is not equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isNE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a != b
}
predicate isNE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a != b }
/**
* Holds if `a` is less than `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isLT(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a < b
}
predicate isLT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a < b }
/**
* Holds if `a` is less than or equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isLE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a <= b
}
predicate isLE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a <= b }
/**
* Holds if `a` is greater than `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isGT(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a > b
}
predicate isGT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a > b }
/**
* Holds if `a` is greater than or equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isGE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a >= b
}
predicate isGE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a >= b }

View File

@@ -13,14 +13,15 @@ private import IntegerConstant
*/
bindingset[defStart, defEnd, useStart, useEnd]
Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntValue useEnd) {
if isEQ(defStart, useStart) and isEQ(defEnd, useEnd) then
result instanceof MustExactlyOverlap
else if isLE(defStart, useStart) and isGE(defEnd, useEnd) then
result instanceof MustTotallyOverlap
else if isLE(defEnd, useStart) or isGE(defStart, useEnd) then
none()
if isEQ(defStart, useStart) and isEQ(defEnd, useEnd)
then result instanceof MustExactlyOverlap
else
result instanceof MayPartiallyOverlap
if isLE(defStart, useStart) and isGE(defEnd, useEnd)
then result instanceof MustTotallyOverlap
else
if isLE(defEnd, useStart) or isGE(defStart, useEnd)
then none()
else result instanceof MayPartiallyOverlap
}
/**

View File

@@ -6,32 +6,26 @@
/**
* Gets the value of the maximum representable integer.
*/
int maxValue() {
result = 2147483647
}
int maxValue() { result = 2147483647 }
/**
* Gets the value of the minimum representable integer.
*/
int minValue() {
result = -2147483648
}
int minValue() { result = -2147483648 }
/**
* Holds if the value `f` is within the range of representable integers.
*/
pragma[inline]
bindingset[f]
private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue())
}
pragma[inline]
private predicate isRepresentable(float f) { f >= minValue() and f <= maxValue() }
/**
* Returns `a + b`. If the addition overflows, there is no result.
*/
bindingset[a, b]
int add(int a, int b) {
isRepresentable((float)a + (float)b) and
isRepresentable(a.(float) + b.(float)) and
result = a + b
}
@@ -40,7 +34,7 @@ int add(int a, int b) {
*/
bindingset[a, b]
int sub(int a, int b) {
isRepresentable((float)a - (float)b) and
isRepresentable(a.(float) - b.(float)) and
result = a - b
}
@@ -57,7 +51,7 @@ int mul(int a, int b) {
b = 0 and
result = 0
or
isRepresentable((float)a * (float)b) and
isRepresentable(a.(float) * b.(float)) and
result = a * b
}
@@ -66,63 +60,34 @@ int mul(int a, int b) {
*/
bindingset[a, b]
int div(int a, int b) {
b != 0 and (a != minValue() or b != -1) and
b != 0 and
(a != minValue() or b != -1) and
result = a / b
}
/** Returns `a == b`. */
bindingset[a, b]
int compareEQ(int a, int b) {
if a = b then
result = 1
else
result = 0
}
int compareEQ(int a, int b) { if a = b then result = 1 else result = 0 }
/** Returns `a != b`. */
bindingset[a, b]
int compareNE(int a, int b) {
if a != b then
result = 1
else
result = 0
}
int compareNE(int a, int b) { if a != b then result = 1 else result = 0 }
/** Returns `a < b`. */
bindingset[a, b]
int compareLT(int a, int b) {
if a < b then
result = 1
else
result = 0
}
int compareLT(int a, int b) { if a < b then result = 1 else result = 0 }
/** Returns `a > b`. */
bindingset[a, b]
int compareGT(int a, int b) {
if a > b then
result = 1
else
result = 0
}
int compareGT(int a, int b) { if a > b then result = 1 else result = 0 }
/** Returns `a <= b`. */
bindingset[a, b]
int compareLE(int a, int b) {
if a <= b then
result = 1
else
result = 0
}
int compareLE(int a, int b) { if a <= b then result = 1 else result = 0 }
/** Returns `a >= b`. */
bindingset[a, b]
int compareGE(int a, int b) {
if a >= b then
result = 1
else
result = 0
}
int compareGE(int a, int b) { if a >= b then result = 1 else result = 0 }
/**
* Returns `-a`. If the negation would overflow, there is no result.

View File

@@ -8,19 +8,13 @@ abstract class Overlap extends TOverlap {
}
class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap {
override final string toString() {
result = "MayPartiallyOverlap"
}
final override string toString() { result = "MayPartiallyOverlap" }
}
class MustTotallyOverlap extends Overlap, TMustTotallyOverlap {
override final string toString() {
result = "MustTotallyOverlap"
}
final override string toString() { result = "MustTotallyOverlap" }
}
class MustExactlyOverlap extends Overlap, TMustExactlyOverlap {
override final string toString() {
result = "MustExactlyOverlap"
}
final override string toString() { result = "MustExactlyOverlap" }
}

View File

@@ -120,7 +120,9 @@ class Namespace extends DotNet::Namespace, TypeContainer, Declaration, @namespac
override string toString() { result = DotNet::Namespace.super.toString() }
override predicate hasQualifiedName(string a, string b) { DotNet::Namespace.super.hasQualifiedName(a, b) }
override predicate hasQualifiedName(string a, string b) {
DotNet::Namespace.super.hasQualifiedName(a, b)
}
}
/**

View File

@@ -2,4 +2,5 @@
* Most queries should operate on the aliased SSA IR, so that's what we expose
* publicly as the "IR".
*/
import implementation.raw.IR
import implementation.raw.IR

View File

@@ -10,14 +10,10 @@ private newtype TIRConfiguration = MkIRConfiguration()
* The query can extend this class to control which functions have IR generated for them.
*/
class IRConfiguration extends TIRConfiguration {
string toString() {
result = "IRConfiguration"
}
string toString() { result = "IRConfiguration" }
/**
* Holds if IR should be created for callable `callable`. By default, holds for all callables.
*/
predicate shouldCreateIRForFunction(Callable callable) {
any()
}
predicate shouldCreateIRForFunction(Callable callable) { any() }
}

View File

@@ -1,6 +1,6 @@
/**
* @name IR Sanity Check
* @description Performs sanity checks on the Intermediate Representation. This query should have no results.
* @description Performs sanity checks on the Intermediate Representation. This query should have no results.
* @kind table
* @id csharp/ir-sanity-check
*/

View File

@@ -1,12 +1,13 @@
private import internal.EdgeKindInternal
private newtype TEdgeKind =
TGotoEdge() or // Single successor (including fall-through)
TTrueEdge() or // 'true' edge of conditional branch
TFalseEdge() or // 'false' edge of conditional branch
TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) { // Case label of switch
TGotoEdge() or // Single successor (including fall-through)
TTrueEdge() or // 'true' edge of conditional branch
TFalseEdge() or // 'false' edge of conditional branch
TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) {
// Case label of switch
Language::hasCaseEdge(minValue, maxValue)
}
@@ -24,70 +25,50 @@ abstract class EdgeKind extends TEdgeKind {
* or `IRBlock`.
*/
class GotoEdge extends EdgeKind, TGotoEdge {
override final string toString() {
result = "Goto"
}
final override string toString() { result = "Goto" }
}
GotoEdge gotoEdge() {
result = TGotoEdge()
}
GotoEdge gotoEdge() { result = TGotoEdge() }
/**
* A "true" edge, representing the successor of a conditional branch when the
* condition is non-zero.
*/
class TrueEdge extends EdgeKind, TTrueEdge {
override final string toString() {
result = "True"
}
final override string toString() { result = "True" }
}
TrueEdge trueEdge() {
result = TTrueEdge()
}
TrueEdge trueEdge() { result = TTrueEdge() }
/**
* A "false" edge, representing the successor of a conditional branch when the
* condition is zero.
*/
class FalseEdge extends EdgeKind, TFalseEdge {
override final string toString() {
result = "False"
}
final override string toString() { result = "False" }
}
FalseEdge falseEdge() {
result = TFalseEdge()
}
FalseEdge falseEdge() { result = TFalseEdge() }
/**
* An "exception" edge, representing the successor of an instruction when that
* instruction's evaluation throws an exception.
*/
class ExceptionEdge extends EdgeKind, TExceptionEdge {
override final string toString() {
result = "Exception"
}
final override string toString() { result = "Exception" }
}
ExceptionEdge exceptionEdge() {
result = TExceptionEdge()
}
ExceptionEdge exceptionEdge() { result = TExceptionEdge() }
/**
* A "default" edge, representing the successor of a `Switch` instruction when
* none of the case values matches the condition value.
*/
class DefaultEdge extends EdgeKind, TDefaultEdge {
override final string toString() {
result = "Default"
}
final override string toString() { result = "Default" }
}
DefaultEdge defaultEdge() {
result = TDefaultEdge()
}
DefaultEdge defaultEdge() { result = TDefaultEdge() }
/**
* A "case" edge, representing the successor of a `Switch` instruction when the
@@ -95,28 +76,20 @@ DefaultEdge defaultEdge() {
*/
class CaseEdge extends EdgeKind, TCaseEdge {
string minValue;
string maxValue;
CaseEdge() {
this = TCaseEdge(minValue, maxValue)
CaseEdge() { this = TCaseEdge(minValue, maxValue) }
final override string toString() {
if minValue = maxValue
then result = "Case[" + minValue + "]"
else result = "Case[" + minValue + ".." + maxValue + "]"
}
override final string toString() {
if minValue = maxValue then
result = "Case[" + minValue + "]"
else
result = "Case[" + minValue + ".." + maxValue + "]"
}
string getMinValue() { result = minValue }
string getMinValue() {
result = minValue
}
string getMaxValue() {
result = maxValue
}
string getMaxValue() { result = maxValue }
}
CaseEdge caseEdge(string minValue, string maxValue) {
result = TCaseEdge(minValue, maxValue)
}
CaseEdge caseEdge(string minValue, string maxValue) { result = TCaseEdge(minValue, maxValue) }

View File

@@ -10,14 +10,10 @@ private newtype TIRConfiguration = MkIRConfiguration()
* The query can extend this class to control which functions have IR generated for them.
*/
class IRConfiguration extends TIRConfiguration {
string toString() {
result = "IRConfiguration"
}
string toString() { result = "IRConfiguration" }
/**
* Holds if IR should be created for function `func`. By default, holds for all functions.
*/
predicate shouldCreateIRForFunction(Language::Function func) {
any()
}
predicate shouldCreateIRForFunction(Language::Function func) { any() }
}

View File

@@ -15,17 +15,13 @@ private newtype TMemoryAccessKind =
* memory result.
*/
class MemoryAccessKind extends TMemoryAccessKind {
string toString() {
none()
}
string toString() { none() }
/**
* Holds if the operand or result accesses memory pointed to by the `AddressOperand` on the
* same instruction.
*/
predicate usesAddressOperand() {
none()
}
predicate usesAddressOperand() { none() }
}
/**
@@ -33,13 +29,9 @@ class MemoryAccessKind extends TMemoryAccessKind {
* same instruction.
*/
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
override string toString() {
result = "indirect"
}
override final predicate usesAddressOperand() {
any()
}
override string toString() { result = "indirect" }
final override predicate usesAddressOperand() { any() }
}
/**
@@ -47,13 +39,9 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
* `AddressOperand` on the same instruction.
*/
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
override string toString() {
result = "indirect(may)"
}
override string toString() { result = "indirect(may)" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
@@ -62,13 +50,9 @@ class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess
* `BufferSizeOperand`.
*/
class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
override string toString() {
result = "buffer"
}
override string toString() { result = "buffer" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
@@ -77,31 +61,23 @@ class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
* elements given by the `BufferSizeOperand`.
*/
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
override string toString() {
result = "buffer(may)"
}
override string toString() { result = "buffer(may)" }
override final predicate usesAddressOperand() {
any()
}
final override predicate usesAddressOperand() { any() }
}
/**
* The operand or result accesses all memory whose address has escaped.
*/
class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess {
override string toString() {
result = "escaped"
}
override string toString() { result = "escaped" }
}
/**
* The operand or result may access all memory whose address has escaped.
*/
class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
override string toString() {
result = "escaped(may)"
}
override string toString() { result = "escaped(may)" }
}
/**
@@ -109,9 +85,7 @@ class EscapedMayMemoryAccess extends MemoryAccessKind, TEscapedMayMemoryAccess {
* definition.
*/
class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
override string toString() {
result = "phi"
}
override string toString() { result = "phi" }
}
/**
@@ -119,9 +93,7 @@ class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
* definition.
*/
class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
override string toString() {
result = "chi(total)"
}
override string toString() { result = "chi(total)" }
}
/**
@@ -129,9 +101,7 @@ class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
* definition.
*/
class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
override string toString() {
result = "chi(partial)"
}
override string toString() { result = "chi(partial)" }
}
/**
@@ -139,7 +109,5 @@ class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
* `UnmodeledDefinition` and on the operands of `UnmodeledUse`.
*/
class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess {
override string toString() {
result = "unmodeled"
}
override string toString() { result = "unmodeled" }
}

View File

@@ -77,152 +77,382 @@ private newtype TOpcode =
TNewObj()
class Opcode extends TOpcode {
string toString() {
result = "UnknownOpcode"
}
string toString() { result = "UnknownOpcode" }
}
abstract class UnaryOpcode extends Opcode {}
abstract class UnaryOpcode extends Opcode { }
abstract class BinaryOpcode extends Opcode {}
abstract class BinaryOpcode extends Opcode { }
abstract class PointerArithmeticOpcode extends BinaryOpcode {}
abstract class PointerArithmeticOpcode extends BinaryOpcode { }
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {}
abstract class PointerOffsetOpcode extends PointerArithmeticOpcode { }
abstract class ArithmeticOpcode extends Opcode {}
abstract class ArithmeticOpcode extends Opcode { }
abstract class BinaryArithmeticOpcode extends BinaryOpcode, ArithmeticOpcode {}
abstract class BinaryArithmeticOpcode extends BinaryOpcode, ArithmeticOpcode { }
abstract class UnaryArithmeticOpcode extends UnaryOpcode, ArithmeticOpcode {}
abstract class UnaryArithmeticOpcode extends UnaryOpcode, ArithmeticOpcode { }
abstract class BitwiseOpcode extends Opcode {}
abstract class BitwiseOpcode extends Opcode { }
abstract class BinaryBitwiseOpcode extends BinaryOpcode, BitwiseOpcode {}
abstract class BinaryBitwiseOpcode extends BinaryOpcode, BitwiseOpcode { }
abstract class UnaryBitwiseOpcode extends UnaryOpcode, BitwiseOpcode {}
abstract class UnaryBitwiseOpcode extends UnaryOpcode, BitwiseOpcode { }
abstract class CompareOpcode extends BinaryOpcode {}
abstract class CompareOpcode extends BinaryOpcode { }
abstract class RelationalOpcode extends CompareOpcode {}
abstract class RelationalOpcode extends CompareOpcode { }
abstract class CopyOpcode extends Opcode {}
abstract class CopyOpcode extends Opcode { }
abstract class MemoryAccessOpcode extends Opcode {}
abstract class MemoryAccessOpcode extends Opcode { }
abstract class ReturnOpcode extends Opcode {}
abstract class ReturnOpcode extends Opcode { }
abstract class ThrowOpcode extends Opcode {}
abstract class ThrowOpcode extends Opcode { }
abstract class CatchOpcode extends Opcode {}
abstract class CatchOpcode extends Opcode { }
abstract class OpcodeWithCondition extends Opcode {}
abstract class OpcodeWithCondition extends Opcode { }
abstract class BuiltInOperationOpcode extends Opcode {}
abstract class BuiltInOperationOpcode extends Opcode { }
abstract class SideEffectOpcode extends Opcode {}
abstract class SideEffectOpcode extends Opcode { }
/**
* An opcode that reads a value from memory.
*/
abstract class OpcodeWithLoad extends MemoryAccessOpcode {}
abstract class OpcodeWithLoad extends MemoryAccessOpcode { }
/**
* An opcode that reads from a set of memory locations as a side effect.
*/
abstract class ReadSideEffectOpcode extends SideEffectOpcode {}
abstract class ReadSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that writes to a set of memory locations as a side effect.
*/
abstract class WriteSideEffectOpcode extends SideEffectOpcode {}
abstract class WriteSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that may overwrite some, all, or none of an existing set of memory locations. Modeled
* as a read of the original contents, plus a "may" write of the new contents.
*/
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode {}
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that accesses a buffer via an `AddressOperand` and a `BufferSizeOperand`.
*/
abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
abstract class BufferAccessOpcode extends MemoryAccessOpcode { }
module Opcode {
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
class Error extends Opcode, TError { override final string toString() { result = "Error" } }
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } }
class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } }
class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } }
class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } }
class ReturnValue extends ReturnOpcode, OpcodeWithLoad, TReturnValue { override final string toString() { result = "ReturnValue" } }
class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } }
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } }
class Load extends CopyOpcode, OpcodeWithLoad, TLoad { override final string toString() { result = "Load" } }
class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } }
class Add extends BinaryArithmeticOpcode, TAdd { override final string toString() { result = "Add" } }
class Sub extends BinaryArithmeticOpcode, TSub { override final string toString() { result = "Sub" } }
class Mul extends BinaryArithmeticOpcode, TMul { override final string toString() { result = "Mul" } }
class Div extends BinaryArithmeticOpcode, TDiv { override final string toString() { result = "Div" } }
class Rem extends BinaryArithmeticOpcode, TRem { override final string toString() { result = "Rem" } }
class Negate extends UnaryArithmeticOpcode, TNegate { override final string toString() { result = "Negate" } }
class ShiftLeft extends BinaryBitwiseOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } }
class ShiftRight extends BinaryBitwiseOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } }
class BitAnd extends BinaryBitwiseOpcode, TBitAnd { override final string toString() { result = "BitAnd" } }
class BitOr extends BinaryBitwiseOpcode, TBitOr { override final string toString() { result = "BitOr" } }
class BitXor extends BinaryBitwiseOpcode, TBitXor { override final string toString() { result = "BitXor" } }
class BitComplement extends UnaryBitwiseOpcode, TBitComplement { override final string toString() { result = "BitComplement" } }
class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } }
class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } }
class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } }
class CompareLT extends RelationalOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
class CompareGT extends RelationalOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
class CompareLE extends RelationalOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
class CompareGE extends RelationalOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } }
class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } }
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } }
class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } }
class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } }
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } }
class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } }
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } }
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } }
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } }
class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } }
class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } }
class ElementsAddress extends UnaryOpcode, TElementsAddress { override final string toString() { result = "ElementsAddress" } }
class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } }
class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } }
class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } }
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } }
class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } }
class Call extends Opcode, TCall { override final string toString() { result = "Call" } }
class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } }
class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } }
class ThrowValue extends ThrowOpcode, OpcodeWithLoad, TThrowValue { override final string toString() { result = "ThrowValue" } }
class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } }
class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } }
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } }
class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } }
class AliasedDefinition extends Opcode, TAliasedDefinition { override final string toString() { result = "AliasedDefinition" } }
class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } }
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn { override final string toString() { result = "BuiltIn" } }
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } }
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOperationOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode, TIndirectWriteSideEffect { override final string toString() { result = "IndirectWriteSideEffect" } }
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode, TIndirectMayWriteSideEffect { override final string toString() { result = "IndirectMayWriteSideEffect" } }
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
class Chi extends Opcode, TChi { override final string toString() { result = "Chi" } }
class InlineAsm extends Opcode, TInlineAsm { override final string toString() { result = "InlineAsm" } }
class Unreached extends Opcode, TUnreached { override final string toString() { result = "Unreached" } }
class NewObj extends Opcode, TNewObj { override final string toString() { result = "NewObj" } }
class NoOp extends Opcode, TNoOp {
final override string toString() { result = "NoOp" }
}
class Uninitialized extends MemoryAccessOpcode, TUninitialized {
final override string toString() { result = "Uninitialized" }
}
class Error extends Opcode, TError {
final override string toString() { result = "Error" }
}
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter {
final override string toString() { result = "InitializeParameter" }
}
class InitializeThis extends Opcode, TInitializeThis {
final override string toString() { result = "InitializeThis" }
}
class EnterFunction extends Opcode, TEnterFunction {
final override string toString() { result = "EnterFunction" }
}
class ExitFunction extends Opcode, TExitFunction {
final override string toString() { result = "ExitFunction" }
}
class ReturnValue extends ReturnOpcode, OpcodeWithLoad, TReturnValue {
final override string toString() { result = "ReturnValue" }
}
class ReturnVoid extends ReturnOpcode, TReturnVoid {
final override string toString() { result = "ReturnVoid" }
}
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue {
final override string toString() { result = "CopyValue" }
}
class Load extends CopyOpcode, OpcodeWithLoad, TLoad {
final override string toString() { result = "Load" }
}
class Store extends CopyOpcode, MemoryAccessOpcode, TStore {
final override string toString() { result = "Store" }
}
class Add extends BinaryArithmeticOpcode, TAdd {
final override string toString() { result = "Add" }
}
class Sub extends BinaryArithmeticOpcode, TSub {
final override string toString() { result = "Sub" }
}
class Mul extends BinaryArithmeticOpcode, TMul {
final override string toString() { result = "Mul" }
}
class Div extends BinaryArithmeticOpcode, TDiv {
final override string toString() { result = "Div" }
}
class Rem extends BinaryArithmeticOpcode, TRem {
final override string toString() { result = "Rem" }
}
class Negate extends UnaryArithmeticOpcode, TNegate {
final override string toString() { result = "Negate" }
}
class ShiftLeft extends BinaryBitwiseOpcode, TShiftLeft {
final override string toString() { result = "ShiftLeft" }
}
class ShiftRight extends BinaryBitwiseOpcode, TShiftRight {
final override string toString() { result = "ShiftRight" }
}
class BitAnd extends BinaryBitwiseOpcode, TBitAnd {
final override string toString() { result = "BitAnd" }
}
class BitOr extends BinaryBitwiseOpcode, TBitOr {
final override string toString() { result = "BitOr" }
}
class BitXor extends BinaryBitwiseOpcode, TBitXor {
final override string toString() { result = "BitXor" }
}
class BitComplement extends UnaryBitwiseOpcode, TBitComplement {
final override string toString() { result = "BitComplement" }
}
class LogicalNot extends UnaryOpcode, TLogicalNot {
final override string toString() { result = "LogicalNot" }
}
class CompareEQ extends CompareOpcode, TCompareEQ {
final override string toString() { result = "CompareEQ" }
}
class CompareNE extends CompareOpcode, TCompareNE {
final override string toString() { result = "CompareNE" }
}
class CompareLT extends RelationalOpcode, TCompareLT {
final override string toString() { result = "CompareLT" }
}
class CompareGT extends RelationalOpcode, TCompareGT {
final override string toString() { result = "CompareGT" }
}
class CompareLE extends RelationalOpcode, TCompareLE {
final override string toString() { result = "CompareLE" }
}
class CompareGE extends RelationalOpcode, TCompareGE {
final override string toString() { result = "CompareGE" }
}
class PointerAdd extends PointerOffsetOpcode, TPointerAdd {
final override string toString() { result = "PointerAdd" }
}
class PointerSub extends PointerOffsetOpcode, TPointerSub {
final override string toString() { result = "PointerSub" }
}
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff {
final override string toString() { result = "PointerDiff" }
}
class Convert extends UnaryOpcode, TConvert {
final override string toString() { result = "Convert" }
}
class ConvertToBase extends UnaryOpcode, TConvertToBase {
final override string toString() { result = "ConvertToBase" }
}
class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase {
final override string toString() { result = "ConvertToVirtualBase" }
}
class ConvertToDerived extends UnaryOpcode, TConvertToDerived {
final override string toString() { result = "ConvertToDerived" }
}
class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull {
final override string toString() { result = "CheckedConvertOrNull" }
}
class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow {
final override string toString() { result = "CheckedConvertOrThrow" }
}
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
final override string toString() { result = "DynamicCastToVoid" }
}
class VariableAddress extends Opcode, TVariableAddress {
final override string toString() { result = "VariableAddress" }
}
class FieldAddress extends UnaryOpcode, TFieldAddress {
final override string toString() { result = "FieldAddress" }
}
class ElementsAddress extends UnaryOpcode, TElementsAddress {
final override string toString() { result = "ElementsAddress" }
}
class FunctionAddress extends Opcode, TFunctionAddress {
final override string toString() { result = "FunctionAddress" }
}
class Constant extends Opcode, TConstant {
final override string toString() { result = "Constant" }
}
class StringConstant extends Opcode, TStringConstant {
final override string toString() { result = "StringConstant" }
}
class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch {
final override string toString() { result = "ConditionalBranch" }
}
class Switch extends OpcodeWithCondition, TSwitch {
final override string toString() { result = "Switch" }
}
class Call extends Opcode, TCall {
final override string toString() { result = "Call" }
}
class CatchByType extends CatchOpcode, TCatchByType {
final override string toString() { result = "CatchByType" }
}
class CatchAny extends CatchOpcode, TCatchAny {
final override string toString() { result = "CatchAny" }
}
class ThrowValue extends ThrowOpcode, OpcodeWithLoad, TThrowValue {
final override string toString() { result = "ThrowValue" }
}
class ReThrow extends ThrowOpcode, TReThrow {
final override string toString() { result = "ReThrow" }
}
class Unwind extends Opcode, TUnwind {
final override string toString() { result = "Unwind" }
}
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition {
final override string toString() { result = "UnmodeledDefinition" }
}
class UnmodeledUse extends Opcode, TUnmodeledUse {
final override string toString() { result = "UnmodeledUse" }
}
class AliasedDefinition extends Opcode, TAliasedDefinition {
final override string toString() { result = "AliasedDefinition" }
}
class Phi extends Opcode, TPhi {
final override string toString() { result = "Phi" }
}
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn {
final override string toString() { result = "BuiltIn" }
}
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart {
final override string toString() { result = "VarArgsStart" }
}
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd {
final override string toString() { result = "VarArgsEnd" }
}
class VarArg extends BuiltInOperationOpcode, TVarArg {
final override string toString() { result = "VarArg" }
}
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy {
final override string toString() { result = "VarArgCopy" }
}
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect {
final override string toString() { result = "CallSideEffect" }
}
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect {
final override string toString() { result = "CallReadSideEffect" }
}
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode,
TIndirectReadSideEffect {
final override string toString() { result = "IndirectReadSideEffect" }
}
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode,
TIndirectWriteSideEffect {
final override string toString() { result = "IndirectWriteSideEffect" }
}
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode,
TIndirectMayWriteSideEffect {
final override string toString() { result = "IndirectMayWriteSideEffect" }
}
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect {
final override string toString() { result = "BufferReadSideEffect" }
}
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode,
TBufferWriteSideEffect {
final override string toString() { result = "BufferWriteSideEffect" }
}
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode,
TBufferMayWriteSideEffect {
final override string toString() { result = "BufferMayWriteSideEffect" }
}
class Chi extends Opcode, TChi {
final override string toString() { result = "Chi" }
}
class InlineAsm extends Opcode, TInlineAsm {
final override string toString() { result = "InlineAsm" }
}
class Unreached extends Opcode, TUnreached {
final override string toString() { result = "Unreached" }
}
class NewObj extends Opcode, TNewObj {
final override string toString() { result = "NewObj" }
}
}

View File

@@ -2,7 +2,5 @@ private import internal.TempVariableTagInternal
private import Imports::TempVariableTag
class TempVariableTag extends TTempVariableTag {
string toString() {
result = getTempVariableTagId(this)
}
string toString() { result = getTempVariableTagId(this) }
}

View File

@@ -13,14 +13,10 @@ private newtype TOperandTag =
TUnmodeledUseOperand() or
TCallTargetOperand() or
TThisArgumentOperand() or
TPositionalArgumentOperand(int argIndex) {
Language::hasPositionalArgIndex(argIndex)
} or
TPositionalArgumentOperand(int argIndex) { Language::hasPositionalArgIndex(argIndex) } or
TChiTotalOperand() or
TChiPartialOperand() or
TAsmOperand(int index) {
Language::hasAsmOperandIndex(index)
}
TAsmOperand(int index) { Language::hasAsmOperandIndex(index) }
/**
* Identifies the kind of operand on an instruction. Each `Instruction` has at
@@ -28,291 +24,195 @@ private newtype TOperandTag =
* an `Instruction` is determined by the instruction's opcode.
*/
abstract class OperandTag extends TOperandTag {
abstract string toString();
abstract string toString();
abstract int getSortOrder();
abstract int getSortOrder();
string getLabel() {
result = ""
}
string getLabel() { result = "" }
}
/**
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
abstract class MemoryOperandTag extends OperandTag {
}
abstract class MemoryOperandTag extends OperandTag { }
/**
* An operand that consumes a register (non-memory) result.
*/
abstract class RegisterOperandTag extends OperandTag {
}
abstract class RegisterOperandTag extends OperandTag { }
/**
* A memory operand whose type may be different from the result type of its definition instruction.
*/
abstract class TypedOperandTag extends MemoryOperandTag {
}
abstract class TypedOperandTag extends MemoryOperandTag { }
// 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`, `InitializeParameter`, `IndirectReadSideEffect`).
*/
class AddressOperandTag extends RegisterOperandTag, TAddressOperand {
override final string toString() {
result = "Address"
}
final override string toString() { result = "Address" }
override final int getSortOrder() {
result = 0
}
override final string getLabel() {
result = "&:"
}
final override int getSortOrder() { result = 0 }
final override string getLabel() { result = "&:" }
}
AddressOperandTag addressOperand() {
result = TAddressOperand()
}
AddressOperandTag addressOperand() { result = TAddressOperand() }
/**
* The buffer size operand of an instruction that represents a read or write of
* a buffer.
*/
class BufferSizeOperand extends RegisterOperandTag, TBufferSizeOperand {
override final string toString() {
result = "BufferSize"
}
final override string toString() { result = "BufferSize" }
override final int getSortOrder() {
result = 1
}
final override int getSortOrder() { result = 1 }
}
/**
* The operand representing the read side effect of a `SideEffectInstruction`.
*/
class SideEffectOperandTag extends TypedOperandTag, TSideEffectOperand {
override final string toString() {
result = "SideEffect"
}
final override string toString() { result = "SideEffect" }
override final int getSortOrder() {
result = 2
}
final override int getSortOrder() { result = 2 }
}
SideEffectOperandTag sideEffectOperand() {
result = TSideEffectOperand()
}
SideEffectOperandTag sideEffectOperand() { result = TSideEffectOperand() }
/**
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperandTag extends TypedOperandTag, TLoadOperand {
override final string toString() {
result = "Load"
}
final override string toString() { result = "Load" }
override final int getSortOrder() {
result = 3
}
final override int getSortOrder() { result = 3 }
}
LoadOperandTag loadOperand() {
result = TLoadOperand()
}
LoadOperandTag loadOperand() { result = TLoadOperand() }
/**
* The source value operand of a `Store` instruction.
*/
class StoreValueOperandTag extends RegisterOperandTag, TStoreValueOperand {
override final string toString() {
result = "StoreValue"
}
final override string toString() { result = "StoreValue" }
override final int getSortOrder() {
result = 4
}
final override int getSortOrder() { result = 4 }
}
StoreValueOperandTag storeValueOperand() {
result = TStoreValueOperand()
}
StoreValueOperandTag storeValueOperand() { result = TStoreValueOperand() }
/**
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
*/
class UnaryOperandTag extends RegisterOperandTag, TUnaryOperand {
override final string toString() {
result = "Unary"
}
final override string toString() { result = "Unary" }
override final int getSortOrder() {
result = 5
}
final override int getSortOrder() { result = 5 }
}
UnaryOperandTag unaryOperand() {
result = TUnaryOperand()
}
UnaryOperandTag unaryOperand() { result = TUnaryOperand() }
/**
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class LeftOperandTag extends RegisterOperandTag, TLeftOperand {
override final string toString() {
result = "Left"
}
final override string toString() { result = "Left" }
override final int getSortOrder() {
result = 6
}
final override int getSortOrder() { result = 6 }
}
LeftOperandTag leftOperand() {
result = TLeftOperand()
}
LeftOperandTag leftOperand() { result = TLeftOperand() }
/**
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class RightOperandTag extends RegisterOperandTag, TRightOperand {
override final string toString() {
result = "Right"
}
final override string toString() { result = "Right" }
override final int getSortOrder() {
result = 7
}
final override int getSortOrder() { result = 7 }
}
RightOperandTag rightOperand() {
result = TRightOperand()
}
RightOperandTag rightOperand() { result = TRightOperand() }
/**
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperandTag extends RegisterOperandTag, TConditionOperand {
override final string toString() {
result = "Condition"
}
final override string toString() { result = "Condition" }
override final int getSortOrder() {
result = 8
}
final override int getSortOrder() { result = 8 }
}
ConditionOperandTag conditionOperand() {
result = TConditionOperand()
}
ConditionOperandTag conditionOperand() { result = TConditionOperand() }
/**
* An operand of the special `UnmodeledUse` instruction, representing a value
* whose set of uses is unknown.
*/
class UnmodeledUseOperandTag extends MemoryOperandTag, TUnmodeledUseOperand {
override final string toString() {
result = "UnmodeledUse"
}
final override string toString() { result = "UnmodeledUse" }
override final int getSortOrder() {
result = 9
}
final override int getSortOrder() { result = 9 }
}
UnmodeledUseOperandTag unmodeledUseOperand() {
result = TUnmodeledUseOperand()
}
UnmodeledUseOperandTag unmodeledUseOperand() { result = TUnmodeledUseOperand() }
/**
* The operand representing the target function of an `Call` instruction.
*/
class CallTargetOperandTag extends RegisterOperandTag, TCallTargetOperand {
override final string toString() {
result = "CallTarget"
}
final override string toString() { result = "CallTarget" }
override final int getSortOrder() {
result = 10
}
final override int getSortOrder() { result = 10 }
override final string getLabel() {
result = "func:"
}
final override string getLabel() { result = "func:" }
}
CallTargetOperandTag callTargetOperand() {
result = TCallTargetOperand()
}
CallTargetOperandTag 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 ArgumentOperandTag extends RegisterOperandTag {
}
abstract class ArgumentOperandTag extends RegisterOperandTag { }
/**
* An operand representing the implicit 'this' argument to a member function
* call.
*/
class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
ThisArgumentOperandTag() {
this = TThisArgumentOperand()
}
ThisArgumentOperandTag() { this = TThisArgumentOperand() }
override final string toString() {
result = "Arg(this)"
}
final override string toString() { result = "Arg(this)" }
override final int getSortOrder() {
result = 11
}
final override int getSortOrder() { result = 11 }
override final string getLabel() {
result = "this:"
}
final override string getLabel() { result = "this:" }
}
ThisArgumentOperandTag thisArgumentOperand() {
result = TThisArgumentOperand()
}
ThisArgumentOperandTag thisArgumentOperand() { result = TThisArgumentOperand() }
/**
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperandTag extends ArgumentOperandTag,
TPositionalArgumentOperand {
class PositionalArgumentOperandTag extends ArgumentOperandTag, TPositionalArgumentOperand {
int argIndex;
PositionalArgumentOperandTag() {
this = TPositionalArgumentOperand(argIndex)
}
PositionalArgumentOperandTag() { this = TPositionalArgumentOperand(argIndex) }
override final string toString() {
result = "Arg(" + argIndex + ")"
}
final override string toString() { result = "Arg(" + argIndex + ")" }
override final int getSortOrder() {
result = 12 + argIndex
}
final override int getSortOrder() { result = 12 + argIndex }
override final string getLabel() {
result = argIndex.toString() + ":"
}
final int getArgIndex() {
result = argIndex
}
final override string getLabel() { result = argIndex.toString() + ":" }
final int getArgIndex() { result = argIndex }
}
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
@@ -320,61 +220,35 @@ PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
}
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
override final string toString() {
result = "ChiTotal"
}
final override string toString() { result = "ChiTotal" }
override final int getSortOrder() {
result = 13
}
final override int getSortOrder() { result = 13 }
override final string getLabel() {
result = "total:"
}
final override string getLabel() { result = "total:" }
}
ChiTotalOperandTag chiTotalOperand() {
result = TChiTotalOperand()
}
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
override final string toString() {
result = "ChiPartial"
}
final override string toString() { result = "ChiPartial" }
override final int getSortOrder() {
result = 14
}
final override int getSortOrder() { result = 14 }
override final string getLabel() {
result = "partial:"
}
final override string getLabel() { result = "partial:" }
}
ChiPartialOperandTag chiPartialOperand() {
result = TChiPartialOperand()
}
ChiPartialOperandTag chiPartialOperand() { result = TChiPartialOperand() }
class AsmOperandTag extends RegisterOperandTag, TAsmOperand {
int index;
AsmOperandTag() {
this = TAsmOperand(index)
}
AsmOperandTag() { this = TAsmOperand(index) }
override final string toString() {
result = "AsmOperand(" + index + ")"
}
final override string toString() { result = "AsmOperand(" + index + ")" }
override final int getSortOrder() {
result = 15 + index
}
final override int getSortOrder() { result = 15 + index }
override final string getLabel() {
result = index.toString() + ":"
}
final override string getLabel() { result = index.toString() + ":" }
}
AsmOperandTag asmOperand(int index) {
result = TAsmOperand(index)
}
AsmOperandTag asmOperand(int index) { result = TAsmOperand(index) }

View File

@@ -2,11 +2,11 @@ private import TIRVariableInternal
private import Imports::TempVariableTag
newtype TIRVariable =
TIRUserVariable(Language::Variable var, Language::Type type,
Language::Function func) {
TIRUserVariable(Language::Variable var, Language::Type type, Language::Function func) {
Construction::hasUserVariable(func, var, type)
} or
TIRTempVariable(Language::Function func, Language::AST ast, TempVariableTag tag,
Language::Type type) {
TIRTempVariable(
Language::Function func, Language::AST ast, TempVariableTag tag, Language::Type type
) {
Construction::hasTempVariable(func, ast, tag, type)
}

View File

@@ -15,21 +15,15 @@ private newtype TIRPropertyProvider = MkIRPropertyProvider()
* single instance of this class to specify the additional properties computed by the library.
*/
class IRPropertyProvider extends TIRPropertyProvider {
string toString() {
result = "IRPropertyProvider"
}
string toString() { result = "IRPropertyProvider" }
/**
* Gets the value of the property named `key` for the specified instruction.
*/
string getInstructionProperty(Instruction instruction, string key) {
none()
}
string getInstructionProperty(Instruction instruction, string key) { none() }
/**
* Gets the value of the property named `key` for the specified block.
*/
string getBlockProperty(IRBlock block, string key) {
none()
}
string getBlockProperty(IRBlock block, string key) { none() }
}

View File

@@ -16,32 +16,25 @@ private import Cached
* Most consumers should use the class `IRBlock`.
*/
class IRBlockBase extends TIRBlock {
final string toString() {
result = getFirstInstruction(this).toString()
}
final string toString() { result = getFirstInstruction(this).toString() }
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
final string getUniqueId() {
result = getFirstInstruction(this).getUniqueId()
}
/**
* Gets the zero-based index of the block within its function. This is used
* by debugging and printing code only.
*/
int getDisplayIndex() {
this = rank[result + 1](IRBlock funcBlock |
funcBlock.getEnclosingFunction() = getEnclosingFunction() |
funcBlock order by funcBlock.getUniqueId()
)
funcBlock.getEnclosingFunction() = getEnclosingFunction()
|
funcBlock order by funcBlock.getUniqueId()
)
}
final Instruction getInstruction(int index) {
result = getInstruction(this, index)
}
final Instruction getInstruction(int index) { result = getInstruction(this, index) }
final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
@@ -52,17 +45,11 @@ class IRBlockBase extends TIRBlock {
result = getAPhiInstruction()
}
final Instruction getFirstInstruction() {
result = getFirstInstruction(this)
}
final Instruction getFirstInstruction() { result = getFirstInstruction(this) }
final Instruction getLastInstruction() {
result = getInstruction(getInstructionCount() - 1)
}
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
final int getInstructionCount() {
result = getInstructionCount(this)
}
final int getInstructionCount() { result = getInstructionCount(this) }
final IRFunction getEnclosingIRFunction() {
result = getFirstInstruction(this).getEnclosingIRFunction()
@@ -79,40 +66,26 @@ class IRBlockBase extends TIRBlock {
* instruction of another block.
*/
class IRBlock extends IRBlockBase {
final IRBlock getASuccessor() {
blockSuccessor(this, result)
}
final IRBlock getASuccessor() { blockSuccessor(this, result) }
final IRBlock getAPredecessor() {
blockSuccessor(result, this)
}
final IRBlock getAPredecessor() { blockSuccessor(result, this) }
final IRBlock getSuccessor(EdgeKind kind) {
blockSuccessor(this, result, kind)
}
final IRBlock getSuccessor(EdgeKind kind) { blockSuccessor(this, result, kind) }
final IRBlock getBackEdgeSuccessor(EdgeKind kind) {
backEdgeSuccessor(this, result, kind)
}
final IRBlock getBackEdgeSuccessor(EdgeKind kind) { backEdgeSuccessor(this, result, kind) }
final predicate immediatelyDominates(IRBlock block) {
blockImmediatelyDominates(this, block)
}
final predicate immediatelyDominates(IRBlock block) { blockImmediatelyDominates(this, block) }
final predicate strictlyDominates(IRBlock block) {
blockImmediatelyDominates+(this, block)
}
final predicate strictlyDominates(IRBlock block) { blockImmediatelyDominates+(this, block) }
final predicate dominates(IRBlock block) {
strictlyDominates(block) or this = block
}
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
pragma[noinline]
final IRBlock dominanceFrontier() {
dominates(result.getAPredecessor()) and
not strictlyDominates(result)
}
/**
* Holds if this block is reachable from the entry point of its function
*/
@@ -125,22 +98,21 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) or // Incoming edge is not a GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
) // A back edge enters this instruction
)
}
@@ -148,11 +120,10 @@ private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
cached
private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
@@ -165,15 +136,16 @@ private cached module Cached {
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
cached
Instruction getInstruction(TIRBlock block, int index) {
result = getInstructionFromFirst(getFirstInstruction(block), index)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached
int getInstructionCount(TIRBlock block) { result = strictcount(getInstruction(block, _)) }
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
@@ -185,7 +157,8 @@ private cached module Cached {
private predicate blockIdentity(TIRBlock b1, TIRBlock b2) { b1 = b2 }
pragma[noopt]
cached predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
cached
predicate backEdgeSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
backEdgeSuccessorRaw(pred, succ, kind)
or
// See the QLDoc on `backEdgeSuccessorRaw`.
@@ -226,14 +199,12 @@ private cached module Cached {
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached
predicate blockSuccessor(TIRBlock pred, TIRBlock succ) { blockSuccessor(pred, succ, _) }
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
cached
predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}
Instruction getFirstInstruction(TIRBlock block) { block = MkIRBlock(result) }

View File

@@ -2,9 +2,7 @@ private import internal.IRInternal
import Instruction
private newtype TIRFunction =
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
MkIRFunction(Language::Function func) { Construction::functionHasIR(func) }
/**
* Represents the IR for a function.
@@ -12,27 +10,19 @@ private newtype TIRFunction =
class IRFunction extends TIRFunction {
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
}
IRFunction() { this = MkIRFunction(func) }
final string toString() {
result = "IR: " + func.toString()
}
final string toString() { result = "IR: " + func.toString() }
/**
* Gets the function whose IR is represented.
*/
final Language::Function getFunction() {
result = func
}
final Language::Function getFunction() { result = func }
/**
* Gets the location of the function.
*/
final Language::Location getLocation() {
result = func.getLocation()
}
final Language::Location getLocation() { result = func.getLocation() }
/**
* Gets the entry point for this function.
@@ -64,38 +54,28 @@ class IRFunction extends TIRFunction {
* Gets the single return instruction for this function.
*/
pragma[noinline]
final ReturnInstruction getReturnInstruction() {
result.getEnclosingIRFunction() = this
}
final ReturnInstruction getReturnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets the variable used to hold the return value of this function. If this
* function does not return a value, this predicate does not hold.
*/
pragma[noinline]
final IRReturnVariable getReturnVariable() {
result.getEnclosingIRFunction() = this
}
final IRReturnVariable getReturnVariable() { result.getEnclosingIRFunction() = this }
/**
* Gets the block containing the entry point of this function.
*/
*/
pragma[noinline]
final IRBlock getEntryBlock() {
result.getFirstInstruction() = getEnterFunctionInstruction()
}
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
/**
* Gets all instructions in this function.
*/
final Instruction getAnInstruction() {
result.getEnclosingIRFunction() = this
}
final Instruction getAnInstruction() { result.getEnclosingIRFunction() = this }
/**
* Gets all blocks in this function.
*/
final IRBlock getABlock() {
result.getEnclosingIRFunction() = this
}
final IRBlock getABlock() { result.getEnclosingIRFunction() = this }
}

View File

@@ -1,6 +1,6 @@
/**
* @name Raw IR Sanity Check
* @description Performs sanity checks on the Intermediate Representation. This query should have no results.
* @description Performs sanity checks on the Intermediate Representation. This query should have no results.
* @kind table
* @id csharp/raw-ir-sanity-check
*/

View File

@@ -1,3 +1,2 @@
private import IR
import InstructionSanity

View File

@@ -37,27 +37,21 @@ abstract class IRVariable extends TIRVariable {
* within the function.
*/
abstract string getUniqueId();
/**
* Gets the source location of this variable.
*/
final Language::Location getLocation() {
result = getAST().getLocation()
}
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() {
result.getFunction() = func
}
final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
/**
* Gets the function that references this variable.
*/
final Language::Function getEnclosingFunction() {
result = func
}
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -65,34 +59,25 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
IRUserVariable() { this = TIRUserVariable(var, type, func) }
override final string toString() {
result = getVariable().toString()
}
final override string toString() { result = getVariable().toString() }
override final Language::AST getAST() {
result = var
}
final override Language::AST getAST() { result = var }
override final string getUniqueId() {
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
/**
* Gets the original user-declared variable.
*/
Language::Variable getVariable() {
result = var
}
Language::Variable getVariable() { result = var }
}
/**
@@ -100,31 +85,22 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable {
}
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
Language::isVariableAutomatic(var)
}
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() {
result = var
}
final override Language::AutomaticVariable getVariable() { result = var }
}
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
not Language::isVariableAutomatic(var)
}
IRStaticUserVariable() { not Language::isVariableAutomatic(var) }
final override Language::StaticVariable getVariable() {
result = var
}
final override Language::StaticVariable getVariable() { result = var }
}
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
@@ -134,55 +110,39 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
override final Language::Type getType() {
result = type
}
final override Language::Type getType() { result = type }
override final Language::AST getAST() {
result = ast
}
final override Language::AST getAST() { result = ast }
override final string getUniqueId() {
final override string getUniqueId() {
result = "Temp: " + Construction::getTempVariableUniqueId(this)
}
final TempVariableTag getTag() {
result = tag
}
final TempVariableTag getTag() { result = tag }
override string toString() {
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
ast.getLocation().getStartColumn().toString()
ast.getLocation().getStartColumn().toString()
}
string getBaseString() {
result = "#temp"
}
string getBaseString() { result = "#temp" }
}
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() {
tag = ReturnValueTempVar()
}
IRReturnVariable() { tag = ReturnValueTempVar() }
override final string toString() {
result = "#return"
}
final override string toString() { result = "#return" }
}
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() {
tag = ThrowTempVar()
}
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() {
result = "#throw"
}
override string getBaseString() { result = "#throw" }
}

View File

@@ -12,11 +12,15 @@ private newtype TOperand =
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
TNonPhiMemoryOperand(
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
@@ -46,24 +50,16 @@ private predicate isInCycle(Instruction instr) {
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
class Operand extends TOperand {
string toString() {
result = "Operand"
}
string toString() { result = "Operand" }
final Language::Location getLocation() {
result = getUse().getLocation()
}
final Language::Location getLocation() { result = getUse().getLocation() }
final IRFunction getEnclosingIRFunction() {
result = getUse().getEnclosingIRFunction()
}
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
/**
* Gets the `Instruction` that consumes this operand.
*/
Instruction getUse() {
none()
}
Instruction getUse() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -71,9 +67,7 @@ class Operand extends TOperand {
* means that the resulting instruction may only _partially_ or _potentially_
* be the value of this operand.
*/
Instruction getAnyDef() {
none()
}
Instruction getAnyDef() { none() }
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
@@ -91,10 +85,7 @@ class Operand extends TOperand {
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated
final Instruction getUseInstruction() {
result = getUse()
}
deprecated final Instruction getUseInstruction() { result = getUse() }
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
@@ -103,31 +94,22 @@ class Operand extends TOperand {
*
* Gets the `Instruction` whose result is the value of the operand.
*/
deprecated
final Instruction getDefinitionInstruction() {
result = getAnyDef()
}
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
/**
* Gets the overlap relationship between the operand's definition and its use.
*/
Overlap getDefinitionOverlap() {
none()
}
Overlap getDefinitionOverlap() { none() }
/**
* Holds if the result of the definition instruction does not exactly overlap this use.
*/
final predicate isDefinitionInexact() {
not getDefinitionOverlap() instanceof MustExactlyOverlap
}
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
/**
* Gets a prefix to use when dumping the operand in an operand list.
*/
string getDumpLabel() {
result = ""
}
string getDumpLabel() { result = "" }
/**
* Gets a string describing this operand, suitable for display in IR dumps. This consists of the
@@ -146,18 +128,13 @@ class Operand extends TOperand {
* the empty string.
*/
private string getInexactSpecifier() {
if isDefinitionInexact() then
result = "~"
else
result = ""
if isDefinitionInexact() then result = "~" else result = ""
}
/**
* Get the order in which the operand should be sorted in the operand list.
*/
int getDumpSortOrder() {
result = -1
}
int getDumpSortOrder() { result = -1 }
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
@@ -166,9 +143,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Language::Type getType() {
result = getAnyDef().getResultType()
}
Language::Type getType() { result = getAnyDef().getResultType() }
/**
* Holds if the value consumed by this operand is a glvalue. If this
@@ -177,17 +152,13 @@ class Operand extends TOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getAnyDef().isGLValue()
}
predicate isGLValue() { getAnyDef().isGLValue() }
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = Language::getTypeSize(getType())
}
int getSize() { result = Language::getTypeSize(getType()) }
}
/**
@@ -207,9 +178,7 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() {
none()
}
MemoryAccessKind getMemoryAccess() { none() }
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -227,7 +196,9 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -235,25 +206,15 @@ class NonPhiOperand extends Operand {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
}
override final Instruction getUse() {
result = useInstr
}
final override Instruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final string getDumpLabel() {
result = tag.getLabel()
}
final override string getDumpLabel() { result = tag.getLabel() }
override final int getDumpSortOrder() {
result = tag.getSortOrder()
}
final override int getDumpSortOrder() { result = tag.getSortOrder() }
final OperandTag getOperandTag() {
result = tag
}
final OperandTag getOperandTag() { result = tag }
}
/**
@@ -262,7 +223,7 @@ class NonPhiOperand extends Operand {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
override final Overlap getDefinitionOverlap() {
final override Overlap getDefinitionOverlap() {
// All register results overlap exactly with their uses.
result instanceof MustExactlyOverlap
}
@@ -270,21 +231,18 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
}
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
}
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Language::Type getType() {
final override Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -296,9 +254,7 @@ class TypedOperand extends NonPhiMemoryOperand {
class AddressOperand extends RegisterOperand {
override AddressOperandTag tag;
override string toString() {
result = "Address"
}
override string toString() { result = "Address" }
}
/**
@@ -308,13 +264,9 @@ class AddressOperand extends RegisterOperand {
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
}
override string toString() { result = "Load" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof IndirectMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -323,9 +275,7 @@ class LoadOperand extends TypedOperand {
class StoreValueOperand extends RegisterOperand {
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
}
override string toString() { result = "StoreValue" }
}
/**
@@ -334,9 +284,7 @@ class StoreValueOperand extends RegisterOperand {
class UnaryOperand extends RegisterOperand {
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
}
override string toString() { result = "Unary" }
}
/**
@@ -345,9 +293,7 @@ class UnaryOperand extends RegisterOperand {
class LeftOperand extends RegisterOperand {
override LeftOperandTag tag;
override string toString() {
result = "Left"
}
override string toString() { result = "Left" }
}
/**
@@ -356,9 +302,7 @@ class LeftOperand extends RegisterOperand {
class RightOperand extends RegisterOperand {
override RightOperandTag tag;
override string toString() {
result = "Right"
}
override string toString() { result = "Right" }
}
/**
@@ -367,9 +311,7 @@ class RightOperand extends RegisterOperand {
class ConditionOperand extends RegisterOperand {
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
}
override string toString() { result = "Condition" }
}
/**
@@ -379,13 +321,9 @@ class ConditionOperand extends RegisterOperand {
class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
}
override string toString() { result = "UnmodeledUse" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -394,9 +332,7 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
class CallTargetOperand extends RegisterOperand {
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
}
override string toString() { result = "CallTarget" }
}
/**
@@ -415,9 +351,7 @@ class ArgumentOperand extends RegisterOperand {
class ThisArgumentOperand extends ArgumentOperand {
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
}
override string toString() { result = "ThisArgument" }
}
/**
@@ -425,32 +359,26 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
argIndex = tag.getArgIndex()
}
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
override string toString() {
result = "Arg(" + argIndex + ")"
}
override string toString() { result = "Arg(" + argIndex + ")" }
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
final int getIndex() { result = argIndex }
}
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = Language::getTypeSize(getType())
final override int getSize() {
if getType() instanceof Language::UnknownType
then result = Construction::getInstructionOperandSize(useInstr, tag)
else result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {
@@ -485,48 +413,35 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() {
this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() {
result = "Phi"
}
override string toString() { result = "Phi" }
override final PhiInstruction getUse() {
result = useInstr
}
final override PhiInstruction getUse() { result = useInstr }
override final Instruction getAnyDef() {
result = defInstr
}
final override Instruction getAnyDef() { result = defInstr }
override final Overlap getDefinitionOverlap() {
result = overlap
}
final override Overlap getDefinitionOverlap() { result = overlap }
override final int getDumpSortOrder() {
result = 11 + getPredecessorBlock().getDisplayIndex()
}
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
override final string getDumpLabel() {
final override string getDumpLabel() {
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
}
/**
* Gets the predecessor block from which this value comes.
*/
final IRBlock getPredecessorBlock() {
result = predecessorBlock
}
final IRBlock getPredecessorBlock() { result = predecessorBlock }
override final MemoryAccessKind getMemoryAccess() {
result instanceof PhiMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof PhiMemoryAccess }
}
/**
@@ -535,27 +450,18 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
class ChiTotalOperand extends NonPhiMemoryOperand {
override ChiTotalOperandTag tag;
override string toString() {
result = "ChiTotal"
}
override string toString() { result = "ChiTotal" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiTotalMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiTotalMemoryAccess }
}
/**
* The partial operand of a Chi node, representing the value being written to part of the memory.
*/
class ChiPartialOperand extends NonPhiMemoryOperand {
override ChiPartialOperandTag tag;
override string toString() {
result = "ChiPartial"
}
override string toString() { result = "ChiPartial" }
override final MemoryAccessKind getMemoryAccess() {
result instanceof ChiPartialMemoryAccess
}
final override MemoryAccessKind getMemoryAccess() { result instanceof ChiPartialMemoryAccess }
}

View File

@@ -9,23 +9,17 @@ private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
string toString() { result = "PrintIRConfiguration" }
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Function func) {
any()
}
predicate shouldPrintFunction(Language::Function func) { any() }
}
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
/**
@@ -38,27 +32,17 @@ private class FilteredIRConfiguration extends IRConfiguration {
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
result = provider.getInstructionProperty(instr, key)
)
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
}
private string getAdditionalBlockProperty(IRBlock block, string key) {
exists(IRPropertyProvider provider |
result = provider.getBlockProperty(block, key)
)
exists(IRPropertyProvider provider | result = provider.getBlockProperty(block, key))
}
private newtype TPrintableIRNode =
TPrintableIRFunction(IRFunction irFunc) {
shouldPrintFunction(irFunc.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getEnclosingFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getEnclosingFunction())
}
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
/**
* A node to be emitted in the IR graph.
@@ -85,29 +69,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
* Gets the parent of this node.
*/
abstract PrintableIRNode getParent();
/**
* Gets the kind of graph represented by this node ("graph" or "tree").
*/
string getGraphKind() {
none()
}
string getGraphKind() { none() }
/**
* Holds if this node should always be rendered as text, even in a graphical
* viewer.
*/
predicate forceText() {
none()
}
predicate forceText() { none() }
/**
* Gets the value of the node property with the specified key.
*/
string getProperty(string key) {
key = "semmle.label" and result = getLabel() or
key = "semmle.order" and result = getOrder().toString() or
key = "semmle.graphKind" and result = getGraphKind() or
key = "semmle.label" and result = getLabel()
or
key = "semmle.order" and result = getOrder().toString()
or
key = "semmle.graphKind" and result = getGraphKind()
or
key = "semmle.forceText" and forceText() and result = "true"
}
}
@@ -118,37 +101,28 @@ abstract class PrintableIRNode extends TPrintableIRNode {
class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
IRFunction irFunc;
PrintableIRFunction() {
this = TPrintableIRFunction(irFunc)
}
PrintableIRFunction() { this = TPrintableIRFunction(irFunc) }
override string toString() {
result = irFunc.toString()
}
override string toString() { result = irFunc.toString() }
override Language::Location getLocation() {
result = irFunc.getLocation()
}
override Language::Location getLocation() { result = irFunc.getLocation() }
override string getLabel() {
result = Language::getIdentityString(irFunc.getFunction())
}
override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) }
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
)
location = orderedFunc.getIRFunction().getLocation()
|
orderedFunc
order by
location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(),
orderedFunc.getLabel()
)
}
override final PrintableIRNode getParent() {
none()
}
final override PrintableIRNode getParent() { none() }
final IRFunction getIRFunction() {
result = irFunc
}
final IRFunction getIRFunction() { result = irFunc }
}
/**
@@ -157,35 +131,21 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
IRBlock block;
PrintableIRBlock() {
this = TPrintableIRBlock(block)
}
PrintableIRBlock() { this = TPrintableIRBlock(block) }
override string toString() {
result = getLabel()
}
override string toString() { result = getLabel() }
override Language::Location getLocation() {
result = block.getLocation()
}
override Language::Location getLocation() { result = block.getLocation() }
override string getLabel() {
result = "Block " + block.getDisplayIndex().toString()
}
override string getLabel() { result = "Block " + block.getDisplayIndex().toString() }
override int getOrder() {
result = block.getDisplayIndex()
}
override int getOrder() { result = block.getDisplayIndex() }
override final string getGraphKind() {
result = "tree"
}
final override string getGraphKind() { result = "tree" }
override final predicate forceText() {
any()
}
final override predicate forceText() { any() }
override final PrintableIRFunction getParent() {
final override PrintableIRFunction getParent() {
result.getIRFunction() = block.getEnclosingIRFunction()
}
@@ -194,9 +154,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getAdditionalBlockProperty(block, key)
}
final IRBlock getBlock() {
result = block
}
final IRBlock getBlock() { result = block }
}
/**
@@ -205,45 +163,35 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
Instruction instr;
PrintableInstruction() {
this = TPrintableInstruction(instr)
}
PrintableInstruction() { this = TPrintableInstruction(instr) }
override string toString() {
result = instr.toString()
}
override string toString() { result = instr.toString() }
override Language::Location getLocation() {
result = instr.getLocation()
}
override Language::Location getLocation() { result = instr.getLocation() }
override string getLabel() {
exists(IRBlock block |
instr = block.getAnInstruction() and
exists(string resultString, string operationString, string operandsString,
int resultWidth, int operationWidth |
exists(
string resultString, string operationString, string operandsString, int resultWidth,
int operationWidth
|
resultString = instr.getResultString() and
operationString = instr.getOperationString() and
operandsString = instr.getOperandsString() and
columnWidths(block, resultWidth, operationWidth) and
result = resultString + getPaddingString(resultWidth - resultString.length()) +
" = " + operationString + getPaddingString(operationWidth - operationString.length()) +
" : " + operandsString
result = resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
operationString + getPaddingString(operationWidth - operationString.length()) + " : " +
operandsString
)
)
}
override int getOrder() {
result = instr.getDisplayIndexInBlock()
}
override int getOrder() { result = instr.getDisplayIndexInBlock() }
override final PrintableIRBlock getParent() {
result.getBlock() = instr.getBlock()
}
final override PrintableIRBlock getParent() { result.getBlock() = instr.getBlock() }
final Instruction getInstruction() {
result = instr
}
final Instruction getInstruction() { result = instr }
override string getProperty(string key) {
result = PrintableIRNode.super.getProperty(key) or
@@ -253,19 +201,26 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
private predicate columnWidths(IRBlock block, int resultWidth, int operationWidth) {
resultWidth = max(Instruction instr | instr.getBlock() = block | instr.getResultString().length()) and
operationWidth = max(Instruction instr | instr.getBlock() = block | instr.getOperationString().length())
operationWidth = max(Instruction instr |
instr.getBlock() = block
|
instr.getOperationString().length()
)
}
private int maxColumnWidth() {
result = max(Instruction instr, int width |
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length() |
width)
width = instr.getResultString().length() or
width = instr.getOperationString().length() or
width = instr.getOperandsString().length()
|
width
)
}
private string getPaddingString(int n) {
n = 0 and result = "" or
n = 0 and result = ""
or
n > 0 and n <= maxColumnWidth() and result = getPaddingString(n - 1) + " "
}
@@ -275,9 +230,10 @@ query predicate nodes(PrintableIRNode node, string key, string value) {
private int getSuccessorIndex(IRBlock pred, IRBlock succ) {
succ = rank[result + 1](IRBlock aSucc, EdgeKind kind |
aSucc = pred.getSuccessor(kind) |
aSucc order by kind.toString()
)
aSucc = pred.getSuccessor(kind)
|
aSucc order by kind.toString()
)
}
query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key, string value) {
@@ -291,11 +247,10 @@ query predicate edges(PrintableIRBlock pred, PrintableIRBlock succ, string key,
if predBlock.getBackEdgeSuccessor(kind) = succBlock
then value = kind.toString() + " (back edge)"
else value = kind.toString()
) or
(
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
or
key = "semmle.order" and
value = getSuccessorIndex(predBlock, succBlock).toString()
)
)
}

View File

@@ -4,10 +4,14 @@ private import IR
language[monotonicAggregates]
int getConstantValue(Instruction instr) {
result = instr.(IntegerConstantInstruction).getValue().toInt() or
result = getBinaryInstructionValue(instr) or
result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) or
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
result = instr.(IntegerConstantInstruction).getValue().toInt()
or
result = getBinaryInstructionValue(instr)
or
result = neg(getConstantValue(instr.(NegateInstruction).getUnary()))
or
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
or
exists(PhiInstruction phi |
phi = instr and
result = max(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def)) and
@@ -34,15 +38,24 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
exists(int left, int right |
binaryInstructionOperands(instr, left, right) and
(
instr instanceof AddInstruction and result = add(left, right) or
instr instanceof SubInstruction and result = sub(left, right) or
instr instanceof MulInstruction and result = mul(left, right) or
instr instanceof DivInstruction and result = div(left, right) or
instr instanceof CompareEQInstruction and result = compareEQ(left, right) or
instr instanceof CompareNEInstruction and result = compareNE(left, right) or
instr instanceof CompareLTInstruction and result = compareLT(left, right) or
instr instanceof CompareGTInstruction and result = compareGT(left, right) or
instr instanceof CompareLEInstruction and result = compareLE(left, right) or
instr instanceof AddInstruction and result = add(left, right)
or
instr instanceof SubInstruction and result = sub(left, right)
or
instr instanceof MulInstruction and result = mul(left, right)
or
instr instanceof DivInstruction and result = div(left, right)
or
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
or
instr instanceof CompareNEInstruction and result = compareNE(left, right)
or
instr instanceof CompareLTInstruction and result = compareLT(left, right)
or
instr instanceof CompareGTInstruction and result = compareGT(left, right)
or
instr instanceof CompareLEInstruction and result = compareLE(left, right)
or
instr instanceof CompareGEInstruction and result = compareGE(left, right)
)
)

View File

@@ -10,10 +10,7 @@ class ValueNumberPropertyProvider extends IRPropertyProvider {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1 then
result = vn.toString()
else
result = "unique"
if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique"
)
}
}
@@ -25,9 +22,7 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) {
initializeThisValueNumber(_, irFunc)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, Type type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -37,44 +32,40 @@ newtype TValueNumber =
TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, irFunc, field, objectAddress)
} or
TBinaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand,
ValueNumber rightOperand) {
TBinaryValueNumber(
IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand
) {
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(IRFunction irFunc, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand) {
TPointerArithmeticValueNumber(
IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
) {
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) {
unaryValueNumber(_, irFunc, opcode, type, operand)
} or
TInheritanceConversionValueNumber(IRFunction irFunc, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand) {
TInheritanceConversionValueNumber(
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand
) {
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
} or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) {
uniqueValueNumber(instr, irFunc)
}
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/
class ValueNumber extends TValueNumber {
final string toString() {
result = getExampleInstruction().getResultId()
}
final string toString() { result = getExampleInstruction().getResultId() }
final Location getLocation() {
result = getExampleInstruction().getLocation()
}
final Location getLocation() { result = getExampleInstruction().getLocation() }
/**
* Gets the instructions that have been assigned this value number. This will always produce at
* least one result.
*/
final Instruction getAnInstruction() {
this = valueNumber(result)
}
final Instruction getAnInstruction() { this = valueNumber(result) }
/**
* Gets one of the instructions that was assigned this value number. The chosen instuction is
@@ -82,14 +73,13 @@ class ValueNumber extends TValueNumber {
*/
final Instruction getExampleInstruction() {
result = min(Instruction instr |
instr = getAnInstruction() |
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
final Operand getAUse() {
this = valueNumber(result.getDefinitionInstruction())
instr = getAnInstruction()
|
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
)
}
final Operand getAUse() { this = valueNumber(result.getDefinitionInstruction()) }
}
/**
@@ -129,14 +119,16 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction
}
private predicate variableAddressValueNumber(VariableAddressInstruction instr, IRFunction irFunc,
IRVariable var) {
private predicate variableAddressValueNumber(
VariableAddressInstruction instr, IRFunction irFunc, IRVariable var
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getVariable() = var
}
private predicate initializeParameterValueNumber(InitializeParameterInstruction instr,
IRFunction irFunc, IRVariable var) {
private predicate initializeParameterValueNumber(
InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getVariable() = var
}
@@ -145,40 +137,46 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(ConstantInstruction instr, IRFunction irFunc, Type type,
string value) {
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, Type type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getValue() = value
}
private predicate stringConstantValueNumber(StringConstantInstruction instr, IRFunction irFunc, Type type,
string value) {
private predicate stringConstantValueNumber(
StringConstantInstruction instr, IRFunction irFunc, Type type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultType() = type and
instr.getValue().getValue() = value
}
private predicate fieldAddressValueNumber(FieldAddressInstruction instr, IRFunction irFunc,
Field field, ValueNumber objectAddress) {
private predicate fieldAddressValueNumber(
FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getField() = field and
valueNumber(instr.getObjectAddress()) = objectAddress
}
private predicate binaryValueNumber(BinaryInstruction instr, IRFunction irFunc, Opcode opcode,
Type type, ValueNumber leftOperand, ValueNumber rightOperand) {
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand,
ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
(not instr instanceof PointerArithmeticInstruction) and
not instr instanceof PointerArithmeticInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}
private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr,
IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand) {
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize,
ValueNumber leftOperand, ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getResultType() = type and
@@ -187,17 +185,20 @@ private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction inst
valueNumber(instr.getRight()) = rightOperand
}
private predicate unaryValueNumber(UnaryInstruction instr, IRFunction irFunc, Opcode opcode,
Type type, ValueNumber operand) {
private predicate unaryValueNumber(
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
(not instr instanceof InheritanceConversionInstruction) and
not instr instanceof InheritanceConversionInstruction and
instr.getOpcode() = opcode and
instr.getResultType() = type and
valueNumber(instr.getUnary()) = operand
}
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
private predicate inheritanceConversionValueNumber(
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass,
Class derivedClass, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getBaseClass() = baseClass and
@@ -211,15 +212,17 @@ private predicate inheritanceConversionValueNumber(InheritanceConversionInstruct
*/
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc and
(not instr.getResultType() instanceof VoidType) and
not instr.getResultType() instanceof VoidType and
not numberableInstruction(instr)
}
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
cached ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr) or
cached
ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr)
or
exists(IRFunction irFunc |
uniqueValueNumber(instr, irFunc) and
result = TUniqueValueNumber(irFunc, instr)
@@ -229,9 +232,7 @@ cached ValueNumber valueNumber(Instruction instr) {
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
ValueNumber valueNumberOfOperand(Operand op) {
result = valueNumber(op.getDefinitionInstruction())
}
ValueNumber valueNumberOfOperand(Operand op) { result = valueNumber(op.getDefinitionInstruction()) }
/**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
@@ -244,47 +245,55 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
exists(IRVariable var |
variableAddressValueNumber(instr, irFunc, var) and
result = TVariableAddressValueNumber(irFunc, var)
) or
)
or
exists(IRVariable var |
initializeParameterValueNumber(instr, irFunc, var) and
result = TInitializeParameterValueNumber(irFunc, var)
) or
(
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
) or
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(Type type, string value |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)
) or
)
or
exists(Type type, string value |
stringConstantValueNumber(instr, irFunc, type, value) and
result = TStringConstantValueNumber(irFunc, type, value)
) or
)
or
exists(Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
) or
)
or
exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
) or
)
or
exists(Opcode opcode, Type type, ValueNumber operand |
unaryValueNumber(instr, irFunc, opcode, type, operand) and
result = TUnaryValueNumber(irFunc, opcode, type, operand)
) or
)
or
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass,
operand) and
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
) or
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand |
)
or
exists(
Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
|
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
rightOperand) and
rightOperand) and
result = TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand,
rightOperand)
) or
)
or
// The value number of a copy is just the value number of its source value.
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
)

View File

@@ -15,28 +15,30 @@ TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
instruction = MkInstruction(result, _)
}
InstructionTag getInstructionTag(Instruction instruction) {
instruction = MkInstruction(_, result)
}
InstructionTag getInstructionTag(Instruction instruction) { instruction = MkInstruction(_, result) }
import Cached
cached private module Cached {
cached predicate functionHasIR(Callable callable) {
cached
private module Cached {
cached
predicate functionHasIR(Callable callable) {
exists(getTranslatedFunction(callable)) and
callable.fromSource()
}
cached newtype TInstruction =
cached
newtype TInstruction =
MkInstruction(TranslatedElement element, InstructionTag tag) {
element.hasInstruction(_, tag, _, _)
}
cached predicate hasUserVariable(Callable callable, Variable var, Type type) {
cached
predicate hasUserVariable(Callable callable, Variable var, Type type) {
getTranslatedFunction(callable).hasUserVariable(var, type)
}
cached predicate hasTempVariable(Callable callable, Language::AST ast, TempVariableTag tag,
Type type) {
cached
predicate hasTempVariable(Callable callable, Language::AST ast, TempVariableTag tag, Type type) {
exists(TranslatedElement element |
element.getAST() = ast and
callable = element.getFunction() and
@@ -44,63 +46,71 @@ cached private module Cached {
)
}
cached predicate hasModeledMemoryResult(Instruction instruction) {
none()
}
cached
predicate hasModeledMemoryResult(Instruction instruction) { none() }
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
cached
Expr getInstructionConvertedResultExpression(Instruction instruction) {
exists(TranslatedExpr translatedExpr |
translatedExpr = getTranslatedExpr(result) and
instruction = translatedExpr.getResult()
)
}
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
exists(Expr converted, TranslatedExpr translatedExpr |
result = converted.stripCasts()
|
cached
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
exists(Expr converted, TranslatedExpr translatedExpr | result = converted.stripCasts() |
translatedExpr = getTranslatedExpr(converted) and
instruction = translatedExpr.getResult()
)
}
cached Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperand(
getInstructionTag(instruction), tag)
cached
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
result = getInstructionTranslatedElement(instruction)
.getInstructionOperand(getInstructionTag(instruction), tag)
}
cached Instruction getMemoryOperandDefinition(Instruction instruction, MemoryOperandTag tag, Overlap overlap) {
overlap instanceof MustTotallyOverlap and
result = getInstructionTranslatedElement(instruction).getInstructionOperand(
getInstructionTag(instruction), tag)
cached
Instruction getMemoryOperandDefinition(
Instruction instruction, MemoryOperandTag tag, Overlap overlap
) {
overlap instanceof MustTotallyOverlap and
result = getInstructionTranslatedElement(instruction)
.getInstructionOperand(getInstructionTag(instruction), tag)
}
cached Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
cached
Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
// For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as
// the result type of the load.
if instruction instanceof LoadInstruction then
result = instruction.(LoadInstruction).getResultType()
if instruction instanceof LoadInstruction
then result = instruction.(LoadInstruction).getResultType()
else
result = getInstructionTranslatedElement(instruction).getInstructionOperandType(
getInstructionTag(instruction), tag)
result = getInstructionTranslatedElement(instruction)
.getInstructionOperandType(getInstructionTag(instruction), tag)
}
cached int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperandSize(
getInstructionTag(instruction), tag)
cached
int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) {
result = getInstructionTranslatedElement(instruction)
.getInstructionOperandSize(getInstructionTag(instruction), tag)
}
cached Instruction getPhiOperandDefinition(PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap) {
cached
Instruction getPhiOperandDefinition(
PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap
) {
none()
}
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
none()
}
cached
Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() }
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getInstructionTranslatedElement(instruction).getInstructionSuccessor(
getInstructionTag(instruction), kind)
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = getInstructionTranslatedElement(instruction)
.getInstructionSuccessor(getInstructionTag(instruction), kind)
}
// This predicate has pragma[noopt] because otherwise the `getAChild*` calls
@@ -109,7 +119,8 @@ cached private module Cached {
// - Find all edges into the start of the loop (x 2).
// - Restrict to edges that originate within the loop (/ 2).
pragma[noopt]
cached Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
cached
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
// While loop:
// Any edge from within the body of the loop to the condition of the loop
// is a back edge. This includes edges from `continue` and the fall-through
@@ -186,114 +197,128 @@ cached private module Cached {
goto.getLocation().getEndLine() < goto.getTarget().getLocation().getStartLine()
}
cached Language::AST getInstructionAST(Instruction instruction) {
cached
Language::AST getInstructionAST(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getAST()
}
cached predicate instructionHasType(Instruction instruction, Type type, boolean isLValue) {
cached
predicate instructionHasType(Instruction instruction, Type type, boolean isLValue) {
getInstructionTranslatedElement(instruction)
.hasInstruction(_, getInstructionTag(instruction), type, isLValue)
.hasInstruction(_, getInstructionTag(instruction), type, isLValue)
}
cached Opcode getInstructionOpcode(Instruction instruction) {
cached
Opcode getInstructionOpcode(Instruction instruction) {
getInstructionTranslatedElement(instruction)
.hasInstruction(result, getInstructionTag(instruction), _, _)
.hasInstruction(result, getInstructionTag(instruction), _, _)
}
cached IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
cached
IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
result.getFunction() = getInstructionTranslatedElement(instruction).getFunction()
}
cached IRVariable getInstructionVariable(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getInstructionVariable(
getInstructionTag(instruction))
cached
IRVariable getInstructionVariable(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionVariable(getInstructionTag(instruction))
}
cached Field getInstructionField(Instruction instruction) {
cached
Field getInstructionField(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and
result = element.getInstructionField(tag)
)
}
cached ArrayAccess getInstructionArrayAccess(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getInstructionArrayAccess(
getInstructionTag(instruction))
}
cached Callable getInstructionFunction(Instruction instruction) {
cached
ArrayAccess getInstructionArrayAccess(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionFunction(getInstructionTag(instruction))
.getInstructionArrayAccess(getInstructionTag(instruction))
}
cached string getInstructionConstantValue(Instruction instruction) {
result =
getInstructionTranslatedElement(instruction).getInstructionConstantValue(
getInstructionTag(instruction))
cached
Callable getInstructionFunction(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionFunction(getInstructionTag(instruction))
}
cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
result =
getInstructionTranslatedElement(instruction).getInstructionStringLiteral(
getInstructionTag(instruction))
cached
string getInstructionConstantValue(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionConstantValue(getInstructionTag(instruction))
}
cached Type getInstructionExceptionType(Instruction instruction) {
result =
getInstructionTranslatedElement(instruction).getInstructionExceptionType(
getInstructionTag(instruction))
cached
StringLiteral getInstructionStringLiteral(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionStringLiteral(getInstructionTag(instruction))
}
cached predicate getInstructionInheritance(Instruction instruction,
Class baseClass, Class derivedClass) {
getInstructionTranslatedElement(instruction).getInstructionInheritance(
getInstructionTag(instruction), baseClass, derivedClass)
cached
Type getInstructionExceptionType(Instruction instruction) {
result = getInstructionTranslatedElement(instruction)
.getInstructionExceptionType(getInstructionTag(instruction))
}
cached
predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) {
getInstructionTranslatedElement(instruction)
.getInstructionInheritance(getInstructionTag(instruction), baseClass, derivedClass)
}
pragma[noinline]
private predicate instructionOrigin(Instruction instruction,
TranslatedElement element, InstructionTag tag) {
private predicate instructionOrigin(
Instruction instruction, TranslatedElement element, InstructionTag tag
) {
element = getInstructionTranslatedElement(instruction) and
tag = getInstructionTag(instruction)
}
cached int getInstructionElementSize(Instruction instruction) {
cached
int getInstructionElementSize(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and
result = element.getInstructionElementSize(tag)
)
}
cached int getInstructionResultSize(Instruction instruction) {
cached
int getInstructionResultSize(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and
result = element.getInstructionResultSize(tag)
)
}
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
cached
Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and
result = element.getPrimaryInstructionForSideEffect(tag)
)
}
cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instr) {
none()
}
}
cached
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instr) { none() }
}
import CachedForDebugging
cached private module CachedForDebugging {
cached string getTempVariableUniqueId(IRTempVariable var) {
cached
private module CachedForDebugging {
cached
string getTempVariableUniqueId(IRTempVariable var) {
exists(TranslatedElement element |
var = element.getTempVariable(_) and
result = element.getId() + ":" + getTempVariableTagId(var.getTag())
)
}
cached string getInstructionUniqueId(Instruction instruction) {
cached
string getInstructionUniqueId(Instruction instruction) {
result = getInstructionTranslatedElement(instruction).getId() + ":" +
getInstructionTagId(getInstructionTag(instruction))
getInstructionTagId(getInstructionTag(instruction))
}
}

View File

@@ -1,19 +1,15 @@
import csharp
import semmle.code.csharp.ir.Util
//private predicate fieldIsInitialized(Field field) {
// exists(field.getInitializer())
//}
private predicate elementIsInitialized(int elementIndex) {
exists(ArrayInitWithMod initList |
initList.isInitialized(elementIndex)
)
exists(ArrayInitWithMod initList | initList.isInitialized(elementIndex))
}
newtype TInstructionTag =
OnlyInstructionTag() or // Single instruction (not including implicit Load)
OnlyInstructionTag() or // Single instruction (not including implicit Load)
InitializeThisTag() or
InitializerVariableAddressTag() or
InitializerLoadStringTag() or
@@ -57,42 +53,27 @@ newtype TInstructionTag =
ConditionValueResultLoadTag() or
BoolConversionConstantTag() or
BoolConversionCompareTag() or
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
CatchTag() or
ThrowTag() or
UnwindTag() or
InitializerUninitializedTag() or
InitializerElementIndexTag(int elementIndex) {
elementIsInitialized(elementIndex)
} or
InitializerElementAddressTag(int elementIndex) {
elementIsInitialized(elementIndex)
} or
InitializerElementDefaultValueTag(int elementIndex) {
elementIsInitialized(elementIndex)
} or
InitializerElementDefaultValueStoreTag(int elementIndex) {
elementIsInitialized(elementIndex)
} or
// Added for C#
InitializerElementIndexTag(int elementIndex) { elementIsInitialized(elementIndex) } or
InitializerElementAddressTag(int elementIndex) { elementIsInitialized(elementIndex) } or
InitializerElementDefaultValueTag(int elementIndex) { elementIsInitialized(elementIndex) } or
InitializerElementDefaultValueStoreTag(int elementIndex) { elementIsInitialized(elementIndex) } or
// Added for C#
NewObjTag() or
// TODO: remove the need for indexing
PointerAddTag(int index) {
index in [0 .. 255]
} or
ElementsAddressTag(int index) {
index in [0 .. 255]
} or
PointerAddTag(int index) { index in [0 .. 255] } or
ElementsAddressTag(int index) { index in [0 .. 255] } or
ConvertTag() or
GeneratedNEQTag() or
GeneratedConstantTag() or
GeneratedBranchTag()
class InstructionTag extends TInstructionTag {
final string toString() {
result = "Tag"
}
final string toString() { result = "Tag" }
}
/**
@@ -100,79 +81,135 @@ class InstructionTag extends TInstructionTag {
* instruction IDs to ensure stable IR dumps.
*/
string getInstructionTagId(TInstructionTag tag) {
tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load)
tag = InitializerVariableAddressTag() and result = "InitVarAddr" or
tag = InitializerLoadStringTag() and result = "InitLoadStr" or
tag = InitializerStoreTag() and result = "InitStore" or
tag = InitializerUninitializedTag() and result = "InitUninit" or
tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or
tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or
tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or
tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or
tag = AssignOperationLoadTag() and result = "AssignOpLoad" or
tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or
tag = AssignmentConvertRightTag() and result = "AssignConvRight" or
tag = AssignOperationOpTag() and result = "AssignOpOp" or
tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or
tag = AssignmentStoreTag() and result = "AssignStore" or
tag = CrementLoadTag() and result = "CrementLoad" or
tag = CrementConstantTag() and result = "CrementConst" or
tag = CrementOpTag() and result = "CrementOp" or
tag = CrementStoreTag() and result = "CrementStore" or
tag = EnterFunctionTag() and result = "EnterFunc" or
tag = ReturnValueAddressTag() and result = "RetValAddr" or
tag = ReturnTag() and result = "Ret" or
tag = ExitFunctionTag() and result = "ExitFunc" or
tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or
tag = UnmodeledUseTag() and result = "UnmodeledUse" or
tag = AliasedDefinitionTag() and result = "AliasedDef" or
tag = SwitchBranchTag() and result = "SwitchBranch" or
tag = CallTargetTag() and result = "CallTarget" or
tag = CallTag() and result = "Call" or
tag = CallSideEffectTag() and result = "CallSideEffect" or
tag = AllocationSizeTag() and result = "AllocSize" or
tag = AllocationElementSizeTag() and result = "AllocElemSize" or
tag = AllocationExtentConvertTag() and result = "AllocExtConv" or
tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or
tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or
tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or
tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or
tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or
tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or
tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or
tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or
tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or
tag = BoolConversionConstantTag() and result = "BoolConvConst" or
tag = BoolConversionCompareTag() and result = "BoolConvComp" or
tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion
tag = CatchTag() and result = "Catch" or
tag = ThrowTag() and result = "Throw" or
tag = UnwindTag() and result = "Unwind" or
tag = OnlyInstructionTag() and result = "Only" // Single instruction (not including implicit Load)
or
tag = InitializerVariableAddressTag() and result = "InitVarAddr"
or
tag = InitializerLoadStringTag() and result = "InitLoadStr"
or
tag = InitializerStoreTag() and result = "InitStore"
or
tag = InitializerUninitializedTag() and result = "InitUninit"
or
tag = ZeroPadStringConstantTag() and result = "ZeroPadConst"
or
tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex"
or
tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr"
or
tag = ZeroPadStringStoreTag() and result = "ZeroPadStore"
or
tag = AssignOperationLoadTag() and result = "AssignOpLoad"
or
tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft"
or
tag = AssignmentConvertRightTag() and result = "AssignConvRight"
or
tag = AssignOperationOpTag() and result = "AssignOpOp"
or
tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes"
or
tag = AssignmentStoreTag() and result = "AssignStore"
or
tag = CrementLoadTag() and result = "CrementLoad"
or
tag = CrementConstantTag() and result = "CrementConst"
or
tag = CrementOpTag() and result = "CrementOp"
or
tag = CrementStoreTag() and result = "CrementStore"
or
tag = EnterFunctionTag() and result = "EnterFunc"
or
tag = ReturnValueAddressTag() and result = "RetValAddr"
or
tag = ReturnTag() and result = "Ret"
or
tag = ExitFunctionTag() and result = "ExitFunc"
or
tag = UnmodeledDefinitionTag() and result = "UnmodeledDef"
or
tag = UnmodeledUseTag() and result = "UnmodeledUse"
or
tag = AliasedDefinitionTag() and result = "AliasedDef"
or
tag = SwitchBranchTag() and result = "SwitchBranch"
or
tag = CallTargetTag() and result = "CallTarget"
or
tag = CallTag() and result = "Call"
or
tag = CallSideEffectTag() and result = "CallSideEffect"
or
tag = AllocationSizeTag() and result = "AllocSize"
or
tag = AllocationElementSizeTag() and result = "AllocElemSize"
or
tag = AllocationExtentConvertTag() and result = "AllocExtConv"
or
tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch"
or
tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr"
or
tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst"
or
tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore"
or
tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr"
or
tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst"
or
tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore"
or
tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr"
or
tag = ConditionValueResultLoadTag() and result = "CondValResLoad"
or
tag = BoolConversionConstantTag() and result = "BoolConvConst"
or
tag = BoolConversionCompareTag() and result = "BoolConvComp"
or
tag = LoadTag() and result = "Load" // Implicit load due to lvalue-to-rvalue conversion
or
tag = CatchTag() and result = "Catch"
or
tag = ThrowTag() and result = "Throw"
or
tag = UnwindTag() and result = "Unwind"
or
// Added for C#
tag = NewObjTag() and result = "NewObj" or
tag = ElementsAddressTag(_) and result = "ElementsAddress" or
tag = PointerAddTag(_) and result = "PointerAdd" or
tag = ConvertTag() and result = "Convert" or
tag = GeneratedNEQTag() and result = "GeneratedNEQTag" or
tag = GeneratedConstantTag() and result = "GeneratedConstantTag" or
tag = GeneratedBranchTag() and result = "GeneratedBranchTag" or
tag = NewObjTag() and result = "NewObj"
or
tag = ElementsAddressTag(_) and result = "ElementsAddress"
or
tag = PointerAddTag(_) and result = "PointerAdd"
or
tag = ConvertTag() and result = "Convert"
or
tag = GeneratedNEQTag() and result = "GeneratedNEQTag"
or
tag = GeneratedConstantTag() and result = "GeneratedConstantTag"
or
tag = GeneratedBranchTag() and result = "GeneratedBranchTag"
or
// TODO: Reread
// exists(Field field, Class cls, int index, string tagName |
// field = cls.getCanonicalMember(index) and
// (
// tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or
// tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or
// tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore"
// ) and
// result = tagName + "(" + index + ")"
// ) or
// exists(Field field, Class cls, int index, string tagName |
// field = cls.getCanonicalMember(index) and
// (
// tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or
// tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or
// tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore"
// ) and
// result = tagName + "(" + index + ")"
// ) or
exists(int index, string tagName |
(
tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex" or
tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr" or
tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal" or
tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex"
or
tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr"
or
tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal"
or
tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore"
) and
result = tagName + "(" + index + ")"

View File

@@ -18,60 +18,54 @@ abstract class TranslatedCall extends TranslatedExpr {
// The qualifier is evaluated before the call target, because the value of
// the call target may depend on the value of the qualifier for virtual
// calls.
id = -2 and result = this.getQualifier() or
id = -1 and result = this.getCallTarget() or
id = -2 and result = this.getQualifier()
or
id = -1 and result = this.getCallTarget()
or
result = this.getArgument(id)
}
override final Instruction getFirstInstruction() {
if exists(this.getQualifier()) then
result = this.getQualifier().getFirstInstruction()
else
result = this.getFirstCallTargetInstruction()
final override Instruction getFirstInstruction() {
if exists(this.getQualifier())
then result = this.getQualifier().getFirstInstruction()
else result = this.getFirstCallTargetInstruction()
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
(
tag = CallTag() and
opcode instanceof Opcode::Call and
resultType = getCallResultType() and
isLValue = false
)
tag = CallTag() and
opcode instanceof Opcode::Call and
resultType = getCallResultType() and
isLValue = false
or
hasSideEffect() and
tag = CallSideEffectTag() and
(
hasSideEffect() and
tag = CallSideEffectTag() and
(
if hasWriteSideEffect() then (
opcode instanceof Opcode::CallSideEffect and
resultType instanceof Language::UnknownType
)
else (
opcode instanceof Opcode::CallReadSideEffect and
resultType instanceof Language::UnknownType
)
) and
isLValue = false
)
if hasWriteSideEffect()
then (
opcode instanceof Opcode::CallSideEffect and
resultType instanceof Language::UnknownType
) else (
opcode instanceof Opcode::CallReadSideEffect and
resultType instanceof Language::UnknownType
)
) and
isLValue = false
}
override Instruction getChildSuccessor(TranslatedElement child) {
(
child = this.getQualifier() and
result = this.getFirstCallTargetInstruction()
) or
(
child = this.getCallTarget() and
result = this.getFirstArgumentOrCallInstruction()
) or
child = this.getQualifier() and
result = this.getFirstCallTargetInstruction()
or
child = this.getCallTarget() and
result = this.getFirstArgumentOrCallInstruction()
or
exists(int argIndex |
child = this.getArgument(argIndex) and
if exists(this.getArgument(argIndex + 1)) then
result = this.getArgument(argIndex + 1).getFirstInstruction()
else
result = this.getInstruction(CallTag())
if exists(this.getArgument(argIndex + 1))
then result = this.getArgument(argIndex + 1).getFirstInstruction()
else result = this.getInstruction(CallTag())
)
}
@@ -80,16 +74,14 @@ abstract class TranslatedCall extends TranslatedExpr {
(
(
tag = CallTag() and
if this.hasSideEffect() then
result = this.getInstruction(CallSideEffectTag())
else
result = this.getParent().getChildSuccessor(this)
) or
(
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getParent().getChildSuccessor(this)
if this.hasSideEffect()
then result = this.getInstruction(CallSideEffectTag())
else result = this.getParent().getChildSuccessor(this)
)
or
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getParent().getChildSuccessor(this)
)
}
@@ -98,28 +90,25 @@ abstract class TranslatedCall extends TranslatedExpr {
(
tag = CallTag() and
(
(
operandTag instanceof CallTargetOperandTag and
result = this.getCallTargetResult()
) or
(
operandTag instanceof ThisArgumentOperandTag and
result = this.getQualifierResult()
) or
operandTag instanceof CallTargetOperandTag and
result = this.getCallTargetResult()
or
operandTag instanceof ThisArgumentOperandTag and
result = this.getQualifierResult()
or
exists(PositionalArgumentOperandTag argTag |
argTag = operandTag and
result = this.getArgument(argTag.getArgIndex()).getResult()
)
)
) or
(
tag = CallSideEffectTag() and
this.hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = this.getEnclosingFunction().getUnmodeledDefinitionInstruction()
)
or
tag = CallSideEffectTag() and
this.hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = this.getEnclosingFunction().getUnmodeledDefinitionInstruction()
or
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
@@ -132,9 +121,7 @@ abstract class TranslatedCall extends TranslatedExpr {
result instanceof Language::UnknownType
}
override final Instruction getResult() {
result = this.getInstruction(CallTag())
}
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
/**
* Gets the result type of the call.
@@ -144,9 +131,7 @@ abstract class TranslatedCall extends TranslatedExpr {
/**
* Holds if the call has a `this` argument.
*/
predicate hasQualifier() {
exists(this.getQualifier())
}
predicate hasQualifier() { exists(this.getQualifier()) }
/**
* Gets the `TranslatedExpr` for the indirect target of the call, if any.
@@ -169,9 +154,7 @@ abstract class TranslatedCall extends TranslatedExpr {
* overridden by a subclass for cases where there is a call target that is not
* computed from an expression (e.g. a direct call).
*/
Instruction getCallTargetResult() {
result = this.getCallTarget().getResult()
}
Instruction getCallTargetResult() { result = this.getCallTarget().getResult() }
/**
* Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value
@@ -185,9 +168,7 @@ abstract class TranslatedCall extends TranslatedExpr {
* overridden by a subclass for cases where there is a `this` argument that is
* not computed from a child expression (e.g. a constructor call).
*/
Instruction getQualifierResult() {
result = this.getQualifier().getResult()
}
Instruction getQualifierResult() { result = this.getQualifier().getResult() }
/**
* Gets the argument with the specified `index`. Does not include the `this`
@@ -200,10 +181,9 @@ abstract class TranslatedCall extends TranslatedExpr {
* argument. Otherwise, returns the call instruction.
*/
final Instruction getFirstArgumentOrCallInstruction() {
if this.hasArguments() then
result = this.getArgument(0).getFirstInstruction()
else
result = this.getInstruction(CallTag())
if this.hasArguments()
then result = this.getArgument(0).getFirstInstruction()
else result = this.getInstruction(CallTag())
}
/**
@@ -219,9 +199,9 @@ abstract class TranslatedCall extends TranslatedExpr {
private predicate hasSideEffect() { hasReadSideEffect() or hasWriteSideEffect() }
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getResult()
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getResult()
}
}
@@ -268,7 +248,7 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedC
final override TranslatedExpr getQualifier() {
expr instanceof QualifiableExpr and
result = getTranslatedExpr(expr.(QualifiableExpr).getQualifier())
result = getTranslatedExpr(expr.(QualifiableExpr).getQualifier())
}
final override TranslatedExpr getArgument(int index) {
@@ -301,7 +281,7 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
* the constructor call, address will be passed to a variable declaration.
*/
class TranslatedConstructorCall extends TranslatedFunctionCall {
TranslatedConstructorCall() {
TranslatedConstructorCall() {
expr instanceof ObjectCreation or
expr instanceof ConstructorInitializer
}
@@ -314,7 +294,7 @@ class TranslatedConstructorCall extends TranslatedFunctionCall {
result = context.getReceiver()
)
}
override Type getCallResultType() { result instanceof VoidType }
override predicate hasQualifier() { any() }

View File

@@ -12,65 +12,43 @@ abstract class ConditionContext extends TranslatedElement {
abstract Instruction getChildFalseSuccessor(TranslatedCondition child);
}
TranslatedCondition getTranslatedCondition(Expr expr) {
result.getExpr() = expr
}
TranslatedCondition getTranslatedCondition(Expr expr) { result.getExpr() = expr }
abstract class TranslatedCondition extends TranslatedElement {
Expr expr;
override final string toString() {
result = expr.toString()
}
final override string toString() { result = expr.toString() }
override final Language::AST getAST() {
result = expr
}
final override Language::AST getAST() { result = expr }
final ConditionContext getConditionContext() {
result = this.getParent()
}
final ConditionContext getConditionContext() { result = this.getParent() }
final Expr getExpr() {
result = expr
}
final Expr getExpr() { result = expr }
override final Callable getFunction() {
result = expr.getEnclosingCallable()
}
final override Callable getFunction() { result = expr.getEnclosingCallable() }
final Type getResultType() {
result = expr.getType()
}
final Type getResultType() { result = expr.getType() }
}
abstract class TranslatedFlexibleCondition extends TranslatedCondition,
ConditionContext, TTranslatedFlexibleCondition {
TranslatedFlexibleCondition() {
this = TTranslatedFlexibleCondition(expr)
}
abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext,
TTranslatedFlexibleCondition {
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
override final TranslatedElement getChild(int id) {
id = 0 and result = this.getOperand()
}
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
override final Instruction getFirstInstruction() {
final override Instruction getFirstInstruction() {
result = this.getOperand().getFirstInstruction()
}
override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
final override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
none()
}
override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
none()
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override final Instruction getChildSuccessor(TranslatedElement child) {
none()
}
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
abstract TranslatedCondition getOperand();
}
@@ -105,45 +83,36 @@ class TranslatedNotCondition extends TranslatedFlexibleCondition {
child = this.getOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override TranslatedCondition getOperand() {
result = getTranslatedCondition(expr.getOperand())
}
override TranslatedCondition getOperand() { result = getTranslatedCondition(expr.getOperand()) }
}
abstract class TranslatedNativeCondition extends TranslatedCondition,
TTranslatedNativeCondition {
TranslatedNativeCondition() {
this = TTranslatedNativeCondition(expr)
}
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }
override final Instruction getChildSuccessor(TranslatedElement child) {
none()
}
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
abstract class TranslatedBinaryLogicalOperation extends
TranslatedNativeCondition, ConditionContext {
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
override BinaryLogicalOperation expr;
override final TranslatedElement getChild(int id) {
id = 0 and result = this.getLeftOperand() or
final override TranslatedElement getChild(int id) {
id = 0 and result = this.getLeftOperand()
or
id = 1 and result = this.getRightOperand()
}
override final Instruction getFirstInstruction() {
final override Instruction getFirstInstruction() {
result = this.getLeftOperand().getFirstInstruction()
}
override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
final override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
none()
}
override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
none()
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final TranslatedCondition getLeftOperand() {
result = getTranslatedCondition(expr.getLeftOperand())
@@ -152,27 +121,22 @@ abstract class TranslatedBinaryLogicalOperation extends
final TranslatedCondition getRightOperand() {
result = getTranslatedCondition(expr.getRightOperand())
}
final TranslatedCondition getAnOperand() {
result = this.getLeftOperand() or
result = this.getLeftOperand() or
result = this.getRightOperand()
}
}
class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
TranslatedLogicalAndExpr() {
expr instanceof LogicalAndExpr
}
TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr }
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
(
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction()
) or
(
child = this.getRightOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
)
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
@@ -190,33 +154,24 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
(
child = this.getLeftOperand() and
result = getRightOperand().getFirstInstruction()
) or
(
child = this.getRightOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
)
child = this.getLeftOperand() and
result = getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
}
class TranslatedValueCondition extends TranslatedCondition,
TTranslatedValueCondition {
TranslatedValueCondition() {
this = TTranslatedValueCondition(expr)
}
class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCondition {
TranslatedValueCondition() { this = TTranslatedValueCondition(expr) }
override TranslatedElement getChild(int id) {
id = 0 and result = getValueExpr()
}
override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() }
override Instruction getFirstInstruction() {
result = this.getValueExpr().getFirstInstruction()
}
override Instruction getFirstInstruction() { result = this.getValueExpr().getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = ValueConditionConditionalBranchTag() and
opcode instanceof Opcode::ConditionalBranch and
resultType instanceof VoidType and
@@ -228,29 +183,22 @@ class TranslatedValueCondition extends TranslatedCondition,
result = this.getInstruction(ValueConditionConditionalBranchTag())
}
override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and
(
(
kind instanceof TrueEdge and
result = this.getConditionContext().getChildTrueSuccessor(this)
) or
(
kind instanceof FalseEdge and
result = this.getConditionContext().getChildFalseSuccessor(this)
)
kind instanceof TrueEdge and
result = this.getConditionContext().getChildTrueSuccessor(this)
or
kind instanceof FalseEdge and
result = this.getConditionContext().getChildFalseSuccessor(this)
)
}
override Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) {
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = ValueConditionConditionalBranchTag() and
operandTag instanceof ConditionOperandTag and
result = this.getValueExpr().getResult()
}
private TranslatedExpr getValueExpr() {
result = getTranslatedExpr(expr)
}
private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) }
}

View File

@@ -22,82 +22,66 @@ TranslatedLocalDeclaration getTranslatedLocalDeclaration(LocalVariableDeclExpr d
abstract class TranslatedLocalDeclaration extends TranslatedElement, TTranslatedDeclaration {
LocalVariableDeclExpr expr;
TranslatedLocalDeclaration() {
this = TTranslatedDeclaration(expr)
}
TranslatedLocalDeclaration() { this = TTranslatedDeclaration(expr) }
override final Callable getFunction() {
result = expr.getEnclosingCallable()
}
final override Callable getFunction() { result = expr.getEnclosingCallable() }
override final string toString() {
result = expr.toString()
}
final override string toString() { result = expr.toString() }
override final Language::AST getAST() {
result = expr
}
final override Language::AST getAST() { result = expr }
}
/**
* Represents the IR translation of the declaration of a local variable,
* including its initialization, if any.
*/
class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration,
InitializationContext {
class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, InitializationContext {
LocalVariable var;
TranslatedLocalVariableDeclaration() {
var = expr.getVariable()
}
override TranslatedElement getChild(int id) {
id = 0 and result = this.getInitialization()
}
TranslatedLocalVariableDeclaration() { var = expr.getVariable() }
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
override Instruction getFirstInstruction() {
result = this.getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
(
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVariableType(var) and
isLValue = true
) or
(
this.hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getVariableType(var) and
isLValue = false
)
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVariableType(var) and
isLValue = true
or
this.hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getVariableType(var) and
isLValue = false
}
override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if this.hasUninitializedInstruction() then
result = this.getInstruction(InitializerStoreTag())
if this.hasUninitializedInstruction()
then result = this.getInstruction(InitializerStoreTag())
else
if this.isInitializedByExpr() then
if this.isInitializedByExpr()
then
// initialization is done by the expression
result = this.getParent().getChildSuccessor(this)
else
result = this.getInitialization().getFirstInstruction()
) or
else result = this.getInitialization().getFirstInstruction()
)
or
this.hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
this.hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = this.getInitialization().getFirstInstruction() or
not exists(this.getInitialization()) and result = this.getParent().getChildSuccessor(this)
)
result = this.getInitialization().getFirstInstruction()
or
not exists(this.getInitialization()) and result = this.getParent().getChildSuccessor(this)
)
}
@@ -107,7 +91,8 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration,
override IRVariable getInstructionVariable(InstructionTag tag) {
(
tag = InitializerVariableAddressTag() or
tag = InitializerVariableAddressTag()
or
this.hasUninitializedInstruction() and tag = InitializerStoreTag()
) and
result = getIRUserVariable(getFunction(), var)
@@ -124,18 +109,18 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration,
result = this.getInstruction(InitializerVariableAddressTag())
}
override Type getTargetType() {
result = getVariableType(var)
}
override Type getTargetType() { result = getVariableType(var) }
private TranslatedInitialization getInitialization() {
// First complex initializations
if (var.getInitializer() instanceof ArrayCreation) then
result = getTranslatedInitialization(var.getInitializer().(ArrayCreation).getInitializer())
else if (var.getInitializer() instanceof ObjectCreation) then
result = getTranslatedInitialization(var.getInitializer())
else // then the simple variable initialization
result = getTranslatedInitialization(var.getInitializer())
if var.getInitializer() instanceof ArrayCreation
then result = getTranslatedInitialization(var.getInitializer().(ArrayCreation).getInitializer())
else
if var.getInitializer() instanceof ObjectCreation
then result = getTranslatedInitialization(var.getInitializer())
else
// then the simple variable initialization
result = getTranslatedInitialization(var.getInitializer())
}
private predicate hasUninitializedInstruction() {
@@ -145,12 +130,10 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration,
) and
not this.isInitializedByExpr()
}
/**
* Predicate that holds if a declaration is not explicitly initialized,
* but will be initialized as part of an expression.
*/
private predicate isInitializedByExpr() {
expr.getParent() instanceof IsExpr
}
private predicate isInitializedByExpr() { expr.getParent() instanceof IsExpr }
}

View File

@@ -66,9 +66,10 @@ private predicate ignoreExprOnly(Expr expr) {
not translateFunction(expr.getEnclosingCallable())
or
// Ignore size of arrays when translating
(expr.getParent() instanceof ArrayCreation and expr.hasValue()) or
expr.getParent() instanceof ArrayCreation and expr.hasValue()
or
// Ignore the child expression of a goto case stmt
(expr.getParent() instanceof GotoCaseStmt)
expr.getParent() instanceof GotoCaseStmt
}
/**
@@ -156,7 +157,7 @@ newtype TTranslatedElement =
expr instanceof AssignableRead and
not expr.getParent() instanceof ArrayAccess and
not (
expr.getParent() instanceof Assignment and
expr.getParent() instanceof Assignment and
expr.getType() instanceof RefType
) and
// Ignore loads for reads in `++` and `--` since their
@@ -238,10 +239,8 @@ newtype TTranslatedElement =
isFirstValueInitializedElementInRange(initList, elementIndex) and
elementCount = getEndOfValueInitializedRange(initList, elementIndex) - elementIndex
} or
// The initialization of a base class from within a constructor.
TTranslatedConstructorInitializer(ConstructorInitializer init) {
not ignoreExpr(init)
} or
// The initialization of a base class from within a constructor.
TTranslatedConstructorInitializer(ConstructorInitializer init) { not ignoreExpr(init) } or
// A statement
TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or
// A function

View File

@@ -14,252 +14,212 @@ private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
/**
* Gets the `TranslatedFunction` that represents function `callable`.
*/
TranslatedFunction getTranslatedFunction(Callable callable) {
result.getAST() = callable
}
TranslatedFunction getTranslatedFunction(Callable callable) { result.getAST() = callable }
/**
* Represents the IR translation of a function. This is the root element for
* all other elements associated with this function.
*/
class TranslatedFunction extends TranslatedElement,
TTranslatedFunction {
class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
Callable callable;
TranslatedFunction() {
this = TTranslatedFunction(callable)
}
TranslatedFunction() { this = TTranslatedFunction(callable) }
override final string toString() {
result = callable.toString()
}
final override string toString() { result = callable.toString() }
override final Language::AST getAST() {
result = callable
}
final override Language::AST getAST() { result = callable }
/**
* Gets the function being translated.
*/
override final Callable getFunction() {
result = callable
}
final override Callable getFunction() { result = callable }
override final TranslatedElement getChild(int id) {
id = -2 and result = this.getConstructorInitializer() or
id = -1 and result = this.getBody() or
final override TranslatedElement getChild(int id) {
id = -2 and result = this.getConstructorInitializer()
or
id = -1 and result = this.getBody()
or
result = this.getParameter(id)
}
private final TranslatedConstructorInitializer getConstructorInitializer() {
final private TranslatedConstructorInitializer getConstructorInitializer() {
exists(ConstructorInitializer ci |
ci = callable.getAChild() and
result = getTranslatedConstructorInitializer(ci))
ci = callable.getAChild() and
result = getTranslatedConstructorInitializer(ci)
)
}
private final TranslatedStmt getBody() {
result = getTranslatedStmt(callable.getBody())
}
final private TranslatedStmt getBody() { result = getTranslatedStmt(callable.getBody()) }
private final TranslatedParameter getParameter(int index) {
final private TranslatedParameter getParameter(int index) {
result = getTranslatedParameter(callable.getParameter(index))
}
override final Instruction getFirstInstruction() {
final override Instruction getFirstInstruction() {
result = this.getInstruction(EnterFunctionTag())
}
override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
(
(
tag = EnterFunctionTag() and
result = this.getInstruction(AliasedDefinitionTag())
) or (
tag = AliasedDefinitionTag() and
result = this.getInstruction(UnmodeledDefinitionTag())
) or
tag = EnterFunctionTag() and
result = this.getInstruction(AliasedDefinitionTag())
or
tag = AliasedDefinitionTag() and
result = this.getInstruction(UnmodeledDefinitionTag())
or
(
tag = UnmodeledDefinitionTag() and
if exists(getThisType()) then
result = this.getInstruction(InitializeThisTag())
else if exists(getParameter(0)) then
result = this.getParameter(0).getFirstInstruction()
if exists(getThisType())
then result = this.getInstruction(InitializeThisTag())
else
result = this.getBody().getFirstInstruction()
) or
if exists(getParameter(0))
then result = this.getParameter(0).getFirstInstruction()
else result = this.getBody().getFirstInstruction()
)
or
(
tag = InitializeThisTag() and
if exists(getParameter(0)) then
result = this.getParameter(0).getFirstInstruction()
if exists(getParameter(0))
then result = this.getParameter(0).getFirstInstruction()
else
if (exists(getConstructorInitializer())) then
result = this.getConstructorInitializer().getFirstInstruction()
else
result = this.getBody().getFirstInstruction()
) or
(
tag = ReturnValueAddressTag() and
result = this.getInstruction(ReturnTag())
) or
(
tag = ReturnTag() and
result = this.getInstruction(UnmodeledUseTag())
) or
(
tag = UnwindTag() and
result = this.getInstruction(UnmodeledUseTag())
) or
(
tag = UnmodeledUseTag() and
result = this.getInstruction(ExitFunctionTag())
if exists(getConstructorInitializer())
then result = this.getConstructorInitializer().getFirstInstruction()
else result = this.getBody().getFirstInstruction()
)
or
tag = ReturnValueAddressTag() and
result = this.getInstruction(ReturnTag())
or
tag = ReturnTag() and
result = this.getInstruction(UnmodeledUseTag())
or
tag = UnwindTag() and
result = this.getInstruction(UnmodeledUseTag())
or
tag = UnmodeledUseTag() and
result = this.getInstruction(ExitFunctionTag())
)
}
override final Instruction getChildSuccessor(TranslatedElement child) {
final override Instruction getChildSuccessor(TranslatedElement child) {
exists(int paramIndex |
child = this.getParameter(paramIndex) and
if exists(callable.getParameter(paramIndex + 1)) then
result = this.getParameter(paramIndex + 1).getFirstInstruction()
if exists(callable.getParameter(paramIndex + 1))
then result = this.getParameter(paramIndex + 1).getFirstInstruction()
else
if (exists(getConstructorInitializer())) then
result = this.getConstructorInitializer().getFirstInstruction()
else
result = this.getBody().getFirstInstruction()
) or
(
child = this.getConstructorInitializer() and
result = this.getBody().getFirstInstruction()
) or
(
child = this.getBody() and
result = this.getReturnSuccessorInstruction()
if exists(getConstructorInitializer())
then result = this.getConstructorInitializer().getFirstInstruction()
else result = this.getBody().getFirstInstruction()
)
or
child = this.getConstructorInitializer() and
result = this.getBody().getFirstInstruction()
or
child = this.getBody() and
result = this.getReturnSuccessorInstruction()
}
override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
final override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
(
(
tag = EnterFunctionTag() and
opcode instanceof Opcode::EnterFunction and
resultType instanceof VoidType and
isLValue = false
) or
(
tag = UnmodeledDefinitionTag() and
opcode instanceof Opcode::UnmodeledDefinition and
resultType instanceof Language::UnknownType and
isLValue = false
) or
(
tag = AliasedDefinitionTag() and
opcode instanceof Opcode::AliasedDefinition and
resultType instanceof Language::UnknownType and
isLValue = false
) or
(
tag = InitializeThisTag() and
opcode instanceof Opcode::InitializeThis and
resultType = getThisType() and
isLValue = true
) or
(
tag = ReturnValueAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = this.getReturnType() and
not resultType instanceof VoidType and
isLValue = true
) or
tag = EnterFunctionTag() and
opcode instanceof Opcode::EnterFunction and
resultType instanceof VoidType and
isLValue = false
or
tag = UnmodeledDefinitionTag() and
opcode instanceof Opcode::UnmodeledDefinition and
resultType instanceof Language::UnknownType and
isLValue = false
or
tag = AliasedDefinitionTag() and
opcode instanceof Opcode::AliasedDefinition and
resultType instanceof Language::UnknownType and
isLValue = false
or
tag = InitializeThisTag() and
opcode instanceof Opcode::InitializeThis and
resultType = getThisType() and
isLValue = true
or
tag = ReturnValueAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = this.getReturnType() and
not resultType instanceof VoidType and
isLValue = true
or
(
tag = ReturnTag() and
resultType instanceof VoidType and
isLValue = false and
if this.getReturnType() instanceof VoidType then
opcode instanceof Opcode::ReturnVoid
else
opcode instanceof Opcode::ReturnValue
) or
(
tag = UnwindTag() and
opcode instanceof Opcode::Unwind and
resultType instanceof VoidType and
isLValue = false and
(
// Only generate the `Unwind` instruction if there is any exception
// handling present in the function.
exists(TryStmt try |
try.getEnclosingCallable() = callable
) or
exists(ThrowStmt throw |
throw.getEnclosingCallable() = callable
)
)
) or
(
tag = UnmodeledUseTag() and
opcode instanceof Opcode::UnmodeledUse and
resultType instanceof VoidType and
isLValue = false
) or
(
tag = ExitFunctionTag() and
opcode instanceof Opcode::ExitFunction and
resultType instanceof VoidType and
isLValue = false
if this.getReturnType() instanceof VoidType
then opcode instanceof Opcode::ReturnVoid
else opcode instanceof Opcode::ReturnValue
)
or
tag = UnwindTag() and
opcode instanceof Opcode::Unwind and
resultType instanceof VoidType and
isLValue = false and
(
// Only generate the `Unwind` instruction if there is any exception
// handling present in the function.
exists(TryStmt try | try.getEnclosingCallable() = callable) or
exists(ThrowStmt throw | throw.getEnclosingCallable() = callable)
)
or
tag = UnmodeledUseTag() and
opcode instanceof Opcode::UnmodeledUse and
resultType instanceof VoidType and
isLValue = false
or
tag = ExitFunctionTag() and
opcode instanceof Opcode::ExitFunction and
resultType instanceof VoidType and
isLValue = false
)
}
override final Instruction getExceptionSuccessorInstruction() {
result = this.getInstruction(UnwindTag())
final override Instruction getExceptionSuccessorInstruction() {
result = this.getInstruction(UnwindTag())
}
override final Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) {
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = UnmodeledUseTag() and
operandTag instanceof UnmodeledUseOperandTag and
result.getEnclosingFunction() = callable and
result.hasMemoryResult()
or
tag = UnmodeledUseTag() and
operandTag instanceof UnmodeledUseOperandTag and
result = getUnmodeledDefinitionInstruction()
or
tag = ReturnTag() and
not this.getReturnType() instanceof VoidType and
(
tag = UnmodeledUseTag() and
operandTag instanceof UnmodeledUseOperandTag and
result.getEnclosingFunction() = callable and
result.hasMemoryResult()
) or
(
tag = UnmodeledUseTag() and
operandTag instanceof UnmodeledUseOperandTag and
operandTag instanceof AddressOperandTag and
result = this.getInstruction(ReturnValueAddressTag())
or
operandTag instanceof LoadOperandTag and
result = getUnmodeledDefinitionInstruction()
) or
(
tag = ReturnTag() and
not this.getReturnType() instanceof VoidType and
(
(
operandTag instanceof AddressOperandTag and
result = this.getInstruction(ReturnValueAddressTag())
) or
(
operandTag instanceof LoadOperandTag and
result = getUnmodeledDefinitionInstruction()
)
)
)
}
override final Type getInstructionOperandType(InstructionTag tag,
TypedOperandTag operandTag) {
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
tag = ReturnTag() and
not this.getReturnType() instanceof VoidType and
operandTag instanceof LoadOperandTag and
result = this.getReturnType()
}
override final IRVariable getInstructionVariable(InstructionTag tag) {
final override IRVariable getInstructionVariable(InstructionTag tag) {
tag = ReturnValueAddressTag() and
result = this.getReturnVariable()
}
override final predicate hasTempVariable(TempVariableTag tag, Type type) {
final override predicate hasTempVariable(TempVariableTag tag, Type type) {
tag = ReturnValueTempVar() and
type = this.getReturnType() and
not type instanceof VoidType
@@ -270,10 +230,9 @@ class TranslatedFunction extends TranslatedElement,
* statement. In C#, this should be the instruction which generates `VariableAddress[#return]`.
*/
final Instruction getReturnSuccessorInstruction() {
if this.getReturnType() instanceof VoidType then
result = this.getInstruction(ReturnTag())
else
result = this.getInstruction(ReturnValueAddressTag())
if this.getReturnType() instanceof VoidType
then result = this.getInstruction(ReturnTag())
else result = this.getInstruction(ReturnValueAddressTag())
}
/**
@@ -297,24 +256,21 @@ class TranslatedFunction extends TranslatedElement,
final Instruction getInitializeThisInstruction() {
result = this.getInstruction(InitializeThisTag())
}
/**
* Gets the type pointed to by the `this` pointer for this function (i.e. `*this`).
* Holds only if the function is an instance member function, constructor, or destructor.
*/
final Type getThisType() {
// `callable` is a user declared member and it is not static
(
callable instanceof Member and
not callable.(Member).isStatic() and
result = callable.getDeclaringType()
) or
callable instanceof Member and
not callable.(Member).isStatic() and
result = callable.getDeclaringType()
or
// `callable` is a compiler generated accessor
(
callable instanceof Accessor and
not callable.(Accessor).isStatic() and
result = callable.getDeclaringType()
)
callable instanceof Accessor and
not callable.(Accessor).isStatic() and
result = callable.getDeclaringType()
}
/**
@@ -324,29 +280,24 @@ class TranslatedFunction extends TranslatedElement,
*/
final predicate hasUserVariable(Variable var, Type type) {
(
(
var.(Member).isStatic() and
exists(VariableAccess access |
access.getTarget() = var and
access.getEnclosingCallable() = callable
)
) or
var.(Member).isStatic() and
exists(VariableAccess access |
access.getTarget() = var and
access.getEnclosingCallable() = callable
)
or
var.(LocalScopeVariable).getCallable() = callable
) and
type = getVariableType(var)
}
private final Type getReturnType() {
result = callable.getReturnType()
}
final private Type getReturnType() { result = callable.getReturnType() }
}
/**
* Gets the `TranslatedParameter` that represents parameter `param`.
*/
TranslatedParameter getTranslatedParameter(Parameter param) {
result.getAST() = param
}
TranslatedParameter getTranslatedParameter(Parameter param) { result.getAST() = param }
/**
* Represents the IR translation of a function parameter, including the
@@ -355,66 +306,48 @@ TranslatedParameter getTranslatedParameter(Parameter param) {
class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
Parameter param;
TranslatedParameter() {
this = TTranslatedParameter(param)
}
TranslatedParameter() { this = TTranslatedParameter(param) }
override final string toString() {
result = param.toString()
}
final override string toString() { result = param.toString() }
override final Language::AST getAST() {
result = param
}
final override Language::AST getAST() { result = param }
override final Callable getFunction() {
result = param.getCallable()
}
final override Callable getFunction() { result = param.getCallable() }
override final Instruction getFirstInstruction() {
final override Instruction getFirstInstruction() {
result = this.getInstruction(InitializerVariableAddressTag())
}
override final TranslatedElement getChild(int id) {
none()
}
final override TranslatedElement getChild(int id) { none() }
override final Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
(
(
tag = InitializerVariableAddressTag() and
result = this.getInstruction(InitializerStoreTag())
) or
(
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
)
}
override final Instruction getChildSuccessor(TranslatedElement child) {
none()
}
override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
(
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVariableType(param) and
isLValue = true
) or
(
result = this.getInstruction(InitializerStoreTag())
or
tag = InitializerStoreTag() and
opcode instanceof Opcode::InitializeParameter and
resultType = getVariableType(param) and
isLValue = false
result = this.getParent().getChildSuccessor(this)
)
}
override final IRVariable getInstructionVariable(InstructionTag tag) {
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
final override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVariableType(param) and
isLValue = true
or
tag = InitializerStoreTag() and
opcode instanceof Opcode::InitializeParameter and
resultType = getVariableType(param) and
isLValue = false
}
final override IRVariable getInstructionVariable(InstructionTag tag) {
(
tag = InitializerStoreTag() or
tag = InitializerVariableAddressTag()
@@ -422,14 +355,11 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
result = getIRUserVariable(getFunction(), param)
}
override final Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) {
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = InitializerStoreTag() and
(
(
operandTag instanceof AddressOperandTag and
result = this.getInstruction(InitializerVariableAddressTag())
)
operandTag instanceof AddressOperandTag and
result = this.getInstruction(InitializerVariableAddressTag())
)
}
}

View File

@@ -1,6 +1,6 @@
/**
* Class that deals with variable initializations.
* Separated from `TranslatedExpr` for clarity.
* Separated from `TranslatedExpr` for clarity.
*/
import csharp
@@ -49,9 +49,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
final override Callable getFunction() { result = expr.getEnclosingCallable() }
override final Language::AST getAST() {
result = expr
}
final override Language::AST getAST() { result = expr }
/**
* Gets the expression that is doing the initialization.
@@ -62,9 +60,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
* Gets the initialization context that describes the location being
* initialized.
*/
final InitializationContext getContext() {
result = this.getParent()
}
final InitializationContext getContext() { result = this.getParent() }
final TranslatedFunction getEnclosingFunction() {
result = getTranslatedFunction(expr.getEnclosingCallable())
@@ -76,7 +72,8 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
*/
abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext {
override Instruction getFirstInstruction() {
result = this.getChild(0).getFirstInstruction() or
result = this.getChild(0).getFirstInstruction()
or
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
}
@@ -135,7 +132,9 @@ class TranslatedDirectInitialization extends TranslatedInitialization {
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
override Instruction getFirstInstruction() { result = this.getInitializer().getFirstInstruction() }
override Instruction getFirstInstruction() {
result = this.getInitializer().getFirstInstruction()
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
@@ -166,7 +165,7 @@ class TranslatedDirectInitialization extends TranslatedInitialization {
result = this.getInitializer().getResult()
)
}
TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
}
@@ -176,138 +175,112 @@ class TranslatedDirectInitialization extends TranslatedInitialization {
* object of type `expr.getType()` is allocated, which is then initialized by the
* constructor.
*/
class TranslatedObjectInitialization extends TranslatedInitialization,
StructorCallContext {
class TranslatedObjectInitialization extends TranslatedInitialization, StructorCallContext {
override ObjectCreation expr;
override TranslatedElement getChild(int id) {
id = 0 and result = this.getConstructorCall() or
id = 0 and result = this.getConstructorCall()
or
id = 1 and result = this.getInitializerExpr()
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue) {
(
// Instruction that allocated space for a new object,
// and returns its address
tag = NewObjTag() and
opcode instanceof Opcode::NewObj and
resultType = expr.getType() and
isLValue = false
)
or
(
// Store op used to assign the variable that
// is initialized the address of the newly allocated
// object
tag = InitializerStoreTag() and
opcode instanceof Opcode::Store and
resultType = expr.getType() and
isLValue = false
)
or
(
needsConversion() and
tag = AssignmentConvertRightTag() and
// For now only use `Opcode::Convert` to
// crudely represent conversions. Could
// be useful to represent the whole chain of conversions
opcode instanceof Opcode::Convert and
resultType = this.getContext().getTargetType() and
isLValue = false
)
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
// Instruction that allocated space for a new object,
// and returns its address
tag = NewObjTag() and
opcode instanceof Opcode::NewObj and
resultType = expr.getType() and
isLValue = false
or
// Store op used to assign the variable that
// is initialized the address of the newly allocated
// object
tag = InitializerStoreTag() and
opcode instanceof Opcode::Store and
resultType = expr.getType() and
isLValue = false
or
needsConversion() and
tag = AssignmentConvertRightTag() and
// For now only use `Opcode::Convert` to
// crudely represent conversions. Could
// be useful to represent the whole chain of conversions
opcode instanceof Opcode::Convert and
resultType = this.getContext().getTargetType() and
isLValue = false
}
override final Instruction getFirstInstruction() {
result = this.getInstruction(NewObjTag())
}
final override Instruction getFirstInstruction() { result = this.getInstruction(NewObjTag()) }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
(
(
tag = NewObjTag() and
result = this.getConstructorCall().getFirstInstruction()
)
tag = NewObjTag() and
result = this.getConstructorCall().getFirstInstruction()
or
(
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this)
or
(
tag = AssignmentConvertRightTag() and
result = this.getInstruction(InitializerStoreTag())
)
tag = AssignmentConvertRightTag() and
result = this.getInstruction(InitializerStoreTag())
)
}
override Instruction getChildSuccessor(TranslatedElement child) {
(
child = this.getConstructorCall() and
if (exists(this.getInitializerExpr())) then
result = this.getInitializerExpr().getFirstInstruction()
if exists(this.getInitializerExpr())
then result = this.getInitializerExpr().getFirstInstruction()
else
if this.needsConversion() then
result = this.getInstruction(AssignmentConvertRightTag())
else
result = this.getInstruction(InitializerStoreTag())
) or
if this.needsConversion()
then result = this.getInstruction(AssignmentConvertRightTag())
else result = this.getInstruction(InitializerStoreTag())
)
or
(
child = this.getInitializerExpr() and
if this.needsConversion() then
result = this.getInstruction(AssignmentConvertRightTag())
else
result = this.getInstruction(InitializerStoreTag())
if this.needsConversion()
then result = this.getInstruction(AssignmentConvertRightTag())
else result = this.getInstruction(InitializerStoreTag())
)
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = InitializerStoreTag() and
(
tag = InitializerStoreTag() and
operandTag instanceof AddressOperandTag and
result = this.getParent().(InitializationContext).getTargetAddress()
or
(
(
operandTag instanceof AddressOperandTag and
result = this.getParent().(InitializationContext).getTargetAddress()
) or
(
operandTag instanceof StoreValueOperandTag and
if (needsConversion()) then
result = this.getInstruction(AssignmentConvertRightTag())
else
result = this.getInstruction(NewObjTag())
)
operandTag instanceof StoreValueOperandTag and
if needsConversion()
then result = this.getInstruction(AssignmentConvertRightTag())
else result = this.getInstruction(NewObjTag())
)
) or
(
tag = AssignmentConvertRightTag() and
operandTag instanceof UnaryOperandTag and
result = this.getInstruction(NewObjTag())
)
or
tag = AssignmentConvertRightTag() and
operandTag instanceof UnaryOperandTag and
result = this.getInstruction(NewObjTag())
}
TranslatedExpr getConstructorCall() {
result = getTranslatedExpr(expr)
}
TranslatedExpr getInitializerExpr() {
result = getTranslatedExpr(expr.getInitializer())
}
override Instruction getReceiver() {
TranslatedExpr getConstructorCall() { result = getTranslatedExpr(expr) }
TranslatedExpr getInitializerExpr() { result = getTranslatedExpr(expr.getInitializer()) }
override Instruction getReceiver() {
// The newly allocated object will be the target of the constructor call
result = this.getInstruction(NewObjTag())
}
private predicate needsConversion() {
expr.getType() != this.getContext().getTargetType()
}
private predicate needsConversion() { expr.getType() != this.getContext().getTargetType() }
}
//private string getZeroValue(Type type) {
// if type instanceof FloatingPointType then result = "0.0" else result = "0"
//}
/**
* Represents the IR translation of the initialization of an array element from
* an element of an initializer list.
@@ -319,13 +292,13 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
result = initList.toString() + "[" + getElementIndex().toString() + "]"
}
override final Language::AST getAST() {
result = initList
}
final override Language::AST getAST() { result = initList }
final override Callable getFunction() { result = initList.getEnclosingCallable() }
final override Instruction getFirstInstruction() { result = this.getInstruction(getElementIndexTag()) }
final override Instruction getFirstInstruction() {
result = this.getInstruction(getElementIndexTag())
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
@@ -416,12 +389,11 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
}
// TODO: Possibly refactor into something simpler
abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement, StructorCallContext {
abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement,
StructorCallContext {
Call call;
override final Language::AST getAST() {
result = call
}
final override Language::AST getAST() { result = call }
final override TranslatedElement getChild(int id) {
id = 0 and result = this.getConstructorCall()
@@ -437,37 +409,31 @@ abstract class TranslatedConstructorCallFromConstructor extends TranslatedElemen
final TranslatedExpr getConstructorCall() { result = getTranslatedExpr(call) }
}
TranslatedConstructorInitializer getTranslatedConstructorInitializer(ConstructorInitializer ci) {
result.getAST() = ci
result.getAST() = ci
}
/**
* Represents the IR translation of a call from a constructor to a base class
* Represents the IR translation of a call from a constructor to a base class
* constructor or another constructor in same class .
*/
// Review: do we need the conversion instructions in C#?
class TranslatedConstructorInitializer extends TranslatedConstructorCallFromConstructor,
TTranslatedConstructorInitializer {
TranslatedConstructorInitializer() {
this = TTranslatedConstructorInitializer(call)
}
override string toString() {
result = "constuructor init: " + call.toString()
}
override Instruction getFirstInstruction() {
if (needsConversion()) then
result = this.getInstruction(OnlyInstructionTag())
else
result = this.getConstructorCall().getFirstInstruction()
class TranslatedConstructorInitializer extends TranslatedConstructorCallFromConstructor,
TTranslatedConstructorInitializer {
TranslatedConstructorInitializer() { this = TTranslatedConstructorInitializer(call) }
override string toString() { result = "constuructor init: " + call.toString() }
override Instruction getFirstInstruction() {
if needsConversion()
then result = this.getInstruction(OnlyInstructionTag())
else result = this.getConstructorCall().getFirstInstruction()
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
this.needsConversion() and
this.needsConversion() and
tag = OnlyInstructionTag() and
opcode instanceof Opcode::Convert and
resultType = call.getTarget().getDeclaringType() and
@@ -480,11 +446,10 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons
result = this.getConstructorCall().getFirstInstruction()
}
override Instruction getReceiver() {
if this.needsConversion() then
result = this.getInstruction(OnlyInstructionTag())
else
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
override Instruction getReceiver() {
if this.needsConversion()
then result = this.getInstruction(OnlyInstructionTag())
else result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
@@ -494,9 +459,9 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons
}
predicate needsConversion() {
call.getTarget().getDeclaringType() != this.getFunction().getDeclaringType()
call.getTarget().getDeclaringType() != this.getFunction().getDeclaringType()
}
override predicate getInstructionInheritance(
InstructionTag tag, Class baseClass, Class derivedClass
) {

View File

@@ -1,7 +1,9 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph {
import Reachability::Graph
class Block = Reachability::ReachableBlock;
}

View File

@@ -9,13 +9,13 @@ private class DominancePropertyProvider extends IRPropertyProvider {
blockImmediatelyDominates(dominator, block) and
key = "ImmediateDominator" and
result = "Block " + dominator.getDisplayIndex().toString()
) or
(
key = "DominanceFrontier" and
result = strictconcat(IRBlock frontierBlock |
frontierBlock = getDominanceFrontier(block) |
)
or
key = "DominanceFrontier" and
result = strictconcat(IRBlock frontierBlock |
frontierBlock = getDominanceFrontier(block)
|
frontierBlock.getDisplayIndex().toString(), ", " order by frontierBlock.getDisplayIndex()
)
)
}
}

View File

@@ -4,17 +4,14 @@ import IR
private class ReachableBlockPropertyProvider extends IRPropertyProvider {
override string getBlockProperty(IRBlock block, string key) {
(
not block instanceof ReachableBlock and
key = "Unreachable" and
not block instanceof ReachableBlock and
key = "Unreachable" and
result = "true"
or
exists(EdgeKind kind |
isInfeasibleEdge(block, kind) and
key = "Infeasible(" + kind.toString() + ")" and
result = "true"
) or
(
exists(EdgeKind kind |
isInfeasibleEdge(block, kind) and
key = "Infeasible(" + kind.toString() + ")" and
result = "true"
)
)
}
}

View File

@@ -5,10 +5,7 @@ private import ConstantAnalysis
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
exists(int conditionValue |
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
if conditionValue = 0 then
kind instanceof TrueEdge
else
kind instanceof FalseEdge
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
)
}
@@ -25,9 +22,7 @@ private IRBlock getAFeasiblePredecessorBlock(IRBlock successor) {
}
private predicate isBlockReachable(IRBlock block) {
exists(IRFunction f |
getAFeasiblePredecessorBlock*(block) = f.getEntryBlock()
)
exists(IRFunction f | getAFeasiblePredecessorBlock*(block) = f.getEntryBlock())
}
/**
@@ -35,34 +30,22 @@ private predicate isBlockReachable(IRBlock block) {
* edges.
*/
class ReachableBlock extends IRBlockBase {
ReachableBlock() {
isBlockReachable(this)
}
ReachableBlock() { isBlockReachable(this) }
final ReachableBlock getAFeasiblePredecessor() {
result = getAFeasiblePredecessorBlock(this)
}
final ReachableBlock getAFeasiblePredecessor() { result = getAFeasiblePredecessorBlock(this) }
final ReachableBlock getAFeasibleSuccessor() {
this = getAFeasiblePredecessorBlock(result)
}
final ReachableBlock getAFeasibleSuccessor() { this = getAFeasiblePredecessorBlock(result) }
}
/**
* An instruction that is contained in a reachable block.
*/
class ReachableInstruction extends Instruction {
ReachableInstruction() {
this.getBlock() instanceof ReachableBlock
}
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
}
module Graph {
predicate isEntryBlock(ReachableBlock block) {
exists(IRFunction f |
block = f.getEntryBlock()
)
}
predicate isEntryBlock(ReachableBlock block) { exists(IRFunction f | block = f.getEntryBlock()) }
predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) {
succ = pred.getAFeasibleSuccessor()

View File

@@ -1,2 +1,2 @@
import semmle.code.csharp.ir.implementation.raw.IR as IR
import semmle.code.csharp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis
import semmle.code.csharp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis

View File

@@ -2,49 +2,43 @@ private import csharp as CSharp
private import IRUtilities
class Function = CSharp::Callable;
class Location = CSharp::Location;
class AST = CSharp::Element;
class Type = CSharp::Type;
class UnknownType = CSharp::NullType;
class VoidType = CSharp::VoidType;
class IntegralType = CSharp::IntegralType;
class FloatingPointType = CSharp::FloatingPointType;
private newtype TClassDerivation =
private newtype TClassDerivation =
// Note that this is the `Class` type exported from this module, not CSharp::Class.
MkClassDerivation(Class base, Class derived) {
derived.getABaseType() = base
}
MkClassDerivation(Class base, Class derived) { derived.getABaseType() = base }
private newtype TBuiltInOperation = NoOp()
private newtype TBuiltInOperation =
NoOp()
class BuiltInOperation extends TBuiltInOperation {
string toString() {
result = "BuiltInOp"
}
string toString() { result = "BuiltInOp" }
}
class ClassDerivation extends MkClassDerivation {
Class baseClass;
Class derivedClass;
ClassDerivation() {
this = MkClassDerivation(baseClass, derivedClass)
}
ClassDerivation() { this = MkClassDerivation(baseClass, derivedClass) }
string toString() {
result = "ClassDerivation"
}
string toString() { result = "ClassDerivation" }
final Class getBaseClass() {
result = baseClass
}
final Class getBaseClass() { result = baseClass }
final Class getDerivedClass() {
result = derivedClass
}
final Class getDerivedClass() { result = derivedClass }
final int getByteOffset() {
// Inheritance never requires adjusting the `this` pointer in C#.
@@ -55,47 +49,51 @@ class ClassDerivation extends MkClassDerivation {
class StringLiteral = CSharp::StringLiteral;
class Variable = CSharp::Variable;
class AutomaticVariable = CSharp::LocalScopeVariable;
class StaticVariable = CSharp::Variable;
class Parameter = CSharp::Parameter;
class Field = CSharp::Field;
// TODO: Remove necessity for these.
class Expr = CSharp::Expr;
class Class = CSharp::ValueOrRefType; // Used for inheritance conversions
string getIdentityString(Function func) {
result = func.getLabel()
}
class Class = CSharp::ValueOrRefType; // Used for inheritance conversions
string getIdentityString(Function func) { result = func.getLabel() }
predicate hasCaseEdge(string minValue, string maxValue) {
// TODO: Need to handle pattern matching
exists(CSharp :: CaseStmt cst |
hasCaseEdge(cst, minValue, maxValue)
)
exists(CSharp::CaseStmt cst | hasCaseEdge(cst, minValue, maxValue))
}
predicate hasPositionalArgIndex(int argIndex) {
exists(CSharp::MethodCall call |
exists(call.getArgument(argIndex))
)
exists(CSharp::MethodCall call | exists(call.getArgument(argIndex)))
}
predicate hasAsmOperandIndex(int operandIndex) {
none()
}
predicate hasAsmOperandIndex(int operandIndex) { none() }
int getTypeSize(Type type) {
// REVIEW: Is this complete?
result = type.(CSharp::SimpleType).getSize() or
result = getTypeSize(type.(CSharp::Enum).getUnderlyingType()) or
result = type.(CSharp::SimpleType).getSize()
or
result = getTypeSize(type.(CSharp::Enum).getUnderlyingType())
or
// TODO: Generate a reasonable size
type instanceof CSharp::Struct and result = 16 or
type instanceof CSharp::RefType and result = getPointerSize() or
type instanceof CSharp::PointerType and result = getPointerSize() or
result = getTypeSize(type.(CSharp::TupleType).getUnderlyingType()) or
type instanceof CSharp::Struct and result = 16
or
type instanceof CSharp::RefType and result = getPointerSize()
or
type instanceof CSharp::PointerType and result = getPointerSize()
or
result = getTypeSize(type.(CSharp::TupleType).getUnderlyingType())
or
// TODO: Add room for extra field
result = getTypeSize(type.(CSharp::NullableType).getUnderlyingType()) or
result = getTypeSize(type.(CSharp::NullableType).getUnderlyingType())
or
type instanceof CSharp::VoidType and result = 0
}
@@ -104,9 +102,7 @@ int getPointerSize() {
result = 8
}
predicate isVariableAutomatic(Variable var) {
var instanceof CSharp::LocalScopeVariable
}
predicate isVariableAutomatic(Variable var) { var instanceof CSharp::LocalScopeVariable }
string getStringLiteralText(StringLiteral s) {
// REVIEW: Is this the right escaping?
@@ -118,6 +114,4 @@ predicate hasPotentialLoop(Function f) {
exists(CSharp::GotoStmt s | s.getEnclosingCallable() = f)
}
predicate hasGoto(Function f) {
exists(CSharp::GotoStmt s | s.getEnclosingCallable() = f)
}
predicate hasGoto(Function f) { exists(CSharp::GotoStmt s | s.getEnclosingCallable() = f) }

View File

@@ -19,23 +19,24 @@ private Type getDecayedType(Type type) {
Type getVariableType(Variable v) {
exists(Type declaredType |
declaredType = v.getType() and
if v instanceof Parameter then (
result = getDecayedType(declaredType) or
if v instanceof Parameter
then
result = getDecayedType(declaredType)
or
not exists(getDecayedType(declaredType)) and result = declaredType
)
else if declaredType instanceof ArrayType then (
// TODO: Arrays have a declared dimension in C#, so this should not be needed
// and not declaredType.(ArrayType).hasArraySize()
result = v.getInitializer().getType() or
not exists(v.getInitializer()) and result = declaredType
)
else (
result = declaredType
)
else
if declaredType instanceof ArrayType
then
// TODO: Arrays have a declared dimension in C#, so this should not be needed
// and not declaredType.(ArrayType).hasArraySize()
result = v.getInitializer().getType()
or
not exists(v.getInitializer()) and result = declaredType
else result = declaredType
)
}
predicate hasCaseEdge(CaseStmt caseStmt, string minValue, string maxValue) {
minValue = caseStmt.getPattern().getValue() and
maxValue = minValue
}
}

View File

@@ -3,56 +3,42 @@ class IntValue = int;
/**
* Returns the value of the maximum representable integer.
*/
int maxValue() {
result = 2147483647
}
int maxValue() { result = 2147483647 }
/**
* Returns the value of the minimum representable integer.
*/
int minValue() {
result = -2147483647
}
int minValue() { result = -2147483647 }
/**
* Returns a value representing an unknown integer.
*/
IntValue unknown() {
result = -2147483648
}
IntValue unknown() { result = -2147483648 }
/**
* Holds if `n` has a known value.
*/
bindingset[n]
predicate hasValue(IntValue n) {
n != unknown()
}
predicate hasValue(IntValue n) { n != unknown() }
/**
* Returns a string representation of `n`. If `n` does not have a known value, the result is "??".
*/
bindingset[n]
string intValueToString(IntValue n) {
if hasValue(n) then result = n.toString() else result = "??"
}
string intValueToString(IntValue n) { if hasValue(n) then result = n.toString() else result = "??" }
/**
* Holds if the value `f` is within the range of representable integers.
*/
pragma[inline]
bindingset[f]
private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue())
}
pragma[inline]
private predicate isRepresentable(float f) { f >= minValue() and f <= maxValue() }
/**
* Gets the value of `n`. Holds only if `n` has a known value.
*/
bindingset[n]
int getValue(IntValue n) {
hasValue(n) and result = n
}
int getValue(IntValue n) { hasValue(n) and result = n }
/**
* Returns `a + b`. If either input is unknown, or if the addition overflows,
@@ -60,10 +46,9 @@ int getValue(IntValue n) {
*/
bindingset[a, b]
IntValue add(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then
result = a + b
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) + b.(float))
then result = a + b
else result = unknown()
}
/**
@@ -72,10 +57,9 @@ IntValue add(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue sub(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then
result = a - b
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) - b.(float))
then result = a - b
else result = unknown()
}
/**
@@ -85,12 +69,12 @@ IntValue sub(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue mul(IntValue a, IntValue b) {
if (a = 0) or (b = 0) then
result = 0
else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then
result = a * b
if a = 0 or b = 0
then result = 0
else
result = unknown()
if hasValue(a) and hasValue(b) and isRepresentable(a.(float) * b.(float))
then result = a * b
else result = unknown()
}
/**
@@ -102,10 +86,7 @@ IntValue div(IntValue a, IntValue b) {
// Normally, integer division has to worry about overflow for INT_MIN/-1.
// However, since we use INT_MIN to represent an unknown value anyway, we only
// have to worry about division by zero.
if hasValue(a) and hasValue(b) and (b != 0) then
result = a / b
else
result = unknown()
if hasValue(a) and hasValue(b) and b != 0 then result = a / b else result = unknown()
}
/**
@@ -113,14 +94,9 @@ IntValue div(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareEQ(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a = b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a = b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -128,14 +104,9 @@ IntValue compareEQ(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareNE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a != b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a != b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -143,14 +114,9 @@ IntValue compareNE(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareLT(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a < b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a < b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -158,14 +124,9 @@ IntValue compareLT(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareGT(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a > b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a > b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -173,14 +134,9 @@ IntValue compareGT(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareLE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a <= b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a <= b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -188,14 +144,9 @@ IntValue compareLE(IntValue a, IntValue b) {
*/
bindingset[a, b]
IntValue compareGE(IntValue a, IntValue b) {
if hasValue(a) and hasValue(b) then (
if a >= b then
result = 1
else
result = 0
)
else
result = unknown()
if hasValue(a) and hasValue(b)
then if a >= b then result = 1 else result = 0
else result = unknown()
}
/**
@@ -203,53 +154,41 @@ IntValue compareGE(IntValue a, IntValue b) {
*/
bindingset[a]
IntValue neg(IntValue a) {
result = -a // -INT_MIN = INT_MIN, so this preserves unknown
result = -a // -INT_MIN = INT_MIN, so this preserves unknown
}
/**
* Holds if `a` is equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isEQ(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a = b
}
predicate isEQ(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a = b }
/**
* Holds if `a` is not equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isNE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a != b
}
predicate isNE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a != b }
/**
* Holds if `a` is less than `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isLT(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a < b
}
predicate isLT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a < b }
/**
* Holds if `a` is less than or equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isLE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a <= b
}
predicate isLE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a <= b }
/**
* Holds if `a` is greater than `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isGT(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a > b
}
predicate isGT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a > b }
/**
* Holds if `a` is greater than or equal to `b`. Does not hold if either `a` or `b` is unknown.
*/
bindingset[a, b]
predicate isGE(IntValue a, IntValue b) {
hasValue(a) and hasValue(b) and a >= b
}
predicate isGE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a >= b }

View File

@@ -13,14 +13,15 @@ private import IntegerConstant
*/
bindingset[defStart, defEnd, useStart, useEnd]
Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntValue useEnd) {
if isEQ(defStart, useStart) and isEQ(defEnd, useEnd) then
result instanceof MustExactlyOverlap
else if isLE(defStart, useStart) and isGE(defEnd, useEnd) then
result instanceof MustTotallyOverlap
else if isLE(defEnd, useStart) or isGE(defStart, useEnd) then
none()
if isEQ(defStart, useStart) and isEQ(defEnd, useEnd)
then result instanceof MustExactlyOverlap
else
result instanceof MayPartiallyOverlap
if isLE(defStart, useStart) and isGE(defEnd, useEnd)
then result instanceof MustTotallyOverlap
else
if isLE(defEnd, useStart) or isGE(defStart, useEnd)
then none()
else result instanceof MayPartiallyOverlap
}
/**

View File

@@ -6,32 +6,26 @@
/**
* Gets the value of the maximum representable integer.
*/
int maxValue() {
result = 2147483647
}
int maxValue() { result = 2147483647 }
/**
* Gets the value of the minimum representable integer.
*/
int minValue() {
result = -2147483648
}
int minValue() { result = -2147483648 }
/**
* Holds if the value `f` is within the range of representable integers.
*/
pragma[inline]
bindingset[f]
private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue())
}
pragma[inline]
private predicate isRepresentable(float f) { f >= minValue() and f <= maxValue() }
/**
* Returns `a + b`. If the addition overflows, there is no result.
*/
bindingset[a, b]
int add(int a, int b) {
isRepresentable((float)a + (float)b) and
isRepresentable(a.(float) + b.(float)) and
result = a + b
}
@@ -40,7 +34,7 @@ int add(int a, int b) {
*/
bindingset[a, b]
int sub(int a, int b) {
isRepresentable((float)a - (float)b) and
isRepresentable(a.(float) - b.(float)) and
result = a - b
}
@@ -57,7 +51,7 @@ int mul(int a, int b) {
b = 0 and
result = 0
or
isRepresentable((float)a * (float)b) and
isRepresentable(a.(float) * b.(float)) and
result = a * b
}
@@ -66,63 +60,34 @@ int mul(int a, int b) {
*/
bindingset[a, b]
int div(int a, int b) {
b != 0 and (a != minValue() or b != -1) and
b != 0 and
(a != minValue() or b != -1) and
result = a / b
}
/** Returns `a == b`. */
bindingset[a, b]
int compareEQ(int a, int b) {
if a = b then
result = 1
else
result = 0
}
int compareEQ(int a, int b) { if a = b then result = 1 else result = 0 }
/** Returns `a != b`. */
bindingset[a, b]
int compareNE(int a, int b) {
if a != b then
result = 1
else
result = 0
}
int compareNE(int a, int b) { if a != b then result = 1 else result = 0 }
/** Returns `a < b`. */
bindingset[a, b]
int compareLT(int a, int b) {
if a < b then
result = 1
else
result = 0
}
int compareLT(int a, int b) { if a < b then result = 1 else result = 0 }
/** Returns `a > b`. */
bindingset[a, b]
int compareGT(int a, int b) {
if a > b then
result = 1
else
result = 0
}
int compareGT(int a, int b) { if a > b then result = 1 else result = 0 }
/** Returns `a <= b`. */
bindingset[a, b]
int compareLE(int a, int b) {
if a <= b then
result = 1
else
result = 0
}
int compareLE(int a, int b) { if a <= b then result = 1 else result = 0 }
/** Returns `a >= b`. */
bindingset[a, b]
int compareGE(int a, int b) {
if a >= b then
result = 1
else
result = 0
}
int compareGE(int a, int b) { if a >= b then result = 1 else result = 0 }
/**
* Returns `-a`. If the negation would overflow, there is no result.

View File

@@ -8,19 +8,13 @@ abstract class Overlap extends TOverlap {
}
class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap {
override final string toString() {
result = "MayPartiallyOverlap"
}
final override string toString() { result = "MayPartiallyOverlap" }
}
class MustTotallyOverlap extends Overlap, TMustTotallyOverlap {
override final string toString() {
result = "MustTotallyOverlap"
}
final override string toString() { result = "MustTotallyOverlap" }
}
class MustExactlyOverlap extends Overlap, TMustExactlyOverlap {
override final string toString() {
result = "MustExactlyOverlap"
}
final override string toString() { result = "MustExactlyOverlap" }
}

View File

@@ -12,4 +12,3 @@ newtype TIRVariable =
TIRTempVariable(Callable callable, Language::AST ast, TempVariableTag tag, Type type) {
Construction::hasTempVariable(callable, ast, tag, type)
}

View File

@@ -8,8 +8,11 @@ newtype TTempVariableTag =
LambdaTempVar()
string getTempVariableTagId(TTempVariableTag tag) {
tag = ConditionValueTempVar() and result = "CondVal" or
tag = ReturnValueTempVar() and result = "Ret" or
tag = ThrowTempVar() and result = "Throw" or
tag = ConditionValueTempVar() and result = "CondVal"
or
tag = ReturnValueTempVar() and result = "Ret"
or
tag = ThrowTempVar() and result = "Throw"
or
tag = LambdaTempVar() and result = "Lambda"
}