public Binary.PredefinedOperator[] GetPredefinedEnumAritmeticOperators(TypeSpec enumType, bool nullable) { TypeSpec underlying; Binary.Operator mask = 0; if (nullable) { underlying = Nullable.NullableInfo.GetEnumUnderlyingType(this, enumType); mask = Binary.Operator.NullableMask; } else { underlying = EnumSpec.GetUnderlyingType(enumType); } var operators = new[] { new Binary.PredefinedOperator(enumType, underlying, mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType), new Binary.PredefinedOperator(underlying, enumType, mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType), new Binary.PredefinedOperator(enumType, mask | Binary.Operator.SubtractionMask, underlying) }; return(operators); }
// // The stack contains the pointer and the value of type `type' // public void EmitStoreFromPtr(TypeSpec type) { if (type.IsEnum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Int: case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Stind_I4); return; case BuiltinTypeSpec.Type.Long: case BuiltinTypeSpec.Type.ULong: ig.Emit(OpCodes.Stind_I8); return; case BuiltinTypeSpec.Type.Char: case BuiltinTypeSpec.Type.Short: case BuiltinTypeSpec.Type.UShort: ig.Emit(OpCodes.Stind_I2); return; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Stind_R4); return; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Stind_R8); return; case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: ig.Emit(OpCodes.Stind_I1); return; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Stind_I); return; } if (type.IsStruct || TypeManager.IsGenericParameter(type)) { Emit(OpCodes.Stobj, type); } else { ig.Emit(OpCodes.Stind_Ref); } }
bool CanBeVolatile() { switch (MemberType.BuiltinType) { case BuiltinTypeSpec.Type.Bool: case BuiltinTypeSpec.Type.Char: case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.Short: case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Int: case BuiltinTypeSpec.Type.UInt: case BuiltinTypeSpec.Type.Float: case BuiltinTypeSpec.Type.UIntPtr: case BuiltinTypeSpec.Type.IntPtr: return(true); } if (TypeSpec.IsReferenceType(MemberType)) { return(true); } if (MemberType.IsPointer) { return(true); } if (MemberType.IsEnum) { switch (EnumSpec.GetUnderlyingType(MemberType).BuiltinType) { case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.Short: case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Int: case BuiltinTypeSpec.Type.UInt: return(true); default: return(false); } } return(false); }
// // The stack contains the pointer and the value of type `type' // public void EmitStoreFromPtr(TypeSpec type) { if (type.IsEnum) { type = EnumSpec.GetUnderlyingType(type); } if (type == TypeManager.int32_type || type == TypeManager.uint32_type) { ig.Emit(OpCodes.Stind_I4); } else if (type == TypeManager.int64_type || type == TypeManager.uint64_type) { ig.Emit(OpCodes.Stind_I8); } else if (type == TypeManager.char_type || type == TypeManager.short_type || type == TypeManager.ushort_type) { ig.Emit(OpCodes.Stind_I2); } else if (type == TypeManager.float_type) { ig.Emit(OpCodes.Stind_R4); } else if (type == TypeManager.double_type) { ig.Emit(OpCodes.Stind_R8); } else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || type == TypeManager.bool_type) { ig.Emit(OpCodes.Stind_I1); } else if (type == TypeManager.intptr_type) { ig.Emit(OpCodes.Stind_I); } else if (TypeManager.IsStruct(type) || TypeManager.IsGenericParameter(type)) { Emit(OpCodes.Stobj, type); } else { ig.Emit(OpCodes.Stind_Ref); } }
public override Constant ConvertImplicitly(TypeSpec type) { // // The 0 literal can be converted to an enum value // if (Value == 0 && type.IsEnum) { Constant c = ConvertImplicitly(EnumSpec.GetUnderlyingType(type)); if (c == null) { return(null); } return(new EnumConstant(c, type)); } return(base.ConvertImplicitly(type)); }
public override Constant ConvertImplicitly(TypeSpec type, ResolveContext opt_ec, bool upconvert_only = false) { // // The 0 literal can be converted to an enum value // if (Value == 0 && type.IsEnum) { Constant c = ConvertImplicitly(EnumSpec.GetUnderlyingType(type), opt_ec, upconvert_only); if (c == null) { return(null); } return(new EnumConstant(c, type)); } return(base.ConvertImplicitly(type, opt_ec, upconvert_only)); }
public override Constant ConvertImplicitly(ResolveContext rc, TypeSpec type) { // // The 0 literal can be converted to an enum value // if (Value == 0 && TypeManager.IsEnumType(type)) { Constant c = ConvertImplicitly(rc, EnumSpec.GetUnderlyingType(type)); if (c == null) { return(null); } return(new EnumConstant(c, type).Resolve(rc)); } return(base.ConvertImplicitly(rc, type)); }
// // The stack contains the pointer and the value of type `type' // public void EmitStoreFromPtr(TypeSpec type) { if (type.IsEnum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Int: case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Stind_I4); return; case BuiltinTypeSpec.Type.Long: case BuiltinTypeSpec.Type.ULong: ig.Emit(OpCodes.Stind_I8); return; case BuiltinTypeSpec.Type.Char: case BuiltinTypeSpec.Type.Short: case BuiltinTypeSpec.Type.UShort: ig.Emit(OpCodes.Stind_I2); return; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Stind_R4); return; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Stind_R8); return; case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: ig.Emit(OpCodes.Stind_I1); return; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Stind_I); return; } switch (type.Kind) { case MemberKind.Struct: case MemberKind.TypeParameter: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Stobj, type.GetMetaInfo()); break; default: ig.Emit(OpCodes.Stind_Ref); break; } }
// // Emits the right opcode to store to an array // public void EmitArrayStore(ArrayContainer ac) { if (ac.Rank > 1) { if (IsAnonymousStoreyMutateRequired) { ac = (ArrayContainer)ac.Mutate(CurrentAnonymousMethod.Storey.Mutator); } ig.Emit(OpCodes.Call, ac.GetSetMethod()); return; } var type = ac.Element; if (type.Kind == MemberKind.Enum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: Emit(OpCodes.Stelem_I1); return; case BuiltinTypeSpec.Type.Short: case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: Emit(OpCodes.Stelem_I2); return; case BuiltinTypeSpec.Type.Int: case BuiltinTypeSpec.Type.UInt: Emit(OpCodes.Stelem_I4); return; case BuiltinTypeSpec.Type.Long: case BuiltinTypeSpec.Type.ULong: Emit(OpCodes.Stelem_I8); return; case BuiltinTypeSpec.Type.Float: Emit(OpCodes.Stelem_R4); return; case BuiltinTypeSpec.Type.Double: Emit(OpCodes.Stelem_R8); return; } switch (type.Kind) { case MemberKind.Struct: Emit(OpCodes.Stobj, type); break; case MemberKind.TypeParameter: Emit(OpCodes.Stelem, type); break; case MemberKind.PointerType: Emit(OpCodes.Stelem_I); break; default: Emit(OpCodes.Stelem_Ref); break; } }
// // Emits the right opcode to load from an array // public void EmitArrayLoad(ArrayContainer ac) { if (ac.Rank > 1) { if (IsAnonymousStoreyMutateRequired) { ac = (ArrayContainer)ac.Mutate(CurrentAnonymousMethod.Storey.Mutator); } ig.Emit(OpCodes.Call, ac.GetGetMethod()); return; } var type = ac.Element; if (type.Kind == MemberKind.Enum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Bool: // // bool array can actually store any byte value in underlying byte slot // and C# spec does not specify any normalization rule, except the result // is undefined // case BuiltinTypeSpec.Type.Byte: ig.Emit(OpCodes.Ldelem_U1); break; case BuiltinTypeSpec.Type.SByte: ig.Emit(OpCodes.Ldelem_I1); break; case BuiltinTypeSpec.Type.Short: ig.Emit(OpCodes.Ldelem_I2); break; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: ig.Emit(OpCodes.Ldelem_U2); break; case BuiltinTypeSpec.Type.Int: ig.Emit(OpCodes.Ldelem_I4); break; case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Ldelem_U4); break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: ig.Emit(OpCodes.Ldelem_I8); break; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Ldelem_R4); break; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Ldelem_R8); break; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Ldelem_I); break; default: switch (type.Kind) { case MemberKind.Struct: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Ldelema, type.GetMetaInfo()); ig.Emit(OpCodes.Ldobj, type.GetMetaInfo()); break; case MemberKind.TypeParameter: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Ldelem, type.GetMetaInfo()); break; case MemberKind.PointerType: ig.Emit(OpCodes.Ldelem_I); break; default: ig.Emit(OpCodes.Ldelem_Ref); break; } break; } }
// // Emits the right opcode to load from an array // public void EmitArrayLoad(ArrayContainer ac) { if (ac.Rank > 1) { if (IsAnonymousStoreyMutateRequired) { ac = (ArrayContainer)ac.Mutate(CurrentAnonymousMethod.Storey.Mutator); } ig.Emit(OpCodes.Call, ac.GetGetMethod()); return; } var type = ac.Element; if (type.Kind == MemberKind.Enum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Bool: // // Workaround MSIL limitation. Load bool element as single bit, // bool array can actually store any byte value // ig.Emit(OpCodes.Ldelem_U1); ig.Emit(OpCodes.Ldc_I4_0); ig.Emit(OpCodes.Cgt_Un); break; case BuiltinTypeSpec.Type.Byte: ig.Emit(OpCodes.Ldelem_U1); break; case BuiltinTypeSpec.Type.SByte: ig.Emit(OpCodes.Ldelem_I1); break; case BuiltinTypeSpec.Type.Short: ig.Emit(OpCodes.Ldelem_I2); break; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: ig.Emit(OpCodes.Ldelem_U2); break; case BuiltinTypeSpec.Type.Int: ig.Emit(OpCodes.Ldelem_I4); break; case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Ldelem_U4); break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: ig.Emit(OpCodes.Ldelem_I8); break; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Ldelem_R4); break; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Ldelem_R8); break; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Ldelem_I); break; default: switch (type.Kind) { case MemberKind.Struct: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Ldelema, type.GetMetaInfo()); ig.Emit(OpCodes.Ldobj, type.GetMetaInfo()); break; case MemberKind.TypeParameter: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Ldelem, type.GetMetaInfo()); break; case MemberKind.PointerType: ig.Emit(OpCodes.Ldelem_I); break; default: ig.Emit(OpCodes.Ldelem_Ref); break; } break; } }
// // Load the object from the pointer. // public void EmitLoadFromPtr(TypeSpec type) { if (type.Kind == MemberKind.Enum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Int: ig.Emit(OpCodes.Ldind_I4); return; case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Ldind_U4); return; case BuiltinTypeSpec.Type.Short: ig.Emit(OpCodes.Ldind_I2); return; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: ig.Emit(OpCodes.Ldind_U2); return; case BuiltinTypeSpec.Type.Byte: ig.Emit(OpCodes.Ldind_U1); return; case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: ig.Emit(OpCodes.Ldind_I1); return; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: ig.Emit(OpCodes.Ldind_I8); return; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Ldind_R4); return; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Ldind_R8); return; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Ldind_I); return; } switch (type.Kind) { case MemberKind.Struct: case MemberKind.TypeParameter: Emit(OpCodes.Ldobj, type); break; case MemberKind.PointerType: ig.Emit(OpCodes.Ldind_I); break; default: ig.Emit(OpCodes.Ldind_Ref); break; } }
// // Load the object from the pointer. // public void EmitLoadFromPtr(TypeSpec t) { if (t == TypeManager.int32_type) { ig.Emit(OpCodes.Ldind_I4); } else if (t == TypeManager.uint32_type) { ig.Emit(OpCodes.Ldind_U4); } else if (t == TypeManager.short_type) { ig.Emit(OpCodes.Ldind_I2); } else if (t == TypeManager.ushort_type) { ig.Emit(OpCodes.Ldind_U2); } else if (t == TypeManager.char_type) { ig.Emit(OpCodes.Ldind_U2); } else if (t == TypeManager.byte_type) { ig.Emit(OpCodes.Ldind_U1); } else if (t == TypeManager.sbyte_type) { ig.Emit(OpCodes.Ldind_I1); } else if (t == TypeManager.uint64_type) { ig.Emit(OpCodes.Ldind_I8); } else if (t == TypeManager.int64_type) { ig.Emit(OpCodes.Ldind_I8); } else if (t == TypeManager.float_type) { ig.Emit(OpCodes.Ldind_R4); } else if (t == TypeManager.double_type) { ig.Emit(OpCodes.Ldind_R8); } else if (t == TypeManager.bool_type) { ig.Emit(OpCodes.Ldind_I1); } else if (t == TypeManager.intptr_type) { ig.Emit(OpCodes.Ldind_I); } else if (t.IsEnum) { if (t == TypeManager.enum_type) { ig.Emit(OpCodes.Ldind_Ref); } else { EmitLoadFromPtr(EnumSpec.GetUnderlyingType(t)); } } else if (TypeManager.IsStruct(t) || TypeManager.IsGenericParameter(t)) { Emit(OpCodes.Ldobj, t); } else if (t.IsPointer) { ig.Emit(OpCodes.Ldind_I); } else { ig.Emit(OpCodes.Ldind_Ref); } }
// // Emits the right opcode to store to an array // public void EmitArrayStore(ArrayContainer ac) { if (ac.Rank > 1) { if (IsAnonymousStoreyMutateRequired) { ac = (ArrayContainer)ac.Mutate(CurrentAnonymousMethod.Storey.Mutator); } ig.Emit(OpCodes.Call, ac.GetSetMethod()); return; } var type = ac.Element; if (type.IsEnum) { type = EnumSpec.GetUnderlyingType(type); } if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || type == TypeManager.bool_type) { Emit(OpCodes.Stelem_I1); } else if (type == TypeManager.short_type || type == TypeManager.ushort_type || type == TypeManager.char_type) { Emit(OpCodes.Stelem_I2); } else if (type == TypeManager.int32_type || type == TypeManager.uint32_type) { Emit(OpCodes.Stelem_I4); } else if (type == TypeManager.int64_type || type == TypeManager.uint64_type) { Emit(OpCodes.Stelem_I8); } else if (type == TypeManager.float_type) { Emit(OpCodes.Stelem_R4); } else if (type == TypeManager.double_type) { Emit(OpCodes.Stelem_R8); } else if (type == TypeManager.intptr_type) { Emit(OpCodes.Stobj, type); } else if (TypeManager.IsStruct(type)) { Emit(OpCodes.Stobj, type); } else if (type.IsGenericParameter) { Emit(OpCodes.Stelem, type); } else if (type.IsPointer) { Emit(OpCodes.Stelem_I); } else { Emit(OpCodes.Stelem_Ref); } }
// // Load the object from the pointer. // public void EmitLoadFromPtr(TypeSpec type) { if (type.Kind == MemberKind.Enum) { type = EnumSpec.GetUnderlyingType(type); } switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Int: ig.Emit(OpCodes.Ldind_I4); break; case BuiltinTypeSpec.Type.UInt: ig.Emit(OpCodes.Ldind_U4); break; case BuiltinTypeSpec.Type.Short: ig.Emit(OpCodes.Ldind_I2); break; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: ig.Emit(OpCodes.Ldind_U2); break; case BuiltinTypeSpec.Type.Byte: ig.Emit(OpCodes.Ldind_U1); break; case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: ig.Emit(OpCodes.Ldind_I1); break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: ig.Emit(OpCodes.Ldind_I8); break; case BuiltinTypeSpec.Type.Float: ig.Emit(OpCodes.Ldind_R4); break; case BuiltinTypeSpec.Type.Double: ig.Emit(OpCodes.Ldind_R8); break; case BuiltinTypeSpec.Type.IntPtr: ig.Emit(OpCodes.Ldind_I); break; default: switch (type.Kind) { case MemberKind.Struct: case MemberKind.TypeParameter: if (IsAnonymousStoreyMutateRequired) { type = CurrentAnonymousMethod.Storey.Mutator.Mutate(type); } ig.Emit(OpCodes.Ldobj, type.GetMetaInfo()); break; case MemberKind.PointerType: ig.Emit(OpCodes.Ldind_I); break; default: ig.Emit(OpCodes.Ldind_Ref); break; } break; } if (TrackStackTypes) { // TODO: test for async when `this' can be used inside structs SetStackType(type); } }