}
}
+ //
+ // Provides "local" store across code that can yield: locals
+ // or fields, notice that this should not be used by anonymous
+ // methods to create local storage, those only require
+ // variable mapping.
+ //
+ public class VariableStorage {
+ ILGenerator ig;
+ FieldBuilder fb;
+ LocalBuilder local;
+
+ static int count;
+
+ public VariableStorage (EmitContext ec, Type t)
+ {
+ count++;
+ if (ec.InIterator)
+ fb = IteratorHandler.Current.MapVariable ("s_", count.ToString (), t);
+ else
+ local = ec.ig.DeclareLocal (t);
+ ig = ec.ig;
+ }
+
+ public void EmitThis ()
+ {
+ if (fb != null)
+ ig.Emit (OpCodes.Ldarg_0);
+ }
+
+ public void EmitStore ()
+ {
+ if (fb == null)
+ ig.Emit (OpCodes.Stloc, local);
+ else
+ ig.Emit (OpCodes.Stfld, fb);
+ }
+
+ public void EmitLoad ()
+ {
+ if (fb == null)
+ ig.Emit (OpCodes.Ldloc, local);
+ else
+ ig.Emit (OpCodes.Ldfld, fb);
+ }
+ }
+
/// <summary>
/// An Emit Context is created for each body of code (from methods,
/// properties bodies, indexer bodies or constructor bodies)
//
// We should also set it if the method is generic
//
- IsGeneric = ds.IsGeneric || ((Modifiers.METHOD_GENERIC) != 0);
+ IsGeneric = ds.IsGeneric || ((code_flags & Modifiers.METHOD_GENERIC) != 0);
}
public EmitContext (TypeContainer tc, Location l, ILGenerator ig,
// Starts a new code branching. This inherits the state of all local
// variables and parameters from the current branching.
// </summary>
- public FlowBranching StartFlowBranching (FlowBranchingType type, Location loc)
+ public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
{
FlowBranching cfb = new FlowBranching (CurrentBranching, type, null, loc);
public FlowBranching StartFlowBranching (Block block)
{
FlowBranching cfb;
- FlowBranchingType type;
+ FlowBranching.BranchingType type;
- if (CurrentBranching.Type == FlowBranchingType.SWITCH)
- type = FlowBranchingType.SWITCH_SECTION;
+ if (CurrentBranching.Type == FlowBranching.BranchingType.Switch)
+ type = FlowBranching.BranchingType.SwitchSection;
else
- type = FlowBranchingType.BLOCK;
+ type = FlowBranching.BranchingType.Block;
cfb = new FlowBranching (CurrentBranching, type, block, block.StartLocation);
// Ends a code branching. Merges the state of locals and parameters
// from all the children of the ending branching.
// </summary>
- public FlowReturns EndFlowBranching ()
+ public FlowBranching.FlowReturns EndFlowBranching ()
{
FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
try {
int errors = Report.Errors;
- block.EmitMeta (this, ip, block);
+ block.EmitMeta (this, ip);
if (Report.Errors == errors){
bool old_do_flow_analysis = DoFlowAnalysis;
}
cfb = (FlowBranching) FlowStack.Pop ();
- FlowReturns returns = cfb.MergeTopBlock ();
+ FlowBranching.FlowReturns returns = cfb.MergeTopBlock ();
DoFlowAnalysis = old_do_flow_analysis;
has_ret = block.Emit (this);
- if ((returns == FlowReturns.ALWAYS) ||
- (returns == FlowReturns.EXCEPTION) ||
- (returns == FlowReturns.UNREACHABLE))
+ if ((returns == FlowBranching.FlowReturns.Always) ||
+ (returns == FlowBranching.FlowReturns.Exception) ||
+ (returns == FlowBranching.FlowReturns.Unreachable))
has_ret = true;
if (Report.Errors == errors){
/// Returns a temporary storage for a variable of type t as
/// a local variable in the current body.
/// </summary>
- public LocalBuilder GetTemporaryStorage (Type t)
+ public LocalBuilder GetTemporaryLocal (Type t)
{
- LocalBuilder location;
+ LocalBuilder location = null;
if (temporary_storage != null){
- location = (LocalBuilder) temporary_storage [t];
- if (location != null)
- return location;
+ object o = temporary_storage [t];
+ if (o != null){
+ if (o is ArrayList){
+ ArrayList al = (ArrayList) o;
+
+ for (int i = 0; i < al.Count; i++){
+ if (al [i] != null){
+ location = (LocalBuilder) al [i];
+ al [i] = null;
+ break;
+ }
+ }
+ } else
+ location = (LocalBuilder) o;
+ if (location != null)
+ return location;
+ }
}
- location = ig.DeclareLocal (t);
-
- return location;
+ return ig.DeclareLocal (t);
}
- public void FreeTemporaryStorage (LocalBuilder b)
+ public void FreeTemporaryLocal (LocalBuilder b, Type t)
{
- // Empty for now.
+ if (temporary_storage == null){
+ temporary_storage = new Hashtable ();
+ temporary_storage [t] = b;
+ return;
+ }
+ object o = temporary_storage [t];
+ if (o == null){
+ temporary_storage [t] = b;
+ return;
+ }
+ if (o is ArrayList){
+ ArrayList al = (ArrayList) o;
+ for (int i = 0; i < al.Count; i++){
+ if (al [i] == null){
+ al [i] = b;
+ return;
+ }
+ }
+ al.Add (b);
+ return;
+ }
+ ArrayList replacement = new ArrayList ();
+ replacement.Add (o);
+ temporary_storage.Remove (t);
+ temporary_storage [t] = replacement;
}
/// <summary>
public FieldBuilder MapVariable (string name, Type t)
{
if (InIterator){
- return IteratorHandler.Current.MapVariable (name, t);
+ return IteratorHandler.Current.MapVariable ("v_", name, t);
}
throw new Exception ("MapVariable for an unknown state");
}
+ //
+ // Invoke this routine to remap a VariableInfo into the
+ // proper MemberAccess expression
+ //
+ public Expression RemapLocal (LocalInfo local_info)
+ {
+ FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolve (this);
+ }
+
+ public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side)
+ {
+ FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolveLValue (this, right_side);
+ }
+
+ public Expression RemapParameter (int idx)
+ {
+ FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolve (this);
+ }
+
+ public Expression RemapParameterLValue (int idx, Expression right_side)
+ {
+ FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolveLValue (this, right_side);
+ }
+
//
// Emits the proper object to address fields on a remapped
// variable/parameter to field in anonymous-method/iterator proxy classes.
}
}
- public void EmitArgument (int idx)
- {
- if (InIterator)
- ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.parameter_fields [idx]);
- else
- throw new Exception ("EmitStoreArgument for an unknown state");
- }
-
- public void EmitStoreArgument (int idx)
- {
- if (InIterator)
- ig.Emit (OpCodes.Stfld, IteratorHandler.Current.parameter_fields [idx]);
- else
- throw new Exception ("EmitStoreArgument for an unknown state");
- }
-
public Expression GetThis (Location loc)
{
This my_this;