Exemplo n.º 1
0
        /// <summary>
        /// Gets the non register.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static Operand GetNonRegister(Operand value, Type type)
        {
            Operand operand = value;

            while (operand is IR.Operands.Register)
            {
                IR.Operands.Register register = operand as IR.Operands.Register;

                if (register.Parent.Use.Length != 1)
                {
                    throw new EngineException(string.Format("Could not propagate '{0}'.", value.ToString()));
                }

                operand = register.Parent.Use [0];
            }

            if (operand is NullConstant)
            {
                return(null);
            }

            if (operand.GetType() != type)
            {
                throw new EngineException(string.Format("'{0}' expected but '{1}' found.", type.ToString(), operand.GetType().ToString()));
            }

            return(operand);
        }
Exemplo n.º 2
0
        private Memory GetAddress(IR.Operands.FieldOperand field)
        {
            if (field.Instance != null)
            {
                IR.Operands.Register identifier = field.Instance as IR.Operands.Register;
                R32Type register;

                if (identifier.IsRegisterSet)
                {
                    register = Assembly.GetRegister(identifier.Register);
                }

                else
                {
                    register = R32.EDX;

                    this.assembly.MOV(register, new DWordMemory(this.GetAddress(identifier)));
                }

                return(new Memory(null, register, null, 0, this.assembly.Engine.GetFieldOffset(field)));
            }

            return(new Memory(field.Field.FieldDefinition.ToString()));
        }
Exemplo n.º 3
0
 private Memory GetAddress(IR.Operands.Register register)
 {
     return(new Memory(null, R32.EBP, null, 0, this.GetIdentifierDisplacement(register)));
 }
