예제 #1
0
        static void TestCore()
        {
            // Module creation
            using (var module = new Module())
            {
                // Literals and constants
                var constI32     = module.Const(1);
                var constI64     = module.Const(2L);
                var constF32     = module.Const(3.14f);
                var constF64     = module.Const(2.1828);
                var constF32Bits = module.Const(Literal.Float32Bits(0xFFFF1234));
                var constF64Bits = module.Const(Literal.Float64Bits(0xFFFF12345678ABCDL));

                var switchValueNames = new[] { "the-value" };
                var switchBodyNames  = new[] { "the-nothing" };

                var callOperands2  = new[] { MakeInt32(module, 13), MakeFloat64(module, 3.7) };
                var callOperands4  = new[] { MakeInt32(module, 13), MakeInt64(module, 37L), MakeFloat32(module, 1.3f), MakeFloat64(module, 3.7) };
                var callOperands4b = new[] { MakeInt32(module, 13), MakeInt64(module, 37L), MakeFloat32(module, 1.3f), MakeFloat64(module, 3.7) };

                var parameters = new[] { ValueType.Int32, ValueType.Int64, ValueType.Float32, ValueType.Float64 };
                var iiIfF      = module.AddFunctionType("iiIfF", ValueType.Int32, parameters);

                var temp1  = MakeInt32(module, 1);
                var temp2  = MakeInt32(module, 2);
                var temp3  = MakeInt32(module, 3);
                var temp4  = MakeInt32(module, 4);
                var temp5  = MakeInt32(module, 5);
                var temp6  = MakeInt32(module, 0);
                var temp7  = MakeInt32(module, 1);
                var temp8  = MakeInt32(module, 0);
                var temp9  = MakeInt32(module, 1);
                var temp10 = MakeInt32(module, 1);
                var temp11 = MakeInt32(module, 3);
                var temp12 = MakeInt32(module, 5);
                var temp13 = MakeInt32(module, 10);
                var temp14 = MakeInt32(module, 11);
                var temp15 = MakeInt32(module, 110);
                var temp16 = MakeInt64(module, 111);

                var valueList = new[] {
                    // Unary
                    MakeUnary(module, UnaryOperator.ClzInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ClzInt64, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.PopcntInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.NegFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.AbsFloat64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.CeilFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.FloorFloat64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.TruncFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.NearestFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.SqrtFloat64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.EqZInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ExtendSInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ExtendUInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.WrapInt64, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.TruncSFloat32ToInt32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.TruncSFloat32ToInt64, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.TruncUFloat32ToInt32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.TruncUFloat32ToInt64, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.TruncSFloat64ToInt32, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.TruncSFloat64ToInt64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.TruncUFloat64ToInt32, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.TruncUFloat64ToInt64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.ReinterpretFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.ReinterpretFloat64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.ConvertSInt32ToFloat32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ConvertSInt32ToFloat64, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ConvertUInt32ToFloat32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ConvertUInt32ToFloat64, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ConvertSInt64ToFloat32, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.ConvertSInt64ToFloat64, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.ConvertUInt64ToFloat32, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.ConvertUInt64ToFloat64, ValueType.Int64),
                    MakeUnary(module, UnaryOperator.PromoteFloat32, ValueType.Float32),
                    MakeUnary(module, UnaryOperator.DemoteFloat64, ValueType.Float64),
                    MakeUnary(module, UnaryOperator.ReinterpretInt32, ValueType.Int32),
                    MakeUnary(module, UnaryOperator.ReinterpretInt64, ValueType.Int64),

                    // Binary
                    MakeBinary(module, BinaryOperator.AddInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.SubFloat64, ValueType.Float64),
                    MakeBinary(module, BinaryOperator.DivSInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.DivUInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.RemSInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.RemUInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.AndInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.OrInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.XorInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.ShlInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.ShrUInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.ShrSInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.RotLInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.RotRInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.DivFloat32, ValueType.Float32),
                    MakeBinary(module, BinaryOperator.CopySignFloat64, ValueType.Float64),
                    MakeBinary(module, BinaryOperator.MinFloat32, ValueType.Float32),
                    MakeBinary(module, BinaryOperator.MaxFloat64, ValueType.Float64),
                    MakeBinary(module, BinaryOperator.EqInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.NeFloat32, ValueType.Float32),
                    MakeBinary(module, BinaryOperator.LtSInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.LtUInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.LeSInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.LeUInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.GtSInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.GtUInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.GeSInt32, ValueType.Int32),
                    MakeBinary(module, BinaryOperator.GeUInt64, ValueType.Int64),
                    MakeBinary(module, BinaryOperator.LtFloat32, ValueType.Float32),
                    MakeBinary(module, BinaryOperator.LeFloat64, ValueType.Float64),
                    MakeBinary(module, BinaryOperator.GtFloat64, ValueType.Float64),
                    MakeBinary(module, BinaryOperator.GeFloat32, ValueType.Float32),

                    // All the rest
                    module.Block(ValueType.Auto), // Block with no name and no type
                    module.If(temp1, temp2, temp3),
                    module.If(temp4, temp5),
                    module.Loop("in", MakeInt32(module, 0)),
                    module.Loop(MakeInt32(module, 0)),
                    module.Break("the-value", temp6, temp7),
                    module.Break("the-nothing", condition: MakeInt32(module, 2)),
                    module.Break("the-value", value: MakeInt32(module, 3)),
                    module.Break("the-nothing"),
                    module.Switch(switchValueNames, "the-value", temp8, temp9),
                    module.Switch(switchBodyNames, "the-nothing", MakeInt32(module, 2)),
                    module.Unary(UnaryOperator.EqZInt32, // Check the output type of the call node
                                 module.Call("kitchen()sinker", callOperands4, ValueType.Int32)
                                 ),
                    module.Unary(UnaryOperator.EqZInt32, // check the output type of the call node
                                 module.Unary(UnaryOperator.TruncSFloat32ToInt32,
                                              module.CallImport("an-imported", callOperands2, ValueType.Float32)
                                              )
                                 ),
                    module.Unary(UnaryOperator.EqZInt32, // Check the output type of the call node
                                 module.CallIndirect(MakeInt32(module, 2449), callOperands4b, "iiIfF")
                                 ),
                    module.Drop(module.GetLocal(0, ValueType.Int32)),
                    module.SetLocal(0, MakeInt32(module, 101)),
                    module.Drop(module.TeeLocal(0, MakeInt32(module, 102))),
                    module.Load(4, false, 0, 0, ValueType.Int32, MakeInt32(module, 1)),
                    module.Load(2, true, 2, 1, ValueType.Int64, MakeInt32(module, 8)),
                    module.Load(4, false, 0, 0, ValueType.Float32, MakeInt32(module, 2)),
                    module.Load(8, false, 2, 8, ValueType.Float64, MakeInt32(module, 9)),
                    module.Store(4, 0, 0, temp13, temp14, ValueType.Int32),
                    module.Store(8, 2, 4, temp15, temp16, ValueType.Int64),
                    module.Select(temp10, temp11, temp12),
                    module.Return(MakeInt32(module, 1337)),
                    // TODO: Host
                    module.Nop(),
                    module.Unreachable(),
                };

                // Test printing a standalone expression
                valueList[3].Print();

                // Make the main body of our function, one block with a return value, and one without
                var value        = module.Block("the-value", valueList, ValueType.Auto);
                var droppedValue = module.Drop(value);
                var nothing      = module.Block("the-nothing", droppedValue, ValueType.Auto);
                var bodyList     = new[] { nothing, MakeInt32(module, 42) };
                var body         = module.Block("the-body", bodyList, ValueType.Auto);

                // Create the function
                var localTypes = new[] { ValueType.Int32 };
                var sinker     = module.AddFunction("kitchen()sinker", iiIfF, localTypes, body);

                // Globals
                module.AddGlobal("a-global", ValueType.Int32, false, MakeInt32(module, 7));
                module.AddGlobal("a-mutable-global", ValueType.Float32, true, MakeFloat32(module, 7.5f));

                // Imports
                var iparamsList = new[] { ValueType.Int32, ValueType.Float64 };
                var fiF         = module.AddFunctionType("fiF", ValueType.Float32, iparamsList);
                module.AddFunctionImport("an-imported", "module", "base", fiF);

                // Exports
                module.AddFunctionExport("kitchen()sinker", "kitchen_sinker");

                // Function table. One per module.
                var functions = new[] { sinker };
                module.SetFunctionTable(functions);

                // Memory. One per module.
                var segments = new[] {
                    new MemorySegment("hello, world", module.Const(10))
                };
                module.SetMemory(1, 256, "mem", segments);

                // Start function. One per module.
                var v       = module.AddFunctionType("v", ValueType.None);
                var starter = module.AddFunction("starter", v, module.Nop());
                module.SetStart(starter);

                // Unnamed function type
                var noname = module.AddFunctionType(ValueType.None);

                // A bunch of our code needs drop(), auto-add it
                module.AutoDrop();

                // Verify it validates (note that the using block ensures disposal even with exceptions)
                if (!module.Validate())
                {
                    throw new Exception("Module failed validation.");
                }

                // Print it out
                module.Print();

                // Clean up the module (via using), which owns all the objects we created above
            }
        }