Beispiel #1
0
 public override CodeNode VisitValidateSharedLengthLocal(ValidateSharedLengthLocalNode node)
 {
     _Writer.WriteStartElement("ValidateSharedLengthLocal");
     _Writer.WriteAttributeString("ArrayFieldIndex", node.ArrayFieldIndex.ToString());
     _Writer.WriteAttributeString("LengthFieldIndex", node.LengthFieldIndex.ToString());
     _Writer.WriteEndElement();
     return(node);
 }
Beispiel #2
0
        public override CodeNode VisitValidateSharedLengthLocal(ValidateSharedLengthLocalNode node)
        {
            Log($"Validationg shared length with index {node.LengthFieldIndex}.");
            var arrayLocal  = _FieldLocals[node.ArrayFieldIndex];
            var lengthLocal = _FieldLocals[node.LengthFieldIndex];

            //someone else created the length, we need to verify they are equal
            var dontThrow     = ILGen.DefineLabel();
            var notNull       = ILGen.DefineLabel();
            var compareLength = ILGen.DefineLabel();

            ILGen.Ldloc(arrayLocal);
            //if the array is null, goto notNulls
            ILGen.Ldnull();
            ILGen.Ceq();
            ILGen.Brfalse(notNull);
            //it is null, treat the length as 0 and compare the length
            Log($"Array is null (treat as zero length).");

            ILGen.Ldc_I4_0();
            ILGen.Br(compareLength);

            //array is not null. get its real length
            ILGen.MarkLabel(notNull);
            Log($"Getting array length.");
            ILGen.Ldloc(arrayLocal);
            ILGen.Ldlen();

            ILGen.MarkLabel(compareLength);
            Log($"Comparing length array length.");
            //FYI, we don't need a special case for nibble since we represent it as a byte array
            if (lengthLocal.LocalType == typeof(ushort))
            {
                ILGen.Conv_U2();
            }
            else if (lengthLocal.LocalType == typeof(byte))
            {
                ILGen.Conv_I4();
            }
            else
            {
                throw new NotSupportedException(string.Format(Resources.UnsupportedArrayLengthType, lengthLocal.LocalType));
            }
            ILGen.Ldloc(lengthLocal);
            ILGen.Ceq();
            ILGen.Brtrue(dontThrow);
            Log($"Lengths aren't equal. Throw.");

            ILGen.Ldstr(string.Format(Resources.SharedLengthViolation, node.LengthFieldIndex));
            ILGen.Newobj <InvalidOperationException>(typeof(string));
            ILGen.Throw();
            ILGen.MarkLabel(dontThrow);
            Log($"Done.");
            return(node);
        }
        CodeNode GenerateArrayAssignment(KeyValuePair <FieldLayoutAttribute, PropertyInfo> pair)
        {
            var fieldType = pair.Key.FieldType;
            ArrayFieldLayoutAttribute arrayLayout = (ArrayFieldLayoutAttribute)pair.Key;

            var initNodes = new List <CodeNode>();

            //there are no array optionals, we should always have to create the local here
            if (_FieldLocalsTouched.Add(arrayLayout.FieldIndex))
            {
                initNodes.Add(new CreateFieldLocalForWritingNode(arrayLayout.FieldIndex, fieldType.MakeArrayType()));
            }
            else
            {
                throw new InvalidOperationException("Array local was touched before we generated code for it.");
            }

            if (pair.Value == null)
            {
                throw new InvalidOperationException(Resources.ArraysMustBeAssignable);
            }

            CodeNode             writeNode;
            FieldLayoutAttribute lengthLayout = _Fields[arrayLayout.ArrayLengthFieldIndex].Key;

            if (_FieldLocalsTouched.Add(arrayLayout.ArrayLengthFieldIndex))
            {
                writeNode = new BlockNode(
                    new CreateFieldLocalForWritingNode(arrayLayout.ArrayLengthFieldIndex, _Fields[arrayLayout.ArrayLengthFieldIndex].Key.FieldType),
                    new SetLengthLocalNode(arrayLayout.FieldIndex, arrayLayout.ArrayLengthFieldIndex));
            }
            else
            {
                writeNode = new ValidateSharedLengthLocalNode(arrayLayout.FieldIndex, arrayLayout.ArrayLengthFieldIndex);
            }

            writeNode = new BlockNode(
                writeNode,
                new WriteTypeNode(fieldType.MakeArrayType(), new LoadFieldLocalNode(arrayLayout.FieldIndex)));

            return(new WriteFieldNode(arrayLayout.FieldIndex, fieldType.MakeArrayType(),
                                      initialization: new BlockNode(initNodes),
                                      sourceProperty: pair.Value,
                                      writeOperation: writeNode));
        }
Beispiel #4
0
 public virtual CodeNode VisitValidateSharedLengthLocal(ValidateSharedLengthLocalNode node)
 {
     return(node);
 }