public TranslatedSub GetSubroutine(TranslationTier tier, bool isWorthOptimizing) { RegUsage = new RegisterUsage(); RegUsage.BuildUses(_ilBlocks[0]); DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes); long intNiRegsMask = RegUsage.GetIntNotInputs(_ilBlocks[0]); long vecNiRegsMask = RegUsage.GetVecNotInputs(_ilBlocks[0]); TranslatedSub subroutine = new TranslatedSub( method, intNiRegsMask, vecNiRegsMask, tier, isWorthOptimizing); _locals = new Dictionary <Register, int>(); _localsCount = 0; Generator = method.GetILGenerator(); foreach (ILBlock ilBlock in _ilBlocks) { ilBlock.Emit(this); } subroutine.PrepareMethod(); return(subroutine); }
public void Emit(ILMethodBuilder context) { long intInputs = context.RegUsage.GetIntInputs(_block); long vecInputs = context.RegUsage.GetVecInputs(_block); if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete) { intInputs = RegisterUsage.ClearCallerSavedIntRegs(intInputs, context.IsAarch64); vecInputs = RegisterUsage.ClearCallerSavedVecRegs(vecInputs, context.IsAarch64); } LoadLocals(context, intInputs, RegisterType.Int); LoadLocals(context, vecInputs, RegisterType.Vector); }
private void EmitStoreContext(ILGenerator generator, BasicBlock block) { RegisterMask outputs = _regUsage.GetOutputs(block); long intOutputs = outputs.IntMask; long vecOutputs = outputs.VecMask; if (Optimizations.AssumeStrictAbiCompliance && _isComplete) { intOutputs = RegisterUsage.ClearCallerSavedIntRegs(intOutputs, _mode); vecOutputs = RegisterUsage.ClearCallerSavedVecRegs(vecOutputs, _mode); } StoreLocals(generator, intOutputs, RegisterType.Int); StoreLocals(generator, vecOutputs, RegisterType.Vector); }
public void Emit(ILMethodBuilder context) { long intOutputs = context.RegUsage.GetIntOutputs(_block); long vecOutputs = context.RegUsage.GetVecOutputs(_block); if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete) { intOutputs = RegisterUsage.ClearCallerSavedIntRegs(intOutputs, context.IsAarch64); vecOutputs = RegisterUsage.ClearCallerSavedVecRegs(vecOutputs, context.IsAarch64); } if (_callSub != null) { //Those register are assigned on the callee function, without //reading it's value first. We don't need to write them because //they are not going to be read on the callee. intOutputs &= ~_callSub.IntNiRegsMask; vecOutputs &= ~_callSub.VecNiRegsMask; } StoreLocals(context, intOutputs, RegisterType.Int); StoreLocals(context, vecOutputs, RegisterType.Vector); }
public TranslatedSub Build(BasicBlock[] blocks, string name, TranslationTier tier, bool rejit = true) { _regUsage = new RegisterUsage(blocks[0], blocks.Length); DynamicMethod method = new DynamicMethod(name, typeof(long), TranslatedSub.FixedArgTypes); TranslatedSub subroutine = new TranslatedSub(method, tier, rejit); _locals = new Dictionary <Register, int>(); Dictionary <ILLabel, Label> labels = new Dictionary <ILLabel, Label>(); ILGenerator generator = method.GetILGenerator(); Label GetLabel(ILLabel label) { if (!labels.TryGetValue(label, out Label ilLabel)) { ilLabel = generator.DefineLabel(); labels.Add(label, ilLabel); } return(ilLabel); } foreach (BasicBlock block in blocks) { for (int index = 0; index < block.Count; index++) { Operation operation = block.GetOperation(index); switch (operation.Type) { case OperationType.Call: generator.Emit(OpCodes.Call, operation.GetArg <MethodInfo>(0)); break; case OperationType.CallVirtual: generator.Emit(OpCodes.Callvirt, operation.GetArg <MethodInfo>(0)); break; case OperationType.IL: generator.Emit(operation.GetArg <OpCode>(0)); break; case OperationType.ILBranch: generator.Emit(operation.GetArg <OpCode>(0), GetLabel(operation.GetArg <ILLabel>(1))); break; case OperationType.LoadArgument: generator.EmitLdarg(operation.GetArg <int>(0)); break; case OperationType.LoadConstant: EmitLoadConstant(generator, operation.GetArg(0)); break; case OperationType.LoadContext: EmitLoadContext(generator, operation.Parent); break; case OperationType.LoadField: generator.Emit(OpCodes.Ldfld, operation.GetArg <FieldInfo>(0)); break; case OperationType.LoadLocal: EmitLoadLocal( generator, operation.GetArg <int>(0), operation.GetArg <RegisterType>(1), operation.GetArg <RegisterSize>(2)); break; case OperationType.MarkLabel: generator.MarkLabel(GetLabel(operation.GetArg <ILLabel>(0))); break; case OperationType.StoreContext: EmitStoreContext(generator, operation.Parent); break; case OperationType.StoreLocal: EmitStoreLocal( generator, operation.GetArg <int>(0), operation.GetArg <RegisterType>(1), operation.GetArg <RegisterSize>(2)); break; } } } subroutine.PrepareMethod(); return(subroutine); }