C#/C++: Share IR implementation

This commit is contained in:
Dave Bartolomeo
2019-07-22 12:37:21 -07:00
committed by AndreiDiaconu1
parent 50ba4d1fda
commit 609ca034c0
51 changed files with 830 additions and 469 deletions

View File

@@ -39,42 +39,82 @@
"IR Instruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll"
],
"IR IRBlock": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRBlock.qll"
],
"IR IRVariable": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll"
],
"IR IRFunction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRFunction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRFunction.qll"
],
"IR Operand": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll"
],
"IR IR": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IR.qll"
],
"IR IRSanity": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll"
],
"IR PrintIR": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll"
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll"
],
"IR IntegerConstant": [
"cpp/ql/src/semmle/code/cpp/ir/internal/IntegerConstant.qll",
"csharp/ql/src/semmle/code/csharp/ir/internal/IntegerConstant.qll"
],
"IR IntegerInteval": [
"cpp/ql/src/semmle/code/cpp/ir/internal/IntegerInterval.qll",
"csharp/ql/src/semmle/code/csharp/ir/internal/IntegerInterval.qll"
],
"IR IntegerPartial": [
"cpp/ql/src/semmle/code/cpp/ir/internal/IntegerPartial.qll",
"csharp/ql/src/semmle/code/csharp/ir/internal/IntegerPartial.qll"
],
"IR Overlap": [
"cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll",
"csharp/ql/src/semmle/code/csharp/ir/internal/Overlap.qll"
],
"IR EdgeKind": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/EdgeKind.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/EdgeKind.qll"
],
"IR MemoryAccessKind": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/MemoryAccessKind.qll"
],
"IR TempVariableTag": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/TempVariableTag.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/TempVariableTag.qll"
],
"IR Opcode": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll"
],
"C++ IR InstructionImports": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll",
@@ -148,5 +188,23 @@
"C++ IR PrintDominance": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll"
],
"C# IR InstructionImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionImports.qll"
],
"C# IR IRImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRImports.qll"
],
"C# IR IRBlockImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRBlockImports.qll"
],
"C# IR IRVariableImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRVariableImports.qll"
],
"C# IR OperandImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/OperandImports.qll"
],
"C# IR PrintIRImports": [
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/PrintIRImports.qll"
]
}

View File

@@ -42,6 +42,7 @@ private newtype TOpcode =
TDynamicCastToVoid() or
TVariableAddress() or
TFieldAddress() or
TIndexedElementAddress() or
TFunctionAddress() or
TConstant() or
TStringConstant() or
@@ -190,6 +191,7 @@ module Opcode {
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 IndexedElementAddress extends BinaryOpcode, TIndexedElementAddress { override final string toString() { result = "IndexedElementAddress" } }
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" } }

View File

@@ -1,4 +1,5 @@
private import semmle.code.cpp.ir.internal.TempVariableTag
private import internal.TempVariableTagInternal
private import Imports::TempVariableTag
class TempVariableTag extends TTempVariableTag {
string toString() {

View File

@@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction {
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
result = Language::getTypeSize(getResultType())
)
}

View File

@@ -186,7 +186,7 @@ class Operand extends TOperand {
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getType().getSize()
result = Language::getTypeSize(getType())
}
}
@@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {

View File

@@ -0,0 +1,6 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
private import semmle.code.cpp.ir.internal.TempVariableTag as TempVariableTag_
module Imports {
module TempVariableTag = TempVariableTag_;
}

View File

@@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction {
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
result = Language::getTypeSize(getResultType())
)
}

View File

@@ -186,7 +186,7 @@ class Operand extends TOperand {
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getType().getSize()
result = Language::getTypeSize(getType())
}
}
@@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {

View File

@@ -512,7 +512,7 @@ class Instruction extends Construction::TInstruction {
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
result = Language::getTypeSize(getResultType())
)
}

View File

