/** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ private void emitReturn(Name onStack) { // return statement Class rclass = invokerType.returnType(); BasicType rtype = lambdaForm.returnType(); //assert(rtype == basicType(rclass)); // must agree if (rtype == BasicType.V_TYPE) { // [IKVM] unlike the JVM, the CLR doesn't like left over values on the stack if (onStack != null && onStack._type() != BasicType.V_TYPE) { ilgen.Emit(OpCodes.Pop); } } else { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; // put return value on the stack if it is not already there if (rn != onStack) { emitLoadInsn(rtype, lambdaForm.result); } emitImplicitConversion(rtype, rclass, rn); } ilgen.Emit(OpCodes.Ret); }
/** * Emit an implicit conversion for an argument which must be of the given pclass. * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. * * @param ptype type of value present on stack * @param pclass type of value required on stack * @param arg compile-time representation of value on stack (Node, constant) or null if none */ private void emitImplicitConversion(BasicType ptype, Class pclass, object arg) { //assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller if (pclass == ptype.basicTypeClass() && ptype != BasicType.L_TYPE) { return; // nothing to do } switch (ptype.name()) { case "L_TYPE": if (VerifyType.isNullConversion(CoreClasses.java.lang.Object.Wrapper.ClassObject, pclass, false)) { //if (PROFILE_LEVEL > 0) // emitReferenceCast(Object.class, arg); return; } emitReferenceCast(pclass, arg); return; case "I_TYPE": if (!VerifyType.isNullConversion(java.lang.Integer.TYPE, pclass, false)) { emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); } return; } throw new BailoutException(Bailout.PreconditionViolated, "bad implicit conversion: tc=" + ptype + ": " + pclass); }
private void emitPushArgument(Class ptype, object arg) { BasicType bptype = BasicType.basicType(ptype); if (arg is Name) { Name n = (Name)arg; emitLoadInsn(n._type(), n.index()); emitImplicitConversion(n._type(), ptype, n); } else if ((arg == null || arg is string) && bptype == BasicType.L_TYPE) { emitConst(arg); } else { if (Wrapper.isWrapperType(ikvm.extensions.ExtensionMethods.getClass(arg)) && bptype != BasicType.L_TYPE) { emitConst(arg); } else { EmitConstant(arg); emitImplicitConversion(BasicType.L_TYPE, ptype, arg); } } }
/* * NOTE: These load/store methods use the localsMap to find the correct index! */ private void emitLoadInsn(BasicType type, int index) { // [IKVM] we don't need the localsMap (it is used to correct for long/double taking two slots) if (locals[index] == null) { MethodHandleUtil.LoadPackedArg(ilgen, index, 1, packedArgPos, packedArgType); } else { ilgen.Emit(OpCodes.Ldloc, locals[index]); } }
private void emitStoreInsn(BasicType type, int index) { ilgen.Emit(OpCodes.Stloc, locals[index]); }
/** * Emit an implicit conversion for an argument which must be of the given pclass. * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. * * @param ptype type of value present on stack * @param pclass type of value required on stack * @param arg compile-time representation of value on stack (Node, constant) or null if none */ private void emitImplicitConversion(BasicType ptype, Class pclass, object arg) { //assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller if (pclass == ptype.basicTypeClass() && ptype != BasicType.L_TYPE) return; // nothing to do switch (ptype.name()) { case "L_TYPE": if (VerifyType.isNullConversion(CoreClasses.java.lang.Object.Wrapper.ClassObject, pclass, false)) { //if (PROFILE_LEVEL > 0) // emitReferenceCast(Object.class, arg); return; } emitReferenceCast(pclass, arg); return; case "I_TYPE": if (!VerifyType.isNullConversion(java.lang.Integer.TYPE, pclass, false)) emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); return; } throw new BailoutException(Bailout.PreconditionViolated, "bad implicit conversion: tc=" + ptype + ": " + pclass); }
private void emitStoreInsn(BasicType type, int index) { ilgen.Emit(OpCodes.Stloc, locals[index]); }
/* * NOTE: These load/store methods use the localsMap to find the correct index! */ private void emitLoadInsn(BasicType type, int index) { // [IKVM] we don't need the localsMap (it is used to correct for long/double taking two slots) if (locals[index] == null) { MethodHandleUtil.LoadPackedArg(ilgen, index, 1, packedArgPos, packedArgType); } else { ilgen.Emit(OpCodes.Ldloc, locals[index]); } }