+ abstract class Emitter
+ {
+ protected LocalInfo vi;
+ protected Expression converted;
+
+ protected Emitter (Expression expr, LocalInfo li)
+ {
+ converted = expr;
+ vi = li;
+ }
+
+ public abstract void Emit (EmitContext ec);
+ public abstract void EmitExit (ILGenerator ig);
+ }
+
+ class ExpressionEmitter: Emitter {
+ public ExpressionEmitter (Expression converted, LocalInfo li) :
+ base (converted, li)
+ {
+ }
+
+ public override void Emit (EmitContext ec) {
+ //
+ // Store pointer in pinned location
+ //
+ converted.Emit (ec);
+ ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_U);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+ }
+
+ class StringEmitter: Emitter {
+ LocalBuilder pinned_string;
+ Location loc;
+
+ public StringEmitter (Expression expr, LocalInfo li, Location loc):
+ base (expr, li)
+ {
+ this.loc = loc;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+
+ Expression sptr = new StringPtr (pinned_string, loc);
+ converted = Convert.ImplicitConversionRequired (
+ ec, sptr, vi.VariableType, loc);
+
+ if (converted == null)
+ return;
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit(ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldnull);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+ }
+ }