private void @as() { FTypeRef typeRef = pod.typeRef(u2()); PERWAPI.Type type = emitter.findType(typeRef.nnameBoxed()); code.TypeInst(TypeOp.isinst, type); }
/// <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); }
////////////////////////////////////////////////////////////////////////// // 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); } }
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); }
////////////////////////////////////////////////////////////////////////// // 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); } }
////////////////////////////////////////////////////////////////////////// // 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); } }
/* * 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; }
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); }
////////////////////////////////////////////////////////////////////////// // 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); }
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); }
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())); }
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; }
public bool isWide() { return(FTypeRef.isWide(stackType)); }
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(); }