Пример #1
0
        private void @as()
        {
            FTypeRef typeRef = pod.typeRef(u2());

            PERWAPI.Type type = emitter.findType(typeRef.nnameBoxed());
            code.TypeInst(TypeOp.isinst, type);
        }
Пример #2
0
        /// <summary>
        /// Map to .NET register info for the given Fantom local variables.
        /// </summary>
        internal static Reg[] initRegs(FPod pod, bool isStatic, FMethodVar[] vars)
        {
            Reg[] regs   = new Reg[isStatic ? vars.Length : vars.Length + 1];
            int   nindex = 0;

            for (int i = 0; i < regs.Length; ++i)
            {
                Reg r = new Reg();
                if (i == 0 && !isStatic)
                {
                    // this pointer
                    r.stackType = FTypeRef.OBJ;
                    r.nindex    = nindex;
                    ++nindex;
                }
                else
                {
                    FTypeRef typeRef = pod.typeRef(vars[isStatic ? i : i - 1].type);
                    r.stackType = typeRef.stackType;
                    r.nindex    = nindex;
                    nindex     += 1; //nindex += typeRef.isWide() ? 2 : 1;
                }
                regs[i] = r;
            }
            return(regs);
        }
Пример #3
0
        //////////////////////////////////////////////////////////////////////////
        // Is/As
        //////////////////////////////////////////////////////////////////////////

        private void @is()
        {
            FTypeRef typeRef = pod.typeRef(u2());

            // if a generic instance, we have to use a method call
            // because Fantom types don't map to Java classes exactly;
            // otherwise we can use straight bytecode
            if (typeRef.isGenericInstance())
            {
                if (parent.IsViaType == null)
                {
                    parent.IsViaType = emitter.findMethod("Fanx.Util.OpUtil", "is",
                                                          new string[] { "System.Object", "Fan.Sys.Type" }, "System.Boolean");
                }
                loadType(typeRef);
                code.MethInst(MethodOp.call, parent.IsViaType);
            }
            else
            {
                PERWAPI.Type type = emitter.findType(typeRef.nnameBoxed());
                code.TypeInst(TypeOp.isinst, type);
                code.Inst(Op.ldnull);
                code.Inst(Op.cgt_un);
            }
        }
Пример #4
0
        private void loadType(FTypeRef tref)
        {
            string podName  = tref.podName;
            string typeName = tref.typeName;

            // if pod is "sys", then we can perform a shortcut and use
            // one of the predefined fields in Sys
            if (!tref.isGenericInstance() && podName == "sys")
            {
                PERWAPI.Field field = emitter.findField("Fan.Sys.Sys", typeName + "Type", "Fan.Sys.Type");
                code.FieldInst(FieldOp.ldsfld, field);
                if (tref.isNullable())
                {
                    typeToNullable();
                }
                return;
            }

            // lazy allocate my parent's type literal map: sig -> fieldName
            if (parent.typeLiteralFields == null)
            {
                parent.typeLiteralFields = new Hashtable();
            }
            Hashtable map = parent.typeLiteralFields;

            // types are lazy loaded and then cached in a private static field called
            // type$literal$count which will get generated by FTypeEmit (we keep track of signature
            // to fieldname in the typeConstFields map)
            string sig       = tref.signature;
            string fieldName = (string)map[sig];

            if (fieldName == null)
            {
                fieldName = "type$literal$" + map.Count;
                map[sig]  = fieldName;
            }
            //int fieldRef = emit.field(parent.className + "." + fieldName + ":Lfan/sys/Type;");

            //code.op2(GETSTATIC, fieldRef);
            //code.op(DUP);
            //int nonNull = code.branch(IFNONNULL);
            //code.op(POP);
            //code.op2(LDC_W, emit.strConst(sig));
            //code.op(ICONST_1);
            //code.op2(INVOKESTATIC, parent.sysFindType());
            //code.op(DUP);
            //code.op2(PUTSTATIC, fieldRef);
            //code.mark(nonNull);

            //emitter.EmitField(string name, string type, FieldAttr attr)
            //PERWAPI.Field field = emitter.EmitField("Fan.Sys.Sys", typeName + "Type", "Fan.Sys.Type");
            //code.FieldInst(FieldOp.ldsfld, field);

            // TODO - store in static field (all that crap above this)
            code.ldstr(sig);
            Method method = emitter.findMethod("Fan.Sys.Type", "find",
                                               new string[] { "System.String" }, "Fan.Sys.Type");

            code.MethInst(MethodOp.call, method);
        }
