本文整理汇总了C#中BoundSequence类的典型用法代码示例。如果您正苦于以下问题:C# BoundSequence类的具体用法?C# BoundSequence怎么用?C# BoundSequence使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
BoundSequence类属于命名空间,在下文中一共展示了BoundSequence类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: AddSequence
internal void AddSequence(SyntheticBoundNodeFactory F, BoundSequence sequence)
{
locals.AddRange(sequence.Locals);
foreach (var sideEffect in sequence.SideEffects)
{
statements.Add(F.ExpressionStatement(sideEffect));
}
}
示例2: VisitSequence
public override BoundNode VisitSequence(BoundSequence node)
{
ReadOnlyArray<BoundExpression> sideEffects = (ReadOnlyArray<BoundExpression>)this.VisitList(node.SideEffects);
BoundExpression value = (BoundExpression)this.Visit(node.Value);
TypeSymbol type = this.VisitType(node.Type);
if (!RequiresSpill(sideEffects) && value.Kind != BoundKind.SpillSequence)
{
return node.Update(node.Locals, sideEffects, value, type);
}
var spillBuilder = new SpillBuilder();
spillBuilder.Locals.AddRange(node.Locals);
foreach (var sideEffect in sideEffects)
{
spillBuilder.Statements.Add(
(sideEffect.Kind == BoundKind.SpillSequence)
? RewriteSpillSequenceAsBlock((BoundSpillSequence)sideEffect)
: F.ExpressionStatement(sideEffect));
}
BoundExpression newValue;
if (value.Kind == BoundKind.SpillSequence)
{
var awaitEffect = (BoundSpillSequence)value;
spillBuilder.AddSpill(awaitEffect);
newValue = awaitEffect.Value;
}
else
{
newValue = value;
}
return spillBuilder.BuildSequenceAndFree(F, newValue);
}
示例3: VisitSequence
public override BoundNode VisitSequence(BoundSequence node)
{
var newLocals = RewriteLocals(node.Locals);
var newSideEffects = VisitList<BoundExpression>(node.SideEffects);
var newValue = (BoundExpression)this.Visit(node.Value);
var newType = this.VisitType(node.Type);
return node.Update(newLocals, newSideEffects, newValue, newType);
}
示例4: EmitSideEffects
private void EmitSideEffects(BoundSequence sequence)
{
var sideEffects = sequence.SideEffects;
if (!sideEffects.IsDefaultOrEmpty)
{
foreach (var se in sideEffects)
{
EmitExpression(se, false);
}
}
}
示例5: DefineLocals
private void DefineLocals(BoundSequence sequence)
{
if (sequence.Locals.IsEmpty)
{
return;
}
_builder.OpenLocalScope();
foreach (var local in sequence.Locals)
{
DefineLocal(local, sequence.Syntax);
}
}
示例6: VisitSequence
public override BoundNode VisitSequence(BoundSequence node)
{
BoundSpillSequence2 ss2 = null;
var value = VisitExpression(ref ss2, node.Value);
BoundSpillSequence2 ss1 = null;
var sideEffects = VisitExpressionList(ref ss1, node.SideEffects, forceSpill: ss2 != null, sideEffectsOnly: true);
if (ss1 == null && ss2 == null)
{
return node.Update(node.Locals, sideEffects, value, node.Type);
}
if (ss1 == null) ss1 = new BoundSpillSequence2(); // possible if sideEffects is empty
ss1.AddRange(sideEffects, MakeExpressionStatement);
ss1.AddRange(node.Locals);
ss1.IncludeSequence(ss2);
return ss1.Update(value);
}
示例7: VisitSequence
// here we have a case of indirect assignment: *t1 = expr;
// normally we would need to push t1 and that will cause spilling of t2
//
// TODO: an interesting case arises in unused x[i]++ and ++x[i] :
// we have trees that look like:
//
// t1 = &(x[0])
// t2 = *t1
// *t1 = t2 + 1
//
// t1 = &(x[0])
// t2 = *t1 + 1
// *t1 = t2
//
// in these cases, we could keep t2 on stack (dev10 does).
// we are dealing with exactly 2 locals and access them in strict order
// t1, t2, t1, t2 and we are not using t2 after that.
// We may consider detecting exactly these cases and pretend that we do not need
// to push either t1 or t2 in this case.
//
public override BoundNode VisitSequence(BoundSequence node)
{
// Normally we can only use stack for local scheduling if stack is not used for evaluation.
// In a context of a regular block that simply means that eval stack must be empty.
// Sequences, can be entered on a nonempty evaluation stack
// Ex:
// a.b = Seq{var y, y = 1, y} // a is on the stack for the duration of the sequence.
//
// However evaluation stack at the entry cannot be used inside the sequence, so such stack
// works as effective "empty" for locals declared in sequence.
// Therefore sequence locals can be stack scheduled at same stack as at the entry to the sequence.
// it may seem attractive to relax the stack requirement to be:
// "all uses must agree on stack depth".
// The following example illustrates a case where x is safely used at "declarationStack + 1"
// Ex:
// Seq{var x; y.a = Seq{x = 1; x}; y} // x is used while y is on the eval stack
//
// It is, however not safe assumption in general since eval stack may be accessed between usages.
// Ex:
// Seq{var x; y.a = Seq{x = 1; x}; y.z = x; y} // x blocks access to y
//
// There is one case where we want to tweak the "use at declaration stack" rule - in the case of
// compound assignment that involves ByRef operand captures (like: x[y]++ ) .
//
// Those cases produce specific sequences of the shapes:
//
// prefix: Seq{var temp, ref operand; operand initializers; *operand = Seq{temp = (T)(operand + 1); temp;} result: temp}
// postfix: Seq{var temp, ref operand; operand initializers; *operand = Seq{temp = operand; ; (T)(temp + 1);} result: temp}
//
// 1) temp is used as the result of the sequence (and that is the only reason why it is declared in the outer sequence).
// 2) all side-effects except the last one do not use the temp.
// 3) last side-effect is an indirect assignment of a sequence (and target does not involve the temp).
//
// Note that in a case of side-effects context, the result value will be ignored and therefore
// all usages of the nested temp will be confined to the nested sequence that is executed at +1 stack.
//
// We will detect such case and indicate +1 as the desired stack depth at local accesses.
//
var declarationStack = StackDepth();
var locals = node.Locals;
if (!locals.IsDefaultOrEmpty)
{
if (_context == ExprContext.Sideeffects)
{
foreach (var local in locals)
{
if (IsNestedLocalOfCompoundOperator(local, node))
{
// special case
DeclareLocal(local, declarationStack + 1);
}
else
{
DeclareLocal(local, declarationStack);
}
}
}
else
{
DeclareLocals(locals, declarationStack);
}
}
// rewrite operands
var origContext = _context;
var sideeffects = node.SideEffects;
ArrayBuilder<BoundExpression> rewrittenSideeffects = null;
if (!sideeffects.IsDefault)
{
for (int i = 0; i < sideeffects.Length; i++)
{
var sideeffect = sideeffects[i];
var rewrittenSideeffect = this.VisitExpression(sideeffect, ExprContext.Sideeffects);
if (rewrittenSideeffects == null && rewrittenSideeffect != sideeffect)
//.........这里部分代码省略.........
示例8: EmitSequenceCondBranch
private void EmitSequenceCondBranch(BoundSequence sequence, ref object dest, bool sense)
{
DefineLocals(sequence);
EmitSideEffects(sequence);
EmitCondBranch(sequence.Value, ref dest, sense);
// sequence is used as a value, can release all locals
FreeLocals(sequence, doNotRelease: null);
}
示例9: MergeArgumentsAndSideEffects
/// <summary>
/// Process tempStores and add them as side-effects to arguments where needed. The return
/// value tells how many temps are actually needed. For unnecessary temps the corresponding
/// temp store will be cleared.
/// </summary>
private static int MergeArgumentsAndSideEffects(
BoundExpression[] arguments,
ArrayBuilder<RefKind> refKinds,
ArrayBuilder<BoundAssignmentOperator> tempStores)
{
Debug.Assert(arguments != null);
Debug.Assert(refKinds != null);
Debug.Assert(tempStores != null);
int tempsRemainedInUse = tempStores.Count;
// Suppose we've got temporaries: t0 = A(), t1 = B(), t2 = C(), t4 = D(), t5 = E()
// and arguments: t0, t2, t1, t4, 10, t5
//
// We wish to produce arguments list: A(), SEQ(t1=B(), C()), t1, D(), 10, E()
//
// Our algorithm essentially finds temp stores that must happen before given argument
// load, and if there are any they become side effects of the given load.
// Stores immediately followed by loads of the same thing can be eliminated.
//
// Constraints:
// Stores must happen before corresponding loads.
// Stores cannot move relative to other stores. If arg was movable it would not need a temp.
int firstUnclaimedStore = 0;
for (int a = 0; a < arguments.Length; ++a)
{
var argument = arguments[a];
// if argument is a load, search for corresponding store. if store is found, extract
// the actual expression we were storing and add it as an argument - this one does
// not need a temp. if there are any unclaimed stores before the found one, add them
// as side effects that precede this arg, they cannot happen later.
// NOTE: missing optional parameters are not filled yet and therefore nulls - no need to do anything for them
if (argument?.Kind == BoundKind.Local)
{
var correspondingStore = -1;
for (int i = firstUnclaimedStore; i < tempStores.Count; i++)
{
if (tempStores[i].Left == argument)
{
correspondingStore = i;
break;
}
}
// store found?
if (correspondingStore != -1)
{
var value = tempStores[correspondingStore].Right;
// When we created the temp, we dropped the argument RefKind
// since the local contained its own RefKind. Since we're removing
// the temp, the argument RefKind needs to be restored.
refKinds[a] = ((BoundLocal)argument).LocalSymbol.RefKind;
// the matched store will not need to go into side-effects, only ones before it will
// remove the store to signal that we are not using its temp.
tempStores[correspondingStore] = null;
tempsRemainedInUse--;
// no need for side-effects?
// just combine store and load
if (correspondingStore == firstUnclaimedStore)
{
arguments[a] = value;
}
else
{
var sideeffects = new BoundExpression[correspondingStore - firstUnclaimedStore];
for (int s = 0; s < sideeffects.Length; s++)
{
sideeffects[s] = tempStores[firstUnclaimedStore + s];
}
arguments[a] = new BoundSequence(
value.Syntax,
// this sequence does not own locals. Note that temps that
// we use for the rewrite are stored in one arg and loaded
// in another so they must live in a scope above.
ImmutableArray<LocalSymbol>.Empty,
sideeffects.AsImmutableOrNull(),
value,
value.Type);
}
firstUnclaimedStore = correspondingStore + 1;
}
}
}
Debug.Assert(firstUnclaimedStore == tempStores.Count, "not all side-effects were claimed");
return tempsRemainedInUse;
}
示例10: RewriteArgumentsForComCall
// Omit ref feature for COM interop: We can pass arguments by value for ref parameters if we are calling a method/property on an instance of a COM imported type.
// We should have ignored the 'ref' on the parameter during overload resolution for the given method call.
// If we had any ref omitted argument for the given call, we create a temporary local and
// replace the argument with the following BoundSequence: { side-effects: { temp = argument }, value = { ref temp } }
// NOTE: The temporary local must be scoped to live across the entire BoundCall node,
// otherwise the codegen optimizer might re-use the same temporary for multiple ref-omitted arguments for this call.
private void RewriteArgumentsForComCall(
ImmutableArray<ParameterSymbol> parameters,
BoundExpression[] actualArguments, //already re-ordered to match parameters
ArrayBuilder<RefKind> argsRefKindsBuilder,
ArrayBuilder<LocalSymbol> temporariesBuilder)
{
Debug.Assert(actualArguments != null);
Debug.Assert(actualArguments.Length == parameters.Length);
Debug.Assert(argsRefKindsBuilder == null || argsRefKindsBuilder.Count == parameters.Length);
var argsCount = actualArguments.Length;
for (int argIndex = 0; argIndex < argsCount; ++argIndex)
{
RefKind paramRefKind = parameters[argIndex].RefKind;
RefKind argRefKind = argsRefKindsBuilder[argIndex];
// Rewrite only if the argument was passed with no ref/out and the
// parameter was declared ref.
if (argRefKind != RefKind.None || paramRefKind != RefKind.Ref)
{
continue;
}
var argument = actualArguments[argIndex];
if (argument.Kind == BoundKind.Local)
{
var localRefKind = ((BoundLocal)argument).LocalSymbol.RefKind;
if (localRefKind == RefKind.Ref)
{
// Already passing an address from the ref local.
continue;
}
Debug.Assert(localRefKind == RefKind.None);
}
BoundAssignmentOperator boundAssignmentToTemp;
BoundLocal boundTemp = _factory.StoreToTemp(argument, out boundAssignmentToTemp);
actualArguments[argIndex] = new BoundSequence(
argument.Syntax,
locals: ImmutableArray<LocalSymbol>.Empty,
sideEffects: ImmutableArray.Create<BoundExpression>(boundAssignmentToTemp),
value: boundTemp,
type: boundTemp.Type);
argsRefKindsBuilder[argIndex] = RefKind.Ref;
temporariesBuilder.Add(boundTemp.LocalSymbol);
}
}
示例11: EmitSequenceExpression
private void EmitSequenceExpression(BoundSequence sequence, bool used)
{
var hasLocals = !sequence.Locals.IsEmpty;
if (hasLocals)
{
builder.OpenLocalScope();
foreach (var local in sequence.Locals)
{
DefineLocal(local, sequence.Syntax);
}
}
EmitSideEffects(sequence);
// CONSIDER: LocalRewriter.RewriteNestedObjectOrCollectionInitializerExpression may create a bound sequence with an unused BoundTypeExpression as the value,
// CONSIDER: which must be ignored by codegen. See comments in RewriteNestedObjectOrCollectionInitializerExpression for details and an example.
// CONSIDER: We may want to instead consider making the Value field of BoundSequence node optional to allow a sequence with
// CONSIDER: only side effects and no value. Note that VB's BoundSequence node has an optional value field.
// CONSIDER: This will allow us to remove the below check before emitting the value.
Debug.Assert(sequence.Value.Kind != BoundKind.TypeExpression || !used);
if (sequence.Value.Kind != BoundKind.TypeExpression)
{
EmitExpression(sequence.Value, used);
}
if (hasLocals)
{
builder.CloseLocalScope();
foreach (var local in sequence.Locals)
{
FreeLocal(local);
}
}
}
示例12: FreeLocals
private void FreeLocals(BoundSequence sequence)
{
if (sequence.Locals.IsEmpty)
{
return;
}
builder.CloseLocalScope();
foreach (var local in sequence.Locals)
{
FreeLocal(local);
}
}
示例13: VisitObjectCreationExpression
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
{
Debug.Assert(node != null);
// Rewrite the arguments.
// NOTE: We may need additional argument rewriting such as generating a params array,
// re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
// NOTE: This is done later by MakeArguments, for now we just lower each argument.
var rewrittenArguments = VisitList(node.Arguments);
// We have already lowered each argument, but we may need some additional rewriting for the arguments,
// such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
ImmutableArray<LocalSymbol> temps;
ImmutableArray<RefKind> argumentRefKindsOpt = node.ArgumentRefKindsOpt;
rewrittenArguments = MakeArguments(node.Syntax, rewrittenArguments, node.Constructor, node.Constructor, node.Expanded, node.ArgsToParamsOpt, ref argumentRefKindsOpt, out temps);
BoundExpression rewrittenObjectCreation;
if (_inExpressionLambda)
{
if (!temps.IsDefaultOrEmpty)
{
throw ExceptionUtilities.UnexpectedValue(temps.Length);
}
rewrittenObjectCreation = node.UpdateArgumentsAndInitializer(rewrittenArguments, MakeObjectCreationInitializerForExpressionTree(node.InitializerExpressionOpt), changeTypeOpt: node.Constructor.ContainingType);
if (node.Type.IsInterfaceType())
{
Debug.Assert(rewrittenObjectCreation.Type == ((NamedTypeSymbol)node.Type).ComImportCoClass);
rewrittenObjectCreation = MakeConversion(rewrittenObjectCreation, node.Type, false, false);
}
return rewrittenObjectCreation;
}
rewrittenObjectCreation = node.UpdateArgumentsAndInitializer(rewrittenArguments, newInitializerExpression: null, changeTypeOpt: node.Constructor.ContainingType);
// replace "new S()" with a default struct ctor with "default(S)"
if (node.Constructor.IsDefaultValueTypeConstructor())
{
rewrittenObjectCreation = new BoundDefaultOperator(rewrittenObjectCreation.Syntax, rewrittenObjectCreation.Type);
}
if (!temps.IsDefaultOrEmpty)
{
rewrittenObjectCreation = new BoundSequence(
node.Syntax,
temps,
ImmutableArray<BoundExpression>.Empty,
rewrittenObjectCreation,
node.Type);
}
if (node.Type.IsInterfaceType())
{
Debug.Assert(rewrittenObjectCreation.Type == ((NamedTypeSymbol)node.Type).ComImportCoClass);
rewrittenObjectCreation = MakeConversion(rewrittenObjectCreation, node.Type, false, false);
}
if (node.InitializerExpressionOpt == null || node.InitializerExpressionOpt.HasErrors)
{
return rewrittenObjectCreation;
}
return MakeObjectCreationWithInitializer(node.Syntax, rewrittenObjectCreation, node.InitializerExpressionOpt, node.Type);
}
示例14: EmitSequenceCondBranch
private void EmitSequenceCondBranch(BoundSequence sequence, ref object dest, bool sense)
{
var hasLocals = !sequence.Locals.IsEmpty;
if (hasLocals)
{
builder.OpenLocalScope();
foreach (var local in sequence.Locals)
{
DefineLocal(local, sequence.Syntax);
}
}
EmitSideEffects(sequence);
EmitCondBranch(sequence.Value, ref dest, sense);
if (hasLocals)
{
builder.CloseLocalScope();
foreach (var local in sequence.Locals)
{
FreeLocal(local);
}
}
}
示例15: DigForValueLocal
// if sequence value is a local scoped to the sequence, return that local
private LocalSymbol DigForValueLocal(BoundSequence topSequence)
{
return DigForValueLocal(topSequence, topSequence.Value);
}