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); }
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; }
/// <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); }
/// <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); }
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); }
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); }
/// <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); }
// 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(); } }
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); }