/
EugenyCh7
/
CodeDOMTest
Обзор
Документация
Войти
/
EugenyCh7
/
CodeDOMTest
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
InstructionEncoderTest
LiteAssemblyBuilder/Test/InstructionEncoderTest/InstructionEncoderTest.cs
255 строк
9 KB
eugenych
fix
06 авг 2023, 13:21
06 авг 2023, 13:21
0e82aaf
Код
Авторство
О чём код?
using LiteAssemblyBuilder; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; namespace InstructionEncoderTest { internal class InstructionEncoderTest { /*public static double CalcRectangleArea(double length, double width) { if (length < 0.0) { throw new ArgumentOutOfRangeException("length"); } if (width < 0.0) { throw new ArgumentOutOfRangeException("width"); } return length * width; }*/ private static void Generate(LiteBuilder lb) { BlobBuilder methodSignature = lb.GenerateBlobBuilder(build => { build .MethodSignature() .Parameters( 2, returnType => returnType.Type().Double(), parameters => { parameters.AddParameter().Type().Double(); parameters.AddParameter().Type().Double(); }); }); // Create module and assembly lb.AddModule(); lb.AddAssembly(); // Create references to System.Object and System.Console types. AssemblyReferenceHandle corlibAssemblyRef = lb.AddAssemblyReference( "System.Runtime", new Version(7, 0, 0, 0), new byte[] { 0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a }); TypeReferenceHandle systemObjectTypeRef = lb.AddTypeReference(corlibAssemblyRef, "System", "Object"); // Get reference to Object's constructor. BlobBuilder objectCtorMember = lb.GenerateBlobBuilder(build => { build .MethodSignature(isInstanceMethod: true) .Parameters(0, returnType => returnType.Void(), parameters => { }); }); MemberReferenceHandle objectCtorMemberRef = lb.AddMemberReference( systemObjectTypeRef, ".ctor", objectCtorMember); // Emit IL for Program::.ctor int ctorBodyOffset = lb.AddMethodBody(null, il => { // ldarg.0 il.LoadArgument(0); // call instance void [mscorlib]System.Object::.ctor() il.Call(objectCtorMemberRef); // ret il.OpCode(ILOpCode.Ret); }); // Emit IL for a method int methodBodyOffset = lb.AddMethodBody(new ControlFlowBuilder(), il => { // Get reference to System.ArgumentOutOfRangeException constructor TypeReferenceHandle typeRefHandle = lb.AddTypeReference(corlibAssemblyRef, "System", "ArgumentOutOfRangeException"); // Signature: .ctor(string) BlobBuilder ctor = lb.GenerateBlobBuilder(build => { build .MethodSignature(isInstanceMethod: true) .Parameters(1, returnType => returnType.Void(), parameters => parameters.AddParameter().Type().String()); }); MemberReferenceHandle ctorMemberRef = lb.AddMemberReference( typeRefHandle, ".ctor", ctor); LabelHandle label1 = il.DefineLabel(); LabelHandle label2 = il.DefineLabel(); // ldarg.0 il.OpCode(ILOpCode.Ldarg_0); // ldc.r8 0 il.LoadConstantR8(0); // bge.un.s LABEL1 il.Branch(ILOpCode.Bge_un_s, label1); // ldstr "length" il.LoadString(lb.MetadataBuilder.GetOrAddUserString("length")); // newobj instance void [System.Runtime]System.ArgumentOutOfRangeException::.ctor(string) il.OpCode(ILOpCode.Newobj); il.Token(ctorMemberRef); // throw il.OpCode(ILOpCode.Throw); // LABEL1: ldarg.1 il.MarkLabel(label1); il.OpCode(ILOpCode.Ldarg_1); // ldc.r8 0 il.LoadConstantR8(0); // bge.un.s LABEL2 il.Branch(ILOpCode.Bge_un_s, label2); // ldstr "width" il.LoadString(lb.MetadataBuilder.GetOrAddUserString("width")); // newobj instance void [System.Runtime]System.ArgumentOutOfRangeException::.ctor(string) il.OpCode(ILOpCode.Newobj); il.Token(ctorMemberRef); // throw il.OpCode(ILOpCode.Throw); // LABEL2: ldarg.0 il.MarkLabel(label2); il.OpCode(ILOpCode.Ldarg_0); // ldarg.1 il.OpCode(ILOpCode.Ldarg_1); // mul il.OpCode(ILOpCode.Mul); // ret il.OpCode(ILOpCode.Ret); }); // Create method definition MethodDefinitionHandle methodDef = lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, MethodImplAttributes.IL, "TestMethod", methodSignature, methodBodyOffset); // Create parameters for a method definition lb.AddParameter(ParameterAttributes.None, "length"); lb.AddParameter(ParameterAttributes.None, "width"); // Create method definition for Program::.ctor MethodDefinitionHandle ctorDef = lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, MethodImplAttributes.IL, ".ctor", objectCtorMember, ctorBodyOffset); // Create type definition for the special <Module> type that holds global functions lb.AddTypeDefinition( default, null, "<Module>", default); // Create type definition for ConsoleApplication.Program lb.AddTypeDefinition( TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, lb.AssemblyName, "Program", baseType: systemObjectTypeRef); } private static void WritePEImage( Stream peStream, LiteBuilder lb, MethodDefinitionHandle entryPointHandle) { // Create executable with the managed metadata from the specified MetadataBuilder. var peHeaderBuilder = new PEHeaderBuilder( imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll); var peBuilder = new ManagedPEBuilder( peHeaderBuilder, new MetadataRootBuilder(lb.MetadataBuilder), lb.BlobBuilder, entryPoint: entryPointHandle, flags: CorFlags.ILOnly, deterministicIdProvider: content => lb.ContentId); // Write executable into the specified stream. var peBlob = new BlobBuilder(); BlobContentId contentId = peBuilder.Serialize(peBlob); peBlob.WriteContentTo(peStream); } public static void BuildAssembly(string name) { using (var peStream = new FileStream(name + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { LiteBuilder lb = new LiteBuilder( name + ".dll", name, new Version(1, 0, 0, 0), new Guid("17E5BDE2-2243-5EAD-ABB3-1002F92068A7"), 0x04030201); Generate(lb); WritePEImage(peStream, lb, default); } Console.WriteLine(name); Assembly ass = Assembly.LoadFrom(name + ".dll"); Type t = ass.GetType(name + ".Program"); MethodInfo mi = t.GetMethod("TestMethod"); try { object ret = mi.Invoke(null, new object[] { 2.0, 4.0 }); if (ret == null) Console.WriteLine("(null)"); else Console.WriteLine(ret); } catch (TargetInvocationException ex) { Console.WriteLine(ex.ToString()); } } public static void Run() { BuildAssembly("Test"); } } }