internal CodeGenContext(CodeGenContext context) { this.Assembly = context.Assembly; this.Method = context.Method; this.CLRLocals = context.CLRLocals; this.labels = context.labels; this.CurrentRubyClass = context.CurrentRubyClass; this.orig_func = context.orig_func; // BBTAG this.orig_func_formals = context.orig_func_formals; // BBTAG this.currentSkeleton = context.currentSkeleton; // BBTAG this.postPassList = context.postPassList; // BBTAG this.peFiles = context.peFiles; // BBTAG }
/// <summary> /// Define a new method to emit for the current class. /// </summary> public CILInstructions emitMethod( string name, string retType, string[] paramNames, string[] paramTypes, MethAttr attr, string[] localNames, string[] localTypes) { Param[] pars = new Param[paramNames.Length]; for (int i=0; i<pars.Length; i++) pars[i] = new Param(ParamAttr.Default, paramNames[i], findType(paramTypes[i])); // first check if this method was already stubbed out methodDef = (MethodDef)methods[getMethodKey(className, name, paramTypes)]; if (methodDef == null) { // if not, we need to create it methodDef = classDef.AddMethod(attr, ImplAttr.IL, name, findType(retType), pars); } else { // if stubbed out, make sure we define the method correctly methodDef.SetMethAttributes(attr); } if ((attr & MethAttr.Static) != MethAttr.Static) methodDef.AddCallConv(CallConv.Instance); if (localNames.Length > 0) { Local[] locals = new Local[localNames.Length]; for (int i=0; i<locals.Length; i++) locals[i] = new Local(localNames[i], findType(localTypes[i])); methodDef.AddLocals(locals, true); } // TODO - what the f**k should this be? methodDef.SetMaxStack(16 + pars.Length + localNames.Length); // add to lookup table addToMethodMap(className, name, paramTypes, methodDef); // don't create code buffer if abstract if ((attr & MethAttr.Abstract) == MethAttr.Abstract) return null; return methodDef.CreateCodeBuffer(); }
/*-------------------- Constructors ---------------------------------*/ internal ImplMap(ushort flag, MethodDef implMeth, string iName, ModuleRef mScope) { flags = flag; meth = implMeth; importName = iName; importScope = mScope; tabIx = MDTable.ImplMap; if (iName == null) flags |= NoMangle; sortTable = true; //throw(new NotYetImplementedException("PInvoke ")); }
internal void CheckParent(MethodDef paren, PEReader buff) { if (paren == buff.GetCodedElement(CIx.TypeOrMethodDef,parentIx)) { parent = paren; paren.InsertGenericParam(this); } }
public void AddMethod(MethodDef meth, MethodType mType) { AddMethod(new MethodSemantics(mType,meth,this)); }
/// <summary> /// Add a method to this class /// </summary> /// <param name="meth">Descriptor for the method to be added</param> public void AddMethod(MethodDef meth) { MethodDef m = (MethodDef)GetMethodDesc(meth.Name(),meth.GetParTypes()); if (m != null) throw new DescriptorException("Method " + m.NameString()); methods.Add(meth); meth.SetParent(this); }
/*-------------------- Constructors ---------------------------------*/ internal CILInstructions(MethodDef meth) { thisMeth = meth; }
internal void GetGenericParams(MethodDef meth) { if (tables[(int)MDTable.GenericParam] != null) { for (int j=0; j < tables[(int)MDTable.GenericParam].Length; j++) { ((GenericParam)tables[(int)MDTable.GenericParam][j]).CheckParent(meth,this); } } }
public void MakeVarArgMethod(MethodDef paren, Type[] optPars) { if (paren != null) { parent = null; varArgParent = paren; } sig.optParTypes = optPars; if (sig.optParTypes != null) sig.numOptPars = (uint)sig.optParTypes.Length; sig.callConv = CallConv.Vararg; }
internal static void Read(PEReader buff, TableRow[] methDefs) { MethodDef prevDef = null; prevDef = new MethodDef(buff); methDefs[0] = prevDef; for (int i=1; i < methDefs.Length; i++) { prevDef.Row = (uint)i; MethodDef methDef = new MethodDef(buff); prevDef.numPars = methDef.parIx - prevDef.parIx; prevDef = methDef; methDefs[i] = methDef; } prevDef.Row = (uint)methDefs.Length; prevDef.numPars = (buff.GetTableSize(MDTable.Param)+1) - prevDef.parIx; }
internal void Resolve(PEReader buff, MethodDef meth) { if (resolved) return; buff.currentMethodScope = meth; buff.currentClassScope = (Class)meth.GetParent(); locals = buff.ReadLocalSig(sigIx); buff.currentMethodScope = null; buff.currentClassScope = null; }
internal override FieldDef DefineAllocator(CodeGenContext context, MethodDef ctor) { // Conservative - don't create allocator if we're not sure what the base class is // BBTAG: should be able to create this in all cases now, since we do a test in // define_alloc_func //if (super_class != null) // return null; ClassRef baseClass = Runtime.MethodBodyNRef(0); ClassDef allocator = context.CreateGlobalClass("_Internal", "Method_" + internal_name + "_Allocator", baseClass); context.currentSkeleton.allocator = allocator; // internal static Call0(Class last_class, object recv, ...) { body } CodeGenContext Call = context.CreateMethod(allocator, MethAttr.PublicVirtual, "Call0", PrimitiveType.Object, new Param[] { new Param(ParamAttr.Default, "last_class", Runtime.ClassRef), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef), new Param(ParamAttr.Default, "block", Runtime.ProcRef)}); // return new MyClass((Class)recv)); Call.ldarg("recv"); Call.cast(Runtime.ClassRef); Call.newobj(ctor); Call.ret(); Call.Close(); // internal MyAllocator() {} CodeGenContext constructor = context.CreateConstructor(allocator); constructor.ldarg(0); constructor.call(Runtime.MethodBodyCtor(baseClass)); constructor.ret(); constructor.Close(); // internal static MyAllocator singleton; FieldDef singleton = CodeGenContext.AddField(allocator, FieldAttr.PublicStatic, "myRubyMethod", allocator); // static MyAllocator() { // singleton = new MyAllocator(); // } CodeGenContext staticConstructor = context.CreateStaticConstructor(allocator); staticConstructor.newobj(constructor.Method); staticConstructor.stsfld(singleton); staticConstructor.ret(); staticConstructor.Close(); return singleton; }
internal virtual FieldDef DefineAllocator(CodeGenContext context, MethodDef ctor) { return null; }
internal static void GenerateMainMethod(CodeGenContext context, ClassDef fileClass, MethodDef SetOptions, List<SOURCEFILE> files) { // public static void Main(string[] args) { CodeGenContext Main = context.CreateModuleMethod("Main", PrimitiveType.Void, new Param[] { new Param(ParamAttr.Default, "args", new PERWAPI.ZeroBasedArray(PrimitiveType.String)) }); Main.Method.DeclareEntryPoint(); PERWAPI.CILLabel endLabel = Main.NewLabel(); // try { Main.StartBlock(Clause.Try); if (SetOptions != null) { // SetOptions(args); Main.ldarg("args"); Main.call(SetOptions); } // register other ruby source files in assembly so that they can be loaded if requested foreach (SOURCEFILE f in files) { // Ruby.Runtime.Program.AddProgram(filename, fileClass); Main.ldstr(File.stripExtension(f.location.file)); Main.ldtoken(f.fileClass); Main.call(Runtime.SystemType.GetTypeFromHandle); Main.call(Runtime.Program.AddProgram); } // Explicit load // Load(ruby_top_self, null); Main.ldsfld(Runtime.Object.ruby_top_self); Main.ldnull(); Main.call(LoadMethod.Method); Main.pop(); Main.Goto(endLabel); // } TryBlock block = Main.EndTryBlock(); // finally { Main.StartBlock(Clause.Finally); // Program.ruby_stop(); Main.call(Runtime.Program.ruby_stop); Main.endfinally(); // } Main.EndFinallyBlock(block); Main.CodeLabel(endLabel); Main.ret(); Main.Close(); // } }
/// <summary> /// Add a MethodDef into the lookup table. /// </summary> public void addToMethodMap(string className, string name, string[] paramTypes, MethodDef def) { string key = getMethodKey(className, name, paramTypes); methods[key] = def; }
internal Scope(Scope parent, MethodDef thisMeth) { _thisMeth = thisMeth; _parent = parent; }
public void ReadByteCodes(MethodDef meth, uint rva) { if (rva == 0) return; BaseStream.Seek(GetOffset(rva),SeekOrigin.Begin); CILInstructions instrs = meth.CreateCodeBuffer(); uint formatByte = ReadByte(); uint format = formatByte & 0x3; if (Diag.DiagOn) Console.WriteLine("code header format = " + Hex.Byte((int)formatByte)); uint size = 0; if (format == CILInstructions.TinyFormat) { size = formatByte >> 2; if (Diag.DiagOn) Console.WriteLine("Tiny Format, code size = " + size); instrs.SetAndResolveInstructions(DoByteCodes(size,meth)); } else if (format == CILInstructions.FatFormat) { uint headerSize = ReadByte(); bool initLocals = (formatByte & CILInstructions.InitLocals) != 0; bool moreSects = (formatByte & CILInstructions.MoreSects) != 0; meth.SetMaxStack((int)ReadUInt16()); size = ReadUInt32(); if (Diag.DiagOn) Console.WriteLine("Fat Format, code size = " + size); uint locVarSig = ReadUInt32(); CILInstruction[] instrList = this.DoByteCodes(size,meth); while (moreSects) { // find next 4 byte boundary long currPos = BaseStream.Position; if (currPos % 4 != 0) { long pad = 4 - (currPos % 4); for (int p = 0; p < pad; p++) ReadByte(); } uint flags = ReadByte(); //while (flags == 0) flags = ReadByte(); // maximum of 3 to get 4 byte boundary?? moreSects = (flags & CILInstructions.SectMoreSects) != 0; bool fatSect = (flags & CILInstructions.SectFatFormat) != 0; if ((flags & CILInstructions.EHTable) == 0) throw new Exception("Section not an Exception Handler Table"); int sectLen = ReadByte() + (ReadByte() << 8) + (ReadByte() << 16); int numClauses = sectLen - 4; if (fatSect) numClauses /= 24; else numClauses /= 12; for (int i=0; i < numClauses; i++) { EHClauseType eFlag; if (fatSect) eFlag = (EHClauseType)ReadUInt32(); else eFlag = (EHClauseType)ReadUInt16(); uint tryOff = 0, tryLen = 0, hOff = 0, hLen = 0; if (fatSect) { tryOff = ReadUInt32(); tryLen = ReadUInt32(); hOff = ReadUInt32(); hLen = ReadUInt32(); } else { tryOff = ReadUInt16(); tryLen = ReadByte(); hOff = ReadUInt16(); hLen = ReadByte(); } EHClause ehClause = new EHClause(eFlag,tryOff,tryLen,hOff,hLen); if (eFlag == EHClauseType.Exception) ehClause.ClassToken(GetTokenElement(ReadUInt32())); else ehClause.FilterOffset(ReadUInt32()); instrs.AddEHClause(ehClause); } } if (locVarSig != 0) { LocalSig lSig = (LocalSig)GetTokenElement(locVarSig); lSig.Resolve(this,meth); meth.AddLocals(lSig.GetLocals(),initLocals); } instrs.SetAndResolveInstructions(instrList); } else { Console.WriteLine("byte code format error"); } }
internal override Member ResolveParent(PEReader buff) { if (parent != null) return this; buff.currentMethodScope = this; MetaDataElement paren = buff.GetCodedElement(CIx.MemberRefParent,parentIx); buff.currentMethodScope = null; if (paren is MethodDef) { parent = null; varArgParent = (MethodDef)paren; //this.sig = buff.ReadMethSig(this,name,sigIx); ((MethodDef)paren).AddVarArgSig(this); return this; } else if (paren is ClassSpec) { ((ClassSpec)paren).AddMethod(this); return this; } else if (paren is PrimitiveType) { paren = MSCorLib.mscorlib.GetDefaultClass(); } else if (paren is ClassDef) { this.sig = buff.ReadMethSig(this,name,sigIx); return ((ClassDef)paren).GetMethod(this.sig); } else if (paren is TypeSpec) { paren = new ConstructedTypeSpec((TypeSpec)paren); //Console.WriteLine("Got TypeSpec as parent of Member"); //return this; //throw new Exception("Got TypeSpec as parent of Member"); //((TypeSpec)paren).AddMethod(buff,this); } if (paren is ReferenceScope) parent = ((ReferenceScope)paren).GetDefaultClass(); parent = (Class)paren; //if ((MethodRef)parent.GetMethodDesc(name) != null) throw new PEFileException("Existing method!!"); //sig = buff.ReadMethSig(this,name,sigIx); //MethodRef existing = (MethodRef)parent.GetMethod(sig); //if (existing != null) // return existing; parent.AddToMethodList(this); return this; }
/* private long GetOffset(int rva) { for (int i=0; i < inputSections.Length; i++) { long offs = inputSections[i].GetOffset(rva); if (offs > 0) return offs; } return 0; } public bool ReadPadding(int boundary) { while ((Position % boundary) != 0) { if (buffer[index++] != 0) { return false; } } return true; } public String ReadName() { int len = NAMELEN; char [] nameStr = new char[NAMELEN]; char ch = (char)ReadByte(); int i=0; for (; (i < NAMELEN) && (ch != '\0'); i++) { nameStr[i] = ch; ch = (char)ReadByte(); } return new String(nameStr,0,i); } internal String ReadString() { char [] str = new char[STRLEN]; int i=0; char ch = (char)ReadByte(); for (; ch != '\0'; i++) { str[i] = ch; ch = (char)ReadByte(); } return new String(str,0,i); } public long GetPos() { return BaseStream.Position; } public void SetPos(int ix) { BaseStream.Position = ix; } */ /* public void SetToRVA(int rva) { index = PESection.GetOffset(rva); // Console.WriteLine("Setting buffer to rva " + PEConsts.Hex(rva) + " = index " + PEConsts.Hex(index)); // Console.WriteLine("Setting buffer to rva " + rva + " = index " + index); } public byte[] GetBuffer() { return buffer; } */ private CILInstruction[] DoByteCodes(uint len, MethodDef thisMeth) { uint pos = 0; ArrayList instrList = new ArrayList(); //int instrIx = 0; while (pos < len) { uint offset = pos; uint opCode = ReadByte(); pos++; IType iType = IType.op; if (opCode == 0xFE) { uint ix = ReadByte(); pos++; opCode = (opCode << 8) + ix; iType = FileImage.longInstrMap[ix]; } else iType = FileImage.instrMap[opCode]; if (Diag.DiagOn) Console.WriteLine("Got instruction type " + iType); CILInstruction nextInstr = null; if (iType == IType.specialOp) { pos += 4; if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode)); switch (opCode) { case ((int)SpecialOp.ldc_i8) : nextInstr = new LongInstr((SpecialOp)opCode,ReadInt64()); pos += 4; break; case ((int)SpecialOp.ldc_r4) : nextInstr = new FloatInstr((SpecialOp)opCode,ReadSingle()); break; case ((int)SpecialOp.ldc_r8) : nextInstr = new DoubleInstr((SpecialOp)opCode,ReadDouble()); pos += 4; break; case ((int)SpecialOp.calli) : nextInstr = new SigInstr((SpecialOp)opCode,(CalliSig)GetTokenElement(ReadUInt32())); break; case ((int)SpecialOp.Switch) : // switch uint count = ReadUInt32(); int[] offsets = new int[count]; for (uint i=0; i < count; i++) offsets[i] = ReadInt32(); pos += (4 * count); nextInstr = new SwitchInstr(offsets); break; case ((int)SpecialOp.ldstr) : // ldstr uint strIx = ReadUInt32(); strIx = strIx & FileImage.ElementMask; nextInstr = new StringInstr((SpecialOp)opCode,userstring.GetUserString(strIx)); break; case ((int)MethodOp.ldtoken) : MetaDataElement elem = GetTokenElement(ReadUInt32()); if (elem is Method) nextInstr = new MethInstr((MethodOp)opCode,(Method)elem); else if (elem is Field) nextInstr = new FieldInstr((FieldOp)opCode,(Field)elem); else nextInstr =new TypeInstr((TypeOp)opCode,(Type)elem); break; } } else if (iType == IType.branchOp) { if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode)); if ((opCode < 0x38) || (opCode == 0xDE)) { // br or leave.s nextInstr = new BranchInstr(opCode,ReadSByte()); pos++; } else { nextInstr = new BranchInstr(opCode,ReadInt32()); pos += 4; } } else { if (Diag.DiagOn) Console.Write(Hex.Byte((int)opCode)); switch (iType) { case (IType.op) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (Op)opCode); nextInstr = new Instr((Op)opCode); break; case (IType.methOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (MethodOp)opCode); nextInstr = new MethInstr((MethodOp)opCode,(Method)GetTokenElement(ReadUInt32())); pos += 4; break; case (IType.typeOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (TypeOp)opCode); uint ttok = ReadUInt32(); Type typeToken = (Type)GetTokenElement(ttok); if (typeToken is GenericParTypeSpec) typeToken = ((GenericParTypeSpec)typeToken).GetGenericParam(thisMeth); nextInstr = new TypeInstr((TypeOp)opCode,typeToken); pos += 4; break; case (IType.fieldOp) : if (Diag.DiagOn) Console.WriteLine("Got instruction " + (FieldOp)opCode); nextInstr = new FieldInstr((FieldOp)opCode,(Field)GetTokenElement(ReadUInt32())); pos += 4; break; case (IType.int8Op) : nextInstr = new IntInstr((IntOp)opCode,ReadSByte()); pos++; break; case (IType.uint8Op) : nextInstr = new UIntInstr((IntOp)opCode,ReadByte()); pos++; break; case (IType.uint16Op) : nextInstr =new UIntInstr((IntOp)opCode,ReadUInt16()); pos++; break; case (IType.int32Op) : nextInstr =new IntInstr((IntOp)opCode,ReadInt32()); pos += 4; break; } } if (nextInstr != null) nextInstr.Resolve(); instrList.Add(nextInstr); } CILInstruction[] instrs = new CILInstruction[instrList.Count]; for (int i=0; i < instrs.Length; i++) { instrs[i] = (CILInstruction)instrList[i]; } return instrs; }
/*-------------------- Constructors ---------------------------------*/ internal MethodSemantics(MethodType mType, MethodDef method, Feature feature) { type = mType; meth = method; eventOrProp = feature; sortTable = true; tabIx = MDTable.MethodSemantics; }
/// <summary> /// Add a method to this class /// </summary> /// <param name="name">method name</param> /// <param name="retType">return type</param> /// <param name="pars">parameters</param> /// <returns>a descriptor for this new method</returns> public MethodDef AddMethod(string name, Type retType, Param[] pars) { System.Diagnostics.Debug.Assert(retType != null); MethSig mSig = new MethSig(name); mSig.SetParTypes(pars); MethodDef meth = (MethodDef)GetMethod(mSig); if (meth != null) throw new DescriptorException("Method " + meth.NameString()); mSig.retType = retType; meth = new MethodDef(this,mSig,pars); methods.Add(meth); return meth; }
internal override void Resolve(PEReader buff) { meth = (MethodDef)buff.GetElement(MDTable.Method,methIx); eventOrProp = (Feature)buff.GetCodedElement(CIx.HasSemantics,assocIx); eventOrProp.AddMethod(this); }
internal void Resolve(PEReader buff, MethodDef meth) { if (resolved) return; }
/// <summary> /// Add a "global" method to this module /// </summary> /// <param name="meth">The method to be added</param> public void AddMethod(MethodDef meth) { defaultClass.AddMethod(meth); }
public void RemoveMethod(MethodDef meth) { bool found = false; for (int i=0; i < tide; i++) { if (found) methods[i-1] = methods[i]; else if (methods[i].GetMethod() == meth) found = true; } }
/// <summary> /// Delete a method from this module /// </summary> /// <param name="meth">The method to be deleted</param> public void RemoveMethod(MethodDef meth) { defaultClass.RemoveMethod(meth); }
internal GenericParam GetGenericParam(MethodDef meth) { if (gPar == null) { if (isClassPar) { ClassDef methClass = (ClassDef)meth.GetParent(); gPar = methClass.GetGenericParam((int)index); } else { gPar = meth.GetGenericParam((int)index); } } return gPar; }
//public void ReadPDB() { // PDBReader reader = new PDBReader(this.fileName); // foreach (ClassDef cDef in GetClasses()) // foreach (MethodDef mDef in cDef.GetMethods()) { // CILInstructions buffer = mDef.GetCodeBuffer(); // PDBMethod meth = reader.GetMethod((int) mDef.Token()); // if (meth == null) // continue; // no symbols for this method // PDBSequencePoint[] spList = meth.SequencePoints; // MergeBuffer mergeBuffer = new MergeBuffer(buffer.GetInstructions()); // PDBScope outer = meth.Scope; // buffer.currentScope = ReadPDBScope(outer, mergeBuffer, null, mDef); // foreach (PDBSequencePoint sp in spList) { // PDBDocument doc = sp.Document; // mergeBuffer.Add(new Line((uint) sp.Line, (uint) sp.Column, (uint) sp.EndLine, (uint) sp.EndColumn, // SourceFile.GetSourceFile(doc.URL, doc.Language, doc.LanguageVendor, doc.DocumentType)), // (uint) sp.Offset); // } // buffer.SetInstructions(mergeBuffer.Instructions); // } // } private Scope ReadPDBScope(PDBScope scope, MergeBuffer mergeBuffer, Scope parent, MethodDef thisMeth) { Scope thisScope = new Scope(parent, thisMeth); if (parent != null) mergeBuffer.Add(new OpenScope(thisScope), (uint) scope.StartOffset); foreach (PDBVariable var in scope.Variables) thisScope.AddLocalBinding(var.Name, var.Address); foreach (PDBScope child in scope.Children) ReadPDBScope(child, mergeBuffer, thisScope, thisMeth); if (parent != null) mergeBuffer.Add(new CloseScope(thisScope), (uint) scope.EndOffset); return thisScope; }
internal override void Resolve(PEReader buff) { meth = (MethodDef)buff.GetCodedElement(CIx.MemberForwarded,memForIndex); importScope = (ModuleRef)buff.GetElement(MDTable.ModuleRef,scopeIx); if (meth != null) meth.AddPInvokeInfo(this); }
internal Scope(MethodDef thisMeth) : this(null, thisMeth) { }