/
EugenyCh7
/
CodeDOMTest
Обзор
Документация
Войти
/
EugenyCh7
/
CodeDOMTest
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
LiteAssemblyBuilder/InstructionEncoderTest/InstructionEncoderTest.cs
463 строки
17 KB
eugenych
+ GenerateLocalVariables
24 сен 2023, 18:42
24 сен 2023, 18:42
06ed624
Код
Авторство
О чём код?
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) { // 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"); // Create type definition for the special <Module> type that holds global functions lb.AddTypeDefinition( default, null, "<Module>", default); lb.AddTypeDefinition( default, null, "<Module-1>", default); // Get reference to Object's constructor. MethodSignatureEncoder objectCtorMember = lb.GenerateMethodSignature(new MethodSignatureParameters() { IsInstanceMethod = true }, sig => { sig.Parameters(0, returnType => returnType.Void(), parameters => { }); }); // Emit IL for Program::.ctor int ctorBodyOffset = lb.AddMethodBody(new MethodBodyParameters(), il => { MemberReferenceHandle objectCtorMemberRef = lb.AddMemberReference( systemObjectTypeRef, ".ctor", objectCtorMember.Builder); // ldarg.0 il.LoadArgument(0); // call instance void [mscorlib]System.Object::.ctor() il.Call(objectCtorMemberRef); // ret il.OpCode(ILOpCode.Ret); }); // Create method definition for Program::.ctor lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, MethodImplAttributes.IL, ".ctor", objectCtorMember.Builder, ctorBodyOffset); MethodSignatureEncoder methodSignature = lb.GenerateMethodSignature(new MethodSignatureParameters(), sig => { sig.Parameters(2, returnType => returnType.Type().Double(), parameters => { parameters.AddParameter().Type().Double(); parameters.AddParameter().Type().Double(); }); }); // Emit IL for a method int methodBodyOffset = lb.AddMethodBody(new MethodBodyParameters(), il => { // Get reference to System.ArgumentOutOfRangeException constructor TypeReferenceHandle typeRefHandle = lb.AddTypeReference(corlibAssemblyRef, "System", "ArgumentOutOfRangeException"); // Signature: .ctor(string) MethodSignatureEncoder ctor = lb.GenerateMethodSignature(new MethodSignatureParameters() { IsInstanceMethod = true }, sig => { sig.Parameters(1, returnType => returnType.Void(), parameters => { parameters.AddParameter().Type().String(); }); }); MemberReferenceHandle ctorMemberRef = lb.AddMemberReference( typeRefHandle, ".ctor", ctor.Builder); 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.ToUserStringHandle("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.ToUserStringHandle("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 parameters for a method definition lb.AddParameter(ParameterAttributes.None, "length"); lb.AddParameter(ParameterAttributes.None, "width"); // Create method definition lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, MethodImplAttributes.IL, "TestMethod", methodSignature.Builder, methodBodyOffset); MethodSignatureEncoder methodSignature2 = lb.GenerateMethodSignature(new MethodSignatureParameters(), sig => { sig.Parameters(2, returnType => returnType.Type().Double(), parameters => { parameters.AddParameter().Type().Double(); parameters.AddParameter().Type().Double(); }); }); int methodBodyOffset2 = lb.AddMethodBody(new MethodBodyParameters(), il => { // Get reference to System.ArgumentOutOfRangeException constructor TypeReferenceHandle typeRefHandle = lb.AddTypeReference(corlibAssemblyRef, "System", "ArgumentOutOfRangeException"); // Signature: .ctor(string) MethodSignatureEncoder ctor = lb.GenerateMethodSignature(new MethodSignatureParameters() { IsInstanceMethod = true }, sig => { sig.Parameters(1, returnType => returnType.Void(), parameters => { parameters.AddParameter().Type().String(); }); }); MemberReferenceHandle ctorMemberRef = lb.AddMemberReference( typeRefHandle, ".ctor", ctor.Builder); 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 "first" il.LoadString(lb.ToUserStringHandle("first")); // 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 "second" il.LoadString(lb.ToUserStringHandle("second")); // 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); }); lb.AddParameter(ParameterAttributes.None, "first"); lb.AddParameter(ParameterAttributes.None, "second"); lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, MethodImplAttributes.IL, "TestMethod2", methodSignature2.Builder, methodBodyOffset2); MethodSignatureEncoder methodSignatureRef = lb.GenerateMethodSignature(new MethodSignatureParameters(), sig => { sig.Parameters(2, returnType => returnType.Type().Double(), parameters => { parameters.AddParameter().Type().Double(); parameters.AddParameter().Type(true).Double(); }); }); LocalVariablesEncoder locals = lb.GenerateLocalVariables(3, encoder => { encoder.AddVariable().Type().Boolean(); encoder.AddVariable().Type().Boolean(); encoder.AddVariable().Type().Double(); }); int methodBodyOffsetRef = lb.AddMethodBody(new MethodBodyParameters() { LocalVariablesSignature = lb.ToStandaloneSignatureHandle(locals.Builder) }, il => { // Get reference to System.ArgumentOutOfRangeException constructor TypeReferenceHandle typeRefHandle = lb.AddTypeReference(corlibAssemblyRef, "System", "ArgumentOutOfRangeException"); // Signature: .ctor(string) MethodSignatureEncoder ctor = lb.GenerateMethodSignature(new MethodSignatureParameters() { IsInstanceMethod = true }, sig => { sig.Parameters(1, returnType => returnType.Void(), parameters => { parameters.AddParameter().Type().String(); }); }); MemberReferenceHandle ctorMemberRef = lb.AddMemberReference( typeRefHandle, ".ctor", ctor.Builder); LabelHandle label1 = il.DefineLabel(); LabelHandle label2 = il.DefineLabel(); LabelHandle label3 = il.DefineLabel(); // if (first < 0.0) il.LoadArgument(0); il.LoadConstantR8(0.0); il.OpCode(ILOpCode.Clt); il.StoreLocal(0); il.LoadLocal(0); il.Branch(ILOpCode.Brfalse_s, label1); // throw new ArgumentOutOfRangeException("first"); il.LoadString(lb.ToUserStringHandle("first")); il.OpCode(ILOpCode.Newobj); il.Token(ctorMemberRef); il.OpCode(ILOpCode.Throw); // if (second < 0.0) il.MarkLabel(label1); il.LoadArgument(1); il.OpCode(ILOpCode.Ldind_r8); il.LoadConstantR8(0.0); il.OpCode(ILOpCode.Clt); il.StoreLocal(1); il.LoadLocal(1); il.Branch(ILOpCode.Brfalse_s, label2); // throw new ArgumentOutOfRangeException("second"); il.LoadString(lb.ToUserStringHandle("second")); il.OpCode(ILOpCode.Newobj); il.Token(ctorMemberRef); il.OpCode(ILOpCode.Throw); // return first * second; il.MarkLabel(label2); il.LoadArgument(0); il.LoadArgument(1); il.OpCode(ILOpCode.Ldind_r8); il.OpCode(ILOpCode.Mul); il.StoreLocal(2); il.Branch(ILOpCode.Br_s, label3); il.MarkLabel(label3); il.LoadLocal(2); il.OpCode(ILOpCode.Ret); }); lb.AddParameter(ParameterAttributes.None, "first"); lb.AddParameter(ParameterAttributes.None, "second"); lb.AddMethodDefinition( MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, MethodImplAttributes.IL, "TestMethod3", methodSignatureRef.Builder, methodBodyOffsetRef); // Create type definition for Test.Program lb.AddTypeDefinition( TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, lb.AssemblyName, "Program", systemObjectTypeRef); lb.AddTypeDefinition( default, null, "<Module-2>", default); } 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) { string moduleName = $"{name}.dll"; using (var peStream = new FileStream(moduleName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { LiteBuilder lb = new LiteBuilder( moduleName, 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(moduleName); //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"); } } }