Пример #5
0
        //////////////////////////////////////////////////////////////////////////
        // Overrides
        //////////////////////////////////////////////////////////////////////////

        protected override string @base()
        {
            // if the base is a generic instance, then this must be a closure
            // method type (since we can't subclass List or Map).  We subclass
            // from one of the canned Func.Indirect inner classes.
            FTypeRef refer = pod.typeRef(type.m_base);

            if (refer.isGenericInstance())
            {
                this.funcType = (FuncType)Type.find(refer.signature, true);
                int paramCount = funcType.m_params.Length;
                if (paramCount > Func.MaxIndirectParams)
                {
                    return("Fan.Sys.Func/IndirectX");
                }
                else
                {
                    return("Fan.Sys.Func/Indirect" + paramCount);
                }
            }
            else
            {
                string baset = nname(type.m_base);
                if (baset == "System.Object")
                {
                    return("Fan.Sys.FanObj");
                }
                if (baset == "Fan.Sys.Type")
                {
                    return("Fan.Sys.ClassType");
                }
                return(baset);
            }
        }
Пример #6
0
        //////////////////////////////////////////////////////////////////////////
        // Code Utils
        //////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Push the specified number of arguments onto the stack.
        /// </summary>
        private void pushArgs(PERWAPI.CILInstructions code, bool self, int count)
        {
            if (self)
            {
                code.Inst(PERWAPI.Op.ldarg_0);
            }
            for (int i = 0; i < count; i++)
            {
                FTypeRef var = emit.pod.typeRef(method.m_vars[i].type);
                FCodeEmit.loadVar(code, var.stackType, self ? i + 1 : i);
            }
        }
Пример #7
0
        /*
         * synchronized Class emit()
         * {
         * if (cls == null)
         *  cls = FPodEmit.emitAndLoad(fpod);
         * return cls;
         * }
         *
         * synchronized void precompiled(Class cls)
         * throws Exception
         * {
         * this.cls = cls;
         * FPodEmit.initFields(fpod, cls);
         * }
         */

        internal Type findType(int qname)
        {
            if (qname == 0xFFFF || qname == -1)
            {
                return(null);
            }

            // lookup type with typeRef index
            FTypeRef reference = fpod.typeRef(qname);

            // if generic instance, then this type must be used in a method
            // signature, not type meta-data (b/c I can't subclass generic types),
            // so it's safe that my pod has been loaded and is now registered (in
            // case the generic type is parameterized via types in my pod)
            if (reference.isGenericInstance())
            {
                return(TypeParser.load(reference.signature, true, this));
            }

            // otherwise I need to handle if I am loading my own pod, because
            // I might not yet be added to the system namespace if I'm just
            // loading my own hollow types
            string podName  = reference.podName;
            string typeName = reference.typeName;
            Pod    pod      = podName == m_name ? this : doFind(podName, true, null);
            Type   type     = pod.type(typeName, false);

            if (type != null)
            {
                if (reference.isNullable())
                {
                    type = type.toNullable();
                }
                return(type);
            }

            // handle generic parameter types (for sys pod only)
            if (m_name == "sys")
            {
                type = Sys.genericParamType(typeName);
                if (type != null)
                {
                    if (reference.isNullable())
                    {
                        type = type.toNullable();
                    }
                    return(type);
                }
            }

            // lost cause
            throw UnknownTypeErr.make(podName + "::" + typeName).val;
        }
Пример #8
0
        private void doCompare(string suffix, FTypeRef lhs, FTypeRef rhs)
        {
            // get lhs and rhs types
            string[] args = new string[]
            {
                lhs.isRef() ? "System.Object" : lhs.nname(),
                     rhs.isRef() ? "System.Object" : rhs.nname()
            };
            string ret = (suffix == "") ? "System.Int64" : "System.Boolean";

            PERWAPI.Method m = emitter.findMethod("Fanx.Util.OpUtil", "compare" + suffix, args, ret);
            code.MethInst(MethodOp.call, m);
        }
