/// <summary> /// Performs a stack layout of all local variables in the list. /// </summary> /// <param name="locals">The enumerable holding all locals.</param> /// <param name="callingConvention">The cc.</param> /// <param name="offsetOfFirst">Specifies the offset of the first stack operand in the list.</param> /// <param name="direction">The direction.</param> /// <returns></returns> private static int LayoutVariables(List<Operand> locals, ICallingConvention callingConvention, int offsetOfFirst, int direction) { int offset = offsetOfFirst; foreach (Operand operand in locals) { // Does the offset fit the alignment requirement? int alignment; int size; int padding; int thisOffset; callingConvention.GetStackRequirements(operand, out size, out alignment); if (direction == 1) { padding = (offset % alignment); offset -= (padding + size); thisOffset = offset; } else { padding = (offset % alignment); if (padding != 0) padding = alignment - padding; thisOffset = offset; offset += (padding + size); } operand.Offset = new IntPtr(thisOffset); } return offset; }
/// <summary> /// Processes a method call instruction. /// </summary> /// <param name="ctx">The transformation context.</param> private void HandleInvokeInstruction(Context ctx) { ICallingConvention cc = Architecture.GetCallingConvention(ctx.InvokeTarget.Signature.CallingConvention); Debug.Assert(null != cc, @"Failed to retrieve the calling convention."); cc.Expand(ctx); }
public FunctionCall(Label function, Variable result = null, IList <Variable> args = null, ICallingConvention callingConvention = null) { Function = function; Arguments = args ?? new List <Variable>(); Result = result; CallingConvention = callingConvention; }
/// <summary> /// Retrieves a calling convention object for the requested calling convention. /// </summary> /// <returns> /// An instance of <see cref="ICallingConvention"/>. /// </returns> public override ICallingConvention GetCallingConvention() { if (callingConvention == null) { callingConvention = new DefaultCallingConvention(this); } return(callingConvention); }
/// <summary> /// Sorts all local variables by their size requirements. /// </summary> /// <param name="locals">Holds all local variables to sort..</param> /// <param name="cc">The calling convention used to determine size and alignment requirements.</param> private static void OrderVariables(List <StackOperand> locals, ICallingConvention cc) { /* Sort the list by stack size requirements - this moves equally sized operands closer together, * in the hope that this reduces padding on the stack to enforce HW alignment requirements. */ locals.Sort(delegate(StackOperand op1, StackOperand op2) { int size1, size2, alignment; cc.GetStackRequirements(op1, out size1, out alignment); cc.GetStackRequirements(op2, out size2, out alignment); return(size2 - size1); }); }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> /// <param name="cc">The calling convention used to invoke the method, which controls parameter layout.</param> private void LayoutParameters(IMethodCompiler compiler, ICallingConvention cc) { List <StackOperand> paramOps = new List <StackOperand> (); for (int i = 0; i < compiler.Method.Parameters.Count; i++) { paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); } LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) { LogOperands(paramOps); } }
/// <summary> /// Setups the specified compiler. /// </summary> /// <param name="compiler">The compiler.</param> public void Setup(IMethodCompiler compiler) { if (compiler == null) { throw new ArgumentNullException(@"compiler"); } methodCompiler = compiler; InstructionSet = compiler.InstructionSet; basicBlocks = compiler.BasicBlocks; architecture = compiler.Architecture; typeModule = compiler.Method.Module; typeSystem = compiler.TypeSystem; typeLayout = compiler.TypeLayout; callingConvention = architecture.GetCallingConvention(); architecture.GetTypeRequirements(BuiltInSigType.IntPtr, out nativePointerSize, out nativePointerAlignment); }
/// <summary> /// Runs the specified method compiler. /// </summary> public void Run() { // Allocate a list of locals List <StackOperand> locals = new List <StackOperand> (); // Retrieve the calling convention of the method ICallingConvention cc = Architecture.GetCallingConvention(MethodCompiler.Method.Signature.CallingConvention); Debug.Assert(null != cc, "Failed to retrieve the calling convention of the method."); // Iterate all Blocks and collect locals From all Blocks foreach (BasicBlock block in BasicBlocks) { CollectLocalVariables(locals, block); } // Sort all found locals OrderVariables(locals, cc); // Now we assign increasing stack offsets to each variable _localsSize = LayoutVariables(locals, cc, cc.OffsetOfFirstLocal, 1); if (TRACING.TraceInfo == true) { Trace.WriteLine(String.Format("Stack layout for method {0}", MethodCompiler.Method)); LogOperands(locals); } // Layout parameters LayoutParameters(MethodCompiler, cc); // Create a prologue instruction Context prologueCtx = new Context(InstructionSet, FindBlock(-1)).InsertBefore(); prologueCtx.SetInstruction(IR.Instruction.PrologueInstruction); prologueCtx.Other = _localsSize; prologueCtx.Label = -1; // Create an epilogue instruction Context epilogueCtx = new Context(InstructionSet, FindBlock(Int32.MaxValue)); epilogueCtx.AppendInstruction(IR.Instruction.EpilogueInstruction); epilogueCtx.Other = _localsSize; epilogueCtx.Label = Int32.MaxValue; }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.ReturnInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.ReturnInstruction(Context ctx) { Operand op = ctx.Operand1; if (op != null) { ICallingConvention cc = Architecture.GetCallingConvention(MethodCompiler.Method.Signature.CallingConvention); cc.MoveReturnValue(ctx, op); ctx.AppendInstruction(CPUx86.Instruction.JmpInstruction); ctx.SetBranch(Int32.MaxValue); } else { ctx.SetInstruction(CPUx86.Instruction.JmpInstruction); ctx.SetBranch(Int32.MaxValue); } }
/// <summary> /// Performs a stack layout of all local variables in the list. /// </summary> /// <param name="locals">The enumerable holding all locals.</param> /// <param name="cc">The cc.</param> /// <param name="offsetOfFirst">Specifies the offset of the first stack operand in the list.</param> /// <param name="direction">The direction.</param> /// <returns></returns> private static int LayoutVariables(IEnumerable <StackOperand> locals, ICallingConvention cc, int offsetOfFirst, int direction) { int offset = offsetOfFirst; foreach (StackOperand lvo in locals) { // Does the offset fit the alignment requirement? int alignment; int size; int padding; int thisOffset; cc.GetStackRequirements(lvo, out size, out alignment); if (1 == direction) { padding = (offset % alignment); offset -= (padding + size); thisOffset = offset; } else { padding = (offset % alignment); if (0 != padding) { padding = alignment - padding; } thisOffset = offset; offset += (padding + size); } lvo.Offset = new IntPtr(thisOffset); } return(offset); }
/// <summary> /// Sorts all local variables by their size requirements. /// </summary> /// <param name="locals">Holds all local variables to sort..</param> /// <param name="callingConvention">The calling convention used to determine size and alignment requirements.</param> private static void OrderVariables(List<Operand> locals, ICallingConvention callingConvention) { // Sort the list by stack size requirements - this moves equally sized operands closer together, // in the hope that this reduces padding on the stack to enforce HW alignment requirements. locals.Sort(delegate(Operand op1, Operand op2) { int size1, size2, alignment; callingConvention.GetStackRequirements(op1, out size1, out alignment); callingConvention.GetStackRequirements(op2, out size2, out alignment); return size2 - size1; }); }
/// <summary> /// Setups the specified compiler. /// </summary> /// <param name="compiler">The compiler.</param> public void Setup(IMethodCompiler compiler) { if (compiler == null) throw new ArgumentNullException(@"compiler"); methodCompiler = compiler; instructionSet = compiler.InstructionSet; basicBlocks = compiler.BasicBlocks; architecture = compiler.Architecture; typeModule = compiler.Method.Module; typeSystem = compiler.TypeSystem; typeLayout = compiler.TypeLayout; callingConvention = architecture.GetCallingConvention(); architecture.GetTypeRequirements(BuiltInSigType.IntPtr, out nativePointerSize, out nativePointerAlignment); }
/// <summary> /// Performs a stack layout of all local variables in the list. /// </summary> /// <param name="locals">The enumerable holding all locals.</param> /// <param name="cc">The cc.</param> /// <param name="offsetOfFirst">Specifies the offset of the first stack operand in the list.</param> /// <param name="direction">The direction.</param> /// <returns></returns> private static int LayoutVariables(IEnumerable<StackOperand> locals, ICallingConvention cc, int offsetOfFirst, int direction) { int offset = offsetOfFirst; foreach (StackOperand lvo in locals) { // Does the offset fit the alignment requirement? int alignment; int size; int padding; int thisOffset; cc.GetStackRequirements(lvo, out size, out alignment); if (1 == direction) { padding = (offset % alignment); offset -= (padding + size); thisOffset = offset; } else { padding = (offset % alignment); if (0 != padding) padding = alignment - padding; thisOffset = offset; offset += (padding + size); } lvo.Offset = new IntPtr(thisOffset); } return offset; }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> /// <param name="cc">The calling convention used to invoke the method, which controls parameter layout.</param> private void LayoutParameters(IMethodCompiler compiler, ICallingConvention cc) { List<StackOperand> paramOps = new List<StackOperand>(); int offset = 0; if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) ++offset; for (int i = 0; i < compiler.Method.Parameters.Count + offset; ++i) paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); /*if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter + 4, -1); else*/ LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) LogOperands(paramOps); }
public Context(ICallingConvention callingConvention) { CallingConvention = callingConvention; Registers = new RegisterContainer(callingConvention.GetRegisters()); VariableAccounter = new VariableAccounter(); }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> /// <param name="cc">The calling convention used to invoke the method, which controls parameter layout.</param> private void LayoutParameters(IMethodCompiler compiler, ICallingConvention cc) { List<StackOperand> paramOps = new List<StackOperand> (); for (int i = 0; i < compiler.Method.Parameters.Count; i++) paramOps.Add ((StackOperand)compiler.GetParameterOperand (i)); LayoutVariables (paramOps, cc, cc.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) LogOperands (paramOps); }
/// <summary> /// Retrieves a calling convention object for the requested calling convention. /// </summary> /// <returns> /// An instance of <see cref="ICallingConvention"/>. /// </returns> public override ICallingConvention GetCallingConvention() { // TODO if (callingConvention == null) callingConvention = null; // new DefaultCallingConvention(this); return callingConvention; }
/// <summary> /// Retrieves a calling convention object for the requested calling convention. /// </summary> /// <param name="typeLayout">The type layout.</param> /// <returns> /// An instance of <see cref="ICallingConvention"/>. /// </returns> public override ICallingConvention GetCallingConvention(ITypeLayout typeLayout) { if (callingConvention == null) callingConvention = new DefaultCallingConvention(this, typeLayout); return callingConvention; }