public CompilerInstruction(Compiler compiler, InstructionCode code, Operand[] operands)
            : base(compiler)
        {
            Contract.Requires(compiler != null);
            Contract.Requires(operands != null);

            _code = code;
            _emitOptions = compiler.EmitOptions;
            // Each created instruction takes emit options and clears it.
            compiler.EmitOptions = EmitOptions.None;

            _operands = operands;
            _memoryOperand = null;

            _variables = null;

            for (int i = 0; i < operands.Length; i++)
            {
                if (operands[i].IsMem)
                {
                    _memoryOperand = (Mem)operands[i];
                    break;
                }
            }

            InstructionDescription id = InstructionDescription.FromInstruction(_code);
            _isSpecial = id.IsSpecial;
            _isFPU = id.IsFPU;
            _isGPBHiUsed = false;
            _isGPBLoUsed = false;

            if (_isSpecial)
            {
                // ${SPECIAL_INSTRUCTION_HANDLING_BEGIN}
                switch (_code)
                {
                case InstructionCode.Cpuid:
                    // Special...
                    break;

                case InstructionCode.Cbw:
                case InstructionCode.Cdqe:
                case InstructionCode.Cwde:
                    // Special...
                    break;

                case InstructionCode.Cdq:
                case InstructionCode.Cqo:
                case InstructionCode.Cwd:
                    // Special...
                    break;

                case InstructionCode.Cmpxchg:
                case InstructionCode.Cmpxchg8b:
                case InstructionCode.Cmpxchg16b:
                    // Special...
                    if (_code == InstructionCode.Cmpxchg16b && !Util.IsX64)
                        throw new NotSupportedException(string.Format("The '{0}' instruction is only supported on X64.", _code));

                    break;

                case InstructionCode.Daa:
                case InstructionCode.Das:
                    // Special...
                    if (!Util.IsX86)
                        throw new NotSupportedException(string.Format("The '{0}' instruction is only supported on X86.", _code));

                    break;

                case InstructionCode.Imul:
                    switch (operands.Length)
                    {
                    case 2:
                        // IMUL dst, src is not special instruction.
                        _isSpecial = false;
                        break;
                    case 3:
                        if (!(_operands[0].IsVar && _operands[1].IsVar && _operands[2].IsVarMem))
                        {
                            // Only IMUL dst_hi, dst_lo, reg/mem is special, all others don't.
                            _isSpecial = false;
                        }
                        break;
                    }
                    break;
                case InstructionCode.Mul:
                case InstructionCode.Idiv:
                case InstructionCode.Div:
                    // Special...
                    break;

                case InstructionCode.MovPtr:
                    // Special...
                    break;

                case InstructionCode.Lahf:
                case InstructionCode.Sahf:
                    // Special...
                    break;

                case InstructionCode.Maskmovdqu:
                case InstructionCode.Maskmovq:
                    // Special...
                    break;

                case InstructionCode.Enter:
                case InstructionCode.Leave:
                    // Special...
                    break;

                case InstructionCode.Ret:
                    // Special...
                    break;

                case InstructionCode.Monitor:
                case InstructionCode.Mwait:
                    // Special...
                    break;

                case InstructionCode.Pop:
                case InstructionCode.Popad:
                case InstructionCode.Popfd:
                case InstructionCode.Popfq:
                    // Special...
                    break;

                case InstructionCode.Push:
                case InstructionCode.Pushad:
                case InstructionCode.Pushfd:
                case InstructionCode.Pushfq:
                    // Special...
                    break;

                case InstructionCode.Rcl:
                case InstructionCode.Rcr:
                case InstructionCode.Rol:
                case InstructionCode.Ror:
                case InstructionCode.Sal:
                case InstructionCode.Sar:
                case InstructionCode.Shl:
                case InstructionCode.Shr:
                    // Rot instruction is special only if last operand is variable (register).
                    _isSpecial = _operands[1].IsVar;
                    break;

                case InstructionCode.Shld:
                case InstructionCode.Shrd:
                    // Shld/Shrd instruction is special only if last operand is variable (register).
                    _isSpecial = _operands[2].IsVar;
                    break;

                case InstructionCode.Rdtsc:
                case InstructionCode.Rdtscp:
                    // Special...
                    break;

                case InstructionCode.RepLodsb:
                case InstructionCode.RepLodsd:
                case InstructionCode.RepLodsq:
                case InstructionCode.RepLodsw:
                case InstructionCode.RepMovsb:
                case InstructionCode.RepMovsd:
                case InstructionCode.RepMovsq:
                case InstructionCode.RepMovsw:
                case InstructionCode.RepStosb:
                case InstructionCode.RepStosd:
                case InstructionCode.RepStosq:
                case InstructionCode.RepStosw:
                case InstructionCode.RepeCmpsb:
                case InstructionCode.RepeCmpsd:
                case InstructionCode.RepeCmpsq:
                case InstructionCode.RepeCmpsw:
                case InstructionCode.RepeScasb:
                case InstructionCode.RepeScasd:
                case InstructionCode.RepeScasq:
                case InstructionCode.RepeScasw:
                case InstructionCode.RepneCmpsb:
                case InstructionCode.RepneCmpsd:
                case InstructionCode.RepneCmpsq:
                case InstructionCode.RepneCmpsw:
                case InstructionCode.RepneScasb:
                case InstructionCode.RepneScasd:
                case InstructionCode.RepneScasq:
                case InstructionCode.RepneScasw:
                    // Special...
                    break;

                default:
                    throw new CompilerException("Instruction is marked as special but handling for it is not present.");
                }
                // ${SPECIAL_INSTRUCTION_HANDLING_END}
            }
        }
        internal void DumpFunction(CompilerContext cc)
        {
            Logger logger = Compiler.Logger;
            if (logger == null)
                throw new InvalidOperationException("Cannot dump a function without a logger.");

            int i;
            StringBuilder buffer = new StringBuilder();

            // Log function prototype.
            {
                int argumentsCount = _functionPrototype.Arguments.Length;
                bool first = true;

                logger.LogString("; Function Prototype:" + Environment.NewLine);
                logger.LogString(";" + Environment.NewLine);

                for (i = 0; i < argumentsCount; i++)
                {
                    FunctionDeclaration.Argument a = _functionPrototype.Arguments[i];
                    CompilerVar vdata = _argumentVariables[i];

                    if (first)
                    {
                        logger.LogString("; IDX| Type     | Sz | Home           |" + Environment.NewLine);
                        logger.LogString("; ---+----------+----+----------------+" + Environment.NewLine);
                    }

                    buffer.Clear();

                    if (a._registerIndex != RegIndex.Invalid)
                    {
                        var regOp = new GPReg(Register.NativeRegisterType, a._registerIndex);
                        Assembler.DumpOperand(buffer, regOp, Register.NativeRegisterType);
                    }
                    else
                    {
                        Mem memOp = new Mem();
                        memOp.Base = RegIndex.Esp;
                        memOp.Displacement = (IntPtr)a._stackOffset;
                        Assembler.DumpOperand(buffer, memOp, Register.NativeRegisterType);
                    }

                    // original format string: "; %-3u| %-9s| %-3u| %-15s|\n"
                    logger.LogFormat("; {0,-3}| {1,-9}| {2,-3}| {3,-15}|" + Environment.NewLine,
                        // Argument index.
                        i,
                        // Argument type.
                        (int)vdata.Type < _variableTypeCount ? VariableInfo.GetVariableInfo(vdata.Type).Name : "invalid",
                        // Argument size.
                        vdata.Size,
                        // Argument memory home.
                        buffer
                        );

                    first = false;
                }
                logger.LogString(";" + Environment.NewLine);
            }

            // Log variables.
            {
                int variablesCount = Compiler.Variables.Count;
                bool first = true;

                logger.LogString("; Variables:" + Environment.NewLine);
                logger.LogString(";" + Environment.NewLine);

                for (i = 0; i < variablesCount; i++)
                {
                    CompilerVar vdata = Compiler.GetVarData(i);
                    Contract.Assert(vdata != null);

                    // If this variable is not related to this function then skip it.
                    if (vdata.Scope != this)
                        continue;

                    // Get some information about variable type.
                    VariableInfo vinfo = VariableInfo.GetVariableInfo(vdata.Type);

                    if (first)
                    {
                        logger.LogString("; ID | Type     | Sz | Home           | Register Access   | Memory Access     |" + Environment.NewLine);
                        logger.LogString("; ---+----------+----+----------------+-------------------+-------------------+" + Environment.NewLine);
                    }

                    buffer.Clear();
                    buffer.Append("[None]");

                    if (vdata.HomeMemoryData != null)
                    {
                        buffer.Clear();

                        Mem memOp = new Mem();
                        if (vdata.IsMemArgument)
                        {
                            FunctionDeclaration.Argument a = _functionPrototype.Arguments[i];

                            memOp.Base = cc.ArgumentsBaseReg;
                            memOp.Displacement += cc.ArgumentsBaseOffset;
                            memOp.Displacement += a._stackOffset;
                        }
                        else
                        {
                            VarMemBlock memBlock = vdata.HomeMemoryData;
                            memOp.Base = cc.VariablesBaseReg;
                            memOp.Displacement += cc.VariablesBaseOffset;
                            memOp.Displacement += memBlock.Offset;
                        }

                        Assembler.DumpOperand(buffer, memOp, Register.NativeRegisterType);
                    }

                    string registerAccess = string.Format("r={0}w={1}x={2}", vdata.RegisterReadCount, vdata.RegisterWriteCount, vdata.RegisterRWCount);
                    string memoryAccess = string.Format("r={0}w={1}x={2}", vdata.MemoryReadCount, vdata.MemoryWriteCount, vdata.MemoryRWCount);
                    logger.LogFormat("; {0,-3}| {1,-9}| {2,-3}| {3,-15}| {4,-18}| {5,-18}|" + Environment.NewLine,
                        // Variable id.
                        (uint)(i & Operand.OperandIdValueMask),
                        // Variable type.
                        (int)vdata.Type < _variableTypeCount ? vinfo.Name : "invalid",
                        // Variable size.
                        vdata.Size,
                        // Variable memory home.
                        buffer,
                        // Register access count.
                        registerAccess,
                        // Memory access count.
                        memoryAccess
                        );

                    first = false;
                }
                logger.LogString(";" + Environment.NewLine);
            }

            // Log modified registers.
            {
                buffer.Clear();

                int r;
                int modifiedRegisters = 0;

                for (r = 0; r < 3; r++)
                {
                    bool first = true;
                    RegisterMask regs;
                    RegType type;

                    switch (r)
                    {
                    case 0:
                        regs = cc.ModifiedGPRegisters;
                        type = Register.NativeRegisterType;
                        buffer.Append("; GP : ");
                        break;
                    case 1:
                        regs = cc.ModifiedMMRegisters;
                        type = RegType.MM;
                        buffer.Append("; MM : ");
                        break;
                    case 2:
                        regs = cc.ModifiedXMMRegisters;
                        type = RegType.XMM;
                        buffer.Append("; XMM: ");
                        break;
                    default:
                        Contract.Assert(false, "");
                        continue;
                    }

                    for (i = 0; i < RegNum.Base; i++)
                    {
                        if ((regs & RegisterMask.FromIndex((RegIndex)i)) != RegisterMask.Zero)
                        {
                            if (!first)
                            {
                                buffer.Append(',');
                                buffer.Append(' ');
                            }

                            DumpRegister(buffer, type, i);
                            first = false;
                            modifiedRegisters++;
                        }
                    }

                    buffer.AppendLine();
                }

                logger.LogFormat("; Modified registers ({0}):" + Environment.NewLine, modifiedRegisters);
                logger.LogString(buffer.ToString());
            }

            logger.LogString(Environment.NewLine);
        }
        private Mem BaseVarMem(BaseVar var, int ptrSize)
        {
            Contract.Requires(var != null);

            int memSize = (ptrSize == Operand.InvalidValue ? var.Size : (byte)ptrSize);
            Mem m = new Mem(var.Id, memSize);
            return m;
        }
Beispiel #4
0
        internal Mem GetVarMem(CompilerVar var)
        {
            Contract.Requires(var != null);
            Contract.Ensures(Contract.Result<Mem>() != null);

            Mem m = new Mem(var.Id);
            if (!var.IsMemArgument)
                m.Displacement = (IntPtr)_adjustESP;

            MarkMemoryUsed(var);
            return m;
        }
Beispiel #5
0
        internal static Mem BaseVarMem(BaseVar var, int ptrSize)
        {
            Contract.Requires(var != null);

            int memSize = (ptrSize == InvalidValue) ? var.Size : (byte)ptrSize;
            Mem m = new Mem(var.Id, memSize);
            return m;
        }