Example #1
0
        /// <summary>
        /// Decodes the specified instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
        public override void Decode(Context ctx, IInstructionDecoder decoder)
        {
            // Decode base classes first
            base.Decode(ctx, decoder);

            // Read the type specification
            Token token = decoder.DecodeTokenType();

            // Patch usage of generic arguments
            var enclosingType = decoder.Method.DeclaringType;
            var signatureType = decoder.GenericTypePatcher.PatchSignatureType(decoder.TypeModule, enclosingType, token);

            // FIXME: If ctx.Operands1 is an integral constant, we can infer the maximum size of the array
            // and instantiate an ArrayTypeSpecification with max. sizes. This way we could eliminate bounds
            // checks in an optimization stage later on, if we find that a value never exceeds the array
            // bounds.
            var resultType = new SZArraySigType(null, signatureType);
            ctx.Result = decoder.Compiler.CreateTemporary(resultType);
        }
        /// <summary>
        /// Parses an SZArray attribute value.
        /// </summary>
        /// <param name="reader">The binary reader used to read from the attribute blob.</param>
        /// <param name="sigType">Type of the SZArray.</param>
        /// <returns>
        /// An Array, which represents the SZArray definition.
        /// </returns>
        private static object ParseSZArrayArg(BinaryReader reader, SZArraySigType sigType)
        {
            // Return value
            Array result;

            // Determine the number of elements
            int numElements = reader.ReadInt32();
            if (-1 == numElements)
                return null;

            // Retrieve the array element type
            Type elementType = GetTypeFromSigType(sigType);
            Debug.Assert(null != elementType, @"Failed to get System.Type for SigType.");

            result = Array.CreateInstance(elementType, numElements);
            for (int idx = 0; idx < numElements; idx++)
            {
                object item = ParseElem(reader, sigType.ElementType);
                result.SetValue(item, idx);
            }

            return result;
        }
        private Operand CalculateArrayElementOffset(Context context, SZArraySigType arraySignatureType, Operand arrayIndexOperand)
        {
            int elementSizeInBytes = 0, alignment = 0;
            architecture.GetTypeRequirements(arraySignatureType.ElementType, out elementSizeInBytes, out alignment);

            //
            // The sequence we're emitting is:
            //
            //      offset = arrayIndexOperand * elementSize
            //      temp = offset + 12
            //      result = *(arrayOperand * temp)
            //
            // The array data starts at offset 12 from the array object itself. The 12 is a hardcoded assumption
            // of x86, which might change for other platforms. We need to refactor this into some helper classes.
            //

            Operand elementOffset = methodCompiler.CreateVirtualRegister(BuiltInSigType.Int32);
            Operand elementSizeOperand = Operand.CreateConstant(BuiltInSigType.Int32, elementSizeInBytes);
            context.AppendInstruction(IRInstruction.MulS, elementOffset, arrayIndexOperand, elementSizeOperand);

            return elementOffset;
        }
 private Operand LoadArrayBaseAddress(Context context, SZArraySigType arraySignatureType, Operand arrayOperand)
 {
     Operand arrayAddress = methodCompiler.CreateVirtualRegister(new PtrSigType(arraySignatureType.ElementType));
     Operand fixedOffset = Operand.CreateConstant(BuiltInSigType.Int32, 12);
     context.SetInstruction(IRInstruction.AddS, arrayAddress, arrayOperand, fixedOffset);
     return arrayAddress;
 }
 private Operand LoadArrayBaseAddress(Context context, SZArraySigType arraySignatureType, Operand arrayOperand)
 {
     Operand arrayAddress = this.methodCompiler.CreateTemporary(new PtrSigType(arraySignatureType.ElementType));
     Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, 12);
     context.SetInstruction(Instruction.AddSInstruction, arrayAddress, arrayOperand, fixedOffset);
     return arrayAddress;
 }