The `raw/internal` folder has been restructured to better enhance code sharing between compiler generated elements and AST generated elements.
The translated calls classes have been refactored to better fit the C# library.
A new folder has been added, `common` that provides blueprints for the classes that deal with translations of calls, declarations, exprs and conditions.
Several `TranslatedX.qll` files have been modified so that they use those blueprint classes.
This commit is contained in:
AndreiDiaconu1 2019-08-29 15:36:19 +01:00
Родитель aa009d07fd
Коммит 80b7512fe2
14 изменённых файлов: 1045 добавлений и 487 удалений

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

@ -54,6 +54,7 @@ newtype TInstructionTag =
BoolConversionConstantTag() or
BoolConversionCompareTag() or
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
AddressTag() or
CatchTag() or
ThrowTag() or
UnwindTag() or
@ -192,16 +193,8 @@ string getInstructionTagId(TInstructionTag tag) {
or
tag = GeneratedBranchTag() and result = "GeneratedBranchTag"
or
// TODO: Reread
// exists(Field field, Class cls, int index, string tagName |
// field = cls.getCanonicalMember(index) and
// (
// tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or
// tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or
// tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore"
// ) and
// result = tagName + "(" + index + ")"
// ) or
tag = AddressTag() and result = "AddressTag"
or
exists(int index, string tagName |
(
tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex"

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

@ -5,267 +5,67 @@ private import InstructionTag
private import TranslatedElement
private import TranslatedExpr
private import semmle.code.csharp.ir.Util
private import semmle.code.csharp.ir.implementation.raw.internal.common.TranslatedCallBlueprint
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
/**
* The IR translation of a call to a function. The call may be from an actual
* call in the source code, or could be a call that is part of the translation
* of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
* The IR translation of a call to a function. The function can be a normal function
* (eg. `MethodCall`) or a constructor call (eg. `ObjectCreation`). Notice that the
* AST generated translated calls are tied to an expression (unlike compiler generated ones,
* which can be attached to either a statement or an expression).
*/
abstract class TranslatedCall extends TranslatedExpr {
final override TranslatedElement getChild(int id) {
// We choose the child's id in the order of evaluation.
// The qualifier is evaluated before the call target, because the value of
// the call target may depend on the value of the qualifier for virtual
// calls.
id = -2 and result = this.getQualifier()
or
id = -1 and result = this.getCallTarget()
or
result = this.getArgument(id)
}
final override Instruction getFirstInstruction() {
if exists(this.getQualifier())
then result = this.getQualifier().getFirstInstruction()
else result = this.getFirstCallTargetInstruction()
abstract class TranslatedCall extends TranslatedExpr, TranslatedCallBlueprint {
final override Instruction getResult() {
result = TranslatedCallBlueprint.super.getResult()
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = CallTag() and
opcode instanceof Opcode::Call and
resultType = getCallResultType() and
isLValue = false
or
hasSideEffect() and
tag = CallSideEffectTag() and
(
if hasWriteSideEffect()
then (
opcode instanceof Opcode::CallSideEffect and
resultType instanceof Language::UnknownType
) else (
opcode instanceof Opcode::CallReadSideEffect and
resultType instanceof Language::UnknownType
)
) and
isLValue = false
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getQualifier() and
result = this.getFirstCallTargetInstruction()
or
child = this.getCallTarget() and
result = this.getFirstArgumentOrCallInstruction()
or
exists(int argIndex |
child = this.getArgument(argIndex) and
if exists(this.getArgument(argIndex + 1))
then result = this.getArgument(argIndex + 1).getFirstInstruction()
else result = this.getInstruction(CallTag())
)
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
(
(
tag = CallTag() and
if this.hasSideEffect()
then result = this.getInstruction(CallSideEffectTag())
else result = this.getParent().getChildSuccessor(this)
)
or
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getParent().getChildSuccessor(this)
)
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = CallTag() and
(
tag = CallTag() and
(
operandTag instanceof CallTargetOperandTag and
result = this.getCallTargetResult()
or
operandTag instanceof ThisArgumentOperandTag and
result = this.getQualifierResult()
or
exists(PositionalArgumentOperandTag argTag |
argTag = operandTag and
result = this.getArgument(argTag.getArgIndex()).getResult()
)
)
)
or
tag = CallSideEffectTag() and
this.hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
override Instruction getUnmodeledDefinitionInstruction() {
result = this.getEnclosingFunction().getUnmodeledDefinitionInstruction()
or
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
}
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
tag = CallSideEffectTag() and
this.hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result instanceof Language::UnknownType
}
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
/**
* Gets the result type of the call.
*/
abstract Type getCallResultType();
/**
* Holds if the call has a `this` argument.
*/
predicate hasQualifier() { exists(this.getQualifier()) }
/**
* Gets the `TranslatedExpr` for the indirect target of the call, if any.
*/
TranslatedExpr getCallTarget() { none() }
/**
* Gets the first instruction of the sequence to evaluate the call target.
* By default, this is just the first instruction of `getCallTarget()`, but
* it can be overridden by a subclass for cases where there is a call target
* that is not computed from an expression (e.g. a direct call).
*/
Instruction getFirstCallTargetInstruction() {
result = this.getCallTarget().getFirstInstruction()
}
/**
* Gets the instruction whose result value is the target of the call. By
* default, this is just the result of `getCallTarget()`, but it can be
* overridden by a subclass for cases where there is a call target that is not
* computed from an expression (e.g. a direct call).
*/
Instruction getCallTargetResult() { result = this.getCallTarget().getResult() }
/**
* Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value
* that is passed as the `this` argument.
*/
abstract TranslatedExpr getQualifier();
/**
* Gets the instruction whose result value is the `this` argument of the call.
* By default, this is just the result of `getQualifier()`, but it can be
* overridden by a subclass for cases where there is a `this` argument that is
* not computed from a child expression (e.g. a constructor call).
*/
Instruction getQualifierResult() { result = this.getQualifier().getResult() }
/**
* Gets the argument with the specified `index`. Does not include the `this`
* argument.
*/
abstract TranslatedExpr getArgument(int index);
/**
* If there are any arguments, gets the first instruction of the first
* argument. Otherwise, returns the call instruction.
*/
final Instruction getFirstArgumentOrCallInstruction() {
if this.hasArguments()
then result = this.getArgument(0).getFirstInstruction()
else result = this.getInstruction(CallTag())
}
/**
* Holds if the call has any arguments, not counting the `this` argument.
*/
abstract predicate hasArguments();
// TODO: Fix side effects
predicate hasReadSideEffect() { any() }
predicate hasWriteSideEffect() { any() }
private predicate hasSideEffect() { hasReadSideEffect() or hasWriteSideEffect() }
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
this.hasSideEffect() and
tag = CallSideEffectTag() and
result = this.getResult()
}
}
/**
* IR translation of a direct call to a specific function. Used for both
* explicit calls and implicit calls.
* Represents the IR translation of a direct function call. The call can be one of the following:
* `MethodCall`, `LocalFunctionCall`, `AccessorCall`, `OperatorCall`.
* Note that `DelegateCall`s are not treated here since they need
*/
abstract class TranslatedDirectCall extends TranslatedCall {
final override Instruction getFirstCallTargetInstruction() {
result = this.getInstruction(CallTargetTag())
}
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
TranslatedCall.super.hasInstruction(opcode, tag, resultType, isLValue)
or
tag = CallTargetTag() and
opcode instanceof Opcode::FunctionAddress and
resultType = expr.getType() and
isLValue = true
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
or
tag = CallTargetTag() and
kind instanceof GotoEdge and
result = this.getFirstArgumentOrCallInstruction()
}
}
/**
* The IR translation of a call to a function.
*/
abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedCall {
class TranslatedFunctionCall extends TranslatedNonConstantExpr, TranslatedCall {
override Call expr;
override Type getCallResultType() { result = this.getResultType() }
final override predicate hasArguments() { exists(expr.getArgument(0)) }
final override TranslatedExpr getQualifier() {
expr instanceof QualifiableExpr and
result = getTranslatedExpr(expr.(QualifiableExpr).getQualifier())
TranslatedFunctionCall() {
expr instanceof MethodCall or
expr instanceof LocalFunctionCall or
expr instanceof AccessorCall or
expr instanceof OperatorCall
}
final override TranslatedExpr getArgument(int index) {
result = getTranslatedExpr(expr.getArgument(index))
}
}
/**
* Represents the IR translation of a direct function call.
*/
class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
override Call expr;
override Callable getInstructionFunction(InstructionTag tag) {
tag = CallTargetTag() and result = expr.getTarget()
}
override predicate hasArguments() {
exists(expr.getArgument(0))
}
override TranslatedExpr getArgument(int index) {
result = getTranslatedExpr(expr.getArgument(index))
}
override TranslatedExpr getQualifier() {
expr instanceof QualifiableExpr and
result = getTranslatedExpr(expr.(QualifiableExpr).getQualifier())
}
override Instruction getQualifierResult() {
result = this.getQualifier().getResult()
}
override Type getCallResultType() {
result = expr.getTarget().getReturnType()
}
override predicate hasReadSideEffect() {
not expr.getTarget().(SideEffectFunction).neverReadsMemory()
}
@ -276,26 +76,45 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
}
/**
* Represents the IR translation of a call to a constructor.
* The target of the call is a newly allocated object whose address, after
* the constructor call, address will be passed to a variable declaration.
* Represents the IR translation of a call to a constructor or to a constructor initializer.
* The qualifier of the call is obtained from the constructor call context.
* Note that `DelegateCreation` is not present here, since the call to a delegate constructor is
* compiler generated.
*/
class TranslatedConstructorCall extends TranslatedFunctionCall {
TranslatedConstructorCall() {
class TranslatedConstructorCall extends TranslatedNonConstantExpr, TranslatedCall {
override Call expr;
TranslatedConstructorCall() {
expr instanceof ObjectCreation or
expr instanceof ConstructorInitializer
}
override Callable getInstructionFunction(InstructionTag tag) {
tag = CallTargetTag() and result = expr.getTarget()
}
override predicate hasArguments() {
exists(expr.getArgument(0))
}
override TranslatedExpr getArgument(int index) {
result = getTranslatedExpr(expr.getArgument(index))
}
// The qualifier for a constructor call has already been generated
// (the `NewObj` instruction)
override TranslatedExpr getQualifier() {
none()
}
override Type getCallResultType() {
result instanceof VoidType
}
override Instruction getQualifierResult() {
// We must retrieve the qualifier from the context the
// constructor call happened
exists(StructorCallContext context |
exists(ConstructorCallContext context |
context = this.getParent() and
result = context.getReceiver()
)
}
override Type getCallResultType() { result instanceof VoidType }
override predicate hasQualifier() { any() }
}

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

@ -4,26 +4,23 @@ private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr
private import common.TranslatedConditionBlueprint
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
abstract class ConditionContext extends TranslatedElement {
abstract Instruction getChildTrueSuccessor(TranslatedCondition child);
abstract Instruction getChildFalseSuccessor(TranslatedCondition child);
TranslatedCondition getTranslatedCondition(Expr expr) {
result.getExpr() = expr
}
TranslatedCondition getTranslatedCondition(Expr expr) { result.getExpr() = expr }
abstract class TranslatedCondition extends TranslatedElement {
abstract class TranslatedCondition extends ConditionBlueprint {
Expr expr;
final override string toString() { result = expr.toString() }
final override Language::AST getAST() { result = expr }
final ConditionContext getConditionContext() { result = this.getParent() }
final Expr getExpr() { result = expr }
final Expr getExpr() {
result = expr
}
final override Callable getFunction() { result = expr.getEnclosingCallable() }
@ -56,12 +53,12 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
override ParenthesizedExpr expr;
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
final override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
final override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
@ -74,12 +71,12 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
class TranslatedNotCondition extends TranslatedFlexibleCondition {
override LogicalNotExpr expr;
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
@ -131,15 +128,18 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr }
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
(
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction()
) or
(
child = this.getRightOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getAnOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
@ -148,57 +148,34 @@ class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
override LogicalOrExpr expr;
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = getAnOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getLeftOperand() and
result = getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
}
}
class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCondition {
TranslatedValueCondition() { this = TTranslatedValueCondition(expr) }
override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() }
override Instruction getFirstInstruction() { result = this.getValueExpr().getFirstInstruction() }
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = ValueConditionConditionalBranchTag() and
opcode instanceof Opcode::ConditionalBranch and
resultType instanceof VoidType and
isLValue = false
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getValueExpr() and
result = this.getInstruction(ValueConditionConditionalBranchTag())
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
(
kind instanceof TrueEdge and
result = this.getConditionContext().getChildTrueSuccessor(this)
or
kind instanceof FalseEdge and
child = this.getLeftOperand() and
result = getRightOperand().getFirstInstruction()
) or
(
child = this.getRightOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this)
)
}
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = ValueConditionConditionalBranchTag() and
operandTag instanceof ConditionOperandTag and
class TranslatedValueCondition extends TranslatedCondition, ValueConditionBlueprint,
TTranslatedValueCondition {
TranslatedValueCondition() {
this = TTranslatedValueCondition(expr)
}
override TranslatedExpr getValueExpr() {
result = getTranslatedExpr(expr)
}
override Instruction valueExprResult() {
result = this.getValueExpr().getResult()
}
private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) }
}

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

@ -7,6 +7,7 @@ private import TranslatedElement
private import TranslatedExpr
private import TranslatedInitialization
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
private import common.TranslatedDeclarationBlueprint
/**
* Gets the `TranslatedDeclaration` that represents the declaration
@ -35,58 +36,28 @@ abstract class TranslatedLocalDeclaration extends TranslatedElement, TTranslated
* Represents the IR translation of the declaration of a local variable,
* including its initialization, if any.
*/
class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, InitializationContext {
class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, LocalVariableDeclarationBlueprint,
InitializationContext {
LocalVariable var;
TranslatedLocalVariableDeclaration() { var = expr.getVariable() }
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
override Instruction getFirstInstruction() {
TranslatedLocalVariableDeclaration() {
var = expr.getVariable()
}
override Instruction getTargetAddress() {
result = this.getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVariableType(var) and
isLValue = true
or
this.hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getVariableType(var) and
isLValue = false
override LocalVariable getDeclVar() {
result = var
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if this.hasUninitializedInstruction()
then result = this.getInstruction(InitializerStoreTag())
else
if this.isInitializedByExpr()
then
// initialization is done by the expression
result = this.getParent().getChildSuccessor(this)
else result = this.getInitialization().getFirstInstruction()
)
or
this.hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = this.getInitialization().getFirstInstruction()
or
not exists(this.getInitialization()) and result = this.getParent().getChildSuccessor(this)
)
override Type getVarType() {
result = getVariableType(getDeclVar())
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
override Type getTargetType() {
result = getVariableType(var)
}
override IRVariable getInstructionVariable(InstructionTag tag) {
@ -95,23 +66,10 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, Ini
or
this.hasUninitializedInstruction() and tag = InitializerStoreTag()
) and
result = getIRUserVariable(getFunction(), var)
result = getIRUserVariable(getFunction(), getDeclVar())
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
this.hasUninitializedInstruction() and
tag = InitializerStoreTag() and
operandTag instanceof AddressOperandTag and
result = this.getInstruction(InitializerVariableAddressTag())
}
override Instruction getTargetAddress() {
result = this.getInstruction(InitializerVariableAddressTag())
}
override Type getTargetType() { result = getVariableType(var) }
private TranslatedInitialization getInitialization() {
override TranslatedInitialization getInitialization() {
// First complex initializations
if var.getInitializer() instanceof ArrayCreation
then result = getTranslatedInitialization(var.getInitializer().(ArrayCreation).getInitializer())
@ -123,17 +81,7 @@ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, Ini
result = getTranslatedInitialization(var.getInitializer())
}
private predicate hasUninitializedInstruction() {
(
not exists(this.getInitialization()) or
this.getInitialization() instanceof TranslatedListInitialization
) and
not this.isInitializedByExpr()
override predicate isInitializedByElement() {
expr.getParent() instanceof IsExpr
}
/**
* Predicate that holds if a declaration is not explicitly initialized,
* but will be initialized as part of an expression.
*/
private predicate isInitializedByExpr() { expr.getParent() instanceof IsExpr }
}

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

@ -22,6 +22,12 @@ ArrayType getArrayOfDim(int dim, Type type) {
result.getElementType() = type
}
predicate canCreateCompilerGeneratedElement (int nth) {
// For now we allow a max of 15 compiler generated elements
nth in [0 .. 14]
}
/**
* Gets the "real" parent of `expr`. This predicate treats conversions as if
* they were explicit nodes in the expression tree, rather than as implicit
@ -253,8 +259,13 @@ newtype TTranslatedElement =
)
} or
// A local declaration
TTranslatedDeclaration(LocalVariableDeclExpr entry)
TTranslatedDeclaration(LocalVariableDeclExpr entry) or
// A compiler generated element, generated by `generatedBy` during the
// desugaring process
TTranslatedCompilerGeneratedElement(Element generatedBy, int index) {
canCreateCompilerGeneratedElement(index)
}
/**
* Gets the index of the first explicitly initialized element in `initList`
* whose index is greater than `afterElementIndex`, where `afterElementIndex`

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

@ -9,8 +9,9 @@ private import TranslatedDeclaration
private import TranslatedElement
private import TranslatedFunction
private import TranslatedInitialization
private import TranslatedFunction
private import TranslatedStmt
private import common.TranslatedConditionBlueprint
private import common.TranslatedCallBlueprint
private import common.TranslatedExprBlueprint
import TranslatedCall
private import semmle.code.csharp.ir.Util
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
@ -35,14 +36,9 @@ TranslatedExpr getTranslatedExpr(Expr expr) {
* as the `TranslatedAllocatorCall` and `TranslatedAllocationSize` within the
* translation of a `NewExpr`.
*/
abstract class TranslatedExpr extends TranslatedElement {
abstract class TranslatedExpr extends TranslatedExprBlueprint {
Expr expr;
/**
* Gets the instruction that produces the result of the expression.
*/
abstract Instruction getResult();
/**
* Holds if this `TranslatedExpr` produces the final result of the original
* expression from the AST.
@ -243,12 +239,12 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
override Instruction getChildSuccessor(TranslatedElement child) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
result = this.getInstruction(ConditionValueTrueTempAddressTag())
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
result = this.getInstruction(ConditionValueFalseTempAddressTag())
}
@ -746,8 +742,7 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
// and not the LHS (the address of the LHS is generated during
// the translation of the initialization).
(
expr.getParent() instanceof LocalVariableDeclAndInitExpr
implies
expr.getParent() instanceof LocalVariableDeclAndInitExpr implies
expr = expr.getParent().(LocalVariableDeclAndInitExpr).getInitializer()
)
}
@ -1452,13 +1447,13 @@ class TranslatedAssignOperation extends TranslatedAssignment {
/**
* Abstract class implemented by any `TranslatedElement` that has a child
* expression that is a call to a constructor or destructor, in order to
* provide a pointer to the object being constructed or destroyed.
* expression that is a call to a constructor, in order to
* provide a pointer to the object being constructed.
*/
abstract class StructorCallContext extends TranslatedElement {
abstract class ConstructorCallContext extends TranslatedElement {
/**
* Gets the instruction whose result value is the address of the object to be
* constructed or destroyed.
* constructed.
*/
abstract Instruction getReceiver();
}
@ -1609,12 +1604,12 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionCont
)
}
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction()
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
result = this.getElse().getFirstInstruction()
}

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

@ -175,7 +175,7 @@ class TranslatedDirectInitialization extends TranslatedInitialization {
* object of type `expr.getType()` is allocated, which is then initialized by the
* constructor.
*/
class TranslatedObjectInitialization extends TranslatedInitialization, StructorCallContext {
class TranslatedObjectInitialization extends TranslatedInitialization, ConstructorCallContext {
override ObjectCreation expr;
override TranslatedElement getChild(int id) {
@ -389,8 +389,7 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
}
// TODO: Possibly refactor into something simpler
abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement,
StructorCallContext {
abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement, ConstructorCallContext {
Call call;
final override Language::AST getAST() { result = call }

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

@ -8,6 +8,7 @@ private import TranslatedElement
private import TranslatedExpr
private import TranslatedFunction
private import TranslatedInitialization
private import common.TranslatedConditionBlueprint
private import IRInternal
private import semmle.code.csharp.ir.internal.IRUtilities
@ -243,10 +244,14 @@ class TranslatedTryStmt extends TranslatedStmt {
none()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
none()
}
override Instruction getFirstInstruction() {
result = this.getBody().getFirstInstruction()
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getCatchClause(_) and result = this.getFinally().getFirstInstruction()
or
@ -562,12 +567,12 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction()
}
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction()
@ -615,11 +620,11 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
override final Instruction getChildTrueSuccessor(ConditionBlueprint child) {
child = this.getCondition() and result = this.getBody().getFirstInstruction()
}
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
override final Instruction getChildFalseSuccessor(ConditionBlueprint child) {
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
}
}

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

@ -0,0 +1,217 @@
/**
* Contains an abstract class that serves as a blueprint for classes that deal with the translation of calls
* (both AST generated and compiler generated).
*/
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.implementation.raw.internal.InstructionTag
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedElement
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.csharp.ir.Util
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
private import TranslatedExprBlueprint
abstract class TranslatedCallBlueprint extends TranslatedElement {
override final TranslatedElement getChild(int id) {
// We choose the child's id in the order of evaluation.
// Note: some calls do need qualifiers, though instructions for them have already
// been generated; eg. a constructor does not need to generate a qualifier,
// though the `this` argument exists and is the result of the instruction
// that allocated the new object. For those calls, `getQualifier()` should
// be void.
id = -1 and result = getQualifier() or
result = getArgument(id)
}
override final Instruction getFirstInstruction() {
if exists(getQualifier()) then
result = getQualifier().getFirstInstruction()
else
result = getInstruction(CallTargetTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
(
tag = CallTag() and
opcode instanceof Opcode::Call and
resultType = getCallResultType() and
isLValue = false
) or
(
hasSideEffect() and
tag = CallSideEffectTag() and
(
if hasWriteSideEffect() then (
opcode instanceof Opcode::CallSideEffect and
resultType instanceof Language::UnknownType
)
else (
opcode instanceof Opcode::CallReadSideEffect and
resultType instanceof Language::UnknownType
)
) and
isLValue = false
) or
(
tag = CallTargetTag() and
opcode instanceof Opcode::FunctionAddress and
// Since the DB does not have a function type,
// we just use the UnknownType
resultType instanceof Language::UnknownType and
isLValue = true
)
}
override Instruction getChildSuccessor(TranslatedElement child) {
(
child = getQualifier() and
result = getInstruction(CallTargetTag())
) or
exists(int argIndex |
child = getArgument(argIndex) and
if exists(getArgument(argIndex + 1)) then
result = getArgument(argIndex + 1).getFirstInstruction()
else
result = getInstruction(CallTag())
)
}
override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
kind instanceof GotoEdge and
(
(
tag = CallTag() and
if hasSideEffect() then
result = getInstruction(CallSideEffectTag())
else
result = getParent().getChildSuccessor(this)
) or
(
hasSideEffect() and
tag = CallSideEffectTag() and
result = getParent().getChildSuccessor(this)
) or
(
tag = CallTargetTag() and
kind instanceof GotoEdge and
result = getFirstArgumentOrCallInstruction()
)
)
}
override Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) {
(
tag = CallTag() and
(
(
operandTag instanceof CallTargetOperandTag and
result = getInstruction(CallTargetTag())
) or
(
operandTag instanceof ThisArgumentOperandTag and
result = getQualifierResult()
) or
exists(PositionalArgumentOperandTag argTag |
argTag = operandTag and
result = getArgument(argTag.getArgIndex()).getResult()
)
)
) or
(
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = getUnmodeledDefinitionInstruction()
)
}
override final Type getInstructionOperandType(InstructionTag tag,
TypedOperandTag operandTag) {
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result instanceof Language::UnknownType
}
Instruction getResult() {
result = getInstruction(CallTag())
}
/**
* Gets the result type of the call.
*/
abstract Type getCallResultType();
/**
* Gets the unmodeled definition instruction of the enclosing
* function (of the element this call is attached to).
*/
abstract Instruction getUnmodeledDefinitionInstruction();
/**
* Holds if the call has a `this` argument.
*/
predicate hasQualifier() {
exists(getQualifier())
}
/**
* Gets the expr for the qualifier of the call.
*/
abstract TranslatedExprBlueprint getQualifier();
/**
* Gets the instruction whose result value is the `this` argument of the call.
* In general, this is just the result of `getQualifier()`, but it can be
* overridden by a subclass for cases where there is a `this` argument that is
* not computed from a child expression (e.g. a constructor call).
*/
abstract Instruction getQualifierResult();
/**
* Gets the argument with the specified `index`. Does not include the `this`
* argument. We use `TranslatedExprBlueprint` so that we can give both `TranslatedExpr` args,
* in the case of AST generated arguments, or `TranslatedCompilerElement` args in the case of
* compiler generated arguments.
*/
abstract TranslatedExprBlueprint getArgument(int index);
/**
* If there are any arguments, gets the first instruction of the first
* argument. Otherwise, returns the call instruction.
*/
final Instruction getFirstArgumentOrCallInstruction() {
if hasArguments() then
result = getArgument(0).getFirstInstruction()
else
result = getInstruction(CallTag())
}
/**
* Holds if the call has any arguments, not counting the `this` argument.
*/
abstract predicate hasArguments();
predicate hasReadSideEffect() {
any()
}
predicate hasWriteSideEffect() {
any()
}
private predicate hasSideEffect() {
hasReadSideEffect() or hasWriteSideEffect()
}
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
hasSideEffect() and
tag = CallSideEffectTag() and
result = getResult()
}
}

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

@ -0,0 +1,92 @@
/**
* Contains several abstract classes that serve as blueprints.
*/
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.implementation.raw.internal.InstructionTag
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedElement
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedCondition
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
/**
* Represents the context of the condition, ie. provides
* information about the instruction that follows a conditional branch.
*/
abstract class ConditionContext extends TranslatedElement {
abstract Instruction getChildTrueSuccessor(ConditionBlueprint child);
abstract Instruction getChildFalseSuccessor(ConditionBlueprint child);
}
/**
* Abstract class that serves as a blueprint for the classes that deal with both the AST generated conditions
* and the compiler generated ones (captures the common patterns).
*/
abstract class ConditionBlueprint extends TranslatedElement {
final ConditionContext getConditionContext() {
result = getParent()
}
}
/**
* Abstract class that serves as a blueprint for the classes that deal with both the AST generated _value_ conditions
* and the compiler generated ones (captures the common patterns).
*/
abstract class ValueConditionBlueprint extends ConditionBlueprint {
override TranslatedElement getChild(int id) {
id = 0 and result = getValueExpr()
}
override Instruction getFirstInstruction() {
result = getValueExpr().getFirstInstruction()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
tag = ValueConditionConditionalBranchTag() and
opcode instanceof Opcode::ConditionalBranch and
resultType instanceof VoidType and
isLValue = false
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getValueExpr() and
result = getInstruction(ValueConditionConditionalBranchTag())
}
override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and
(
(
kind instanceof TrueEdge and
result = getConditionContext().getChildTrueSuccessor(this)
) or
(
kind instanceof FalseEdge and
result = getConditionContext().getChildFalseSuccessor(this)
)
)
}
override Instruction getInstructionOperand(InstructionTag tag,
OperandTag operandTag) {
tag = ValueConditionConditionalBranchTag() and
operandTag instanceof ConditionOperandTag and
result = valueExprResult()
}
/**
* Gets the instruction that represents the result of the value expression.
*/
abstract Instruction valueExprResult();
/**
* Gets the `TranslatedElements that represents the value expression.
*/
abstract TranslatedElement getValueExpr();
}

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

@ -0,0 +1,120 @@
/**
* Contains an abstract class that serves as a blueprint for the classes that deal with both the AST
* generated declarations and the compiler generated ones (captures the common patterns).
*/
import csharp
private import semmle.code.csharp.ir.implementation.Opcode
private import semmle.code.csharp.ir.internal.IRUtilities
private import semmle.code.csharp.ir.implementation.internal.OperandTag
private import semmle.code.csharp.ir.implementation.raw.internal.InstructionTag
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedElement
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedInitialization
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
abstract class LocalVariableDeclarationBlueprint extends TranslatedElement {
override TranslatedElement getChild(int id) {
id = 0 and result = getInitialization()
}
override Instruction getFirstInstruction() {
result = getVarAddress()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
Type resultType, boolean isLValue) {
(
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getVarType() and
isLValue = true
) or
(
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getVarType() and
isLValue = false
)
}
override Instruction getInstructionSuccessor(InstructionTag tag,
EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if hasUninitializedInstruction() then
result = getInstruction(InitializerStoreTag())
else
if isInitializedByElement() then
// initialization is done by an element
result = getParent().getChildSuccessor(this)
else
result = getInitialization().getFirstInstruction()
) or
(
hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = getInitialization().getFirstInstruction() or
not exists(getInitialization()) and result = getParent().getChildSuccessor(this)
)
)
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and result = getParent().getChildSuccessor(this)
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
operandTag instanceof AddressOperandTag and
result = getVarAddress()
}
/**
* Holds if the declaration should have an `Uninitialized` instruction.
* Compiler generated elements should override this predicate and
* make it empty, since we always initialize the vars declared during the
* desugaring process.
*/
predicate hasUninitializedInstruction() {
(
not exists(getInitialization()) or
getInitialization() instanceof TranslatedListInitialization
) and
not isInitializedByElement()
}
Instruction getVarAddress() {
result = getInstruction(InitializerVariableAddressTag())
}
/**
* Gets the declared variable. For compiler generated elements, this
* should be empty (since we treat temp vars differently).
*/
abstract LocalVariable getDeclVar();
/**
* Gets the type of the declared variable.
*/
abstract Type getVarType();
/**
* Gets the initialization, if there is one.
* For compiler generated elements we don't treat the initialization
* as a different step, but do it during the declaration.
*/
abstract TranslatedElement getInitialization();
/**
* Predicate that holds if a declaration is not explicitly initialized,
* but will be implicitly initialized by an element.
*/
abstract predicate isInitializedByElement();
}

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

@ -0,0 +1,14 @@
/**
* Contains an abstract class that serves as a blueprint for classes that deal with the translation of exprs
* (both AST generated and compiler generated).
*/
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedElement
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
abstract class TranslatedExprBlueprint extends TranslatedElement {
/**
* Gets the instruction that produces the result of the expression.
*/
abstract Instruction getResult();
}

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

@ -0,0 +1,368 @@
import csharp
private int getMaxCallArgIndex() {
result = max(int argIndex |
exists(Call call |
exists(call.getArgument(argIndex))
) or
// Quick fix so that generated calls (`Invoke` etc) will have the
// correct number of parameters; it is an overestimation,
// since we don't care about all the callables, so it
// should be restricted more
exists(Callable callable |
callable.getNumberOfParameters() = argIndex
)
)
}
private newtype TOperandTag =
TAddressOperand() or
TBufferSizeOperand() or
TSideEffectOperand() or
TLoadOperand() or
TStoreValueOperand() or
TUnaryOperand() or
TLeftOperand() or
TRightOperand() or
TConditionOperand() or
TUnmodeledUseOperand() or
TCallTargetOperand() or
TThisArgumentOperand() or
TPositionalArgumentOperand(int argIndex) {
argIndex in [0..getMaxCallArgIndex()]
} or
TChiTotalOperand() or
TChiPartialOperand()
/**
* Identifies the kind of operand on an instruction. Each `Instruction` has at
* most one operand of any single `OperandTag`. The set of `OperandTag`s used by
* an `Instruction` is determined by the instruction's opcode.
*/
abstract class OperandTag extends TOperandTag {
abstract string toString();
abstract int getSortOrder();
string getLabel() {
result = ""
}
}
/**
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
abstract class MemoryOperandTag extends OperandTag {
}
/**
* An operand that consumes a register (non-memory) result.
*/
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 {
}
// 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"
}
override final int getSortOrder() {
result = 0
}
override final string getLabel() {
result = "&:"
}
}
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"
}
override final 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"
}
override final int getSortOrder() {
result = 2
}
}
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"
}
override final int getSortOrder() {
result = 3
}
}
LoadOperandTag loadOperand() {
result = TLoadOperand()
}
/**
* The source value operand of a `Store` instruction.
*/
class StoreValueOperandTag extends RegisterOperandTag, TStoreValueOperand {
override final string toString() {
result = "StoreValue"
}
override final int getSortOrder() {
result = 4
}
}
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"
}
override final int getSortOrder() {
result = 5
}
}
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"
}
override final int getSortOrder() {
result = 6
}
}
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"
}
override final int getSortOrder() {
result = 7
}
}
RightOperandTag rightOperand() {
result = TRightOperand()
}
/**
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperandTag extends RegisterOperandTag, TConditionOperand {
override final string toString() {
result = "Condition"
}
override final int getSortOrder() {
result = 8
}
}
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"
}
override final int getSortOrder() {
result = 9
}
}
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"
}
override final int getSortOrder() {
result = 10
}
override final string getLabel() {
result = "func:"
}
}
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 {
}
/**
* An operand representing the implicit 'this' argument to a member function
* call.
*/
class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
ThisArgumentOperandTag() {
this = TThisArgumentOperand()
}
override final string toString() {
result = "Arg(this)"
}
override final int getSortOrder() {
result = 11
}
override final string getLabel() {
result = "this:"
}
}
ThisArgumentOperandTag thisArgumentOperand() {
result = TThisArgumentOperand()
}
/**
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperandTag extends ArgumentOperandTag,
TPositionalArgumentOperand {
int argIndex;
PositionalArgumentOperandTag() {
this = TPositionalArgumentOperand(argIndex)
}
override final string toString() {
result = "Arg(" + argIndex + ")"
}
override final int getSortOrder() {
result = 12 + argIndex
}
override final string getLabel() {
result = argIndex.toString() + ":"
}
final int getArgIndex() {
result = argIndex
}
}
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
result = TPositionalArgumentOperand(argIndex)
}
class ChiTotalOperandTag extends MemoryOperandTag, TChiTotalOperand {
override final string toString() {
result = "ChiTotal"
}
override final int getSortOrder() {
result = 13
}
override final string getLabel() {
result = "total:"
}
}
ChiTotalOperandTag chiTotalOperand() {
result = TChiTotalOperand()
}
class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
override final string toString() {
result = "ChiPartial"
}
override final int getSortOrder() {
result = 14
}
override final string getLabel() {
result = "partial:"
}
}
ChiPartialOperandTag chiPartialOperand() {
result = TChiPartialOperand()
}

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

@ -143,7 +143,7 @@ casts.cs:
# 11| mu0_2(null) = UnmodeledDefinition :
# 13| r0_3(glval<Casts_A>) = VariableAddress[Aobj] :
# 13| r0_4(Casts_A) = NewObj :
# 13| r0_5(glval<Casts_A>) = FunctionAddress[Casts_A] :
# 13| r0_5(glval<null>) = FunctionAddress[Casts_A] :
# 13| v0_6(Void) = Call : func:r0_5, this:r0_4
# 13| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 13| mu0_8(Casts_A) = Store : &:r0_3, r0_4
@ -197,7 +197,7 @@ constructor_init.cs:
# 17| mu0_2(null) = UnmodeledDefinition :
# 17| r0_3(glval<DerivedClass>) = InitializeThis :
# 17| r0_4(glval<BaseClass>) = Convert[DerivedClass : BaseClass] : r0_3
# 17| r0_5(glval<BaseClass>) = FunctionAddress[BaseClass] :
# 17| r0_5(glval<null>) = FunctionAddress[BaseClass] :
# 17| v0_6(Void) = Call : func:r0_5, this:r0_4
# 17| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 18| v0_8(Void) = NoOp :
@ -214,7 +214,7 @@ constructor_init.cs:
# 21| r0_4(glval<Int32>) = VariableAddress[i] :
# 21| mu0_5(Int32) = InitializeParameter[i] : &:r0_4
# 21| r0_6(glval<BaseClass>) = Convert[DerivedClass : BaseClass] : r0_3
# 21| r0_7(glval<BaseClass>) = FunctionAddress[BaseClass] :
# 21| r0_7(glval<null>) = FunctionAddress[BaseClass] :
# 21| r0_8(glval<Int32>) = VariableAddress[i] :
# 21| r0_9(Int32) = Load : &:r0_8, ~mu0_2
# 21| v0_10(Void) = Call : func:r0_7, this:r0_6, 0:r0_9
@ -234,7 +234,7 @@ constructor_init.cs:
# 25| mu0_5(Int32) = InitializeParameter[i] : &:r0_4
# 25| r0_6(glval<Int32>) = VariableAddress[j] :
# 25| mu0_7(Int32) = InitializeParameter[j] : &:r0_6
# 25| r0_8(glval<DerivedClass>) = FunctionAddress[DerivedClass] :
# 25| r0_8(glval<null>) = FunctionAddress[DerivedClass] :
# 25| r0_9(glval<Int32>) = VariableAddress[i] :
# 25| r0_10(Int32) = Load : &:r0_9, ~mu0_2
# 25| v0_11(Void) = Call : func:r0_8, this:r0_3, 0:r0_10
@ -251,20 +251,20 @@ constructor_init.cs:
# 29| mu0_2(null) = UnmodeledDefinition :
# 31| r0_3(glval<DerivedClass>) = VariableAddress[obj1] :
# 31| r0_4(DerivedClass) = NewObj :
# 31| r0_5(glval<DerivedClass>) = FunctionAddress[DerivedClass] :
# 31| r0_5(glval<null>) = FunctionAddress[DerivedClass] :
# 31| v0_6(Void) = Call : func:r0_5, this:r0_4
# 31| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 31| mu0_8(DerivedClass) = Store : &:r0_3, r0_4
# 32| r0_9(glval<DerivedClass>) = VariableAddress[obj2] :
# 32| r0_10(DerivedClass) = NewObj :
# 32| r0_11(glval<DerivedClass>) = FunctionAddress[DerivedClass] :
# 32| r0_11(glval<null>) = FunctionAddress[DerivedClass] :
# 32| r0_12(Int32) = Constant[1] :
# 32| v0_13(Void) = Call : func:r0_11, this:r0_10, 0:r0_12
# 32| mu0_14(null) = ^CallSideEffect : ~mu0_2
# 32| mu0_15(DerivedClass) = Store : &:r0_9, r0_10
# 33| r0_16(glval<DerivedClass>) = VariableAddress[obj3] :
# 33| r0_17(DerivedClass) = NewObj :
# 33| r0_18(glval<DerivedClass>) = FunctionAddress[DerivedClass] :
# 33| r0_18(glval<null>) = FunctionAddress[DerivedClass] :
# 33| r0_19(Int32) = Constant[1] :
# 33| r0_20(Int32) = Constant[2] :
# 33| v0_21(Void) = Call : func:r0_18, this:r0_17, 0:r0_19, 1:r0_20
@ -343,7 +343,7 @@ func_with_param_call.cs:
# 10| mu0_1(null) = AliasedDefinition :
# 10| mu0_2(null) = UnmodeledDefinition :
# 12| r0_3(glval<Int32>) = VariableAddress[#return] :
# 12| r0_4(glval<Int32>) = FunctionAddress[f] :
# 12| r0_4(glval<null>) = FunctionAddress[f] :
# 12| r0_5(Int32) = Constant[2] :
# 12| r0_6(Int32) = Constant[3] :
# 12| r0_7(Int32) = Call : func:r0_4, 0:r0_5, 1:r0_6
@ -385,46 +385,46 @@ inheritance_polymorphism.cs:
# 23| System.Void Program.Main()
# 23| Block 0
# 23| v0_0(Void) = EnterFunction :
# 23| mu0_1(null) = AliasedDefinition :
# 23| mu0_2(null) = UnmodeledDefinition :
# 25| r0_3(glval<B>) = VariableAddress[objB] :
# 25| r0_4(B) = NewObj :
# 25| r0_5(glval<B>) = FunctionAddress[B] :
# 25| v0_6(Void) = Call : func:r0_5, this:r0_4
# 25| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 25| mu0_8(B) = Store : &:r0_3, r0_4
# 26| r0_9(glval<B>) = VariableAddress[objB] :
# 26| r0_10(B) = Load : &:r0_9, ~mu0_2
# 26| r0_11(glval<Int32>) = FunctionAddress[function] :
# 26| r0_12(Int32) = Call : func:r0_11, this:r0_10
# 26| mu0_13(null) = ^CallSideEffect : ~mu0_2
# 29| r0_14(glval<A>) = VariableAddress[objA] :
# 29| mu0_15(A) = Uninitialized[objA] : &:r0_14
# 30| r0_16(glval<B>) = VariableAddress[objB] :
# 30| r0_17(A) = Convert : r0_16
# 30| r0_18(glval<A>) = VariableAddress[objA] :
# 30| mu0_19(A) = Store : &:r0_18, r0_17
# 31| r0_20(glval<A>) = VariableAddress[objA] :
# 31| r0_21(A) = Load : &:r0_20, ~mu0_2
# 31| r0_22(glval<Int32>) = FunctionAddress[function] :
# 31| r0_23(Int32) = Call : func:r0_22, this:r0_21
# 31| mu0_24(null) = ^CallSideEffect : ~mu0_2
# 33| r0_25(glval<A>) = VariableAddress[objC] :
# 33| r0_26(C) = NewObj :
# 33| r0_27(glval<C>) = FunctionAddress[C] :
# 33| v0_28(Void) = Call : func:r0_27, this:r0_26
# 33| mu0_29(null) = ^CallSideEffect : ~mu0_2
# 33| r0_30(A) = Convert : r0_26
# 33| mu0_31(C) = Store : &:r0_25, r0_30
# 34| r0_32(glval<A>) = VariableAddress[objC] :
# 34| r0_33(A) = Load : &:r0_32, ~mu0_2
# 34| r0_34(glval<Int32>) = FunctionAddress[function] :
# 34| r0_35(Int32) = Call : func:r0_34, this:r0_33
# 34| mu0_36(null) = ^CallSideEffect : ~mu0_2
# 23| v0_37(Void) = ReturnVoid :
# 23| v0_38(Void) = UnmodeledUse : mu*
# 23| v0_39(Void) = ExitFunction :
# 23| v0_0(Void) = EnterFunction :
# 23| mu0_1(null) = AliasedDefinition :
# 23| mu0_2(null) = UnmodeledDefinition :
# 25| r0_3(glval<B>) = VariableAddress[objB] :
# 25| r0_4(B) = NewObj :
# 25| r0_5(glval<null>) = FunctionAddress[B] :
# 25| v0_6(Void) = Call : func:r0_5, this:r0_4
# 25| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 25| mu0_8(B) = Store : &:r0_3, r0_4
# 26| r0_9(glval<B>) = VariableAddress[objB] :
# 26| r0_10(B) = Load : &:r0_9, ~mu0_2
# 26| r0_11(glval<null>) = FunctionAddress[function] :
# 26| r0_12(Int32) = Call : func:r0_11, this:r0_10
# 26| mu0_13(null) = ^CallSideEffect : ~mu0_2
# 29| r0_14(glval<A>) = VariableAddress[objA] :
# 29| mu0_15(A) = Uninitialized[objA] : &:r0_14
# 30| r0_16(glval<B>) = VariableAddress[objB] :
# 30| r0_17(A) = Convert : r0_16
# 30| r0_18(glval<A>) = VariableAddress[objA] :
# 30| mu0_19(A) = Store : &:r0_18, r0_17
# 31| r0_20(glval<A>) = VariableAddress[objA] :
# 31| r0_21(A) = Load : &:r0_20, ~mu0_2
# 31| r0_22(glval<null>) = FunctionAddress[function] :
# 31| r0_23(Int32) = Call : func:r0_22, this:r0_21
# 31| mu0_24(null) = ^CallSideEffect : ~mu0_2
# 33| r0_25(glval<A>) = VariableAddress[objC] :
# 33| r0_26(C) = NewObj :
# 33| r0_27(glval<null>) = FunctionAddress[C] :
# 33| v0_28(Void) = Call : func:r0_27, this:r0_26
# 33| mu0_29(null) = ^CallSideEffect : ~mu0_2
# 33| r0_30(A) = Convert : r0_26
# 33| mu0_31(C) = Store : &:r0_25, r0_30
# 34| r0_32(glval<A>) = VariableAddress[objC] :
# 34| r0_33(A) = Load : &:r0_32, ~mu0_2
# 34| r0_34(glval<null>) = FunctionAddress[function] :
# 34| r0_35(Int32) = Call : func:r0_34, this:r0_33
# 34| mu0_36(null) = ^CallSideEffect : ~mu0_2
# 23| v0_37(Void) = ReturnVoid :
# 23| v0_38(Void) = UnmodeledUse : mu*
# 23| v0_39(Void) = ExitFunction :
isexpr.cs:
# 8| System.Void IsExpr.Main()
@ -521,14 +521,14 @@ obj_creation.cs:
# 17| mu0_2(null) = UnmodeledDefinition :
# 19| r0_3(glval<MyClass>) = VariableAddress[obj] :
# 19| r0_4(MyClass) = NewObj :
# 19| r0_5(glval<MyClass>) = FunctionAddress[MyClass] :
# 19| r0_5(glval<null>) = FunctionAddress[MyClass] :
# 19| r0_6(Int32) = Constant[100] :
# 19| v0_7(Void) = Call : func:r0_5, this:r0_4, 0:r0_6
# 19| mu0_8(null) = ^CallSideEffect : ~mu0_2
# 19| mu0_9(MyClass) = Store : &:r0_3, r0_4
# 20| r0_10(glval<MyClass>) = VariableAddress[obj_initlist] :
# 20| r0_11(MyClass) = NewObj :
# 20| r0_12(glval<MyClass>) = FunctionAddress[MyClass] :
# 20| r0_12(glval<null>) = FunctionAddress[MyClass] :
# 20| v0_13(Void) = Call : func:r0_12, this:r0_11
# 20| mu0_14(null) = ^CallSideEffect : ~mu0_2
# 20| r0_15(Int32) = Constant[101] :
@ -554,7 +554,7 @@ prop.cs:
# 7| r0_3(glval<PropClass>) = InitializeThis :
# 9| r0_4(glval<Int32>) = VariableAddress[#return] :
# 9| r0_5(PropClass) = CopyValue : r0_3
# 9| r0_6(glval<Int32>) = FunctionAddress[func] :
# 9| r0_6(glval<null>) = FunctionAddress[func] :
# 9| r0_7(Int32) = Call : func:r0_6, this:r0_5
# 9| mu0_8(null) = ^CallSideEffect : ~mu0_2
# 9| mu0_9(Int32) = Store : &:r0_4, r0_7
@ -601,20 +601,20 @@ prop.cs:
# 26| mu0_2(null) = UnmodeledDefinition :
# 28| r0_3(glval<PropClass>) = VariableAddress[obj] :
# 28| r0_4(PropClass) = NewObj :
# 28| r0_5(glval<PropClass>) = FunctionAddress[PropClass] :
# 28| r0_5(glval<null>) = FunctionAddress[PropClass] :
# 28| v0_6(Void) = Call : func:r0_5, this:r0_4
# 28| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 28| mu0_8(PropClass) = Store : &:r0_3, r0_4
# 29| r0_9(glval<PropClass>) = VariableAddress[obj] :
# 29| r0_10(PropClass) = Load : &:r0_9, ~mu0_2
# 29| r0_11(glval<Int32>) = FunctionAddress[set_Prop] :
# 29| r0_11(glval<null>) = FunctionAddress[set_Prop] :
# 29| r0_12(Int32) = Constant[5] :
# 29| r0_13(Int32) = Call : func:r0_11, this:r0_10, 0:r0_12
# 29| v0_13(Void) = Call : func:r0_11, this:r0_10, 0:r0_12
# 29| mu0_14(null) = ^CallSideEffect : ~mu0_2
# 30| r0_15(glval<Int32>) = VariableAddress[x] :
# 30| r0_16(glval<PropClass>) = VariableAddress[obj] :
# 30| r0_17(PropClass) = Load : &:r0_16, ~mu0_2
# 30| r0_18(glval<Int32>) = FunctionAddress[get_Prop] :
# 30| r0_18(glval<null>) = FunctionAddress[get_Prop] :
# 30| r0_19(Int32) = Call : func:r0_18, this:r0_17
# 30| mu0_20(null) = ^CallSideEffect : ~mu0_2
# 30| r0_21(Int32) = Load : &:r0_19, ~mu0_2
@ -644,7 +644,7 @@ simple_call.cs:
# 10| mu0_2(null) = UnmodeledDefinition :
# 10| r0_3(glval<test_simple_call>) = InitializeThis :
# 12| r0_4(glval<Int32>) = VariableAddress[#return] :
# 12| r0_5(glval<Int32>) = FunctionAddress[f] :
# 12| r0_5(glval<null>) = FunctionAddress[f] :
# 12| r0_6(Int32) = Call : func:r0_5
# 12| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 12| mu0_8(Int32) = Store : &:r0_4, r0_6
@ -743,7 +743,7 @@ stmts.cs:
# 22| mu0_2(null) = UnmodeledDefinition :
# 24| r0_3(glval<Object>) = VariableAddress[caseSwitch] :
# 24| r0_4(Object) = NewObj :
# 24| r0_5(glval<Object>) = FunctionAddress[Object] :
# 24| r0_5(glval<null>) = FunctionAddress[Object] :
# 24| v0_6(Void) = Call : func:r0_5, this:r0_4
# 24| mu0_7(null) = ^CallSideEffect : ~mu0_2
# 24| mu0_8(Object) = Store : &:r0_3, r0_4
@ -829,7 +829,7 @@ stmts.cs:
# 52| Block 3
# 52| r3_0(glval<Exception>) = VariableAddress[#throw52:17] :
# 52| r3_1(Exception) = NewObj :
# 52| r3_2(glval<Exception>) = FunctionAddress[Exception] :
# 52| r3_2(glval<null>) = FunctionAddress[Exception] :
# 52| v3_3(Void) = Call : func:r3_2, this:r3_1
# 52| mu3_4(null) = ^CallSideEffect : ~mu0_2
# 52| mu3_5(Exception) = Store : &:r3_0, r3_1