public AwaitCatchFrame(TypeSystemServices tss, BooCodeBuilder builder, Method currentMethod) { pendingCaughtException = builder.DeclareTempLocal(currentMethod, tss.ObjectType); pendingCatch = builder.DeclareTempLocal(currentMethod, tss.IntType); handlers = new List <Block>(); _hoistedLocals = new Dictionary <InternalLocal, InternalLocal>(); _orderedHoistedLocals = new List <InternalLocal>(); _currentMethod = currentMethod; }
public static void UnpackArray(BooCodeBuilder codeBuilder, Method method, Block block, Expression expression, DeclarationCollection declarations) { ILocalEntity local = expression.Entity as ILocalEntity; if (null == local) { local = codeBuilder.DeclareTempLocal(method, expression.ExpressionType); block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference(local), expression)); } for (int i = 0; i < declarations.Count; ++i) { Declaration declaration = declarations[i]; block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference( declaration.Entity), codeBuilder.CreateSlicing( codeBuilder.CreateReference(local), i))); } }
public InternalLabel ProxyReturnIfNeeded( Method containingMethod, Node valueOpt, out InternalLocal retVal) { retVal = null; // no need to proxy returns at the root if (IsRoot()) { return(null); } var returnProxy = returnProxyLabel; if (returnProxy == null) { returnProxyLabel = returnProxy = _builder.CreateLabel(valueOpt ?? containingMethod, "returnProxy", _tryDepth); } if (valueOpt != null) { retVal = returnValue; if (retVal == null) { Debug.Assert(_tryStatementOpt != null); returnValue = retVal = _builder.DeclareTempLocal( containingMethod, ((ITypedEntity)valueOpt.Entity).Type); } } return(returnProxy); }
private Expression VisitExpression(ref BoundSpillSequenceBuilder builder, Expression expression) { // wrap the node in a spill sequence to mark the fact that it must be moved up the tree. // The caller will handle this node type if the result is discarded. if (expression != null && expression.NodeType == NodeType.AwaitExpression) { // we force the await expression to be assigned to a temp variable var awaitExpression = (AwaitExpression)expression; awaitExpression.BaseExpression = VisitExpression(ref builder, awaitExpression.BaseExpression); var local = _F.DeclareTempLocal(_currentMethod, awaitExpression.ExpressionType); var replacement = _F.CreateAssignment( awaitExpression.LexicalInfo, _F.CreateLocalReference(local), awaitExpression); if (builder == null) { builder = new BoundSpillSequenceBuilder(); } builder.AddLocal(local); builder.AddStatement(new ExpressionStatement(replacement)); return(_F.CreateLocalReference(local)); } var e = Visit(expression); if (e == null || e.NodeType != SpillSequenceBuilder) { return(e); } var newBuilder = (BoundSpillSequenceBuilder)e; if (builder == null) { builder = newBuilder.Update(null); } else { builder.Include(newBuilder); } return(newBuilder.Value); }
public static void UnpackEnumerable(BooCodeBuilder codeBuilder, Method method, Block block, Expression expression, DeclarationCollection declarations) { TypeSystemServices tss = codeBuilder.TypeSystemServices; InternalLocal local = codeBuilder.DeclareTempLocal(method, tss.IEnumeratorType); IType expressionType = expression.ExpressionType; if (expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumeratorType)) { block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference(local), expression)); } else { if (!expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumerableType)) { expression = codeBuilder.CreateMethodInvocation( RuntimeServices_GetEnumerable, expression); } block.Add( codeBuilder.CreateAssignment( block.LexicalInfo, codeBuilder.CreateReference(local), codeBuilder.CreateMethodInvocation( expression, IEnumerable_GetEnumerator))); } for (int i = 0; i < declarations.Count; ++i) { Declaration declaration = declarations[i]; block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference(declaration.Entity), codeBuilder.CreateMethodInvocation(RuntimeServices_MoveNext, codeBuilder.CreateReference(local)))); } }
public void HoistLocal(InternalLocal local, BooCodeBuilder F) { if (!_hoistedLocals.Keys.Any(l => l.Name == local.Name && l.Type == local.Type)) { _hoistedLocals.Add(local, local); _orderedHoistedLocals.Add(local); return; } // code uses "await" in two sibling catches with exception filters // locals with same names and types may cause problems if they are lifted // and become fields with identical signatures. // To avoid such problems we will mangle the name of the second local. // This will only affect debugging of this extremely rare case. var newLocal = F.DeclareTempLocal(_currentMethod, local.Type); _hoistedLocals.Add(local, newLocal); _orderedHoistedLocals.Add(newLocal); }