private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment)
        {
            var allocatedType   = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            var assignmentField = assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundary
            if (allocation.Instruction is CIL.NewarrInstruction)
            {
                int elements = GetConstant(allocation.Operand1);
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, SectionKind.ROData, typeDefinitionSymbol, 0);
            }

            var staticAddress = Operand.CreateSymbol(assignmentField.FieldType, symbolName.Name);
            var result1       = AllocateVirtualRegister(assignmentField.FieldType);

            //Operand result2 = AllocateVirtualRegister(assignmentField.FieldType);

            // Issue a load request before the newobj and before the assignment.
            new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress);
            assignment.Operand1 = result1;

            // If the instruction is a newarr
            if (allocation.Instruction is CIL.NewarrInstruction)
            {
                allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1);
                return;
            }

            //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress);

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.Result      = null;
            allocation.ResultCount = 0;
            allocation.OperandCount++;

            for (int i = allocation.OperandCount; i > 0; i--)
            {
                var op = allocation.GetOperand(i - 1);
                allocation.SetOperand(i, op);
            }

            allocation.Operand1    = result1;
            allocation.Instruction = CILInstruction.Get(OpCode.Call);
        }
Beispiel #2
0
        protected override void Finish()
        {
            if (counts == null)
            {
                return;
            }

            int total = 0;

            for (int op = 0; op < counts.Length; op++)
            {
                int count = counts[op];

                if (count == 0)
                {
                    continue;
                }

                var cil = CILInstruction.Get((OpCode)op);

                //UpdateCounter("CILDecodingStage.OpCode." + cil.FullName, count);

                total += count;
            }

            //UpdateCounter("CILDecodingStage.CILInstructions", total);

            instruction = null;
            block       = null;
            counts      = null;
        }
        private void PerformStaticAllocationOf(Context allocation, Context assignment)
        {
            MosaType  allocatedType   = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            MosaField assignmentField = (assignment.Instruction is DupInstruction) ? FindStsfldForDup(assignment).MosaField : assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundry
            if (allocation.Instruction is NewarrInstruction)
            {
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * (int)allocation.Previous.Operand1.ConstantSignedLongInteger) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, BuiltInPatch.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0);
            }

            // Issue a load request before the newobj and before the assignment.
            Operand symbol1 = InsertLoadBeforeInstruction(assignment, symbolName.Name, assignmentField.FieldType);

            assignment.Operand1 = symbol1;

            // If the instruction is a newarr and the assignment instruction is a dup then we want to remove it
            if (allocation.Instruction is NewarrInstruction && assignment.Instruction is DupInstruction)
            {
                assignment.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), assignment.Result, assignment.Operand1);
            }

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.ResultCount = 0;
            if (allocation.Instruction is NewarrInstruction)
            {
                allocation.OperandCount = 0;
                allocation.SetInstruction(CILInstruction.Get(OpCode.Nop));
            }
            else
            {
                Operand symbol2           = InsertLoadBeforeInstruction(allocation, symbolName.Name, assignmentField.FieldType);
                IEnumerable <Operand> ops = allocation.Operands;
                allocation.OperandCount++;
                allocation.Operand1 = symbol2;
                int i = 0;
                foreach (Operand op in ops)
                {
                    i++;
                    allocation.SetOperand(i, op);
                }
                allocation.ReplaceInstructionOnly(CILInstruction.Get(OpCode.Call));
            }
        }
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, MosaType type)
        {
            var     before = context.InsertBefore();
            Operand result = MethodCompiler.CreateVirtualRegister(type);
            Operand op     = Operand.CreateManagedSymbol(type, symbolName);

            before.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result, op);

            return(result);
        }
Beispiel #5
0
        /// <summary>
        /// Decodes the instruction stream of the reader and populates the compiler.
        /// </summary>
        /// <exception cref="InvalidMetadataException"></exception>
        private void DecodeInstructions()
        {
            block = null;

            // Prefix instruction
            bool prefix = false;

            for (int i = 0; i < MethodCompiler.Method.Code.Count; i++)
            {
                instruction = MethodCompiler.Method.Code[i];

                block = BasicBlocks.GetByLabel(instruction.Offset) ?? block;

                var op = (OpCode)instruction.OpCode;

                var cil = CILInstruction.Get(op);

                if (cil == null)
                {
                    throw new InvalidMetadataException();
                }

                // Create and initialize the corresponding instruction
                var node = new InstructionNode();
                node.Label       = instruction.Offset;
                node.HasPrefix   = prefix;
                node.Instruction = cil;

                block.BeforeLast.Insert(node);

                cil.Decode(node, this);

                prefix = (cil is PrefixInstruction);
                instructionCount++;

                bool addjmp = false;

                var flow = node.Instruction.FlowControl;

                if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                {
                    var nextInstruction = MethodCompiler.Method.Code[i + 1];

                    if (BasicBlocks.GetByLabel(nextInstruction.Offset) != null)
                    {
                        var target = GetBlockByLabel(nextInstruction.Offset);

                        var jmpNode = new InstructionNode(IRInstruction.Jmp, target);
                        jmpNode.Label = instruction.Offset;
                        block.BeforeLast.Insert(jmpNode);
                    }
                }
            }
        }
Beispiel #6
0
        private void DecodeInstructionTargets()
        {
            bool branched = false;

            for (int i = 0; i < MethodCompiler.Method.Code.Count; i++)
            {
                instruction = MethodCompiler.Method.Code[i];

                if (branched)
                {
                    GetBlockByLabel(instruction.Offset);
                    branched = false;
                }

                var op = (OpCode)instruction.OpCode;

                var cil = CILInstruction.Get(op);

                branched = cil.DecodeTargets(this);
            }
        }