protected Node Transform(Node node, BasicBlock block, TypeSystem typeSystem, ExpressionVariables variables) { var newNode = new InstructionNode(node.Instruction, block); // todo: determine result type // todo: determine size int operandIndex = 0; foreach (var nodeOperand in node.ParentNodes) { if (nodeOperand.NodeType == NodeType.Expression) { // todo: expressions } else if (nodeOperand.NodeType == NodeType.FixedIntegerConstant) { // todo } else if (nodeOperand.NodeType == NodeType.FixedDoubleConstant) { // todo } else if (nodeOperand.NodeType == NodeType.ConstantVariable) { newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias)); continue; } else if (nodeOperand.NodeType == NodeType.PhyiscalRegister) { var type = typeSystem.BuiltIn.I4; // todo Operand.CreateCPURegister(type, node.PhysicalRegister); continue; } else if (nodeOperand.NodeType == NodeType.VirtualRegister) { newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias)); continue; } else if (nodeOperand.NodeType == NodeType.OperandVariable) { newNode.SetOperand(operandIndex++, variables.GetOperand(nodeOperand.Alias)); continue; } throw new CompilerException("Error"); } return(null); }
private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment) { var allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type; var assignmentField = assignment.MosaField; // Get size of type int typeSize = TypeLayout.GetTypeSize(allocatedType); // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size // Also need to align to a 4-byte boundary if (allocation.Instruction is CIL.NewarrInstruction) { int elements = GetConstant(allocation.Operand1); typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name. var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + "<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); // Try to get typeDefinitionSymbol if allocatedType isn't a value type string typeDefinitionSymbol = GetTypeDefinition(allocatedType); if (typeDefinitionSymbol != null) { MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, SectionKind.ROData, typeDefinitionSymbol, 0); } var staticAddress = Operand.CreateSymbol(assignmentField.FieldType, symbolName.Name); var result1 = AllocateVirtualRegister(assignmentField.FieldType); //Operand result2 = AllocateVirtualRegister(assignmentField.FieldType); // Issue a load request before the newobj and before the assignment. new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress); assignment.Operand1 = result1; // If the instruction is a newarr if (allocation.Instruction is CIL.NewarrInstruction) { allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1); return; } //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress); // Change the newobj to a call and increase the operand count to include the this ptr. // If the instruction is a newarr, then just replace with a nop instead allocation.Result = null; allocation.ResultCount = 0; allocation.OperandCount++; for (int i = allocation.OperandCount; i > 0; i--) { var op = allocation.GetOperand(i - 1); allocation.SetOperand(i, op); } allocation.Operand1 = result1; allocation.Instruction = CILInstruction.Get(OpCode.Call); }
private void UpdateNodeWithValueNumbers(InstructionNode node) { // update operands with their value number for (int i = 0; i < node.OperandCount; i++) { var operand = node.GetOperand(i); if (operand.IsVirtualRegister) { var valueNumber = GetValueNumber(operand); if (valueNumber != null) { if (operand != valueNumber) { //trace?.Log($"BEFORE: {node}"); //trace?.Log($"Replaced: {operand} with {valueNumber}"); node.SetOperand(i, valueNumber); trace?.Log($"UPDATED: {node}"); } } else { if (IsPhiInstruction(node.Instruction)) { continue; } //Debug.Assert(IsPhiInstruction(node.Instruction)); if (!IsPhiInstruction(node.Instruction)) { throw new CompilerException("ValueNumbering Stage: Expected PHI instruction but found instead: " + node + " for " + operand); } } } } }
/// <summary> /// Emits the constant operands. /// </summary> /// <param name="node">The node.</param> protected void EmitFloatingPointConstants(InstructionNode node) { for (int i = 0; i < node.OperandCount; i++) { var operand = node.GetOperand(i); if (operand == null || !operand.IsConstant || !operand.IsR) { continue; } if (operand.IsUnresolvedConstant) { continue; } var v1 = AllocateVirtualRegister(operand.Type); var symbol = (operand.IsR4) ? MethodCompiler.Linker.GetConstantSymbol(operand.ConstantSingleFloatingPoint) : MethodCompiler.Linker.GetConstantSymbol(operand.ConstantDoubleFloatingPoint); var s1 = Operand.CreateLabel(operand.Type, symbol.Name); var before = new Context(node).InsertBefore(); if (operand.IsR4) { before.SetInstruction(X86.MovssLoad, InstructionSize.Size32, v1, s1, ConstantZero); } else { before.SetInstruction(X86.MovsdLoad, InstructionSize.Size64, v1, s1, ConstantZero); } node.SetOperand(i, v1); } }
private void ReplaceOperands(InstructionNode node) { if (node.Result != null && repl.ContainsKey(node.Result)) { node.Result = repl[node.Result]; } if (node.Result2 != null && repl.ContainsKey(node.Result2)) { node.Result2 = repl[node.Result2]; } int count = node.OperandCount; for (int i = 0; i < count; i++) { var operand = node.GetOperand(i); if (operand != null && repl.ContainsKey(operand)) { node.SetOperand(i, repl[operand]); } } }
/// <summary> /// Emits the constant operands. /// </summary> /// <param name="node">The node.</param> protected void EmitFloatingPointConstants(InstructionNode node) { for (int i = 0; i < node.OperandCount; i++) { var operand = node.GetOperand(i); if (operand == null || !operand.IsConstant || !operand.IsR) { continue; } if (operand.IsUnresolvedConstant) { continue; } var before = new Context(node).InsertBefore(); var v1 = AllocateVirtualRegister(operand.Type); if (operand.IsR4) { var symbol = Linker.GetConstantSymbol(operand.ConstantFloat); var label = Operand.CreateLabel(operand.Type, symbol.Name); before.SetInstruction(MovssLoad, v1, label, ConstantZero); } else { var symbol = Linker.GetConstantSymbol(operand.ConstantDouble); var label = Operand.CreateLabel(operand.Type, symbol.Name); before.SetInstruction(MovsdLoad, v1, label, ConstantZero); } node.SetOperand(i, v1); } }
protected void Inline(InstructionNode callSiteNode, BasicBlocks blocks) { var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count); var map = new Dictionary <Operand, Operand>(); var nextBlock = Split(callSiteNode); // create basic blocks foreach (var block in blocks) { var newBlock = CreateNewBlock(); mapBlocks.Add(block, newBlock); } // copy instructions foreach (var block in blocks) { var newBlock = mapBlocks[block]; for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction == IRInstruction.Prologue) { continue; } if (node.Instruction == IRInstruction.Epilogue) { newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock)); continue; } if (node.Instruction == IRInstruction.SetReturn32 || node.Instruction == IRInstruction.SetReturn64 || node.Instruction == IRInstruction.SetReturnR4 || node.Instruction == IRInstruction.SetReturnR8 || node.Instruction == IRInstruction.SetReturnCompound) { if (callSiteNode.Result != null) { var newOperand = Map(node.Operand1, map, callSiteNode); BaseInstruction moveInstruction = null; if (node.Instruction == IRInstruction.SetReturn32) { moveInstruction = IRInstruction.Move32; } else if (node.Instruction == IRInstruction.SetReturn64) { moveInstruction = IRInstruction.Move64; } else if (node.Instruction == IRInstruction.SetReturnR4) { moveInstruction = IRInstruction.MoveR4; } else if (node.Instruction == IRInstruction.SetReturnR8) { moveInstruction = IRInstruction.MoveR8; } else if (node.Instruction == IRInstruction.SetReturnCompound) { moveInstruction = IRInstruction.MoveCompound; } Debug.Assert(moveInstruction != null); var moveNode = new InstructionNode(moveInstruction, callSiteNode.Result, newOperand); newBlock.BeforeLast.Insert(moveNode); } continue; } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount) { ConditionCode = node.ConditionCode, Label = callSiteNode.Label }; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map, callSiteNode); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map, callSiteNode); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) { newNode.MosaType = node.MosaType; } if (node.MosaField != null) { newNode.MosaField = node.MosaField; } UpdateParameterInstructions(newNode); newBlock.BeforeLast.Insert(newNode); } } var prologue = mapBlocks[blocks.PrologueBlock]; var callSiteOperands = callSiteNode.GetOperands(); if (callSiteOperands.Count > 1) { var context = new Context(prologue); for (int i = 1; i < callSiteOperands.Count; i++) { var operand = callSiteOperands[i]; if (!operand.IsVirtualRegister || operand.Low == null) { continue; } context.AppendInstruction(IRInstruction.GetLow64, operand.Low, operand); context.AppendInstruction(IRInstruction.GetHigh64, operand.High, operand); } } callSiteNode.SetInstruction(IRInstruction.Jmp, prologue); }
protected BasicBlocks CopyInstructions() { var newBasicBlocks = new BasicBlocks(); var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(BasicBlocks.Count); var map = new Dictionary <Operand, Operand>(); foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.CreateBlock(block.Label); mapBlocks.Add(block, newBlock); } var newPrologueBlock = newBasicBlocks.GetByLabel(BasicBlock.PrologueLabel); foreach (var operand in MethodCompiler.Parameters) { if (operand.Definitions.Count > 0) { var newOp = Map(operand, map); var newOperand = Operand.CreateVirtualRegister(operand.Type, -operand.Index); var moveInstruction = StoreOnStack(newOperand.Type) ? IRInstruction.MoveCompound : GetMoveInstruction(newOperand.Type); var moveNode = new InstructionNode(moveInstruction, newOperand, newOp); newPrologueBlock.BeforeLast.Insert(moveNode); // redirect map from parameter to virtual register going forward map.Remove(operand); map.Add(operand, newOperand); } } foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.GetByLabel(block.Label); for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount); newNode.Size = node.Size; newNode.ConditionCode = node.ConditionCode; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) { newNode.MosaType = node.MosaType; } if (node.MosaField != null) { newNode.MosaField = node.MosaField; } if (node.InvokeMethod != null) { newNode.InvokeMethod = node.InvokeMethod; } newBlock.BeforeLast.Insert(newNode); } } var trace = CreateTraceLog("InlineMap"); if (trace.Active) { foreach (var entry in map) { trace.Log(entry.Value.ToString() + " from: " + entry.Key.ToString()); } } return(newBasicBlocks); }
protected BasicBlocks CopyInstructions() { var newBasicBlocks = new BasicBlocks(); var mapBlocks = new Dictionary<BasicBlock, BasicBlock>(BasicBlocks.Count); var map = new Dictionary<Operand, Operand>(); foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.CreateBlock(block.Label); mapBlocks.Add(block, newBlock); } var newPrologueBlock = newBasicBlocks.GetByLabel(BasicBlock.PrologueLabel); foreach (var operand in MethodCompiler.Parameters) { if (operand.Definitions.Count > 0) { var newOp = Map(operand, map); var newOperand = Operand.CreateVirtualRegister(operand.Type, -operand.Index); newPrologueBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, newOperand, newOp)); // redirect map from parameter to virtual register going forward map.Remove(operand); map.Add(operand, newOperand); } } foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.GetByLabel(block.Label); for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) continue; var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount); newNode.Size = node.Size; newNode.ConditionCode = node.ConditionCode; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) newNode.MosaType = node.MosaType; if (node.MosaField != null) newNode.MosaField = node.MosaField; if (node.InvokeMethod != null) newNode.InvokeMethod = node.InvokeMethod; newBlock.BeforeLast.Insert(newNode); } } var trace = CreateTraceLog("InlineMap"); if (trace.Active) { foreach (var entry in map) { trace.Log(entry.Value.ToString() + " from: " + entry.Key.ToString()); } } return newBasicBlocks; }
protected void Inline(InstructionNode callNode, BasicBlocks blocks) { var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count); var map = new Dictionary <Operand, Operand>(); var nextBlock = Split(callNode); // create basic blocks foreach (var block in blocks) { var newBlock = CreateNewBlock(); mapBlocks.Add(block, newBlock); } // copy instructions foreach (var block in blocks) { var newBlock = mapBlocks[block]; for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction == IRInstruction.Prologue) { continue; } if (node.Instruction == IRInstruction.Epilogue) { continue; } if (node.Instruction == IRInstruction.Return) { if (callNode.Result != null) { var newOp = Map(node.Operand1, map, callNode); var moveInsturction = GetMoveInstruction(callNode.Result.Type); var moveNode = new InstructionNode(moveInsturction, callNode.Result, newOp); newBlock.BeforeLast.Insert(moveNode); } newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock)); continue; } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount); newNode.Size = node.Size; newNode.ConditionCode = node.ConditionCode; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map, callNode); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map, callNode); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) { newNode.MosaType = node.MosaType; } if (node.MosaField != null) { newNode.MosaField = node.MosaField; } if (node.InvokeMethod != null) { newNode.InvokeMethod = node.InvokeMethod; } UpdateParameterInstructions(newNode); newBlock.BeforeLast.Insert(newNode); } } callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]); }
protected BasicBlocks CopyInstructions() { var newBasicBlocks = new BasicBlocks(); var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(BasicBlocks.Count); var map = new Dictionary <Operand, Operand>(); var staticCalls = new List <MosaMethod>(); foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.CreateBlock(block.Label); mapBlocks.Add(block, newBlock); } var newPrologueBlock = newBasicBlocks.GetByLabel(BasicBlock.PrologueLabel); foreach (var operand in MethodCompiler.Parameters) { if (operand.Definitions.Count > 0) { var newOp = Map(operand, map); var newOperand = Operand.CreateVirtualRegister(operand.Type, -operand.Index); var moveInstruction = !MosaTypeLayout.CanFitInRegister(newOperand) ? IRInstruction.MoveCompound : GetMoveInstruction(newOperand.Type); var moveNode = new InstructionNode(moveInstruction, newOperand, newOp); newPrologueBlock.BeforeLast.Insert(moveNode); // redirect map from parameter to virtual register going forward map.Remove(operand); map.Add(operand, newOperand); } } foreach (var block in BasicBlocks) { var newBlock = newBasicBlocks.GetByLabel(block.Label); for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmptyOrNop) { continue; } if (node.Instruction == IRInstruction.CallStatic) { staticCalls.AddIfNew(node.Operand1.Method); } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount) { ConditionCode = node.ConditionCode, InvokeMethod = node.InvokeMethod, MosaField = node.MosaField, MosaType = node.MosaType, //Label = callSiteNode.Label, }; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) { newNode.MosaType = node.MosaType; } if (node.MosaField != null) { newNode.MosaField = node.MosaField; } newBlock.BeforeLast.Insert(newNode); } } var trace = CreateTraceLog("InlineMap", 9); if (trace != null) { foreach (var entry in map) { trace.Log($"{entry.Value} from: {entry.Key}"); } } return(newBasicBlocks); }
private void ReplaceOperands(InstructionNode node) { if (node.Result != null && repl.ContainsKey(node.Result)) node.Result = repl[node.Result]; if (node.Result2 != null && repl.ContainsKey(node.Result2)) node.Result2 = repl[node.Result2]; int count = node.OperandCount; for (int i = 0; i < count; i++) { var operand = node.GetOperand(i); if (operand != null && repl.ContainsKey(operand)) node.SetOperand(i, repl[operand]); } }
protected void Inline(InstructionNode callNode, BasicBlocks blocks) { var mapBlocks = new Dictionary<BasicBlock, BasicBlock>(blocks.Count); var map = new Dictionary<Operand, Operand>(); var nextBlock = Split(callNode); // create basic blocks foreach (var block in blocks) { var newBlock = CreateNewBlock(); mapBlocks.Add(block, newBlock); } // copy instructions foreach (var block in blocks) { var newBlock = mapBlocks[block]; for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) continue; if (node.Instruction == IRInstruction.Prologue) continue; if (node.Instruction == IRInstruction.Epilogue) continue; if (node.Instruction == IRInstruction.Return) { if (callNode.Result != null) { var newOp = Map(node.Operand1, map, callNode); newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, callNode.Result, newOp)); } newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock)); continue; } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount); newNode.Size = node.Size; newNode.ConditionCode = node.ConditionCode; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map, callNode); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map, callNode); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) newNode.MosaType = node.MosaType; if (node.MosaField != null) newNode.MosaField = node.MosaField; if (node.InvokeMethod != null) newNode.InvokeMethod = node.InvokeMethod; newBlock.BeforeLast.Insert(newNode); } } callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]); }
private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment) { var allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type; var assignmentField = assignment.MosaField; // Get size of type int typeSize = TypeLayout.GetTypeSize(allocatedType); // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size // Also need to align to a 4-byte boundary if (allocation.Instruction is NewarrInstruction) { int elements = GetConstant(allocation.Operand1); typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name. var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize); // Try to get typeDefinitionSymbol if allocatedType isn't a value type string typeDefinitionSymbol = GetTypeDefinition(allocatedType); if (typeDefinitionSymbol != null) { MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0); } Operand staticAddress = Operand.CreateManagedSymbol(assignmentField.FieldType, symbolName.Name); Operand result1 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType); //Operand result2 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType); // Issue a load request before the newobj and before the assignment. new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress); assignment.Operand1 = result1; // If the instruction is a newarr if (allocation.Instruction is NewarrInstruction) { allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1); return; } //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress); // Change the newobj to a call and increase the operand count to include the this ptr. // If the instruction is a newarr, then just replace with a nop instead allocation.Result = null; allocation.ResultCount = 0; allocation.OperandCount++; for (int i = allocation.OperandCount; i > 0; i--) { var op = allocation.GetOperand(i - 1); allocation.SetOperand(i, op); } allocation.Operand1 = result1; allocation.Instruction = CILInstruction.Get(OpCode.Call); }