This commit is contained in:
Tom Hvitved 2019-08-30 09:54:05 +02:00
Родитель 9f59e385d1
Коммит 75eb7f92a2
34 изменённых файлов: 2113 добавлений и 4010 удалений

Просмотреть файл

@ -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) }

Просмотреть файл

@ -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" }
}

Просмотреть файл

@ -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" }
}
}

Просмотреть файл

@ -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) }
}

Просмотреть файл

@ -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() }
}

Просмотреть файл

@ -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) }

Просмотреть файл

@ -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 }
}

Просмотреть файл

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

Просмотреть файл

@ -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" }
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 }
}

Просмотреть файл

@ -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()
)
)
}

Просмотреть файл

@ -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) }

Просмотреть файл

@ -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)
}

Просмотреть файл

@ -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() }
}

Просмотреть файл

@ -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) }

Просмотреть файл

@ -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 }
}

Просмотреть файл

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

Просмотреть файл

@ -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" }
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 }
}

Просмотреть файл

@ -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()
)
)
}

Просмотреть файл

@ -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() }
}

Просмотреть файл

@ -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) }

Просмотреть файл

@ -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 }
}

Просмотреть файл

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

Просмотреть файл

@ -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" }
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 }
}

Просмотреть файл

@ -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()
)
)
}

Просмотреть файл

@ -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 }

Просмотреть файл

@ -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
}
/**

Просмотреть файл

@ -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.

Просмотреть файл

@ -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" }
}