public FlatOperand Resolve(SymbolInfo si, IMethodSymbol method, ExpressionSyntax expression, ArgumentListSyntax args, TypeInfo result_type, FlatOperand into_lvalue, List<FlatStatement> instructions) { // check for intrinsics string intrinsic; if (method.GetIntrinsic(out intrinsic)) { var im = ls2csc.Intrinsics.ResolveMethod(intrinsic); if (im == null) { throw new NotImplementedException("Unhandled intrinsic method " + intrinsic); } return im.Resolve(expression, args, result_type, si, into_lvalue, this, instructions); } int nArgs = args.Arguments.Count; //int nFirstArg = 0; if (!method.ReturnsVoid) { nArgs++; //nFirstArg = 1; } if (method.IsStatic || method.MethodKind == MethodKind.DelegateInvoke) { FlatOperand fop_method; if (method.MethodKind == MethodKind.DelegateInvoke) { fop_method = ResolveExpression(expression, null, instructions); } else { FlatOperand fop_type = Resolve(method.ContainingType, null, instructions); fop_method = Resolve(method, fop_type, null, instructions); } // 1. RESOLVETYPE switch (nArgs) { case 0: { instructions.Add(FlatStatement.FASTCALLSTATICMETHOD(fop_method)); return FlatOperand.LiteralNull(); } break; case 1: { if (!method.ReturnsVoid) { FlatOperand fop_return = AllocateRegister(""); FlatOperand lvalue_return = fop_return.GetLValue(this, instructions); instructions.Add(FlatStatement.REREFERENCE(lvalue_return, FlatOperand.LiteralNull())); instructions.Add(FlatStatement.FASTCALLSTATICMETHOD(fop_method, fop_return)); FlatOperand rvalue_return = lvalue_return.AsRValue(FlatValue.Null()); if (into_lvalue == null) into_lvalue = AllocateRegister("").GetLValue(this, instructions); instructions.Add(FlatStatement.DEREFERENCE(into_lvalue, rvalue_return)); return into_lvalue.AsRValue(rvalue_return.ImmediateValue); } FlatOperand input0_fop = ResolveExpression(args.Arguments[0].Expression, null, instructions); FlatOperand input0_use = input0_fop; FlatOperand input0_reference = null; if (args.Arguments[0].RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { input0_reference = AllocateRegister(""); instructions.Add(FlatStatement.REREFERENCE(input0_reference.GetLValue(this, instructions), input0_fop)); input0_use = input0_reference; } instructions.Add(FlatStatement.FASTCALLSTATICMETHOD(fop_method, input0_use)); if (input0_reference != null) instructions.Add(FlatStatement.DEREFERENCE(input0_fop.GetLValue(this, instructions), input0_reference)); return FlatOperand.LiteralNull(); } break; case 2: { if (!method.ReturnsVoid) { FlatOperand fop_return = AllocateRegister(""); FlatOperand lvalue_return = fop_return.GetLValue(this, instructions); instructions.Add(FlatStatement.REREFERENCE(lvalue_return, FlatOperand.LiteralNull())); FlatOperand input0_fop = ResolveExpression(args.Arguments[0].Expression, null, instructions); FlatOperand input0_use = input0_fop; FlatOperand input0_reference = null; if (args.Arguments[0].RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { input0_reference = AllocateRegister(""); instructions.Add(FlatStatement.REREFERENCE(input0_reference.GetLValue(this, instructions), input0_fop)); input0_use = input0_reference; } instructions.Add(FlatStatement.FASTCALLSTATICMETHOD(fop_method, fop_return, input0_use)); FlatOperand rvalue_return = lvalue_return.AsRValue(FlatValue.Null()); if (into_lvalue == null) into_lvalue = AllocateRegister("").GetLValue(this, instructions); instructions.Add(FlatStatement.DEREFERENCE(into_lvalue, rvalue_return)); if (input0_reference != null) instructions.Add(FlatStatement.DEREFERENCE(input0_fop.GetLValue(this, instructions), input0_reference)); return into_lvalue.AsRValue(rvalue_return.ImmediateValue); } { FlatOperand input0_fop = ResolveExpression(args.Arguments[0].Expression, null, instructions); FlatOperand input0_use = input0_fop; FlatOperand input0_reference = null; if (args.Arguments[0].RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { input0_reference = AllocateRegister(""); instructions.Add(FlatStatement.REREFERENCE(input0_reference.GetLValue(this, instructions), input0_fop)); input0_use = input0_reference; } FlatOperand input1_fop = ResolveExpression(args.Arguments[1].Expression, null, instructions); FlatOperand input1_use = input1_fop; FlatOperand input1_reference = null; if (args.Arguments[1].RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { input1_reference = AllocateRegister(""); instructions.Add(FlatStatement.REREFERENCE(input1_reference.GetLValue(this, instructions), input1_fop)); input1_use = input1_reference; } instructions.Add(FlatStatement.FASTCALLSTATICMETHOD(fop_method, input0_use, input1_use)); if (input0_reference != null) instructions.Add(FlatStatement.DEREFERENCE(input0_fop.GetLValue(this, instructions), input0_reference)); if (input1_reference != null) instructions.Add(FlatStatement.DEREFERENCE(input1_fop.GetLValue(this, instructions), input1_reference)); return FlatOperand.LiteralNull(); } } break; default: { if (!method.ReturnsVoid) { FlatOperand fop_return = AllocateRegister(""); FlatOperand lvalue_return = fop_return.GetLValue(this, instructions); instructions.Add(FlatStatement.REREFERENCE(lvalue_return, FlatOperand.LiteralNull())); List<ReferencedArgument> references = null; FlatOperand fop_args = ResolveArgumentsToArray(args, fop_return, null, out references, instructions); instructions.Add(FlatStatement.CALLSTATICMETHOD(fop_method, fop_args)); FlatOperand rvalue_return = lvalue_return.AsRValue(FlatValue.Null()); if (into_lvalue == null) into_lvalue = AllocateRegister("").GetLValue(this, instructions); instructions.Add(FlatStatement.DEREFERENCE(into_lvalue, rvalue_return)); DereferenceArgumentsAfterCall(references, instructions); return into_lvalue.AsRValue(rvalue_return.ImmediateValue); } /**/ { List<ReferencedArgument> references = null; FlatOperand fop_args = ResolveArgumentsToArray(args, null, null, out references, instructions); { instructions.Add(FlatStatement.CALLSTATICMETHOD(fop_method, fop_args)); DereferenceArgumentsAfterCall(references, instructions); return FlatOperand.LiteralNull(); } } } break; } } FlatOperand fop_subject; if (expression is MemberAccessExpressionSyntax) { MemberAccessExpressionSyntax meas = (MemberAccessExpressionSyntax)expression; fop_subject = ResolveExpression(meas.Expression, null, instructions); } else { // implied "this" fop_subject = FlatOperand.ThisRef(FlatValue.FromType(method.ContainingType)); } { FlatOperand fop_type = TypeOf(fop_subject, null, null, instructions); FlatOperand fop_method = Resolve(method, fop_type, null, instructions); // non-static method // 1. RESOLVETYPE // FASTCALL switch (nArgs) { case 0: { instructions.Add(FlatStatement.FASTCALLMETHOD(fop_method, fop_subject)); return FlatOperand.LiteralNull(); } break; case 1: { if (!method.ReturnsVoid) { FlatOperand fop_return = AllocateRegister(""); FlatOperand lvalue_return = fop_return.GetLValue(this, instructions); instructions.Add(FlatStatement.REREFERENCE(lvalue_return, FlatOperand.LiteralNull())); instructions.Add(FlatStatement.FASTCALLMETHOD(fop_method, fop_subject, fop_return)); FlatOperand rvalue_return = lvalue_return.AsRValue(FlatValue.Null()); if (into_lvalue == null) into_lvalue = AllocateRegister("").GetLValue(this, instructions); instructions.Add(FlatStatement.DEREFERENCE(into_lvalue, rvalue_return)); return into_lvalue.AsRValue(rvalue_return.ImmediateValue); } FlatOperand input0_fop = ResolveExpression(args.Arguments[0].Expression, null, instructions); FlatOperand input0_use = input0_fop; FlatOperand input0_reference = null; if (args.Arguments[0].RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { input0_reference = AllocateRegister(""); instructions.Add(FlatStatement.REREFERENCE(input0_reference.GetLValue(this, instructions), input0_fop)); input0_use = input0_reference; } instructions.Add(FlatStatement.FASTCALLMETHOD(fop_method, fop_subject, input0_use)); if (input0_reference != null) instructions.Add(FlatStatement.DEREFERENCE(input0_fop.GetLValue(this, instructions), input0_reference)); return FlatOperand.LiteralNull(); } break; default: { if (!method.ReturnsVoid) { FlatOperand fop_return = AllocateRegister(""); FlatOperand lvalue_return = fop_return.GetLValue(this, instructions); instructions.Add(FlatStatement.REREFERENCE(lvalue_return, FlatOperand.LiteralNull())); List<ReferencedArgument> references = null; FlatOperand fop_args = ResolveArgumentsToArray(args, fop_return, null, out references, instructions); instructions.Add(FlatStatement.CALLMETHOD(fop_method, fop_subject, fop_args)); FlatOperand rvalue_return = lvalue_return.AsRValue(FlatValue.Null()); if (into_lvalue == null) into_lvalue = AllocateRegister("").GetLValue(this, instructions); instructions.Add(FlatStatement.DEREFERENCE(into_lvalue, rvalue_return)); DereferenceArgumentsAfterCall(references, instructions); return into_lvalue.AsRValue(rvalue_return.ImmediateValue); } /**/ { List<ReferencedArgument> references = null; FlatOperand fop_args = ResolveArgumentsToArray(args, null, null, out references, instructions); { instructions.Add(FlatStatement.CALLMETHOD(fop_method, fop_subject, fop_args)); DereferenceArgumentsAfterCall(references, instructions); return FlatOperand.LiteralNull(); } } } break; } } /**/ throw new NotImplementedException(); } public FlatOperand Resolve(InvocationExpressionSyntax node, TypeInfo result_type, FlatOperand into_lvalue, List<FlatStatement> instructions) { SymbolInfo si = Model.GetSymbolInfo(node); if (si.Symbol == null) { throw new NotImplementedException("non-Symbol invocation expression"); } if (si.Symbol.Kind != SymbolKind.Method) { throw new NotImplementedException("non-Method invocation"); } IMethodSymbol method = (IMethodSymbol)si.Symbol; return Resolve(si,method, node.Expression, node.ArgumentList, result_type, into_lvalue, instructions); } public FlatOperand ResolveArgument(ArgumentSyntax arg, FlatOperand into_lvalue, List<FlatStatement> instructions) { /* // Summary: // ExpressionSyntax node representing the argument. public ExpressionSyntax Expression { get; } // // Summary: // NameColonSyntax node representing the optional name arguments. public NameColonSyntax NameColon { get; } // // Summary: // SyntaxToken representing the optional ref or out keyword. public SyntaxToken RefOrOutKeyword { get; } */ if (arg.NameColon != null) { //throw new NotImplementedException("name : value"); throw new NotSupportedException("name : value syntax in BracketedArgumentListSyntax"); } if (arg.RefOrOutKeyword.CSharpKind() != SyntaxKind.None) { throw new NotSupportedException("ref/out keyword in BracketedArgumentListSyntax"); } FlatOperand opnd = ResolveExpression(arg.Expression, into_lvalue, instructions); return opnd; }