// this method creates a new class for the given namespace public NamespaceTypeDefinition createNewClass(String className, IUnitNamespace containingUnitNamespace, bool isPublic, bool isStatic) { // create a new class object NamespaceTypeDefinition newClass = new NamespaceTypeDefinition(); newClass.ContainingUnitNamespace = containingUnitNamespace; newClass.InternFactory = this.host.InternFactory; newClass.IsClass = true; newClass.IsForeignObject = false; newClass.IsInterface = false; newClass.IsPublic = isPublic; newClass.IsStatic = isStatic; newClass.Methods = new List <IMethodDefinition>(); newClass.Name = this.host.NameTable.GetNameFor(className); // create list of base classes (only base class is System.Object) newClass.BaseClasses = new List <ITypeReference>(); newClass.BaseClasses.Add(this.host.PlatformType.SystemObject); // add new class to module assembly Assembly tempAssembly = (Assembly)this.module; tempAssembly.AllTypes.Add(newClass); return(newClass); }
public NodeObject(int dimension, int validPathCount, NamespaceTypeDefinition thisClass, MethodDefinition constructorToUse, PathElement pathElement, List <int> positionInGraph) { // a list of possible objects in the graph that fulfill the needed attributes like this object this.possibleExchangeObjects = new List <NodeObject>(); // a list of possible classes this object could made of this.possibleClasses = new List <NamespaceTypeDefinition>(); // set the amount of child nodes this node object has this.dimension = dimension; this.nodeObjects = new NodeObject[this.dimension]; // class to use for this node object this.thisClass = thisClass; // constructor to use when a node for the graph is created this.constructorToUse = constructorToUse; // interfaces that this object represents (or not represents) this.pathElements.Add(pathElement); // set the maximum amount of valid paths that this node can be an element of // (in the list elementOfValidPath is the id of the valid path stored this element is a part of) this.validPathCount = validPathCount; this.elementOfValidPath = new List <int>(this.validPathCount); // set the position of this node in the graph this.positionInGraph = positionInGraph; // null every object in the array for (int i = 0; i < this.dimension; i++) { this.nodeObjects[i] = null; } }
public NodeObject(int dimension, int validPathCount, NamespaceTypeDefinition thisClass, MethodDefinition constructorToUse, PathElement pathElement, List<int> positionInGraph) { // a list of possible objects in the graph that fulfill the needed attributes like this object this.possibleExchangeObjects = new List<NodeObject>(); // a list of possible classes this object could made of this.possibleClasses = new List<NamespaceTypeDefinition>(); // set the amount of child nodes this node object has this.dimension = dimension; this.nodeObjects = new NodeObject[this.dimension]; // class to use for this node object this.thisClass = thisClass; // constructor to use when a node for the graph is created this.constructorToUse = constructorToUse; // interfaces that this object represents (or not represents) this.pathElements.Add(pathElement); // set the maximum amount of valid paths that this node can be an element of // (in the list elementOfValidPath is the id of the valid path stored this element is a part of) this.validPathCount = validPathCount; this.elementOfValidPath = new List<int>(this.validPathCount); // set the position of this node in the graph this.positionInGraph = positionInGraph; // null every object in the array for (int i = 0; i < this.dimension; i++) { this.nodeObjects[i] = null; } }
public override void RewriteChildren(NamespaceTypeDefinition namespaceTypeDefinition) { string typeName = Util.FullyQualifiedTypeNameFromType(namespaceTypeDefinition); Element currentElement = null; // Unlike all other types that visited from either a namespace or a parent, // the module type is visited from the containing module if (_systemTypes.Contains(typeName)) { currentElement = new SpecialTrimType(typeName); _trimElements.Push(currentElement); } this.RewriteChildren((NamedTypeDefinition)namespaceTypeDefinition); //namespaceTypeDefinition.ContainingUnitNamespace = this.GetCurrentNamespace(); if (!_systemTypes.Contains(typeName)) { TypeElement type = _currentTrimAssembly.GetTypeElement(typeName); MutateType(namespaceTypeDefinition, type); } if (currentElement != null) { _trimElements.Pop(); } }
public NodeObject(int dimension, int validPathCount, NamespaceTypeDefinition thisClass, MethodDefinition constructorToUse, PathElement pathElement, List<int> positionInGraph, int validPathId) : this(dimension, validPathCount, thisClass, constructorToUse, pathElement, positionInGraph) { // add the id of the valid path to the list this.elementOfValidPath.Add(validPathId); }
// this method creates a new method for the given class public MethodDefinition createNewMethod(String methodName, NamespaceTypeDefinition methodClass, ITypeReference methodType, TypeMemberVisibility methodVisibility, List <IParameterDefinition> methodParameters, CallingConvention methodCallingConvention, bool isStatic, bool isAbstract, bool isVirtual) { // create a new method MethodDefinition newMethod = new MethodDefinition(); newMethod.ContainingTypeDefinition = methodClass; newMethod.InternFactory = this.host.InternFactory; newMethod.IsCil = true; newMethod.IsStatic = isStatic; newMethod.Name = this.host.NameTable.GetNameFor(methodName); newMethod.Type = methodType; newMethod.Visibility = methodVisibility; newMethod.IsAbstract = isAbstract; newMethod.IsVirtual = isVirtual; newMethod.Parameters = methodParameters; newMethod.CallingConvention = methodCallingConvention; // add method to class if (methodClass.Methods == null) { methodClass.Methods = new List <IMethodDefinition>(); methodClass.Methods.Add(newMethod); } else { methodClass.Methods.Add(newMethod); } return(newMethod); }
// TODO can we avoid visiting every type? Are there only a few, identifiable, types that may perform navigation? public override void TraverseChildren(ITypeDefinition typeDefinition) { typeBeingTraversed = typeDefinition; if (typeDefinition.isPhoneApplicationClass(host)) { NamespaceTypeDefinition mutableTypeDef = typeDefinition as NamespaceTypeDefinition; if (mutableTypeDef != null) { // TODO unify code for current uri fieldreference FieldDefinition fieldDef = new FieldDefinition() { ContainingTypeDefinition = mutableTypeDef, InternFactory = host.InternFactory, IsStatic = true, Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE), Type = host.PlatformType.SystemString, Visibility = TypeMemberVisibility.Public, }; PhoneCodeHelper.CurrentURIFieldDefinition = fieldDef; mutableTypeDef.Fields.Add(fieldDef); } } codeTraverser.Traverse(typeDefinition); base.TraverseChildren(typeDefinition); }
/// <summary> /// Do not deeper if type is not allowed - (as requested on mutation testing start) /// </summary> /// <param name="namespaceTypeDefinition"></param> public override void RewriteChildren(NamespaceTypeDefinition namespaceTypeDefinition) { if (_filter.Matches(namespaceTypeDefinition)) { base.RewriteChildren(namespaceTypeDefinition); } }
private INamedTypeDefinition GenerateTypeA(IUnitNamespace rootNamespace) { var nt = Host.NameTable; var typeA = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("A"), InternFactory = Host.InternFactory, IsClass = true }; var typeParameter = new GenericTypeParameter { Name = nt.GetNameFor("T"), InternFactory = Host.InternFactory, DefiningType = typeA, }; typeA.GenericParameters.Add(typeParameter); var baseGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = typeParameter, ContainingTypeDefinition = typeA, InternFactory = Host.InternFactory, IsNewSlot = true }; typeA.Methods.Add(baseGetMethod); var il = new ILGenerator(Host); var localVar = new LocalDefinition { Type = typeParameter, Name = nt.GetNameFor("local1"), }; // tricky moment, ILGeneratorMethodBody fills internal collection of local vars only in constructor. // lines below should not be swapped il.AddVariableToCurrentScope(localVar); var body = new ILGeneratorMethodBody(il, true, 1) { MethodDefinition = baseGetMethod }; baseGetMethod.Body = body; il.Emit(OperationCode.Ldloca, localVar); il.Emit(OperationCode.Initobj, typeParameter); il.Emit(OperationCode.Ldloc_0); il.Emit(OperationCode.Ret); return(typeA); }
/// <summary> /// Create private GraphInstance __graphInstance backing field. /// </summary> /// <param name="namespaceTypeDefinition"></param> /// <returns></returns> public override NamespaceTypeDefinition Mutate(NamespaceTypeDefinition namespaceTypeDefinition) { // Only inject types marked with GraphTypeAttribute if (namespaceTypeDefinition.Attributes.Where(a => a.Type.ToString() == "ExoGraph.GraphTypeAttribute").Any()) { // Add __graphInstance private field //var graphInstanceField = new FieldDefinition() //{ // Name = host.NameTable.GetNameFor("__graphInstance"), // Type = graphInstance, // InternFactory = host.InternFactory, //}; //namespaceTypeDefinition.Fields.Add(graphInstanceField); //// Add IGraphInstance interface to type definition //namespaceTypeDefinition.Interfaces.Add(UnitHelper.FindType(host.NameTable, exoGraphAssembly, "ExoGraph.IGraphInstance")); //// Add ExoGraph.IGraphInstance.get_Instance getter //var get_Instance = new MethodDefinition //{ // ContainingTypeDefinition = namespaceTypeDefinition, // Type = graphInstance, // Name = host.NameTable.GetNameFor("ExoGraph.IGraphInstance.get_Instance"), // IsSpecialName = true, // IsHiddenBySignature = true, // InternFactory = host.InternFactory, // Body = new MethodBody() // { // Operations = new List<IOperation>() // { // // Load this pointer onto stack // new Operation() { OperationCode = OperationCode.Ldarg_0 }, // // Load graph instance from local field // new Operation() { OperationCode = OperationCode.Ldfld, Value = graphInstanceField }, // // return the graph instance // new Operation() { OperationCode = OperationCode.Ret }, // } // } //}; //namespaceTypeDefinition.Methods.Add(get_Instance); //// Add IGraphInstance.Instance property //namespaceTypeDefinition.Properties.Add(new PropertyDefinition() //{ // Accessors = new List<IMethodReference>() { get_Instance }, // ContainingTypeDefinition = namespaceTypeDefinition, // Visibility = TypeMemberVisibility.Public, // Name = host.NameTable.GetNameFor("ExoGraph.IGraphInstance.Instance"), // Type = graphInstance, // Getter = get_Instance //}); } return base.Mutate(namespaceTypeDefinition); }
/// <summary> /// Create private GraphInstance __graphInstance backing field. /// </summary> /// <param name="namespaceTypeDefinition"></param> /// <returns></returns> public override NamespaceTypeDefinition Mutate(NamespaceTypeDefinition namespaceTypeDefinition) { // Only inject types marked with GraphTypeAttribute if (namespaceTypeDefinition.Attributes.Where(a => a.Type.ToString() == "ExoGraph.GraphTypeAttribute").Any()) { // Add __graphInstance private field //var graphInstanceField = new FieldDefinition() //{ // Name = host.NameTable.GetNameFor("__graphInstance"), // Type = graphInstance, // InternFactory = host.InternFactory, //}; //namespaceTypeDefinition.Fields.Add(graphInstanceField); //// Add IGraphInstance interface to type definition //namespaceTypeDefinition.Interfaces.Add(UnitHelper.FindType(host.NameTable, exoGraphAssembly, "ExoGraph.IGraphInstance")); //// Add ExoGraph.IGraphInstance.get_Instance getter //var get_Instance = new MethodDefinition //{ // ContainingTypeDefinition = namespaceTypeDefinition, // Type = graphInstance, // Name = host.NameTable.GetNameFor("ExoGraph.IGraphInstance.get_Instance"), // IsSpecialName = true, // IsHiddenBySignature = true, // InternFactory = host.InternFactory, // Body = new MethodBody() // { // Operations = new List<IOperation>() // { // // Load this pointer onto stack // new Operation() { OperationCode = OperationCode.Ldarg_0 }, // // Load graph instance from local field // new Operation() { OperationCode = OperationCode.Ldfld, Value = graphInstanceField }, // // return the graph instance // new Operation() { OperationCode = OperationCode.Ret }, // } // } //}; //namespaceTypeDefinition.Methods.Add(get_Instance); //// Add IGraphInstance.Instance property //namespaceTypeDefinition.Properties.Add(new PropertyDefinition() //{ // Accessors = new List<IMethodReference>() { get_Instance }, // ContainingTypeDefinition = namespaceTypeDefinition, // Visibility = TypeMemberVisibility.Public, // Name = host.NameTable.GetNameFor("ExoGraph.IGraphInstance.Instance"), // Type = graphInstance, // Getter = get_Instance //}); } return(base.Mutate(namespaceTypeDefinition)); }
// this method creates an new interface for the given namespace public NamespaceTypeDefinition createNewInterface(String className, IUnitNamespace containingUnitNamespace) { // create a new class object and modify it to be an interface NamespaceTypeDefinition newInterface = this.createNewClass(className, containingUnitNamespace, false, false); newInterface.IsAbstract = true; newInterface.IsInterface = true; newInterface.BaseClasses = null; return(newInterface); }
private void ReportNameCollisionAndRename(NamespaceTypeDefinition nsType, NamespaceTypeDefinition laterNsType, int position) { Contract.Requires(nsType != null); Contract.Requires(laterNsType != null); laterNsType.Name = this.host.NameTable.GetNameFor(laterNsType.Name.Value + "``" + position); this.host.ReportError(new ErrorMessage() { Code = 4, ErrorReporter = this, Error = MergeError.DuplicateGlobalField, MessageParameter = TypeHelper.GetTypeName(nsType), }); }
protected void DefineModule(Assembly assembly, RootUnitNamespace rootNamespace) { var nt = Host.NameTable; var module = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("<Module>"), InternFactory = Host.InternFactory, IsClass = true }; assembly.AllTypes.Add(module); }
public override IRootUnitNamespace Rewrite(IRootUnitNamespace root) { var testClass = new NamespaceTypeDefinition { BaseClasses = new List <ITypeReference>(1) { Host.PlatformType.SystemObject }, ContainingUnitNamespace = root, InternFactory = Host.InternFactory, IsClass = true, IsPublic = true, Methods = new List <IMethodDefinition>(1), Name = NameTable.GetNameFor("VisualMutatorGeneratedClass"), }; ((RootUnitNamespace)root).Members.Add(testClass); ((Assembly)Module).AllTypes.Add(testClass); var mainMethod = new MethodDefinition { ContainingTypeDefinition = testClass, InternFactory = Host.InternFactory, IsCil = true, IsStatic = true, Name = NameTable.GetNameFor("FailOnZero"), Type = Host.PlatformType.SystemInt32, Visibility = TypeMemberVisibility.Public, }; mainMethod.Parameters = new List <IParameterDefinition>() { new ParameterDefinition() { Type = Host.PlatformType.SystemInt32, Name = NameTable.GetNameFor("x"), } }; testClass.Methods.Add(mainMethod); var body = new SourceMethodBody(Host) { MethodDefinition = mainMethod, LocalsAreZeroed = true }; mainMethod.Body = body; body.Block = GeneratedBlock; return(root); }
private INamedTypeDefinition GenerateTypeA(IUnitNamespace rootNamespace) { var nt = Host.NameTable; var typeA = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("A"), InternFactory = Host.InternFactory, IsClass = true }; var typeParameter = new GenericTypeParameter { Name = nt.GetNameFor("T"), InternFactory = Host.InternFactory, DefiningType = typeA, }; typeA.GenericParameters.Add(typeParameter); var baseGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = typeParameter, ContainingTypeDefinition = typeA, InternFactory = Host.InternFactory, IsNewSlot = true }; typeA.Methods.Add(baseGetMethod); var il = new ILGenerator(Host); var localVar = new LocalDefinition { Type = typeParameter, Name = nt.GetNameFor("local1"), }; // tricky moment, ILGeneratorMethodBody fills internal collection of local vars only in constructor. // lines below should not be swapped il.AddVariableToCurrentScope(localVar); var body = new ILGeneratorMethodBody(il, true, 1) {MethodDefinition = baseGetMethod}; baseGetMethod.Body = body; il.Emit(OperationCode.Ldloca, localVar); il.Emit(OperationCode.Initobj, typeParameter); il.Emit(OperationCode.Ldloc_0); il.Emit(OperationCode.Ret); return typeA; }
// this function fills the rest of the graph with random nodes private void fillNodesRecursively(NodeObject currentNode, List <int> currentPosition, int currentDepth, int maxDepth, List <PossibleNode> allPossibleNodes, ValidGraphPath[] validPaths) { // check if the maximal depth is reached if (currentDepth >= maxDepth) { return; } // fill all missing nodes of the current object with new random nodes for (int idx = 0; idx < currentNode.dimension; idx++) { // copy position list and add path index to the position List <int> tempCurrentPosition = new List <int>(currentPosition); tempCurrentPosition.Add(idx); if (currentNode.nodeObjects[idx] == null) { // get random possible node from list of all possible nodes int randElement = this.prng.Next(allPossibleNodes.Count); PossibleNode possibleNode = allPossibleNodes.ElementAt(randElement); NamespaceTypeDefinition classToUse = possibleNode.givenClass; MethodDefinition nodeConstructor = possibleNode.nodeConstructor; // generate path element from chosen interface PathElement pathElement = new PathElement(); // create new node object currentNode.nodeObjects[idx] = new NodeObject(this.graphDimension, this.graphValidPathCount, classToUse, nodeConstructor, pathElement, tempCurrentPosition); // search through every valid path if the new created filler node has the same attributes as the valid path node // => add it to the list of possible nodes that can be used for an exchange between valid node and filler node for (int validPathId = 0; validPathId < validPaths.Count(); validPathId++) { for (int depth = 0; depth < validPaths[validPathId].pathElements.Count(); depth++) { // check if the used class of the current filler node is in the list of possible classes of the valid path node if (validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleClasses.Contains(classToUse)) { // add current filler node to the list of possible exchange nodes if (!validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleExchangeObjects.Contains(currentNode.nodeObjects[idx])) { validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleExchangeObjects.Add(currentNode.nodeObjects[idx]); } } } } } this.fillNodesRecursively(currentNode.nodeObjects[idx], tempCurrentPosition, currentDepth + 1, maxDepth, allPossibleNodes, validPaths); } }
public override void RewriteChildren(Assembly assembly) { // Clear all win32 resources. The version resource will get repopulated. assembly.Win32Resources = new List <IWin32Resource>(); // Remove all the references they will get repopulated while outputing. assembly.AssemblyReferences.Clear(); // Remove all the module references (aka native references) assembly.ModuleReferences = new List <IModuleReference>(); // Remove all file references (ex: *.nlp files in mscorlib) assembly.Files = new List <IFileReference>(); // Remove all security attributes (ex: permissionset in IL) assembly.SecurityAttributes = new List <ISecurityAttribute>(); // Reset the core assembly symbolic identity to the seed core assembly (e.g. mscorlib, corefx) // and not the contract core (e.g. System.Runtime). assembly.CoreAssemblySymbolicIdentity = _seedCoreAssemblyReference.AssemblyIdentity; // Add reference to seed core assembly up-front so that we keep the same order as the C# compiler. assembly.AssemblyReferences.Add(_seedCoreAssemblyReference); // Remove all type definitions except for the "<Module>" type. Remove all fields and methods from it. NamespaceTypeDefinition moduleType = assembly.AllTypes.SingleOrDefault(t => t.Name.Value == "<Module>") as NamespaceTypeDefinition; assembly.AllTypes.Clear(); if (moduleType != null) { moduleType.Fields?.Clear(); moduleType.Methods?.Clear(); assembly.AllTypes.Add(moduleType); } // Remove any preexisting typeforwards. assembly.ExportedTypes = new List <IAliasForType>(); // Remove any preexisting resources. assembly.Resources = new List <IResourceReference>(); // Clear the reference assembly flag from the contract. // For design-time facades, it will be added back later. assembly.Flags &= ~ReferenceAssemblyFlag; // This flag should not be set until the delay-signed assembly we emit is actually signed. assembly.StrongNameSigned = false; base.RewriteChildren(assembly); }
private void MakeInternal(NamedTypeDefinition nsType) { NestedTypeDefinition nestedTypeDef = nsType as NestedTypeDefinition; NamespaceTypeDefinition namespaceTypeDef = nsType as NamespaceTypeDefinition; if (namespaceTypeDef != null) { namespaceTypeDef.IsPublic = false; } else if (nestedTypeDef != null) { nestedTypeDef.Visibility = GetInternalVisibility(nestedTypeDef.Visibility); } }
public override void Mutate(Assembly assembly) { Logger.LogInfo("Adding processed flag."); var processedInterface = new NamespaceTypeDefinition() { InternFactory = Host.InternFactory, ContainingUnitNamespace = assembly.UnitNamespaceRoot, Name = Host.NameTable.GetNameFor("ProcessedByWeavR"), IsAbstract = true, IsInterface = true, MangleName = false }; assembly.AllTypes.Add(processedInterface); ((RootUnitNamespace)assembly.UnitNamespaceRoot).Members.Add(processedInterface); }
public override void RewriteChildren(RootUnitNamespace rootUnitNamespace) { this.classHoldingThreeArgVersions = this.GetContractClass(rootUnitNamespace); base.RewriteChildren(rootUnitNamespace); #region Possibly add class for any contract methods that were defined. if (0 < this.threeArgumentVersionofContractMethod.Count) { // Only add class to assembly if any 3 arg versions were actually created rootUnitNamespace.Members.Add(classHoldingThreeArgVersions); this.allTypes.Add(classHoldingThreeArgVersions); } #endregion Possibly add class for any contract methods that were defined. #region Create a reference to [ContractReferenceAssembly] to mark the assembly with INamespaceTypeDefinition contractReferenceAssemblyAttribute = null; #region First see if we can find it in the same assembly as the one we are rewriting var unit = rootUnitNamespace.Unit; contractReferenceAssemblyAttribute = UnitHelper.FindType(this.host.NameTable, unit, "System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute") as INamespaceTypeDefinition; #endregion First see if we can find it in the same assembly as the one we are rewriting #region If it doesn't exist there, then define it in the same place that the three-argument versions are defined if (contractReferenceAssemblyAttribute is Dummy) { contractReferenceAssemblyAttribute = CreateContractReferenceAssemblyAttribute(rootUnitNamespace); } #endregion If it doesn't exist there, then define it in the same place that the three-argument versions are defined #region Create a reference to the ctor var ctorRef = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = contractReferenceAssemblyAttribute, InternFactory = this.host.InternFactory, Name = host.NameTable.Ctor, Type = systemVoidType, }; var rm = ctorRef.ResolvedMethod; this.ContractReferenceAssemblyAttributeInstance = new CustomAttribute() { Constructor = ctorRef, }; #endregion Create a reference to the ctor #endregion Create a reference to [ContractReferenceAssembly] to mark the assembly with return; }
static void mergeClassWithAllAncestors(NamespaceTypeDefinition mergeTargetClass, PeReader.DefaultHost host) { List <NamespaceTypeDefinition> ancestorClasses = new List <NamespaceTypeDefinition>(); ancestorClasses.Add(mergeTargetClass); NamespaceTypeDefinition currentClass = mergeTargetClass; NamespaceTypeDefinition ancestorClass = null; while (true) { // get class from which was inherited if (currentClass.BaseClasses.Count() == 1) { // only add base classes of type NamespaceTypeDefinition if (currentClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition != null) { ancestorClass = (currentClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition); } // ignore ancestor that are not of type NamespaceTypeDefinition else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // add ancestor class to list of ancestor classes globalLog.writeLine("Found ancestor: " + ancestorClass.ToString()); ancestorClasses.Add(ancestorClass); currentClass = ancestorClass; } // mrge class with ancenstor (start with the "highest" ancestor) for (int i = (ancestorClasses.Count - 1); i >= 0; i--) { globalLog.writeLine("Merge class \"" + ancestorClasses[i].ToString() + "\" with ancestor"); mergeClassWithAncestor(ancestorClasses[i], host); globalLog.writeLine(""); } }
/// <summary> /// Creates the appropriate kind of type definition (nested or not) and /// adds it to the type symbol cache. /// </summary> private NamedTypeDefinition CreateTypeDefinition(INamedTypeSymbol typeSymbol) { Contract.Requires(typeSymbol != null); NamedTypeDefinition cciType; if (typeSymbol.ContainingType == null) { cciType = new NamespaceTypeDefinition() { ContainingUnitNamespace = (IUnitNamespace)this.namespaceSymbolCache[typeSymbol.ContainingNamespace], IsPublic = typeSymbol.DeclaredAccessibility == Accessibility.Public, }; } else { cciType = new NestedTypeDefinition() { ContainingTypeDefinition = (ITypeDefinition)this.typeSymbolCache[typeSymbol.ContainingType], Visibility = TypeMemberVisibility.Private, }; } if (typeSymbol.TypeKind == TypeKind.Interface) { cciType.IsAbstract = true; cciType.IsInterface = true; } else { cciType.BaseClasses = new List <ITypeReference> { this.Map(typeSymbol.BaseType) }; cciType.IsBeforeFieldInit = true; // REVIEW: How to determine from typeSymbol? } cciType.IsClass = typeSymbol.IsReferenceType; cciType.IsValueType = typeSymbol.IsValueType; cciType.IsSealed = typeSymbol.IsSealed; cciType.InternFactory = this.host.InternFactory; cciType.Locations = Helper.WrapLocations(typeSymbol.Locations); cciType.Name = this.host.NameTable.GetNameFor(typeSymbol.Name); this.typeSymbolCache.Add(typeSymbol, cciType); return(cciType); }
private NamespaceTypeDefinition CreateContractClass(UnitNamespace unitNamespace) { var contractTypeName = this.host.NameTable.GetNameFor("Contract"); var contractNamespaceName = this.host.NameTable.GetNameFor("System.Diagnostics.Contracts"); Microsoft.Cci.MethodReference compilerGeneratedCtor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0); CustomAttribute compilerGeneratedAttribute = new CustomAttribute(); compilerGeneratedAttribute.Constructor = compilerGeneratedCtor; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = unitNamespace, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { // NB: The string name must be kept in sync with the code that recognizes contract // methods!! Name = contractTypeName, Attributes = new List <ICustomAttribute> { compilerGeneratedAttribute }, BaseClasses = new List <ITypeReference> { this.systemObjectType }, ContainingUnitNamespace = contractsNs, InternFactory = this.host.InternFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; return(result); }
public virtual void VisitNamespace(UnitNamespace unitNamespace) { if (unitNamespace.Members == null) { return; } for (int i = 0; i < unitNamespace.Members.Count; i++) { INamespaceMember member = unitNamespace.Members[i]; MethodDefinition methodDef = member as MethodDefinition; if (methodDef != null) { VisitMethod(methodDef, null); continue; } NamespaceTypeDefinition typeDef = member as NamespaceTypeDefinition; if (typeDef != null) { VisitType(typeDef); continue; } UnitNamespace ns = member as UnitNamespace; if (ns != null) { VisitNamespace(ns); } else { throw new InvalidOperationException("INamespaceMember"); } } }
public void AddGenericParamInPlace(NamespaceTypeDefinition namespaceTypeDefinition) { var oneMoreGP = new List <IGenericTypeParameter>(); var gp1 = new GenericTypeParameter() { InternFactory = this.host.InternFactory, PlatformType = this.host.PlatformType, Name = this.host.NameTable.GetNameFor("_SX_"), DefiningType = namespaceTypeDefinition, Index = 0 }; oneMoreGP.Add(gp1); if (namespaceTypeDefinition.GenericParameters != null) { foreach (GenericTypeParameter gp in namespaceTypeDefinition.GenericParameters) { gp.Index++; oneMoreGP.Add(gp); } } namespaceTypeDefinition.GenericParameters = oneMoreGP; }
private NamespaceTypeDefinition GenerateTypeB(IUnitNamespace rootNamespace, ITypeReference baseType) { var nt = Host.NameTable; var typeB = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("B"), InternFactory = Host.InternFactory, IsClass = true, BaseClasses = { baseType } }; var overrideGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = Host.PlatformType.SystemString, ContainingTypeDefinition = typeB, InternFactory = Host.InternFactory }; typeB.Methods.Add(overrideGetMethod); var il = new ILGenerator(Host); var body = new ILGeneratorMethodBody(il, true, 1) { MethodDefinition = overrideGetMethod }; overrideGetMethod.Body = body; il.Emit(OperationCode.Ldstr, "1"); il.Emit(OperationCode.Ret); return(typeB); }
public override void RewriteChildren(NamespaceTypeDefinition namespaceTypeDefinition) { this.PruneInterfacesAndExplicitImplementationOverrides(namespaceTypeDefinition); base.RewriteChildren(namespaceTypeDefinition); }
static void Main(string[] args) { var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor("hello"), ModuleName = nameTable.GetNameFor("hello.exe"), PlatformType = host.PlatformType, Kind = ModuleKind.ConsoleApplication, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); var testClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List<IMethodDefinition>(1), Name = nameTable.GetNameFor("Test"), }; rootUnitNamespace.Members.Add(testClass); assembly.AllTypes.Add(testClass); testClass.BaseClasses = new List<ITypeReference>() { host.PlatformType.SystemObject }; var mainMethod = new MethodDefinition() { ContainingTypeDefinition = testClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; testClass.Methods.Add(mainMethod); var ilGenerator = new ILGenerator(host, mainMethod); var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console"); var writeLine = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString); ilGenerator.Emit(OperationCode.Ldstr, "hello"); ilGenerator.Emit(OperationCode.Call, writeLine); ilGenerator.Emit(OperationCode.Ret); var body = new ILGeneratorMethodBody(ilGenerator, true, 1, mainMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); mainMethod.Body = body; using (var peStream = File.Create("hello.exe")) { PeWriter.WritePeToStream(assembly, host, peStream); } } }
// adds the given interface to the given class public void addInterface(NamespaceTypeDefinition addTargetClass, ITypeDefinition interfaceToAdd) { // add interface to target class if (addTargetClass.Interfaces != null) { // check if interface is already implemented by class if (addTargetClass.Interfaces.Contains(interfaceToAdd)) { this.logger.writeLine("Class \"" + addTargetClass.ToString() + "\" already implements interface \"" + interfaceToAdd.ToString() + "\""); return; } else { this.logger.writeLine("Add interface \"" + interfaceToAdd.ToString() + "\" to class \"" + addTargetClass.ToString() + "\""); addTargetClass.Interfaces.Add(interfaceToAdd); } } else { List<ITypeReference> interfaceList = new List<ITypeReference>(); interfaceList.Add(interfaceToAdd); addTargetClass.Interfaces = interfaceList; } // copy all attributes from the interface to the target class if (interfaceToAdd.Fields != null) { foreach (FieldDefinition field in interfaceToAdd.Fields) { FieldDefinition copy = new FieldDefinition(); this.helperClass.copyField(copy, field); copy.ContainingTypeDefinition = addTargetClass; // set intern factory of the copied field to the one of the class // (without it, the generated binary file will have strange results like use only the same field) copy.InternFactory = addTargetClass.InternFactory; addTargetClass.Fields.Add(copy); } } // copy all methods from the interface to the target class if (interfaceToAdd.Methods != null) { foreach (IMethodDefinition method in interfaceToAdd.Methods) { // search through all methods in the target class // to see if this method was already added bool foundMethod = false; foreach (IMethodDefinition tempMethod in addTargetClass.Methods) { // skip constructors if (tempMethod.IsConstructor) { continue; } // check if the number of parameters are the same if (tempMethod.ParameterCount == method.ParameterCount) { // check if the parameters have the same type in the same order bool parameterCorrect = true; for (int i = 0; i < method.ParameterCount; i++) { if (method.Parameters.ElementAt(i).Type != tempMethod.Parameters.ElementAt(i).Type) { parameterCorrect = false; break; } } // check if the return type is the same bool returnTypeCorrect = false; if (method.Type.Equals(tempMethod.Type)) { returnTypeCorrect = true; } // check if both methods are static // (c# compiler does not allow static + non-static function with // same signature in same class, but CIL does) bool bothStatic = false; if (method.IsStatic == tempMethod.IsStatic) { bothStatic = true; } // if the parameters and return type are correct => check the name if (parameterCorrect && returnTypeCorrect && bothStatic) { if (method.Name.Equals(tempMethod.Name)) { // if name is the same => method already added foundMethod = true; break; } } } } // skip if method was already added if (foundMethod) { this.logger.writeLine("Method \"" + method.Name.ToString() + "\" already exists"); continue; } this.logger.writeLine("Add method: " + method.Name.ToString()); // copy method MethodDefinition copy = new MethodDefinition(); this.helperClass.copyMethod(copy, method); copy.ContainingTypeDefinition = addTargetClass; // generate random dead code for newly created method ILGenerator ilGenerator = new ILGenerator(host, method); foreach (IOperation tempOperation in CodeGenerator.generateDeadCode(true)) { ilGenerator.Emit(tempOperation.OperationCode, tempOperation.Value); } IMethodBody newBody = new ILGeneratorMethodBody(ilGenerator, true, 8, method, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); copy.Body = newBody; // set intern factory of the copied method to the one of the class // (without it, the generated binary file will have strange results like call always the same method) copy.InternFactory = addTargetClass.InternFactory; // set method to not abstract copy.IsAbstract = false; // set method to not external copy.IsExternal = false; // set intern factory of the copied method to the one of the class // (without it, the generating of the binary file will have strange results) copy.InternFactory = addTargetClass.InternFactory; // add method to the class addTargetClass.Methods.Add(copy); } } }
private void createNodeInterface(IUnitNamespace targetNamespace) { this.nodeInterface = this.helperClass.createNewInterface("iNode", targetNamespace); // TODO: interface name // create getter and setter for the startPointer variable this.interfaceStartPointerGet = this.helperClass.createNewMethod("startPointer_get", this.nodeInterface, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, true, true); // TODO: method name List<IParameterDefinition> parameters = new List<IParameterDefinition>(); ParameterDefinition parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Name = host.NameTable.GetNameFor("value"); parameter.Type = this.nodeInterface; parameters.Add(parameter); this.interfaceStartPointerSet = this.helperClass.createNewMethod("startPointer_set", this.nodeInterface, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, true, true); // TODO: method name // create getter and setter for the childNodes array variable parameters = new List<IParameterDefinition>(); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); this.interfaceChildNodesGet = this.helperClass.createNewMethod("childNodes_get", this.nodeInterface, this.nodeInterface, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, true, true); // TODO: method name parameters = new List<IParameterDefinition>(); // iNode parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.nodeInterface; parameters.Add(parameter); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); this.interfaceChildNodesSet = this.helperClass.createNewMethod("childNodes_set", this.nodeInterface, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, true, true); // TODO: method name // when debugging is activated // => create getter for the id variable that distinct identifies the object if (this.debugging) { this.logger.writeLine("Debugging activated: Adding getter for unique object id to node interface"); this.debuggingInterfaceIdGet = this.helperClass.createNewMethod("DEBUG_objectId_get", this.nodeInterface, this.host.PlatformType.SystemString, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, true, true); // TODO: method name } }
// this function adds the created iNode interface to the class and also implements all neded functions public void addNodeInterfaceToTargetClass(NamespaceTypeDefinition givenClass) { this.logger.writeLine(""); this.logger.writeLine("Add node interface \"" + this.nodeInterface.ToString() + "\" to class \"" + givenClass.ToString() + "\""); // check if generated interface was already added to target class if (givenClass.Interfaces != null && givenClass.Interfaces.Contains(this.nodeInterface)) { this.logger.writeLine("Class \"" + givenClass.ToString() + "\" already contains node interface \"" + this.nodeInterface.ToString() + "\""); return; } // add nodes interface to class if (givenClass.Interfaces != null) { givenClass.Interfaces.Add(this.nodeInterface); } else { givenClass.Interfaces = new List<ITypeReference>(); givenClass.Interfaces.Add(this.nodeInterface); } // add start pointer field FieldDefinition startPointerField = new FieldDefinition(); startPointerField.IsCompileTimeConstant = false; startPointerField.IsNotSerialized = false; startPointerField.IsReadOnly = false; startPointerField.IsRuntimeSpecial = false; startPointerField.IsSpecialName = false; startPointerField.Type = this.nodeInterface; startPointerField.IsStatic = false; startPointerField.Visibility = TypeMemberVisibility.Public; startPointerField.Name = host.NameTable.GetNameFor("startPointer"); startPointerField.InternFactory = host.InternFactory; startPointerField.ContainingTypeDefinition = givenClass; if (givenClass.Fields != null) { givenClass.Fields.Add(startPointerField); } else { givenClass.Fields = new List<IFieldDefinition>(); givenClass.Fields.Add(startPointerField); } // create getter for the startPointer variable MethodDefinition startPointerGetMethod = this.helperClass.createNewMethod("startPointer_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ILGenerator ilGenerator = new ILGenerator(host, startPointerGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, startPointerField); ilGenerator.Emit(OperationCode.Ret); IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); startPointerGetMethod.Body = body; // create setter for the startPointer variable List<IParameterDefinition> parameters = new List<IParameterDefinition>(); ParameterDefinition parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Name = host.NameTable.GetNameFor("value"); parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition startPointerSetMethod = this.helperClass.createNewMethod("startPointer_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, startPointerSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stfld, startPointerField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); startPointerSetMethod.Body = body; // add childNodes array field FieldDefinition childNodesField = new FieldDefinition(); childNodesField.IsCompileTimeConstant = false; childNodesField.IsNotSerialized = false; childNodesField.IsReadOnly = false; childNodesField.IsRuntimeSpecial = false; childNodesField.IsSpecialName = false; // create array of node interface type VectorTypeReference nodeInterfaceArrayType = new VectorTypeReference(); nodeInterfaceArrayType.ElementType = this.nodeInterface; nodeInterfaceArrayType.Rank = 1; nodeInterfaceArrayType.IsFrozen = true; nodeInterfaceArrayType.IsValueType = false; nodeInterfaceArrayType.InternFactory = host.InternFactory; childNodesField.Type = nodeInterfaceArrayType; childNodesField.IsStatic = false; childNodesField.Visibility = TypeMemberVisibility.Public; childNodesField.Name = host.NameTable.GetNameFor("childNodes"); childNodesField.InternFactory = host.InternFactory; childNodesField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(childNodesField); // create getter for the childNodes variable parameters = new List<IParameterDefinition>(); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); MethodDefinition childNodesGetMethod = this.helperClass.createNewMethod("childNodes_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, childNodesGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, childNodesField); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Ldelem_Ref); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); childNodesGetMethod.Body = body; // create setter for the childNodes variable parameters = new List<IParameterDefinition>(); // iNode parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.nodeInterface; parameters.Add(parameter); // int parameter parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.host.PlatformType.SystemInt32; parameters.Add(parameter); MethodDefinition childNodesSetMethod = this.helperClass.createNewMethod("childNodes_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, childNodesSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, childNodesField); ilGenerator.Emit(OperationCode.Ldarg_2); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stelem_Ref); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); childNodesSetMethod.Body = body; // add current node field FieldDefinition currentNodeField = new FieldDefinition(); currentNodeField.IsCompileTimeConstant = false; currentNodeField.IsNotSerialized = false; currentNodeField.IsReadOnly = false; currentNodeField.IsRuntimeSpecial = false; currentNodeField.IsSpecialName = false; currentNodeField.Type = this.nodeInterface; currentNodeField.IsStatic = false; currentNodeField.Visibility = TypeMemberVisibility.Public; currentNodeField.Name = host.NameTable.GetNameFor("currentNode"); currentNodeField.InternFactory = host.InternFactory; currentNodeField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(currentNodeField); // create getter for the currentNode variable MethodDefinition currentNodeGetMethod = this.helperClass.createNewMethod("currentNode_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, currentNodeGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, currentNodeField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); currentNodeGetMethod.Body = body; // create setter for the currentNode variable parameters = new List<IParameterDefinition>(); parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Name = host.NameTable.GetNameFor("value"); parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition currentNodeSetMethod = this.helperClass.createNewMethod("currentNode_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the setter method ilGenerator = new ILGenerator(host, currentNodeSetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_1); ilGenerator.Emit(OperationCode.Stfld, currentNodeField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); currentNodeSetMethod.Body = body; // check if debugging is activated // => add graph debugging attributes and methods MethodDefinition objectIdGetMethod = null; FieldDefinition objectIdField = null; if (this.debugging) { this.logger.writeLine("Debugging activated: Adding field for unique object id and getter method"); // add objectId field objectIdField = new FieldDefinition(); objectIdField.IsCompileTimeConstant = false; objectIdField.IsNotSerialized = false; objectIdField.IsReadOnly = false; objectIdField.IsRuntimeSpecial = false; objectIdField.IsSpecialName = false; objectIdField.Type = this.host.PlatformType.SystemString; objectIdField.IsStatic = false; objectIdField.Name = host.NameTable.GetNameFor("DEBUG_objectId"); objectIdField.Visibility = TypeMemberVisibility.Public; objectIdField.InternFactory = host.InternFactory; objectIdField.ContainingTypeDefinition = givenClass; givenClass.Fields.Add(objectIdField); // create getter for the objectId variable objectIdGetMethod = this.helperClass.createNewMethod("DEBUG_objectId_get", givenClass, this.host.PlatformType.SystemString, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name // create a body for the getter method ilGenerator = new ILGenerator(host, objectIdGetMethod); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldfld, objectIdField); ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 1, objectIdGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty); objectIdGetMethod.Body = body; } // add .ctor(iNode) to target class parameters = new List<IParameterDefinition>(); parameter = new ParameterDefinition(); parameter.IsIn = false; parameter.IsOptional = false; parameter.IsOut = false; parameter.Type = this.nodeInterface; parameters.Add(parameter); MethodDefinition nodeConstructor = this.helperClass.createNewMethod(".ctor", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, false); nodeConstructor.IsSpecialName = true; nodeConstructor.IsHiddenBySignature = true; nodeConstructor.IsRuntimeSpecial = true; // generate node constructor body ilGenerator = new ILGenerator(host, currentNodeSetMethod); // create local variable list List<ILocalDefinition> localVariables = new List<ILocalDefinition>(); // call system.object constructor ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Call, this.helperClass.objectCtor); // initialize childNodes array ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension); ilGenerator.Emit(OperationCode.Newarr, nodeInterfaceArrayType); ilGenerator.Emit(OperationCode.Stfld, childNodesField); // check if debugging is activated // => add code to constructor that generates a unique id for this object if (this.debugging) { this.logger.writeLine("Debugging activated: Adding code to generate unique id to node constructor"); // create local integer variable needed for debugging code LocalDefinition intLocal = new LocalDefinition(); intLocal.IsReference = false; intLocal.IsPinned = false; intLocal.IsModified = false; intLocal.Type = this.host.PlatformType.SystemInt32; intLocal.MethodDefinition = nodeConstructor; localVariables.Add(intLocal); // use the hash code of this instance as unique object id ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.objectGetHashCode); ilGenerator.Emit(OperationCode.Stloc, intLocal); // cast random integer to string and store in object id ilGenerator.Emit(OperationCode.Ldloca, intLocal); ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString); ilGenerator.Emit(OperationCode.Stfld, objectIdField); } ilGenerator.Emit(OperationCode.Ret); body = new ILGeneratorMethodBody(ilGenerator, true, 8, nodeConstructor, localVariables, Enumerable<ITypeDefinition>.Empty); nodeConstructor.Body = body; // add class to the list of possible nodes for the graph PossibleNode tempStruct = new PossibleNode(); tempStruct.nodeConstructor = nodeConstructor; tempStruct.givenClass = givenClass; // for each interface the class implements add it to the according list foreach (ITypeReference interfaceRef in givenClass.Interfaces) { this.logger.writeLine("Add class \"" + givenClass.ToString() + "\" to graph interface list \"" + interfaceRef.ToString() + "\""); // check if a list with this interface already exists // => if it does just add current class to list if (this.graphInterfaces.ContainsKey(interfaceRef)) { List<PossibleNode> tempList = (List<PossibleNode>)this.graphInterfaces[interfaceRef]; tempList.Add(tempStruct); } // if not => add new list for this interface else { List<PossibleNode> tempList = new List<PossibleNode>(); tempList.Add(tempStruct); this.graphInterfaces.Add(interfaceRef, tempList); } } this.logger.writeLine(""); }
// adds the given interface to the given class public void addInterface(NamespaceTypeDefinition addTargetClass, ITypeDefinition interfaceToAdd) { // add interface to target class if (addTargetClass.Interfaces != null) { // check if interface is already implemented by class if (addTargetClass.Interfaces.Contains(interfaceToAdd)) { this.logger.writeLine("Class \"" + addTargetClass.ToString() + "\" already implements interface \"" + interfaceToAdd.ToString() + "\""); return; } else { this.logger.writeLine("Add interface \"" + interfaceToAdd.ToString() + "\" to class \"" + addTargetClass.ToString() + "\""); addTargetClass.Interfaces.Add(interfaceToAdd); } } else { List <ITypeReference> interfaceList = new List <ITypeReference>(); interfaceList.Add(interfaceToAdd); addTargetClass.Interfaces = interfaceList; } // copy all attributes from the interface to the target class if (interfaceToAdd.Fields != null) { foreach (FieldDefinition field in interfaceToAdd.Fields) { FieldDefinition copy = new FieldDefinition(); this.helperClass.copyField(copy, field); copy.ContainingTypeDefinition = addTargetClass; // set intern factory of the copied field to the one of the class // (without it, the generated binary file will have strange results like use only the same field) copy.InternFactory = addTargetClass.InternFactory; addTargetClass.Fields.Add(copy); } } // copy all methods from the interface to the target class if (interfaceToAdd.Methods != null) { foreach (IMethodDefinition method in interfaceToAdd.Methods) { // search through all methods in the target class // to see if this method was already added bool foundMethod = false; foreach (IMethodDefinition tempMethod in addTargetClass.Methods) { // skip constructors if (tempMethod.IsConstructor) { continue; } // check if the number of parameters are the same if (tempMethod.ParameterCount == method.ParameterCount) { // check if the parameters have the same type in the same order bool parameterCorrect = true; for (int i = 0; i < method.ParameterCount; i++) { if (method.Parameters.ElementAt(i).Type != tempMethod.Parameters.ElementAt(i).Type) { parameterCorrect = false; break; } } // check if the return type is the same bool returnTypeCorrect = false; if (method.Type.Equals(tempMethod.Type)) { returnTypeCorrect = true; } // check if both methods are static // (c# compiler does not allow static + non-static function with // same signature in same class, but CIL does) bool bothStatic = false; if (method.IsStatic == tempMethod.IsStatic) { bothStatic = true; } // if the parameters and return type are correct => check the name if (parameterCorrect && returnTypeCorrect && bothStatic) { if (method.Name.Equals(tempMethod.Name)) { // if name is the same => method already added foundMethod = true; break; } } } } // skip if method was already added if (foundMethod) { this.logger.writeLine("Method \"" + method.Name.ToString() + "\" already exists"); continue; } this.logger.writeLine("Add method: " + method.Name.ToString()); // copy method MethodDefinition copy = new MethodDefinition(); this.helperClass.copyMethod(copy, method); copy.ContainingTypeDefinition = addTargetClass; // generate random dead code for newly created method ILGenerator ilGenerator = new ILGenerator(host, method); foreach (IOperation tempOperation in CodeGenerator.generateDeadCode(true)) { ilGenerator.Emit(tempOperation.OperationCode, tempOperation.Value); } IMethodBody newBody = new ILGeneratorMethodBody(ilGenerator, true, 8, method, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); copy.Body = newBody; // set intern factory of the copied method to the one of the class // (without it, the generated binary file will have strange results like call always the same method) copy.InternFactory = addTargetClass.InternFactory; // set method to not abstract copy.IsAbstract = false; // set method to not external copy.IsExternal = false; // set intern factory of the copied method to the one of the class // (without it, the generating of the binary file will have strange results) copy.InternFactory = addTargetClass.InternFactory; // add method to the class addTargetClass.Methods.Add(copy); } } }
static void mergeClassWithAllAncestors(NamespaceTypeDefinition mergeTargetClass, PeReader.DefaultHost host) { List<NamespaceTypeDefinition> ancestorClasses = new List<NamespaceTypeDefinition>(); ancestorClasses.Add(mergeTargetClass); NamespaceTypeDefinition currentClass = mergeTargetClass; NamespaceTypeDefinition ancestorClass = null; while (true) { // get class from which was inherited if (currentClass.BaseClasses.Count() == 1) { // only add base classes of type NamespaceTypeDefinition if (currentClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition != null) { ancestorClass = (currentClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition); } // ignore ancestor that are not of type NamespaceTypeDefinition else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // add ancestor class to list of ancestor classes globalLog.writeLine("Found ancestor: " + ancestorClass.ToString()); ancestorClasses.Add(ancestorClass); currentClass = ancestorClass; } // mrge class with ancenstor (start with the "highest" ancestor) for (int i = (ancestorClasses.Count - 1); i >= 0; i--) { globalLog.writeLine("Merge class \"" + ancestorClasses[i].ToString() + "\" with ancestor"); mergeClassWithAncestor(ancestorClasses[i], host); globalLog.writeLine(""); } }
private NamespaceTypeDefinition CreateContractClass(UnitNamespace unitNamespace) { var contractTypeName = this.host.NameTable.GetNameFor("Contract"); var contractNamespaceName = this.host.NameTable.GetNameFor("System.Diagnostics.Contracts"); Microsoft.Cci.MethodReference compilerGeneratedCtor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0); CustomAttribute compilerGeneratedAttribute = new CustomAttribute(); compilerGeneratedAttribute.Constructor = compilerGeneratedCtor; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = unitNamespace, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { // NB: The string name must be kept in sync with the code that recognizes contract // methods!! Name = contractTypeName, Attributes = new List<ICustomAttribute>{ compilerGeneratedAttribute }, BaseClasses = new List<ITypeReference>{ this.systemObjectType }, ContainingUnitNamespace = contractsNs, InternFactory = this.host.InternFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; return result; }
private NamespaceTypeDefinition CreateContractReferenceAssemblyAttribute(IRootUnitNamespace rootNs) { var internFactory = this.host.InternFactory; var nameTable = this.host.NameTable; var contractReferenceAssemblyAttributeName = nameTable.GetNameFor("ContractReferenceAssemblyAttribute"); var contractNamespaceName = nameTable.GetNameFor("System.Diagnostics.Contracts"); #region Define type CustomAttribute compilerGeneratedAttribute = new CustomAttribute() { Constructor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0) }; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = rootNs, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { Name = contractReferenceAssemblyAttributeName, Attributes = new List <ICustomAttribute> { compilerGeneratedAttribute }, BaseClasses = new List <ITypeReference> { this.systemAttributeType }, ContainingUnitNamespace = contractsNs, //unitNamespace, InternFactory = internFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Methods = new List <IMethodDefinition>(), Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; contractsNs.Members.Add(result); this.allTypes.Add(result); #endregion Define type #region Define the ctor List <IStatement> statements = new List <IStatement>(); SourceMethodBody body = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; MethodDefinition ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = result, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = nameTable.Ctor, Type = this.systemVoidType, Visibility = TypeMemberVisibility.Public, }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = result, }; // base(); foreach (var baseClass in result.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = result, }, Type = this.systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List <IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); result.Methods.Add(ctor); #endregion Define the ctor return(result); }
private static NamespaceTypeDefinition DefineMethodHashAttributeType(HostEnvironment host, RootUnitNamespace rootUnitNamespace) { Contract.Requires(host != null); var internFactory = host.InternFactory; #region Define the type var methodHashAttributeType = new NamespaceTypeDefinition() { BaseClasses = new List <ITypeReference> { host.PlatformType.SystemAttribute, }, ContainingUnitNamespace = rootUnitNamespace, InternFactory = internFactory, //IsBeforeFieldInit = true, IsClass = true, IsPublic = true, //IsSealed = true, Methods = new List <IMethodDefinition>(1), Name = host.NameTable.GetNameFor("MethodHashAttribute"), //Layout = LayoutKind.Auto, //StringFormat = StringFormatKind.Ansi, }; #endregion #region Define the ctor var systemVoidType = host.PlatformType.SystemVoid; List <IStatement> statements = new List <IStatement>(); SourceMethodBody body = new SourceMethodBody(host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = methodHashAttributeType, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = host.NameTable.Ctor, Type = systemVoidType, Visibility = TypeMemberVisibility.Public, }; var systemStringType = host.PlatformType.SystemString; var systemIntType = host.PlatformType.SystemInt32; ctor.Parameters = new List <IParameterDefinition>() { new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("a"), Type = systemStringType, Index = 0, }, new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("b"), Type = systemIntType, Index = 1, } }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = methodHashAttributeType, }; // base(); foreach (var baseClass in methodHashAttributeType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = internFactory, Name = host.NameTable.Ctor, Type = systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = methodHashAttributeType, }, Type = systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List <IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); methodHashAttributeType.Methods.Add(ctor); #endregion Define the ctor return(methodHashAttributeType); }
private Assembly TranslateMetadata(IAssemblySymbol assemblySymbol) { Contract.Requires(assemblySymbol != null); Contract.Ensures(Contract.Result <Assembly>() != null); IAssemblyReference cciAssemblyReference = null; Assembly cciAssembly = null; if (assemblySymbolCache.TryGetValue(assemblySymbol, out cciAssemblyReference)) { cciAssembly = cciAssemblyReference as Assembly; System.Diagnostics.Debug.Assert(cciAssembly != null); return(cciAssembly); } var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var name = assemblySymbol.Identity.Name; var iname = nameTable.GetNameFor(name); cciAssembly = new Assembly() { Attributes = this.TranslateMetadata(assemblySymbol.GetAttributes()), Name = iname, Locations = Helper.WrapLocations(assemblySymbol.Locations), ModuleName = iname, Kind = ModuleKind.DynamicallyLinkedLibrary, RequiresStartupStub = this.host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, Version = assemblySymbol.Identity.Version, }; cciAssembly.AssemblyReferences.Add(coreAssembly); this.assemblySymbolCache.Add(assemblySymbol, cciAssembly); this.module = cciAssembly; var rootUnitNamespace = new RootUnitNamespace(); cciAssembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = cciAssembly; this.namespaceSymbolCache.Add(assemblySymbol.GlobalNamespace, rootUnitNamespace); var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; cciAssembly.AllTypes.Add(moduleClass); foreach (var m in assemblySymbol.GlobalNamespace.GetMembers()) { var namespaceSymbol = m as INamespaceSymbol; if (namespaceSymbol != null) { var cciNtd = TranslateMetadata(namespaceSymbol); rootUnitNamespace.Members.Add(cciNtd); continue; } var typeSymbol = m as ITypeSymbol; if (typeSymbol != null) { var namedType = TranslateMetadata((INamedTypeSymbol)typeSymbol); // TODO: fix //namedType.Attributes = TranslateMetadata(typeSymbol.GetAttributes()); var cciType = (INamespaceTypeDefinition)namedType; rootUnitNamespace.Members.Add(cciType); //cciAssembly.AllTypes.Add(cciType); continue; } } //if (this.entryPoint != null) { // cciAssembly.Kind = ModuleKind.ConsoleApplication; // cciAssembly.EntryPoint = this.entryPoint; //} return(cciAssembly); }
public GraphTransformer(IModule module, PeReader.DefaultHost host, Log.Log logger, Random prng, IUnitNamespace targetNamespace, NamespaceTypeDefinition targetClass, int depth, int dimension, bool debugging = false) { this.host = host; this.logger = logger; this.module = module; this.prng = prng; this.helperClass = new Helper(module, host, logger); this.cfgBuilder = new Cfg.CfgBuilder(module, host, logger); this.targetClass = targetClass; this.graphDepth = depth; this.graphDimension = dimension; this.debugging = debugging; this.debuggingNumber = 0; // create iNode interface this.createNodeInterface(targetNamespace); // add created iNode interface to the given target class this.addNodeInterfaceToTargetClass(this.targetClass); }
private IModule CreateNewDll(string assemblyName) { var host = new PeReader.DefaultHost(); var core = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly(); assembly.Name = host.NameTable.GetNameFor(assemblyName); assembly.ModuleName = host.NameTable.GetNameFor(assemblyName + ".dll"); assembly.Kind = ModuleKind.DynamicallyLinkedLibrary; assembly.PlatformType = host.PlatformType; assembly.TargetRuntimeVersion = core.TargetRuntimeVersion; assembly.AssemblyReferences.Add(core); foreach (var referencePath in model.ReferencePaths) { assembly.AssemblyReferences.Add(host.LoadUnitFrom(referencePath) as IAssembly); } var root = new RootUnitNamespace(); root.Unit = assembly; assembly.UnitNamespaceRoot = root; var module = new NamespaceTypeDefinition(); module.Name = host.NameTable.GetNameFor("<Module>"); module.IsClass = true; module.InternFactory = host.InternFactory; module.ContainingUnitNamespace = root; assembly.AllTypes.Add(module); var rootTypeNamespace = new NestedUnitNamespace(); rootTypeNamespace.Name = host.NameTable.GetNameFor(assembly.Name.Value); root.Members.Add(rootTypeNamespace); foreach (var classConfiguration in model.Classes) { var newClass = new NamespaceTypeDefinition(); newClass.IsAbstract = classConfiguration.IsAbstract; newClass.IsClass = true; newClass.BaseClasses = new List<ITypeReference>{ host.PlatformType.SystemObject }; newClass.IsPublic = true; if (classConfiguration.IsStatic) { newClass.IsStatic = true; newClass.IsAbstract = true; newClass.IsSealed = true; } if (!String.IsNullOrEmpty(classConfiguration.Namespace)) { NestedUnitNamespace classContainer = rootTypeNamespace; var namespaceNames = classConfiguration.Namespace.Split('.'); foreach (var namespaceName in namespaceNames) { var existingMembers = classContainer.GetMembersNamed(host.NameTable.GetNameFor(namespaceName), false); var nestedNamespace = new NestedUnitNamespace(); foreach (var existing in existingMembers) { if (existing as NestedUnitNamespace != null) { nestedNamespace = existing as NestedUnitNamespace; break; } } nestedNamespace.Name = host.NameTable.GetNameFor(namespaceName); nestedNamespace.ContainingUnitNamespace = classContainer; classContainer.Members.Add(nestedNamespace); classContainer = nestedNamespace; } newClass.ContainingUnitNamespace = classContainer; } else { newClass.ContainingUnitNamespace = rootTypeNamespace; } newClass.InternFactory = host.InternFactory; newClass.Name = host.NameTable.GetNameFor(classConfiguration.Name); newClass.Methods = new List<IMethodDefinition>(classConfiguration.Methods.Count); newClass.Fields = new List<IFieldDefinition>(classConfiguration.Fields.Count); foreach (var methodConfiguration in classConfiguration.Methods) { var newMethod = new MethodDefinition(); newMethod.Name = host.NameTable.GetNameFor(methodConfiguration.Name); newMethod.IsStatic = methodConfiguration.IsStatic; newMethod.ContainingTypeDefinition = newClass; newMethod.IsCil = true; newMethod.IsHiddenBySignature = true; newMethod.InternFactory = host.InternFactory; newMethod.Visibility = TypeMemberVisibility.Public; newMethod.Type = host.PlatformType.SystemVoid; var newMethodParameters = new List<IParameterDefinition>(); foreach (var param in methodConfiguration.Parameters) { var newMethodParameter = new ParameterDefinition(); newMethodParameter.ContainingSignature = newMethod; newMethodParameter.Index = (ushort)methodConfiguration.Parameters.IndexOf(param); newMethodParameter.Name = host.NameTable.GetNameFor(param.Key); newMethodParameter.Type = new UnitReflector(host).Get(param.Value); newMethodParameters.Add(newMethodParameter); } newMethod.Parameters = newMethodParameters; var methodBody = new SourceMethodBody(host, null); methodBody.MethodDefinition = newMethod; methodBody.LocalsAreZeroed = true; var block = new BlockStatement(); var returnStatement = new ReturnStatement(); if (methodConfiguration.ReturnType != null) { newMethod.Type = new UnitReflector(host).Get(methodConfiguration.ReturnType); returnStatement.Expression = new CompileTimeConstant(); } if (methodConfiguration.MethodBody != null) { var codeBuilder = new CodeBuilder(host, newMethod.Parameters); methodConfiguration.MethodBody(codeBuilder); foreach (var statement in codeBuilder.Statements) { block.Statements.Add(statement); } } // "Stack must be empty on return from a void method" //returnStatement.Expression = new CompileTimeConstant(); //block.Statements.Add(returnStatement); methodBody.Block = block; newMethod.Body = methodBody; newClass.Methods.Add(newMethod); } foreach (var field in classConfiguration.Fields) { var fieldDefinition = new FieldDefinition(); fieldDefinition.ContainingTypeDefinition = newClass; fieldDefinition.InternFactory = host.InternFactory; fieldDefinition.IsReadOnly = field.IsReadonly; fieldDefinition.IsStatic = field.IsStatic; fieldDefinition.Name = host.NameTable.GetNameFor(field.Name); fieldDefinition.Type = new UnitReflector(host).Get(field.FieldType); fieldDefinition.Visibility = field.Accessibility.ToTypeMemberVisibility(); newClass.Fields.Add(fieldDefinition); } assembly.AllTypes.Add(newClass); } using (var dll = File.Create(assemblyName + ".dll")) { PeWriter.WritePeToStream(assembly, host, dll); dll.Close(); } return assembly; }
private static NamespaceTypeDefinition DefineMethodHashAttributeType(HostEnvironment host, RootUnitNamespace rootUnitNamespace) { Contract.Requires(host != null); var internFactory = host.InternFactory; #region Define the type var methodHashAttributeType = new NamespaceTypeDefinition() { BaseClasses = new List<ITypeReference> { host.PlatformType.SystemAttribute, }, ContainingUnitNamespace = rootUnitNamespace, InternFactory = internFactory, //IsBeforeFieldInit = true, IsClass = true, IsPublic = true, //IsSealed = true, Methods = new List<IMethodDefinition>(1), Name = host.NameTable.GetNameFor("MethodHashAttribute"), //Layout = LayoutKind.Auto, //StringFormat = StringFormatKind.Ansi, }; #endregion #region Define the ctor var systemVoidType = host.PlatformType.SystemVoid; List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = methodHashAttributeType, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = host.NameTable.Ctor, Type = systemVoidType, Visibility = TypeMemberVisibility.Public, }; var systemStringType = host.PlatformType.SystemString; var systemIntType = host.PlatformType.SystemInt32; ctor.Parameters = new List<IParameterDefinition>(){ new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("a"), Type = systemStringType, Index = 0, }, new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("b"), Type = systemIntType, Index = 1, } }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = methodHashAttributeType, }; // base(); foreach (var baseClass in methodHashAttributeType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = internFactory, Name = host.NameTable.Ctor, Type = systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = methodHashAttributeType, }, Type = systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); methodHashAttributeType.Methods.Add(ctor); #endregion Define the ctor return methodHashAttributeType; }
// this method creates a new class for the given namespace public NamespaceTypeDefinition createNewClass(String className, IUnitNamespace containingUnitNamespace, bool isPublic, bool isStatic) { // create a new class object NamespaceTypeDefinition newClass = new NamespaceTypeDefinition(); newClass.ContainingUnitNamespace = containingUnitNamespace; newClass.InternFactory = this.host.InternFactory; newClass.IsClass = true; newClass.IsForeignObject = false; newClass.IsInterface = false; newClass.IsPublic = isPublic; newClass.IsStatic = isStatic; newClass.Methods = new List<IMethodDefinition>(); newClass.Name = this.host.NameTable.GetNameFor(className); // create list of base classes (only base class is System.Object) newClass.BaseClasses = new List<ITypeReference>(); newClass.BaseClasses.Add(this.host.PlatformType.SystemObject); // add new class to module assembly Assembly tempAssembly = (Assembly)this.module; tempAssembly.AllTypes.Add(newClass); return newClass; }
// builds a CFG for the given class (means a CFG for all methods of this class) and returns it public ClassCfg buildCfgForClass(NamespaceTypeDefinition targetClass) { ClassCfg classCfg = new ClassCfg(); classCfg.classObj = targetClass; if (targetClass.Methods != null) { foreach (MethodDefinition method in targetClass.Methods) { // ignore method if it is external if (method.IsExternal) { continue; } logger.writeLine("Create CFG for method \"" + method.ToString() + "\""); classCfg.methodCfgs.Add(buildCfgForMethod(method)); logger.writeLine(""); } } return classCfg; }
private NamespaceTypeDefinition CreateContractReferenceAssemblyAttribute(IRootUnitNamespace rootNs) { var internFactory = this.host.InternFactory; var nameTable = this.host.NameTable; var contractReferenceAssemblyAttributeName = nameTable.GetNameFor("ContractReferenceAssemblyAttribute"); var contractNamespaceName = nameTable.GetNameFor("System.Diagnostics.Contracts"); #region Define type CustomAttribute compilerGeneratedAttribute = new CustomAttribute() { Constructor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0) }; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = rootNs, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { Name = contractReferenceAssemblyAttributeName, Attributes = new List<ICustomAttribute>{ compilerGeneratedAttribute }, BaseClasses = new List<ITypeReference>{ this.systemAttributeType }, ContainingUnitNamespace = contractsNs, //unitNamespace, InternFactory = internFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Methods = new List<IMethodDefinition>(), Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; contractsNs.Members.Add(result); this.allTypes.Add(result); #endregion Define type #region Define the ctor List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; MethodDefinition ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = result, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = nameTable.Ctor, Type = this.systemVoidType, Visibility = TypeMemberVisibility.Public, }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = result, }; // base(); foreach (var baseClass in result.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = result, }, Type = this.systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); result.Methods.Add(ctor); #endregion Define the ctor return result; }
static void Main(string[] args) { var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor("hello"), ModuleName = nameTable.GetNameFor("hello.exe"), Kind = ModuleKind.ConsoleApplication, PlatformType = host.PlatformType, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); var testClass = new NamespaceTypeDefinition() { BaseClasses = new List <ITypeReference>(1) { host.PlatformType.SystemObject }, ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List <IMethodDefinition>(1), Name = nameTable.GetNameFor("Test"), }; rootUnitNamespace.Members.Add(testClass); assembly.AllTypes.Add(testClass); var mainMethod = new MethodDefinition() { ContainingTypeDefinition = testClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; testClass.Methods.Add(mainMethod); var body = new SourceMethodBody(host) { MethodDefinition = mainMethod, LocalsAreZeroed = true }; mainMethod.Body = body; var block = new BlockStatement(); body.Block = block; var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console"); var writeLine = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString); var call = new MethodCall() { IsStaticCall = true, MethodToCall = writeLine, Type = host.PlatformType.SystemVoid }; call.Arguments.Add(new CompileTimeConstant() { Type = host.PlatformType.SystemString, Value = "hello" }); block.Statements.Add(new ExpressionStatement() { Expression = call }); block.Statements.Add(new ReturnStatement()); using (var peStream = File.Create("hello.exe")) { PeWriter.WritePeToStream(assembly, host, peStream); } } }
public void Compile(string fileName) { string appName = Path.GetFileNameWithoutExtension(fileName); string exeName = appName + ".exe"; string src = ""; using (TextReader file = new StreamReader(fileName)) { src = file.ReadToEnd(); } var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { // Load Mirage types IModule module = host.LoadUnitFrom("Mirage.dll") as IModule; if (module == null || module is Dummy) { return; } var machineType = module.GetAllTypes().First(x => x.Name.Value == "Machine"); var inputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleInput"); var outputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleOutput"); // Create assembly var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor(appName), ModuleName = nameTable.GetNameFor(exeName), PlatformType = host.PlatformType, Kind = ModuleKind.ConsoleApplication, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); // Create namespace var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; // Create module class var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); // Create program class var programClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List<IMethodDefinition>(1), Name = nameTable.GetNameFor("Program"), }; programClass.BaseClasses = new List<ITypeReference>() { host.PlatformType.SystemObject }; rootUnitNamespace.Members.Add(programClass); // Add types to the assembly assembly.AllTypes.Add(machineType); foreach (var t in machineType.NestedTypes) { assembly.AllTypes.Add(t); } assembly.AllTypes.Add(inputType); assembly.AllTypes.Add(outputType); assembly.AllTypes.Add(programClass); // Create main method var mainMethod = new MethodDefinition() { ContainingTypeDefinition = programClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; programClass.Methods.Add(mainMethod); // Create constructors and methods IMethodReference machineConstructor = new Microsoft.Cci.MethodReference( host, machineType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); IMethodReference inputConstructor = new Microsoft.Cci.MethodReference( host, inputType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); var inputCast = TypeHelper.GetMethod(inputType, nameTable.GetNameFor("op_Implicit"), inputType); IMethodReference outputConstructor = new Microsoft.Cci.MethodReference( host, outputType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); var outputCast = TypeHelper.GetMethod(outputType, nameTable.GetNameFor("op_Implicit"), outputType); var opIncPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncPointers")); var opDecPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecPointers")); var opIncHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncHiPointer")); var opDecHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecHiPointer")); var opReflectHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("ReflectHiPointer")); var opLoadHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadHiPointer")); var opDragLoPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DragLoPointer")); var opXchPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("XchPointers")); var opClear = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Clear")); var opAdd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Add")); var opDec = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Dec")); var opNot = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Not")); var opAnd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("And")); var opOr = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Or")); var opXor = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Xor")); var opSal = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sal")); var opSar = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sar")); var opLoadData = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadData"), host.PlatformType.SystemString); var opInput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Input"), inputCast.Type); var opOutput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Output"), outputCast.Type); var opJz = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Jz")); // Create program code var labels = new Stack<ILGeneratorLabel>(100); var ilGenerator = new ILGenerator(host, mainMethod); ilGenerator.Emit(OperationCode.Newobj, machineConstructor); ilGenerator.Emit(OperationCode.Stloc_0); ilGenerator.Emit(OperationCode.Newobj, inputConstructor); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.Emit(OperationCode.Newobj, outputConstructor); ilGenerator.Emit(OperationCode.Stloc_2); int pc = 0; while (pc < src.Length) { char opcode = src[pc++]; switch (opcode) { case '>': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opIncPointers); break; case '<': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDecPointers); break; case ']': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opIncHiPointer); break; case '[': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDecHiPointer); break; case '#': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opReflectHiPointer); break; case '$': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opLoadHiPointer); break; case '=': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDragLoPointer); break; case '%': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opXchPointers); break; case '_': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opClear); break; case '+': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opAdd); break; case '-': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDec); break; case '~': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opNot); break; case '&': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opAnd); break; case '|': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opOr); break; case '^': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opXor); break; case '*': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opSal); break; case '/': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opSar); break; case '(': int dataStart = pc; int dataEnd = dataStart; while (src[pc++] != ')') { dataEnd = pc; } ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldstr, src.Substring(dataStart, dataEnd - dataStart)); ilGenerator.Emit(OperationCode.Callvirt, opLoadData); break; case '?': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Call, inputCast); ilGenerator.Emit(OperationCode.Callvirt, opInput); break; case '!': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Call, outputCast); ilGenerator.Emit(OperationCode.Callvirt, opOutput); break; case '{': var cycleStart = new ILGeneratorLabel(); var cycleEnd = new ILGeneratorLabel(); labels.Push(cycleStart); labels.Push(cycleEnd); ilGenerator.Emit(OperationCode.Br, cycleEnd); ilGenerator.MarkLabel(cycleStart); break; case '}': ilGenerator.MarkLabel(labels.Pop()); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opJz); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Ceq); ilGenerator.Emit(OperationCode.Stloc_3); ilGenerator.Emit(OperationCode.Ldloc_3); ilGenerator.Emit(OperationCode.Brtrue, labels.Pop()); break; default: break; } } ilGenerator.Emit(OperationCode.Ret); mainMethod.Body = new ILGeneratorMethodBody( ilGenerator, true, 8, mainMethod, new List<ILocalDefinition>() { new LocalDefinition() { Type = machineType }, new LocalDefinition() { Type = inputType }, new LocalDefinition() { Type = outputType }, new LocalDefinition() { Type = host.PlatformType.SystemInt32 }, }, Enumerable<ITypeDefinition>.Empty ); using (var peStream = File.Create(exeName)) { PeWriter.WritePeToStream(assembly, host, peStream); } } }
private NamespaceTypeDefinition GenerateTypeB(IUnitNamespace rootNamespace, ITypeReference baseType) { var nt = Host.NameTable; var typeB = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("B"), InternFactory = Host.InternFactory, IsClass = true, BaseClasses = { baseType } }; var overrideGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = Host.PlatformType.SystemString, ContainingTypeDefinition = typeB, InternFactory = Host.InternFactory }; typeB.Methods.Add(overrideGetMethod); var il = new ILGenerator(Host); var body = new ILGeneratorMethodBody(il, true, 1) {MethodDefinition = overrideGetMethod}; overrideGetMethod.Body = body; il.Emit(OperationCode.Ldstr, "1"); il.Emit(OperationCode.Ret); return typeB; }
// this method creates a new method for the given class public MethodDefinition createNewMethod(String methodName, NamespaceTypeDefinition methodClass, ITypeReference methodType, TypeMemberVisibility methodVisibility, List<IParameterDefinition> methodParameters, CallingConvention methodCallingConvention, bool isStatic, bool isAbstract, bool isVirtual) { // create a new method MethodDefinition newMethod = new MethodDefinition(); newMethod.ContainingTypeDefinition = methodClass; newMethod.InternFactory = this.host.InternFactory; newMethod.IsCil = true; newMethod.IsStatic = isStatic; newMethod.Name = this.host.NameTable.GetNameFor(methodName); newMethod.Type = methodType; newMethod.Visibility = methodVisibility; newMethod.IsAbstract = isAbstract; newMethod.IsVirtual = isVirtual; newMethod.Parameters = methodParameters; newMethod.CallingConvention = methodCallingConvention; // add method to class if (methodClass.Methods == null) { methodClass.Methods = new List<IMethodDefinition>(); methodClass.Methods.Add(newMethod); } else { methodClass.Methods.Add(newMethod); } return newMethod; }
private Assembly TranslateMetadata(R.IAssemblySymbol assemblySymbol) { Contract.Requires(assemblySymbol != null); Contract.Ensures(Contract.Result<Assembly>() != null); IAssemblyReference cciAssemblyReference = null; Assembly cciAssembly = null; if (assemblySymbolCache.TryGetValue(assemblySymbol, out cciAssemblyReference)) { cciAssembly = cciAssemblyReference as Assembly; System.Diagnostics.Debug.Assert(cciAssembly != null); return cciAssembly; } var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var name = assemblySymbol.Identity.Name; var iname = nameTable.GetNameFor(name); cciAssembly = new Assembly() { Attributes = this.TranslateMetadata(assemblySymbol.GetAttributes()), Name = iname, Locations = Helper.WrapLocations(assemblySymbol.Locations), ModuleName = iname, Kind = ModuleKind.DynamicallyLinkedLibrary, RequiresStartupStub = this.host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, Version = assemblySymbol.Identity.Version, }; cciAssembly.AssemblyReferences.Add(coreAssembly); this.assemblySymbolCache.Add(assemblySymbol, cciAssembly); this.module = cciAssembly; var rootUnitNamespace = new RootUnitNamespace(); cciAssembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = cciAssembly; this.namespaceSymbolCache.Add(assemblySymbol.GlobalNamespace, rootUnitNamespace); var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; cciAssembly.AllTypes.Add(moduleClass); foreach (var m in assemblySymbol.GlobalNamespace.GetMembers()) { var namespaceSymbol = m as NamespaceSymbol; if (namespaceSymbol != null) { var cciNtd = TranslateMetadata(namespaceSymbol); rootUnitNamespace.Members.Add(cciNtd); continue; } var typeSymbol = m as TypeSymbol; if (typeSymbol != null) { var namedType = TranslateMetadata((R.INamedTypeSymbol) typeSymbol); // TODO: fix //namedType.Attributes = TranslateMetadata(typeSymbol.GetAttributes()); var cciType = (INamespaceTypeDefinition) namedType; rootUnitNamespace.Members.Add(cciType); //cciAssembly.AllTypes.Add(cciType); continue; } } //if (this.entryPoint != null) { // cciAssembly.Kind = ModuleKind.ConsoleApplication; // cciAssembly.EntryPoint = this.entryPoint; //} return cciAssembly; }
protected override Assembly Generate() { var nt = Host.NameTable; var mscorlib = Host.LoadAssembly(Host.CoreAssemblySymbolicIdentity); var assembly = new Assembly { Name = nt.GetNameFor(AssemblyName), ModuleName = nt.GetNameFor(DllName), Kind = ModuleKind.DynamicallyLinkedLibrary, TargetRuntimeVersion = mscorlib.TargetRuntimeVersion, MetadataFormatMajorVersion = 2 }; assembly.AssemblyReferences.Add(mscorlib); var rootNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootNamespace; rootNamespace.Unit = assembly; // define module var module = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("<Module>"), InternFactory = Host.InternFactory, IsClass = true }; assembly.AllTypes.Add(module); // define X<T> var xType = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("X"), InternFactory = Host.InternFactory, IsClass = true }; var typeParameter = new GenericTypeParameter { Name = nt.GetNameFor("T"), InternFactory = Host.InternFactory, IsClass = true, DefiningType = xType }; xType.GenericParameters.Add(typeParameter); assembly.AllTypes.Add(xType); var aType = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("A"), InternFactory = Host.InternFactory, IsClass = true }; assembly.AllTypes.Add(aType); var bType = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("B"), InternFactory = Host.InternFactory, IsClass = true }; assembly.AllTypes.Add(bType); aType.BaseClasses.Add(new GenericTypeInstanceReference { GenericType = xType, GenericArguments = { bType }, InternFactory = Host.InternFactory }); bType.BaseClasses.Add(new GenericTypeInstanceReference { GenericType = xType, GenericArguments = { aType }, InternFactory = Host.InternFactory }); return assembly; }
/// <summary> /// Creates the appropriate kind of type definition (nested or not) and /// adds it to the type symbol cache. /// </summary> private NamedTypeDefinition CreateTypeDefinition(R.INamedTypeSymbol typeSymbol) { Contract.Requires(typeSymbol != null); NamedTypeDefinition cciType; if (typeSymbol.ContainingType == null) { cciType = new NamespaceTypeDefinition() { ContainingUnitNamespace = (IUnitNamespace)this.namespaceSymbolCache[typeSymbol.ContainingNamespace], IsPublic = typeSymbol.DeclaredAccessibility == R.CommonAccessibility.Public, }; } else { cciType = new NestedTypeDefinition() { ContainingTypeDefinition = (ITypeDefinition)this.typeSymbolCache[typeSymbol.ContainingType], Visibility = TypeMemberVisibility.Private, }; } if (typeSymbol.TypeKind == R.CommonTypeKind.Interface) { cciType.IsAbstract = true; cciType.IsInterface = true; } else { cciType.BaseClasses = new List<ITypeReference> { this.Map(typeSymbol.BaseType) }; cciType.IsBeforeFieldInit = true; // REVIEW: How to determine from typeSymbol? } cciType.IsClass = typeSymbol.IsReferenceType; cciType.IsValueType = typeSymbol.IsValueType; cciType.IsSealed = typeSymbol.IsSealed; cciType.InternFactory = this.host.InternFactory; cciType.Locations = Helper.WrapLocations(typeSymbol.Locations); cciType.Name = this.host.NameTable.GetNameFor(typeSymbol.Name); this.typeSymbolCache.Add(typeSymbol, cciType); return cciType; }
static void mergeClassWithAncestor(NamespaceTypeDefinition mergeTargetClass, PeReader.DefaultHost host) { // get class from which was inherited ITypeDefinition ancestorClass = null; INamedEntity ancestorClassName = null; if (mergeTargetClass.BaseClasses.Count == 1) { // TODO // entferne wenn Methode umgeschrieben /* // ignore inheritance from System.Object if (mergeTargetClass.BaseClasses[0].ToString() != "System.Object") { ancestorClass = (mergeTargetClass.BaseClasses[0] as NamespaceTypeDefinition); } // return if ancestor class equals System.Object else { return; } */ // check base class is of type NamespaceTypeDefinition if (mergeTargetClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition != null) { ancestorClass = (mergeTargetClass.BaseClasses.ElementAt(0) as ITypeDefinition); ancestorClassName = (mergeTargetClass.BaseClasses.ElementAt(0) as INamedEntity); } // ignore inheritance from System.Object else if (mergeTargetClass.BaseClasses[0].ToString() == "System.Object") { return; } // check for needed values in base class and its resolved value (for example when base class of type NamespaceTypeReference) else if ((mergeTargetClass.BaseClasses.ElementAt(0).ResolvedType as ITypeDefinition != null) && (mergeTargetClass.BaseClasses.ElementAt(0) as INamedEntity != null)) { // TODO // weiss nicht ob es Sinn macht externe Klassen wie z.B. system.ValueType // in die aktuelle Klasse rein zu mergen => denn Trick mit methoden auf Virtual stellen // damit JIT Compiler unsere Methoden aufruft klappt nicht in dem Fall (da wir die Methoden von System.ValueType nicht umschreiben koennen) //ancestorClass = (mergeTargetClass.BaseClasses[0].ResolvedType as ITypeDefinition); //ancestorClassName = (mergeTargetClass.BaseClasses[0].ResolvedType as INamedEntity); return; } else { throw new ArgumentException("Do not know how to handle base class."); } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // copy all attributes from the ancestor class to the current class if (ancestorClass.Fields != null) { globalLog.writeLine("Copying fileds"); foreach (FieldDefinition field in ancestorClass.Fields) { FieldDefinition copy = new FieldDefinition(); globalLog.writeLine("Copying field: " + field.Name.ToString()); copyField(copy, field); copy.ContainingTypeDefinition = mergeTargetClass; // set intern factory of the copied field to the one of the class // (without it, the generated binary file will have strange results like use only the same field) copy.InternFactory = mergeTargetClass.InternFactory; mergeTargetClass.Fields.Add(copy); } globalLog.writeLine(""); } // list of all constructors of the ancestor class List<MethodDefinition> copiedAncestorConstructors = new List<MethodDefinition>(); // copy methods from the ancestor class to the current class if (ancestorClass.Methods != null) { globalLog.writeLine("Copying methods"); foreach (IMethodDefinition method in ancestorClass.Methods) { globalLog.writeLine("Copying method: " + method.Name.ToString()); // check if the method is a constructor if (method.IsConstructor) { MethodDefinition copiedAncestorConstructor = new MethodDefinition(); copyMethod(copiedAncestorConstructor, method, host); // TODO // name muss noch geaendert werden String tempName = "ctor_" + ancestorClassName.Name.ToString(); copiedAncestorConstructor.Name = host.NameTable.GetNameFor(tempName); // constructor has the "SpecialName" (the name describes the functionality) // and "RTSpecialName" (runtime should check name encoding) flag set // runtime will raise an exception if these flags are set for a copied constructor // which is added as a normal function copiedAncestorConstructor.IsSpecialName = false; copiedAncestorConstructor.IsRuntimeSpecial = false; // TODO: // vielleicht einfach von späterer Schleife machen lassen (sollte jetzt schon gehen, aber noch nicht getestet, // deshalb erst ein mal drin gelassen) // copy constructor and rewrite instructions to use attributes and functions // inside the same class var testIlGenerator = new ILGenerator(host, copiedAncestorConstructor); foreach (var operation in copiedAncestorConstructor.Body.Operations) { switch (operation.OperationCode) { case OperationCode.Call: // HIER NOCH CHECKEN OB ANDERE FUNKTIONEN INNERHALB DES ANCESTORS AUFGERUFEN WERDEN // DIESE MUESSEN UMGELEITET WERDEN /* Microsoft.Cci.MutableCodeModel.MethodDefinition blah = null; if (operation.Value is Microsoft.Cci.MutableCodeModel.MethodDefinition) { blah = (Microsoft.Cci.MutableCodeModel.MethodDefinition)(operation.Value); NamespaceTypeDefinition test = (NamespaceTypeDefinition)blah.ContainingTypeDefinition; if (ancestorClass.Name.Equals(test.Name)) { System.Console.WriteLine("Ja"); } } */ testIlGenerator.Emit(operation.OperationCode, operation.Value); break; case OperationCode.Stfld: FieldDefinition attribute = (FieldDefinition)operation.Value; // search for the method attribute that is used in the copied constructor // and replace it with the method attribute from the current class FieldDefinition foundField = null; foreach (FieldDefinition field in mergeTargetClass.Fields) { if (attribute.Name.Equals(field.Name) && attribute.Type.Equals(field.Type)) { foundField = field; break; } } if (foundField == null) { System.Console.WriteLine("Attribute not found"); return; } testIlGenerator.Emit(operation.OperationCode, foundField); break; default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables); List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, copiedAncestorConstructor, variableListCopy, privateHelperTypesListCopy); copiedAncestorConstructor.Body = newBody; // set intern factory of the copied constructor to the one of the class // (without it, the generated binary file will have strange results like call always the same method) copiedAncestorConstructor.InternFactory = mergeTargetClass.InternFactory; // add copied constructor to the class copiedAncestorConstructor.ContainingTypeDefinition = mergeTargetClass; copiedAncestorConstructor.Visibility = TypeMemberVisibility.Private; mergeTargetClass.Methods.Add(copiedAncestorConstructor); // add copied ancestor constructor to the list of copied ancestor constructors copiedAncestorConstructors.Add(copiedAncestorConstructor); continue; } else { // copy method MethodDefinition copy = new MethodDefinition(); copyMethod(copy, method, host); copy.ContainingTypeDefinition = mergeTargetClass; // set intern factory of the copied method to the one of the class // (without it, the generating of the binary file will have strange results) copy.InternFactory = mergeTargetClass.InternFactory; // add method to the class if (mergeTargetClass.Methods == null) { mergeTargetClass.Methods = new List<IMethodDefinition>(); } mergeTargetClass.Methods.Add(copy); } } globalLog.writeLine(""); } // rewrite constructors of the class to call the copied constructor instead of // the constructor of the ancestor class // (rewriting methods is handled later) foreach (MethodDefinition method in mergeTargetClass.Methods) { // check if method is a constructor if (method.IsConstructor) { var testIlGenerator = new ILGenerator(host, method); foreach (var operation in method.Body.Operations) { switch (operation.OperationCode) { // only call instructions that call a constructor have to be redirected case OperationCode.Call: MethodDefinition calledMethod = (MethodDefinition)operation.Value; if (calledMethod.IsConstructor) { // TODO hier treten noch Probleme auf, wenn System.Object ist nicht der oberste Ancestor // sondern z.B. System.ValueType // check if the called constructor is not the constructor of System.Object // and if the constructor that is called is not a constructor of THIS class NamespaceTypeDefinition calledMethodNamespace = (NamespaceTypeDefinition)calledMethod.ContainingTypeDefinition; if (calledMethodNamespace.ToString() != "System.Object" && !calledMethodNamespace.Name.Equals(mergeTargetClass.Name)) { // search for the copied constructor that has to be called // (it is searched by parameter types because they always are named the same ".ctor") MethodDefinition copiedConstructorToCall = null; foreach (MethodDefinition copiedAncestorConstructor in copiedAncestorConstructors) { // check if the count of the parameters of the called constructor and the copied constructor are the same if (copiedAncestorConstructor.ParameterCount == calledMethod.ParameterCount) { // check if the parameters have the same type in the same order bool found = true; for (int i = 0; i < calledMethod.ParameterCount; i++) { if (calledMethod.Parameters[i].Type != copiedAncestorConstructor.Parameters[i].Type) { found = false; break; } } if (found) { copiedConstructorToCall = copiedAncestorConstructor; break; } } } if (copiedConstructorToCall == null) { throw new ArgumentException("No copied constructor with the same parameter types in the same order."); } // call copied constructor instead of constructor of the ancestor testIlGenerator.Emit(operation.OperationCode, copiedConstructorToCall); } // just emit if the called constructor is the constructor of System.Object else { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } // just emit operation if no constructor is called // (rewriting methods is handled later) else { testIlGenerator.Emit(operation.OperationCode, operation.Value); } break; // just emit operation if none of the above cases match default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables); List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, method, variableListCopy, privateHelperTypesListCopy); method.Body = newBody; } } // rewrite all methods to use local attributes/methods instead of the ones of the ancestor foreach (MethodDefinition method in mergeTargetClass.Methods) { var testIlGenerator = new ILGenerator(host, method); foreach (var operation in method.Body.Operations) { switch (operation.OperationCode) { case OperationCode.Stfld: case OperationCode.Ldfld: // get namespace of attribute FieldDefinition attribute = (FieldDefinition)operation.Value; INamedTypeDefinition attributeNamespace = (INamedTypeDefinition)attribute.ContainingTypeDefinition; // check if namespace of attribute equals the namespace of THIS class // => just emit operation if (mergeTargetClass.Name.Equals(attributeNamespace.Name)) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // try the namespace of all ancestors of this class to see if it was copied else { // flag that indicates if the operation was emitted during the search loop bool operationEmitted = false; // search through all ancestors to find the namespace of the used attribute NamespaceTypeDefinition tempAncestorClass = mergeTargetClass; while (true) { // get class from which was inherited if (tempAncestorClass.BaseClasses.Count == 1) { // ignore inheritance from System.Object if (tempAncestorClass.BaseClasses[0].ToString() != "System.Object") { tempAncestorClass = (tempAncestorClass.BaseClasses[0] as NamespaceTypeDefinition); } // return if ancestor class equals System.Object else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // check namespace of used attribute is equal to namespace of ancestor // => change target of operation to THIS class if (tempAncestorClass.Name.Equals(attributeNamespace.Name)) { // search for the method attribute that is used in the copied method // and replace it with the method attribute from the current class FieldDefinition foundField = null; foreach (FieldDefinition field in mergeTargetClass.Fields) { if (attribute.Name.Equals(field.Name) && attribute.Type.Equals(field.Type)) { foundField = field; break; } } if (foundField == null) { throw new ArgumentException("Attribute not found."); } // emit operation and set flag that it was emitted operationEmitted = true; testIlGenerator.Emit(operation.OperationCode, foundField); break; } } // if operation was not emitted yet => emit it if (operationEmitted == false) { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } break; case OperationCode.Call: // just emit if value is of type method reference if (operation.Value is Microsoft.Cci.MutableCodeModel.MethodReference) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // get namespace of called method MethodDefinition calledMethod = (MethodDefinition)operation.Value; NamespaceTypeDefinition calledMethodNamespace = (NamespaceTypeDefinition)calledMethod.ContainingTypeDefinition; // check if namespace of called method equals the namespace of THIS class // => just emit operation if (mergeTargetClass.Name.Equals(calledMethodNamespace.Name)) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // try the namespace of all ancestors of this class to see if it was copied else { // flag that indicates if the operation was emitted during the search loop bool operationEmitted = false; // search through all ancestors to find the namespace of the called method NamespaceTypeDefinition tempAncestorClass = mergeTargetClass; while (true) { // get class from which was inherited if (tempAncestorClass.BaseClasses.Count == 1) { // ignore inheritance from System.Object if (tempAncestorClass.BaseClasses[0].ToString() != "System.Object") { tempAncestorClass = (tempAncestorClass.BaseClasses[0] as NamespaceTypeDefinition); } // return if ancestor class equals System.Object else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // check namespace of called method is equal to namespace of ancestor, if the same // => find copied method in THIS class // => change target of operation to method in THIS class if (tempAncestorClass.Name.Equals(calledMethodNamespace.Name)) { // search through all methods in THISS class and search for the copied one MethodDefinition foundMethod = null; foreach (MethodDefinition newMethod in mergeTargetClass.Methods) { // skip constructors (can not be called from the ancestor) if (newMethod.IsConstructor) { continue; } if (newMethod.ParameterCount == calledMethod.ParameterCount) { // check if the parameters have the same type in the same order bool parameterCorrect = true; for (int i = 0; i < calledMethod.ParameterCount; i++) { if (calledMethod.Parameters[i].Type != newMethod.Parameters[i].Type) { parameterCorrect = false; break; } } // if the parameters are correct => check the name if (parameterCorrect) { if (calledMethod.Name.Equals(newMethod.Name)) { // if name is the same => found method to call foundMethod = newMethod; break; } } } } // check if the method we want to call was found if (foundMethod == null) { throw new ArgumentException("Did not find a method to call."); } // emit operation and set flag that it was emitted operationEmitted = true; testIlGenerator.Emit(operation.OperationCode, foundMethod); break; } } // if operation was not emitted yet => emit it if (operationEmitted == false) { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } break; // just emit operation if none of the above cases match default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables); List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, method, variableListCopy, privateHelperTypesListCopy); method.Body = newBody; } }
static void Main(string[] args) { var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor("hello"), ModuleName = nameTable.GetNameFor("hello.exe"), PlatformType = host.PlatformType, Kind = ModuleKind.ConsoleApplication, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); var testClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List <IMethodDefinition>(1), Name = nameTable.GetNameFor("Test"), }; rootUnitNamespace.Members.Add(testClass); assembly.AllTypes.Add(testClass); testClass.BaseClasses = new List <ITypeReference>() { host.PlatformType.SystemObject }; var mainMethod = new MethodDefinition() { ContainingTypeDefinition = testClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; testClass.Methods.Add(mainMethod); var ilGenerator = new ILGenerator(host, mainMethod); var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console"); var writeLine = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString); ilGenerator.Emit(OperationCode.Ldstr, "hello"); ilGenerator.Emit(OperationCode.Call, writeLine); ilGenerator.Emit(OperationCode.Ret); var body = new ILGeneratorMethodBody(ilGenerator, true, 1, mainMethod, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); mainMethod.Body = body; using (var peStream = File.Create("hello.exe")) { PeWriter.WritePeToStream(assembly, host, peStream); } } }
public void Compile(string fileName) { string appName = Path.GetFileNameWithoutExtension(fileName); string exeName = appName + ".exe"; string src = ""; using (TextReader file = new StreamReader(fileName)) { src = file.ReadToEnd(); } var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { // Load Mirage types IModule module = host.LoadUnitFrom("Mirage.dll") as IModule; if (module == null || module is Dummy) { return; } var machineType = module.GetAllTypes().First(x => x.Name.Value == "Machine"); var inputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleInput"); var outputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleOutput"); // Create assembly var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor(appName), ModuleName = nameTable.GetNameFor(exeName), PlatformType = host.PlatformType, Kind = ModuleKind.ConsoleApplication, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); // Create namespace var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; // Create module class var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); // Create program class var programClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List <IMethodDefinition>(1), Name = nameTable.GetNameFor("Program"), }; programClass.BaseClasses = new List <ITypeReference>() { host.PlatformType.SystemObject }; rootUnitNamespace.Members.Add(programClass); // Add types to the assembly assembly.AllTypes.Add(machineType); foreach (var t in machineType.NestedTypes) { assembly.AllTypes.Add(t); } assembly.AllTypes.Add(inputType); assembly.AllTypes.Add(outputType); assembly.AllTypes.Add(programClass); // Create main method var mainMethod = new MethodDefinition() { ContainingTypeDefinition = programClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; programClass.Methods.Add(mainMethod); // Create constructors and methods IMethodReference machineConstructor = new Microsoft.Cci.MethodReference( host, machineType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); IMethodReference inputConstructor = new Microsoft.Cci.MethodReference( host, inputType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); var inputCast = TypeHelper.GetMethod(inputType, nameTable.GetNameFor("op_Implicit"), inputType); IMethodReference outputConstructor = new Microsoft.Cci.MethodReference( host, outputType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0 ); var outputCast = TypeHelper.GetMethod(outputType, nameTable.GetNameFor("op_Implicit"), outputType); var opIncPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncPointers")); var opDecPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecPointers")); var opIncHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncHiPointer")); var opDecHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecHiPointer")); var opReflectHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("ReflectHiPointer")); var opLoadHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadHiPointer")); var opDragLoPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DragLoPointer")); var opXchPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("XchPointers")); var opClear = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Clear")); var opAdd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Add")); var opDec = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Dec")); var opNot = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Not")); var opAnd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("And")); var opOr = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Or")); var opXor = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Xor")); var opSal = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sal")); var opSar = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sar")); var opLoadData = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadData"), host.PlatformType.SystemString); var opInput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Input"), inputCast.Type); var opOutput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Output"), outputCast.Type); var opJz = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Jz")); // Create program code var labels = new Stack <ILGeneratorLabel>(100); var ilGenerator = new ILGenerator(host, mainMethod); ilGenerator.Emit(OperationCode.Newobj, machineConstructor); ilGenerator.Emit(OperationCode.Stloc_0); ilGenerator.Emit(OperationCode.Newobj, inputConstructor); ilGenerator.Emit(OperationCode.Stloc_1); ilGenerator.Emit(OperationCode.Newobj, outputConstructor); ilGenerator.Emit(OperationCode.Stloc_2); int pc = 0; while (pc < src.Length) { char opcode = src[pc++]; switch (opcode) { case '>': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opIncPointers); break; case '<': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDecPointers); break; case ']': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opIncHiPointer); break; case '[': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDecHiPointer); break; case '#': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opReflectHiPointer); break; case '$': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opLoadHiPointer); break; case '=': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDragLoPointer); break; case '%': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opXchPointers); break; case '_': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opClear); break; case '+': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opAdd); break; case '-': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opDec); break; case '~': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opNot); break; case '&': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opAnd); break; case '|': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opOr); break; case '^': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opXor); break; case '*': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opSal); break; case '/': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opSar); break; case '(': int dataStart = pc; int dataEnd = dataStart; while (src[pc++] != ')') { dataEnd = pc; } ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldstr, src.Substring(dataStart, dataEnd - dataStart)); ilGenerator.Emit(OperationCode.Callvirt, opLoadData); break; case '?': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldloc_1); ilGenerator.Emit(OperationCode.Call, inputCast); ilGenerator.Emit(OperationCode.Callvirt, opInput); break; case '!': ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Ldloc_2); ilGenerator.Emit(OperationCode.Call, outputCast); ilGenerator.Emit(OperationCode.Callvirt, opOutput); break; case '{': var cycleStart = new ILGeneratorLabel(); var cycleEnd = new ILGeneratorLabel(); labels.Push(cycleStart); labels.Push(cycleEnd); ilGenerator.Emit(OperationCode.Br, cycleEnd); ilGenerator.MarkLabel(cycleStart); break; case '}': ilGenerator.MarkLabel(labels.Pop()); ilGenerator.Emit(OperationCode.Ldloc_0); ilGenerator.Emit(OperationCode.Callvirt, opJz); ilGenerator.Emit(OperationCode.Ldc_I4_0); ilGenerator.Emit(OperationCode.Ceq); ilGenerator.Emit(OperationCode.Stloc_3); ilGenerator.Emit(OperationCode.Ldloc_3); ilGenerator.Emit(OperationCode.Brtrue, labels.Pop()); break; default: break; } } ilGenerator.Emit(OperationCode.Ret); mainMethod.Body = new ILGeneratorMethodBody( ilGenerator, true, 8, mainMethod, new List <ILocalDefinition>() { new LocalDefinition() { Type = machineType }, new LocalDefinition() { Type = inputType }, new LocalDefinition() { Type = outputType }, new LocalDefinition() { Type = host.PlatformType.SystemInt32 }, }, Enumerable <ITypeDefinition> .Empty ); using (var peStream = File.Create(exeName)) { PeWriter.WritePeToStream(assembly, host, peStream); } } }