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 static void PatchConstructor(BaseMethodCompiler methodCompiler) { Operand thisOperand = methodCompiler.Parameters[0]; Operand instanceOperand = methodCompiler.Parameters[1]; Operand methodPointerOperand = methodCompiler.Parameters[2]; var size = methodCompiler.Architecture.NativeInstructionSize; MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset); MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset); var context = new Context(CreateMethodStructure(methodCompiler, true)); Operand v1 = methodCompiler.CreateVirtualRegister(thisOperand.Type); context.AppendInstruction(IRInstruction.Move, v1, thisOperand); context.AppendInstruction(IRInstruction.Store, size, null, v1, methodPointerOffsetOperand, methodPointerOperand); context.MosaType = methodPointerOperand.Type; context.AppendInstruction(IRInstruction.Store, size, null, v1, instanceOffsetOperand, instanceOperand); context.MosaType = instanceOperand.Type; context.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldSize(MosaField field) { var size = 0; //FIXME: This is not thread safe! if (fieldSizes.TryGetValue(field, out size)) { return(size); } else { ResolveType(field.DeclaringType); } // If the field is another struct, we have to dig down and compute its size too. if (field.FieldType.IsValueType) { size = GetTypeSize(field.FieldType); } else { size = GetMemorySize(field.FieldType); } fieldSizes.Add(field, size); return(size); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldSize(MosaField field) { lock (_lock) { return(ComputeFieldSize(field)); } }
private int ComputeFieldSize(MosaField field) { if (fieldSizes.TryGetValue(field, out int size)) { return(size); } else { ResolveType(field.DeclaringType); } // If the field is another struct, we have to dig down and compute its size too. if (field.FieldType.IsValueType) { size = GetTypeSize(field.FieldType); } else { size = NativePointerSize; } fieldSizes.Add(field, size); return(size); }
public bool IsFieldAccessed(MosaField field) { if (!IsEnabled) { return(true); // always } return(accessedFields.Contains(field)); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldOffset(MosaField field) { ResolveType(field.DeclaringType); var offset = 0; fieldOffsets.TryGetValue(field, out offset); return(offset); }
/// <summary> /// Creates a new runtime member <see cref="Operand"/>. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public static Operand CreateField(MosaField field) { var operand = new Operand(field.FieldType); operand.IsMemoryAddress = true; operand.IsField = true; operand.Displacement = 0; operand.Field = field; return(operand); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldOffset(MosaField field) { lock (_lock) { ResolveType(field.DeclaringType); fieldOffsets.TryGetValue(field, out int offset); return(offset); } }
private void AllocateSpace(MosaField field, SectionKind section, int size, int alignment) { using (var stream = Compiler.Linker.Allocate(field.FullName, section, size, alignment)) { if (field.Data != null) { stream.Write(field.Data, 0, size); } else { stream.WriteZeroBytes(size); } } }
/// <summary> /// Creates a new runtime member <see cref="Operand"/>. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public static Operand CreateField(MosaField field) { Debug.Assert(field.IsStatic); var operand = new Operand(field.FieldType); operand.IsStaticField = true; operand.Offset = 0; operand.Field = field; //operand.IsResolved = true; operand.IsConstant = true; return(operand); }
/// <summary> /// Creates a new runtime member <see cref="Operand" />. /// </summary> /// <param name="field">The field.</param> /// <param name="typeSystem">The type system.</param> /// <returns></returns> public static Operand CreateStaticField(MosaField field, TypeSystem typeSystem) { Debug.Assert(field.IsStatic); var type = field.FieldType.IsReferenceType ? typeSystem.BuiltIn.Object : field.FieldType.ToManagedPointer(); return(new Operand(type) { IsStaticField = true, // field.IsStatic Offset = 0, Field = field, IsConstant = true }); }
public void AccessedField(MosaField field) { if (!IsEnabled) { return; } if (!field.IsStatic) { return; } lock (accessedFields) { accessedFields.AddIfNew(field); } }
private void ResolveField(MosaField field) { var resolver = new GenericArgumentResolver(); if (field.DeclaringType.GenericArguments.Count > 0) { resolver.PushTypeGenericArguments(field.DeclaringType.GenericArguments.GetGenericArguments()); } using (var mosaField = metadata.Controller.MutateField(field)) { mosaField.FieldType = metadata.Loader.GetType(resolver.Resolve(field.GetFieldSig().Type)); mosaField.HasOpenGenericParams = field.DeclaringType.HasOpenGenericParams || field.FieldType.GetTypeSig().HasOpenGenericParameter(); ResolveCustomAttributes(mosaField, field.GetUnderlyingObject <UnitDesc <FieldDef, FieldSig> >().Definition); } }
private static void PatchInvoke(BaseMethodCompiler methodCompiler, bool withReturn) { // check if instance is null (if so, it's a static call to the methodPointer) MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset); MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset); var size = methodCompiler.Architecture.NativeInstructionSize; Context b0 = new Context(CreateMethodStructure(methodCompiler, false)); Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Operand[] vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); if (methodCompiler.TypeLayout.IsCompoundType(methodCompiler.Parameters[i].Type)) { b0.AppendInstruction(IRInstruction.CompoundMove, vrs[i], methodCompiler.Parameters[i]); } else { b0.AppendInstruction(IRInstruction.Move, vrs[i], methodCompiler.Parameters[i]); } } Operand thisOperand = vrs[0]; Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4); Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4); Operand opReturn = withReturn ? methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.Object) : null; Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0); b0.AppendInstruction(IRInstruction.Load, size, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(IRInstruction.Load, size, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(IRInstruction.IntegerCompare, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, opCompare, c0); b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); // no instance b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b1.InvokeMethod = methodCompiler.Method; for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b1.AddOperand(vrs[i]); } b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b2.InvokeMethod = methodCompiler.Method; b2.AddOperand(opInstance); for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b2.AddOperand(vrs[i]); } b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock); if (withReturn) { b3.SetOperand(0, opReturn); } }
public void AddField(MosaField field) { fieldLookup.Add(field.GetUnderlyingObject<UnitDesc<FieldDef, FieldSig>>().Token, field); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldSize(MosaField field) { var size = 0; if (fieldSizes.TryGetValue(field, out size)) { return size; } else { ResolveType(field.DeclaringType); } // If the field is another struct, we have to dig down and compute its size too. if (field.FieldType.IsValueType) { size = GetTypeSize(field.FieldType); } else { size = GetMemorySize(field.FieldType); } fieldSizes.Add(field, size); return size; }
/// <summary> /// Creates a new runtime member <see cref="Operand"/>. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public static Operand CreateField(MosaField field) { Debug.Assert(field.IsStatic); var operand = new Operand(field.FieldType); operand.IsStaticField = true; operand.Offset = 0; operand.Field = field; //operand.IsResolved = true; operand.IsConstant = true; return operand; }
public void AddField(MosaField field) { fieldLookup.Add(field.GetUnderlyingObject <UnitDesc <FieldDef, FieldSig> >().Token, field); }
private void ResolveField(MosaField field) { GenericArgumentResolver resolver = new GenericArgumentResolver(); if (field.DeclaringType.GenericArguments.Count > 0) resolver.PushTypeGenericArguments(field.DeclaringType.GenericArguments.GetGenericArguments()); using (var mosaField = metadata.Controller.MutateField(field)) { mosaField.FieldType = metadata.Loader.GetType(resolver.Resolve(field.GetFieldSig().Type)); mosaField.HasOpenGenericParams = field.DeclaringType.HasOpenGenericParams || field.FieldType.GetTypeSig().HasOpenGenericParameter(); ResolveCustomAttributes(mosaField, field.GetUnderlyingObject<UnitDesc<FieldDef, FieldSig>>().Definition); } }
/// <summary> /// Creates a new runtime member <see cref="Operand"/>. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public static Operand CreateField(MosaField field) { var operand = new Operand(field.FieldType); operand.IsMemoryAddress = true; operand.IsField = true; operand.Displacement = 0; operand.Field = field; return operand; }
public MosaField.Mutator MutateField(MosaField field) { return new MosaField.Mutator(field); }
public MosaField CreateField(MosaField source = null) { if (source == null) { return new MosaField() { ID = id++, TypeSystem = typeSystem }; } else { MosaField result = source.Clone(); result.ID = id++; return result; } }
protected string FormatRuntimeMember(MosaField field) { return(field.Name); }
/// <summary> /// Allocates memory for the static field and initializes it. /// </summary> /// <param name="field">The field.</param> private void CreateStaticField(MosaField field) { // Determine the size of the type & alignment requirements int size, alignment; Architecture.GetTypeRequirements(TypeLayout, field.FieldType, out size, out alignment); size = (int)TypeLayout.GetFieldSize(field); // The linker section to move this field into SectionKind section = field.Data != null ? section = SectionKind.Data : section = SectionKind.BSS; AllocateSpace(field, section, size, alignment); }
public static FieldSig GetFieldSig(this MosaField field) { return(field.GetUnderlyingObject <UnitDesc <FieldDef, FieldSig> >().Signature); }
private MosaType LoadGenericTypeInstanceSig(GenericInstSig typeSig) { //Debug.Assert(false, typeSig.FullName); MosaType origin = GetType(typeSig.GenericType); MosaType result = metadata.Controller.CreateType(origin); var desc = result.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >(); using (var resultType = metadata.Controller.MutateType(result)) { resultType.UnderlyingObject = desc.Clone(typeSig); resultType.ElementType = origin; foreach (var genericArg in typeSig.GenericArguments) { resultType.GenericArguments.Add(GetType(genericArg)); } metadata.Resolver.EnqueueForResolve(result); GenericArgumentResolver resolver = new GenericArgumentResolver(); resolver.PushTypeGenericArguments(typeSig.GenericArguments); for (int i = 0; i < result.Methods.Count; i++) { MosaMethod method = metadata.Controller.CreateMethod(result.Methods[i]); using (var mosaMethod = metadata.Controller.MutateMethod(method)) { mosaMethod.DeclaringType = result; mosaMethod.UnderlyingObject = method.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >(); } resultType.Methods[i] = method; metadata.Resolver.EnqueueForResolve(method); } for (int i = 0; i < result.Fields.Count; i++) { MosaField field = metadata.Controller.CreateField(result.Fields[i]); using (var mosaField = metadata.Controller.MutateField(field)) { mosaField.DeclaringType = result; mosaField.UnderlyingObject = field.GetUnderlyingObject <UnitDesc <FieldDef, FieldSig> >(); } resultType.Fields[i] = field; metadata.Resolver.EnqueueForResolve(field); } for (int i = 0; i < result.Properties.Count; i++) { MosaProperty property = metadata.Controller.CreateProperty(result.Properties[i]); PropertySig newSig = property.GetPropertySig().Clone(); newSig.RetType = resolver.Resolve(newSig.RetType); using (var mosaProperty = metadata.Controller.MutateProperty(property)) { mosaProperty.DeclaringType = result; mosaProperty.UnderlyingObject = property.GetUnderlyingObject <UnitDesc <PropertyDef, PropertySig> >(); } resultType.Properties[i] = property; metadata.Resolver.EnqueueForResolve(property); } resultType.HasOpenGenericParams = typeSig.HasOpenGenericParameter(); } metadata.Controller.AddType(result); return(result); }
private void Load(MosaModule module, TypeDef typeDef) { TypeSig typeSig = typeDef.ToTypeSig(); // Check to see if its one of our classes we need for SZ Arrays if (typeDef.Name.Contains("SZArrayHelper`1")) { szHelperSig = typeSig as ClassOrValueTypeSig; } else if (typeDef.Name.Contains("IList`1")) { iListSig = typeSig as ClassOrValueTypeSig; } MosaType mosaType = metadata.Controller.CreateType(); using (var type = metadata.Controller.MutateType(mosaType)) { type.Module = module; type.UnderlyingObject = new UnitDesc <TypeDef, TypeSig>(typeDef.Module, typeDef, typeSig); type.Namespace = typeDef.Namespace; type.Name = typeDef.Name; type.IsInterface = typeDef.IsInterface; type.IsEnum = typeDef.IsEnum; type.IsDelegate = typeDef.BaseType != null && typeDef.BaseType.DefinitionAssembly.IsCorLib() && (typeDef.BaseType.FullName == "System.Delegate" || typeDef.BaseType.FullName == "System.MulticastDelegate"); type.IsModule = typeDef.IsGlobalModuleType; type.IsExplicitLayout = typeDef.IsExplicitLayout; if (typeDef.IsExplicitLayout) { type.ClassSize = (int)typeDef.ClassSize; type.PackingSize = typeDef.PackingSize; } type.TypeAttributes = (MosaTypeAttributes)typeDef.Attributes; type.TypeCode = (MosaTypeCode)typeSig.ElementType; // Load members foreach (var fieldDef in typeDef.Fields) { MosaField mosaField = metadata.Controller.CreateField(); using (var field = metadata.Controller.MutateField(mosaField)) LoadField(mosaType, field, fieldDef); type.Fields.Add(mosaField); metadata.Cache.AddField(mosaField); LoadedUnits.Add(mosaField); } foreach (var methodDef in typeDef.Methods) { MosaMethod mosaMethod = metadata.Controller.CreateMethod(); using (var method = metadata.Controller.MutateMethod(mosaMethod)) LoadMethod(mosaType, method, methodDef); type.Methods.Add(mosaMethod); metadata.Cache.AddMethod(mosaMethod); LoadedUnits.Add(mosaMethod); } foreach (var propertyDef in typeDef.Properties) { MosaProperty mosaProperty = metadata.Controller.CreateProperty(); using (var property = metadata.Controller.MutateProperty(mosaProperty)) LoadProperty(mosaType, property, propertyDef); type.Properties.Add(mosaProperty); metadata.Cache.AddProperty(mosaProperty); LoadedUnits.Add(mosaProperty); } } typeCache[typeSig] = mosaType; metadata.Controller.AddType(mosaType); metadata.Cache.AddType(mosaType); LoadedUnits.Add(mosaType); }
/// <summary> /// Gets the size of the field. /// </summary> /// <param name="field">The field.</param> /// <returns></returns> public int GetFieldOffset(MosaField field) { ResolveType(field.DeclaringType); var offset = 0; fieldOffsets.TryGetValue(field, out offset); return offset; }
protected string FormatRuntimeMember(MosaField field) { return field.Name; }
public void TrackFieldReferenced(MosaField field) { // TODO }
void ICompilationScheduler.TrackFieldReferenced(MosaField field) { Debug.Assert(!field.FieldType.HasOpenGenericParams); (this as ICompilationScheduler).TrackTypeAllocated(field.DeclaringType); }