static RuleBasedPrototypeExceptionSpecs() { Default = new RuleBasedPrototypeExceptionSpecs(); // Instruction prototypes that never throw. Default.Register <AllocaArrayPrototype>(ExceptionSpecification.NoThrow); Default.Register <AllocaPrototype>(ExceptionSpecification.NoThrow); Default.Register <BoxPrototype>(ExceptionSpecification.NoThrow); Default.Register <ConstantPrototype>(ExceptionSpecification.NoThrow); Default.Register <CopyPrototype>(ExceptionSpecification.NoThrow); Default.Register <DynamicCastPrototype>(ExceptionSpecification.NoThrow); Default.Register <GetStaticFieldPointerPrototype>(ExceptionSpecification.NoThrow); Default.Register <LoadPrototype>(ExceptionSpecification.NoThrow); Default.Register <ReinterpretCastPrototype>(ExceptionSpecification.NoThrow); Default.Register <StorePrototype>(ExceptionSpecification.NoThrow); // Instruction prototypes that may throw because of implicit null checks. Default.Register <GetFieldPointerPrototype>( new NullCheckExceptionSpecification(0, ExceptionSpecification.ThrowAny)); Default.Register <NewDelegatePrototype>( proto => proto.Lookup == MethodLookup.Virtual ? new NullCheckExceptionSpecification(0, ExceptionSpecification.ThrowAny) : ExceptionSpecification.NoThrow); Default.Register <UnboxPrototype>( new NullCheckExceptionSpecification(0, ExceptionSpecification.ThrowAny)); // Call-like instruction prototypes. Default.Register <CallPrototype>( proto => proto.Lookup == MethodLookup.Static ? proto.Callee.GetExceptionSpecification() : ExceptionSpecification.ThrowAny); Default.Register <NewObjectPrototype>( proto => proto.Constructor.GetExceptionSpecification()); Default.Register <IndirectCallPrototype>(ExceptionSpecification.ThrowAny); // Unchecked arithmetic intrinsics never throw. foreach (var name in ArithmeticIntrinsics.Operators.All) { Default.Register( ArithmeticIntrinsics.GetArithmeticIntrinsicName(name, false), ExceptionSpecification.NoThrow); } // Array intrinsics are a little more complicated. // TODO: model bounds checks somehow. Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetElementPointer), ExceptionSpecification.ThrowAny); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.LoadElement), ExceptionSpecification.ThrowAny); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.StoreElement), ExceptionSpecification.ThrowAny); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetLength), new NullCheckExceptionSpecification(0, ExceptionSpecification.ThrowAny)); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.NewArray), ExceptionSpecification.NoThrow); // Exception intrinsics. Default.Register( ExceptionIntrinsics.Namespace.GetIntrinsicName(ExceptionIntrinsics.Operators.Capture), ExceptionSpecification.NoThrow); Default.Register( ExceptionIntrinsics.Namespace.GetIntrinsicName(ExceptionIntrinsics.Operators.GetCapturedException), ExceptionSpecification.NoThrow); Default.Register( ExceptionIntrinsics.Namespace.GetIntrinsicName(ExceptionIntrinsics.Operators.Rethrow), ExceptionSpecification.ThrowAny); Default.Register( ExceptionIntrinsics.Namespace.GetIntrinsicName(ExceptionIntrinsics.Operators.Throw), proto => ExceptionSpecification.Exact.Create(proto.ParameterTypes[0])); // Object intrinsics. // TODO: model exception thrown by type check. Default.Register( ObjectIntrinsics.Namespace.GetIntrinsicName(ObjectIntrinsics.Operators.UnboxAny), ExceptionSpecification.ThrowAny); // Memory intrinsics. Default.Register( MemoryIntrinsics.Namespace.GetIntrinsicName(MemoryIntrinsics.Operators.AllocaPinned), ExceptionSpecification.NoThrow); }
static RuleBasedPrototypeMemorySpecs() { Default = new RuleBasedPrototypeMemorySpecs(); Default.Register <AllocaArrayPrototype>(MemorySpecification.Nothing); Default.Register <AllocaPrototype>(MemorySpecification.Nothing); Default.Register <BoxPrototype>(MemorySpecification.Nothing); Default.Register <ConstantPrototype>(MemorySpecification.Nothing); Default.Register <CopyPrototype>(MemorySpecification.Nothing); Default.Register <DynamicCastPrototype>(MemorySpecification.Nothing); Default.Register <GetStaticFieldPointerPrototype>(MemorySpecification.Nothing); Default.Register <ReinterpretCastPrototype>(MemorySpecification.Nothing); Default.Register <GetFieldPointerPrototype>(MemorySpecification.Nothing); Default.Register <NewDelegatePrototype>(MemorySpecification.Nothing); Default.Register <UnboxPrototype>(MemorySpecification.Nothing); // Mark volatile loads and stores as unknown to ensure that they are never reordered // with regard to other memory operations. // TODO: is this really how we should represent volatility? Default.Register <LoadPrototype>(proto => proto.IsVolatile ? MemorySpecification.Unknown : MemorySpecification.ArgumentRead.Create(0)); Default.Register <StorePrototype>(proto => proto.IsVolatile ? MemorySpecification.Unknown : MemorySpecification.ArgumentWrite.Create(0)); // Call-like instruction prototypes. Default.Register <CallPrototype>( proto => proto.Lookup == MethodLookup.Static ? proto.Callee.GetMemorySpecification() : MemorySpecification.Unknown); Default.Register <NewObjectPrototype>( proto => proto.Constructor.GetMemorySpecification()); Default.Register <IndirectCallPrototype>(MemorySpecification.Unknown); // Arithmetic intrinsics never read or write. foreach (var name in ArithmeticIntrinsics.Operators.All) { Default.Register( ArithmeticIntrinsics.GetArithmeticIntrinsicName(name, false), MemorySpecification.Nothing); Default.Register( ArithmeticIntrinsics.GetArithmeticIntrinsicName(name, true), MemorySpecification.Nothing); } // Array intrinsics. Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetElementPointer), MemorySpecification.Nothing); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.LoadElement), MemorySpecification.UnknownRead); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.StoreElement), MemorySpecification.UnknownWrite); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetLength), MemorySpecification.Nothing); Default.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.NewArray), MemorySpecification.Nothing); // Exception intrinsics. Default.Register( ExceptionIntrinsics.Namespace.GetIntrinsicName(ExceptionIntrinsics.Operators.GetCapturedException), MemorySpecification.UnknownRead); // Object intrinsics. Default.Register( ObjectIntrinsics.Namespace.GetIntrinsicName(ObjectIntrinsics.Operators.UnboxAny), MemorySpecification.UnknownRead); // Memory intrinsics. Default.Register( MemoryIntrinsics.Namespace.GetIntrinsicName(MemoryIntrinsics.Operators.AllocaPinned), MemorySpecification.Nothing); }