public override void Emit(CodeGen cg) { // emit "this", if any if (_expression != null) { if (_member.DeclaringType.IsValueType) { _expression.EmitAddress(cg, _member.DeclaringType); } else { _expression.Emit(cg); } } switch (_member.MemberType) { case MemberTypes.Field: _value.Emit(cg); cg.EmitFieldSet((FieldInfo)_member); break; case MemberTypes.Property: _value.Emit(cg); cg.EmitPropertySet((PropertyInfo)_member); break; default: Debug.Assert(false, "Invalid member type"); break; } }
internal override void EmitAddress(CodeGen cg, Type asType) { if (NodeType == AstNodeType.Convert && Type == asType) { _operand.EmitAddress(cg, asType); } else { base.EmitAddress(cg, asType); } }
internal override void EmitAddress(CodeGen cg, Type asType) { Label eoi = cg.DefineLabel(); Label next = cg.DefineLabel(); _test.Emit(cg); cg.Emit(OpCodes.Brfalse, next); _true.EmitAddress(cg, asType); cg.Emit(OpCodes.Br, eoi); cg.MarkLabel(next); _false.EmitAddress(cg, asType); cg.MarkLabel(eoi); }
private void EmitInstance(CodeGen cg) { if (_expression != null) { if (_member.DeclaringType.IsValueType) { _expression.EmitAddress(cg, _member.DeclaringType); } else { _expression.Emit(cg); } } }
private static void EmitArgument(CodeGen cg, Expression argument, Type type) { //if (argument.Type != type && (argument.Type.IsValueType || type.IsValueType)) if (!type.IsAssignableFrom(argument.Type) || (argument.Type != type && (argument.Type.IsValueType || type.IsValueType))) { argument = Ast.Convert(argument, type); } if (type.IsByRef) { argument.EmitAddress(cg, type.GetElementType()); } else { argument.Emit(cg); } }
internal override void EmitAddress(CodeGen cg, Type asType) { for (int index = 0; index < _expressions.Count; index++) { Expression current = _expressions[index]; // Emit the expression if (index == _valueIndex) { current.EmitAddress(cg, asType); } else { current.Emit(cg); // If we don't want the expression just emitted as the result, // pop it off of the stack, unless it is a void expression. if (current.Type != typeof(void)) { cg.Emit(OpCodes.Pop); } } } }
public override void Emit(CodeGen cg) { // TODO: Improve the following to direct call: Callable.Call(Callable.Create(...)) //EmitLocation(cg); if (_instance != null && !cg.IsDynamicMethod) // damn DM! // go away! // this dangerous too for now { if (!IsParamsMethod()) { if (_instance is CodeBlockExpression) { CodeBlockExpression cbe = (CodeBlockExpression)_instance; Debug.Assert(_arguments.Count == _parameterInfos.Length); for (int arg = 0; arg < _parameterInfos.Length; arg++) { Expression argument = _arguments[arg]; Type type = _parameterInfos[arg].ParameterType; EmitArgument(cg, argument, type); } EmitLocation(cg); if (tailcall) { // TODO: Remove tail calls from list of known non-recursive methods //Console.WriteLine(cbe.Block.Name); tailcall = true; } cbe.EmitDirect(cg, tailcall); if (ScriptDomainManager.Options.LightweightDebugging && !tailcall && Span.IsValid) { cg.EmitConstant(SpanToLong(Span)); cg.EmitCall(Debugging.DebugMethods.ExpressionOut); } return; } } else // 'params' { } } if (_method == BuiltinsIsTrue) { EmitLocation(cg); var arg = Unwrap(_arguments[0]); if (arg.Type == typeof(bool)) { arg.Emit(cg); } else if (arg.Type == typeof(object)) { Label next = cg.DefineLabel(); Label end = cg.DefineLabel(); arg.Emit(cg); cg.Emit(OpCodes.Dup); cg.Emit(OpCodes.Isinst, typeof(bool)); cg.Emit(OpCodes.Brfalse, next); cg.EmitUnbox(typeof(bool)); cg.Emit(OpCodes.Br, end); cg.MarkLabel(next); cg.Emit(OpCodes.Pop); cg.EmitConstant(true); cg.MarkLabel(end); } else { cg.EmitConstant(true); } return; } var ii = _instance; ii = Unwrap(ii); BoundExpression.Emitter fixup = null; bool varargs = false; var pttt = Array.ConvertAll(_parameterInfos, x => x.ParameterType); if (ii is BoundExpression) { var be = ii as BoundExpression; if (BoundExpression.Fixups.ContainsKey(be.Variable.Name)) { fixup = BoundExpression.Fixups[be.Variable.Name]; pttt = BoundExpression.FixupTypes[be.Variable.Name]; } else { CodeGen rcg; CodeGenDescriptor[] cgd; if (CodeGen._codeBlockLookup.TryGetValue(be.Variable.Name, out rcg)) { var lpttt = pt.GetValue(rcg.MethodInfo) as Type[]; if (_arguments.Count == lpttt.Length) { _method = rcg.MethodInfo; pttt = lpttt; } } else if (CodeGen._codeBlockLookupX.TryGetValue(be.Variable.Name, out rcg)) { var lpppt = pt.GetValue(rcg.MethodInfo) as Type[]; if (lpppt.Length - 1 > _arguments.Count) { } else if (AllArgsAreObject(_arguments)) { _method = rcg.MethodInfo; pttt = lpppt; varargs = true; } else if (_arguments.Count == 1 && lpppt.Length == 1 && _arguments[0].Type == typeof(object[]) && _arguments[0] is MethodCallExpression && ((MethodCallExpression)_arguments[0])._method.Name == "ListToVector") { _arguments[0] = Unwrap(((MethodCallExpression)_arguments[0]).Arguments[0]); _method = rcg.MethodInfo; pttt = lpppt; } } else if (CodeGen._codeBlockLookupN.TryGetValue(be.Variable.Name, out cgd)) { if (AllArgsAreObject(_arguments)) { foreach (var i in cgd) { if (i.arity == _arguments.Count) { _method = i.cg.MethodInfo; pttt = pt.GetValue(_method) as Type[]; break; } } } } } } // Emit instance, if calling an instance method if (!_method.IsStatic) { Type type = _method.DeclaringType; if (type.IsValueType) { _instance.EmitAddress(cg, type); } else { if (fixup == null) { _instance.Emit(cg); } } } if (varargs) { int arg = 0; for (; arg < pttt.Length - 1; arg++) { Expression argument = _arguments[arg]; Type type = pttt[arg]; EmitArgument(cg, argument, type); } // make tail var tailargs = new List <Expression>(); for (; arg < _arguments.Count; arg++) { tailargs.Add(_arguments[arg]); } var tailarr = tailargs.ToArray(); var tail = Ast.ComplexCallHelper(MakeList(tailarr, true), tailarr); EmitArgument(cg, tail, typeof(object)); } else { // Emit arguments // we cant really complain here or show error... Debug.Assert(_arguments.Count == pttt.Length); for (int arg = 0; arg < pttt.Length && arg < _arguments.Count; arg++) { Expression argument = _arguments[arg]; Type type = pttt[arg]; EmitArgument(cg, argument, type); } } // check for possible conversion/boxing needed, disabled tail call if (tailcall) { if (ShouldTailCallBeRemoved(cg)) { //Console.WriteLine("Removing tail call: {0} in {1}", cg.MethodBase, cg.TypeGen.AssemblyGen.AssemblyBuilder); tailcall = false; } } EmitLocation(cg); // Emit the actual call if (fixup == null) { cg.EmitCall(_method, tailcall); } else { fixup(cg, tailcall); } if (ScriptDomainManager.Options.LightweightDebugging && !tailcall && Span.IsValid) { cg.EmitConstant(SpanToLong(Span)); cg.EmitCall(Debugging.DebugMethods.ExpressionOut); } }