Exemplo n.º 4
0
        /// <summary>
        /// Gets the assembly code.
        /// </summary>
        /// <returns></returns>
        public bool GetAssemblyCode()
        {
            if (this.method.SkipProcessing)
            {
                return(true);
            }

            string fullname = method.MethodFullName;

            assembly.ALIGN(Assembly.ALIGNMENT);

            foreach (string label in method.Labels)
            {
                assembly.LABEL(label);

                this.assembly.AddSymbol(new COFF.Label(label));
            }

            if (this.method.EntryPoint)
            {
                assembly.LABEL(Assembly.KERNEL_MAIN);

                this.assembly.AddSymbol(new COFF.Label(Assembly.KERNEL_MAIN));
            }

            assembly.LABEL(string.Format(Assembly.METHOD_BEGIN, fullname));

            this.assembly.AddSymbol(new COFF.Function(fullname));

            assembly.LABEL(fullname);

            if (this.method.IsAbstract)
            {
                return(true);
            }

            bool isNaked = this.method.IsNaked;

            if (!isNaked)
            {
                assembly.PUSH(R32.EBP);
                assembly.MOV(R32.EBP, R32.ESP);
                assembly.PUSH(R32.EBX);
                assembly.PUSH(R32.ESI);
                assembly.PUSH(R32.EDI);
            }
            else
            {
                assembly.MOV(R32.EAX, R32.EBP);
                assembly.MOV(R32.EBP, R32.ESP);

                // The value stands for the above PUSH instructions
                // after saving the ESP register and we set it to 0
                // as nothing got saved
                this.reservedStackSlots = 0;
            }

            int stackSize = method.StackSize;

            if (this.method.HasExceptionHandling)
            {
                this.reservedStackSlots += 2;
                stackSize += 2;
            }

            if (stackSize > 0)
            {
                assembly.SUB(R32.ESP, (UInt32)(stackSize * this.assembly.IntSize));
            }

            foreach (Block block in method)
            {
                assembly.LABEL(string.Format(Assembly.METHOD_BLOCK_LABEL, fullname, block.Index.ToString()));

                if (block.IsFinallyBegin ||
                    block.IsFilterBegin ||
                    block.IsFaultBegin)
                {
                    this.assembly.MOV(this.GetExceptionHandlingSPSlot, R32.ESP);
                }

                if (block.IsFilterBegin ||
                    block.IsCatchBegin)
                {
                    // Save the reference to the exception so that it is used later when rethrowing
                    this.assembly.MOV(this.GetExceptionHandlingExceptionObjectSlot, R32.EAX);

                    // TODO find a more elegant way to set the exception when calling the handler?
                    if (block.InstructionsCount > 0 &&
                        block [0] is IR.Instructions.Stloc)
                    {
                        IR.Operands.Register exception = block [0].Use [0] as IR.Operands.Register;

                        if (exception.IsRegisterSet)
                        {
                            this.assembly.MOV(Assembly.GetRegister(exception.Register), R32.EAX);
                        }
                        else
                        {
                            this.assembly.MOV(new DWordMemory(this.GetAddress(exception)), R32.EAX);
                        }
                    }
                }

                foreach (SharpOS.AOT.IR.Instructions.Instruction instruction in block)
                {
                    assembly.COMMENT(instruction.ToString());

                    if (instruction.Ignore)
                    {
                        continue;
                    }

                    if (instruction is IR.Instructions.Call)
                    {
                        this.Call(instruction as SharpOS.AOT.IR.Instructions.Call);
                    }

                    else if (instruction is IR.Instructions.Return)
                    {
                        this.Return(instruction as IR.Instructions.Return);
                    }

                    else if (instruction is IR.Instructions.Initialize)
                    {
                        this.Initialize(instruction as IR.Instructions.Initialize);
                    }

                    else if (instruction is IR.Instructions.Ldc)
                    {
                        this.Ldc(instruction as IR.Instructions.Ldc);
                    }

                    else if (instruction is IR.Instructions.Ldind)
                    {
                        this.Ldind(instruction as IR.Instructions.Ldind);
                    }

                    else if (instruction is IR.Instructions.Ldloc)
                    {
                        this.Ldloc(instruction as IR.Instructions.Ldloc);
                    }

                    else if (instruction is IR.Instructions.Ldloca)
                    {
                        this.Ldloca(instruction as IR.Instructions.Ldloca);
                    }

                    else if (instruction is IR.Instructions.Ldarg)
                    {
                        this.Ldarg(instruction as IR.Instructions.Ldarg);
                    }

                    else if (instruction is IR.Instructions.Ldarga)
                    {
                        this.Ldarga(instruction as IR.Instructions.Ldarga);
                    }

                    else if (instruction is IR.Instructions.Ldfld)
                    {
                        this.Ldfld(instruction as IR.Instructions.Ldfld);
                    }

                    else if (instruction is IR.Instructions.Ldsfld)
                    {
                        this.Ldsfld(instruction as IR.Instructions.Ldsfld);
                    }

                    else if (instruction is IR.Instructions.Ldflda)
                    {
                        this.Ldflda(instruction as IR.Instructions.Ldflda);
                    }

                    else if (instruction is IR.Instructions.Ldsflda)
                    {
                        this.Ldsflda(instruction as IR.Instructions.Ldsflda);
                    }

                    else if (instruction is IR.Instructions.Ldftn)
                    {
                        this.Ldftn(instruction as IR.Instructions.Ldftn);
                    }

                    else if (instruction is IR.Instructions.Localloc)
                    {
                        this.Localloc(instruction as IR.Instructions.Localloc);
                    }

                    else if (instruction is IR.Instructions.Ldstr)
                    {
                        this.Ldstr(instruction as IR.Instructions.Ldstr);
                    }

                    else if (instruction is IR.Instructions.Ldnull)
                    {
                        this.Ldnull(instruction as IR.Instructions.Ldnull);
                    }

                    else if (instruction is IR.Instructions.Stloc)
                    {
                        this.Stloc(instruction as IR.Instructions.Stloc);
                    }

                    else if (instruction is IR.Instructions.Starg)
                    {
                        this.Starg(instruction as IR.Instructions.Starg);
                    }

                    else if (instruction is IR.Instructions.Stind)
                    {
                        this.Stind(instruction as IR.Instructions.Stind);
                    }

                    else if (instruction is IR.Instructions.Stfld)
                    {
                        this.Stfld(instruction as IR.Instructions.Stfld);
                    }

                    else if (instruction is IR.Instructions.Stsfld)
                    {
                        this.Stsfld(instruction as IR.Instructions.Stsfld);
                    }

                    else if (instruction is IR.Instructions.Convert)
                    {
                        this.Convert(instruction as IR.Instructions.Convert);
                    }

                    else if (instruction is IR.Instructions.Dup)
                    {
                        this.Dup(instruction as IR.Instructions.Dup);
                    }

                    else if (instruction is IR.Instructions.Jump)
                    {
                        this.Jump(instruction as IR.Instructions.Jump);
                    }

                    else if (instruction is IR.Instructions.Branch)
                    {
                        this.Branch(instruction as IR.Instructions.Branch);
                    }

                    else if (instruction is IR.Instructions.SimpleBranch)
                    {
                        this.SimpleBranch(instruction as IR.Instructions.SimpleBranch);
                    }

                    else if (instruction is IR.Instructions.ConditionCheck)
                    {
                        this.ConditionCheck(instruction as IR.Instructions.ConditionCheck);
                    }

                    else if (instruction is IR.Instructions.Add)
                    {
                        this.Add(instruction as IR.Instructions.Add);
                    }

                    else if (instruction is IR.Instructions.Sub)
                    {
                        this.Sub(instruction as IR.Instructions.Sub);
                    }

                    else if (instruction is IR.Instructions.Mul)
                    {
                        this.Mul(instruction as IR.Instructions.Mul);
                    }

                    else if (instruction is IR.Instructions.Div)
                    {
                        this.Div(instruction as IR.Instructions.Div);
                    }

                    else if (instruction is IR.Instructions.Rem)
                    {
                        this.Rem(instruction as IR.Instructions.Rem);
                    }

                    else if (instruction is IR.Instructions.Neg)
                    {
                        this.Neg(instruction as IR.Instructions.Neg);
                    }

                    else if (instruction is IR.Instructions.Shl)
                    {
                        this.Shl(instruction as IR.Instructions.Shl);
                    }

                    else if (instruction is IR.Instructions.Shr)
                    {
                        this.Shr(instruction as IR.Instructions.Shr);
                    }

                    else if (instruction is IR.Instructions.And)
                    {
                        this.And(instruction as IR.Instructions.And);
                    }

                    else if (instruction is IR.Instructions.Or)
                    {
                        this.Or(instruction as IR.Instructions.Or);
                    }

                    else if (instruction is IR.Instructions.Xor)
                    {
                        this.Xor(instruction as IR.Instructions.Xor);
                    }

                    else if (instruction is IR.Instructions.Not)
                    {
                        this.Not(instruction as IR.Instructions.Not);
                    }

                    else if (instruction is IR.Instructions.Pop)
                    {
                        this.Pop(instruction as IR.Instructions.Pop);
                    }

                    else if (instruction is IR.Instructions.Newobj)
                    {
                        this.Newobj(instruction as IR.Instructions.Newobj);
                    }

                    else if (instruction is IR.Instructions.Stobj)
                    {
                        this.Stobj(instruction as IR.Instructions.Stobj);
                    }

                    else if (instruction is IR.Instructions.Ldobj)
                    {
                        this.Ldobj(instruction as IR.Instructions.Ldobj);
                    }

                    else if (instruction is IR.Instructions.Initobj)
                    {
                        this.Initobj(instruction as IR.Instructions.Initobj);
                    }

                    else if (instruction is IR.Instructions.SizeOf)
                    {
                        this.SizeOf(instruction as IR.Instructions.SizeOf);
                    }

                    else if (instruction is IR.Instructions.Switch)
                    {
                        this.Switch(instruction as IR.Instructions.Switch);
                    }

                    else if (instruction is IR.Instructions.Box)
                    {
                        this.Box(instruction as IR.Instructions.Box);
                    }

                    else if (instruction is IR.Instructions.Unbox)
                    {
                        this.Unbox(instruction as IR.Instructions.Unbox);
                    }

                    else if (instruction is IR.Instructions.UnboxAny)
                    {
                        this.UnboxAny(instruction as IR.Instructions.UnboxAny);
                    }

                    else if (instruction is IR.Instructions.Newarr)
                    {
                        this.Newarr(instruction as IR.Instructions.Newarr);
                    }

                    else if (instruction is IR.Instructions.Stelem)
                    {
                        this.Stelem(instruction as IR.Instructions.Stelem);
                    }

                    else if (instruction is IR.Instructions.Ldelem)
                    {
                        this.Ldelem(instruction as IR.Instructions.Ldelem);
                    }

                    else if (instruction is IR.Instructions.Ldelema)
                    {
                        this.Ldelema(instruction as IR.Instructions.Ldelema);
                    }

                    else if (instruction is IR.Instructions.Ldlen)
                    {
                        this.Ldlen(instruction as IR.Instructions.Ldlen);
                    }

                    else if (instruction is IR.Instructions.Isinst)
                    {
                        this.Isinst(instruction as IR.Instructions.Isinst);
                    }

                    else if (instruction is IR.Instructions.Castclass)
                    {
                        this.Castclass(instruction as IR.Instructions.Castclass);
                    }

                    else if (instruction is IR.Instructions.Leave)
                    {
                        this.Leave(instruction as IR.Instructions.Leave);
                    }

                    else if (instruction is IR.Instructions.Endfinally)
                    {
                        this.Endfinally(instruction as IR.Instructions.Endfinally);
                    }

                    else if (instruction is IR.Instructions.Endfilter)
                    {
                        this.Endfilter(instruction as IR.Instructions.Endfilter);
                    }

                    else if (instruction is IR.Instructions.Break)
                    {
                        this.Break(instruction as IR.Instructions.Break);
                    }

                    else if (instruction is IR.Instructions.Throw)
                    {
                        this.Throw(instruction as IR.Instructions.Throw);
                    }

                    else
                    {
                        throw new EngineException("'" + instruction + "' is not supported.");
                    }
                }
            }

            assembly.LABEL(fullname + " exit");

            if (!isNaked)
            {
                assembly.LEA(R32.ESP, new DWordMemory(null, R32.EBP, null, 0, -12));
                assembly.POP(R32.EDI);
                assembly.POP(R32.ESI);
                assembly.POP(R32.EBX);
                assembly.POP(R32.EBP);
                assembly.RET();
            }

            assembly.LABEL(string.Format(Assembly.METHOD_END, fullname));

            return(true);
        }
