/// <inheritdoc/> public override FlowGraph Apply(FlowGraph graph) { var builder = graph.ToBuilder(); foreach (var insn in builder.NamedInstructions) { ValueTag array; ClrFieldDefinition pseudoField; if (IsArrayInit(insn, out array, out pseudoField)) { array = ElideReinterpretCasts(array, builder.ToImmutable()); var arrayType = TypeHelpers.UnboxIfPossible(graph.GetValueType(array)); IType elementType; IReadOnlyList <Constant> data; int rank; if (ClrArrayType.TryGetArrayElementType(arrayType, out elementType) && ClrArrayType.TryGetArrayRank(arrayType, out rank) && rank == 1 && TryDecodePseudoFieldData(pseudoField, elementType, out data)) { // Generate instructions to fill the array. FillWith(array, data, elementType, insn); // Neuter the old array init function. insn.Instruction = Instruction.CreateConstant(DefaultConstant.Instance, insn.ResultType); } } } return(builder.ToImmutable()); }
/// <summary> /// Takes a Flame type and converts it to a Cecil type reference. /// For this to work, <paramref name="type"/> cannot reference /// non-Cecil types. /// </summary> /// <param name="type"> /// The type to convert to a type reference. /// </param> /// <returns> /// A type reference. /// </returns> public static Mono.Cecil.TypeReference ImportReference( this Mono.Cecil.ModuleDefinition module, IType type) { if (type is ClrTypeDefinition) { var typeRef = ((ClrTypeDefinition)type).Definition; // The module can be null for testing purposes. return(module == null ? typeRef : module.ImportReference(typeRef)); } else if (type is ClrGenericParameter) { // There's no need to "import" generic parameters: they can only be // used in the same place where they are defined. return(((ClrGenericParameter)type).Definition); } else if (type is PointerType) { var pointerType = (PointerType)type; var elemType = pointerType.ElementType; var elemTypeRef = module.ImportReference(elemType); if (pointerType.Kind == PointerKind.Reference) { return(new Mono.Cecil.ByReferenceType(elemTypeRef)); } else if (pointerType.Kind == PointerKind.Box) { if (elemType.IsReferenceType()) { var def = module.ImportReference(elemTypeRef); return(module == null ? def : module.ImportReference(def)); } else { return(module.ImportReference(module.TypeSystem.Object)); } } else { return(new Mono.Cecil.PointerType(elemTypeRef)); } } IType elementType; if (ClrArrayType.TryGetArrayElementType(type, out elementType)) { // Handle arrays. int rank; ClrArrayType.TryGetArrayRank(type, out rank); return(new Mono.Cecil.ArrayType(module.ImportReference(elementType), rank)); } else if (type is TypeSpecialization) { // Handle generics. var instance = new Mono.Cecil.GenericInstanceType( module.ImportReference( type.GetRecursiveGenericDeclaration())); foreach (var item in type.GetRecursiveGenericArguments()) { instance.GenericArguments.Add(module.ImportReference(item)); } return(instance); } else { throw new NotSupportedException($"Cannot import ill-understood type '{type.FullName}'."); } }