/* Performs indirect loading of value * (corresponds to CILPE.CFG.LoadIndirect class) */ public void Perform_LoadIndirect(Type type, out Exception exc) { exc = null; Value val = Pop(); if (val is NullValue) { exc = new NullReferenceException(); } else { if (!(val is PointerValue)) { throw new InvalidOperandException(); } object obj = (val as PointerValue).GetReferencedObject(); if (type == typeof(object)) { Push(new ObjectReferenceValue(obj)); } else { StructValue.TypeIndex typeIndex = StructValue.getTypeIndex(type); if (typeIndex != StructValue.TypeIndex.INVALID) { StructValue.TypeIndex objTypeIndex = StructValue.getTypeIndex(obj.GetType()); if (!compareTypes(objTypeIndex, typeIndex)) { throw new InvalidOperandException(); } Push(new StructValue(obj as ValueType)); } else if (type.IsValueType) { if (type != obj.GetType()) { throw new InvalidOperandException(); } Push(new StructValue(obj as ValueType)); } else { throw new InvalidLoadIndirectException(); } } } }
/* Performs loading of array element * (corresponds to CILPE.CFG.LoadElement class) */ public void Perform_LoadElement(Type type, out Exception exc) { int index = popArrayIndex(); Array array = popArray(out exc); if (exc == null) { if (type != typeof(object)) { StructValue.TypeIndex typeIndex = StructValue.getTypeIndex(type); StructValue.TypeIndex arrTypeIndex = StructValue.getTypeIndex(array.GetType().GetElementType()); if (!compareTypes(arrTypeIndex, typeIndex)) { exc = new ArrayTypeMismatchException(); } } if (exc == null) { object elem = null; try { elem = array.GetValue(index); } catch (IndexOutOfRangeException e) { exc = e; } if (exc == null) { if (StructValue.getTypeIndex(type) != StructValue.TypeIndex.INVALID) { Push(new StructValue(elem as ValueType)); } else { if (elem != null) { Push(new ObjectReferenceValue(elem)); } else { Push(new NullValue()); } } } } } }
/* Performs conversion of primitive value on top of the stack * (corresponds to CILPE.CFG.ConvertValue class) */ public void Perform_ConvertValue(Type type, bool overflow, bool unsigned, out Exception exc) { exc = null; Value val = Pop(); if (!(val is StructValue && (val as StructValue).IsPrimitive)) { throw new InvalidOperandException(); } StructValue primVal = val as StructValue; StructValue.TypeIndex typeIndex = StructValue.getTypeIndex(type), valTypeIndex = primVal.getTypeIndex(); if (!overflow && unsigned && typeIndex != StructValue.TypeIndex.FLOAT64 || overflow && typeIndex == StructValue.TypeIndex.FLOAT32 || overflow && typeIndex == StructValue.TypeIndex.FLOAT64) { throw new InvalidConvertOpException(); } object res; bool success = DataModelUtils.Convert( (int)typeIndex, overflow, unsigned, primVal.Obj, (int)valTypeIndex, out res ); if (!success) { exc = res as Exception; } else { push(new StructValue(res as ValueType)); } }
private bool compareTypes(StructValue.TypeIndex type1, StructValue.TypeIndex type2) { if (type1 == StructValue.TypeIndex.UNATIVEINT && type2 == StructValue.TypeIndex.NATIVEINT) { type2 = StructValue.TypeIndex.UNATIVEINT; } if (type1 == StructValue.TypeIndex.CHAR && type2 == StructValue.TypeIndex.UINT16) { type2 = StructValue.TypeIndex.CHAR; } if (type1 == StructValue.TypeIndex.BOOL && type2 == StructValue.TypeIndex.INT8) { type2 = StructValue.TypeIndex.BOOL; } return(type1 == type2); }
/* Performs unary operation on the value on top of the stack * (corresponds to CILPE.CFG.UnaryOp class) */ public void Perform_UnaryOp(UnaryOp.ArithOp op) { Value val = Pop(); ValueType res = null; if (val is StructValue && (val as StructValue).IsPrimitive) { StructValue strVal = val as StructValue; ValueType obj = strVal.Obj; StructValue.TypeIndex typeIndex = strVal.getTypeIndex(); if (!DataModelUtils.Unary((int)op, obj, (int)typeIndex, out res)) { throw new InvalidOperandException(); } } else { throw new InvalidOperandException(); } push(new StructValue(res)); }
/* Performs binary operation on two values on top of the stack * (corresponds to CILPE.CFG.BinaryOp class) */ public void Perform_BinaryOp(BinaryOp.ArithOp op, bool overflow, bool unsigned, out Exception exc) { exc = null; /* Determining category of binary operation */ OpCategory category = getCategory(op, overflow, unsigned); if (category == OpCategory.InvalidOp) { throw new InvalidBinaryOpException(); } /* Getting operands from stack */ Value val1, val2; val2 = Pop(); val1 = Pop(); /* Performing binary operation */ object res = null; if (val1 is StructValue && val2 is StructValue) { StructValue.TypeIndex typeA = (val1 as StructValue).getTypeIndex(), typeB = (val2 as StructValue).getTypeIndex(); if (typeA == StructValue.TypeIndex.INVALID || typeB == StructValue.TypeIndex.INVALID) { throw new InvalidOperandException(); } ValueType a = (val1 as StructValue).Obj, b = (val2 as StructValue).Obj; int operandsKind = 0; bool success = true; if (category == OpCategory.ShiftOp) /* shl, shr, shr_un */ { if (typeA == StructValue.TypeIndex.FLOAT64 || typeB == StructValue.TypeIndex.FLOAT64 || typeB == StructValue.TypeIndex.INT64) { throw new InvalidOperandException(); } operandsKind = ((typeB == StructValue.TypeIndex.INT32) ? 0 : 3) + (int)typeA; DataModelUtils.ShiftOp((int)op, unsigned, a, b, operandsKind, out res); } else { if (typeA == typeB) { operandsKind = (int)typeA; } else if (typeA == StructValue.TypeIndex.INT32 && typeB == StructValue.TypeIndex.NATIVEINT) { operandsKind = 4; } else if (typeA == StructValue.TypeIndex.NATIVEINT && typeB == StructValue.TypeIndex.INT32) { operandsKind = 5; } else { throw new InvalidOperandException(); } switch (category) { case OpCategory.NumericOp: /* add, div, mul, rem, sub */ success = DataModelUtils.NumericOp((int)op, a, b, operandsKind, out res); break; case OpCategory.ComparisonOp: /* ceq, cgt, cgt.un, clt, clt.un */ DataModelUtils.ComparisonOp((int)op, unsigned, a, b, operandsKind, out res); break; case OpCategory.IntegerOp: /* and, div.un, or, rem.un, xor */ case OpCategory.OverflowOp: /* add.ovf, add.ovf.un, mul.ovf, mul.ovf.un, sub.ovf, sub.ovf.un */ if (operandsKind == 3) { throw new InvalidOperandException(); } success = DataModelUtils.IntOvfOp((int)op, unsigned, a, b, operandsKind, out res); break; } } if (!success) { exc = res as Exception; res = null; } } else if (op == BinaryOp.ArithOp.CEQ) { if ((val1 is NullValue || val1 is ObjectReferenceValue) && (val2 is NullValue || val2 is ObjectReferenceValue) || (val1 is NullValue || val1 is PointerValue) && (val2 is NullValue || val2 is PointerValue)) { res = Equals(val1, val2) ? (Int32)1 : (Int32)0; } else { throw new InvalidOperandException(); } } else if (op == BinaryOp.ArithOp.CGT) { if (val1 is ObjectReferenceValue && val2 is NullValue && unsigned) { res = (Int32)1; } else if (val1 is NullValue && val2 is NullValue) { res = (Int32)0; } else if (val1 is PointerValue && val2 is NullValue) { res = (Int32)1; } else { throw new InvalidOperandException(); } } else if (op == BinaryOp.ArithOp.CLT) { if (val1 is NullValue && val2 is ObjectReferenceValue && unsigned) { res = (Int32)1; } else if (val1 is NullValue && val2 is NullValue) { res = (Int32)0; } else if (val1 is NullValue && val2 is PointerValue) { res = (Int32)1; } else { throw new InvalidOperandException(); } } else { throw new InvalidOperandException(); } if (res != null) { push(new StructValue(res as ValueType)); } }