Example #1
0
        private void EmitConstant(object value, Type type)
        {
            // Try to emit the constant directly into IL
            if (ILGen.CanEmitConstant(value, type))
            {
                _ilg.EmitConstant(value, type);
                return;
            }

            _boundConstants.EmitConstant(this, value, type);
        }
 protected internal override Expression VisitConstant(ConstantExpression node)
 {
     if (!this._inQuote)
     {
         if (ILGen.CanEmitConstant(node.Value, node.Type))
         {
             return(node);
         }
         this._constants.Peek().AddReference(node.Value, node.Type);
     }
     return(node);
 }
        //CONFORMING
        private void EmitConstant(object value, Type type)
        {
            // Try to emit the constant directly into IL
            if (ILGen.CanEmitConstant(value, type))
            {
                _ilg.EmitConstant(value, type);
                return;
            }

            Debug.Assert(_dynamicMethod); // constructor enforces this

            _boundConstants.EmitConstant(this, value, type);
        }
Example #4
0
        internal LabelInfo(ILGen il, LabelTarget node, bool canReturn)
        {
            _ilg       = il;
            Node       = node;
            Label      = il.DefineLabel();
            _canReturn = canReturn;
            if (node != null && node.Type != typeof(void))
            {
                Value = il.DeclareLocal(node.Type);
            }

            // Until we have more information, default to a leave instruction, which always works
            _opCode = OpCodes.Leave;
        }
Example #5
0
        /// <summary>
        /// Emits a live object as a constant
        /// </summary>
        internal void EmitConstant(LambdaCompiler lc, object value, Type type)
        {
            Debug.Assert(!ILGen.CanEmitConstant(value, type));

            type = TypeUtils.GetConstantType(type);

            LocalBuilder local;

            if (_cache.TryGetValue(new TypedConstant(value, type), out local))
            {
                lc.IL.Emit(OpCodes.Ldloc, local);
                return;
            }
            EmitConstantsArray(lc);
            EmitConstantFromArray(lc, value, type);
        }
Example #6
0
        /// <summary>
        /// Emits a live object as a constant
        /// </summary>
        internal void EmitConstant(LambdaCompiler lc, object value, Type type)
        {
            Debug.Assert(!ILGen.CanEmitConstant(value, type));

            if (!lc.CanEmitBoundConstants)
            {
                throw Error.CannotCompileConstant(value);
            }

            if (_cache.TryGetValue(new TypedConstant(value, type), out var local))
            {
                lc.IL.Emit(OpCodes.Ldloc, local);
                return;
            }
            EmitConstantsArray(lc);
            EmitConstantFromArray(lc, value, type);
        }
Example #7
0
        protected internal override Expression VisitConstant(ConstantExpression node)
        {
            // If we're in Quote, we can ignore constants completely
            if (_inQuote)
            {
                return(node);
            }

            // Constants that can be emitted into IL don't need to be stored on
            // the delegate
            if (ILGen.CanEmitConstant(node.Value, node.Type))
            {
                return(node);
            }

            _constants.Peek().AddReference(node.Value, node.Type);
            return(node);
        }
Example #8
0
        internal void EmitConstant(LambdaCompiler lc, object?value, Type type)
        {
            Debug.Assert(!ILGen.CanEmitConstant(value, type));

            if (!lc.CanEmitBoundConstants)
            {
                throw new InvalidOperationException($"CompileToMethod cannot compile constant '{value}' because it is a non-trivial value, such as a live object. Instead, create an expression tree that can construct this value.");
            }

            if (_cache.TryGetValue(new TypedConstant(value, type), out var local))
            {
                lc.IL.Emit(OpCodes.Ldloc, local);
                return;
            }

            EmitConstantsArray(lc);
            EmitConstantFromArray(lc, value, type);
        }
Example #9
0
        /// <summary>
        /// Emits a live object as a constant
        /// </summary>
        internal void EmitConstant(LambdaCompiler lc, object value, Type type)
        {
            Debug.Assert(!ILGen.CanEmitConstant(value, type));

#if FEATURE_COMPILE_TO_METHODBUILDER
            if (!lc.CanEmitBoundConstants)
            {
                throw Error.CannotCompileConstant(value);
            }
#endif

            if (_cache.TryGetValue(new TypedConstant(value, type), out LocalBuilder? local))
            {
                lc.IL.Emit(OpCodes.Ldloc, local);
                return;
            }
            EmitConstantsArray(lc);
            EmitConstantFromArray(lc, value, type);
        }
Example #10
0
        // Returns true if the label was successfully defined
        // or false if the label is now ambiguous
        internal void Define(ILGen il, LabelBlockInfo block)
        {
            // Prevent the label from being shadowed, which enforces cleaner
            // trees. Also we depend on this for simplicity (keeping only one
            // active IL Label per LabelInfo)
            for (LabelBlockInfo j = block; j != null; j = j.Parent)
            {
                if (j.ContainsTarget(Node))
                {
                    throw Error.LabelTargetAlreadyDefined(Node.Name);
                }
            }

            Definitions.Add(block);
            block.AddLabelInfo(Node, this);

            // Once defined, validate all jumps
            if (Definitions.Count == 1)
            {
                foreach (var r in References)
                {
                    ValidateJump(r);
                }
            }
            else
            {
                // Was just redefined, if we had any across block jumps, they're
                // now invalid
                if (_acrossBlockJump)
                {
                    throw Error.AmbiguousJump(Node.Name);
                }
                // For local jumps, we need a new IL label
                // This is okay because:
                //   1. no across block jumps have been made or will be made
                //   2. we don't allow the label to be shadowed
                Label = il.DefineLabel();
            }
        }
Example #11
0
        private LambdaCompiler(
            AnalyzedTree tree,
            LambdaExpression lambda,
            TypeBuilder typeBuilder,
            MethodInfo method,
            ILGenerator ilg,
            IList <Type> paramTypes,
            bool dynamicMethod,
            bool emitDebugSymbols)
        {
            ContractUtils.Requires(dynamicMethod || method.IsStatic, "dynamicMethod");
            _tree          = tree;
            _lambda        = lambda;
            _typeBuilder   = typeBuilder;
            _method        = method;
            _paramTypes    = new ReadOnlyCollection <Type>(paramTypes);
            _dynamicMethod = dynamicMethod;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            if (!dynamicMethod && _boundConstants.Count > 0)
            {
                throw Error.RtConstRequiresBundDelegate();
            }

            _ilg = new ILGen(ilg);

            Debug.Assert(!emitDebugSymbols || _typeBuilder != null, "emitting debug symbols requires a TypeBuilder");
            _emitDebugSymbols = emitDebugSymbols;

            // See if we can find a return label, so we can emit better IL
            AddReturnLabel(_lambda.Body);

            _boundConstants.EmitCacheConstants(this);
        }