public void Create(Type type) { if (!type.IsArray) { var constructor = type.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new InvalidOperationException("Missing parameterless constructor for type '" + type + "'"); } Il.Newobj(constructor); } else { var rank = type.GetArrayRank(); if (rank == 1) { Il.Ldc_I4(0); Il.Newarr(type.GetElementType()); } else { var constructor = type.GetConstructor(Enumerable.Repeat(typeof(int), rank).ToArray()); if (constructor == null) { throw new InvalidOperationException(string.Format("Missing constructor accepting {0} integers for type '{1}'", rank, type)); } for (int i = 0; i < rank; ++i) { Il.Ldc_I4(0); } Il.Newobj(constructor); } } }
/// <summary> /// Increases <c>index</c> by 8 /// </summary> public void IncreaseIndexBy8() { LoadIndexByRef(); // stack: [ref index] LoadIndex(); // stack: [ref index, index] Il.Ldc_I4(8); // stack: [ref index, index, 8] Il.Add(); // stack: [ref index, index + 8] Il.Stind(typeof(int)); // index = index + 8 }
/// <summary> /// Puts the specified type code at <c>result</c>[<c>index</c>] /// </summary> /// <param name="typeCode">Type code to put</param> public void WriteTypeCode(GroBufTypeCode typeCode) { Il.Ldc_I4(1); AssertLength(); GoToCurrentLocation(); // stack: [&result[index]] Il.Ldc_I4((int)typeCode); // stack: [&result[index], typeCode] Il.Stind(typeof(byte)); // result[index] = typeCode IncreaseIndexBy1(); // index = index + 1 }
public void LoadCompiledLambda(CompiledLambda compiledLambda) { if (ParsedLambda.ConstantsParameter == null) { throw new InvalidOperationException("There is no constants parameter. Cannot load sublambda"); } Type temp; var delegatesAccessor = ParsedLambda.ConstantsBuilder.MakeAccess(ParsedLambda.ConstantsParameter, ParsedLambda.DelegatesFieldId); ExpressionEmittersCollection.Emit(delegatesAccessor, this, out temp); Il.Ldc_I4(compiledLambda.Index); Il.Ldelem(typeof(Delegate)); }
public void AssertTypeCode(GroBufTypeCode expectedTypeCode) { Il.Ldloc(TypeCode); // stack: [typeCode] Il.Ldc_I4((int)expectedTypeCode); // stack: [typeCode, expectedTypeCode] var okLabel = Il.DefineLabel("ok"); Il.Beq(okLabel); SkipValue(); Il.Ret(); Il.MarkLabel(okLabel); }
public void SkipValue() { LoadIndexByRef(); // stack: [ref index] LoadIndex(); // stack: [ref index, index] // todo: сделать switch Il.Ldloc(TypeCode); // stack: [ref index, index, TypeCode] Il.Ldc_I4((int)GroBufTypeCode.DateTimeOld); // stack: [ref index, index, TypeCode, GroBufTypeCode.DateTimeOld] var notDateTimeLabel = Il.DefineLabel("notDateTime"); Il.Bne_Un(notDateTimeLabel); // if(TypeCode != GroBufTypeCode.DateTimeOld) goto notDateTime; stack: [ref index, index] Il.Ldc_I4(8); // stack: [ref index, index, 8] AssertLength(); GoToCurrentLocation(); // stack: [ref index, index, &data[index]] Il.Ldc_I4(4); Il.Add(); Il.Ldind(typeof(int)); // stack: [ref index, index, (int)(&data[index])] Il.Ldc_I4(31); // stack: [ref index, index, (int)&data[index], 31] Il.Shr(true); // stack: [ref index, index, (int)&data[index] >> 31] Il.Ldc_I4(8); // stack: [ref index, index, (int)&data[index] >> 31, 8] Il.Add(); // stack: [ref index, index, (int)&data[index] >> 31 + 8] var increaseLabel = Il.DefineLabel("increase"); Il.Br(increaseLabel); Il.MarkLabel(notDateTimeLabel); LoadField(Context.Lengths); Il.Ldloc(TypeCode); // stack: [ref index, index, lengths, typeCode] Il.Ldelem(typeof(int)); // stack: [ref index, index, lengths[typeCode]] Il.Dup(); // stack: [ref index, index, lengths[typeCode], lengths[typeCode]] Il.Ldc_I4(-1); // stack: [ref index, index, lengths[typeCode], lengths[typeCode], -1] Il.Bne_Un(increaseLabel); // if(lengths[typeCode] != -1) goto increase; Il.Ldc_I4(4); AssertLength(); Il.Pop(); // stack: [ref index, index] Il.Dup(); // stack: [ref index, index, index] LoadData(); // stack: [ref index, index, index, pinnedData] Il.Add(); // stack: [ref index, index, index + pinnedData] Il.Ldind(typeof(uint)); // stack: [ref index, index, *(uint*)(pinnedData + index)] Il.Ldc_I4(4); // stack: [ref index, index, *(uint*)(pinnedData + index), 4] Il.Add(); // stack: [ref index, *(uint*)(pinnedData + index) + 4] Il.MarkLabel(increaseLabel); Il.Dup(); // stack: [ref index, length, length] AssertLength(); // stack: [ref index, length] Il.Add(); // stack: [ref index, index + length] Il.Stind(typeof(int)); // index = index + length }