public override void ConvertToLIR(LIRMethod pLIRMethod) { Label[] lbls = new Label[TargetIRInstructions.Length]; for (int i = 0; i < lbls.Length; i++) { lbls[i] = TargetIRInstructions[i].Label; } var swDatItem = new SwitchEmittableDataItem(lbls); pLIRMethod.CompileUnit.AddData(swDatItem); // Need to load and compare original value first... var vs = pLIRMethod.RequestLocal(Sources[0].GetTypeOfLocation()); Sources[0].LoadTo(pLIRMethod, vs); var vt = pLIRMethod.RequestLocal(AppDomain.System_Boolean); new LIRInstructions.Compare(pLIRMethod, vs, (LIRImm)0, vt, vs.Type, LIRInstructions.CompareCondition.LessThan); new LIRInstructions.BranchTrue(pLIRMethod, vt, ParentMethod.Instructions[this.IRIndex + 1].Label); new LIRInstructions.Compare(pLIRMethod, vs, (LIRImm)lbls.Length, vt, vs.Type, LIRInstructions.CompareCondition.GreaterThan); new LIRInstructions.BranchTrue(pLIRMethod, vt, ParentMethod.Instructions[this.IRIndex + 1].Label); pLIRMethod.ReleaseLocal(vt); var sBase = pLIRMethod.RequestLocal(AppDomain.System_UIntPtr); new LIRInstructions.Move(pLIRMethod, swDatItem.Label, sBase, AppDomain.System_UIntPtr); new LIRInstructions.Math(pLIRMethod, vs, (LIRImm)VMConfig.PointerSizeForTarget, vs, LIRInstructions.MathOperation.Multiply, vs.Type); new LIRInstructions.Math(pLIRMethod, vs, sBase, sBase, LIRInstructions.MathOperation.Add, sBase.Type); pLIRMethod.ReleaseLocal(vs); new LIRInstructions.Move(pLIRMethod, new Indirect(sBase), sBase, sBase.Type); new LIRInstructions.BranchIndirect(pLIRMethod, sBase); pLIRMethod.ReleaseLocal(sBase); }
public static void EmitStaticConstructorCheck(LIRMethod m, IRType targetType, IRType curType, bool forceEmit = false) { if (targetType.HasStaticConstructor && (forceEmit || targetType != curType)) { var con = targetType.StaticConstructor; if ( ( con.Instructions.Count == 1 && con.Instructions[0].Opcode == IROpcode.Return ) || ( con.Instructions.Count == 2 && con.Instructions[0].Opcode == IROpcode.Nop && con.Instructions[1].Opcode == IROpcode.Return ) ) { // We don't need a static constructor call } else { StaticConstructorCalledEmittableDataItem d = null; if (!KnownStaticConstructors.TryGetValue(targetType, out d)) { d = new StaticConstructorCalledEmittableDataItem(targetType); m.CompileUnit.AddData(d); KnownStaticConstructors.Add(targetType, d); } new LIRInstructions.Comment(m, "Static Constructor Check"); var c = m.RequestLocal(targetType.Assembly.AppDomain.System_Boolean); new LIRInstructions.Move(m, new Indirect(d.Label), c, targetType.Assembly.AppDomain.System_Boolean); Label called = new Label(); new LIRInstructions.BranchTrue(m, c, called); m.ReleaseLocal(c); new LIRInstructions.Move(m, (LIRImm)1, new Indirect(d.Label), targetType.Assembly.AppDomain.System_Boolean); new LIRInstructions.Call(m, con); m.MarkLabel(called); } } }
public override void ConvertToLIR(LIRMethod pLIRMethod) { var src = pLIRMethod.RequestLocal(Sources[0].GetTypeOfLocation()); Sources[0].LoadTo(pLIRMethod, src); var dest = pLIRMethod.RequestLocal(Destination.GetTypeOfLocation()); var canCastResult = pLIRMethod.RequestLocal(ParentMethod.Assembly.AppDomain.System_Boolean); var getTypeByGlobalTypeIDResult = pLIRMethod.RequestLocal(ParentMethod.Assembly.AppDomain.System_Type); // Call to Proton.Runtime.RuntimeHelpers.GetTypeByGlobalTypeID method, which returns the runtime System.Type new LIRInstructions.Call(pLIRMethod, ParentMethod.Assembly.AppDomain.Proton_Runtime_RuntimeHelpers_GetTypeByGlobalTypeID.LIRMethod, new List<ISource>(1) { (LIRImm)Type.GlobalTypeID }, getTypeByGlobalTypeIDResult); // Call to Proton.Runtime.RuntimeHelpers.CanCast method, which determines if an object can be cast to a type // TODO: can src be a value type? if so then we may need to box it first to pass it into this call as an object // TODO: this method should throw an exception if the Type is null, so we can skip testing castType before the call new LIRInstructions.Call(pLIRMethod, ParentMethod.Assembly.AppDomain.Proton_Runtime_RuntimeHelpers_CanCast.LIRMethod, new List<ISource>(2) { src, getTypeByGlobalTypeIDResult }, canCastResult); // Don't need getTypeByGlobalTypeIDResult anymore, we have canCastResult pLIRMethod.ReleaseLocal(getTypeByGlobalTypeIDResult); // Branch if we can cast, fall through if we cannot LIRInstructions.BranchTrue canCastBranchTrue = new LIRInstructions.BranchTrue(pLIRMethod, canCastResult); // Getting here means CanCast returned false, so the emitted code depends on ThrowExceptionOnFailure if (!ThrowExceptionOnFailure) { // If we don't throw an exception, then we are expected to set the destination to it's default value (null, 0, etc) new LIRInstructions.Move(pLIRMethod, dest.Type.Empty, dest, dest.Type); } // Now we jump past the previous BranchTrue logic below LIRInstructions.Branch cannotCastBranchOut = new LIRInstructions.Branch(pLIRMethod); // Getting here means CanCast returned true, so we need to set the BranchTrue target label canCastBranchTrue.SetTarget(new Label()); // And now copy src to dest, based on the destination casted type // TODO: Is it safe to use src here, after it was passed as a source to the Call above? new LIRInstructions.Move(pLIRMethod, src, dest, dest.Type); cannotCastBranchOut.SetTarget(new Label()); // We're done with src now, clean that up pLIRMethod.ReleaseLocal(src); if (!ThrowExceptionOnFailure) { // If we don't throw an exception, then we end up moving null to destination // so we can just do a normal cleanup and store here pLIRMethod.ReleaseLocal(canCastResult); Destination.StoreTo(pLIRMethod, dest); pLIRMethod.ReleaseLocal(dest); } else { // Branch if we can cast, fall through if we cannot canCastBranchTrue = new LIRInstructions.BranchTrue(pLIRMethod, canCastResult); // Getting here means we were not able to cast, so we need to cleanup before we throw an // exception, but we do not store anything to the destination pLIRMethod.ReleaseLocal(canCastResult); pLIRMethod.ReleaseLocal(dest); // TODO: Throw exception here, Branch is here to loop infinite, but this is not valid // it is here only as a placeholder, we need to prepare the object being thrown in a // way that the reference is held until an exception handler has the reference Label loopLabel = new Label(); new LIRInstructions.Comment(pLIRMethod, "TODO: Replace this infinite loop with Throw logic"); new LIRInstructions.Branch(pLIRMethod, loopLabel); // Getting here means we were able to cast, just do a normal cleanup canCastBranchTrue.SetTarget(new Label()); pLIRMethod.ReleaseLocal(canCastResult); Destination.StoreTo(pLIRMethod, dest); pLIRMethod.ReleaseLocal(dest); } // Fall through to next IR instruction if we had a successful cast, or failed without // throwing an exception }
public void MarkLabel(Label l) { l.Index = mInstructions.Count; mInstructions.Add(l); }