public override IExpression VisitCastExpression(CastExpressionSyntax node) { var o = this.semanticModel.GetTypeInfo(node); var t = this.mapper.Map(o.Type); var result = new Microsoft.Cci.MutableCodeModel.Conversion() { ValueToConvert = this.Visit(node.Expression), Type = t, TypeAfterConversion = t, }; return(result); }
private Expression ParseConversion(IOperation currentOperation) { Conversion result = new Conversion(); Expression valueToConvert = this.PopOperandStack(); result.ValueToConvert = valueToConvert; switch (currentOperation.OperationCode) { case OperationCode.Conv_R_Un: result.ValueToConvert = this.ConvertToUnsigned(valueToConvert); break; case OperationCode.Conv_Ovf_I_Un: case OperationCode.Conv_Ovf_I1_Un: case OperationCode.Conv_Ovf_I2_Un: case OperationCode.Conv_Ovf_I4_Un: case OperationCode.Conv_Ovf_I8_Un: case OperationCode.Conv_Ovf_U_Un: case OperationCode.Conv_Ovf_U1_Un: case OperationCode.Conv_Ovf_U2_Un: case OperationCode.Conv_Ovf_U4_Un: case OperationCode.Conv_Ovf_U8_Un: result.ValueToConvert = this.ConvertToUnsigned(valueToConvert); result.CheckNumericRange = true; break; case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_U: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_U8: result.CheckNumericRange = true; break; } switch (currentOperation.OperationCode) { case OperationCode.Box: ((Expression)result.ValueToConvert).Type = (ITypeReference)currentOperation.Value; var cc = result.ValueToConvert as CompileTimeConstant; if (cc != null) cc.Value = this.ConvertBoxedValue(cc.Value, cc.Type); result.TypeAfterConversion = this.platformType.SystemObject; break; case OperationCode.Castclass: result.TypeAfterConversion = (ITypeReference)currentOperation.Value; if (result.TypeAfterConversion.IsValueType) //This is not legal IL according to ECMA, but the CLR accepts it if the value to convert is a boxed value type. //Moreover, the CLR seems to leave the boxed object on the stack if the cast succeeds. result = new Conversion() { ValueToConvert = result, TypeAfterConversion = this.platformType.SystemObject }; break; case OperationCode.Conv_I: case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_I_Un: result.TypeAfterConversion = this.platformType.SystemIntPtr; break; case OperationCode.Conv_I1: case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_I1_Un: result.TypeAfterConversion = this.platformType.SystemInt8; break; case OperationCode.Conv_I2: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_I2_Un: result.TypeAfterConversion = this.platformType.SystemInt16; break; case OperationCode.Conv_I4: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_I4_Un: result.TypeAfterConversion = this.platformType.SystemInt32; break; case OperationCode.Conv_I8: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_I8_Un: result.TypeAfterConversion = this.platformType.SystemInt64; break; case OperationCode.Conv_U: case OperationCode.Conv_Ovf_U: case OperationCode.Conv_Ovf_U_Un: result.TypeAfterConversion = this.platformType.SystemUIntPtr; break; case OperationCode.Conv_U1: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_U1_Un: result.TypeAfterConversion = this.platformType.SystemUInt8; break; case OperationCode.Conv_U2: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_U2_Un: result.TypeAfterConversion = this.platformType.SystemUInt16; break; case OperationCode.Conv_U4: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_U4_Un: result.TypeAfterConversion = this.platformType.SystemUInt32; break; case OperationCode.Conv_U8: case OperationCode.Conv_Ovf_U8: case OperationCode.Conv_Ovf_U8_Un: result.TypeAfterConversion = this.platformType.SystemUInt64; break; case OperationCode.Conv_R_Un: result.TypeAfterConversion = this.platformType.SystemFloat64; break; //TODO: need a type for Float80+ case OperationCode.Conv_R4: result.TypeAfterConversion = this.platformType.SystemFloat32; break; case OperationCode.Conv_R8: result.TypeAfterConversion = this.platformType.SystemFloat64; break; case OperationCode.Unbox: result.TypeAfterConversion = Immutable.ManagedPointerType.GetManagedPointerType((ITypeReference)currentOperation.Value, this.host.InternFactory); break; case OperationCode.Unbox_Any: result.TypeAfterConversion = (ITypeReference)currentOperation.Value; break; } return result; }
private ArrayIndexer ParseArrayIndexer(IOperation currentOperation, ITypeReference elementType, bool treatArrayAsSingleDimensioned = false) { Contract.Requires(currentOperation != null); Contract.Requires(elementType != null); uint rank = 1; IArrayTypeReference/*?*/ arrayType = null; if (!treatArrayAsSingleDimensioned) //then currentOperation.Value contains the type of the array, not the type of the indexed element. arrayType = currentOperation.Value as IArrayTypeReference; if (arrayType != null) rank = arrayType.Rank; ArrayIndexer result = new ArrayIndexer(); for (uint i = 0; i < rank; i++) result.Indices.Add(this.PopOperandStack()); result.Indices.Reverse(); var indexedObject = this.PopOperandStack(); result.Type = elementType; //obtained from the instruction, but could be a lossy abstraction, or null if (arrayType == null) arrayType = indexedObject.Type as IArrayTypeReference; if (arrayType != null) //rather use its element type than the caller's element type (which is derived from the operation code). result.Type = arrayType.ElementType; else arrayType = Immutable.Vector.GetVector(elementType, this.host.InternFactory); if (!TypeHelper.TypesAreEquivalent(indexedObject.Type, arrayType)) indexedObject = new Conversion() { ValueToConvert = indexedObject, TypeAfterConversion = arrayType }; Contract.Assume(indexedObject.Type is IArrayTypeReference); result.IndexedObject = indexedObject; Contract.Assume(!(result.Type is Dummy)); return result; }
/// <summary> /// Visits the specified conversion. /// </summary> /// <param name="conversion">The conversion.</param> /// <returns></returns> protected virtual IExpression DeepCopy(Conversion conversion) { conversion.ValueToConvert = Substitute(conversion.ValueToConvert); conversion.Type = this.Substitute(conversion.Type); return conversion; }
/// <summary> /// Visits the specified conversion. /// </summary> /// <param name="conversion">The conversion.</param> public override void Visit(IConversion conversion) { Conversion mutableConversion = new Conversion(conversion); this.resultExpression = this.myCodeCopier.DeepCopy(mutableConversion); }
public override IExpression Visit(IExpression expression) { var convertToUnsigned = expression as ConvertToUnsigned; if (convertToUnsigned != null) expression = new Conversion(convertToUnsigned); return base.Visit(expression); }
public override IExpression Visit(Conversion conversion) { conversion.ValueToConvert = this.Visit(conversion.ValueToConvert); if (TypeHelper.TypesAreEquivalent(conversion.TypeAfterConversion, conversion.ValueToConvert.Type) && // converting a floating point number to the same floating point number is not a nop: it might result in precision loss. !(conversion.TypeAfterConversion.TypeCode == PrimitiveTypeCode.Float32 || conversion.TypeAfterConversion.TypeCode == PrimitiveTypeCode.Float64) ) return conversion.ValueToConvert; else { var cc = conversion.ValueToConvert as CompileTimeConstant; if (cc != null) { if (cc.Value == null) { cc.Type = conversion.TypeAfterConversion; return cc; } if (conversion.TypeAfterConversion.TypeCode == PrimitiveTypeCode.Boolean && conversion.ValueToConvert.Type.TypeCode == PrimitiveTypeCode.Int32 && cc.Value is int) { var bcc = new CompileTimeConstant(); bcc.Value = ((int)cc.Value) != 0; bcc.Type = conversion.TypeAfterConversion; return bcc; } if (conversion.TypeAfterConversion.TypeCode == PrimitiveTypeCode.Char && conversion.ValueToConvert.Type.TypeCode == PrimitiveTypeCode.Int32 && cc.Value is int) { var bcc = new CompileTimeConstant(); bcc.Value = (char)(int)cc.Value; bcc.Type = conversion.TypeAfterConversion; return bcc; } } else if (conversion.TypeAfterConversion.TypeCode == PrimitiveTypeCode.Boolean) { var conditional = conversion.ValueToConvert as Conditional; if (conditional != null) { conditional.ResultIfFalse = this.ConvertToBoolean(conditional.ResultIfFalse); conditional.ResultIfTrue = this.ConvertToBoolean(conditional.ResultIfTrue); conditional.Type = conversion.TypeAfterConversion; return conditional; } } return conversion; } }
/// <summary> /// Create two properties: object Current and T Current as the closure class implements both the /// generic and non-generic version of ienumerator. /// /// Current Implementation generates getters, but not the property. /// </summary> /// <param name="iteratorClosure">Information about the closure created when compiling the current iterator method</param> private void CreateIteratorClosureProperties(IteratorClosureInformation iteratorClosure) { // Non-generic version of the get_Current, which returns the generic version of get_Current. MethodDefinition getterNonGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.IEnumerator.get_Current") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute(); debuggerHiddenAttribute.Constructor = this.DebuggerHiddenCtor; getterNonGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterNonGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterNonGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterNonGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterNonGenericCurrent.Type = this.host.PlatformType.SystemObject; getterNonGenericCurrent.IsSpecialName = true; getterNonGenericCurrent.IsVirtual = true; getterNonGenericCurrent.IsNewSlot = true; getterNonGenericCurrent.IsHiddenBySignature = true; getterNonGenericCurrent.IsSealed = true; iteratorClosure.NonGenericGetCurrent = getterNonGenericCurrent; IMethodReference originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } // assert originalMethod != Dummy MethodImplementation getterImplementation = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterNonGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation); List<IStatement> statements = new List<IStatement>(); IFieldReference currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurr = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; IExpression returnExpression; if (!iteratorClosure.ElementType.IsValueType && TypeHelper.TypesAreAssignmentCompatible(iteratorClosure.ElementType.ResolvedType, this.host.PlatformType.SystemObject.ResolvedType)) { returnExpression = thisDotCurr; } else { Conversion convertion = new Conversion() { CheckNumericRange = false, Type = this.host.PlatformType.SystemObject, TypeAfterConversion = getterNonGenericCurrent.Type, ValueToConvert = thisDotCurr }; returnExpression = convertion; } ReturnStatement returnCurrent = new ReturnStatement() { Expression = returnExpression, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.IsNormalized = true; body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterNonGenericCurrent; getterNonGenericCurrent.Body = body; // Create generic version of get_Current, the body of which is simply returning this.current. MethodDefinition getterGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.Generic.IEnumerator<" + iteratorClosure.ElementType.ToString() +">.get_Current") }; getterGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterGenericCurrent.Type = iteratorClosure.ElementType; getterGenericCurrent.IsSpecialName = true; getterGenericCurrent.IsVirtual = true; getterGenericCurrent.IsNewSlot = true; getterGenericCurrent.IsHiddenBySignature = true; getterGenericCurrent.IsSealed = true; iteratorClosure.GenericGetCurrent = getterGenericCurrent; originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.GenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } MethodImplementation getterImplementation2 = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation2); statements = new List<IStatement>(); currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurrent = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; returnCurrent = new ReturnStatement() { Expression = thisDotCurrent, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); block = new BlockStatement() { Statements = statements }; body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterGenericCurrent; getterGenericCurrent.Body = body; }
/// <summary> /// Rewrites the children of the given conversion expression. /// </summary> public virtual void RewriteChildren(Conversion conversion) { this.RewriteChildren((Expression)conversion); conversion.ValueToConvert = this.Rewrite(conversion.ValueToConvert); conversion.TypeAfterConversion = this.Rewrite(conversion.TypeAfterConversion); }
/// <summary> /// Visits the specified conversion. /// </summary> /// <param name="conversion">The conversion.</param> public override void Visit(IConversion conversion) { Conversion mutableConversion = conversion as Conversion; if (alwaysMakeACopy || mutableConversion == null) mutableConversion = new Conversion(conversion); this.resultExpression = this.myCodeMutator.Visit(mutableConversion); }
/// <summary> /// Visits the specified conversion. /// </summary> /// <param name="conversion">The conversion.</param> /// <returns></returns> public virtual IExpression Visit(Conversion conversion) { conversion.ValueToConvert = Visit(conversion.ValueToConvert); conversion.TypeAfterConversion = this.Visit(conversion.TypeAfterConversion); return conversion; }