private void GenerateIL() {
IEnumerable<ILocalDefinition> localVariables;
ushort maxStack;
IEnumerable<ILocalScope> iteratorScopes;
IEnumerable<ILocalScope> localScopes;
IEnumerable<INamespaceScope> namespaceScopes;
IEnumerable<IOperation> operations;
IEnumerable<IOperationExceptionInformation> operationExceptionInformation;
List<ITypeDefinition>/*?*/ privateHelperTypes = this.privateHelperTypes;
ISynchronizationInformation/*?*/ synchronizationInformation;
uint size;
var isNormalized = this.isNormalized;
NormalizationChecker checker = null;
if (!isNormalized) {
//Assuming that most methods are not iterators and do not contain anonymous delegates, it is worth our while to check if this is really the case.
checker = new NormalizationChecker();
checker.TraverseChildren(this.Block);
isNormalized = !checker.foundAnonymousDelegate && !checker.foundYield;
}
if (isNormalized) {
IMethodDefinition/*?*/ asyncMethod = null;
if (this.localScopeProvider != null) {
var asyncInfo = this.localScopeProvider.GetSynchronizationInformation(this);
if (asyncInfo != null) asyncMethod = asyncInfo.AsyncMethod;
}
var converter = new CodeModelToILConverter(this.host, this.MethodDefinition, this.sourceLocationProvider, asyncMethod, this.iteratorLocalCount);
converter.TrackExpressionSourceLocations = this.trackExpressionSourceLocations;
converter.ConvertToIL(this.Block);
iteratorScopes = converter.GetIteratorScopes();
localScopes = converter.GetLocalScopes();
localVariables = converter.GetLocalVariables();
maxStack = converter.MaximumStackSizeNeeded;
size = converter.GetBodySize();
namespaceScopes = converter.GetNamespaceScopes();
operations = converter.GetOperations();
operationExceptionInformation = converter.GetOperationExceptionInformation();
synchronizationInformation = converter.GetSynchronizationInformation();
} else {
//This object might already be immutable and we are just doing delayed initialization, so make a copy of this.Block.
var mutableBlock = new CodeDeepCopier(this.host, this.sourceLocationProvider).Copy(this.Block);
if (checker.foundAnonymousDelegate) {
var remover = new AnonymousDelegateRemover(this.host, this.sourceLocationProvider);
remover.RemoveAnonymousDelegates(this.MethodDefinition, mutableBlock);
privateHelperTypes = remover.closureClasses;
}
var normalizer = new MethodBodyNormalizer(this.host, this.sourceLocationProvider);
var normalizedBody = (SourceMethodBody)normalizer.GetNormalizedSourceMethodBodyFor(this.MethodDefinition, mutableBlock);
normalizedBody.isNormalized = true;
iteratorScopes = normalizedBody.IteratorScopes;
localScopes = normalizedBody.LocalScopes;
localVariables = normalizedBody.LocalVariables;
maxStack = normalizedBody.MaxStack;
size = normalizedBody.Size;
namespaceScopes = normalizedBody.NamespaceScopes;
operations = normalizedBody.Operations;
operationExceptionInformation = normalizedBody.OperationExceptionInformation;
synchronizationInformation = normalizedBody.SynchronizationInformation;
if (privateHelperTypes == null)
privateHelperTypes = normalizedBody.PrivateHelperTypes;
else //this can happen when this source method body has already been partially normalized, for instance by the removal of yield statements.
privateHelperTypes.AddRange(normalizedBody.PrivateHelperTypes);
}
lock (this) {
if (this.ilWasGenerated) return;
this.ilWasGenerated = true;
this.iteratorScopes = iteratorScopes;
this.localScopes = localScopes;
this.localVariables = localVariables;
this.maxStack = maxStack;
this.namespaceScopes = namespaceScopes;
this.operations = operations;
this.operationExceptionInformation = operationExceptionInformation;
this.synchronizationInformation = synchronizationInformation;
this.privateHelperTypes = privateHelperTypes;
this.size = size;
}
}