Exemplo n.º 5
0
        private void PushOperand(Operand operand)
        {
            if (operand is IntConstant)
            {
                Int32 value = System.Convert.ToInt32((operand as IntConstant).Value);

                assembly.PUSH((UInt32)value);
            }
            else if (operand is LongConstant)
            {
                Int64 value = System.Convert.ToInt64((operand as LongConstant).Value);

                assembly.PUSH((UInt32)(value >> 32));
                assembly.PUSH((UInt32)(value & 0xFFFFFFFF));
            }
            else if (operand is IR.Operands.Register)
            {
                IR.Operands.Register identifier = operand as IR.Operands.Register;

                switch (identifier.InternalType)
                {
                case InternalType.SZArray:
                case InternalType.Array:
                case InternalType.I:
                case InternalType.O:
                case InternalType.M:
                case InternalType.I4:
                    if (identifier.IsRegisterSet)
                    {
                        this.assembly.PUSH(Assembly.GetRegister(identifier.Register));
                    }

                    else
                    {
                        this.assembly.PUSH(new DWordMemory(this.GetAddress(identifier)));
                    }

                    break;

                case InternalType.I8:
                    Memory memory = this.GetAddress(identifier);

                    DWordMemory high = new DWordMemory(memory);
                    high.DisplacementDelta = 4;
                    assembly.PUSH(new DWordMemory(high));

                    DWordMemory low = new DWordMemory(memory);
                    assembly.PUSH(low);

                    break;

                case InternalType.ValueType:
                    int size = this.method.Engine.GetTypeSize(identifier.Type.ToString());

                    uint pushSize = (uint)size;

                    if (pushSize % 4 != 0)
                    {
                        pushSize = (uint)(((pushSize / this.assembly.IntSize) + 1) * this.assembly.IntSize);
                    }

                    this.assembly.SUB(R32.ESP, pushSize);

                    this.assembly.PUSH(R32.ESI);
                    this.assembly.PUSH(R32.EDI);
                    this.assembly.PUSH(R32.ECX);

                    this.assembly.LEA(R32.ESI, new DWordMemory(this.GetAddress(identifier)));

                    // The 3 push above changed the ESP so we need a LEA = ESP + 12
                    this.assembly.LEA(R32.EDI, new Memory(null, R32.ESP, null, 0, 12));
                    this.assembly.MOV(R32.ECX, (uint)size);

                    this.assembly.CLD();
                    this.assembly.REP();
                    this.assembly.MOVSB();

                    this.assembly.POP(R32.ECX);
                    this.assembly.POP(R32.EDI);
                    this.assembly.POP(R32.ESI);
                    break;

                default:
                    throw new NotImplementedEngineException("'" + operand + "' is not supported.");
                }
            }
            else
            {
                throw new NotImplementedEngineException("'" + operand + "' is not supported.");
            }
        }