예제 #1
0
파일: NEWOBJ.cs 프로젝트: NielsDev/IL2VM
        public override void Process(Compiler compiler, MethodData methodData, Instruction instruction)
        {
            // Get .ctor method from operand and get the class associated with it
            MethodReference ctor = instruction.Operand as MethodReference;
            TypeReference type = ctor.DeclaringType;

            // If the object type is native, we ignore the IL object and don't emit a NEWOBJ
            // After that, we call the .CTOR which will be in runtime
            // The .CTOR in runtime will also initialize this object
            if(Util.IsNativeType(type))
            {
                // Create call to .CTOR
                Instruction call = Instruction.Create(OpCodes.Call, ctor);
                compiler.HandleInstruction(call, methodData);
                return;
            }

            // Write opcode and class ID
            int classID = compiler.GetTypeDataFromType(type.Resolve()).Id;
            methodData.AddInstruction(instruction.OpCode.Value);
            methodData.AddInstruction(classID);

            // Write CALL to .ctor
            // Count one extra parameter for the "this" object
            MethodDefinition methodDef = ctor.Resolve();
            int ctorID = compiler.GetMethodID(methodDef);
            if (ctorID == -1)
                ctorID = compiler.ProcessMethod(methodDef);

            methodData.AddInstruction(ctorID);
            methodData.AddInstruction(ctor.Parameters.Count);
        }
예제 #2
0
파일: Call.cs 프로젝트: NielsDev/IL2VM
        public override void Process(Compiler compiler, MethodData methodData, Instruction instruction)
        {
            // Get destination
            MethodReference destinationRef = instruction.Operand as MethodReference;
            string methodName = Util.GetFriendlyMethodName(destinationRef);

            // Check if it's a special method that should be caught here
            if (methodName == "ILVM_Asm_Execute2")
            {
                // IL code at this point will look like this
                // LOAD STRING "<assembly code>"
                // LOAD REGS
                // CALL ASM.EXECUTE

                // So we must check if two instructions before this the assembly code is loaded
                // else we need to throw an error
                Instruction ldstr = instruction.Previous.Previous;
                if (ldstr.OpCode != OpCodes.Ldstr)
                {
                    throw new Exception("Assembly code needs to be directly in the call");
                }
                else
                {
                    // Prepare assembler
                    string code = ldstr.Operand as string;
                    Assembler asm = compiler.Assembler;
                    int offset = asm.GetOffset();

                    // Since this is used as a "method" we need to place a return at the end
                    asm.HandleCode(code);
                    asm.HandleInstruction("ret");
                    int codeSize = asm.GetOffset() - offset;

                    // Write instruction followed by asm offset and asm size
                    methodData.AddInstruction(Ops.OP_RUNTIME_ASM);
                    methodData.AddInstruction(offset);
                    methodData.AddInstruction(codeSize);
                }
                return;
            }

            // If it's implemented in runtime, emit a special seperate instruction for this
            if (compiler.IsRuntimeMethod(methodName))
            {
                // Write instruction followed by the runtime method ID
                methodData.AddInstruction(Ops.OP_RUNTIME_CALL);
                methodData.AddInstruction(compiler.GetRuntimeMethodID(methodName));
            }
            else
            {
                // Get definition from reference
                MethodDefinition destination = destinationRef.Resolve();

                // Lookup the method, if it isn't processed yet, process it
                int methodId = compiler.GetMethodID(destination);
                if (methodId == -1)
                    methodId = compiler.ProcessMethod(destination);

                // If the method is not static, we pass "this" as argument, so we count 1 parameter extra
                int paramCount = destinationRef.Parameters.Count;
                if (!destination.IsStatic)
                    paramCount++;

                // Write instruction followed by the method ID
                methodData.AddInstruction(instruction.OpCode.Value);
                methodData.AddInstruction(methodId);
                methodData.AddInstruction(paramCount);
            }
        }