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