/**
     * Generate an invoker method for the passed {@link LambdaForm}.
     */
    private Delegate generateCustomizedCodeBytes()
    {
        // iterate over the form's names, generating bytecode instructions for each
        // start iterating at the first name following the arguments
        Name onStack = null;

        for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++)
        {
            Name name = lambdaForm.names[i];

            emitStoreResult(onStack);
            onStack = name;  // unless otherwise modified below
            MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
            switch (intr.name())
            {
            case "SELECT_ALTERNATIVE":
                //assert isSelectAlternative(i);
                onStack = emitSelectAlternative(name, lambdaForm.names[i + 1]);
                i++;      // skip MH.invokeBasic of the selectAlternative result
                continue;

            case "GUARD_WITH_CATCH":
                //assert isGuardWithCatch(i);
                onStack = emitGuardWithCatch(i);
                i       = i + 2; // Jump to the end of GWC idiom
                continue;

            case "NEW_ARRAY":
                Class rtype = name.function.methodType().returnType();
                if (InvokerBytecodeGenerator.isStaticallyNameable(rtype))
                {
                    emitNewArray(name);
                    continue;
                }
                break;

            case "ARRAY_LOAD":
                emitArrayLoad(name);
                continue;

            case "IDENTITY":
                //assert(name.arguments.length == 1);
                emitPushArguments(name);
                continue;

            case "NONE":
                // no intrinsic associated
                break;

            // [IKVM] ARRAY_STORE and ZERO appear to be unused
            default:
                throw new BailoutException(Bailout.UnsupportedIntrinsic, "Unknown intrinsic: " + intr);
            }

            MemberName member = name.function._member();
            if (isStaticallyInvocable(member))
            {
                emitStaticInvoke(member, name);
            }
            else
            {
                emitInvoke(name);
            }
        }

        // return statement
        emitReturn(onStack);

        ilgen.DoEmit();
        return(dm.CreateDelegate(delegateType, constants.ToArray()));
    }
    private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType)
    {
        if (invokerType != invokerType.basicType())
        {
            throw new BailoutException(Bailout.NotBasicType, invokerType);
        }
        this.lambdaForm   = lambdaForm;
        this.invokerType  = invokerType;
        this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType);
        MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType);

        Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi);
        // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly)
        this.dm    = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true);
        this.ilgen = CodeEmitter.Create(this.dm);
        if (invokerType.parameterCount() > MethodHandleUtil.MaxArity)
        {
            this.packedArgType = paramTypes[paramTypes.Length - 1];
            this.packedArgPos  = paramTypes.Length - 1;
        }
        else
        {
            this.packedArgPos = Int32.MaxValue;
        }

        locals = new CodeEmitterLocal[lambdaForm.names.Length];
        for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++)
        {
            Name name = lambdaForm.names[i];
            if (name.index() != i)
            {
                throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i");
            }
            switch (name.typeChar())
            {
            case 'L':
                locals[i] = ilgen.DeclareLocal(Types.Object);
                break;

            case 'I':
                locals[i] = ilgen.DeclareLocal(Types.Int32);
                break;

            case 'J':
                locals[i] = ilgen.DeclareLocal(Types.Int64);
                break;

            case 'F':
                locals[i] = ilgen.DeclareLocal(Types.Single);
                break;

            case 'D':
                locals[i] = ilgen.DeclareLocal(Types.Double);
                break;

            case 'V':
                break;

            default:
                throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar());
            }
        }
    }
    private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType)
    {
        if (invokerType != invokerType.basicType())
        {
            throw new BailoutException(Bailout.NotBasicType, invokerType);
        }
        this.lambdaForm = lambdaForm;
        this.invokerType = invokerType;
        this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType);
        MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType);
        Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi);
        // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly)
        this.dm = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true);
        this.ilgen = CodeEmitter.Create(this.dm);
        if (invokerType.parameterCount() > MethodHandleUtil.MaxArity)
        {
            this.packedArgType = paramTypes[paramTypes.Length - 1];
            this.packedArgPos = paramTypes.Length - 1;
        }
        else
        {
            this.packedArgPos = Int32.MaxValue;
        }

        locals = new CodeEmitterLocal[lambdaForm.names.Length];
        for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++)
        {
            Name name = lambdaForm.names[i];
            if (name.index() != i)
            {
                throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i");
            }
            switch (name.typeChar())
            {
                case 'L':
                    locals[i] = ilgen.DeclareLocal(Types.Object);
                    break;
                case 'I':
                    locals[i] = ilgen.DeclareLocal(Types.Int32);
                    break;
                case 'J':
                    locals[i] = ilgen.DeclareLocal(Types.Int64);
                    break;
                case 'F':
                    locals[i] = ilgen.DeclareLocal(Types.Single);
                    break;
                case 'D':
                    locals[i] = ilgen.DeclareLocal(Types.Double);
                    break;
                case 'V':
                    break;
                default:
                    throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar());
            }
        }
    }