예제 #1
0
 public void LoadValue(Local local)
 {
     if (local == null) /* nothing to do; top of stack */ } {
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
			if (arrayType.GetArrayRank() > 1)
			{
				return;
			}

            // int i and T[] arr
            using (Compiler.Local arr = ctx.GetLocalWithValue(arrayType, valueFrom))
			using (Compiler.Local len = new Compiler.Local(ctx, typeof(int)))
            using (Compiler.Local i = new ProtoBuf.Compiler.Local(ctx, typeof(int)))
			using (Compiler.Local writeObject = new Compiler.Local(ctx, typeof(bool)))
            {
				// int len = arr.Count;
				ctx.LoadValue(arr);
				ctx.LoadValue(arrayType.GetProperty("Length"));
				ctx.StoreValue(len);

				// writeObject = true;
				ctx.LoadValue(true);
				ctx.StoreValue(writeObject);

                bool writePacked = (options & OPTIONS_WritePacked) != 0;
                using (Compiler.Local token = writePacked ? new Compiler.Local(ctx, typeof(SubItemToken)) : null)
                {
                    if (writePacked)
                    {
                        ctx.LoadValue(fieldNumber);
                        ctx.LoadValue((int)WireType.String);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteFieldHeader"));

                        ctx.LoadValue(arr);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("StartSubItem"));
                        ctx.StoreValue(token);

                        ctx.LoadValue(fieldNumber);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField"));
                    }
                    else
                    {
                    	ctx.LoadValue(fieldNumber);
						ctx.LoadValue((int)WireType.Variant);
						ctx.LoadReaderWriter();
						ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteFieldHeader"));

						if (AsReference)
						{
							using (Compiler.Local existing = new Compiler.Local(ctx, typeof(bool)))
							using (Compiler.Local objectKey = new Compiler.Local(ctx, typeof(int)))
							{
								//int objectKey = dest.NetCache.AddObjectKey(value, out existing);
								ctx.LoadReaderWriter();
								ctx.LoadValue(typeof(ProtoWriter).GetProperty("NetCache")); //dest.NetCache
								ctx.LoadValue(arr);
								ctx.LoadAddress(existing, typeof(bool));
								ctx.EmitCall(typeof(NetObjectCache).GetMethod("AddObjectKey", new Type[] { typeof(object), typeof(bool).MakeByRefType() }));
								ctx.StoreValue(objectKey);

								//writeObject = !existing;
								ctx.LoadValue(existing);

								Compiler.CodeLabel @writeBoolean = ctx.DefineLabel();
								Compiler.CodeLabel @trueCase = ctx.DefineLabel();

								ctx.BranchIfTrue(@trueCase, true);
								ctx.LoadValue(true);
								ctx.Branch(@writeBoolean, true);
								ctx.MarkLabel(@trueCase);
								ctx.LoadValue(false);
								ctx.MarkLabel(@writeBoolean);
								
								ctx.StoreValue(writeObject);

								//ProtoWriter.WriteUInt32(existing ? (uint)objectKey : 0, dest);
								using (Compiler.Local valueToWrite = new Compiler.Local(ctx, typeof(uint)))
								{
                                    ctx.LoadValue(0);
                                    ctx.StoreValue(valueToWrite);

									Compiler.CodeLabel @endValueWrite = ctx.DefineLabel();

									ctx.LoadValue(existing);
									ctx.BranchIfFalse(@endValueWrite, true);

									ctx.LoadValue(objectKey);
									ctx.CastToObject(typeof(uint));
									ctx.StoreValue(valueToWrite);

									ctx.MarkLabel(@endValueWrite);

									ctx.LoadValue(valueToWrite);
									ctx.LoadReaderWriter();
									ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteUInt32"));
								}
							}
						}
						else
						{
							// bool isEmpty = len == 0;
							// ProtoWriter.WriteBoolean(isEmpty, dest);
							ctx.LoadValue(len);
							ctx.LoadValue(0);
							ctx.TestEqual();
							ctx.LoadReaderWriter();
							ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteBoolean"));
						}
                    }

                	Compiler.CodeLabel @endWrite = ctx.DefineLabel();
                	ctx.LoadValue(writeObject);
                	ctx.BranchIfFalse(@endWrite, false);

                    EmitWriteArrayLoop(ctx, i, arr);

					ctx.MarkLabel(@endWrite);
						
                    if (writePacked)
                    {
                        ctx.LoadValue(token);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("EndSubItem"));
                    }
                }
            }
        }
