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; }
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; }
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; }