private void EmitSwitchBucketsLinearLeaf(ImmutableArray <SwitchBucket> switchBuckets, int low, int high) { for (int i = low; i < high; i++) { var nextBucketLabel = new object(); this.EmitSwitchBucket(switchBuckets[i], nextBucketLabel); // nextBucketLabel: _builder.MarkLabel(nextBucketLabel); } this.EmitSwitchBucket(switchBuckets[high], _fallThroughLabel); }
private void EmitHashTableSwitch() { // Hash value for the key must have already been computed and loaded into keyHash Debug.Assert(keyHash != null); // Compute hash value for each case label constant and store the hash buckets // into a dictionary indexed by hash value. Dictionary <uint, HashBucket> stringHashMap = ComputeStringHashMap( this.caseLabels, this.computeStringHashcodeDelegate); // Emit conditional jumps to hash buckets. // EmitHashBucketJumpTable returns a map from hashValues to hashBucketLabels. Dictionary <uint, object> hashBucketLabelsMap = EmitHashBucketJumpTable(stringHashMap); // Emit hash buckets foreach (var kvPair in stringHashMap) { // hashBucketLabel: // Emit direct string comparisons for each case label in hash bucket builder.MarkLabel(hashBucketLabelsMap[kvPair.Key]); HashBucket hashBucket = kvPair.Value; this.EmitNonHashTableSwitch(hashBucket.ToArray()); } }
public override void CloseScope(ILBuilder builder) { Debug.Assert(_handlers.Count > 1); // Fix up the NextExceptionHandler reference of each leader block. ExceptionHandlerScope tryScope = _handlers[0]; ExceptionHandlerLeaderBlock previousBlock = tryScope.LeaderBlock; for (int i = 1; i < _handlers.Count; i++) { ExceptionHandlerScope handlerScope = _handlers[i]; ExceptionHandlerLeaderBlock nextBlock = handlerScope.LeaderBlock; previousBlock.NextExceptionHandler = nextBlock; previousBlock = nextBlock; } // Generate label for try/catch "leave" target. builder.MarkLabel(_endLabel); // hide the following code, since it could be reached through the label above. builder.DefineHiddenSequencePoint(); Debug.Assert(builder._currentBlock == builder._labelInfos[_endLabel].bb); if (_handlers[1].Type == ScopeType.Finally) { // Generate "nop" branch to itself. If this block is unreachable // (because the finally block does not complete), the "nop" will be // replaced by Br_s. On the other hand, if this block is reachable, // the "nop" will be skipped so any "leave" instructions jumping // to this block will jump to the next instead. builder.EmitBranch(ILOpCode.Nop, _endLabel); _handlers[1].SetBlockedByFinallyDestination(_endLabel); } }