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); }
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)); }
public virtual CodeNode VisitValidateSharedLengthLocal(ValidateSharedLengthLocalNode node) { return(node); }