Пример #9
0
        //////////////////////////////////////////////////////////////////////////
        // Compare
        //////////////////////////////////////////////////////////////////////////

        private void compareEQ()
        {
            FTypeRef lhs = pod.typeRef(u2());
            FTypeRef rhs = pod.typeRef(u2());

            // if this is a.equals(b) and we know a is non-null, then just call equals
            if (lhs.isRef() && !lhs.isNullable() && rhs.isRef())
            {
                PERWAPI.Method m = emitter.findMethod("System.Object", "Equals",
                                                      new string[] { "System.Object" }, "System.Boolean");
                m.AddCallConv(CallConv.Instance);
                code.MethInst(MethodOp.callvirt, m);
                return;
            }

            doCompare("EQ", lhs, rhs);
        }
Пример #10
0
        public static Assembly emitPod(FPod pod, bool load, string path)
        {
            string   podName  = pod.m_podName;
            Assembly assembly = (Assembly)assemblies[podName];

            if (assembly == null)
            {
                Emitter emitter = new Emitter(podName, path);

                // unzip the native.dll if one exists
                unzipToTemp(pod, podName + "Native_.dll");
                unzipToTemp(pod, podName + "Native_.pdb");

                // emit the pod class itself (which declares all constants)
                //FPodEmit.EmitAndLoad(emitter, pod);
                FPodEmit.emit(emitter, pod);

                // the Emitter needs base types to be defined before
                // descendant types, so make sure everything gets stubbed
                // out in the correct order ahead of time
                for (int i = 0; i < pod.m_types.Length; i++)
                {
                    emitter.findType(pod.nname(pod.m_types[i].m_self));
                }

                // emit all the rest of the types in this pod
                for (int i = 0; i < pod.m_types.Length; i++)
                {
                    FType    ftype  = pod.m_types[i];
                    FTypeRef tref   = ftype.m_pod.typeRef(ftype.m_self);
                    Type     parent = Type.find(tref.podName + "::" + tref.typeName, true);

                    // make sure we have reflected to setup slots
                    parent.reflect();

                    // route based on type
                    if ((ftype.m_flags & FConst.Mixin) != 0)
                    {
                        // interface
                        FMixinInterfaceEmit iemit = new FMixinInterfaceEmit(emitter, parent, ftype);
                        iemit.emit();

                        // body class
                        FMixinBodyEmit bemit = new FMixinBodyEmit(emitter, parent, ftype);
                        bemit.emit();

                        ftypes[ftype] = new FTypeEmit[] { iemit, bemit };
                    }
                    else if (parent.@is(Sys.ErrType))
                    {
                        // error
                        FErrEmit emitErr = new FErrEmit(emitter, parent, ftype);
                        emitErr.emit();

                        FErrValEmit emitErrVal = new FErrValEmit(emitter, parent, ftype);
                        emitErrVal.emit();

                        ftypes[ftype] = new FTypeEmit[] { emitErr, emitErrVal };
                    }
                    else
                    {
                        // class
                        FClassEmit emit = new FClassEmit(emitter, parent, ftype);
                        emit.emit();
                        ftypes[ftype] = new FTypeEmit[] { emit };
                    }
                }

                // commit assembly
                byte[] buf = emitter.commit();
                if (load)
                {
                    //long start = System.Environment.TickCount;

                    // load assembly
                    assembly = (buf == null)
            ? Assembly.LoadFile(emitter.fileName)
            : Assembly.Load(buf);
                    assemblies[podName] = assembly;

                    //long end = System.Environment.TickCount;
                    //System.Console.WriteLine("load " + podName + " in " + (end-start) + " ms");

                    // load $Pod type
                    FPodEmit.load(assembly, pod);
                }
            }
            return(assembly);
        }
