mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge pull request #2017 from AndreiDiaconu1/ircsharp-various
C# IR: Some minor additions
This commit is contained in:
@@ -99,6 +99,12 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
// Ignore the expression (that is not a declaration)
|
||||
// that appears in a using block
|
||||
expr.getParent().(UsingBlockStmt).getExpr() = expr
|
||||
or
|
||||
// Ignore the `ThisAccess` when it is used as the qualifier for
|
||||
// a callable access (e.g. when a member callable is passed as a
|
||||
// parameter for a delegate creation expression)
|
||||
expr instanceof ThisAccess and
|
||||
expr.getParent() instanceof CallableAccess
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +205,10 @@ private predicate ignoreLoad(Expr expr) {
|
||||
// to get the address of the first element in an array
|
||||
expr = any(ArrayAccess aa).getQualifier()
|
||||
or
|
||||
// Indexer calls returns a reference or a value,
|
||||
// no need to load it
|
||||
expr instanceof IndexerCall
|
||||
or
|
||||
// No load is needed for the lvalue in an assignment such as:
|
||||
// Eg. `Object obj = oldObj`;
|
||||
expr = any(Assignment a).getLValue() and
|
||||
|
||||
@@ -1382,6 +1382,11 @@ class TranslatedAssignExpr extends TranslatedAssignment {
|
||||
class TranslatedAssignOperation extends TranslatedAssignment {
|
||||
override AssignOperation expr;
|
||||
|
||||
TranslatedAssignOperation() {
|
||||
// Assignments to events is handled differently
|
||||
not expr.getLValue() instanceof EventAccess
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
@@ -1893,104 +1898,6 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of a lambda expression. This initializes a temporary variable whose type is that of the lambda,
|
||||
* using the initializer list that represents the captures of the lambda.
|
||||
*/
|
||||
class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationContext {
|
||||
override LambdaExpr expr;
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override Instruction getResult() { result = this.getInstruction(LoadTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
or
|
||||
not this.hasInitializer() and result = this.getInstruction(LoadTag())
|
||||
)
|
||||
or
|
||||
tag = LoadTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = this.getInstruction(LoadTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = this.getResultType() and
|
||||
isLValue = true
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = this.getResultType() and
|
||||
isLValue = false
|
||||
or
|
||||
tag = LoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = this.getResultType() and
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
or
|
||||
tag = LoadTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
or
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = this.getEnclosingFunction().getUnmodeledDefinitionInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() or
|
||||
tag = InitializerStoreTag()
|
||||
) and
|
||||
result = this.getTempVariable(LambdaTempVar())
|
||||
}
|
||||
|
||||
override predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
tag = LambdaTempVar() and
|
||||
type = this.getResultType()
|
||||
}
|
||||
|
||||
final override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getResultType() }
|
||||
|
||||
private predicate hasInitializer() { exists(this.getInitialization()) }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr.getChild(0))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The translation of a `DelegateCall`. Since this type of call needs
|
||||
* desugaring, we treat it as a special case. The AST node of the
|
||||
@@ -2155,3 +2062,37 @@ class TranslatedDelegateCreation extends TranslatedCreation {
|
||||
|
||||
override predicate needsLoad() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of an assign operation where the lhs is an event access.
|
||||
*/
|
||||
class TranslatedEventAccess extends TranslatedNonConstantExpr {
|
||||
override AssignOperation expr;
|
||||
|
||||
TranslatedEventAccess() { expr.getLValue() instanceof EventAccess }
|
||||
|
||||
// We only translate the lhs, since the rhs is translated as part of the
|
||||
// accessor call.
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getLValue() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getLValue().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getResult() { none() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getLValue() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private TranslatedExpr getLValue() { result = getTranslatedExpr(expr.getLValue()) }
|
||||
}
|
||||
|
||||
35
csharp/ql/test/library-tests/ir/ir/events.cs
Normal file
35
csharp/ql/test/library-tests/ir/ir/events.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
class Events
|
||||
{
|
||||
public delegate string MyDel(string str);
|
||||
public MyDel Inst;
|
||||
|
||||
event MyDel MyEvent;
|
||||
|
||||
public Events()
|
||||
{
|
||||
this.Inst = new MyDel(this.Fun);
|
||||
}
|
||||
|
||||
public void AddEvent()
|
||||
{
|
||||
this.MyEvent += this.Inst;
|
||||
}
|
||||
|
||||
public void RemoveEvent()
|
||||
{
|
||||
this.MyEvent -= this.Inst;
|
||||
}
|
||||
|
||||
public string Fun(string str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Events obj = new Events();
|
||||
obj.AddEvent();
|
||||
string result = obj.MyEvent("string");
|
||||
obj.RemoveEvent();
|
||||
}
|
||||
}
|
||||
30
csharp/ql/test/library-tests/ir/ir/indexers.cs
Normal file
30
csharp/ql/test/library-tests/ir/ir/indexers.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
class Indexers
|
||||
{
|
||||
public class MyClass
|
||||
{
|
||||
public MyClass()
|
||||
{
|
||||
}
|
||||
|
||||
private string[] address = new string[2];
|
||||
public string this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return address[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
address[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
MyClass inst = new MyClass();
|
||||
inst[0] = "str1";
|
||||
inst[1] = "str1";
|
||||
inst[1] = inst[0];
|
||||
}
|
||||
}
|
||||
@@ -480,6 +480,111 @@ delegates.cs:
|
||||
# 11| v0_17(Void) = UnmodeledUse : mu*
|
||||
# 11| v0_18(Void) = ExitFunction :
|
||||
|
||||
events.cs:
|
||||
# 8| System.Void Events..ctor()
|
||||
# 8| Block 0
|
||||
# 8| v0_0(Void) = EnterFunction :
|
||||
# 8| mu0_1(null) = AliasedDefinition :
|
||||
# 8| mu0_2(null) = UnmodeledDefinition :
|
||||
# 8| r0_3(glval<Events>) = InitializeThis :
|
||||
# 10| r0_4(MyDel) = NewObj :
|
||||
# 10| r0_5(glval<null>) = FunctionAddress[MyDel] :
|
||||
# 10| r0_6(glval<MyDel>) = FunctionAddress[Fun] :
|
||||
# 10| v0_7(Void) = Call : func:r0_5, this:r0_4, 0:r0_6
|
||||
# 10| mu0_8(null) = ^CallSideEffect : ~mu0_2
|
||||
# 10| r0_9(Events) = CopyValue : r0_3
|
||||
# 10| r0_10(glval<MyDel>) = FieldAddress[Inst] : r0_9
|
||||
# 10| mu0_11(MyDel) = Store : &:r0_10, r0_4
|
||||
# 8| v0_12(Void) = ReturnVoid :
|
||||
# 8| v0_13(Void) = UnmodeledUse : mu*
|
||||
# 8| v0_14(Void) = ExitFunction :
|
||||
|
||||
# 13| System.Void Events.AddEvent()
|
||||
# 13| Block 0
|
||||
# 13| v0_0(Void) = EnterFunction :
|
||||
# 13| mu0_1(null) = AliasedDefinition :
|
||||
# 13| mu0_2(null) = UnmodeledDefinition :
|
||||
# 13| r0_3(glval<Events>) = InitializeThis :
|
||||
# 15| r0_4(Events) = CopyValue : r0_3
|
||||
# 15| r0_5(glval<null>) = FunctionAddress[add_MyEvent] :
|
||||
# 15| r0_6(Events) = CopyValue : r0_3
|
||||
# 15| r0_7(glval<MyDel>) = FieldAddress[Inst] : r0_6
|
||||
# 15| r0_8(MyDel) = Load : &:r0_7, ~mu0_2
|
||||
# 15| v0_9(Void) = Call : func:r0_5, this:r0_4, 0:r0_8
|
||||
# 15| mu0_10(null) = ^CallSideEffect : ~mu0_2
|
||||
# 13| v0_11(Void) = ReturnVoid :
|
||||
# 13| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 13| v0_13(Void) = ExitFunction :
|
||||
|
||||
# 18| System.Void Events.RemoveEvent()
|
||||
# 18| Block 0
|
||||
# 18| v0_0(Void) = EnterFunction :
|
||||
# 18| mu0_1(null) = AliasedDefinition :
|
||||
# 18| mu0_2(null) = UnmodeledDefinition :
|
||||
# 18| r0_3(glval<Events>) = InitializeThis :
|
||||
# 20| r0_4(Events) = CopyValue : r0_3
|
||||
# 20| r0_5(glval<null>) = FunctionAddress[remove_MyEvent] :
|
||||
# 20| r0_6(Events) = CopyValue : r0_3
|
||||
# 20| r0_7(glval<MyDel>) = FieldAddress[Inst] : r0_6
|
||||
# 20| r0_8(MyDel) = Load : &:r0_7, ~mu0_2
|
||||
# 20| v0_9(Void) = Call : func:r0_5, this:r0_4, 0:r0_8
|
||||
# 20| mu0_10(null) = ^CallSideEffect : ~mu0_2
|
||||
# 18| v0_11(Void) = ReturnVoid :
|
||||
# 18| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 18| v0_13(Void) = ExitFunction :
|
||||
|
||||
# 23| System.String Events.Fun(System.String)
|
||||
# 23| Block 0
|
||||
# 23| v0_0(Void) = EnterFunction :
|
||||
# 23| mu0_1(null) = AliasedDefinition :
|
||||
# 23| mu0_2(null) = UnmodeledDefinition :
|
||||
# 23| r0_3(glval<Events>) = InitializeThis :
|
||||
# 23| r0_4(glval<String>) = VariableAddress[str] :
|
||||
# 23| mu0_5(String) = InitializeParameter[str] : &:r0_4
|
||||
# 25| r0_6(glval<String>) = VariableAddress[#return] :
|
||||
# 25| r0_7(glval<String>) = VariableAddress[str] :
|
||||
# 25| r0_8(String) = Load : &:r0_7, ~mu0_2
|
||||
# 25| mu0_9(String) = Store : &:r0_6, r0_8
|
||||
# 23| r0_10(glval<String>) = VariableAddress[#return] :
|
||||
# 23| v0_11(Void) = ReturnValue : &:r0_10, ~mu0_2
|
||||
# 23| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 23| v0_13(Void) = ExitFunction :
|
||||
|
||||
# 28| System.Void Events.Main(System.String[])
|
||||
# 28| Block 0
|
||||
# 28| v0_0(Void) = EnterFunction :
|
||||
# 28| mu0_1(null) = AliasedDefinition :
|
||||
# 28| mu0_2(null) = UnmodeledDefinition :
|
||||
# 28| r0_3(glval<String[]>) = VariableAddress[args] :
|
||||
# 28| mu0_4(String[]) = InitializeParameter[args] : &:r0_3
|
||||
# 30| r0_5(glval<Events>) = VariableAddress[obj] :
|
||||
# 30| r0_6(Events) = NewObj :
|
||||
# 30| r0_7(glval<null>) = FunctionAddress[Events] :
|
||||
# 30| v0_8(Void) = Call : func:r0_7, this:r0_6
|
||||
# 30| mu0_9(null) = ^CallSideEffect : ~mu0_2
|
||||
# 30| mu0_10(Events) = Store : &:r0_5, r0_6
|
||||
# 31| r0_11(glval<Events>) = VariableAddress[obj] :
|
||||
# 31| r0_12(Events) = Load : &:r0_11, ~mu0_2
|
||||
# 31| r0_13(glval<null>) = FunctionAddress[AddEvent] :
|
||||
# 31| v0_14(Void) = Call : func:r0_13, this:r0_12
|
||||
# 31| mu0_15(null) = ^CallSideEffect : ~mu0_2
|
||||
# 32| r0_16(glval<String>) = VariableAddress[result] :
|
||||
# 32| r0_17(glval<Events>) = VariableAddress[obj] :
|
||||
# 32| r0_18(Events) = Load : &:r0_17, ~mu0_2
|
||||
# 32| r0_19(glval<null>) = FunctionAddress[Invoke] :
|
||||
# 32| r0_20(String) = StringConstant["string"] :
|
||||
# 32| v0_21(Void) = Call : func:r0_19, this:r0_18, 0:r0_20
|
||||
# 32| mu0_22(null) = ^CallSideEffect : ~mu0_2
|
||||
# 32| mu0_23(String) = Store : &:r0_16, v0_21
|
||||
# 33| r0_24(glval<Events>) = VariableAddress[obj] :
|
||||
# 33| r0_25(Events) = Load : &:r0_24, ~mu0_2
|
||||
# 33| r0_26(glval<null>) = FunctionAddress[RemoveEvent] :
|
||||
# 33| v0_27(Void) = Call : func:r0_26, this:r0_25
|
||||
# 33| mu0_28(null) = ^CallSideEffect : ~mu0_2
|
||||
# 28| v0_29(Void) = ReturnVoid :
|
||||
# 28| v0_30(Void) = UnmodeledUse : mu*
|
||||
# 28| v0_31(Void) = ExitFunction :
|
||||
|
||||
foreach.cs:
|
||||
# 4| System.Void ForEach.Main()
|
||||
# 4| Block 0
|
||||
@@ -598,6 +703,104 @@ func_with_param_call.cs:
|
||||
# 10| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 10| v0_13(Void) = ExitFunction :
|
||||
|
||||
indexers.cs:
|
||||
# 5| System.Void Indexers.MyClass..ctor()
|
||||
# 5| Block 0
|
||||
# 5| v0_0(Void) = EnterFunction :
|
||||
# 5| mu0_1(null) = AliasedDefinition :
|
||||
# 5| mu0_2(null) = UnmodeledDefinition :
|
||||
# 5| r0_3(glval<MyClass>) = InitializeThis :
|
||||
# 6| v0_4(Void) = NoOp :
|
||||
# 5| v0_5(Void) = ReturnVoid :
|
||||
# 5| v0_6(Void) = UnmodeledUse : mu*
|
||||
# 5| v0_7(Void) = ExitFunction :
|
||||
|
||||
# 12| System.String Indexers.MyClass.get_Item(System.Int32)
|
||||
# 12| Block 0
|
||||
# 12| v0_0(Void) = EnterFunction :
|
||||
# 12| mu0_1(null) = AliasedDefinition :
|
||||
# 12| mu0_2(null) = UnmodeledDefinition :
|
||||
# 12| r0_3(glval<MyClass>) = InitializeThis :
|
||||
# 10| r0_4(glval<Int32>) = VariableAddress[index] :
|
||||
# 10| mu0_5(Int32) = InitializeParameter[index] : &:r0_4
|
||||
# 14| r0_6(glval<String>) = VariableAddress[#return] :
|
||||
# 14| r0_7(MyClass) = CopyValue : r0_3
|
||||
# 14| r0_8(glval<String[]>) = FieldAddress[address] : r0_7
|
||||
# 14| r0_9(String[]) = ElementsAddress : r0_8
|
||||
# 14| r0_10(glval<Int32>) = VariableAddress[index] :
|
||||
# 14| r0_11(Int32) = Load : &:r0_10, ~mu0_2
|
||||
# 14| r0_12(String[]) = PointerAdd[8] : r0_9, r0_11
|
||||
# 14| r0_13(String) = Load : &:r0_12, ~mu0_2
|
||||
# 14| mu0_14(String) = Store : &:r0_6, r0_13
|
||||
# 12| r0_15(glval<String>) = VariableAddress[#return] :
|
||||
# 12| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2
|
||||
# 12| v0_17(Void) = UnmodeledUse : mu*
|
||||
# 12| v0_18(Void) = ExitFunction :
|
||||
|
||||
# 16| System.Void Indexers.MyClass.set_Item(System.Int32,System.String)
|
||||
# 16| Block 0
|
||||
# 16| v0_0(Void) = EnterFunction :
|
||||
# 16| mu0_1(null) = AliasedDefinition :
|
||||
# 16| mu0_2(null) = UnmodeledDefinition :
|
||||
# 16| r0_3(glval<MyClass>) = InitializeThis :
|
||||
# 10| r0_4(glval<Int32>) = VariableAddress[index] :
|
||||
# 10| mu0_5(Int32) = InitializeParameter[index] : &:r0_4
|
||||
# 16| r0_6(glval<String>) = VariableAddress[value] :
|
||||
# 16| mu0_7(String) = InitializeParameter[value] : &:r0_6
|
||||
# 18| r0_8(glval<String>) = VariableAddress[value] :
|
||||
# 18| r0_9(String) = Load : &:r0_8, ~mu0_2
|
||||
# 18| r0_10(MyClass) = CopyValue : r0_3
|
||||
# 18| r0_11(glval<String[]>) = FieldAddress[address] : r0_10
|
||||
# 18| r0_12(String[]) = ElementsAddress : r0_11
|
||||
# 18| r0_13(glval<Int32>) = VariableAddress[index] :
|
||||
# 18| r0_14(Int32) = Load : &:r0_13, ~mu0_2
|
||||
# 18| r0_15(String[]) = PointerAdd[8] : r0_12, r0_14
|
||||
# 18| mu0_16(String) = Store : &:r0_15, r0_9
|
||||
# 16| v0_17(Void) = ReturnVoid :
|
||||
# 16| v0_18(Void) = UnmodeledUse : mu*
|
||||
# 16| v0_19(Void) = ExitFunction :
|
||||
|
||||
# 23| System.Void Indexers.Main()
|
||||
# 23| Block 0
|
||||
# 23| v0_0(Void) = EnterFunction :
|
||||
# 23| mu0_1(null) = AliasedDefinition :
|
||||
# 23| mu0_2(null) = UnmodeledDefinition :
|
||||
# 25| r0_3(glval<MyClass>) = VariableAddress[inst] :
|
||||
# 25| r0_4(MyClass) = NewObj :
|
||||
# 25| r0_5(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 25| v0_6(Void) = Call : func:r0_5, this:r0_4
|
||||
# 25| mu0_7(null) = ^CallSideEffect : ~mu0_2
|
||||
# 25| mu0_8(MyClass) = Store : &:r0_3, r0_4
|
||||
# 26| r0_9(glval<MyClass>) = VariableAddress[inst] :
|
||||
# 26| r0_10(MyClass) = Load : &:r0_9, ~mu0_2
|
||||
# 26| r0_11(glval<null>) = FunctionAddress[set_Item] :
|
||||
# 26| r0_12(Int32) = Constant[0] :
|
||||
# 26| r0_13(String) = StringConstant["str1"] :
|
||||
# 26| v0_14(Void) = Call : func:r0_11, this:r0_10, 0:r0_12, 1:r0_13
|
||||
# 26| mu0_15(null) = ^CallSideEffect : ~mu0_2
|
||||
# 27| r0_16(glval<MyClass>) = VariableAddress[inst] :
|
||||
# 27| r0_17(MyClass) = Load : &:r0_16, ~mu0_2
|
||||
# 27| r0_18(glval<null>) = FunctionAddress[set_Item] :
|
||||
# 27| r0_19(Int32) = Constant[1] :
|
||||
# 27| r0_20(String) = StringConstant["str1"] :
|
||||
# 27| v0_21(Void) = Call : func:r0_18, this:r0_17, 0:r0_19, 1:r0_20
|
||||
# 27| mu0_22(null) = ^CallSideEffect : ~mu0_2
|
||||
# 28| r0_23(glval<MyClass>) = VariableAddress[inst] :
|
||||
# 28| r0_24(MyClass) = Load : &:r0_23, ~mu0_2
|
||||
# 28| r0_25(glval<null>) = FunctionAddress[set_Item] :
|
||||
# 28| r0_26(Int32) = Constant[1] :
|
||||
# 28| r0_27(glval<MyClass>) = VariableAddress[inst] :
|
||||
# 28| r0_28(MyClass) = Load : &:r0_27, ~mu0_2
|
||||
# 28| r0_29(glval<null>) = FunctionAddress[get_Item] :
|
||||
# 28| r0_30(Int32) = Constant[0] :
|
||||
# 28| r0_31(String) = Call : func:r0_29, this:r0_28, 0:r0_30
|
||||
# 28| mu0_32(null) = ^CallSideEffect : ~mu0_2
|
||||
# 28| v0_33(Void) = Call : func:r0_25, this:r0_24, 0:r0_26, 1:r0_31
|
||||
# 28| mu0_34(null) = ^CallSideEffect : ~mu0_2
|
||||
# 23| v0_35(Void) = ReturnVoid :
|
||||
# 23| v0_36(Void) = UnmodeledUse : mu*
|
||||
# 23| v0_37(Void) = ExitFunction :
|
||||
|
||||
inheritance_polymorphism.cs:
|
||||
# 3| System.Int32 A.function()
|
||||
# 3| Block 0
|
||||
|
||||
Reference in New Issue
Block a user