/// <summary> /// Compiles the specified IL Library and any dependencies using the ASM Preprocesor and ASM Processor. /// </summary> /// <remarks> /// The ASM Compiler's steps convert the ASM into machine code. /// </remarks> /// <param name="TheILLibrary">The library to compile.</param> /// <returns>CompileResult.OK if all steps complete successfully.</returns> public static CompileResult Compile(IL.ILLibrary TheILLibrary) { CompileResult Result = CompileResult.OK; foreach(IL.ILLibrary depLib in TheILLibrary.Dependencies) { Result = Result == CompileResult.OK ? Compile(depLib) : Result; } Result = Result == CompileResult.OK ? ExecuteASMPreprocessor(TheILLibrary.TheASMLibrary) : Result; if (Result == CompileResult.OK) { Result = ExecuteASMProcessor(TheILLibrary.TheASMLibrary); } return Result; }
/// <summary> /// <para>Called to confirm that the IL emit'd to date can be turned into a delegate without error.</para> /// <para>Checks that the stack is empty, that all paths returns, that all labels are marked, etc. etc.</para> /// </summary> private void Validate() { if (!IsVerifying) { return; } var tracer = new ReturnTracer(Branches, Marks, Returns, Throws); var result = tracer.Verify(); if (!result.IsSuccess) { throw new SigilVerificationException("All execution paths must end with Return", result, IL.Instructions(AllLocals)); } ValidateTryCatchFinallyBlocks(); ValidateTryCatchFinallyBranches(); }
public int CompareTo(IL other) { return(ToStringN().CompareTo(other.ToStringN())); }
public static TextureNode LoadTexture(string FilePath, uint GLTarget, byte ImagePreProcess) { string FilePathShort = FilePathStandardization(FilePath); // Is it already loaded? if (FindTexture(FilePathShort) != null) { return(FindTexture(FilePathShort)); } // Texture not found, load it into the memory else { // Add the current working directory of OpenGLDotNet string currentDirName = System.IO.Directory.GetCurrentDirectory(); string FilePathLong = currentDirName + @"\" + FilePathShort; FilePathLong = FilePathLong.Replace(@"\\", @"\"); // Generate a new image number from DevIL uint ILTextureNumber = IL.GenImage(); IL.BindImage(ILTextureNumber); // Load it into the memory with DevIL if (IL.LoadImage(FilePathLong)) { // Preprocess Check if ((ImagePreProcess & TM_PP_FLIP_IMAGE) > 0) { ILU.FlipImage(); } if ((ImagePreProcess & TM_PP_MIRROR_IMAGE) > 0) { ILU.Mirror(); } // Create a new TextureNode TextureNode Node = new TextureNode(); Node.FilePath = FilePathShort; Node.Width = (uint)IL.GetInteger(IL.IL_IMAGE_WIDTH); Node.Height = (uint)IL.GetInteger(IL.IL_IMAGE_HEIGHT); Node.Depth = (uint)IL.GetInteger(IL.IL_IMAGE_DEPTH); Node.GLImageFormat = (uint)IL.GetInteger(IL.IL_IMAGE_FORMAT); Node.GLImageType = (uint)IL.GetInteger(IL.IL_IMAGE_TYPE); Node.DataSize = (uint)IL.GetInteger(IL.IL_IMAGE_SIZE_OF_DATA); // Generate a new texture number from OpenGL uint[] GLTextureNumber = new uint[1]; GL.GenTextures(1, GLTextureNumber); // Assign the new number to node Node.GLTextureNumber = GLTextureNumber[0]; GL.BindTexture(GLTarget, Node.GLTextureNumber); GL.TexImage2D(GLTarget, 0, (int)Node.GLImageFormat, (int)Node.Width, (int)Node.Height, 0, Node.GLImageFormat, Node.GLImageType, IL.GetData()); GL.TexParameteri(GLTarget, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_CLAMP_TO_EDGE); GL.TexParameteri(GLTarget, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_CLAMP_TO_EDGE); GL.TexParameteri(GLTarget, GL.GL_TEXTURE_WRAP_R, (int)GL.GL_CLAMP_TO_EDGE); GL.TexParameteri(GLTarget, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR); GL.TexParameteri(GLTarget, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR); // We are done uploading the image, free up memory from DevIL IL.DeleteImage(ILTextureNumber); Textures.Add(FilePathShort, Node); return(Node); } // Texture couldn't be loaded, return null else { return(null); } } }
/// <summary> /// Emit the IL to put the current "existing" object on the top of the IL stack. /// </summary> public void EmitLoadExisting() { IL.Emit(OpCodes.Ldloc, existingObjectLocal); }
/// <summary> /// Emit the IL to put the build context on top of the IL stack. /// </summary> public void EmitLoadContext() { IL.Emit(OpCodes.Ldarg_0); }
public static uint NtOpenProcess(ProcessAccessFlags desiredAccess, bool inheritHandle, int processId, out IntPtr handle) { IL.DeclareLocals( new LocalVar("result", typeof(uint)), new LocalVar("localHandle", typeof(IntPtr)), new LocalVar("objectAttributes", typeof(ObjectAttributes)), new LocalVar("clientID", typeof(ClientID))); handle = default; Ldloca("localHandle"); Initobj(typeof(IntPtr)); Ldloca("objectAttributes"); Initobj(typeof(ObjectAttributes)); Ldloca("objectAttributes"); Sizeof(typeof(ObjectAttributes)); Stfld(new FieldRef(typeof(ObjectAttributes), "Length")); Ldloca("objectAttributes"); Ldarg(nameof(inheritHandle)); Brtrue_S("true"); Ldc_I4_0(); Br_S("skip"); IL.MarkLabel("true"); Ldc_I4_2(); IL.MarkLabel("skip"); Stfld(new FieldRef(typeof(ObjectAttributes), "Attributes")); Ldloca("clientID"); Initobj(typeof(ClientID)); Ldloca("clientID"); Ldarg(nameof(processId)); Conv_I(); Stfld(new FieldRef(typeof(ClientID), "UniqueProcess")); Ldloca("localHandle"); Conv_U(); Ldarg(nameof(desiredAccess)); Ldloca("objectAttributes"); Conv_U(); Ldloca("clientID"); Conv_U(); Ldsfld(new FieldRef(typeof(NtDll), nameof(_ntOpenProcess))); Calli(new StandAloneMethodSig( CallingConvention.StdCall, typeof(uint), typeof(IntPtr).MakePointerType(), typeof(ProcessAccessFlags), typeof(ObjectAttributes).MakePointerType(), typeof(ClientID).MakePointerType())); Stloc("result"); Ldarg(nameof(handle)); Ldloc("localHandle"); Stind_I(); Ldloc("result"); return(IL.Return <uint>()); }
public void Bind() { IL.BindImage(this.m_id); }
public void Bind() { IL.BindImage(m_id); }
/**<summary>Patches coin pickup text.</summary>*/ private static void Patch_ItemText_NewText() { string functionName = "Terraria.ItemText.NewText"; var newText = IL.GetMethodDefinition(ItemText, "NewText", 4); var onCoinPickupText = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnCoinPickupText")); var onCoinPickupText2 = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnCoinPickupText2")); var checks = new IL.OperandCheck[] { IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Brfalse), IL.CheckField(OpCodes.Ldsfld, "Main::itemText"), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "ItemText::coinText"), IL.Check(OpCodes.Brfalse) }; int start = IL.ScanForNthInstructionPatternEnd(newText, 1, checks); CheckFailedToFindStart(start, 0, functionName); var i = IL.ScanForNthVariablePattern(newText, 1, checks); CheckFailedToFindVariable(i, "i", functionName); var vector = IL.ScanForVariablePattern(newText, start, IL.CheckField(OpCodes.Ldsfld, "Main::fontMouseText"), IL.Check(LocOpCodes.Ldloc), IL.CheckMethod(OpCodes.Callvirt, "DynamicSpriteFont::MeasureString"), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(vector, "vector", functionName); int end = IL.ScanForInstructionPatternEnd(newText, start, IL.Check(OpCodes.Ldc_I4, (int)246), IL.Check(OpCodes.Ldc_I4, (int)138), IL.Check(OpCodes.Ldc_I4_S, (sbyte)96), IL.Check(OpCodes.Newobj), IL.Check(OpCodes.Stfld) ); CheckFailedToFindEnd(end, 0, functionName); IL.MethodReplaceRange(newText, start, end, Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Ldloc_S, i), Instruction.Create(OpCodes.Call, onCoinPickupText), Instruction.Create(OpCodes.Stloc_S, vector) ); checks = new IL.OperandCheck[] { IL.CheckField(OpCodes.Ldsfld, "Main::itemText"), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "ItemText::coinText"), IL.Check(OpCodes.Brfalse) }; start = IL.ScanForInstructionPatternEnd(newText, end + 5, checks); CheckFailedToFindStart(start, 1, functionName); var num2 = IL.ScanForVariablePattern(newText, end + 5, checks); CheckFailedToFindVariable(num2, "num2", functionName); end = IL.ScanForInstructionPatternEnd(newText, start, IL.Check(OpCodes.Ldc_I4, (int)246), IL.Check(OpCodes.Ldc_I4, (int)138), IL.Check(OpCodes.Ldc_I4_S, (sbyte)96), IL.Check(OpCodes.Newobj), IL.Check(OpCodes.Stfld) ); CheckFailedToFindEnd(end, 1, functionName); IL.MethodReplaceRange(newText, start, end, Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Ldloc_S, num2), Instruction.Create(OpCodes.Call, onCoinPickupText2) ); }
/**<summary>Patches store buy and sell price text.</summary>*/ private static void Patch_Main_MouseText_DrawItemTooltip() { string functionName = "Terraria.Main.MouseText_DrawItemTooltip"; var mouseText_DrawItemTooltip = IL.GetMethodDefinition(Main, "MouseText_DrawItemTooltip", 4); var onNPCShopPrice = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnNPCShopPrice")); var storeValue = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, IL.CheckField(OpCodes.Ldsfld, "Main::npcShop"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble), IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckMethod(OpCodes.Callvirt, "Item::GetStoreValue"), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(storeValue, "storeValue", functionName); int start = IL.ScanForInstructionPatternEnd(mouseText_DrawItemTooltip, IL.Check(OpCodes.Ldsfld), IL.CheckMethod(OpCodes.Callvirt, "Item::GetStoreValue"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble) ); CheckFailedToFindStart(start, 0, functionName); var array = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckField(OpCodes.Ldfld, "Item::buy"), IL.Check(OpCodes.Brtrue_S), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldsfld, "Lang::tip") ); CheckFailedToFindVariable(array, "array", functionName); var num4 = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckField(OpCodes.Ldfld, "Item::buy"), IL.Check(OpCodes.Brtrue_S), IL.Check(LocOpCodes.Ldloc), IL.VarCheck(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldsfld, "Lang::tip") ); CheckFailedToFindVariable(num4, "num4", functionName); var array4 = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.VarCheck(LocOpCodes.Ldloc), IL.Check(LocOpCodes.Ldloc, num4), IL.Check(OpCodes.Ldstr, "Price"), IL.Check(OpCodes.Stelem_Ref) ); if (IsTMod) { CheckFailedToFindVariable(array4, "array4", functionName); } var checks = new IL.OperandCheck[] { IL.VarCheck(LocOpCodes.Ldloca), IL.Check(OpCodes.Ldc_R4, 246f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(OpCodes.Ldc_R4, 138f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(OpCodes.Ldc_R4, 96f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(LocOpCodes.Ldloc), IL.CheckMethod(OpCodes.Call, "Color::.ctor") }; var color = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, checks); CheckFailedToFindVariable(color, "color", functionName); int end = IL.ScanForInstructionPatternEnd(mouseText_DrawItemTooltip, start, checks); CheckFailedToFindEnd(end, 0, functionName); start = IL.MethodReplaceRange(mouseText_DrawItemTooltip, start, end, Instruction.Create(OpCodes.Ldloc_S, color), Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldloc_S, array), Instruction.Create(OpCodes.Ldloc_S, storeValue), Instruction.Create(OpCodes.Call, onNPCShopPrice), Instruction.Create(OpCodes.Stloc_S, color) ); if (IsTMod) { start = IL.MethodInsert(mouseText_DrawItemTooltip, start, Instruction.Create(OpCodes.Ldloc_S, array4), Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldstr, "Price"), Instruction.Create(OpCodes.Stelem_Ref) ); } IL.MethodInsert(mouseText_DrawItemTooltip, start, Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldc_I4_1), Instruction.Create(OpCodes.Add), Instruction.Create(OpCodes.Stloc_S, num4) ); }
/**<summary>Patches heal cost tax collect text.</summary>*/ private static void Patch_Main_GUIChatDrawInner() { string functionName = "Terraria.Main.GUIChatDrawInner"; var guiChatDrawInner = IL.GetMethodDefinition(Main, "GUIChatDrawInner", 0); var onTaxCollect = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnTaxCollect")); var onNurseHeal = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnNurseHeal")); var focusText = IL.ScanForVariablePattern(guiChatDrawInner, IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::sign"), IL.Check(OpCodes.Ldc_I4_M1), IL.Check(OpCodes.Ble_S), IL.CheckField(OpCodes.Ldsfld, "Main::editSign"), IL.Check(OpCodes.Brfalse_S), IL.CheckField(OpCodes.Ldsfld, "Lang::inter"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)47), IL.Check(OpCodes.Ldelem_Ref), IL.CheckMethod(OpCodes.Callvirt, "LocalizedText::get_Value"), IL.VarCheck(LocOpCodes.Stloc), IL.Check(OpCodes.Br), IL.CheckField(OpCodes.Ldsfld, "Lang::inter"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)48), IL.Check(OpCodes.Ldelem_Ref), IL.CheckMethod(OpCodes.Callvirt, "LocalizedText::get_Value"), IL.VarCheck(LocOpCodes.Stloc), IL.Check(OpCodes.Br) ); CheckFailedToFindVariable(focusText, "focusText", functionName); var color2 = IL.ScanForVariablePattern(guiChatDrawInner, IL.CheckField(OpCodes.Ldsfld, "Main::mouseTextColor"), IL.Check(OpCodes.Ldc_I4_2), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Ldc_I4, (int)255), IL.Check(OpCodes.Add), IL.Check(OpCodes.Ldc_I4_3), IL.Check(OpCodes.Div), IL.Check(LocOpCodes.Stloc), IL.VarCheck(LocOpCodes.Ldloca), IL.Check(LocOpCodes.Ldloc), IL.CheckRepeat(3), IL.CheckMethod(OpCodes.Call, "Color::.ctor") ); CheckFailedToFindVariable(color2, "color2", functionName); var num6 = IL.ScanForVariablePattern(guiChatDrawInner, IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::statLifeMax2"), IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::statLife"), IL.Check(OpCodes.Sub), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(num6, "num6", functionName); int start = IL.ScanForInstructionPatternEnd(guiChatDrawInner, IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::taxMoney"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Bgt_S), IL.CheckField(OpCodes.Ldsfld, "Lang::inter"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)89), IL.Check(OpCodes.Ldelem_Ref), IL.CheckMethod(OpCodes.Callvirt, "LocalizedText::get_Value"), IL.Check(LocOpCodes.Stloc, focusText), IL.Check(OpCodes.Br) ); CheckFailedToFindStart(start, 0, functionName); int end = IL.ScanForInstructionPatternEnd(guiChatDrawInner, start, IL.CheckField(OpCodes.Ldsfld, "Lang::inter"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)89), IL.Check(OpCodes.Ldelem_Ref), IL.CheckMethod(OpCodes.Callvirt, "LocalizedText::get_Value"), IL.Check(OpCodes.Ldstr, " ("), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldstr, ")"), IL.CheckMethod(OpCodes.Call, "String::Concat"), IL.Check(LocOpCodes.Stloc, focusText) ); CheckFailedToFindEnd(end, 0, functionName); end = IL.MethodReplaceRange(guiChatDrawInner, start, end, Instruction.Create(OpCodes.Ldloca_S, focusText), Instruction.Create(OpCodes.Ldloca_S, color2), Instruction.Create(OpCodes.Ldloca_S, num6), Instruction.Create(OpCodes.Call, onTaxCollect) ); start = IL.ScanForInstructionPatternEnd(guiChatDrawInner, end, IL.CheckField(OpCodes.Ldsfld, "Main::npc"), IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::talkNPC"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "NPC::type"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)18), IL.Check(OpCodes.Bne_Un) ); CheckFailedToFindStart(start, 1, functionName); end = IL.ScanForInstructionPatternEnd(guiChatDrawInner, start, IL.CheckField(OpCodes.Ldsfld, "Lang::inter"), IL.Check(OpCodes.Ldc_I4_S, (sbyte)54), IL.Check(OpCodes.Ldelem_Ref), IL.CheckMethod(OpCodes.Callvirt, "LocalizedText::get_Value"), IL.Check(OpCodes.Ldstr, " ("), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldstr, ")"), IL.CheckMethod(OpCodes.Call, "String::Concat"), IL.Check(LocOpCodes.Stloc, focusText) ); CheckFailedToFindEnd(end, 1, functionName); IL.MethodReplaceRange(guiChatDrawInner, start, end, Instruction.Create(OpCodes.Ldloca_S, focusText), Instruction.Create(OpCodes.Ldloca_S, color2), Instruction.Create(OpCodes.Ldloca_S, num6), Instruction.Create(OpCodes.Call, onNurseHeal) ); }
//-------------------------------- #region Patchers /**<summary>Patches reforge cost text.</summary>*/ private static void Patch_Main_DrawInventory() { string functionName = "Terraria.Main.DrawInventory"; var drawInventory = IL.GetMethodDefinition(Main, "DrawInventory", 0); var onReforgeCost = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnReforgeCost")); var checks = new IL.OperandCheck[] { IL.CheckField(OpCodes.Ldsfld, "Main::reforgeItem"), IL.CheckField(OpCodes.Ldfld, "Item::type"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble), IL.CheckSkipIndefinite(), // TMod fix IL.CheckField(OpCodes.Ldsfld, "Main::reforgeItem"), IL.CheckField(OpCodes.Ldfld, "Item::value"), IL.VarCheck(LocOpCodes.Stloc), IL.CheckSkipIndefinite(), IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::discount"), IL.Check(OpCodes.Brfalse_S), IL.CheckSkipIndefinite(), IL.VarCheck(LocOpCodes.Stloc), IL.Check(OpCodes.Ldstr, ""), IL.Check(LocOpCodes.Stloc) }; int start = IL.ScanForInstructionPatternEnd(drawInventory, checks); CheckFailedToFindStart(start, 0, functionName); var num60 = IL.ScanForVariablePattern(drawInventory, checks); CheckFailedToFindVariable(num60, "num60", functionName); var text3 = IL.ScanForVariablePattern(drawInventory, start - 2, IL.Check(OpCodes.Ldstr, ""), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(text3, "text3", functionName); int end = IL.ScanForInstructionPattern(drawInventory, start, IL.CheckField(OpCodes.Ldsfld, "Main::spriteBatch"), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldc_I4, 130), IL.Check(OpCodes.Add), IL.Check(OpCodes.Conv_R4), IL.Check(OpCodes.Ldarg_0), IL.CheckField(OpCodes.Ldfld, "Main::invBottom"), IL.Check(OpCodes.Conv_R4), IL.Check(OpCodes.Ldc_I4_1), IL.CheckMethod(OpCodes.Call, "ItemSlot::DrawSavings") ); CheckFailedToFindEnd(end, 0, functionName); IL.MethodReplaceRange(drawInventory, start, end, Instruction.Create(OpCodes.Ldloc_S, num60), Instruction.Create(OpCodes.Call, onReforgeCost), Instruction.Create(OpCodes.Stloc_S, text3) ); }
private void ValidateTryCatchFinallyBranches() { foreach (var branch in Branches.AsEnumerable()) { var instr = BranchPatches[branch.Item3]; var toLabel = branch.Item2; var fromIndex = branch.Item3; var toIndex = Marks[toLabel]; var fromTryBlocks = TryBlocks.Where(t => fromIndex >= t.Value.Item1 && fromIndex <= t.Value.Item2).ToList(); var fromCatchBlocks = CatchBlocks.Where(c => fromIndex >= c.Value.Item1 && fromIndex <= c.Value.Item2).ToList(); var fromFinallyBlocks = FinallyBlocks.Where(f => fromIndex >= f.Value.Item1 && fromIndex <= f.Value.Item2).ToList(); var toTryBlocks = TryBlocks.Where(t => toIndex >= t.Value.Item1 && toIndex <= t.Value.Item2).ToList(); var toCatchBlocks = CatchBlocks.Where(c => toIndex >= c.Value.Item1 && toIndex <= c.Value.Item2).ToList(); var toFinallyBlocks = FinallyBlocks.Where(f => toIndex >= f.Value.Item1 && toIndex <= f.Value.Item2).ToList(); var fromTryBlock = fromTryBlocks.OrderByDescending(t => t.Value.Item1).Select(t => t.Key).FirstOrDefault(); var fromCatchBlock = fromCatchBlocks.OrderByDescending(c => c.Value.Item1).Select(c => c.Key).FirstOrDefault(); var fromFinallyBlock = fromFinallyBlocks.OrderByDescending(f => f.Value.Item1).Select(f => f.Key).FirstOrDefault(); var toTryBlock = toTryBlocks.OrderByDescending(t => t.Value.Item1).Select(t => t.Key).FirstOrDefault(); var toCatchBlock = toCatchBlocks.OrderByDescending(c => c.Value.Item1).Select(c => c.Key).FirstOrDefault(); var toFinallyBlock = toFinallyBlocks.OrderByDescending(f => f.Value.Item1).Select(f => f.Key).FirstOrDefault(); // Nothing funky going on, carry on if (fromTryBlock == null && fromCatchBlock == null && fromFinallyBlock == null && toTryBlock == null && toCatchBlock == null && toFinallyBlock == null) { continue; } if (fromCatchBlock != null && toCatchBlock != fromCatchBlock) { if (instr.Item3 != OpCodes.Leave) { throw new SigilVerificationException( "Cannot branch from inside " + fromCatchBlock + " to outside, exit the ExceptionBlock first", IL.Instructions(AllLocals) ); } } if (fromFinallyBlock != null && toFinallyBlock != fromFinallyBlock) { throw new SigilVerificationException( "Cannot branch from inside " + fromFinallyBlock + " to outside, exit the ExceptionBlock first", IL.Instructions(AllLocals) ); } if (toFinallyBlock != null && fromFinallyBlock != toFinallyBlock) { throw new SigilVerificationException( "Cannot branch into a FinallyBlock", IL.Instructions(AllLocals) ); } if (fromTryBlock != null && toTryBlock != fromTryBlock) { if (instr.Item3 != OpCodes.Leave) { throw new SigilVerificationException( "Cannot branch from inside " + fromTryBlock + " to outside, exit the ExceptionBlock first", IL.Instructions(AllLocals) ); } } } }
public void WithRequiredModifier() { IL.DeclareLocals( new LocalVar(new TypeRef(typeof(int)).WithRequiredModifier(typeof(IsConst))) ); }
private void FailStackUnderflow(int expected, string method) { if (expected == 1) { throw new SigilVerificationException(method + " expects a value on the stack, but it was empty", IL.Instructions(AllLocals)); } throw new SigilVerificationException(method + " expects " + expected + " values on the stack", IL.Instructions(AllLocals)); }
public void TypedReference() { IL.DeclareLocals( new LocalVar(typeof(TypedReference)) ); }
public static ulong ToUInt64 <T>(T value) { Ldarg(nameof(value)); Conv_I8(); return(IL.Return <ulong>()); }
private void EmitBranchOp(bool branch, Label label) { IL.Emit(branch ? OpCodes.Brtrue : OpCodes.Brfalse, label); }
/// <summary> /// <para>Declare a new local of the given type in the current method.</para> /// <para> /// Name is optional, and only provided for debugging purposes. It has no /// effect on emitted IL. /// </para> /// <para> /// Be aware that each local takes some space on the stack, inefficient use of locals /// could lead to StackOverflowExceptions at runtime. /// </para> /// <para> /// Jil will reuse local index on the stack if the corresponding Local instance has been disposed. /// By default Jil will set reused locals to their default value, you can change this behavior /// by passing initializeReused = false. /// </para> /// </summary> public Local DeclareLocal(Type type, string name = null, bool initializeReused = true) { if (type == null) { throw new ArgumentNullException("type"); } name = name ?? AutoNamer.Next(this, "_local", Locals.Names, Labels.Names); if (CurrentLocals.ContainsKey(name)) { throw new InvalidOperationException("Local with name '" + name + "' already exists"); } var existingLocal = FreedLocals.FirstOrDefault(l => l.LocalType == type); DeclareLocallDelegate local; ushort localIndex; if (existingLocal == null) { local = IL.DeclareLocal(type); localIndex = NextLocalIndex; NextLocalIndex++; } else { local = existingLocal.LocalDel; localIndex = existingLocal.Index; FreedLocals.Remove(existingLocal); } var ret = new Local(this, localIndex, type, local, name, LocalReleased, IL.Index); UnusedLocals.Add(ret); AllLocals.Add(ret); CurrentLocals[ret.Name] = ret; // we need to initialize this local to it's default value, because otherwise // it might be read from to get some non-sense if (existingLocal != null && initializeReused) { if (!TypeHelpers.IsValueType(type)) { // reference types all get nulled LoadNull(); StoreLocal(ret); } else { // handle known primitives better // so as not to confuse the JIT var defaultLoaded = false; if (type == typeof(bool)) { LoadConstant(default(bool)); defaultLoaded = true; } if (type == typeof(byte)) { LoadConstant(default(byte)); defaultLoaded = true; } if (type == typeof(sbyte)) { LoadConstant(default(sbyte)); defaultLoaded = true; } if (type == typeof(short)) { LoadConstant(default(short)); defaultLoaded = true; } if (type == typeof(ushort)) { LoadConstant(default(ushort)); defaultLoaded = true; } if (type == typeof(int)) { LoadConstant(default(int)); defaultLoaded = true; } if (type == typeof(uint)) { LoadConstant(default(uint)); defaultLoaded = true; } if (type == typeof(long)) { LoadConstant(default(long)); defaultLoaded = true; } if (type == typeof(ulong)) { LoadConstant(default(ulong)); defaultLoaded = true; } if (type == typeof(float)) { LoadConstant(default(float)); defaultLoaded = true; } if (type == typeof(double)) { LoadConstant(default(double)); defaultLoaded = true; } if (defaultLoaded) { StoreLocal(ret); } else { // if it's use defined though, we've got little choice LoadLocalAddress(ret); InitializeObject(type); } } } return(ret); }
private void EmitNullableCoalesce(BinaryExpression b) { Debug.Assert(b.Method == null); var loc = GetLocal(b.Left.Type); var labIfNull = IL.DefineLabel(); var labEnd = IL.DefineLabel(); EmitExpression(b.Left); IL.Emit(OpCodes.Stloc, loc); IL.Emit(OpCodes.Ldloca, loc); IL.EmitHasValue(b.Left.Type); IL.Emit(OpCodes.Brfalse, labIfNull); var nnLeftType = b.Left.Type.GetNonNullable(); if (b.Conversion != null) { Debug.Assert(b.Conversion.ParameterCount == 1); var p = b.Conversion.GetParameter(0); Debug.Assert(p.Type.IsAssignableFrom(b.Left.Type) || p.Type.IsAssignableFrom(nnLeftType)); // emit the delegate instance EmitLambdaExpression(b.Conversion); // emit argument if (!p.Type.IsAssignableFrom(b.Left.Type)) { IL.Emit(OpCodes.Ldloca, loc); IL.EmitGetValueOrDefault(b.Left.Type); } else { IL.Emit(OpCodes.Ldloc, loc); } // emit call to invoke IL.Emit(OpCodes.Callvirt, b.Conversion.Type.GetInvokeMethod()); } else if (TypeUtils.AreEquivalent(b.Type, b.Left.Type)) { IL.Emit(OpCodes.Ldloc, loc); } else { IL.Emit(OpCodes.Ldloca, loc); IL.EmitGetValueOrDefault(b.Left.Type); if (!TypeUtils.AreEquivalent(b.Type, nnLeftType)) { IL.EmitConvertToType(nnLeftType, b.Type, true, this); } } FreeLocal(loc); IL.Emit(OpCodes.Br, labEnd); IL.MarkLabel(labIfNull); EmitExpression(b.Right); if (!TypeUtils.AreEquivalent(b.Right.Type, b.Type)) { IL.EmitConvertToType(b.Right.Type, b.Type, true, this); } IL.MarkLabel(labEnd); }
/// <summary> /// Emit the IL to put the current build key on top of the IL stack. /// </summary> public void EmitLoadBuildKey() { EmitLoadContext(); IL.EmitCall(OpCodes.Callvirt, GetBuildKey, null); }
/// <summary> /// Emit the IL to make the top of the IL stack our current "existing" object. /// </summary> public void EmitStoreExisting() { IL.Emit(OpCodes.Stloc, existingObjectLocal); }
public override bool LinkISO(IL.ILLibrary TheLibrary, LinkInformation LinkInfo) { bool OK = true; string BinPath = LinkInfo.ISOPath.Replace(".iso", ".bin"); string ElfPath = LinkInfo.ISOPath.Replace(".iso", ".elf"); StreamWriter ASMWriter = new StreamWriter(LinkInfo.ASMPath, false); StringBuilder CommandLineArgsBuilder = new StringBuilder(); CommandLineArgsBuilder.Append("--fatal-warnings -EL -Os -T \"" + LinkInfo.LinkScriptPath + "\" -o \"" + ElfPath + "\""); StringBuilder LinkScript = new StringBuilder(); LinkScript.Append(@"ENTRY(Kernel_Start) OUTPUT_ARCH(mips) SECTIONS { . = 0x" + Options.BaseAddress.ToString("X8") + @"; .text : AT(ADDR(.text) - " + Options.LoadOffset.ToString() + @") { "); for (int i = 0; i < LinkInfo.SequencedASMBlocks.Count; i++) { LinkScript.AppendLine(string.Format(" \"{0}\" (.text);", LinkInfo.SequencedASMBlocks[i].ObjectOutputFilePath)); ASMWriter.WriteLine(File.ReadAllText(LinkInfo.SequencedASMBlocks[i].ASMOutputFilePath)); } LinkScript.AppendLine(@" * (.text); } . = ALIGN(0x4); .data : AT(ADDR(.data) - " + Options.LoadOffset.ToString() + @") { * (.data*); } . = ALIGN(0x4); .bss : AT(ADDR(.bss) - " + Options.LoadOffset.ToString() + @") { * (.bss*); } } "); ASMWriter.Close(); File.WriteAllText(LinkInfo.LinkScriptPath, LinkScript.ToString()); OK = Utilities.ExecuteProcess(LinkInfo.LdWorkingDir, Path.Combine(LinkInfo.ToolsPath, @"MIPS\mips-linux-gnu-ld.exe"), CommandLineArgsBuilder.ToString(), "Ld"); if (OK) { if (File.Exists(BinPath)) { File.Delete(BinPath); } OK = Utilities.ExecuteProcess(Options.OutputPath, Path.Combine(LinkInfo.ToolsPath, @"MIPS\mips-linux-gnu-objcopy.exe"), string.Format("-O binary \"{0}\" \"{1}\"", ElfPath, BinPath), "MIPS:ObjCopy"); if (OK) { if (File.Exists(LinkInfo.MapPath)) { File.Delete(LinkInfo.MapPath); } OK = Utilities.ExecuteProcess(Options.OutputPath, Path.Combine(LinkInfo.ToolsPath, @"MIPS\mips-linux-gnu-objdump.exe"), string.Format("--wide --syms \"{0}\"", ElfPath), "MIPS:ObjDump", false, LinkInfo.MapPath); } } return OK; }
public static T Read <T>(void *source) { Ldarg(nameof(source)); Ldobj(typeof(T)); return(IL.Return <T>()); }
public static int SizeOf <T>() { Sizeof(typeof(T)); return(IL.Return <int>()); }
public static T As <T>(object o) where T : class { Ldarg(nameof(o)); return(IL.Return <T>()); }
public static void SkipInit <T>(out T value) { Ret(); throw IL.Unreachable(); }
public static void *AsPointer <T>(ref T value) { Ldarg(nameof(value)); Conv_U(); return(IL.ReturnPointer()); }
/// <summary> /// Emit the IL needed to clear the <see cref="IBuilderContext.CurrentOperation"/>. /// </summary> public void EmitClearCurrentOperation() { EmitLoadContext(); IL.EmitCall(OpCodes.Call, ClearCurrentOperation, null); }
public void InvalidUnreachable() { IL.Unreachable(); }
public static object Construct(Type t, object[] Params) { IL code; if (!_cache.ContainsKey(t)) _cache.Add(t, code = new IL(t)); else code = _cache[t]; return code.GetConstructorInvoker(Params)(Params); }
/// <summary> /// Construct an operand from a value. /// </summary> /// <param name="x">The operand value.</param> public Operand(IL.Label x) : this() { this.Label = x; }
public override bool LinkELF(IL.ILLibrary TheLibrary, LinkInformation LinkInfo) { StringBuilder CommandLineArgsBuilder = new StringBuilder(); if (!LinkInfo.ExecutableOutput) { CommandLineArgsBuilder.Append("-shared "); } CommandLineArgsBuilder.Append("-L .\\Output -T \"" + LinkInfo.LinkScriptPath + "\" -o \"" + LinkInfo.BinPath + "\""); StreamWriter ASMWriter = new StreamWriter(LinkInfo.ASMPath, false); StringBuilder LinkScript = new StringBuilder(); LinkScript.Append((LinkInfo.ExecutableOutput ? "ENTRY(" + LinkInfo.EntryPoint + ")\r\n" : "") + @"GROUP("); LinkScript.Append(string.Join(" ", LinkInfo.SequencedASMBlocks .Where(x => File.Exists(x.OutputFilePath)) .Select(x => "\"" + x.OutputFilePath + "\""))); LinkScript.Append(@") "); if (LinkInfo.depLibNames.Count > 0) { LinkScript.Append("GROUP("); LinkScript.Append(string.Join(" ", LinkInfo.depLibNames.Select(x => "-l" + x))); LinkScript.Append(")"); } LinkScript.AppendLine(@" SECTIONS { . = 0x" + (0x40000000 + (LinkInfo.depLibNames.Count * 0x1000)).ToString("X2") + @"; .text : { "); for (int i = 0; i < LinkInfo.SequencedASMBlocks.Count; i++) { LinkScript.AppendLine(string.Format(" \"{0}\" (.text);", LinkInfo.SequencedASMBlocks[i].OutputFilePath)); ASMWriter.WriteLine(File.ReadAllText(LinkInfo.SequencedASMBlocks[i].OutputFilePath.Replace("\\Objects", "\\ASM").Replace(".o", ".s"))); } LinkScript.AppendLine(@" * (.text); * (.rodata*); } . = ALIGN(0x1000); .data : AT(ADDR(.data)) { * (.data*); } . = ALIGN(0x1000); .bss : AT(ADDR(.bss)) { * (.bss*); } } "); ASMWriter.Close(); File.WriteAllText(LinkInfo.LinkScriptCmdPath, CommandLineArgsBuilder.ToString()); File.WriteAllText(LinkInfo.LinkScriptPath, LinkScript.ToString()); return Utilities.ExecuteProcess(LinkInfo.LdWorkingDir, Path.Combine(LinkInfo.ToolsPath, @"Cygwin\ld.exe"), CommandLineArgsBuilder.ToString(), "Ld"); }
public override bool LinkELF(IL.ILLibrary TheLibrary, LinkInformation LinkInfo) { return false; }
public static void SaveLibraryInfo(string FolderPath, IL.ILLibrary TheLibrary) { string RootAssemblyName = Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name); using (StreamWriter Str = new StreamWriter(Path.Combine(FolderPath, RootAssemblyName + "_Dependencies.txt"), false)) { foreach (IL.ILLibrary DependencyLibrary in TheLibrary.Dependencies) { Str.WriteLine(Utilities.CleanFileName(DependencyLibrary.TheAssembly.GetName().Name)); } } using (StreamWriter Str = new StreamWriter(Path.Combine(FolderPath, RootAssemblyName + "_Library.txt"), false)) { foreach (Types.TypeInfo ATypeInfo in TheLibrary.TypeInfos) { //TypeID //¬BaseTypeID:[ID] //¬IsGCManaged:[Boolean] //¬IsPointer:[Boolean] //¬IsValueType:[Boolean] //¬SizeOnHeapInBytes:[Integer] //¬SizeOnStackInBytes:[Integer] //|Field:[ID] //~Type:[TypeID] //~IsStatic:[Boolean] //~Name:[String] //~OffsetInBytes:[Integer] //|Method:[ID] //~ApplyDebug:[Boolean] //~ApplyGC:[Boolean] //~IDValue:[Integer] //~IsConstructor:[Boolean] //~IsPlugged:[Boolean] //~IsStatic:[Boolean] //~Signature:[String] //~Argument:Offset|Position|TypeID //~Local:Offset|Position|TypeID Str.WriteLine(ATypeInfo.ID); if (ATypeInfo.UnderlyingType.BaseType != null && !ATypeInfo.UnderlyingType.BaseType.AssemblyQualifiedName.Contains("mscorlib")) { Str.WriteLine("¬BaseTypeID:" + TheLibrary.GetTypeInfo(ATypeInfo.UnderlyingType.BaseType).ID); } Str.WriteLine("¬IsGCManaged:" + ATypeInfo.IsGCManaged.ToString()); Str.WriteLine("¬IsPointer:" + ATypeInfo.IsPointer.ToString()); Str.WriteLine("¬IsValueType:" + ATypeInfo.IsValueType.ToString()); Str.WriteLine("¬SizeOnHeapInBytes:" + ATypeInfo.SizeOnHeapInBytes.ToString()); Str.WriteLine("¬SizeOnStackInBytes:" + ATypeInfo.SizeOnStackInBytes.ToString()); foreach (Types.FieldInfo AFieldInfo in ATypeInfo.FieldInfos) { Str.WriteLine("|Field:" + AFieldInfo.ID); Str.WriteLine("~Type:" + TheLibrary.GetTypeInfo(AFieldInfo.FieldType).ID); Str.WriteLine("~IsStatic:" + AFieldInfo.IsStatic.ToString()); Str.WriteLine("~Name:" + AFieldInfo.Name); Str.WriteLine("~OffsetInBytes:" + AFieldInfo.OffsetInBytes.ToString()); } foreach (Types.MethodInfo AMethodInfo in ATypeInfo.MethodInfos) { Str.WriteLine("|Method:" + AMethodInfo.ID); Str.WriteLine("~ApplyDebug:" + AMethodInfo.ApplyDebug.ToString()); Str.WriteLine("~ApplyGC:" + AMethodInfo.ApplyGC.ToString()); Str.WriteLine("~IDValue:" + AMethodInfo.IDValue.ToString()); Str.WriteLine("~IsConstructor:" + AMethodInfo.IsConstructor.ToString()); Str.WriteLine("~IsPlugged:" + AMethodInfo.IsPlugged.ToString()); Str.WriteLine("~IsStatic:" + AMethodInfo.IsStatic.ToString()); Str.WriteLine("~Signature:" + AMethodInfo.Signature); Type RetType = (AMethodInfo.IsConstructor ? typeof(void) : ((System.Reflection.MethodInfo)AMethodInfo.UnderlyingInfo).ReturnType); Str.WriteLine("~ReturnSize:" + Types.TypeScanner.GetSizeOnStackInBytes(RetType)); foreach (Types.VariableInfo AnArgumentInfo in AMethodInfo.ArgumentInfos) { Str.WriteLine("~Argument:" + AnArgumentInfo.Offset.ToString() + "|" + AnArgumentInfo.Position.ToString() + "|" + AnArgumentInfo.TheTypeInfo.ID); } foreach (Types.VariableInfo ALocalInfo in AMethodInfo.LocalInfos) { Str.WriteLine("~Local:" + ALocalInfo.Offset.ToString() + "|" + ALocalInfo.Position.ToString() + "|" + ALocalInfo.TheTypeInfo.ID); } } } } }
public override bool LinkISO(IL.ILLibrary TheLibrary, LinkInformation LinkInfo) { bool OK = true; StreamWriter ASMWriter = new StreamWriter(LinkInfo.ASMPath, false); StringBuilder CommandLineArgsBuilder = new StringBuilder(); CommandLineArgsBuilder.Append("--fatal-warnings -T \"" + LinkInfo.LinkScriptPath + "\" -o \"" + LinkInfo.BinPath + "\""); StringBuilder LinkScript = new StringBuilder(); LinkScript.Append(@"ENTRY(Kernel_Start) OUTPUT_FORMAT(elf32-i386) GROUP("); LinkScript.Append(string.Join(" ", LinkInfo.SequencedASMBlocks .Where(x => File.Exists(x.OutputFilePath)) .Select(x => "\"" + x.OutputFilePath + "\""))); LinkScript.AppendLine(@") SECTIONS { /* The kernel will live at 3GB + 1MB in the virtual address space, which will be mapped to 1MB in the physical address space. */ . = 0x" + Options.BaseAddress.ToString("X8") + @"; .text : AT(ADDR(.text) - " + Options.LoadOffset.ToString() + @") { "); for (int i = 0; i < LinkInfo.SequencedASMBlocks.Count; i++) { LinkScript.AppendLine(string.Format(" \"{0}\" (.text);", LinkInfo.SequencedASMBlocks[i].OutputFilePath)); ASMWriter.WriteLine(File.ReadAllText(LinkInfo.SequencedASMBlocks[i].OutputFilePath.Replace("\\Objects", "\\ASM").Replace(".o", ".s"))); } LinkScript.AppendLine(@" * (.text); * (.rodata*); } . = ALIGN(0x1000); .data : AT(ADDR(.data) - " + Options.LoadOffset.ToString() + @") { * (.data*); } . = ALIGN(0x1000); .bss : AT(ADDR(.bss) - " + Options.LoadOffset.ToString() + @") { * (.bss*); } } "); ASMWriter.Close(); File.WriteAllText(LinkInfo.LinkScriptPath, LinkScript.ToString()); OK = Utilities.ExecuteProcess(LinkInfo.LdWorkingDir, Path.Combine(LinkInfo.ToolsPath, @"Cygwin\ld.exe"), CommandLineArgsBuilder.ToString(), "Ld"); if (OK) { if (File.Exists(LinkInfo.ISOPath)) { File.Delete(LinkInfo.ISOPath); } OK = Utilities.ExecuteProcess(Options.OutputPath, LinkInfo.ISOGenPath, string.Format("4 \"{0}\" \"{1}\" true \"{2}\"", LinkInfo.ISOPath, LinkInfo.ISOLinuxPath, LinkInfo.ISODirPath), "ISO9660Generator"); if (OK) { if (File.Exists(LinkInfo.MapPath)) { File.Delete(LinkInfo.MapPath); } OK = Utilities.ExecuteProcess(Options.OutputPath, Path.Combine(LinkInfo.ToolsPath, @"Cygwin\objdump.exe"), string.Format("--wide --syms \"{0}\"", LinkInfo.BinPath), "ObjDump", false, LinkInfo.MapPath); } } return OK; }
/// <summary> /// Processes the specified type's fields to fill in required data. /// </summary> /// <param name="TheLibrary">The library from which the type originated.</param> /// <param name="theTypeInfo">The type info to process.</param> public static void ProcessTypeFields(IL.ILLibrary TheLibrary, TypeInfo theTypeInfo) { if (theTypeInfo.ProcessedFields) { return; } theTypeInfo.ProcessedFields = true; int totalOffset = 0; //Base class fields if (theTypeInfo.UnderlyingType.BaseType != null) { Type baseType = theTypeInfo.UnderlyingType.BaseType; if (!baseType.AssemblyQualifiedName.Contains("mscorlib")) { totalOffset = TheLibrary.GetTypeInfo(baseType).SizeOnHeapInBytes; } } foreach (FieldInfo aFieldInfo in theTypeInfo.FieldInfos) { if (!aFieldInfo.IsStatic) { aFieldInfo.OffsetInBytes = totalOffset; TypeInfo fieldTypeInfo = TheLibrary.GetTypeInfo(aFieldInfo.FieldType); totalOffset += fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes; } } }
/// <summary> /// Scans the library for types. /// </summary> /// <param name="TheLibrary">The library to scan.</param> public static void ScanTypes(IL.ILLibrary TheLibrary) { if (TheLibrary == null) { return; } else if (TheLibrary.TypeInfos.Count != 0) { //Already scanned return; } foreach (IL.ILLibrary aDependency in TheLibrary.Dependencies) { ScanTypes(aDependency); } List<Type> types = TheLibrary.TheAssembly.GetTypes().ToList(); //Add in the standard types (which come from mscorlib) //#region Standard Types (from mscorlib) //types.Add(typeof(object)); //types.Add(typeof(float)); //types.Add(typeof(double)); //types.Add(typeof(decimal)); //types.Add(typeof(string)); //types.Add(typeof(IntPtr)); //types.Add(typeof(void)); //types.Add(typeof(bool)); //types.Add(typeof(byte)); //types.Add(typeof(sbyte)); //types.Add(typeof(char)); //types.Add(typeof(int)); //types.Add(typeof(long)); //types.Add(typeof(Int16)); //types.Add(typeof(Int32)); //types.Add(typeof(Int64)); //types.Add(typeof(UInt16)); //types.Add(typeof(UInt32)); //types.Add(typeof(UInt64)); //types.Add(typeof(void*)); //types.Add(typeof(bool*)); //types.Add(typeof(byte*)); //types.Add(typeof(sbyte*)); //types.Add(typeof(char*)); //types.Add(typeof(int*)); //types.Add(typeof(long*)); //types.Add(typeof(Int16*)); //types.Add(typeof(Int32*)); //types.Add(typeof(Int64*)); //types.Add(typeof(UInt16*)); //types.Add(typeof(UInt32*)); //types.Add(typeof(UInt64*)); //#endregion foreach (Type aType in types) { ScanType(TheLibrary, aType); } for (int i = 0; i < TheLibrary.TypeInfos.Count; i++) { ProcessType(TheLibrary, TheLibrary.TypeInfos[i]); } for (int i = 0; i < TheLibrary.TypeInfos.Count; i++) { ProcessTypeFields(TheLibrary, TheLibrary.TypeInfos[i]); } }
/// <summary> /// Scans a type to generate type info for the type. Also scans methods and constructors of the type /// amongst some other information. /// </summary> /// <param name="TheLibrary">The library from which the type originated.</param> /// <param name="aType">The type to scan.</param> /// <returns>The new type info.</returns> public static TypeInfo ScanType(IL.ILLibrary TheLibrary, Type aType) { if(TheLibrary.TypeInfos.Where(x => x.UnderlyingType.Equals(aType)).Count() > 0) { return TheLibrary.TypeInfos.Where(x => x.UnderlyingType.Equals(aType)).First(); } string typeName = aType.Name; TypeInfo newTypeInfo = new TypeInfo() { UnderlyingType = aType }; TheLibrary.TypeInfos.Add(newTypeInfo); { object[] CustAttrs = aType.GetCustomAttributes(false); foreach (object aCustAttr in CustAttrs) { if (!aCustAttr.GetType().AssemblyQualifiedName.Contains("mscorlib")) { if (!IL.ILLibrary.SpecialClasses.ContainsKey(aCustAttr.GetType())) { IL.ILLibrary.SpecialClasses.Add(aCustAttr.GetType(), new List<TypeInfo>()); } IL.ILLibrary.SpecialClasses[aCustAttr.GetType()].Add(newTypeInfo); } } } //Ignore all internal data of types from mscorlib except for value types such as // int, uint etc. and associated pointer types if (!aType.AssemblyQualifiedName.Contains("mscorlib")) { // All Fields System.Reflection.FieldInfo[] allFields = aType.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); foreach (System.Reflection.FieldInfo aFieldInfo in allFields) { if (aFieldInfo.DeclaringType.Equals(newTypeInfo.UnderlyingType)) { newTypeInfo.FieldInfos.Add(new FieldInfo() { UnderlyingInfo = aFieldInfo }); } } // Plugged / Unplugged Methods System.Reflection.MethodInfo[] allMethods = aType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).ToArray(); foreach (System.Reflection.MethodInfo aMethodInfo in allMethods) { if (aMethodInfo.DeclaringType.Equals(aType)) { MethodInfo newMethodInfo = new MethodInfo() { UnderlyingInfo = aMethodInfo, PlugAttribute = (Attributes.PluggedMethodAttribute)aMethodInfo.GetCustomAttribute(typeof(Attributes.PluggedMethodAttribute)) }; newTypeInfo.MethodInfos.Add(newMethodInfo); object[] CustAttrs = aMethodInfo.GetCustomAttributes(false); foreach (object aCustAttr in CustAttrs) { if (!aCustAttr.GetType().AssemblyQualifiedName.Contains("mscorlib")) { if (!IL.ILLibrary.SpecialMethods.ContainsKey(aCustAttr.GetType())) { IL.ILLibrary.SpecialMethods.Add(aCustAttr.GetType(), new List<MethodInfo>()); } IL.ILLibrary.SpecialMethods[aCustAttr.GetType()].Add(newMethodInfo); } } } } // Plugged / unplugged Constructors ConstructorInfo[] allConstructors = aType.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .ToArray(); foreach (ConstructorInfo aConstructorInfo in allConstructors) { if (aConstructorInfo.DeclaringType.Equals(aType)) { MethodInfo newMethodInfo = new MethodInfo() { UnderlyingInfo = aConstructorInfo, PlugAttribute = (Attributes.PluggedMethodAttribute)aConstructorInfo.GetCustomAttribute(typeof(Attributes.PluggedMethodAttribute)) }; newTypeInfo.MethodInfos.Add(newMethodInfo); object[] CustAttrs = aConstructorInfo.GetCustomAttributes(false); foreach (object aCustAttr in CustAttrs) { if (!aCustAttr.GetType().AssemblyQualifiedName.Contains("mscorlib")) { if (!IL.ILLibrary.SpecialMethods.ContainsKey(aCustAttr.GetType())) { IL.ILLibrary.SpecialMethods.Add(aCustAttr.GetType(), new List<MethodInfo>()); } IL.ILLibrary.SpecialMethods[aCustAttr.GetType()].Add(newMethodInfo); } } } } } return newTypeInfo; }
/// <summary> /// Processes the specified type info to fill in the required data. /// </summary> /// <param name="TheLibrary">The library from which the type originated.</param> /// <param name="theTypeInfo">The type info to process.</param> public static void ProcessType(IL.ILLibrary TheLibrary, TypeInfo theTypeInfo) { if(theTypeInfo.Processed) { return; } theTypeInfo.Processed = true; theTypeInfo.IsGCManaged = GetIsGCManaged(theTypeInfo.UnderlyingType); if (theTypeInfo.IsValueType || theTypeInfo.IsPointer) { theTypeInfo.SizeOnStackInBytes = GetSizeOnStackInBytes(theTypeInfo.UnderlyingType); theTypeInfo.SizeOnHeapInBytes = GetSizeOnHeapInBytes(theTypeInfo.UnderlyingType); } else { theTypeInfo.SizeOnStackInBytes = GetSizeOnStackInBytes(theTypeInfo.UnderlyingType); theTypeInfo.SizeOnHeapInBytes = 0; if (theTypeInfo.UnderlyingType.BaseType != null) { Type baseType = theTypeInfo.UnderlyingType.BaseType; if (!baseType.AssemblyQualifiedName.Contains("mscorlib")) { TypeInfo baseTypeInfo = TheLibrary.GetTypeInfo(baseType, false); ProcessType(TheLibrary, baseTypeInfo); theTypeInfo.SizeOnHeapInBytes += baseTypeInfo.SizeOnHeapInBytes; } } foreach (FieldInfo aFieldInfo in theTypeInfo.FieldInfos) { if (!aFieldInfo.IsStatic) { TypeInfo fieldTypeInfo = TheLibrary.GetTypeInfo(aFieldInfo.FieldType, false); if (fieldTypeInfo.IsValueType || fieldTypeInfo.IsPointer) { ProcessType(TheLibrary, fieldTypeInfo); } theTypeInfo.SizeOnHeapInBytes += fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : Options.AddressSizeInBytes; } } } }
public static void SetProperty(Type t, object instance, PropertyInfo info, object Value) { IL code; if (_cache.ContainsKey(t)) code = _cache[t]; else _cache.Add(t, code = new IL(t)); code.PropertySetInvoker(info)(instance, Value); }
public static object CallMethod(Type t, object instance, MethodInfo info, Type[] ParamTypes, object[] Params) { IL code; if (_cache.ContainsKey(t)) code = _cache[t]; else _cache.Add(t, code = new IL(t)); return code.MethodInvoker(info, ParamTypes)(instance, Params); }
public static object GetProperty(Type t, object instance, PropertyInfo info) { IL code; if (_cache.ContainsKey(t)) code = _cache[t]; else _cache.Add(t, code = new IL(t)); return code.PropertyGetInvoker(info)(instance); }
public void EmitLoadTypeOnStack(Type t) { IL.Emit(OpCodes.Ldtoken, t); IL.EmitCall(OpCodes.Call, GetTypeFromHandle, null); }
/// <summary> /// Performs the link. /// </summary> /// <param name="TheLibrary">The root library to link.</param> /// <returns>CompileResult.OK if the link succeeded. Otherwise, CompileResult.Fail.</returns> public static CompileResult Link(IL.ILLibrary TheLibrary, bool dependency = false, string Name = null) { bool OK = true; // If: Link to ELF and Libraries // - Link sub-libs to .a files // - Link main lib to .elf file (if present) // If: Link to ISO // - Generate basic link-script // - Generate full link-script by inserting necessary file location instructions for all object files // - Execute ld to build bin file // - Execute ISO9660Generator to build .ISO file if (Options.LinkMode == Options.LinkModes.ELF) { // Check for main method. If found, that library gets linked to Executable not Shared Lib List<string> depLibNames = new List<string>(); foreach (IL.ILLibrary depLib in TheLibrary.Dependencies) { string depLibName = Utilities.CleanFileName(depLib.TheAssembly.GetName().Name); if (Options.ShortenDependencyNames) { if (!DependencyNameMapping.ContainsKey(depLibName)) { DependencyNameMapping.Add(depLibName, (NameGenerator++).ToString()); } depLibName = DependencyNameMapping[depLibName]; } depLibNames.Add(depLibName); OK = OK && (Link(depLib, true, depLibName) == CompileResult.OK); if (!OK) { break; } } if (!OK) { return CompileResult.Fail; } List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>(); SequencedASMBlocks.AddRange(TheLibrary.TheASMLibrary.ASMBlocks); SequencedASMBlocks.Sort(GetOrder); SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block) { if (block != null && block.OriginMethodInfo != null) { DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath); } }); // Find start method if any, use as ENTRY point bool ExecutableOutput = false; string EntryPoint = null; if (IL.ILLibrary.SpecialMethods.ContainsKey(typeof(Attributes.MainMethodAttribute))) { Types.MethodInfo mainMethodInfo = IL.ILLibrary.SpecialMethods[typeof(Attributes.MainMethodAttribute)].First(); IL.ILBlock mainMethodBlock = TheLibrary.GetILBlock(mainMethodInfo, false); if (mainMethodBlock != null) { ExecutableOutput = true; EntryPoint = mainMethodInfo.ID; } } if (Options.ShortenDependencyNames && string.IsNullOrWhiteSpace(Name)) { Name = "Driver"; } string AssemblyName = string.IsNullOrWhiteSpace(Name) ? Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name) : Name; DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary); LinkInformation LinkInfo = new LinkInformation() { ToolsPath = Options.ToolsPath, LinkScriptCmdPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker_command.txt"), LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker.ld"), BinPath = Path.Combine(Options.OutputPath, "Output\\" + (ExecutableOutput ? AssemblyName + ".elf" : "Lib" + AssemblyName + ".a")), MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"), ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"), LdWorkingDir = Path.Combine(Options.OutputPath, "") + "\\", ExecutableOutput = ExecutableOutput, EntryPoint = EntryPoint, SequencedASMBlocks = SequencedASMBlocks, depLibNames = depLibNames }; if (!Directory.Exists(Path.GetDirectoryName(LinkInfo.BinPath))) { Directory.CreateDirectory(Path.GetDirectoryName(LinkInfo.BinPath)); } OK = TargetArchitecture.TargetFunctions.LinkELF(TheLibrary, LinkInfo); if (OK) { DebugDataWriter.ProcessMapFile(LinkInfo.MapPath); } } else if (Options.LinkMode == Options.LinkModes.ISO) { List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>(); List<IL.ILLibrary> FlattenedLibs = TheLibrary.Flatten(); foreach (IL.ILLibrary depLib in FlattenedLibs) { SequencedASMBlocks.AddRange(depLib.TheASMLibrary.ASMBlocks); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, depLib); } SequencedASMBlocks.Sort(GetOrder); SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block) { if (block != null && block.OriginMethodInfo != null) { DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath); } }); string AssemblyName = Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name); DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary); LinkInformation LinkInfo = new LinkInformation() { ToolsPath = Options.ToolsPath, ISOGenPath = Path.Combine(Options.ToolsPath, @"ISO9660Generator.exe"), ISOToolsDirPath = Path.Combine(Options.ToolsPath, @"ISO"), ISODirPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO"), LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\linker.ld"), BinPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\Kernel.bin"), ISOLinuxPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\" + (Options.BuildMode == Options.BuildModes.Debug ? "isolinux-debug.bin" : "isolinux.bin")), ISOPath = Path.Combine(Options.OutputPath, AssemblyName + ".iso"), MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"), ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"), LdWorkingDir = Path.Combine(Options.OutputPath, "DriversCompiler") + "\\", SequencedASMBlocks = SequencedASMBlocks }; if (Directory.Exists(LinkInfo.ISODirPath)) { Directory.Delete(LinkInfo.ISODirPath, true); } CopyDirectory(LinkInfo.ISOToolsDirPath, LinkInfo.ISODirPath, true); OK = TargetArchitecture.TargetFunctions.LinkISO(TheLibrary, LinkInfo); if (OK) { DebugDataWriter.ProcessMapFile(LinkInfo.MapPath); } } return OK ? CompileResult.OK : CompileResult.Fail; }
public abstract bool LinkISO(IL.ILLibrary TheLibrary, LinkInformation LinkInfo);
/// <summary> /// Construct an instruction. /// </summary> /// <param name="reader">The reader that created this instruction.</param> /// <param name="op">The instruction opcode.</param> /// <param name="arg">The instruction operand.</param> /// <param name="label">The instruction's address in the bytecode.</param> public Instruction(ILReader reader, OpCode op, Operand arg, IL.Label label) : this(reader, op, arg, (ushort)label.pos) { }
/// <summary> /// Construct an instruction. /// </summary> /// <param name="reader">The reader that created this instruction.</param> /// <param name="op">The instruction opcode.</param> /// <param name="label">The instruction's address in the bytecode.</param> public Instruction(ILReader reader, OpCode op, IL.Label label) : this(reader, op, default(Operand), label) { }