Пример #11
0
        private void coerce()
        {
            FTypeRef from = pod.typeRef(u2());
            FTypeRef to   = pod.typeRef(u2());

            // Bool boxing/unboxing
            if (from.isBoolPrimitive())
            {
                if (to.isRef())
                {
                    boolBox(); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }
            if (to.isBoolPrimitive())
            {
                if (from.isRef())
                {
                    boolUnbox(!from.isBool()); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }

            // Int boxing/unboxing
            if (from.isIntPrimitive())
            {
                if (to.isRef())
                {
                    intBox(); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }
            if (to.isIntPrimitive())
            {
                if (from.isRef())
                {
                    intUnbox(!from.isInt()); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }

            // Float boxing/unboxing
            if (from.isFloatPrimitive())
            {
                if (to.isRef())
                {
                    floatBox(); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }
            if (to.isFloatPrimitive())
            {
                if (from.isRef())
                {
                    floatUnbox(!from.isFloat()); return;
                }
                throw new Exception("Coerce " + from + " => " + to);
            }

            // check nullable => non-nullable
            if (from.isNullable() && !to.isNullable())
            {
                CILLabel nonnull = code.NewLabel();
                code.Inst(Op.dup);
                code.Inst(Op.ldnull);
                code.Branch(BranchOp.bne_un_s, nonnull);
                if (parent.NullErrMakeCoerce == null)
                {
                    parent.NullErrMakeCoerce = emitter.findMethod("Fan.Sys.NullErr", "makeCoerce",
                                                                  new string[0], "Fan.Sys.Err/Val");
                }
                code.MethInst(MethodOp.call, parent.NullErrMakeCoerce);
                code.Inst(Op.throwOp);
                code.CodeLabel(nonnull);
            }

            // don't bother casting to obj
            if (to.isObj())
            {
                return;
            }

            code.TypeInst(TypeOp.castclass, emitter.findType(to.nname()));
        }
Пример #12
0
 public FCodeEmit(FTypeEmit parent, FBuf fcode, CILInstructions code, Reg[] regs, FTypeRef ret)
 {
     this.pod      = parent.pod;
     this.emitter  = parent.emitter;
     this.parent   = parent;
     this.buf      = fcode.m_buf;
     this.len      = fcode.m_len;
     this.code     = code;
     this.podClass = FanUtil.toDotnetTypeName(pod.m_podName, "$Pod", false);
     this.jumps    = new Jumps(code);
     this.regs     = regs;
     this.ret      = ret;
 }
Пример #13
0
 public bool isWide()
 {
     return(FTypeRef.isWide(stackType));
 }
Пример #14
0
        private void catchErrStart()
        {
            exType = "System.Exception";
            for (int i = 0; i < tryJump.Length; i++)
            {
                if (startPos == tryJump[i])
                {
                    FTypeRef typeRef = pod.typeRef(tryErr[i]);
                    dotnetErr = Fan.Sys.Err.fanToDotnet(typeRef.nname());
                    if (!typeRef.isErr())
                    {
                        exType = typeRef.nname() + "/Val";
                    }
                    break;
                }
            }

            // close try block
            errBlocks.Push(getLastTryBlock());

            // use a filter if we need to "dual-check" for native exception
            if (dotnetErr != null)
            {
                code.CodeLabel(filterStart = code.NewLabel());
                CILLabel match     = code.NewLabel();
                CILLabel endfilter = code.NewLabel();

                // check native type first
                code.Inst(Op.dup);
                code.TypeInst(TypeOp.isinst, emitter.findType(dotnetErr));
                code.Inst(Op.ldnull);
                code.Branch(BranchOp.bne_un_s, match);

                // then check Fantom type
                code.Inst(Op.dup);
                code.TypeInst(TypeOp.isinst, emitter.findType(exType));
                code.Inst(Op.ldnull);
                code.Branch(BranchOp.bne_un_s, match);

                // no match
                code.Inst(Op.pop); // pop exception off stack
                code.IntInst(IntOp.ldc_i4, 0);
                code.Branch(BranchOp.br_s, endfilter);

                // match
                code.CodeLabel(match);
                code.Inst(Op.pop); // pop exception off stack
                code.IntInst(IntOp.ldc_i4, 1);

                // endfilter
                code.CodeLabel(endfilter);
                code.Inst(Op.endfilter);
            }

            // start handler block
            code.StartBlock();

            // there is already a System.Exception on the stack, but
            // we need to map into a sys::Err type
            if (parent.ErrMake == null)
            {
                parent.ErrMake = emitter.findMethod("Fan.Sys.Err", "make",
                                                    new string[] { "System.Exception" }, "Fan.Sys.Err");
            }
            code.MethInst(MethodOp.call, parent.ErrMake);
            cast();
        }