예제 #3
0
        internal void LoadArrayValue(Local arr, Local i)
        {
            Type type = arr.Type;

            type = type.GetElementType();
            this.LoadValue(arr);
            this.LoadValue(i);
            switch (Helpers.GetTypeCode(type))
            {
            case ProtoTypeCode.SByte:
            {
                this.Emit(OpCodes.Ldelem_I1);
                return;
            }

            case ProtoTypeCode.Byte:
            {
                this.Emit(OpCodes.Ldelem_U1);
                return;
            }

            case ProtoTypeCode.Int16:
            {
                this.Emit(OpCodes.Ldelem_I2);
                return;
            }

            case ProtoTypeCode.UInt16:
            {
                this.Emit(OpCodes.Ldelem_U2);
                return;
            }

            case ProtoTypeCode.Int32:
            {
                this.Emit(OpCodes.Ldelem_I4);
                return;
            }

            case ProtoTypeCode.UInt32:
            {
                this.Emit(OpCodes.Ldelem_U4);
                return;
            }

            case ProtoTypeCode.Int64:
            {
                this.Emit(OpCodes.Ldelem_I8);
                return;
            }

            case ProtoTypeCode.UInt64:
            {
                this.Emit(OpCodes.Ldelem_I8);
                return;
            }

            case ProtoTypeCode.Single:
            {
                this.Emit(OpCodes.Ldelem_R4);
                return;
            }

            case ProtoTypeCode.Double:
            {
                this.Emit(OpCodes.Ldelem_R8);
                return;
            }
            }
            if (!type.IsValueType)
            {
                this.Emit(OpCodes.Ldelem_Ref);
                return;
            }
            this.il.Emit(OpCodes.Ldelema, type);
            this.il.Emit(OpCodes.Ldobj, type);
        }
예제 #4
0
 internal void CreateArray(Type elementType, Local length)
 {
     this.LoadValue(length);
     this.il.Emit(OpCodes.Newarr, elementType);
 }
예제 #5
0
 public IDisposable Using(Local local)
 {
     return(new CompilerContext.UsingBlock(this, local));
 }
예제 #6
0
 private bool UseShortForm(Local local)
 {
     return(local.Value.LocalIndex < 256);
 }
예제 #7
0
 public void Switch(CodeLabel[] jumpTable)
 {
     if ((int)jumpTable.Length <= 128)
     {
         Label[] value = new Label[(int)jumpTable.Length];
         for (int i = 0; i < (int)value.Length; i++)
         {
             value[i] = jumpTable[i].Value;
         }
         this.il.Emit(OpCodes.Switch, value);
         return;
     }
     using (Local localWithValue = this.GetLocalWithValue(this.MapType(typeof(int)), null))
     {
         int length = (int)jumpTable.Length;
         int num    = 0;
         int num1   = length / 128;
         if (length % 128 != 0)
         {
             num1++;
         }
         Label[] labelArray = new Label[num1];
         for (int j = 0; j < num1; j++)
         {
             labelArray[j] = this.il.DefineLabel();
         }
         CodeLabel codeLabel = this.DefineLabel();
         this.LoadValue(localWithValue);
         this.LoadValue(128);
         this.Emit(OpCodes.Div);
         this.il.Emit(OpCodes.Switch, labelArray);
         this.Branch(codeLabel, false);
         Label[] value1 = new Label[128];
         for (int k = 0; k < num1; k++)
         {
             this.il.MarkLabel(labelArray[k]);
             int num2 = Math.Min(128, length);
             length -= num2;
             if ((int)value1.Length != num2)
             {
                 value1 = new Label[num2];
             }
             int num3 = num;
             for (int l = 0; l < num2; l++)
             {
                 int num4 = num;
                 num       = num4 + 1;
                 value1[l] = jumpTable[num4].Value;
             }
             this.LoadValue(localWithValue);
             if (num3 != 0)
             {
                 this.LoadValue(num3);
                 this.Emit(OpCodes.Sub);
             }
             this.il.Emit(OpCodes.Switch, value1);
             if (length != 0)
             {
                 this.Branch(codeLabel, false);
             }
         }
         this.MarkLabel(codeLabel);
     }
 }