/* * PERWAPI - An API for Reading and Writing PE Files * * Copyright (c) Diane Corney, Queensland University of Technology, 2004. * * This program is free software; you can redistribute it and/or modify * it under the terms of the PERWAPI Copyright as included with this * distribution in the file PERWAPIcopyright.rtf. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY as is explained in the copyright notice. * * The author may be contacted at d.corney@qut.edu.au * * Version Date: 26/01/07 */ using System; using System.IO; using System.Collections; namespace QUT.PERWAPI { /**************************************************************************/ public class MethSig { internal string name; internal CallConv callConv = CallConv.Default; internal Type retType; internal Type[] parTypes, optParTypes; internal uint numPars = 0, numOptPars = 0, numGenPars = 0; //uint sigIx; /*-------------------- Constructors ---------------------------------*/ internal MethSig(string nam) { name = nam; } internal MethSig InstantiateGenTypes(Class classType, Type[] genTypes) { MethSig newSig = new MethSig(name); newSig.callConv = callConv; newSig.numPars = numPars; newSig.numOptPars = numOptPars; newSig.numGenPars = numGenPars; newSig.parTypes = ReplaceGenPars(parTypes, classType, genTypes); newSig.optParTypes = ReplaceGenPars(optParTypes, classType, genTypes); newSig.retType = SubstituteType(retType, classType, genTypes); return newSig; } private Type[] ReplaceGenPars(Type[] typeList, MetaDataElement paren, Type[] genTypes) { if (typeList == null) return null; Type[] newList = new Type[typeList.Length]; for (int i = 0; i < typeList.Length; i++) { newList[i] = SubstituteType(typeList[i], paren, genTypes); } return newList; } private Type SubstituteType(Type origType, MetaDataElement paren, Type[] genTypes) { if ((origType is GenericParam) && (((GenericParam)origType).GetParent() == paren)) return genTypes[((GenericParam)origType).Index]; return origType; } internal void SetParTypes(Param[] parList) { if (parList == null) { numPars = 0; return; } numPars = (uint)parList.Length; parTypes = new Type[numPars]; for (int i = 0; i < numPars; i++) { parTypes[i] = parList[i].GetParType(); } } internal void ChangeParTypes(ClassDef newType, ClassDef[] oldTypes) { System.Diagnostics.Debug.Assert(newType != null); for (int i = 0; i < oldTypes.Length; i++) { if (retType == oldTypes[i]) retType = newType; for (int j = 0; j < numPars; j++) { if (parTypes[j] == oldTypes[i]) parTypes[j] = newType; } for (int j = 0; j < numOptPars; j++) { if (optParTypes[j] == oldTypes[i]) optParTypes[j] = newType; } } } internal Type MakeRefRetType() { if (retType is ClassDef) { return ((ClassDef)retType).MakeRefOf(); } else { return retType; } } internal Type[] MakeRefParTypes() { Type[] pTypes = new Type[numPars]; for (int i = 0; i < numPars; i++) { if (parTypes[i] is ClassDef) { pTypes[i] = ((ClassDef)parTypes[i]).MakeRefOf(); } else { pTypes[i] = parTypes[i]; } } return pTypes; } /* * internal bool HasNameAndSig(string name, Type[] sigTypes) { if (this.name.CompareTo(name) != 0) return false; return HasSig(sigTypes); } internal bool HasNameAndSig(string name, Type[] sigTypes, Type[] optTypes) { if (this.name.CompareTo(name) != 0) return false; return HasSig(sigTypes,optTypes); } */ internal bool HasSig(Type[] sigTypes) { if (sigTypes == null) return (numPars == 0); if (sigTypes.Length != numPars) return false; for (int i = 0; i < numPars; i++) { if (!sigTypes[i].SameType(parTypes[i])) return false; } return (optParTypes == null) || (optParTypes.Length == 0); } internal bool HasSig(Type[] sigTypes, Type[] optTypes) { if (sigTypes == null) { if (numPars > 0) return false; if (optTypes == null) return (numOptPars == 0); } if (sigTypes.Length != numPars) return false; for (int i = 0; i < numPars; i++) { if (!sigTypes[i].SameType(parTypes[i])) return false; } if (optTypes == null) return numOptPars == 0; if (optTypes.Length != numOptPars) return false; for (int i = 0; i < optTypes.Length; i++) { if (!optTypes[i].SameType(optParTypes[i])) return false; } return true; } /* internal void CheckParTypes(Param[] parList) { //numGenPars = 0; for (int i=0; i < numPars; i++) { if (parTypes[i] is GenericParam) numGenPars++; } if (numGenPars > 0) callConv |= CallConv.Generic; else if ((callConv & CallConv.Generic) > 0) callConv ^= CallConv.Generic; } */ internal void TypeSig(MemoryStream sig) { sig.WriteByte((byte)callConv); if (numGenPars > 0) MetaDataOut.CompressNum(BlobUtil.CompressUInt(numGenPars), sig); MetaDataOut.CompressNum(BlobUtil.CompressUInt(numPars + numOptPars), sig); retType.TypeSig(sig); for (int i = 0; i < numPars; i++) { parTypes[i].TypeSig(sig); } if (numOptPars > 0) { sig.WriteByte((byte)ElementType.Sentinel); for (int i = 0; i < numOptPars; i++) { optParTypes[i].TypeSig(sig); } } } /// /// Check to see if the method signature has a particular calling convention. /// /// The convention to check to see if the method has. /// Ture if the calling convention exists on the method. internal bool HasCallConv(CallConv callCon) { return ((callConv & callCon) == callCon); } internal void WriteCallConv(CILWriter output) { if ((callConv & CallConv.Instance) != 0) { output.Write("instance "); if ((callConv & CallConv.InstanceExplicit) == CallConv.InstanceExplicit) { output.Write("explicit "); } } uint callKind = (uint)callConv & 0x07; switch (callKind) { case 0: break; case 1: output.Write("unmanaged cdecl "); break; case 2: output.Write("unmanaged stdcall "); break; case 3: output.Write("unmanaged thiscall "); break; case 4: output.Write("unmanaged fastcall "); break; case 5: output.Write("vararg "); break; } } internal void Write(CILWriter output) { WriteCallConv(output); retType.WriteType(output); } internal void WriteParTypes(CILWriter output) { output.Write("("); for (int i = 0; i < numPars; i++) { parTypes[i].WriteType(output); if ((i < numPars - 1) || (numOptPars > 0)) output.Write(", "); } for (int i = 0; i < numOptPars; i++) { optParTypes[i].WriteType(output); if (i < numPars - 1) output.Write(", "); } output.Write(")"); } internal string NameString() { string parString = "("; if (numPars > 0) { parString += parTypes[0].NameString(); for (int i = 1; i < numPars; i++) { parString += "," + parTypes[i].NameString(); } } if (numOptPars > 0) { if (numPars > 0) parString += ","; parString += optParTypes[0].NameString(); for (int i = 1; i < numOptPars; i++) { parString += "," + optParTypes[i].NameString(); } } return name + parString + ")"; } internal void BuildTables(MetaDataOut md) { if (!retType.isDef()) retType.BuildMDTables(md); for (int i = 0; i < numPars; i++) { if (!parTypes[i].isDef()) parTypes[i].BuildMDTables(md); } for (int i = 0; i < numOptPars; i++) { if (!optParTypes[i].isDef()) optParTypes[i].BuildMDTables(md); } } internal void BuildCILInfo(CILWriter output) { if (!retType.isDef()) retType.BuildCILInfo(output); for (int i = 0; i < numPars; i++) { if (!parTypes[i].isDef()) parTypes[i].BuildCILInfo(output); } for (int i = 0; i < numOptPars; i++) { if (!optParTypes[i].isDef()) optParTypes[i].BuildCILInfo(output); } } internal void BuildSignatures(MetaDataOut md) { if (!retType.isDef()) retType.BuildSignatures(md); for (int i = 0; i < numPars; i++) { if (!parTypes[i].isDef()) parTypes[i].BuildSignatures(md); } for (int i = 0; i < numOptPars; i++) { if (!optParTypes[i].isDef()) optParTypes[i].BuildSignatures(md); } } } }