private void RetInstr(OptimizationToken tkn)
        {
            Emitter.AddRegConst(AssemRegisters.Rsp, LocalTopSize);
            if (tkn.Parameters.Length == 1)
            {
                Emitter.MovRegisterToRegisterRelativeAddress(tkn.ParameterRegisters[0], AssemRegisters.Rsp, MachineSpec.PointerSize);
            }
            else if (tkn.Parameters.Length != 0)
            {
                throw new Exception("Unexpected parameter count.");
            }

            Emitter.Ret();
        }
        private void CallInstr(OptimizationToken[] tkns, int idx)
        {
            var tkn = tkns[idx];

            switch (tkn.Strings[0])
            {
            case "mthd_s_MSIL2ASM_Builtins_x86_64_Halt_0System_Void_r_":
                Emitter.Hlt();
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_Sti_0System_Void_r_":
                Emitter.Sti();
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_Cli_0System_Void_r_":
                Emitter.Cli();
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_UInt32_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Int32_2System_Void_r_":
                OutOp(tkn, 4);
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_UInt16_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Int16_2System_Void_r_":
                OutOp(tkn, 2);
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Byte_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_SByte_2System_Void_r_":
                OutOp(tkn, 1);
                return;

            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_UInt32_$addr_o_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_UInt16_$addr_o_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Byte_$addr_o_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Int32_$addr_o_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Int16_$addr_o_2System_Void_r_":
            case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_SByte_$addr_o_2System_Void_r_":
                InOp(tkn);
                return;
            }

            //Emit extern
            if (!tkn.Strings[0].Contains(prefix) && !externals.Contains(tkn.Strings[0]))
            {
                externals.Add(tkn.Strings[0]);
            }

            if (tkn.Strings[0] == "ctor_System_Object_0System_Object_i_1System_Object_r_" && !externals.Contains(tkn.Strings[0]))
            {
                externals.Add(tkn.Strings[0]);
            }

            //Determine active registers, save them
            var activeRegs = GetActiveRegistersInclusive(tkns, idx).ToList();

            if (tkn.ResultRegisters.Length == 1 && activeRegs.Contains(tkn.ResultRegisters[0]))
            {
                activeRegs.Remove(tkn.ResultRegisters[0]);
            }

            for (int i = 0; i < activeRegs.Count; i++)
            {
                Emitter.Push(activeRegs[i]);
            }

            //Push arguments onto stack
            for (int i = tkn.Parameters.Length - 1; i >= 0; i--)
            //for (int i = 0; i < tkn.Parameters.Length; i++)
            {
                if (tkn.Parameters[i].ParameterLocation == OptimizationParameterLocation.Const)
                {
                    Emitter.MovConstantToRegisterSize(tkn.Parameters[i].Value, tkn.ParameterRegisters[i], tkn.Parameters[i].Size);
                }

                Emitter.Push(tkn.ParameterRegisters[i]);
            }

            //Push return value onto stack
            Emitter.Push(AssemRegisters.R10);

            //Emit call instruction
            Emitter.CallLabel(tkn.Strings[0]);

            //Pop return value from stack
            if (tkn.ResultRegisters.Length == 1)
            {
                Emitter.Pop(tkn.ResultRegisters[0]);
            }

            //Remove arguments from stack
            Emitter.AddRegConst(AssemRegisters.Rsp, tkn.Parameters.Length * MachineSpec.PointerSize + ((tkn.ResultRegisters.Length == 1) ? 0 : MachineSpec.PointerSize));

            //Restore active registers
            for (int i = 0; i < activeRegs.Count; i++)
            {
                Emitter.Pop(activeRegs[i]);
            }
        }