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); }
protected override void Finish() { if (counts == null) { return; } int total = 0; for (int op = 0; op < counts.Length; op++) { int count = counts[op]; if (count == 0) { continue; } var cil = CILInstruction.Get((OpCode)op); //UpdateCounter("CILDecodingStage.OpCode." + cil.FullName, count); total += count; } //UpdateCounter("CILDecodingStage.CILInstructions", total); instruction = null; block = null; counts = null; }
private void PerformStaticAllocationOf(Context allocation, Context assignment) { MosaType allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type; MosaField assignmentField = (assignment.Instruction is DupInstruction) ? FindStsfldForDup(assignment).MosaField : 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 boundry if (allocation.Instruction is NewarrInstruction) { typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * (int)allocation.Previous.Operand1.ConstantSignedLongInteger) + (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, BuiltInPatch.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0); } // Issue a load request before the newobj and before the assignment. Operand symbol1 = InsertLoadBeforeInstruction(assignment, symbolName.Name, assignmentField.FieldType); assignment.Operand1 = symbol1; // If the instruction is a newarr and the assignment instruction is a dup then we want to remove it if (allocation.Instruction is NewarrInstruction && assignment.Instruction is DupInstruction) { assignment.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), assignment.Result, assignment.Operand1); } // 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.ResultCount = 0; if (allocation.Instruction is NewarrInstruction) { allocation.OperandCount = 0; allocation.SetInstruction(CILInstruction.Get(OpCode.Nop)); } else { Operand symbol2 = InsertLoadBeforeInstruction(allocation, symbolName.Name, assignmentField.FieldType); IEnumerable <Operand> ops = allocation.Operands; allocation.OperandCount++; allocation.Operand1 = symbol2; int i = 0; foreach (Operand op in ops) { i++; allocation.SetOperand(i, op); } allocation.ReplaceInstructionOnly(CILInstruction.Get(OpCode.Call)); } }
private Operand InsertLoadBeforeInstruction(Context context, string symbolName, MosaType type) { var before = context.InsertBefore(); Operand result = MethodCompiler.CreateVirtualRegister(type); Operand op = Operand.CreateManagedSymbol(type, symbolName); before.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result, op); return(result); }
/// <summary> /// Decodes the instruction stream of the reader and populates the compiler. /// </summary> /// <exception cref="InvalidMetadataException"></exception> private void DecodeInstructions() { block = null; // Prefix instruction bool prefix = false; for (int i = 0; i < MethodCompiler.Method.Code.Count; i++) { instruction = MethodCompiler.Method.Code[i]; block = BasicBlocks.GetByLabel(instruction.Offset) ?? block; var op = (OpCode)instruction.OpCode; var cil = CILInstruction.Get(op); if (cil == null) { throw new InvalidMetadataException(); } // Create and initialize the corresponding instruction var node = new InstructionNode(); node.Label = instruction.Offset; node.HasPrefix = prefix; node.Instruction = cil; block.BeforeLast.Insert(node); cil.Decode(node, this); prefix = (cil is PrefixInstruction); instructionCount++; bool addjmp = false; var flow = node.Instruction.FlowControl; if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch) { var nextInstruction = MethodCompiler.Method.Code[i + 1]; if (BasicBlocks.GetByLabel(nextInstruction.Offset) != null) { var target = GetBlockByLabel(nextInstruction.Offset); var jmpNode = new InstructionNode(IRInstruction.Jmp, target); jmpNode.Label = instruction.Offset; block.BeforeLast.Insert(jmpNode); } } } }
private void DecodeInstructionTargets() { bool branched = false; for (int i = 0; i < MethodCompiler.Method.Code.Count; i++) { instruction = MethodCompiler.Method.Code[i]; if (branched) { GetBlockByLabel(instruction.Offset); branched = false; } var op = (OpCode)instruction.OpCode; var cil = CILInstruction.Get(op); branched = cil.DecodeTargets(this); } }