// <summary>
		//   This routine will attempt to simplify the unary expression when the
		//   argument is a constant.
		// </summary>
		Constant TryReduceConstant (ResolveContext ec, Constant e)
		{
			if (e is EmptyConstantCast)
				return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
			
			if (e is SideEffectConstant) {
				Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
				return r == null ? null : new SideEffectConstant (r, e, r.Location);
			}

			Type expr_type = e.Type;
			
			switch (Oper){
			case Operator.UnaryPlus:
				// Unary numeric promotions
				if (expr_type == TypeManager.byte_type)
					return new IntConstant (((ByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.sbyte_type)
					return new IntConstant (((SByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.short_type)
					return new IntConstant (((ShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.ushort_type)
					return new IntConstant (((UShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.char_type)
					return new IntConstant (((CharConstant)e).Value, e.Location);
				
				// Predefined operators
				if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
				    expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
				    expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
				    expr_type == TypeManager.decimal_type) {
					return e;
				}
				
				return null;
				
			case Operator.UnaryNegation:
				// Unary numeric promotions
				if (expr_type == TypeManager.byte_type)
					return new IntConstant (-((ByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.sbyte_type)
					return new IntConstant (-((SByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.short_type)
					return new IntConstant (-((ShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.ushort_type)
					return new IntConstant (-((UShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.char_type)
					return new IntConstant (-((CharConstant)e).Value, e.Location);
				
				// Predefined operators
				if (expr_type == TypeManager.int32_type) {
					int value = ((IntConstant)e).Value;
					if (value == int.MinValue) {
						if (ec.ConstantCheckState) {
							ConstantFold.Error_CompileTimeOverflow (ec, loc);
							return null;
						}
						return e;
					}
					return new IntConstant (-value, e.Location);
				}
				if (expr_type == TypeManager.int64_type) {
					long value = ((LongConstant)e).Value;
					if (value == long.MinValue) {
						if (ec.ConstantCheckState) {
							ConstantFold.Error_CompileTimeOverflow (ec, loc);
							return null;
						}
						return e;
					}
					return new LongConstant (-value, e.Location);
				}
				
				if (expr_type == TypeManager.uint32_type) {
					UIntLiteral uil = e as UIntLiteral;
					if (uil != null) {
						if (uil.Value == 2147483648)
							return new IntLiteral (int.MinValue, e.Location);
						return new LongLiteral (-uil.Value, e.Location);
					}
					return new LongConstant (-((UIntConstant)e).Value, e.Location);
				}
				
				if (expr_type == TypeManager.uint64_type) {
					ULongLiteral ull = e as ULongLiteral;
					if (ull != null && ull.Value == 9223372036854775808)
						return new LongLiteral (long.MinValue, e.Location);
					return null;
				}
				
				if (expr_type == TypeManager.float_type) {
					FloatLiteral fl = e as FloatLiteral;
					// For better error reporting
					if (fl != null)
						return new FloatLiteral (-fl.Value, e.Location);

					return new FloatConstant (-((FloatConstant)e).Value, e.Location);
				}
				if (expr_type == TypeManager.double_type) {
					DoubleLiteral dl = e as DoubleLiteral;
					// For better error reporting
					if (dl != null)
						return new DoubleLiteral (-dl.Value, e.Location);

					return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
				}
				if (expr_type == TypeManager.decimal_type)
					return new DecimalConstant (-((DecimalConstant)e).Value, e.Location);
				
				return null;
				
			case Operator.LogicalNot:
				if (expr_type != TypeManager.bool_type)
					return null;
				
				bool b = (bool)e.GetValue ();
				return new BoolConstant (!b, e.Location);
				
			case Operator.OnesComplement:
				// Unary numeric promotions
				if (expr_type == TypeManager.byte_type)
					return new IntConstant (~((ByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.sbyte_type)
					return new IntConstant (~((SByteConstant)e).Value, e.Location);
				if (expr_type == TypeManager.short_type)
					return new IntConstant (~((ShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.ushort_type)
					return new IntConstant (~((UShortConstant)e).Value, e.Location);
				if (expr_type == TypeManager.char_type)
					return new IntConstant (~((CharConstant)e).Value, e.Location);
				
				// Predefined operators
				if (expr_type == TypeManager.int32_type)
					return new IntConstant (~((IntConstant)e).Value, e.Location);
				if (expr_type == TypeManager.uint32_type)
					return new UIntConstant (~((UIntConstant)e).Value, e.Location);
				if (expr_type == TypeManager.int64_type)
					return new LongConstant (~((LongConstant)e).Value, e.Location);
				if (expr_type == TypeManager.uint64_type){
					return new ULongConstant (~((ULongConstant)e).Value, e.Location);
				}
				if (e is EnumConstant) {
					e = TryReduceConstant (ec, ((EnumConstant)e).Child);
					if (e != null)
						e = new EnumConstant (e, expr_type);
					return e;
				}
				return null;
			}
			throw new Exception ("Can not constant fold: " + Oper.ToString());
		}
Example #2
0
		//
		// Imports System.Reflection parameters
		//
		AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method)
		{
			int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;

			if (pi.Length == 0 && varargs == 0)
				return ParametersCompiled.EmptyReadOnlyParameters;

			TypeSpec[] types = new TypeSpec[pi.Length + varargs];
			IParameterData[] par = new IParameterData[pi.Length + varargs];
			bool is_params = false;
			for (int i = 0; i < pi.Length; i++) {
				ParameterInfo p = pi[i];
				Parameter.Modifier mod = 0;
				Expression default_value = null;
				if (p.ParameterType.IsByRef) {
					if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
						mod = Parameter.Modifier.OUT;
					else
						mod = Parameter.Modifier.REF;

					//
					// Strip reference wrapping
					//
					var el = p.ParameterType.GetElementType ();
					types[i] = ImportType (el, new DynamicTypeReader (p));	// TODO: 1-based positio to be csc compatible
				} else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod &&
					HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
					mod = Parameter.Modifier.This;
					types[i] = ImportType (p.ParameterType);
				} else {
					types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p));

					if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
						if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
							mod = Parameter.Modifier.PARAMS;
							is_params = true;
						}
					}

					if (!is_params && p.IsOptional) {
						object value = p.RawDefaultValue;
						var ptype = types[i];
						if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) {
							if (value == null) {
								default_value = Constant.CreateConstant (ptype, null, Location.Null);
							} else {
								default_value = ImportParameterConstant (value);

								if (ptype.IsEnum) {
									default_value = new EnumConstant ((Constant) default_value, ptype);
								}
							}
						} else if (value == Missing.Value) {
							default_value = EmptyExpression.MissingValue;
						} else if (value == null) {
							default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
						} else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
							default_value = ImportParameterConstant (value);
						}
					}
				}

				par[i] = new ParameterData (p.Name, mod, default_value);
			}

			if (varargs != 0) {
				par[par.Length - 1] = new ArglistParameter (Location.Null);
				types[types.Length - 1] = InternalType.Arglist;
			}

			return method != null ?
				new ParametersImported (par, types, varargs != 0, is_params) :
				new ParametersImported (par, types, is_params);
		}
Example #3
0
		// <summary>
		//   This routine will attempt to simplify the unary expression when the
		//   argument is a constant.  The result is returned in `result' and the
		//   function returns true or false depending on whether a reduction
		//   was performed or not
		// </summary>
		bool Reduce (EmitContext ec, Constant e, out Expression result)
		{
			Type expr_type = e.Type;
			
			switch (Oper){
			case Operator.UnaryPlus:
				result = e;
				return true;
				
			case Operator.UnaryNegation:
				result = TryReduceNegative (e);
				return true;
				
			case Operator.LogicalNot:
				if (expr_type != TypeManager.bool_type) {
					result = null;
					Error23 (expr_type);
					return false;
				}
				
				BoolConstant b = (BoolConstant) e;
				result = new BoolConstant (!(b.Value));
				return true;
				
			case Operator.OnesComplement:
				if (!((expr_type == TypeManager.int32_type) ||
				      (expr_type == TypeManager.uint32_type) ||
				      (expr_type == TypeManager.int64_type) ||
				      (expr_type == TypeManager.uint64_type) ||
				      (expr_type.IsSubclassOf (TypeManager.enum_type)))){

					result = null;
					if (ImplicitConversionExists (ec, e, TypeManager.int32_type)){
						result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
						result = result.Resolve (ec);
					} else if (ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
						result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
						result = result.Resolve (ec);
					} else if (ImplicitConversionExists (ec, e, TypeManager.int64_type)){
						result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
						result = result.Resolve (ec);
					} else if (ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
						result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
						result = result.Resolve (ec);
					}

					if (result == null || !(result is Constant)){
						result = null;
						Error23 (expr_type);
						return false;
					}

					expr_type = result.Type;
					e = (Constant) result;
				}

				if (e is EnumConstant){
					EnumConstant enum_constant = (EnumConstant) e;
					Expression reduced;
					
					if (Reduce (ec, enum_constant.Child, out reduced)){
						result = new EnumConstant ((Constant) reduced, enum_constant.Type);
						return true;
					} else {
						result = null;
						return false;
					}
				}

				if (expr_type == TypeManager.int32_type){
					result = new IntConstant (~ ((IntConstant) e).Value);
				} else if (expr_type == TypeManager.uint32_type){
					result = new UIntConstant (~ ((UIntConstant) e).Value);
				} else if (expr_type == TypeManager.int64_type){
					result = new LongConstant (~ ((LongConstant) e).Value);
				} else if (expr_type == TypeManager.uint64_type){
					result = new ULongConstant (~ ((ULongConstant) e).Value);
				} else {
					result = null;
					Error23 (expr_type);
					return false;
				}
				return true;

			case Operator.AddressOf:
				result = this;
				return false;

			case Operator.Indirection:
				result = this;
				return false;
			}
			throw new Exception ("Can not constant fold: " + Oper.ToString());
		}