void DoEmit(EmitContext ec, bool is_expr) { Label is_null_label = ec.DefineLabel(); Label end_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); if (is_expr) { underlying.Emit(ec); ec.Emit(OpCodes.Br_S, end_label); } else { underlying.EmitStatement(ec); } ec.MarkLabel(is_null_label); if (is_expr) { LiftedNull.Create(type, loc).Emit(ec); } ec.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { Label is_null_label = ec.DefineLabel(); Label end_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); if (user_operator != null) { user_operator.Emit(ec); } else { EmitOperator(ec, NullableInfo.GetUnderlyingType(type)); } ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type)); ec.Emit(OpCodes.Br_S, end_label); ec.MarkLabel(is_null_label); LiftedNull.Create(type, loc).Emit(ec); ec.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { ILGenerator ig = ec.ig; Label is_null_label = ig.DefineLabel(); Label end_label = ig.DefineLabel(); unwrap.EmitCheck(ec); ig.Emit(OpCodes.Brfalse, is_null_label); NullableInfo ni = new NullableInfo(type); if (user_operator != null) { user_operator.Emit(ec); } else { EmitOperator(ec, ni.UnderlyingType); } ig.Emit(OpCodes.Newobj, ni.Constructor); ig.Emit(OpCodes.Br_S, end_label); ig.MarkLabel(is_null_label); LiftedNull.Create(type, loc).Emit(ec); ig.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { ILGenerator ig = ec.ig; Label end_label = ig.DefineLabel(); if (unwrap != null) { Label is_null_label = ig.DefineLabel(); unwrap.EmitCheck(ec); ig.Emit(OpCodes.Brfalse, is_null_label); left.Emit(ec); ig.Emit(OpCodes.Br, end_label); ig.MarkLabel(is_null_label); right.Emit(ec); ig.MarkLabel(end_label); return; } left.Emit(ec); ig.Emit(OpCodes.Dup); ig.Emit(OpCodes.Brtrue, end_label); ig.Emit(OpCodes.Pop); right.Emit(ec); ig.MarkLabel(end_label); }
void EmitBitwiseBoolean(EmitContext ec) { ILGenerator ig = ec.ig; Label load_left = ig.DefineLabel(); Label load_right = ig.DefineLabel(); Label end_label = ig.DefineLabel(); left_unwrap.Emit(ec); ig.Emit(OpCodes.Brtrue_S, load_right); right_unwrap.Emit(ec); ig.Emit(OpCodes.Brtrue_S, load_left); left_unwrap.EmitCheck(ec); ig.Emit(OpCodes.Brfalse_S, load_right); // load left ig.MarkLabel(load_left); if (Oper == Operator.BitwiseAnd) { left_unwrap.Load(ec); } else { right_unwrap.Load(ec); right_unwrap = left_unwrap; } ig.Emit(OpCodes.Br_S, end_label); // load right ig.MarkLabel(load_right); right_unwrap.Load(ec); ig.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { Label end_label = ec.DefineLabel(); if (unwrap != null) { Label is_null_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); // // When both expressions are nullable the unwrap // is needed only for null check not for value uwrap // if (type.IsNullableType && TypeSpecComparer.IsEqual(NullableInfo.GetUnderlyingType(type), unwrap.Type)) { unwrap.Load(ec); } else { left.Emit(ec); } ec.Emit(OpCodes.Br, end_label); ec.MarkLabel(is_null_label); right.Emit(ec); ec.MarkLabel(end_label); return; } left.Emit(ec); ec.Emit(OpCodes.Dup); // Only to make verifier happy if (left.Type.IsGenericParameter) { ec.Emit(OpCodes.Box, left.Type); } ec.Emit(OpCodes.Brtrue, end_label); ec.Emit(OpCodes.Pop); right.Emit(ec); ec.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { Label is_null_label = ec.DefineLabel(); Label end_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); expr.Emit(ec); ec.Emit(OpCodes.Br, end_label); ec.MarkLabel(is_null_label); null_value.Emit(ec); ec.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { ILGenerator ig = ec.ig; Label is_null_label = ig.DefineLabel(); Label end_label = ig.DefineLabel(); unwrap.EmitCheck(ec); ig.Emit(OpCodes.Brfalse, is_null_label); expr.Emit(ec); ig.Emit(OpCodes.Br, end_label); ig.MarkLabel(is_null_label); null_value.Emit(ec); ig.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { Label end_label = ec.DefineLabel(); if (unwrap != null) { Label is_null_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); left.Emit(ec); ec.Emit(OpCodes.Br, end_label); ec.MarkLabel(is_null_label); right.Emit(ec); ec.MarkLabel(end_label); return; } left.Emit(ec); ec.Emit(OpCodes.Dup); // Only to make verifier happy if (left.Type.IsGenericParameter) { ec.Emit(OpCodes.Box, left.Type); } ec.Emit(OpCodes.Brtrue, end_label); ec.Emit(OpCodes.Pop); right.Emit(ec); ec.MarkLabel(end_label); }
public override void Emit(EmitContext ec) { Label end_label = ec.DefineLabel(); if (unwrap != null) { Label is_null_label = ec.DefineLabel(); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse, is_null_label); // // When both expressions are nullable the unwrap // is needed only for null check not for value uwrap // if (type.IsNullableType && TypeSpecComparer.IsEqual(NullableInfo.GetUnderlyingType(type), unwrap.Type)) { unwrap.Load(ec); } else { left.Emit(ec); } ec.Emit(OpCodes.Br, end_label); ec.MarkLabel(is_null_label); right.Emit(ec); ec.MarkLabel(end_label); return; } // // Null check is done on original expression not after expression is converted to // result type. This is in most cases same but when user conversion is involved // we can end up in situation when user operator does the null handling which is // not what the operator is supposed to do. // There is tricky case where cast of left expression is meant to be cast of // whole source expression (null check is done on it) and cast from right-to-left // conversion needs to do null check on unconverted source expression. // if (user_conversion_left) { var op_expr = (UserCast)left; op_expr.Source.Emit(ec); LocalTemporary temp; // TODO: More load kinds can be special cased if (!(op_expr.Source is VariableReference)) { temp = new LocalTemporary(op_expr.Source.Type); temp.Store(ec); temp.Emit(ec); op_expr.Source = temp; } else { temp = null; } var right_label = ec.DefineLabel(); ec.Emit(OpCodes.Brfalse_S, right_label); left.Emit(ec); ec.Emit(OpCodes.Br, end_label); ec.MarkLabel(right_label); if (temp != null) { temp.Release(ec); } } else { // // Common case where expression is not modified before null check and // we generate better/smaller code // left.Emit(ec); ec.Emit(OpCodes.Dup); // Only to make verifier happy if (left.Type.IsGenericParameter) { ec.Emit(OpCodes.Box, left.Type); } ec.Emit(OpCodes.Brtrue, end_label); ec.Emit(OpCodes.Pop); } right.Emit(ec); ec.MarkLabel(end_label); }
void EmitBitwiseBoolean(EmitContext ec) { Label load_left = ec.DefineLabel(); Label load_right = ec.DefineLabel(); Label end_label = ec.DefineLabel(); // null & value, null | value if (left_unwrap == null) { left_unwrap = right_unwrap; right_unwrap = null; right = left; } left_unwrap.Emit(ec); ec.Emit(OpCodes.Brtrue_S, load_right); // value & null, value | null if (right_unwrap != null) { right_unwrap.Emit(ec); ec.Emit(OpCodes.Brtrue_S, load_left); } left_unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brfalse_S, load_right); // load left ec.MarkLabel(load_left); if (Oper == Operator.BitwiseAnd) { left_unwrap.Load(ec); } else { if (right_unwrap == null) { right.Emit(ec); if (right is EmptyConstantCast || right is EmptyCast) { ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type)); } } else { right_unwrap.Load(ec); right_unwrap = left_unwrap; } } ec.Emit(OpCodes.Br_S, end_label); // load right ec.MarkLabel(load_right); if (right_unwrap == null) { if (Oper == Operator.BitwiseAnd) { right.Emit(ec); if (right is EmptyConstantCast || right is EmptyCast) { ec.Emit(OpCodes.Newobj, NullableInfo.GetConstructor(type)); } } else { left_unwrap.Load(ec); } } else { right_unwrap.Load(ec); } ec.MarkLabel(end_label); }