private Statement ParseAssignment(IOperation currentOperation) { TargetExpression target = new TargetExpression(); ITypeReference/*?*/ elementType = null; target.Alignment = this.alignment; target.Definition = currentOperation.Value; target.IsVolatile = this.sawVolatile; Assignment assignment = new Assignment(); assignment.Target = target; assignment.Source = this.PopOperandStack(); ExpressionStatement result = new ExpressionStatement(); result.Expression = assignment; switch (currentOperation.OperationCode) { case OperationCode.Stfld: target.Instance = this.PopOperandStack(); break; case OperationCode.Stelem: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation); target.Definition = indexer; target.Instance = indexer.IndexedObject; break; case OperationCode.Stind_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_Ref: case OperationCode.Stobj: AddressDereference addressDereference = new AddressDereference(); addressDereference.Address = this.PopOperandStack(); addressDereference.Alignment = this.alignment; addressDereference.IsVolatile = this.sawVolatile; //capture the element type. The pointer might be untyped, in which case the instruction is the only point where the element type is known. if (elementType != null) addressDereference.Type = elementType; //else: The type inferencer will fill in the type once the pointer type is known. target.Definition = addressDereference; break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: var local = this.GetLocalWithSourceName((ILocalDefinition)target.Definition); target.Definition = local; this.numberOfAssignments[local] = this.numberOfAssignments.ContainsKey(local) ? this.numberOfAssignments[local] + 1 : 1; break; } this.alignment = 0; this.sawVolatile = false; return result; }
private Expression ParseCopyObject() { AddressDereference source = new AddressDereference(); source.Address = this.PopOperandStack(); AddressDereference addressDeref = new AddressDereference(); addressDeref.Address = this.PopOperandStack(); TargetExpression target = new TargetExpression(); target.Definition = addressDeref; Assignment result = new Assignment(); result.Source = source; result.Target = target; return result; }
private Expression ParseAddressDereference(IOperation currentOperation) { ITypeReference elementType = null; switch (currentOperation.OperationCode) { case OperationCode.Ldind_I: elementType = this.platformType.SystemIntPtr; break; case OperationCode.Ldind_I1: elementType = this.platformType.SystemInt8; break; case OperationCode.Ldind_I2: elementType = this.platformType.SystemInt16; break; case OperationCode.Ldind_I4: elementType = this.platformType.SystemInt32; break; case OperationCode.Ldind_I8: elementType = this.platformType.SystemInt64; break; case OperationCode.Ldind_R4: elementType = this.platformType.SystemFloat32; break; case OperationCode.Ldind_R8: elementType = this.platformType.SystemFloat64; break; case OperationCode.Ldind_U1: elementType = this.platformType.SystemUInt8; break; case OperationCode.Ldind_U2: elementType = this.platformType.SystemUInt16; break; case OperationCode.Ldind_U4: elementType = this.platformType.SystemUInt32; break; } AddressDereference result = new AddressDereference(); result.Address = this.PopOperandStack(); result.Alignment = this.alignment; result.IsVolatile = this.sawVolatile; //Capture the element type. The pointer might be untyped, in which case the instruction is the only point where the element type is known. if (elementType != null) result.Type = elementType; //else: The type inferencer will fill in the type once the pointer type is known. this.alignment = 0; this.sawVolatile = false; return result; }
private Expression ParseAddressDereference(IOperation currentOperation) { Contract.Requires(currentOperation != null); AddressDereference result = new AddressDereference(); result.Address = this.PopOperandStack(); result.Alignment = this.alignment; result.IsVolatile = this.sawVolatile; this.alignment = 0; this.sawVolatile = false; return result; }
private Statement ParseAssignment(IOperation currentOperation) { Contract.Requires(currentOperation != null); TargetExpression target = new TargetExpression(); ITypeReference/*?*/ elementType = null; if (this.alignment > 0) { Contract.Assume(this.alignment == 1 || this.alignment == 2 || this.alignment == 4); target.Alignment = this.alignment; } target.IsVolatile = this.sawVolatile; Assignment assignment = new Assignment(); assignment.Target = target; assignment.Source = this.PopOperandStack(); ExpressionStatement result = new ExpressionStatement(); result.Expression = assignment; switch (currentOperation.OperationCode) { case OperationCode.Starg: case OperationCode.Starg_S: { var definition = currentOperation.Value; if (definition == null) { target.Definition = new ThisReference(); var typeForThis = (INamedTypeDefinition)this.MethodDefinition.ContainingTypeDefinition; if (typeForThis.IsValueType) target.Type = Immutable.ManagedPointerType.GetManagedPointerType(Microsoft.Cci.MutableCodeModel.NamedTypeDefinition.SelfInstance(typeForThis, this.host.InternFactory), this.host.InternFactory); else target.Type = NamedTypeDefinition.SelfInstance(typeForThis, this.host.InternFactory); } else { var par = definition as IParameterDefinition; Contract.Assume(par != null); target.Definition = definition; target.Type = par.Type; } break; } case OperationCode.Stfld: target.Instance = this.PopOperandStack(); goto case OperationCode.Stsfld; case OperationCode.Stsfld: Contract.Assume(currentOperation.Value is IFieldReference); var field = (IFieldReference)currentOperation.Value; target.Definition = field; target.Type = field.Type; break; case OperationCode.Stelem: elementType = (ITypeReference)currentOperation.Value; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_Ref: ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation, elementType??this.platformType.SystemObject, treatArrayAsSingleDimensioned: true); target.Definition = indexer; target.Instance = indexer.IndexedObject; target.Type = indexer.Type; break; case OperationCode.Stind_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stind_Ref; case OperationCode.Stobj: elementType = (ITypeReference)currentOperation.Value; goto case OperationCode.Stind_Ref; case OperationCode.Stind_Ref: AddressDereference addressDereference = new AddressDereference(); addressDereference.Address = this.PopOperandStack(); addressDereference.Alignment = this.alignment; addressDereference.IsVolatile = this.sawVolatile; target.Definition = addressDereference; var pointerType = addressDereference.Address.Type as IPointerTypeReference; if (pointerType != null) addressDereference.Type = pointerType.TargetType; else { var managedPointerType = addressDereference.Address.Type as IManagedPointerTypeReference; if (managedPointerType != null) addressDereference.Type = managedPointerType.TargetType; else { //The pointer itself is untyped, so the instruction must have specified the element type addressDereference.Type = elementType??this.platformType.SystemObject; } } target.Type = addressDereference.Type; break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: Contract.Assume(currentOperation.Value is ILocalDefinition); var local = this.GetLocalWithSourceName((ILocalDefinition)currentOperation.Value); target.Definition = local; this.numberOfAssignmentsToLocal[local] = this.numberOfAssignmentsToLocal.ContainsKey(local) ? this.numberOfAssignmentsToLocal[local] + 1 : 1; target.Type = local.Type; break; default: { var definition = currentOperation.Value; Contract.Assume(definition is ILocalDefinition || definition is IParameterDefinition || definition is IFieldReference || definition is IArrayIndexer || definition is IAddressDereference || definition is IPropertyDefinition); target.Definition = definition; break; } } assignment.Source = TypeInferencer.Convert(assignment.Source, target.Type); //mainly to convert (u)ints to bools, chars and pointers. assignment.Type = target.Type; Contract.Assume(assignment.Target.Type.TypeCode != PrimitiveTypeCode.Boolean || assignment.Source.Type.TypeCode == PrimitiveTypeCode.Boolean || IsByRef(assignment.Target.Definition)); this.alignment = 0; this.sawVolatile = false; return result; }
/// <summary> /// Visits the specified address dereference. /// </summary> /// <param name="addressDereference">The address dereference.</param> /// <returns></returns> protected virtual IExpression DeepCopy(AddressDereference addressDereference) { addressDereference.Address = this.Substitute(addressDereference.Address); addressDereference.Type = this.Substitute(addressDereference.Type); return addressDereference; }
private Statement ParseInitObject(IOperation currentOperation) { Contract.Requires(currentOperation != null); Contract.Assume(currentOperation.Value is ITypeReference); var objectType = (ITypeReference)currentOperation.Value; Assignment assignment = new Assignment(); var addressDeref = new AddressDereference() { Address = this.PopOperandStack(), Type = objectType }; assignment.Target = new TargetExpression() { Definition = addressDeref, Type = objectType }; assignment.Source = new DefaultValue() { DefaultValueType = (ITypeReference)currentOperation.Value, Type = objectType }; assignment.Type = objectType; return new ExpressionStatement() { Expression = assignment }; }
/// <summary> /// Visits the specified address dereference. /// </summary> /// <param name="addressDereference">The address dereference.</param> public override void Visit(IAddressDereference addressDereference) { AddressDereference mutableAddressDereference = new AddressDereference(addressDereference); this.resultExpression = this.myCodeCopier.DeepCopy(mutableAddressDereference); }
/// <summary> /// Create the new body of the iterator method. /// </summary> /// <remarks> /// Pseudo code: /// iteratorClosureLocal = new Closure(0); /// iteratorClosureLocal.field = parameter; // for each parameter including this. /// return iteratorClosureLocal; /// </remarks> private BlockStatement CreateNewIteratorMethodBody(IteratorClosureInformation iteratorClosure) { BlockStatement result = new BlockStatement(); // iteratorClosureLocal = new IteratorClosure(0); LocalDefinition localDefinition = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("iteratorClosureLocal"), Type = GetClosureTypeReferenceFromIterator(iteratorClosure), }; CreateObjectInstance createObjectInstance = new CreateObjectInstance() { MethodToCall = GetMethodReference(iteratorClosure, iteratorClosure.Constructor), Type = localDefinition.Type }; // the start state depends on whether the iterator is an IEnumerable or an IEnumerator. For the former, // it must be created in state -2. Then it is the GetEnumerator method that puts it into its // "start" state, i.e., state 0. var startState = this.isEnumerable ? -2 : 0; createObjectInstance.Arguments.Add(new CompileTimeConstant() { Value = startState, Type = this.host.PlatformType.SystemInt32 }); LocalDeclarationStatement localDeclarationStatement = new LocalDeclarationStatement() { InitialValue = createObjectInstance, LocalVariable = localDefinition }; result.Statements.Add(localDeclarationStatement); // Generate assignments to closure instance's fields for each of the parameters captured by the closure. foreach (object capturedLocalOrParameter in FieldForCapturedLocalOrParameter.Keys) { BoundField boundField = FieldForCapturedLocalOrParameter[capturedLocalOrParameter]; Assignment assignment; ITypeReference localOrParameterType = GetLocalOrParameterType(capturedLocalOrParameter); if (capturedLocalOrParameter is ILocalDefinition) continue; if (capturedLocalOrParameter is IThisReference) { var thisR = new ThisReference(); IExpression thisValue = thisR; if (!this.method.ContainingTypeDefinition.IsClass) { thisValue = new AddressDereference() { Address = thisR, Type = this.method.ContainingTypeDefinition.IsGeneric ? (ITypeReference)this.method.ContainingTypeDefinition.InstanceType : (ITypeReference)this.method.ContainingTypeDefinition }; } assignment = new Assignment { Source = thisValue, Type = this.method.ContainingType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = this.method.ContainingType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } else { assignment = new Assignment { Source = new BoundExpression() { Definition = capturedLocalOrParameter, Instance = null, IsVolatile = false, Type = localOrParameterType }, Type = localOrParameterType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = localOrParameterType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } ExpressionStatement expressionStatement = new ExpressionStatement() { Expression = assignment }; result.Statements.Add(expressionStatement); } // Generate: return iteratorClosureLocal; result.Statements.Add(new ReturnStatement() { Expression = new BoundExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type } }); return result; }
/// <summary> /// Rewrites the children of the given address dereference expression. /// </summary> /// <param name="addressDereference"></param> public virtual void RewriteChildren(AddressDereference addressDereference) { this.RewriteChildren((Expression)addressDereference); addressDereference.Address = this.Rewrite(addressDereference.Address); }
/// <summary> /// Visits the specified address dereference. /// </summary> /// <param name="addressDereference">The address dereference.</param> public override void Visit(IAddressDereference addressDereference) { AddressDereference mutableAddressDereference = addressDereference as AddressDereference; if (alwaysMakeACopy || mutableAddressDereference == null) mutableAddressDereference = new AddressDereference(addressDereference); this.resultExpression = this.myCodeMutator.Visit(mutableAddressDereference); }
/// <summary> /// Visits the specified address dereference. /// </summary> /// <param name="addressDereference">The address dereference.</param> /// <returns></returns> public virtual IExpression Visit(AddressDereference addressDereference) { addressDereference.Address = this.Visit(addressDereference.Address); addressDereference.Type = this.Visit(addressDereference.Type); return addressDereference; }