@@ -186,7 +186,7 @@ class Operand extends TOperand {
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getType().getSize()
result = Language::getTypeSize(getType())
}
}
@@ -450,7 +450,7 @@ class SideEffectOperand extends TypedOperand {
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {

View File

@@ -52,6 +52,10 @@ predicate hasAsmOperandIndex(int operandIndex) {
)
}
int getTypeSize(Type type) {
result = type.getSize()
}
int getPointerSize() {
exists(Cpp::NullPointerType nullptr |
result = nullptr.getSize()

View File

@@ -422,6 +422,9 @@ class ValueType extends ValueOrRefType, @value_type {
* (`FloatingPointType`), or a decimal type (`DecimalType`).
*/
class SimpleType extends ValueType, @simple_type {
/** Gets the size of this type, in bytes. */
int getSize() { none() }
/** Gets the minimum integral value of this type, if any. */
int minValue() { none() }
@@ -436,6 +439,8 @@ class SimpleType extends ValueType, @simple_type {
*/
class BoolType extends SimpleType, @bool_type {
override string toStringWithTypes() { result = "bool" }
override int getSize() { result = 1 }
}
/**
@@ -444,6 +449,8 @@ class BoolType extends SimpleType, @bool_type {
class CharType extends SimpleType, @char_type {
override string toStringWithTypes() { result = "char" }
override int getSize() { result = 2 }
override int minValue() { result = 0 }
override int maxValue() { result = 65535 }
@@ -481,6 +488,8 @@ class SignedIntegralType extends IntegralType, @signed_integral_type { }
class SByteType extends SignedIntegralType, @sbyte_type {
override string toStringWithTypes() { result = "sbyte" }
override int getSize() { result = 1 }
override int minValue() { result = -128 }
override int maxValue() { result = 127 }
@@ -492,6 +501,8 @@ class SByteType extends SignedIntegralType, @sbyte_type {
class ShortType extends SignedIntegralType, @short_type {
override string toStringWithTypes() { result = "short" }
override int getSize() { result = 2 }
override int minValue() { result = -32768 }
override int maxValue() { result = 32767 }
@@ -503,6 +514,8 @@ class ShortType extends SignedIntegralType, @short_type {
class IntType extends SignedIntegralType, @int_type {
override string toStringWithTypes() { result = "int" }
override int getSize() { result = 4 }
override int minValue() { result = -2147483647 - 1 }
override int maxValue() { result = 2147483647 }
@@ -513,6 +526,8 @@ class IntType extends SignedIntegralType, @int_type {
*/
class LongType extends SignedIntegralType, @long_type {
override string toStringWithTypes() { result = "long" }
override int getSize() { result = 8 }
}
/**
@@ -521,6 +536,8 @@ class LongType extends SignedIntegralType, @long_type {
class ByteType extends UnsignedIntegralType, @byte_type {
override string toStringWithTypes() { result = "byte" }
override int getSize() { result = 1 }
override int maxValue() { result = 255 }
}
@@ -530,6 +547,8 @@ class ByteType extends UnsignedIntegralType, @byte_type {
class UShortType extends UnsignedIntegralType, @ushort_type {
override string toStringWithTypes() { result = "ushort" }
override int getSize() { result = 2 }
override int maxValue() { result = 65535 }
}
@@ -538,6 +557,8 @@ class UShortType extends UnsignedIntegralType, @ushort_type {
*/
class UIntType extends UnsignedIntegralType, @uint_type {
override string toStringWithTypes() { result = "uint" }
override int getSize() { result = 4 }
}
/**
@@ -545,6 +566,8 @@ class UIntType extends UnsignedIntegralType, @uint_type {
*/
class ULongType extends UnsignedIntegralType, @ulong_type {
override string toStringWithTypes() { result = "ulong" }
override int getSize() { result = 8 }
}
/**
@@ -559,6 +582,8 @@ class FloatingPointType extends SimpleType, @floating_point_type { }
*/
class FloatType extends FloatingPointType, @float_type {
override string toStringWithTypes() { result = "float" }
override int getSize() { result = 4 }
}
/**
@@ -566,6 +591,8 @@ class FloatType extends FloatingPointType, @float_type {
*/
class DoubleType extends FloatingPointType, @double_type {
override string toStringWithTypes() { result = "double" }
override int getSize() { result = 8 }
}
/**
@@ -573,6 +600,8 @@ class DoubleType extends FloatingPointType, @double_type {
*/
class DecimalType extends SimpleType, @decimal_type {
override string toStringWithTypes() { result = "decimal" }
override int getSize() { result = 16 }
}
/**

View File

@@ -1,19 +1,15 @@
// TODO: Fix the switch
import csharp
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()
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)
}
// TCaseEdge(Expr expr, string condition) { // Case label of switch
// exists(CaseStmt caseStmt |
// hasCaseEdge(caseStmt, minValue, maxValue)
// )
// }
/**
* Represents the kind of an edge in the IR control flow graph. Each
* `Instruction` or `IRBlock` has at most one successor of any single
@@ -28,99 +24,99 @@ abstract class EdgeKind extends TEdgeKind {
* or `IRBlock`.
*/
class GotoEdge extends EdgeKind, TGotoEdge {
final override string toString() { result = "Goto" }
override final 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 {
final override string toString() { result = "True" }
override final 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 {
final override string toString() { result = "False" }
override final 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 {
final override string toString() { result = "Exception" }
override final 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 {
final override string toString() { result = "Default" }
override final string toString() {
result = "Default"
}
}
DefaultEdge defaultEdge() { result = TDefaultEdge() }
DefaultEdge defaultEdge() {
result = TDefaultEdge()
}
///**
// * A "case" edge, representing the successor of a `Switch` instruction when the
// * the condition value matches a correponding `case` label.
// */
/**
* A "case" edge, representing the successor of a `Switch` instruction when the
* the condition value matches a correponding `case` label.
*/
class CaseEdge extends EdgeKind, TCaseEdge {
final override string toString() { result = "CASE" }
string minValue;
string maxValue;
CaseEdge() {
this = TCaseEdge(minValue, maxValue)
}
override final string toString() {
if minValue = maxValue then
result = "Case[" + minValue + "]"
else
result = "Case[" + minValue + ".." + maxValue + "]"
}
string getMinValue() {
result = minValue
}
string getMaxValue() {
result = maxValue
}
}
CaseEdge caseEdge(string minValue, string maxValue) {
result = TCaseEdge(minValue, maxValue)
}
//class CaseEdge extends EdgeKind, TCaseEdge {
// string minValue;
// string maxValue;
//
// CaseEdge() {
// this = TCaseEdge(minValue, maxValue)
// }
//
// override final string toString() {
// if minValue = maxValue then
// result = "Case[" + minValue + "]"
// else
// result = "Case[" + minValue + ".." + maxValue + "]"
// }
//
// string getMinValue() {
// result = minValue
// }
//
// string getMaxValue() {
// result = maxValue
// }
//}
//
//CaseEdge caseEdge(string minValue, string maxValue) {
// result = TCaseEdge(minValue, maxValue)
//}
//
//private predicate hasCaseEdge(CaseStmt caseStmt, string minValue,
// string maxValue) {
// minValue = caseStmt.getExpr().stripCasts().getValue() and
// if exists(caseStmt.getEndExpr()) then
// maxValue = caseStmt.getEndExpr().getFullyConverted().getValue()
// else
// maxValue = minValue
//}
//
//EdgeKind getCaseEdge(SwitchStmt switchStmt) {
// exists(CaseEdge edge |
// result = edge and
// hasCaseEdge(switchStmt, edge.getMinValue(), edge.getMaxValue())
// ) or
// (switchStmt instanceof DefaultCase and result instanceof DefaultEdge)
//}

View File

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

View File

@@ -1,5 +1,3 @@
import csharp
private newtype TMemoryAccessKind =
TIndirectMemoryAccess() or
TIndirectMayMemoryAccess() or

View File

@@ -1,6 +1,7 @@
private newtype TOpcode =
TNoOp() or
TUninitialized() or
TError() or
TInitializeParameter() or
TInitializeThis() or
TEnterFunction() or
@@ -148,6 +149,7 @@ 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" } }

View File

@@ -1,5 +1,5 @@
import csharp
private import semmle.code.csharp.ir.internal.TempVariableTag
private import internal.TempVariableTagInternal
private import Imports::TempVariableTag
class TempVariableTag extends TTempVariableTag {
string toString() {

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language

View File

@@ -1,12 +1,4 @@
import csharp
private int getMaxCallArgIndex() {
result = max(int argIndex |
exists(MethodCall call |
exists(call.getArgument(argIndex))
)
)
}
private import OperandTagInternal
private newtype TOperandTag =
TAddressOperand() or
@@ -22,10 +14,13 @@ private newtype TOperandTag =
TCallTargetOperand() or
TThisArgumentOperand() or
TPositionalArgumentOperand(int argIndex) {
argIndex in [0..getMaxCallArgIndex()]
Language::hasPositionalArgIndex(argIndex)
} or
TChiTotalOperand() or
TChiPartialOperand()
TChiPartialOperand() or
TAsmOperand(int index) {
Language::hasAsmOperandIndex(index)
}
/**
* Identifies the kind of operand on an instruction. Each `Instruction` has at
@@ -359,3 +354,27 @@ class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
ChiPartialOperandTag chiPartialOperand() {
result = TChiPartialOperand()
}
class AsmOperandTag extends RegisterOperandTag, TAsmOperand {
int index;
AsmOperandTag() {
this = TAsmOperand(index)
}
override final string toString() {
result = "AsmOperand(" + index + ")"
}
override final int getSortOrder() {
result = 15 + index
}
override final string getLabel() {
result = index.toString() + ":"
}
}
AsmOperandTag asmOperand(int index) {
result = TAsmOperand(index)
}

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language

View File

@@ -0,0 +1,12 @@
private import TIRVariableInternal
private import Imports::TempVariableTag
newtype TIRVariable =
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) {
Construction::hasTempVariable(func, ast, tag, type)
}

View File

@@ -0,0 +1,7 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
import semmle.code.csharp.ir.implementation.raw.internal.IRConstruction as Construction
private import semmle.code.csharp.ir.implementation.TempVariableTag as TempVariableTag_
module Imports {
module TempVariableTag = TempVariableTag_;
}

View File

@@ -0,0 +1,6 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
private import semmle.code.csharp.ir.internal.TempVariableTag as TempVariableTag_
module Imports {
module TempVariableTag = TempVariableTag_;
}

View File

@@ -3,8 +3,9 @@ import Instruction
import IRBlock
import IRVariable
import Operand
import semmle.code.csharp.ir.implementation.EdgeKind
import semmle.code.csharp.ir.implementation.MemoryAccessKind
private import internal.IRImports as Imports
import Imports::EdgeKind
import Imports::MemoryAccessKind
private newtype TIRPropertyProvider = MkIRPropertyProvider()

View File

@@ -1,6 +1,7 @@
private import internal.IRInternal
import Instruction
import semmle.code.csharp.ir.implementation.EdgeKind
private import internal.IRBlockImports as Imports
import Imports::EdgeKind
private import Cached
/**
@@ -19,7 +20,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).toString()
}
final Location getLocation() {
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
@@ -67,7 +68,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).getEnclosingIRFunction()
}
final Callable getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -1,38 +1,37 @@
private import internal.IRInternal
import Instruction
import csharp
private newtype TIRFunction =
MkIRFunction(Callable callable) {
Construction::functionHasIR(callable)
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
/**
* Represents the IR for a function.
*/
class IRFunction extends TIRFunction {
Callable callable;
Language::Function func;
IRFunction() {
this = MkIRFunction(callable)
this = MkIRFunction(func)
}
final string toString() {
result = "IR: " + callable.toString()
result = "IR: " + func.toString()
}
/**
* Gets the function whose IR is represented.
*/
final Callable getFunction() {
result = callable
final Language::Function getFunction() {
result = func
}
/**
* Gets the location of the function.
*/
final Location getLocation() {
result = callable.getLocation()
final Language::Location getLocation() {
result = func.getLocation()
}
/**

View File

@@ -1,15 +1,14 @@
private import internal.IRInternal
import IRFunction
import csharp
import semmle.code.csharp.ir.implementation.TempVariableTag
private import semmle.code.csharp.ir.internal.IRUtilities
private import semmle.code.csharp.ir.internal.TempVariableTag
private import semmle.code.csharp.ir.internal.TIRVariable
private import semmle.code.csharp.ir.Util
private import internal.IRVariableImports as Imports
import Imports::TempVariableTag
private import Imports::IRUtilities
private import Imports::TTempVariableTag
private import Imports::TIRVariable
IRUserVariable getIRUserVariable(Callable callable, Variable var) {
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
result.getVariable() = var and
result.getEnclosingFunction() = callable
result.getEnclosingFunction() = func
}
/**
@@ -18,20 +17,20 @@ IRUserVariable getIRUserVariable(Callable callable, Variable var) {
* generated by the AST-to-IR translation (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
Callable callable;
Language::Function func;
abstract string toString();
/**
* Gets the type of the variable.
*/
abstract Type getType();
abstract Language::Type getType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Locatable getAST();
abstract Language::AST getAST();
/**
* Gets an identifier string for the variable. This identifier is unique
@@ -42,7 +41,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the source location of this variable.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
@@ -50,43 +49,48 @@ abstract class IRVariable extends TIRVariable {
* Gets the IR for the function that references this variable.
*/
final IRFunction getEnclosingIRFunction() {
result.getFunction() = callable
result.getFunction() = func
}
/**
* Gets the function that references this variable.
*/
final Callable getEnclosingFunction() {
result = callable
final Language::Function getEnclosingFunction() {
result = func
}
}
/**
* Represents a user-declared variable referenced by the IR for a function.
*/
abstract class IRUserVariable extends IRVariable {
Variable var;
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
override final string toString() {
result = var.toString()
result = getVariable().toString()
}
override final Type getType() {
result = getVariableType(var)
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = var
}
override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString()
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
/**
* Gets the original user-declared variable.
*/
final Variable getVariable() {
Language::Variable getVariable() {
result = var
}
}
@@ -99,45 +103,49 @@ abstract class IRUserVariable extends IRVariable {
abstract class IRAutomaticVariable extends IRVariable {
}
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable {
LocalScopeVariable localVar;
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, callable) and
var = localVar
Language::isVariableAutomatic(var)
}
final LocalScopeVariable getLocalVariable() {
result = localVar
final override Language::AutomaticVariable getVariable() {
result = var
}
}
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
this = TIRStaticUserVariable(var, callable)
not Language::isVariableAutomatic(var)
}
final override Language::StaticVariable getVariable() {
result = var
}
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getAST() = ast and
result.getTag() = tag
}
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast;
Language::AST ast;
TempVariableTag tag;
Type type;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(callable, ast, tag, type)
this = TIRTempVariable(func, ast, tag, type)
}
override final Type getType() {
override final Language::Type getType() {
result = type
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = ast
}

View File

@@ -3,13 +3,11 @@ import IRFunction
import IRBlock
import IRVariable
import Operand
import csharp
import semmle.code.csharp.ir.implementation.EdgeKind
import semmle.code.csharp.ir.implementation.MemoryAccessKind
import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.Util
private import internal.InstructionImports as Imports
import Imports::EdgeKind
import Imports::MemoryAccessKind
import Imports::Opcode
private import Imports::OperandTag
module InstructionSanity {
/**
@@ -51,7 +49,6 @@ module InstructionSanity {
* Holds if instruction `instr` is missing an expected operand with tag `tag`.
*/
query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) {
instr.getAST().fromSource() and
exists(OperandTag tag |
expectsOperand(instr, tag) and
not exists(NonPhiOperand operand |
@@ -61,7 +58,7 @@ module InstructionSanity {
message = "Instruction '" + instr.getOpcode().toString() + "' is missing an expected operand with tag '" +
tag.toString() + "' in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = func.getFunction().getName()
funcText = Language::getIdentityString(func.getFunction())
)
}
@@ -69,20 +66,19 @@ module InstructionSanity {
* Holds if instruction `instr` has an unexpected operand with tag `tag`.
*/
query predicate unexpectedOperand(Instruction instr, OperandTag tag) {
instr.getAST().fromSource() and
exists(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag) and
not expectsOperand(instr, tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag)
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
}
/**
* Holds if instruction `instr` has multiple operands with tag `tag`.
*/
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
instr.getAST().fromSource() and
strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
@@ -95,7 +91,6 @@ module InstructionSanity {
* the predecessor block `pred`.
*/
query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) {
instr.getAST().fromSource() and pred.getEnclosingFunction().fromSource() and
pred = instr.getBlock().getAPredecessor() and
not exists(PhiInputOperand operand |
operand = instr.getAnOperand() and
@@ -104,10 +99,10 @@ module InstructionSanity {
}
query predicate missingOperandType(Operand operand, string message) {
exists(Callable callable |
exists(Language::Function func |
not exists(operand.getType()) and
callable = operand.getUseInstruction().getEnclosingFunction() and
message = "Operand missing type in function '" + callable.getName() + "'."
func = operand.getUse().getEnclosingFunction() and
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
)
}
@@ -115,7 +110,6 @@ module InstructionSanity {
* Holds if an instruction, other than `ExitFunction`, has no successors.
*/
query predicate instructionWithoutSuccessor(Instruction instr) {
instr.getAST().fromSource() and
not exists(instr.getASuccessor()) and
not instr instanceof ExitFunctionInstruction and
// Phi instructions aren't linked into the instruction-level flow graph.
@@ -130,7 +124,6 @@ module InstructionSanity {
query predicate ambiguousSuccessors(
Instruction source, EdgeKind kind, int n, Instruction target
) {
source.getAST().fromSource() and target.getAST().fromSource() and
n = strictcount(Instruction t | source.getSuccessor(kind) = t) and
n > 1 and
source.getSuccessor(kind) = target
@@ -140,15 +133,13 @@ module InstructionSanity {
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
* contains no element that can cause loops.
*/
query predicate unexplainedLoop(Callable f, Instruction instr) {
instr.getAST().fromSource() and f.fromSource() and
query predicate unexplainedLoop(Language::Function f, Instruction instr) {
exists(IRBlock block |
instr.getBlock() = block and
block.getEnclosingFunction() = f and
block.getASuccessor+() = block
) and
not exists(LoopStmt l | l.getEnclosingCallable() = f) and
not exists(GotoStmt s | s.getEnclosingCallable() = f)
not Language::hasPotentialLoop(f)
}
/**
@@ -156,7 +147,6 @@ module InstructionSanity {
* predecessors.
*/
query predicate unnecessaryPhiInstruction(PhiInstruction instr) {
instr.getAST().fromSource() and
count(instr.getBlock().getAPredecessor()) < 2
}
@@ -165,9 +155,8 @@ module InstructionSanity {
* a different function.
*/
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
instr.getAST().fromSource() and defInstr.getAST().fromSource() and
operand.getUseInstruction() = instr and
operand.getDefinitionInstruction() = defInstr and
operand.getUse() = instr and
operand.getAnyDef() = defInstr and
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
}
@@ -175,13 +164,11 @@ module InstructionSanity {
* Holds if instruction `instr` is not in exactly one block.
*/
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
instr.getAST().fromSource() and
blockCount = count(instr.getBlock()) and
blockCount != 1
}
private predicate forwardEdge(IRBlock b1, IRBlock b2) {
b1.getEnclosingFunction().fromSource() and b2.getEnclosingFunction().fromSource() and
b1.getASuccessor() = b2 and
not b1.getBackEdgeSuccessor(_) = b2
}
@@ -192,7 +179,6 @@ module InstructionSanity {
* This check ensures we don't have too _few_ back edges.
*/
query predicate containsLoopOfForwardEdges(IRFunction f) {
f.getFunction().fromSource() and
exists(IRBlock block |
forwardEdge+(block, block) and
block.getEnclosingIRFunction() = f
@@ -208,12 +194,11 @@ module InstructionSanity {
* This check ensures we don't have too _many_ back edges.
*/
query predicate lostReachability(IRBlock block) {
block.getEnclosingFunction().fromSource() and
exists(IRFunction f, IRBlock entry |
entry = f.getEntryBlock() and
entry.getASuccessor+() = block and
not forwardEdge+(entry, block) and
not exists(GotoStmt s | s.getEnclosingCallable() = f.getFunction())
not Language::hasGoto(f.getFunction())
)
}
@@ -221,8 +206,7 @@ module InstructionSanity {
* Holds if the number of back edges differs between the `Instruction` graph
* and the `IRBlock` graph.
*/
query predicate backEdgeCountMismatch(Callable f, int fromInstr, int fromBlock) {
f.fromSource() and
query predicate backEdgeCountMismatch(Language::Function f, int fromInstr, int fromBlock) {
fromInstr = count(Instruction i1, Instruction i2 |
i1.getEnclosingFunction() = f and i1.getBackEdgeSuccessor(_) = i2
) and
@@ -279,7 +263,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof VoidType then
if getResultType() instanceof Language::VoidType then
result = "v"
else if hasMemoryResult() then
if isResultModeled() then
@@ -316,20 +300,19 @@ class Instruction extends Construction::TInstruction {
bindingset[type]
private string getValueCategoryString(string type) {
if isLValue() then
result = "lval<" + type + ">"
if isGLValue() then
result = "glval<" + type + ">"
else
result = type
}
// TODO: Memory model in C#?
string getResultTypeString() {
exists(string valcat |
valcat = getValueCategoryString(getResultType().toString()) and
if (getResultType() instanceof UnknownType and
not isLValue())/* and
exists(getResultSize()))*/ then (
result = valcat + "[" + /*getResultSize().toString()*/8.toString() + "]"
if (getResultType() instanceof Language::UnknownType and
not isGLValue() and
exists(getResultSize())) then (
result = valcat + "[" + getResultSize().toString() + "]"
)
else
result = valcat
@@ -393,7 +376,7 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the function that contains this instruction.
*/
final Callable getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getEnclosingIRFunction().getFunction()
}
@@ -407,28 +390,28 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the AST that caused this instruction to be generated.
*/
final Locatable getAST() {
final Language::AST getAST() {
result = Construction::getInstructionAST(this)
}
/**
* Gets the location of the source code for this instruction.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getConvertedResultExpression() {
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
@@ -439,7 +422,7 @@ class Instruction extends Construction::TInstruction {
* If `isGLValue()` holds, then the result type of this instruction should be
* thought of as "pointer to `getResultType()`".
*/
final Type getResultType() {
final Language::Type getResultType() {
Construction::instructionHasType(this, result, _)
}
@@ -461,31 +444,28 @@ class Instruction extends Construction::TInstruction {
* result of the `Load` instruction is a prvalue of type `int`, representing
* the integer value loaded from variable `x`.
*/
final predicate isLValue() {
final predicate isGLValue() {
Construction::instructionHasType(this, _, true)
}
// TODO: Memory model in C#
// /**
// * Gets the size of the result produced by this instruction, in bytes. If the
// * result does not have a known constant size, this predicate does not hold.
// *
// * If `this.isGLValue()` holds for this instruction, the value of
// * `getResultSize()` will always be the size of a pointer.
// */
// final int getResultSize() {
// if isGLValue() then (
// // a glvalue is always pointer-sized.
// exists(NullPointerType nullptr |
// result = nullptr.getSize()
// )
// )
// else if getResultType() instanceof UnknownType then
// result = Construction::getInstructionResultSize(this)
// else (
// result = getResultType().getSize()
// )
// }
/**
* Gets the size of the result produced by this instruction, in bytes. If the
* result does not have a known constant size, this predicate does not hold.
*
* If `this.isGLValue()` holds for this instruction, the value of
* `getResultSize()` will always be the size of a pointer.
*/
final int getResultSize() {
if isGLValue() then (
// a glvalue is always pointer-sized.
result = Language::getPointerSize()
)
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = Language::getTypeSize(getResultType())
)
}
/**
* Gets the opcode that specifies the operation performed by this instruction.
@@ -495,17 +475,18 @@ class Instruction extends Construction::TInstruction {
}
/**
* Gets all direct uses of the result of this instruction.
* Gets all direct uses of the result of this instruction. The result can be
* an `Operand` for which `isDefinitionInexact` holds.
*/
final Operand getAUse() {
result.getDefinitionInstruction() = this
result.getAnyDef() = this
}
/**
* Gets all of this instruction's operands.
*/
final Operand getAnOperand() {
result.getUseInstruction() = this
result.getUse() = this
}
/**
@@ -524,13 +505,22 @@ class Instruction extends Construction::TInstruction {
}
/**
* Returns the operand that holds the memory address to which the instruction stores its
* Gets the operand that holds the memory address to which this instruction stores its
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
* is `r1`.
*/
final AddressOperand getResultAddressOperand() {
getResultMemoryAccess().usesAddressOperand() and
result.getUseInstruction() = this
result.getUse() = this
}
/**
* Gets the instruction that holds the exact memory address to which this instruction stores its
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
* is the instruction that defines `r1`.
*/
final Instruction getResultAddress() {
result = getResultAddressOperand().getDef()
}
/**
@@ -621,7 +611,7 @@ class VariableInstruction extends Instruction {
}
class FieldInstruction extends Instruction {
Field field;
Language::Field field;
FieldInstruction() {
field = Construction::getInstructionField(this)
@@ -631,13 +621,13 @@ class FieldInstruction extends Instruction {
result = field.toString()
}
final Field getField() {
final Language::Field getField() {
result = field
}
}
class FunctionInstruction extends Instruction {
Callable funcSymbol;
Language::Function funcSymbol;
FunctionInstruction() {
funcSymbol = Construction::getInstructionFunction(this)
@@ -647,7 +637,7 @@ class FunctionInstruction extends Instruction {
result = funcSymbol.toString()
}
final Callable getFunctionSymbol() {
final Language::Function getFunctionSymbol() {
result = funcSymbol
}
}
@@ -685,7 +675,7 @@ class InitializeParameterInstruction extends VariableInstruction {
getOpcode() instanceof Opcode::InitializeParameter
}
final Parameter getParameter() {
final Language::Parameter getParameter() {
result = var.(IRUserVariable).getVariable()
}
@@ -713,7 +703,23 @@ class FieldAddressInstruction extends FieldInstruction {
}
final Instruction getObjectAddress() {
result = getObjectAddressOperand().getDefinitionInstruction()
result = getObjectAddressOperand().getDef()
}
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
* modeled in the SSA graph.
*
* This type of instruction appears when there is an `ErrorExpr` in the AST,
* meaning that the extractor could not understand the expression and therefore
* produced a partial AST. Queries that give alerts when some action is _not_
* taken may want to ignore any function that contains an `ErrorInstruction`.
*/
class ErrorInstruction extends Instruction {
ErrorInstruction() {
getOpcode() instanceof Opcode::Error
}
}
@@ -727,9 +733,9 @@ class UninitializedInstruction extends VariableInstruction {
}
/**
* Gets the `LocalVariable` that is uninitialized.
* Gets the variable that is uninitialized.
*/
final LocalVariable getLocalVariable() {
final Language::Variable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
@@ -762,7 +768,7 @@ class ReturnValueInstruction extends ReturnInstruction {
}
final Instruction getReturnValue() {
result = getReturnValueOperand().getDefinitionInstruction()
result = getReturnValueOperand().getDef()
}
}
@@ -776,7 +782,7 @@ class CopyInstruction extends Instruction {
}
final Instruction getSourceValue() {
result = getSourceValueOperand().getDefinitionInstruction()
result = getSourceValueOperand().getDef()
}
}
@@ -800,7 +806,7 @@ class LoadInstruction extends CopyInstruction {
}
final Instruction getSourceAddress() {
result = getSourceAddressOperand().getDefinitionInstruction()
result = getSourceAddressOperand().getDef()
}
override final LoadOperand getSourceValueOperand() {
@@ -822,7 +828,7 @@ class StoreInstruction extends CopyInstruction {
}
final Instruction getDestinationAddress() {
result = getDestinationAddressOperand().getDefinitionInstruction()
result = getDestinationAddressOperand().getDef()
}
override final StoreValueOperand getSourceValueOperand() {
@@ -840,7 +846,7 @@ class ConditionalBranchInstruction extends Instruction {
}
final Instruction getCondition() {
result = getConditionOperand().getDefinitionInstruction()
result = getConditionOperand().getDef()
}
final Instruction getTrueSuccessor() {
@@ -866,28 +872,28 @@ class ConstantInstruction extends ConstantValueInstruction {
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
getResultType() instanceof IntegralType
getResultType() instanceof Language::IntegralType
}
}
class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() {
getResultType() instanceof FloatingPointType
getResultType() instanceof Language::FloatingPointType
}
}
class StringConstantInstruction extends Instruction {
StringLiteral value;
Language::StringLiteral value;
StringConstantInstruction() {
value = Construction::getInstructionStringLiteral(this)
}
override final string getImmediateString() {
result = value.toString().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")
result = Language::getStringLiteralText(value)
}
final StringLiteral getValue() {
final Language::StringLiteral getValue() {
result = value
}
}
@@ -906,11 +912,11 @@ class BinaryInstruction extends Instruction {
}
final Instruction getLeft() {
result = getLeftOperand().getDefinitionInstruction()
result = getLeftOperand().getDef()
}
final Instruction getRight() {
result = getRightOperand().getDefinitionInstruction()
result = getRightOperand().getDef()
}
/**
@@ -1060,7 +1066,7 @@ class UnaryInstruction extends Instruction {
}
final Instruction getUnary() {
result = getUnaryOperand().getDefinitionInstruction()
result = getUnaryOperand().getDef()
}
}
@@ -1075,8 +1081,8 @@ class ConvertInstruction extends UnaryInstruction {
* related by inheritance.
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Class baseClass;
Class derivedClass;
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {
Construction::getInstructionInheritance(this, baseClass, derivedClass)
@@ -1086,29 +1092,28 @@ class InheritanceConversionInstruction extends UnaryInstruction {
result = derivedClass.toString() + " : " + baseClass.toString()
}
// TODO: WHAT IS THE EQUIV IN C#
// /**
// * Gets the `ClassDerivation` for the inheritance relationship between
// * the base and derived classes. This predicate does not hold if the
// * conversion is to an indirect virtual base class.
// */
// final ClassDerivation getDerivation() {
// result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass
// }
/**
* Gets the `ClassDerivation` for the inheritance relationship between
* the base and derived classes. This predicate does not hold if the
* conversion is to an indirect virtual base class.
*/
final Language::ClassDerivation getDerivation() {
result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass
}
/**
* Gets the base class of the conversion. This will be either a direct
* base class of the derived class, or a virtual base class of the
* derived class.
*/
final Class getBaseClass() {
final Language::Class getBaseClass() {
result = baseClass
}
/**
* Gets the derived class of the conversion.
*/
final Class getDerivedClass() {
final Language::Class getDerivedClass() {
result = derivedClass
}
}
@@ -1291,7 +1296,7 @@ class SwitchInstruction extends Instruction {
}
final Instruction getExpression() {
result = getExpressionOperand().getDefinitionInstruction()
result = getExpressionOperand().getDef()
}
final Instruction getACaseSuccessor() {
@@ -1326,7 +1331,7 @@ class CallInstruction extends Instruction {
* function pointer.
*/
final Instruction getCallTarget() {
result = getCallTargetOperand().getDefinitionInstruction()
result = getCallTargetOperand().getDef()
}
/**
@@ -1339,7 +1344,7 @@ class CallInstruction extends Instruction {
/**
* Gets the `Function` that the call targets, if this is statically known.
*/
final Callable getStaticCallTarget() {
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
}
@@ -1347,7 +1352,7 @@ class CallInstruction extends Instruction {
* Gets all of the arguments of the call, including the `this` pointer, if any.
*/
final Instruction getAnArgument() {
result = getAnArgumentOperand().getDefinitionInstruction()
result = getAnArgumentOperand().getDef()
}
/**
@@ -1361,7 +1366,7 @@ class CallInstruction extends Instruction {
* Gets the `this` pointer argument of the call, if any.
*/
final Instruction getThisArgument() {
result = getThisArgumentOperand().getDefinitionInstruction()
result = getThisArgumentOperand().getDef()
}
/**
@@ -1376,7 +1381,7 @@ class CallInstruction extends Instruction {
* Gets the argument at the specified index.
*/
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDefinitionInstruction()
result = getPositionalArgumentOperand(index).getDef()
}
}
@@ -1532,7 +1537,7 @@ class ThrowValueInstruction extends ThrowInstruction {
* Gets the address of the exception thrown by this instruction.
*/
final Instruction getExceptionAddress() {
result = getExceptionAddressOperand().getDefinitionInstruction()
result = getExceptionAddressOperand().getDef()
}
/**
@@ -1546,7 +1551,7 @@ class ThrowValueInstruction extends ThrowInstruction {
* Gets the exception thrown by this instruction.
*/
final Instruction getException() {
result = getExceptionOperand().getDefinitionInstruction()
result = getExceptionOperand().getDef()
}
}
@@ -1581,7 +1586,7 @@ class CatchInstruction extends Instruction {
* An instruction that catches an exception of a specific type.
*/
class CatchByTypeInstruction extends CatchInstruction {
Type exceptionType;
Language::Type exceptionType;
CatchByTypeInstruction() {
getOpcode() instanceof Opcode::CatchByType and
@@ -1595,7 +1600,7 @@ class CatchByTypeInstruction extends CatchInstruction {
/**
* Gets the type of exception to be caught.
*/
final Type getExceptionType() {
final Language::Type getExceptionType() {
result = exceptionType
}
}
@@ -1676,7 +1681,7 @@ class PhiInstruction extends Instruction {
*/
pragma[noinline]
final Instruction getAnInput() {
result = this.getAnInputOperand().getDefinitionInstruction()
result = this.getAnInputOperand().getDef()
}
}
@@ -1744,7 +1749,7 @@ class ChiInstruction extends Instruction {
* memory write.
*/
final Instruction getTotal() {
result = getTotalOperand().getDefinitionInstruction()
result = getTotalOperand().getDef()
}
/**
@@ -1758,7 +1763,7 @@ class ChiInstruction extends Instruction {
* Gets the operand that represents the new value written by the memory write.
*/
final Instruction getPartial() {
result = getPartialOperand().getDefinitionInstruction()
result = getPartialOperand().getDef()
}
}
@@ -1782,25 +1787,3 @@ class BuiltInInstruction extends Instruction {
getOpcode() instanceof BuiltInOpcode
}
}
class IndexedElementInstruction extends Instruction {
ArrayAccess arrAccess;
IndexedElementInstruction() {
arrAccess = Construction::getInstructionArrayAccess(this)
}
override final string getImmediateString() {
result = arrAccess.toString()
}
final ArrayAccess getArrayAccess() {
result = arrAccess
}
}
class IndexedElementAddressInstruction extends VariableInstruction {
IndexedElementAddressInstruction() {
getOpcode() instanceof Opcode::IndexedElementAddress
}
}

View File

@@ -1,22 +1,47 @@
private import internal.IRInternal
import Instruction
import IRBlock
import csharp
import semmle.code.csharp.ir.implementation.MemoryAccessKind
import semmle.code.csharp.ir.internal.Overlap
private import semmle.code.csharp.ir.internal.OperandTag
private import internal.OperandImports as Imports
import Imports::MemoryAccessKind
import Imports::Overlap
private import Imports::OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag)
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap)
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/** Gets a non-phi instruction that defines an operand of `instr`. */
private Instruction getNonPhiOperandDef(Instruction instr) {
result = Construction::getRegisterOperandDefinition(instr, _)
or
result = Construction::getMemoryOperandDefinition(instr, _, _)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
*
* If such cycles are present, either due to a programming error in the IR
* generation or due to a malformed database, it can cause infinite loops in
* analyses that assume a cycle-free graph of non-phi operands. Therefore it's
* better to remove these operands than to leave cycles in the operand graph.
*/
pragma[noopt]
private predicate isInCycle(Instruction instr) {
instr instanceof Instruction and
getNonPhiOperandDef+(instr) = instr
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/
@@ -25,26 +50,62 @@ class Operand extends TOperand {
result = "Operand"
}
final Location getLocation() {
result = getUseInstruction().getLocation()
final Language::Location getLocation() {
result = getUse().getLocation()
}
final IRFunction getEnclosingIRFunction() {
result = getUseInstruction().getEnclosingIRFunction()
result = getUse().getEnclosingIRFunction()
}
/**
* Gets the `Instruction` that consumes this operand.
*/
Instruction getUseInstruction() {
Instruction getUse() {
none()
}
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
* `getDef`, this also has a result when `isDefinitionInexact` holds, which
* means that the resulting instruction may only _partially_ or _potentially_
* be the value of this operand.
*/
Instruction getAnyDef() {
none()
}
/**
* Gets the `Instruction` whose result is the value of the operand. Unlike
* `getAnyDef`, this also has no result when `isDefinitionInexact` holds,
* which means that the resulting instruction must always be exactly the be
* the value of this operand.
*/
final Instruction getDef() {
result = this.getAnyDef() and
getDefinitionOverlap() instanceof MustExactlyOverlap
}
/**
* DEPRECATED: renamed to `getUse`.
*
* Gets the `Instruction` that consumes this operand.
*/
deprecated
final Instruction getUseInstruction() {
result = getUse()
}
/**
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
* predicate is `getAnyDef`, but most uses of this predicate should probably
* be replaced with `getDef`.
*
* Gets the `Instruction` whose result is the value of the operand.
*/
Instruction getDefinitionInstruction() {
none()
deprecated
final Instruction getDefinitionInstruction() {
result = getAnyDef()
}
/**
@@ -76,7 +137,7 @@ class Operand extends TOperand {
* For example: `this:r3_5`
*/
final string getDumpString() {
result = getDumpLabel() + getInexactSpecifier() + getDefinitionInstruction().getResultId()
result = getDumpLabel() + getInexactSpecifier() + getAnyDef().getResultId()
}
/**
@@ -105,8 +166,8 @@ 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.
*/
Type getType() {
result = getDefinitionInstruction().getResultType()
Language::Type getType() {
result = getAnyDef().getResultType()
}
/**
@@ -116,8 +177,8 @@ class Operand extends TOperand {
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isLValue() {
getDefinitionInstruction().isLValue()
predicate isGLValue() {
getAnyDef().isGLValue()
}
/**
@@ -125,7 +186,7 @@ class Operand extends TOperand {
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = 8 //getType().getSize() TODO: C# memory layout
result = Language::getTypeSize(getType())
}
}
@@ -138,7 +199,7 @@ class MemoryOperand extends Operand {
this = TPhiOperand(_, _, _, _)
}
override predicate isLValue() {
override predicate isGLValue() {
// A `MemoryOperand` can never be a glvalue
none()
}
@@ -157,7 +218,7 @@ class MemoryOperand extends Operand {
*/
final AddressOperand getAddressOperand() {
getMemoryAccess().usesAddressOperand() and
result.getUseInstruction() = getUseInstruction()
result.getUse() = getUse()
}
}
@@ -174,11 +235,11 @@ class NonPhiOperand extends Operand {
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
}
override final Instruction getUseInstruction() {
override final Instruction getUse() {
result = useInstr
}
override final Instruction getDefinitionInstruction() {
override final Instruction getAnyDef() {
result = defInstr
}
@@ -223,7 +284,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
override final Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -386,11 +447,10 @@ class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
// TODO: Memory layout in C#
result = 8 //getType().getSize()
result = Language::getTypeSize(getType())
}
override MemoryAccessKind getMemoryAccess() {
@@ -437,11 +497,11 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
result = "Phi"
}
override final PhiInstruction getUseInstruction() {
override final PhiInstruction getUse() {
result = useInstr
}
override final Instruction getDefinitionInstruction() {
override final Instruction getAnyDef() {
result = defInstr
}

View File

@@ -1,7 +1,7 @@
private import internal.IRInternal
private import IR
import csharp
import semmle.code.csharp.ir.IRConfiguration
//private import semmle.code.csharp.Print
private import internal.PrintIRImports as Imports
import Imports::IRConfiguration
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
@@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Callable func) {
predicate shouldPrintFunction(Language::Function func) {
any()
}
}
private predicate shouldPrintFunction(Callable func) {
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
@@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Callable func) {
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Callable func) {
override predicate shouldCreateIRForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
@@ -69,7 +69,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
/**
* Gets the location to be emitted for the node.
*/
abstract Location getLocation();
abstract Language::Location getLocation();
/**
* Gets the label to be emitted for the node.
@@ -126,17 +126,16 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
result = irFunc.toString()
}
override Location getLocation() {
override Language::Location getLocation() {
result = irFunc.getLocation()
}
override string getLabel() {
// TODO: C++ USED THE PRINT MODULE, NOT SURE TOsTRING DOES THE JOB
result = irFunc.getFunction().toString()
result = Language::getIdentityString(irFunc.getFunction())
}
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Location location |
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()
@@ -166,7 +165,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getLabel()
}
override Location getLocation() {
override Language::Location getLocation() {
result = block.getLocation()
}
@@ -214,7 +213,7 @@ class PrintableInstruction extends PrintableIRNode, TPrintableInstruction {
result = instr.toString()
}
override Location getLocation() {
override Language::Location getLocation() {
result = instr.getLocation()
}

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind

View File

@@ -1,6 +1,6 @@
import csharp
import semmle.code.csharp.ir.implementation.raw.IR
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedCondition
@@ -30,6 +30,10 @@ cached private module Cached {
element.hasInstruction(_, tag, _, _)
}
cached predicate hasUserVariable(Callable callable, Variable var, Type type) {
getTranslatedFunction(callable).hasUserVariable(var, type)
}
cached predicate hasTempVariable(Callable callable, Locatable ast, TempVariableTag tag,
Type type) {
exists(TranslatedElement element |

View File

@@ -0,0 +1,2 @@
import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind
import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind

View File

@@ -1 +1,2 @@
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
import IRConstruction as Construction

View File

@@ -0,0 +1,4 @@
import semmle.code.csharp.ir.implementation.TempVariableTag as TempVariableTag
import semmle.code.csharp.ir.internal.IRUtilities as IRUtilities
import semmle.code.csharp.ir.internal.TempVariableTag as TTempVariableTag
import semmle.code.csharp.ir.implementation.internal.TIRVariable as TIRVariable

View File

@@ -0,0 +1,4 @@
import semmle.code.csharp.ir.implementation.EdgeKind as EdgeKind
import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.csharp.ir.implementation.Opcode as Opcode
import semmle.code.csharp.ir.implementation.internal.OperandTag as OperandTag

View File

@@ -0,0 +1,3 @@
import semmle.code.csharp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.csharp.ir.internal.Overlap as Overlap
import semmle.code.csharp.ir.implementation.internal.OperandTag as OperandTag

View File

@@ -0,0 +1 @@
import semmle.code.csharp.ir.IRConfiguration as IRConfiguration

View File

@@ -1,6 +1,6 @@
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr

View File

@@ -1,6 +1,6 @@
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr

View File

@@ -1,7 +1,7 @@
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.IRUtilities
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr

View File

@@ -1,9 +1,8 @@
import csharp
import csharp
import semmle.code.csharp.ir.implementation.raw.IR
private import semmle.code.csharp.ir.IRConfiguration
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedCondition

View File

@@ -1,6 +1,6 @@
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedCondition

View File

@@ -2,7 +2,7 @@ import csharp
import semmle.code.csharp.ir.implementation.raw.IR
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.IRUtilities
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedElement
@@ -315,6 +315,25 @@ class TranslatedFunction extends TranslatedElement,
result = callable.getDeclaringType()
}
/**
* Holds if this function defines or accesses variable `var` with type `type`. This includes all
* parameters and local variables, plus any static fields that are directly accessed by the
* function.
*/
final predicate hasUserVariable(Variable var, Type type) {
(
(
var.(Member).isStatic() and
exists(VariableAccess access |
access.getTarget() = var and
access.getEnclosingCallable() = callable
)
) or
var.(LocalScopeVariable).getCallable() = callable
) and
type = getVariableType(var)
}
private final Type getReturnType() {
result = callable.getReturnType()
}

View File

@@ -1,6 +1,6 @@
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr

View File

@@ -1,6 +1,6 @@
import csharp
private import semmle.code.csharp.ir.internal.TempVariableTag
private import semmle.code.csharp.ir.internal.OperandTag
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedCondition
private import TranslatedDeclarationEntry

View File

@@ -0,0 +1,114 @@
private import csharp as Cpp
class Function = Cpp::Callable;
class Location = Cpp::Location;
class AST = Cpp::Element;
class Type = Cpp::Type;
//REVIEW: This might not exist in the database.
class UnknownType = Cpp::UnknownType;
class VoidType = Cpp::VoidType;
class IntegralType = Cpp::IntegralType;
class FloatingPointType = Cpp::FloatingPointType;
private newtype TClassDerivation =
// Note that this is the `Class` type exported from this module, not CSharp::Class.
MkClassDerivation(Class base, Class derived) {
derived.getABaseType() = base
}
class ClassDerivation extends MkClassDerivation {
Class baseClass;
Class derivedClass;
ClassDerivation() {
this = MkClassDerivation(baseClass, derivedClass)
}
string toString() {
result = "ClassDerivation"
}
final Class getBaseClass() {
result = baseClass
}
final Class getDerivedClass() {
result = derivedClass
}
final int getByteOffset() {
// Inheritance never requires adjusting the `this` pointer in C#.
result = 0
}
}
class StringLiteral = Cpp::StringLiteral;
class Variable = Cpp::Variable;
class AutomaticVariable = Cpp::LocalScopeVariable;
class StaticVariable = Cpp::Variable;
class Parameter = Cpp::Parameter;
class Field = Cpp::Field;
// TODO: Remove necessity for these.
class Expr = Cpp::Expr;
class Class = Cpp::RefType; // Used for inheritance conversions
string getIdentityString(Function func) {
// REVIEW: Is this enough to make it unique?
// result = func.getQualifiedName()
result = func.getName()
}
predicate hasCaseEdge(string minValue, string maxValue) {
// TODO: Need to handle `switch` statements that switch on an integer.
none()
}
predicate hasPositionalArgIndex(int argIndex) {
exists(Cpp::MethodCall call |
exists(call.getArgument(argIndex))
)
}
predicate hasAsmOperandIndex(int operandIndex) {
none()
}
int getTypeSize(Type type) {
// REVIEW: Is this complete?
result = type.(Cpp::SimpleType).getSize() or
result = getTypeSize(type.(Cpp::Enum).getUnderlyingType()) or
// TODO: Generate a reasonable size
type instanceof Cpp::Struct and result = 16 or
type instanceof Cpp::RefType and result = getPointerSize() or
type instanceof Cpp::PointerType and result = getPointerSize() or
result = getTypeSize(type.(Cpp::TupleType).getUnderlyingType()) or
// TODO: Add room for extra field
result = getTypeSize(type.(Cpp::NullableType).getUnderlyingType()) or
type instanceof Cpp::VoidType and result = 0
}
int getPointerSize() {
// TODO: Deal with sizes in general
result = 8
}
predicate isVariableAutomatic(Variable var) {
var instanceof Cpp::LocalScopeVariable
}
string getStringLiteralText(StringLiteral s) {
// REVIEW: Is this the right escaping?
result = s.toString()
}
predicate hasPotentialLoop(Function f) {
exists(Cpp::LoopStmt l | l.getEnclosingCallable() = f) or
exists(Cpp::GotoStmt s | s.getEnclosingCallable() = f)
}
predicate hasGoto(Function f) {
exists(Cpp::GotoStmt s | s.getEnclosingCallable() = f)
}

View File

@@ -1,5 +1,3 @@
import csharp
class IntValue = int;
/**

View File

@@ -1,5 +1,3 @@
import csharp
private newtype TOverlap =
TMayPartiallyOverlap() or
TMustTotallyOverlap() or

View File

@@ -1,135 +1,135 @@
array_acc.cs:
# 4| f
# 4| Block 0
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(lval<array_init_and_access>) = InitializeThis :
# 5| r0_4(lval<Int32[]>) = VariableAddress[arr] :
# 5| mu0_5(Int32[]) = Uninitialized[arr] : &:r0_4
# 5| r0_6(Int32) = Constant[0] :
# 5| r0_7(lval<Int32>) = IndexedElementAddress : r0_4, r0_6
# 5| r0_8(Int32) = Constant[101] :
# 5| mu0_9(Int32) = Store : &:r0_7, r0_8
# 5| r0_10(Int32) = Constant[1] :
# 5| r0_11(lval<Int32>) = IndexedElementAddress : r0_4, r0_10
# 5| r0_12(Int32) = Constant[102] :
# 5| mu0_13(Int32) = Store : &:r0_11, r0_12
# 6| r0_14(Int32) = Constant[5] :
# 6| r0_15(lval<Int32[]>) = VariableAddress[arr] :
# 6| r0_16(Int32) = Constant[1] :
# 6| r0_17(lval<Int32>) = IndexedElementAddress : r0_15, r0_16
# 6| mu0_18(Int32) = Store : &:r0_17, r0_14
# 4| v0_19(Void) = ReturnVoid :
# 4| v0_20(Void) = UnmodeledUse : mu*
# 4| v0_21(Void) = ExitFunction :
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(glval<array_init_and_access>) = InitializeThis :
# 5| r0_4(glval<Int32[]>) = VariableAddress[arr] :
# 5| mu0_5(Int32[]) = Uninitialized[arr] : &:r0_4
# 5| r0_6(Int32) = Constant[0] :
# 5| r0_7(glval<Int32>) = IndexedElementAddress : r0_4, r0_6
# 5| r0_8(Int32) = Constant[101] :
# 5| mu0_9(Int32) = Store : &:r0_7, r0_8
# 5| r0_10(Int32) = Constant[1] :
# 5| r0_11(glval<Int32>) = IndexedElementAddress : r0_4, r0_10
# 5| r0_12(Int32) = Constant[102] :
# 5| mu0_13(Int32) = Store : &:r0_11, r0_12
# 6| r0_14(Int32) = Constant[5] :
# 6| r0_15(glval<Int32[]>) = VariableAddress[arr] :
# 6| r0_16(Int32) = Constant[1] :
# 6| r0_17(glval<Int32>) = IndexedElementAddress : r0_15, r0_16
# 6| mu0_18(Int32) = Store : &:r0_17, r0_14
# 4| v0_19(Void) = ReturnVoid :
# 4| v0_20(Void) = UnmodeledUse : mu*
# 4| v0_21(Void) = ExitFunction :
func_with_param_call.cs:
# 4| f
# 4| Block 0
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(lval<test_call_with_param>) = InitializeThis :
# 4| r0_4(lval<Int32>) = VariableAddress[x] :
# 4| mu0_5(Int32) = InitializeParameter[x] : &:r0_4
# 4| r0_6(lval<Int32>) = VariableAddress[y] :
# 4| mu0_7(Int32) = InitializeParameter[y] : &:r0_6
# 5| r0_8(lval<Int32>) = VariableAddress[#return] :
# 5| r0_9(lval<Int32>) = VariableAddress[x] :
# 5| r0_10(Int32) = Load : &:r0_9, ~mu0_2
# 5| r0_11(lval<Int32>) = VariableAddress[y] :
# 5| r0_12(Int32) = Load : &:r0_11, ~mu0_2
# 5| r0_13(Int32) = Add : r0_10, r0_12
# 5| mu0_14(Int32) = Store : &:r0_8, r0_13
# 4| r0_15(lval<Int32>) = VariableAddress[#return] :
# 4| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2
# 4| v0_17(Void) = UnmodeledUse : mu*
# 4| v0_18(Void) = ExitFunction :
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(glval<test_call_with_param>) = InitializeThis :
# 4| r0_4(glval<Int32>) = VariableAddress[x] :
# 4| mu0_5(Int32) = InitializeParameter[x] : &:r0_4
# 4| r0_6(glval<Int32>) = VariableAddress[y] :
# 4| mu0_7(Int32) = InitializeParameter[y] : &:r0_6
# 5| r0_8(glval<Int32>) = VariableAddress[#return] :
# 5| r0_9(glval<Int32>) = VariableAddress[x] :
# 5| r0_10(Int32) = Load : &:r0_9, ~mu0_2
# 5| r0_11(glval<Int32>) = VariableAddress[y] :
# 5| r0_12(Int32) = Load : &:r0_11, ~mu0_2
# 5| r0_13(Int32) = Add : r0_10, r0_12
# 5| mu0_14(Int32) = Store : &:r0_8, r0_13
# 4| r0_15(glval<Int32>) = VariableAddress[#return] :
# 4| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2
# 4| v0_17(Void) = UnmodeledUse : mu*
# 4| v0_18(Void) = ExitFunction :
# 8| g
# 8| Block 0
# 8| v0_0(Void) = EnterFunction :
# 8| mu0_1(Object) = AliasedDefinition :
# 8| mu0_2(Object) = UnmodeledDefinition :
# 8| r0_3(lval<test_call_with_param>) = InitializeThis :
# 9| r0_4(lval<Int32>) = VariableAddress[#return] :
# 9| r0_5(lval<Int32>) = FunctionAddress[f] :
# 9| r0_6(Int32) = Constant[2] :
# 9| r0_7(Int32) = Constant[3] :
# 9| r0_8(Int32) = Call : func:r0_5, 0:r0_6, 1:r0_7
# 9| v0_9(Void) = ^CallSideEffect : ~mu0_2
# 9| mu0_10(Int32) = Store : &:r0_4, r0_8
# 8| r0_11(lval<Int32>) = VariableAddress[#return] :
# 8| v0_12(Void) = ReturnValue : &:r0_11, ~mu0_2
# 8| v0_13(Void) = UnmodeledUse : mu*
# 8| v0_14(Void) = ExitFunction :
# 8| v0_0(Void) = EnterFunction :
# 8| mu0_1(Object) = AliasedDefinition :
# 8| mu0_2(Object) = UnmodeledDefinition :
# 8| r0_3(glval<test_call_with_param>) = InitializeThis :
# 9| r0_4(glval<Int32>) = VariableAddress[#return] :
# 9| r0_5(glval<Int32>) = FunctionAddress[f] :
# 9| r0_6(Int32) = Constant[2] :
# 9| r0_7(Int32) = Constant[3] :
# 9| r0_8(Int32) = Call : func:r0_5, 0:r0_6, 1:r0_7
# 9| v0_9(Void) = ^CallSideEffect : ~mu0_2
# 9| mu0_10(Int32) = Store : &:r0_4, r0_8
# 8| r0_11(glval<Int32>) = VariableAddress[#return] :
# 8| v0_12(Void) = ReturnValue : &:r0_11, ~mu0_2
# 8| v0_13(Void) = UnmodeledUse : mu*
# 8| v0_14(Void) = ExitFunction :
simple_call.cs:
# 4| f
# 4| Block 0
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(lval<test_simple_call>) = InitializeThis :
# 5| r0_4(lval<Int32>) = VariableAddress[#return] :
# 5| r0_5(Int32) = Constant[0] :
# 5| mu0_6(Int32) = Store : &:r0_4, r0_5
# 4| r0_7(lval<Int32>) = VariableAddress[#return] :
# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
# 4| v0_9(Void) = UnmodeledUse : mu*
# 4| v0_10(Void) = ExitFunction :
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(glval<test_simple_call>) = InitializeThis :
# 5| r0_4(glval<Int32>) = VariableAddress[#return] :
# 5| r0_5(Int32) = Constant[0] :
# 5| mu0_6(Int32) = Store : &:r0_4, r0_5
# 4| r0_7(glval<Int32>) = VariableAddress[#return] :
# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
# 4| v0_9(Void) = UnmodeledUse : mu*
# 4| v0_10(Void) = ExitFunction :
# 8| g
# 8| Block 0
# 8| v0_0(Void) = EnterFunction :
# 8| mu0_1(Object) = AliasedDefinition :
# 8| mu0_2(Object) = UnmodeledDefinition :
# 8| r0_3(lval<test_simple_call>) = InitializeThis :
# 9| r0_4(lval<Int32>) = VariableAddress[#return] :
# 9| r0_5(lval<Int32>) = FunctionAddress[f] :
# 9| r0_6(Int32) = Call : func:r0_5
# 9| v0_7(Void) = ^CallSideEffect : ~mu0_2
# 9| mu0_8(Int32) = Store : &:r0_4, r0_6
# 8| r0_9(lval<Int32>) = VariableAddress[#return] :
# 8| v0_10(Void) = ReturnValue : &:r0_9, ~mu0_2
# 8| v0_11(Void) = UnmodeledUse : mu*
# 8| v0_12(Void) = ExitFunction :
# 8| v0_0(Void) = EnterFunction :
# 8| mu0_1(Object) = AliasedDefinition :
# 8| mu0_2(Object) = UnmodeledDefinition :
# 8| r0_3(glval<test_simple_call>) = InitializeThis :
# 9| r0_4(glval<Int32>) = VariableAddress[#return] :
# 9| r0_5(glval<Int32>) = FunctionAddress[f] :
# 9| r0_6(Int32) = Call : func:r0_5
# 9| v0_7(Void) = ^CallSideEffect : ~mu0_2
# 9| mu0_8(Int32) = Store : &:r0_4, r0_6
# 8| r0_9(glval<Int32>) = VariableAddress[#return] :
# 8| v0_10(Void) = ReturnValue : &:r0_9, ~mu0_2
# 8| v0_11(Void) = UnmodeledUse : mu*
# 8| v0_12(Void) = ExitFunction :
simple_function.cs:
# 4| f
# 4| Block 0
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(lval<test_simple_function>) = InitializeThis :
# 5| r0_4(lval<Int32>) = VariableAddress[#return] :
# 5| r0_5(Int32) = Constant[0] :
# 5| mu0_6(Int32) = Store : &:r0_4, r0_5
# 4| r0_7(lval<Int32>) = VariableAddress[#return] :
# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
# 4| v0_9(Void) = UnmodeledUse : mu*
# 4| v0_10(Void) = ExitFunction :
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(glval<test_simple_function>) = InitializeThis :
# 5| r0_4(glval<Int32>) = VariableAddress[#return] :
# 5| r0_5(Int32) = Constant[0] :
# 5| mu0_6(Int32) = Store : &:r0_4, r0_5
# 4| r0_7(glval<Int32>) = VariableAddress[#return] :
# 4| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
# 4| v0_9(Void) = UnmodeledUse : mu*
# 4| v0_10(Void) = ExitFunction :
variables.cs:
# 4| f
# 4| Block 0
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(lval<test_variables>) = InitializeThis :
# 5| r0_4(lval<Int32>) = VariableAddress[x] :
# 5| mu0_5(Int32) = Uninitialized[x] : &:r0_4
# 5| r0_6(lval<Int32>) = VariableAddress[y] :
# 5| r0_7(Int32) = Constant[5] :
# 5| mu0_8(Int32) = Store : &:r0_6, r0_7
# 6| r0_9(Int32) = Constant[4] :
# 6| r0_10(lval<Int32>) = VariableAddress[x] :
# 6| mu0_11(Int32) = Store : &:r0_10, r0_9
# 7| r0_12(lval<Int32>) = VariableAddress[y] :
# 7| r0_13(Int32) = Load : &:r0_12, ~mu0_2
# 7| r0_14(lval<Int32>) = VariableAddress[x] :
# 7| mu0_15(Int32) = Store : &:r0_14, r0_13
# 4| v0_16(Void) = ReturnVoid :
# 4| v0_17(Void) = UnmodeledUse : mu*
# 4| v0_18(Void) = ExitFunction :
# 4| v0_0(Void) = EnterFunction :
# 4| mu0_1(Object) = AliasedDefinition :
# 4| mu0_2(Object) = UnmodeledDefinition :
# 4| r0_3(glval<test_variables>) = InitializeThis :
# 5| r0_4(glval<Int32>) = VariableAddress[x] :
# 5| mu0_5(Int32) = Uninitialized[x] : &:r0_4
# 5| r0_6(glval<Int32>) = VariableAddress[y] :
# 5| r0_7(Int32) = Constant[5] :
# 5| mu0_8(Int32) = Store : &:r0_6, r0_7
# 6| r0_9(Int32) = Constant[4] :
# 6| r0_10(glval<Int32>) = VariableAddress[x] :
# 6| mu0_11(Int32) = Store : &:r0_10, r0_9
# 7| r0_12(glval<Int32>) = VariableAddress[y] :
# 7| r0_13(Int32) = Load : &:r0_12, ~mu0_2
# 7| r0_14(glval<Int32>) = VariableAddress[x] :
# 7| mu0_15(Int32) = Store : &:r0_14, r0_13
# 4| v0_16(Void) = ReturnVoid :
# 4| v0_17(Void) = UnmodeledUse : mu*
# 4| v0_18(Void) = ExitFunction :