Exemplo n.º 1
0
        /// <summary>
        /// Compiles this tree into a NativeSDF instance that can be used to efficiently sample the distance
        /// field represented by this hierarchy.  A compiled NativeSDF instance will not reflect any changes
        /// made to the hierarchy after the compile step.
        ///
        /// The resulting NativeSDF instance can also be used inside of the Unity Job system, and is compatible
        /// with the Unity Burst compiler.
        /// </summary>
        public NativeSDF Compile(Allocator allocator = Allocator.Persistent)
        {
            var countVisitor = new InstructionCountVisitor();

            VisitInstructions(ref countVisitor);

            var sizeVisitor = new BufferSizeVisitor();

            VisitInstructions(ref sizeVisitor);

            var stackVisitor = new StackSizeVisitor();

            VisitInstructions(ref stackVisitor);

            IntPtr instructions;

            unsafe {
                instructions = (IntPtr)UnsafeUtility.Malloc(sizeVisitor.BufferSize,
                                                            sizeof(float),
                                                            allocator);
            }

            var bufferWriter = new InstructionWriteVisitor();

            bufferWriter.ptr        = instructions;
            bufferWriter.byteOffset = 0;
            VisitInstructions(ref bufferWriter);

            return(new NativeSDF(instructions, countVisitor.InstructionCount, stackVisitor.MaxStack, allocator));
        }
Exemplo n.º 2
0
        public Stmt Create()
        {
            var mDef = this.ctx.MRef.Resolve();

            if (!mDef.HasBody)
            {
                throw new ArgumentException("Method has no body, cannot create AST");
            }
            var body = mDef.Body;

            // Pre-calculate all method block starts
            this.methodBlockStarts = body.Instructions
                                     .SelectMany(x => {
                switch (x.OpCode.FlowControl)
                {
                case FlowControl.Cond_Branch:
                case FlowControl.Branch:
                    if (x.OpCode.Code == Code.Switch)
                    {
                        return(((Instruction[])x.Operand).Concat(x.Next));
                    }
                    else
                    {
                        return(new[] { (Instruction)x.Operand, x.Next });
                    }

                case FlowControl.Throw:
                case FlowControl.Return:
                    return(new[] { x.Next });

                default:
                    return(Enumerable.Empty <Instruction>());
                }
            })
                                     .Concat(body.ExceptionHandlers.SelectMany(x => new[] {
                x.TryStart, x.TryEnd, x.HandlerStart, x.HandlerEnd
            }))
                                     .Concat(body.Instructions.First())
                                     .Where(x => x != null)
                                     .Distinct()
                                     .OrderBy(x => x.Offset)
                                     .ToArray();
            // Create all method blocks
            this.CreatePart(body.Instructions, body.ExceptionHandlers);
            // Map continuations and try statements
            // Must continue to outermost Try statement, if one exists, rather than directly to the first CIL block
            foreach (var mappable in this.mappable)
            {
                mappable.Map(this.blockMap);
            }
            var stmt0      = this.blockMap[body.Instructions.First()].First();
            var vStackSize = new StackSizeVisitor();

            vStackSize.Visit(stmt0);
            // Create entry block, and return it
            var entryBlock = new StmtCil(this.ctx, null, new StmtContinuation(this.ctx, stmt0, false), StmtCil.SpecialBlock.Start);

            return(entryBlock);
        }
Exemplo n.º 3
0
 public Stmt Create() {
     var mDef = this.ctx.MRef.Resolve();
     if (!mDef.HasBody) {
         throw new ArgumentException("Method has no body, cannot create AST");
     }
     var body = mDef.Body;
     // Pre-calculate all method block starts
     this.methodBlockStarts = body.Instructions
         .SelectMany(x => {
             switch (x.OpCode.FlowControl) {
             case FlowControl.Cond_Branch:
             case FlowControl.Branch:
                 if (x.OpCode.Code == Code.Switch) {
                     return ((Instruction[])x.Operand).Concat(x.Next);
                 } else {
                     return new[] { (Instruction)x.Operand, x.Next };
                 }
             case FlowControl.Throw:
             case FlowControl.Return:
                 return new[] { x.Next };
             default:
                 return Enumerable.Empty<Instruction>();
             }
         })
         .Concat(body.ExceptionHandlers.SelectMany(x => new[] {
             x.TryStart, x.TryEnd, x.HandlerStart, x.HandlerEnd
         }))
         .Concat(body.Instructions.First())
         .Where(x => x != null)
         .Distinct()
         .OrderBy(x => x.Offset)
         .ToArray();
     // Create all method blocks
     this.CreatePart(body.Instructions, body.ExceptionHandlers);
     // Map continuations and try statements
     // Must continue to outermost Try statement, if one exists, rather than directly to the first CIL block
     foreach (var mappable in this.mappable) {
         mappable.Map(this.blockMap);
     }
     var stmt0 = this.blockMap[body.Instructions.First()].First();
     var vStackSize = new StackSizeVisitor();
     vStackSize.Visit(stmt0);
     // Create entry block, and return it
     var entryBlock = new StmtCil(this.ctx, null, new StmtContinuation(this.ctx, stmt0, false), StmtCil.SpecialBlock.Start);
     return entryBlock;
 }