private void ReplaceSSALocal(Instruction instruction, SSALocalDefinition ssaLocal) { Contract.Requires(instruction != null); Contract.Requires(ssaLocal != null); var unifiedLocal = this.unifiedLocalFor[ssaLocal]; if (unifiedLocal == null) { foreach (var local in this.availableLocalsFor.GetValuesFor(ssaLocal.Type.InternedKey)) { unifiedLocal = local; break; } if (unifiedLocal == null) { unifiedLocal = new GeneratorLocal() { Name = ssaLocal.Name, Type = ssaLocal.Type }; } this.unifiedLocalFor[ssaLocal] = unifiedLocal; } var oldOperation = instruction.Operation; OperationCode newOp = OperationCode.Ldloc; switch (oldOperation.OperationCode) { case OperationCode.Ldloca: case OperationCode.Ldloca_S: newOp = OperationCode.Ldloca; goto freeUnifiedLocal; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: newOp = OperationCode.Stloc; freeUnifiedLocal: this.availableLocalsFor.Add(ssaLocal.Type.InternedKey, unifiedLocal); break; } instruction.Operation = new Operation() { Location = oldOperation.Location, Offset = oldOperation.Offset, OperationCode = newOp, Value = unifiedLocal }; }
[ContractVerification(false)] //Times out private void Inline(IMethodBody methodBody) { Contract.Requires(methodBody != null); var savedCombinedMaxStack = this.combinedMaxStack; this.combinedMaxStack += methodBody.MaxStack; if (this.combinedMaxStack > this.maxStack) this.maxStack = this.combinedMaxStack; var savedLocalForThis = this.localForThis; var nametable = this.Host.NameTable; var method = methodBody.MethodDefinition; var n = method.ParameterCount; if (!method.IsStatic) n++; var temps = new GeneratorLocal[n]; for (ushort i = 0; i < n; i++) temps[i] = new GeneratorLocal() { MethodDefinition = method }; var j = 0; if (!method.IsStatic) { var temp0 = temps[0]; Contract.Assume(temp0 != null); temp0.Name = nametable.GetNameFor("this"); temp0.Type = method.ContainingTypeDefinition; if (method.ContainingTypeDefinition.IsValueType) temp0.Type = ManagedPointerType.GetManagedPointerType(temp0.Type, this.Host.InternFactory); j = 1; this.localForThis = temp0; } foreach (var par in methodBody.MethodDefinition.Parameters) { Contract.Assume(par != null); Contract.Assume(j < n); var tempj = temps[j++]; Contract.Assume(tempj != null); this.localFor[par] = tempj; tempj.Name = par.Name; tempj.Type = par.Type; if (par.IsByReference) tempj.Type = ManagedPointerType.GetManagedPointerType(tempj.Type, this.Host.InternFactory); } this.Generator.BeginScope(); for (int i = n-1; i >= 0; i--) { var temp = temps[i]; Contract.Assume(temp != null); this.Generator.Emit(OperationCode.Stloc, temp); this.TrackLocal(temp); this.Generator.AddVariableToCurrentScope(temp); } var savedReturnLabel = this.returnLabel; var returnLabel = this.returnLabel = new ILGeneratorLabel(); this.EmitMethodBody(methodBody); this.Generator.MarkLabel(returnLabel); this.returnLabel = savedReturnLabel; this.localForThis = savedLocalForThis; this.Generator.EndScope(); this.combinedMaxStack = savedCombinedMaxStack; }
[ContractVerification(false)] //Times out private void Inline(IMethodBody methodBody) { Contract.Requires(methodBody != null); var savedCombinedMaxStack = this.combinedMaxStack; this.combinedMaxStack += methodBody.MaxStack; if (this.combinedMaxStack > this.maxStack) { this.maxStack = this.combinedMaxStack; } var savedLocalForThis = this.localForThis; var nametable = this.Host.NameTable; var method = methodBody.MethodDefinition; var n = method.ParameterCount; if (!method.IsStatic) { n++; } var temps = new GeneratorLocal[n]; for (ushort i = 0; i < n; i++) { temps[i] = new GeneratorLocal() { MethodDefinition = method } } ; var j = 0; if (!method.IsStatic) { var temp0 = temps[0]; Contract.Assume(temp0 != null); temp0.Name = nametable.GetNameFor("this"); temp0.Type = method.ContainingTypeDefinition; if (method.ContainingTypeDefinition.IsValueType) { temp0.Type = ManagedPointerType.GetManagedPointerType(temp0.Type, this.Host.InternFactory); } j = 1; this.localForThis = temp0; } foreach (var par in methodBody.MethodDefinition.Parameters) { Contract.Assume(par != null); Contract.Assume(j < n); var tempj = temps[j++]; Contract.Assume(tempj != null); this.localFor[par] = tempj; tempj.Name = par.Name; tempj.Type = par.Type; if (par.IsByReference) { tempj.Type = ManagedPointerType.GetManagedPointerType(tempj.Type, this.Host.InternFactory); } } this.Generator.BeginScope(); for (int i = n - 1; i >= 0; i--) { var temp = temps[i]; Contract.Assume(temp != null); this.Generator.Emit(OperationCode.Stloc, temp); this.TrackLocal(temp); this.Generator.AddVariableToCurrentScope(temp); } var savedReturnLabel = this.returnLabel; var returnLabel = this.returnLabel = new ILGeneratorLabel(); this.EmitMethodBody(methodBody); this.Generator.MarkLabel(returnLabel); this.returnLabel = savedReturnLabel; this.localForThis = savedLocalForThis; this.Generator.EndScope(); this.combinedMaxStack = savedCombinedMaxStack; } }
protected override void EmitOperationFor(Instruction instruction) { var operation = instruction.Operation; switch (operation.OperationCode) { case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: var local = this.localFor[operation.Value]; if (local == null) { break; } this.LoadLocal(local); return; case OperationCode.Ldarga: case OperationCode.Ldarga_S: var ssaParameter = operation.Value as SSAParameterDefinition; if (ssaParameter == null) { break; } local = this.localFor[ssaParameter.OriginalParameter]; if (local == null) { this.LoadParameter(ssaParameter.OriginalParameter); } else { this.LoadLocal(local); } this.localFor[ssaParameter] = local = new GeneratorLocal() { Name = ssaParameter.Name, Type = ssaParameter.Type }; this.StoreLocal(local); this.LoadLocalAddress(local); return; case OperationCode.Starg: case OperationCode.Starg_S: ssaParameter = operation.Value as SSAParameterDefinition; if (ssaParameter == null) { break; } this.localFor[ssaParameter] = local = new GeneratorLocal() { Name = ssaParameter.Name, Type = ssaParameter.Type }; this.StoreLocal(local); return; case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: if (this.redundantLocals.Contains(operation.Value)) { return; } local = this.localFor[operation.Value]; if (local == null) { break; } this.LoadLocal(local); return; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: if (this.storesThatShouldBecomePops.Contains(instruction)) { this.ILGenerator.Emit(OperationCode.Pop); return; } if (this.redundantLocals.Contains(operation.Value)) { return; } var ssaLocal = operation.Value as SSALocalDefinition; if (ssaLocal == null) { break; } this.localFor[ssaLocal] = local = new GeneratorLocal() { Name = ssaLocal.Name, Type = ssaLocal.Type }; this.StoreLocal(local); return; } base.EmitOperationFor(instruction); }