protected new PERWAPI.MethodDef GenerateClassForMethod(CodeGenContext context) { // public class Eval: IEval { evalClass = context.CreateGlobalClass("_Internal", "Eval", Runtime.SystemObjectRef); evalClass.AddImplementedInterface(Runtime.IEvalRef); if (context.CurrentRubyClass == null) { context.CurrentRubyClass = CodeGenContext.AddField(evalClass, PERWAPI.FieldAttr.PublicStatic, "myRubyClass", Runtime.ClassRef); CodeGenContext cctor = context.CreateStaticConstructor(evalClass); cctor.ldsfld(Runtime.Init.rb_cObject); cctor.stsfld(context.CurrentRubyClass); cctor.ret(); cctor.Close(); } MethodDef constructor = GenConstructor(evalClass, context); GenInvokeMethod(evalClass, context); return constructor; // } }
////////////////////////////////////////////////////////////////////////// // Methods ////////////////////////////////////////////////////////////////////////// /// <summary> /// Define a new class to emit for this assembly. This class /// becomes the 'current' class, where subsequent EmitMethod /// and EmitField calls will popuate this class. /// </summary> public void emitClass(string baseQName, string qname, string[] interfaces, TypeAttr attr) { string[] s = FanUtil.splitQName(qname); className = qname; // first check if this type was already stubbed out classDef = (ClassDef)types[qname]; if (classDef == null) { // if not, we need to create it if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassDef cdef = (PERWAPI.ClassDef)findType(s[0]); classDef = cdef.AddNestedClass(attr, s[1]); } else { // Normal class classDef = peFile.AddClass(attr, s[0], s[1]); } } else { // if stubbed out, make sure we define the type correctly classDef.SetAttribute(attr); } // base class if (baseQName == null) { classDef.SuperType = null; } else { classDef.SuperType = findType(baseQName) as PERWAPI.Class; } // interfaces for (int i = 0; i < interfaces.Length; i++) { classDef.AddImplementedInterface(findType(interfaces[i]) as PERWAPI.Class); } types[qname] = classDef; }
private void CreateLastClassMethod(ClassDef Class, CodeGenContext context) { CodeGenContext lastClass = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "lastClass", Runtime.ClassRef); lastClass.startMethod(this.location); int frame = lastClass.CreateLocal("frame", Runtime.FrameRef); lastClass.ldarg(0); lastClass.stloc(frame); lastClass.LastClass(this, true); lastClass.ret(); lastClass.ReleaseLocal(frame, true); lastClass.Close(); }
private void GenCallMethod(ClassDef Class, CodeGenContext context) { // internal static object Calln(Class last_class, object recv, Frame caller, ArgList args) CodeGenContext Calln = context.CreateMethod(Class, MethAttr.PublicVirtual, "Calln", PrimitiveType.Object, new Param(ParamAttr.Default, "last_class", Runtime.ClassRef), new Param(ParamAttr.Default, "ruby_class", Runtime.ClassRef), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef), new Param(ParamAttr.Default, "args", Runtime.ArgListRef)); Calln.startMethod(this.location); AddScopeLocals(Calln); if (args != null) { new ASSIGNMENT(args, new BLOCKARGS(args.location), args.location).GenCode(Calln); // Fixme: should be inside try block for ReturnException Calln.pop(); } AddScopeBody(Calln); Calln.ReleaseLocal(0, true); Calln.Close(); }
private void GenCallMethod(ClassDef Class, CodeGenContext context) { List<Param> args = new List<Param>(); args.Add(new Param(ParamAttr.Default, "last_class", Runtime.ClassRef)); args.Add(new Param(ParamAttr.Default, "recv", PrimitiveType.Object)); args.Add(new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); CodeGenContext Call; if (formals.ShortAndSimple()) { args.Add(new Param(ParamAttr.Default, "block", Runtime.ProcRef)); for (StaticLocalVar formal = formals.normal; formal != null; formal = (StaticLocalVar)formal.nd_next) args.Add(new Param(ParamAttr.Default, formal.vid, PrimitiveType.Object)); Call = context.CreateMethod(Class, MethAttr.PublicVirtual, "Call" + formals.min_args, PrimitiveType.Object, args.ToArray()); } else { args.Add(new Param(ParamAttr.Default, "args", Runtime.ArgListRef)); // internal static object Calln(Class last_class, object recv, Frame caller, Proc block, ArrayList args) Call = context.CreateMethod(Class, MethAttr.PublicVirtual, "Calln", PrimitiveType.Object, args.ToArray()); } Call.orig_func = Call.Method; // BBTAG Call.orig_func_formals = formals; // BBTAG Call.currentSkeleton = context.currentSkeleton; // BBTAG Call.postPassList = context.postPassList; // BBTAG Call.peFiles = context.peFiles; // BBTAG Call.startMethod(this.location); AddScopeLocals(Call); if (formals.ShortAndSimple()) formals.CopySimple(Call, this); else formals.CopyToLocals(Call, this); AddScopeBody(Call); Call.newEndPoint(location); Call.ReleaseLocal(0, true); Call.Close(); }
internal InterfaceImpl(ClassDef theClass, TableRow theInterface) { this.theClass = theClass; this.theInterface = (Class)theInterface; tabIx = MDTable.InterfaceImpl; }
internal void ChangeRefsToDefs(ClassDef newPar, ClassDef[] oldTypes) { parent = newPar; bool changeType = false; for (int i=0; i < oldTypes.Length && !changeType; i++) { if (type == oldTypes[i]) type = newPar; } }
/*-------------------- Constructors ---------------------------------*/ internal FieldDef(string name, Type fType, ClassDef paren) : base(name,fType,paren) { tabIx = MDTable.Field; }
/*-------------------- Constructors ---------------------------------*/ internal Feature(string name, ClassDef par) { parent = par; this.name = name; }
internal void ReadMethodImpls(ClassDef theClass, uint classIx) { SetElementPosition(MDTable.InterfaceImpl,0); for (int i=0; (i < tableLengths[(int)MDTable.MethodImpl]); i++) { uint clIx = GetIndex(MDTable.TypeDef); uint bodIx = GetCodedIndex(CIx.MethodDefOrRef); uint declIx = GetCodedIndex(CIx.MethodDefOrRef); if (clIx == classIx) { MethodImpl mImpl = new MethodImpl(this,theClass,bodIx,declIx); theClass.AddMethodImpl(mImpl); tables[(int)MDTable.MethodImpl][i] = mImpl; } } }
internal override void Resolve(PEReader buff) { parent = (ClassDef)buff.GetElement(MDTable.TypeDef,parentIx); if (parent != null) parent.Layout = this; }
internal static ClassLayout FindLayout(PEReader buff, ClassDef paren, uint classIx) { buff.SetElementPosition(MDTable.ClassLayout,0); for (int i=0; i < buff.GetTableSize(MDTable.ClassLayout); i++) { ushort packSize = buff.ReadUInt16(); uint classSize = buff.ReadUInt32(); if (buff.GetIndex(MDTable.TypeDef) == classIx) return new ClassLayout(packSize,classSize,paren); } return null; }
internal ClassLayout(ushort pack, uint cSize, ClassDef par) { packSize = pack; classSize = cSize; parent = par; tabIx = MDTable.ClassLayout; }
/*-------------------- Constructors ---------------------------------*/ internal ClassLayout(int pack, int cSize, ClassDef par) { packSize = (ushort)pack; classSize = (uint)cSize; parent = par; tabIx = MDTable.ClassLayout; }
internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) { 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; } } }
////////////////////////////////////////////////////////////////////////// // Util ////////////////////////////////////////////////////////////////////////// /// <summary> /// Find the Type instance for this fully qualified type name. /// </summary> internal PERWAPI.Type findType(string qname) { // Always convert voids to native if (qname == "Fan.Sys.Void") { qname = "System.Void"; } PERWAPI.Type type = (PERWAPI.Type)types[qname]; if (type == null) { string aname = FanUtil.getPodName(qname); if (aname == null) { aname = "mscorlib"; } if (qname.StartsWith("Fanx.")) { aname = "sys"; // hack for support classes } if (qname.EndsWith("Peer")) { aname += "Native_"; // TODO } // first check if this is a type in this pod that // hasn't been defined yet if (aname == assemblyName) { // stub out type - fill get filled in later (we hope) string[] sn = FanUtil.splitQName(qname); ClassDef stub = null; if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassDef cdef = (PERWAPI.ClassDef)findType(sn[0]); stub = cdef.AddNestedClass(PERWAPI.TypeAttr.NestedPublic, sn[1]); } else { // Normal class stub = peFile.AddClass(PERWAPI.TypeAttr.Public, sn[0], sn[1]); } types[qname] = stub; return(stub); } AssemblyRef aref = (AssemblyRef)assemblies[aname]; if (aref == null) { aref = peFile.MakeExternAssembly(aname); assemblies[aname] = aref; } string[] s = FanUtil.splitQName(qname); if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassRef cref = (PERWAPI.ClassRef)findType(s[0]); type = cref.AddNestedClass(s[1]); } /* * else if (qname.IndexOf("<") != -1) * { * // Generic type * //if (type == null) type = aref.AddClass(s[0], s[1]); * PERWAPI.ClassRef cref = (PERWAPI.ClassRef)findType(s[0]); * cref.SetGenericParams(new GenericParam[] { cref.GetGenericParam(0) }); * type = cref; * } */ else { // Normal class, get/add type type = aref.GetClass(s[0], s[1]); if (type == null) { type = aref.AddClass(s[0], s[1]); } } types[qname] = type; } return(type); }
/*----------------------------- internal functions ------------------------------*/ internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) { throw new NotYetImplementedException("Merge for Events"); }
internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) { for (int i=0; i < tide; i++) { if (buffer[i] is SigInstr) { CalliSig sig = ((SigInstr)buffer[i]).GetSig(); sig.ChangeRefsToDefs(newType,oldTypes); } else if (buffer[i] is TypeInstr) { TypeInstr tinst = (TypeInstr)buffer[i]; if (tinst.GetTypeArg() is ClassDef) { ClassDef iType = (ClassDef)tinst.GetTypeArg(); bool changed = false; for (int j=0; (j < oldTypes.Length) && !changed; j++) { if (iType == oldTypes[j]) tinst.SetTypeArg(newType); } } } } }
internal static string[] GetFeatureNames(PEReader buff, MDTable tabIx, MDTable mapTabIx, ClassDef theClass, uint classIx) { buff.SetElementPosition(mapTabIx,0); uint start = 0, end = 0, i = 0; for (; (i < buff.GetTableSize(tabIx)) && (start == 0); i++) { if (buff.GetIndex(MDTable.TypeDef) == classIx) { start = buff.GetIndex(tabIx); } } if (start == 0) return null; if (i < buff.GetTableSize(mapTabIx)) { uint junk = buff.GetIndex(MDTable.TypeDef); end = buff.GetIndex(tabIx); } else end = buff.GetTableSize(tabIx); if (tabIx == MDTable.Event) theClass.eventIx = start; else theClass.propIx = start; string[] names = new string[end-start]; buff.SetElementPosition(tabIx,start); for (i=start; i < end; i++) { uint junk = buff.ReadUInt16(); names[i] = buff.GetString(); if (tabIx == MDTable.Event) junk = buff.GetCodedIndex(CIx.TypeDefOrRef); else junk = buff.GetBlobIx(); } return names; }
public void MergeClasses(ClassDef[] classes) { ChangeRefsToDefs(this,classes); for (int i=0; i < classes.Length; i++) { fields.AddRange(classes[i].fields); methods.AddRange(classes[i].methods); events.AddRange(classes[i].events); properties.AddRange(classes[i].properties); interfaces.AddRange(classes[i].interfaces); methodImpls.AddRange(classes[i].methodImpls); nestedClasses.AddRange(classes[i].nestedClasses); } }
internal FieldDef(FieldAttr attrSet, string name, Type fType,ClassDef paren) : base(name, fType,paren) { flags = (ushort)attrSet; tabIx = MDTable.Field; }
internal static void Read(PEReader buff, TableRow[] typeDefs, bool isMSCorLib) { ClassDef prevDef = null; prevDef = new ClassDef(buff,1,isMSCorLib); typeDefs[0] = prevDef; for (int i=1; i < typeDefs.Length; i++) { ClassDef typeDef = new ClassDef(buff,(uint)i+1,isMSCorLib); prevDef.fieldEndIx = typeDef.fieldIx; prevDef.methodEndIx = typeDef.methodIx; prevDef = typeDef; typeDefs[i] = typeDef; } prevDef.fieldEndIx = buff.GetTableSize(MDTable.Field)+1; prevDef.methodEndIx = buff.GetTableSize(MDTable.Method)+1; }
internal void SetParent(ClassDef paren) { parent = paren; }
internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) { for (int i=0; i < oldTypes.Length; i++) { for (int j=0; j < oldTypes[i].fields.Count; j++) ((FieldDef)oldTypes[i].fields[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].methods.Count; j++) ((MethodDef)oldTypes[i].methods[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].events.Count; j++) ((Event)oldTypes[i].events[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].properties.Count; j++) ((Property)oldTypes[i].properties[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].interfaces.Count; j++) ((ClassDef)oldTypes[i].interfaces[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].methodImpls.Count; j++) ((MethodImpl)oldTypes[i].methodImpls[j]).ChangeRefsToDefs(this,oldTypes); for (int j=0; j < oldTypes[i].nestedClasses.Count; j++) ((ClassDef)oldTypes[i].nestedClasses[j]).ChangeRefsToDefs(this,oldTypes); } }
internal override void Resolve(PEReader buff) { theClass = (ClassDef)buff.GetElement(MDTable.TypeDef,classIx); theInterface = (Class)buff.GetCodedElement(CIx.TypeDefOrRef,interfacesIndex); theClass.AddImplementedInterface(this); }
internal NestedClassDef MakeNestedClass(ClassDef parent) { NestedClassDef nClass = new NestedClassDef(parent,(TypeAttr)flags,name); ClassDef tmp = nClass; tmp.fieldIx = fieldIx; tmp.fieldEndIx = fieldEndIx; tmp.methodIx = methodIx; tmp.methodEndIx = methodEndIx; tmp.extendsIx = extendsIx; tmp.Row = Row; parent.nestedClasses.Add(nClass); return nClass; }
private MethodDef GenConstructor(ClassDef Class, CodeGenContext context) { // internal Block_N(outer locals ...): base(defining_scope) { ... } List<Param> parameters = new List<Param>(); foreach (FieldDef field in frameFields) parameters.Add(new Param(ParamAttr.Default, field.Name(), field.GetFieldType())); CodeGenContext constructor = context.CreateConstructor(Class, parameters.ToArray()); constructor.ldarg(0); // this constructor.ldarg(1); // defining_scope constructor.call(Runtime.Block.ctor); int N = 0; foreach (FieldDef field in frameFields) { // locals.field = localsN; constructor.ldarg(0); constructor.ldarg("locals" + (N++)); constructor.stfld(field); } constructor.ret(); constructor.Close(); return constructor.Method; }
internal virtual void ResolveParent(PEReader buff, bool isExtern) { CIx cIx = CIx.ResolutionScope; if (isExtern) cIx = CIx.Implementation; if (scope != null) return; MetaDataElement parentScope = buff.GetCodedElement(cIx,resScopeIx); if (parentScope is Module) { // special code for glitch in Everett ilasm ClassDef newDef = new ClassDef((PEFile)parentScope,0,nameSpace,name); ((Module)parentScope).AddToClassList(newDef); buff.InsertInTable(MDTable.TypeRef,Row,newDef); } else { scope = (ReferenceScope)buff.GetCodedElement(cIx,resScopeIx); ClassRef existing = (ClassRef)scope.GetExistingClass(nameSpace,name); if (existing == null) { scope.AddToClassList(this); } else { if (isExtern) buff.InsertInTable(MDTable.ExportedType,Row,existing); else buff.InsertInTable(MDTable.TypeRef,Row,existing); } } }
internal void AddScopeLocals(CodeGenContext context) { // ------------------ Start new Context ---------------------------- // [InteropMethod("MyClass")] // private class ActivationFrame: Ruby.Frame { ... } frame_def = context.CreateGlobalClass("_Internal", "Frame" + (N++), Runtime.FrameRef); Scope parentClass; for (parentClass = this; parentClass != null && !(parentClass is CLASS_OR_MODULE); parentClass = parentClass.parent_scope) ; string className = ""; if (parentClass != null) className = ((CLASS_OR_MODULE)parentClass).internal_name; ClassDef fileClass = FileClass(); string src = ""; if (fileClass != null && fileClass.Name().StartsWith("SourceFile_")) { src = fileClass.Name().Substring(11); frame_def.AddCustomAttribute(Runtime.FrameAttribute.ctor, new Constant[] { new StringConst(src), new StringConst(className) }); } foreach (string local in locals_list) CodeGenContext.AddField(frame_def, PERWAPI.FieldAttr.Public, ID.ToDotNetName(local), PrimitiveType.Object); // internal ActivationFrame(Frame caller): base(caller) { } CodeGenContext frame_ctor = context.CreateConstructor(frame_def, new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); frame_ctor.ldarg(0); frame_ctor.ldarg("caller"); frame_ctor.call(Runtime.Frame.ctor); frame_ctor.ret(); frame_ctor.Close(); // internal string file() { CodeGenContext file = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "file", PrimitiveType.String); file.startMethod(this.location); // return "thisfile.rb" file.ldstr(this.location.file); file.ret(); file.Close(); // internal override string methodName() { CodeGenContext methodName = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "methodName", PrimitiveType.String); methodName.startMethod(this.location); // return "CurrentMethodName" methodName.ldstr(CurrentMethodName()); methodName.ret(); methodName.Close(); CreateNestingMethod(frame_def, context); CreateLastClassMethod(frame_def, context); // ------------------ Return to Old Context ---------------------- // ActivationFrame frame = new ActivationFrame(caller); context.ldarg("caller"); context.newobj(frame_ctor.Method); int frame = context.StoreInTemp("frame", FrameClass, location); Debug.Assert(frame == 0); // frame.block_arg = block; context.ldloc(frame); LoadBlock0(context); context.stfld(Runtime.Frame.block_arg); if (this is BLOCK) { // frame.current_block = this; context.ldloc(frame); context.ldarg(0); context.stfld(Runtime.Frame.current_block); } }
/*-------------------- Constructors ---------------------------------*/ internal Event(string name, Type eType, ClassDef parent) : base(name, parent) { eventType = eType; tabIx = MDTable.Event; }
private void CreateNestingMethod(ClassDef Class, CodeGenContext context) { List<FieldDef> list = new List<FieldDef>(); for (Scope parent = this; parent != null; parent = parent.parent_scope) if (parent is CLASS_OR_MODULE) list.Add(((CLASS_OR_MODULE)parent).singletonField); // internal override Class[] nesting() { CodeGenContext nesting = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "nesting", new PERWAPI.ZeroBasedArray(Runtime.ClassRef)); nesting.startMethod(this.location); // Class[] array = new Class[list.Count]; nesting.ldc_i4(list.Count); nesting.newarr(Runtime.ClassRef); int array = nesting.CreateLocal("array", new PERWAPI.ZeroBasedArray(Runtime.ClassRef)); nesting.stloc(array); for (int i = 0; i < list.Count; i++) { // array[i] = list[i]; nesting.ldloc(array); nesting.ldc_i4(i); nesting.ldsfld(list[i]); nesting.stelem_ref(); } // return array; nesting.ldloc(array); nesting.ret(); nesting.ReleaseLocal(array, true); nesting.Close(); }
internal static string[] ReadNames(PEReader buff, ClassDef theClass, uint classIx) { return Feature.GetFeatureNames(buff,MDTable.Event,MDTable.EventMap,theClass,classIx); }