/// <summary>
        /// Creates the function prolog
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void CreateProlog(CompilationData compilationData)
        {
            var function = compilationData.Function;

            //Calculate the size of the stack aligned to 16 bytes
            var def = function.Definition;
            int neededStackSize =
                (def.Parameters.Count + function.Locals.Count + compilationData.Function.OperandStackSize)
                * Assembler.RegisterSize;

            int stackSize = ((neededStackSize + 15) / 16) * 16;
            compilationData.StackSize = stackSize;

            //Save the base pointer
            Assembler.Push(function.GeneratedCode, Register.BP); //push rbp
            Assembler.Move(function.GeneratedCode, Register.BP, Register.SP);

            //Make room for the variables on the stack
            Assembler.Sub(function.GeneratedCode, Register.SP, stackSize); //sub rsp, <size of stack>

            //Move the arguments to the stack
            this.callingConvetions.MoveArgumentsToStack(compilationData);

            //Zero locals
            this.ZeroLocals(compilationData);
        }
        /// <summary>
        /// Creates the function prolog
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void CreateProlog(CompilationData compilationData)
        {
            var function = compilationData.Function;
            var virtualAssembler = compilationData.VirtualAssembler;

            //Calculate the size of the stack aligned to 16 bytes
            var def = function.Definition;
            int neededStackSize =
                Assembler.RegisterSize
                * (def.Parameters.Count + compilationData.RegisterAllocation.NumSpilledRegisters);

            int stackSize = ((neededStackSize + 15) / 16) * 16;
            compilationData.StackSize = stackSize;

            //Save the base pointer
            Assembler.Push(function.GeneratedCode, Register.BP);
            Assembler.Move(function.GeneratedCode, Register.BP, Register.SP);

            //Make room for the variables on the stack
            if (stackSize > 0)
            {
                Assembler.Sub(function.GeneratedCode, Register.SP, stackSize);
            }

            //Move the arguments to the stack
            this.callingConvetions.MoveArgumentsToStack(compilationData);

            if (compilationData.VirtualAssembler.NeedSpillRegister)
            {
                Assembler.Push(function.GeneratedCode, virtualAssembler.GetIntSpillRegister());
            }

            //Zero locals
            this.ZeroLocals(compilationData);
        }
 /// <summary>
 /// Creates a new virtual assembler
 /// </summary>
 /// <param name="compilationData">The compilation data</param>
 public VirtualAssembler(CompilationData compilationData)
 {
     this.compilationData = compilationData;
     this.needSpillRegister =
         compilationData.RegisterAllocation.Spilled.Keys.Any(x => x.Type == VirtualRegisterType.Integer)
         || compilationData.Function.Instructions.Any(x => x.OpCode == Core.OpCodes.DivInt);
 }
        /// <summary>
        /// Initialises a new instance of <see cref="TemplateCompilationException"/> from serialised data.
        /// </summary>
        /// <param name="info">The serialisation info.</param>
        /// <param name="context">The streaming context.</param>
        protected TemplateCompilationException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
            int count = info.GetInt32("Count");

            var list = new List <RazorEngineCompilerError>();
            var type = typeof(RazorEngineCompilerError);

            for (int i = 0; i < count; i++)
            {
                list.Add((RazorEngineCompilerError)info.GetValue("CompilerErrors[" + i + "]", type));
            }

            CompilerErrors = new ReadOnlyCollection <RazorEngineCompilerError>(list);
            var sourceCode = info.GetString("SourceCode");

            if (string.IsNullOrEmpty(sourceCode))
            {
                sourceCode = null;
            }
            var tmpFolder = info.GetString("TmpFolder");

            if (string.IsNullOrEmpty(tmpFolder))
            {
                tmpFolder = null;
            }
            CompilationData = new CompilationData(sourceCode, tmpFolder);
            Template        = info.GetString("Template");
        }
Exemplo n.º 5
0
 /// <summary>
 /// Initialises a new instance of <see cref="TemplateCompilationException" />.
 /// </summary>
 /// <param name="errors">The set of compiler errors.</param>
 /// <param name="files">The source code that wasn't compiled.</param>
 /// <param name="template">The source template that wasn't compiled.</param>
 public TemplateCompilationException(IList <RazorEngineCompilerError> errors, CompilationData files, string template)
     : base(GetMessage(errors, files, template))
 {
     this.CompilerErrors  = new ReadOnlyCollection <RazorEngineCompilerError>(errors.ToList());
     this.CompilationData = files;
     this.Template        = template;
 }
Exemplo n.º 6
0
 public CompiledTemplate(CompilationData tempFiles, /*ITemplateKey key,*/ string source, Type templateType, Type modelType)
 {
     this.CompilationData = tempFiles;
     //this.Key = key;
     this.Template     = source;
     this.TemplateType = templateType;
     this.ModelType    = modelType;
 }
        /// <summary>
        /// Creates the function epilog
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void CreateEpilog(CompilationData compilationData)
        {
            var generatedCode = compilationData.Function.GeneratedCode;

            //Restore the base pointer
            Assembler.Move(generatedCode, Register.SP, Register.BP);
            Assembler.Pop(generatedCode, Register.BP);
        }
Exemplo n.º 8
0
 public CompiledTemplate(CompilationData tempFiles, ITemplateKey key, ITemplateSource source, Type templateType, Type modelType)
 {
     _tempFiles    = tempFiles;
     _key          = key;
     _source       = source;
     _templateType = templateType;
     _modelType    = modelType;
 }
        /// <summary>
        /// Initialises a new instance of <see cref="TemplateCompilationException"/>.
        /// </summary>
        /// <param name="errors">The set of compiler errors.</param>
        /// <param name="files">The source code that wasn't compiled.</param>
        /// <param name="template">The source template that wasn't compiled.</param>
        public TemplateCompilationException(IEnumerable <RazorEngineCompilerError> errors, CompilationData files, ITemplateSource template)
            : base(TemplateCompilationException.GetMessage(errors, files, template))
        {
            var list = errors.ToList();

            CompilerErrors  = new ReadOnlyCollection <RazorEngineCompilerError>(list);
            CompilationData = files;
            Template        = template.Template;
        }
        /// <summary>
        /// Compiles the given function
        /// </summary>
        /// <param name="function">The compilationData</param>
        public void CompileFunction(CompilationData compilationData)
        {
            var function = compilationData.Function;
            this.CreateProlog(compilationData);

            for (int i = 0; i < function.Instructions.Count; i++)
            {
                this.GenerateInstruction(compilationData, function.Instructions[i], i);
            }
        }
Exemplo n.º 11
0
        internal static CompilationData GetOrCreateCachedCompilationData(Compilation compilation)
        {
            CompilationData data;

            if (!s_cachedCompilationData.TryGetTarget(out data) || data == null || data.Compilation != compilation)
            {
                data = new CompilationData(compilation);
                s_cachedCompilationData.SetTarget(data);
            }

            return(data);
        }
Exemplo n.º 12
0
 public AnalysisState(ImmutableArray <DiagnosticAnalyzer> analyzers, CompilationData compilationData, CompilationOptions compilationOptions)
 {
     _gate                   = new SemaphoreSlim(initialCount: 1);
     _analyzerStateMap       = CreateAnalyzerStateMap(analyzers, out _analyzerStates);
     _compilationData        = compilationData;
     _compilationOptions     = compilationOptions;
     _pendingSourceEvents    = new Dictionary <SyntaxTree, HashSet <CompilationEvent> >();
     _pendingNonSourceEvents = new HashSet <CompilationEvent>();
     _partialSymbolsWithGeneratedSourceEvents = new HashSet <ISymbol>();
     _compilationEventsPool         = new ObjectPool <HashSet <CompilationEvent> >(() => new HashSet <CompilationEvent>());
     _pooledEventsWithAnyActionsSet = new HashSet <CompilationEvent>();
 }
        /// <summary>
        /// Creates the function epilog
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void CreateEpilog(CompilationData compilationData)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var virtualAssembler = compilationData.VirtualAssembler;

            if (compilationData.VirtualAssembler.NeedSpillRegister)
            {
                Assembler.Pop(generatedCode, virtualAssembler.GetIntSpillRegister());
            }

            //Restore the base pointer
            Assembler.Move(generatedCode, Register.SP, Register.BP);
            Assembler.Pop(generatedCode, Register.BP);
        }
Exemplo n.º 14
0
 public AnalysisState(ImmutableArray<DiagnosticAnalyzer> analyzers, CompilationData compilationData)
 {
     _gate = new object();
     _analyzerStateMap = CreateAnalyzerStateMap(analyzers, out _analyzerStates);
     _compilationData = compilationData;
     _pendingSourceEvents = new Dictionary<SyntaxTree, HashSet<CompilationEvent>>();
     _pendingNonSourceEvents = new HashSet<CompilationEvent>();
     _lazyAnalyzerActionCountsMap = null;
     _semanticModelsMap = new ConditionalWeakTable<SyntaxTree, SemanticModel>();
     _treesWithGeneratedSourceEvents = new HashSet<SyntaxTree>();
     _partialSymbolsWithGeneratedSourceEvents = new HashSet<ISymbol>();
     _compilationStartGenerated = false;
     _compilationEndGenerated = false;
     _compilationEventsPool = new ObjectPool<HashSet<CompilationEvent>>(() => new HashSet<CompilationEvent>());
     _pooledEventsWithAnyActionsSet = new HashSet<CompilationEvent>();
 }
Exemplo n.º 15
0
 public AnalysisState(ImmutableArray <DiagnosticAnalyzer> analyzers, CompilationData compilationData, CompilationOptions compilationOptions)
 {
     _gate                                    = new object();
     _analyzerStateMap                        = CreateAnalyzerStateMap(analyzers, out _analyzerStates);
     _compilationData                         = compilationData;
     _compilationOptions                      = compilationOptions;
     _pendingSourceEvents                     = new Dictionary <SyntaxTree, HashSet <CompilationEvent> >();
     _pendingNonSourceEvents                  = new HashSet <CompilationEvent>();
     _lazyAnalyzerActionCountsMap             = null;
     _treesWithGeneratedSourceEvents          = new HashSet <SyntaxTree>();
     _partialSymbolsWithGeneratedSourceEvents = new HashSet <ISymbol>();
     _compilationStartGenerated               = false;
     _compilationEndGenerated                 = false;
     _compilationEventsPool                   = new ObjectPool <HashSet <CompilationEvent> >(() => new HashSet <CompilationEvent>());
     _pooledEventsWithAnyActionsSet           = new HashSet <CompilationEvent>();
 }
Exemplo n.º 16
0
        /// <summary>
        /// Compiles the given function
        /// </summary>
        /// <param name="function">The function to compile</param>
        /// <returns>A pointer to the start of the compiled function</returns>
        public IntPtr Compile(Function function)
        {
            //Compile the function
            var compilationData = new CompilationData(this.virtualMachine, function);
            this.compiledFunctions.Add(function, compilationData);

            if (function.Optimize)
            {
                this.optimizedCodeGen.CompileFunction(compilationData);
            }
            else
            {
                this.codeGen.CompileFunction(compilationData);
            }

            //Allocate native memory. The instructions will be copied later when all symbols has been resolved.
            var memory = this.memoryManager.AllocateCode(function.GeneratedCode.Count);
            function.Definition.SetEntryPoint(memory);

            return memory;
        }
Exemplo n.º 17
0
        public override Tuple <Type, CompilationData> CompileType(TypeContext context)
        {
            var sourceCode   = GetCodeCompileUnit(context);
            var assemblyName = GetAssemblyName(context);

            (new PermissionSet(PermissionState.Unrestricted)).Assert();
            var tempDir = GetTemporaryDirectory();

            var sourceCodeFile = Path.Combine(tempDir, String.Format("{0}.{1}", assemblyName, SourceFileExtension));

            File.WriteAllText(sourceCodeFile, sourceCode);

            var references = GetAllReferences(context);

            var compilation =
                GetEmptyCompilation(assemblyName)
                .AddSyntaxTrees(
                    GetSyntaxTree(sourceCode, sourceCodeFile))
                .AddReferences(GetMetadataReferences(references));

            compilation =
                compilation
                .WithOptions(
                    CreateOptions(context)
                    .WithOutputKind(OutputKind.DynamicallyLinkedLibrary)
                    .WithPlatform(Platform.AnyCpu)
                    .WithSourceReferenceResolver(new RazorEngineSourceReferenceResolver(sourceCodeFile)));

            var assemblyFile = Path.Combine(tempDir, String.Format("{0}.dll", assemblyName));

            var assemblyPdbFile = Path.Combine(tempDir, String.Format("{0}.pdb", assemblyName));
            var compilationData = new CompilationData(sourceCode, tempDir);

            using (var assemblyStream = File.Open(assemblyFile, FileMode.Create, FileAccess.ReadWrite))
                using (var pdbStream = File.Open(assemblyPdbFile, FileMode.Create, FileAccess.ReadWrite))
                {
                    var opts = new EmitOptions()
                               .WithPdbFilePath(assemblyPdbFile);
                    var pdbStreamHelper = pdbStream;

                    if (IsMono())
                    {
                        opts = opts.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
                    }

                    EmitResult result = null;
                    if (Debugger.IsAttached)
                    {
                        result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);
                    }
                    else
                    {
                        result = compilation.Emit(assemblyStream);
                    }
                    //var result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);
                    //var result = compilation.Emit(assemblyStream);
                    if (!result.Success)
                    {
                        var errors =
                            result.Diagnostics.Select(diag =>
                        {
                            var lineSpan = diag.Location.GetLineSpan();
                            return(new Templating.RazorEngineCompilerError(
                                       string.Format("{0}", diag.GetMessage()),
                                       lineSpan.Path,
                                       lineSpan.StartLinePosition.Line,
                                       lineSpan.StartLinePosition.Character,
                                       diag.Id,
                                       diag.Severity != DiagnosticSeverity.Error));
                        });

                        throw new Templating.TemplateCompilationException(errors, compilationData, context.TemplateContent);
                    }
                }

            // load file and return loaded type.
            Assembly assembly;

            if (DisableTempFileLocking)
            {
                assembly = File.Exists(assemblyPdbFile)
                    ? Assembly.Load(File.ReadAllBytes(assemblyFile), File.ReadAllBytes(assemblyPdbFile))
                    : Assembly.Load(File.ReadAllBytes(assemblyFile));
            }
            else
            {
                assembly = Assembly.LoadFrom(assemblyFile);
            }
            var type = assembly.GetType(DynamicTemplateNamespace + "." + context.ClassName);

            return(Tuple.Create(type, compilationData));
        }
Exemplo n.º 18
0
        /// <summary>
        /// Resolves the call target for the given function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void ResolveCallTargets(CompilationData compilationData)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            long entryPoint = compilationData.Function.Definition.EntryPoint.ToInt64();

            foreach (var unresolvedCall in compilationData.UnresolvedFunctionCalls)
            {
                long toCallAddress = unresolvedCall.Function.EntryPoint.ToInt64();

                //Update the call target
                if (unresolvedCall.AddressMode == FunctionCallAddressModes.Absolute)
                {
                    NativeHelpers.SetLong(generatedCode, unresolvedCall.CallSiteOffset + 2, toCallAddress);
                }
                else
                {
                    int target = (int)(toCallAddress - (entryPoint + unresolvedCall.CallSiteOffset + 5));
                    NativeHelpers.SetInt(generatedCode, unresolvedCall.CallSiteOffset + 1, target);
                }
            }

            compilationData.UnresolvedFunctionCalls.Clear();
        }
Exemplo n.º 19
0
        public bool Save(string path, Core.Version version, ClientFeatures features)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            if (this.Disposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            if (!this.Loaded || this.Compiling)
            {
                return(false);
            }

            if (features == ClientFeatures.None || features == ClientFeatures.Transparency)
            {
                features |= version.Value >= (ushort)DatFormat.Format_755 ? ClientFeatures.PatternZ : features;
                features |= version.Value >= (ushort)DatFormat.Format_960 ? ClientFeatures.Extended : features;
                features |= version.Value >= (ushort)DatFormat.Format_1050 ? ClientFeatures.FrameDurations : features;
                features |= version.Value >= (ushort)DatFormat.Format_1057 ? ClientFeatures.FrameGroups : features;
            }

            string directory = Path.GetDirectoryName(path);

            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            if (!this.Changed && this.Version.Equals(version) && this.ClientFeatures == features)
            {
                //  just copy the content and reload if nothing has changed.
                if (this.FilePath != null && !this.FilePath.Equals(path))
                {
                    File.Copy(this.FilePath, path, true);

                    if (!this.InternalLoad(path, version, features, true))
                    {
                        return(false);
                    }

                    if (this.ProgressChanged != null)
                    {
                        this.ProgressChanged(this, 100);
                    }

                    if (this.StorageCompiled != null)
                    {
                        this.StorageCompiled(this);
                    }
                }

                return(true);
            }

            this.compilationData          = new CompilationData();
            this.compilationData.Path     = path;
            this.compilationData.TmpPath  = Path.Combine(directory, Path.GetFileNameWithoutExtension(path) + ".tmp");
            this.compilationData.Version  = version;
            this.compilationData.Features = features;
            this.Compiling = true;
            this.worker.RunWorkerAsync();
            return(true);
        }
        /// <summary>
        /// Generates native code for the given instruction
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="instruction">The current instruction</param>
        /// <param name="index">The index of the instruction</param>
        private void GenerateInstruction(CompilationData compilationData, VirtualInstruction virtualInstruction, int index)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var operandStack = compilationData.OperandStack;
            var funcDef = compilationData.Function.Definition;

            compilationData.InstructionMapping.Add(generatedCode.Count);

            var instruction = virtualInstruction.Instruction;
            var registerAllocation = compilationData.RegisterAllocation;
            var virtualAssembler = compilationData.VirtualAssembler;
            int stackOffset = 1;

            Func<VirtualRegister> GetAssignRegister = () =>
            {
                return virtualInstruction.AssignRegister.Value;
            };

            Func<int, VirtualRegister> GetUseRegister = x =>
            {
                return virtualInstruction.UsesRegisters[x];
            };

            switch (instruction.OpCode)
            {
                case OpCodes.LoadInt:
                    {
                        var storeReg = GetAssignRegister();

                        virtualAssembler.GenerateOneRegisterWithValueInstruction(
                            storeReg,
                            instruction.IntValue,
                            Assembler.Move,
                            Assembler.Move);
                    }
                    break;
                case OpCodes.LoadFloat:
                    {
                        var storeReg = GetAssignRegister();
                        var storeRegister = virtualAssembler.GetFloatRegisterForVirtual(storeReg);
                        int floatPattern = BitConverter.ToInt32(BitConverter.GetBytes(instruction.FloatValue), 0);

                        if (storeRegister.HasValue)
                        {
                            //IntPtr valuePtr = virtualMachine.Compiler.MemoryManager.AllocateReadonly(instruction.FloatValue);
                            //RawAssembler.MoveMemoryToRegister(generatedCode, storeRegister.Value, valuePtr.ToInt32());
                            Assembler.Push(generatedCode, floatPattern);
                            Assembler.Pop(generatedCode, storeRegister.Value);
                        }
                        else
                        {
                            //int floatPattern = BitConverter.ToInt32(BitConverter.GetBytes(instruction.FloatValue), 0);
                            var storeStackOffset = virtualAssembler.CalculateStackOffset(storeReg).Value;
                            Assembler.Move(generatedCode, new MemoryOperand(Register.BP, storeStackOffset), floatPattern);
                        }
                    }
                    break;
                case OpCodes.AddInt:
                case OpCodes.SubInt:
                case OpCodes.MulInt:
                case OpCodes.DivInt:
                    {
                        var op2Reg = GetUseRegister(0);
                        var op1Reg = GetUseRegister(1);
                        var storeReg = GetAssignRegister();
                        bool moveOp1ToStore = true;

                        switch (instruction.OpCode)
                        {
                            case OpCodes.AddInt:
                                virtualAssembler.GenerateTwoRegistersInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Add,
                                    Assembler.Add,
                                    Assembler.Add);
                                break;
                            case OpCodes.SubInt:
                                virtualAssembler.GenerateTwoRegistersInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Sub,
                                    Assembler.Sub,
                                    Assembler.Sub);
                                break;
                            case OpCodes.MulInt:
                                Action<IList<byte>, MemoryOperand, IntRegister> multRegisterToMemoryRegisterWithOffset = (gen, destMem, src) =>
                                {
                                    var spillReg = virtualAssembler.GetIntSpillRegister();
                                    Assembler.Move(gen, spillReg, destMem);
                                    Assembler.Mult(gen, spillReg, src);
                                    Assembler.Move(gen, destMem, spillReg);
                                };

                                virtualAssembler.GenerateTwoRegistersInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Mult,
                                    Assembler.Mult,
                                    multRegisterToMemoryRegisterWithOffset,
                                    MemoryRewrite.MemoryOnRight);
                                break;
                            case OpCodes.DivInt:
                                {
                                    moveOp1ToStore = false;

                                    //The idiv instruction modifies the rdx and rax instruction, so we save them.
                                    var op1Register = virtualAssembler.GetIntRegisterForVirtual(op1Reg);

                                    IList<IntRegister> saveRegisters = null;

                                    if (op1Register.HasValue && op1Register == Register.AX)
                                    {
                                        saveRegisters = virtualAssembler.GetAliveRegisters(index)
                                           .Where(x =>
                                                x.Type == HardwareRegisterType.Int
                                                && x.IntRegister == new IntRegister(Register.DX))
                                           .Select(x => x.IntRegister)
                                           .ToList();
                                    }
                                    else
                                    {
                                        saveRegisters = virtualAssembler.GetAliveRegisters(index)
                                           .Where(x =>
                                                x.Type == HardwareRegisterType.Int
                                                && (x == new IntRegister(Register.AX) || x == new IntRegister(Register.DX)))
                                           .Select(x => x.IntRegister)
                                           .ToList();
                                    }

                                    foreach (var register in saveRegisters)
                                    {
                                        Assembler.Push(generatedCode, register);
                                    }

                                    //Move the first operand to rax
                                    virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                                        Register.AX,
                                        op1Reg,
                                        Assembler.Move,
                                        Assembler.Move,
                                        true);

                                    //Move the second operand to the spill register.
                                    //Not moving to a spill register will cause div by zero if the second operand is in the rdx register.
                                    var spillReg = virtualAssembler.GetIntSpillRegister();
                                    var op2Register = virtualAssembler.GetIntRegisterForVirtual(op2Reg);
                                    bool needSpill = false;

                                    if (op2Register.HasValue && op2Register.Value == Register.DX)
                                    {
                                        needSpill = true;
                                        virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                                            spillReg,
                                            op2Reg,
                                            Assembler.Move,
                                            Assembler.Move);
                                    }

                                    //This sign extends the rax register
                                    generatedCode.Add(0x48);
                                    generatedCode.Add(0x99);

                                    //Divide the register
                                    if (needSpill)
                                    {
                                        Assembler.Div(generatedCode, spillReg);
                                    }
                                    else
                                    {
                                        virtualAssembler.GenerateOneRegisterInstruction(
                                            op2Reg,
                                            Assembler.Div,
                                            Assembler.Div);
                                    }

                                    //Move the result
                                    virtualAssembler.GenerateTwoRegisterFixedSourceInstruction(
                                        storeReg,
                                        Register.AX,
                                        Assembler.Move,
                                        Assembler.Move,
                                        true);

                                    //Restore saved registers
                                    var storeRegister = virtualAssembler.GetIntRegisterForVirtual(storeReg);

                                    foreach (var register in saveRegisters.Reverse())
                                    {
                                        if (storeRegister.HasValue)
                                        {
                                            if (storeRegister != Register.AX)
                                            {
                                                Assembler.Pop(generatedCode, register);
                                            }
                                            else
                                            {
                                                Assembler.Pop(generatedCode);
                                            }
                                        }
                                        else
                                        {
                                            Assembler.Pop(generatedCode, register);
                                        }
                                    }
                                }
                                break;
                        }

                        if (moveOp1ToStore && op1Reg != storeReg)
                        {
                            virtualAssembler.GenerateTwoRegistersInstruction(
                                storeReg,
                                op1Reg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                    }
                    break;
                case OpCodes.AddFloat:
                case OpCodes.SubFloat:
                case OpCodes.MulFloat:
                case OpCodes.DivFloat:
                    {
                        var op2Reg = GetUseRegister(0);
                        var op1Reg = GetUseRegister(1);
                        var storeReg = GetAssignRegister();

                        switch (instruction.OpCode)
                        {
                            case OpCodes.AddFloat:
                                virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Add,
                                    Assembler.Add);
                                break;
                            case OpCodes.SubFloat:
                                virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Sub,
                                    Assembler.Sub);
                                break;
                            case OpCodes.MulFloat:
                                virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Mult,
                                    Assembler.Mult);
                                break;
                            case OpCodes.DivFloat:
                                virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                    op1Reg,
                                    op2Reg,
                                    Assembler.Div,
                                    Assembler.Div);
                                break;
                        }

                        if (op1Reg != storeReg)
                        {
                            virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                storeReg,
                                op1Reg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                    }
                    break;
                case OpCodes.Call:
                    {
                        var signature = this.virtualMachine.Binder.FunctionSignature(
                            instruction.StringValue,
                            instruction.Parameters);

                        var funcToCall = this.virtualMachine.Binder.GetFunction(signature);

                        //Save registers
                        var aliveRegisters = virtualAssembler.GetAliveRegisters(index).ToList();
                        var aliveRegistersStack = new Dictionary<HardwareRegister, int>();
                        int stackIndex = 0;

                        foreach (var register in aliveRegisters)
                        {
                            Assembler.Push(generatedCode, register);
                            aliveRegistersStack.Add(register, stackIndex++);
                        }

                        //Align the stack
                        int stackAlignment = this.callingConvetions.CalculateStackAlignment(
                            compilationData,
                            funcToCall.Parameters,
                            aliveRegisters.Count);

                        if (stackAlignment > 0)
                        {
                            Assembler.Sub(generatedCode, Register.SP, stackAlignment);
                        }

                        //Set the function arguments
                        this.callingConvetions.CallFunctionArguments(
                            compilationData,
                            virtualInstruction.UsesRegisters,
                            aliveRegistersStack,
                            funcToCall);

                        //Reserve 32 bytes for the called function to spill registers
                        Assembler.Sub(generatedCode, Register.SP, 32);

                        //Generate the call
                        if (funcToCall.IsManaged)
                        {
                            //Mark that the function call needs to be patched with the entry point later
                            compilationData.UnresolvedFunctionCalls.Add(new UnresolvedFunctionCall(
                                FunctionCallAddressModes.Relative,
                                funcToCall,
                                generatedCode.Count));

                            Assembler.Call(generatedCode, 0);
                        }
                        else
                        {
                            this.GenerateCall(generatedCode, funcToCall.EntryPoint);
                        }

                        //Unalign the stack
                        Assembler.Add(generatedCode, Register.SP, stackAlignment + 32);

                        //Hande the return value
                        var returnValueReg = VirtualRegister.Invalid;

                        if (!funcToCall.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
                        {
                            returnValueReg = GetAssignRegister();
                        }

                        this.callingConvetions.HandleReturnValue(compilationData, funcToCall, returnValueReg);
                        var assignRegister = virtualAssembler.GetRegisterForVirtual(returnValueReg);

                        //Restore registers
                        foreach (var register in aliveRegisters.Reverse<HardwareRegister>())
                        {
                            //If the assign register is allocated, check if used.
                            if (assignRegister.HasValue)
                            {
                                if (register != assignRegister.Value)
                                {
                                    Assembler.Pop(generatedCode, register);
                                }
                                else
                                {
                                    //The assign register will have the return value as value, so don't pop to a register.
                                    Assembler.Pop(generatedCode);
                                }
                            }
                            else
                            {
                                Assembler.Pop(generatedCode, register);
                            }
                        }
                    }
                    break;
                case OpCodes.Ret:
                    {
                        //Handle the return value
                        var returnValueReg = VirtualRegister.Invalid;

                        if (!funcDef.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
                        {
                            returnValueReg = GetUseRegister(0);
                        }

                        this.callingConvetions.MakeReturnValue(compilationData, returnValueReg);

                        //Restore the base pointer
                        this.CreateEpilog(compilationData);

                        //Make the return
                        Assembler.Return(generatedCode);
                    }
                    break;
                case OpCodes.LoadArgument:
                    {
                        //Load the virtual register with the argument valuie
                        int argOffset = (instruction.IntValue + stackOffset) * -Assembler.RegisterSize;
                        var storeReg = GetAssignRegister();

                        if (storeReg.Type == VirtualRegisterType.Integer)
                        {
                            virtualAssembler.GenerateOneRegisterMemorySourceInstruction(
                                storeReg,
                                new MemoryOperand(Register.BP, argOffset),
                                Assembler.Move,
                                Assembler.Move);
                        }
                        else
                        {
                            virtualAssembler.GenerateOneRegisterMemorySourceFloatInstruction(
                              storeReg,
                              new MemoryOperand(Register.BP, argOffset),
                              Assembler.Move,
                              Assembler.Move);
                        }
                    }
                    break;
                case OpCodes.LoadLocal:
                    {
                        var valueReg = GetAssignRegister();
                        var localReg = GetUseRegister(0);

                        if (localReg.Type == VirtualRegisterType.Float)
                        {
                            virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                valueReg,
                                localReg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                        else
                        {
                            virtualAssembler.GenerateTwoRegistersInstruction(
                                valueReg,
                                localReg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                    }
                    break;
                case OpCodes.StoreLocal:
                    {
                        var valueReg = GetUseRegister(0);
                        var localReg = GetAssignRegister();

                        if (localReg.Type == VirtualRegisterType.Float)
                        {
                            virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                localReg,
                                valueReg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                        else
                        {
                            virtualAssembler.GenerateTwoRegistersInstruction(
                                localReg,
                                valueReg,
                                Assembler.Move,
                                Assembler.Move,
                                Assembler.Move);
                        }
                    }
                    break;
                case OpCodes.Branch:
                    Assembler.Jump(generatedCode, JumpCondition.Always, 0);

                    compilationData.UnresolvedBranches.Add(
                        generatedCode.Count - 5,
                        new UnresolvedBranchTarget(instruction.IntValue, 5));
                    break;
                case OpCodes.BranchEqual:
                case OpCodes.BranchNotEqual:
                case OpCodes.BranchGreaterThan:
                case OpCodes.BranchGreaterOrEqual:
                case OpCodes.BranchLessThan:
                case OpCodes.BranchLessOrEqual:
                    {
                        var opType = compilationData.Function.OperandTypes[index].Last();
                        bool unsignedComparison = false;

                        var op2Reg = GetUseRegister(0);
                        var op1Reg = GetUseRegister(1);

                        //Compare
                        if (opType.IsPrimitiveType(PrimitiveTypes.Float))
                        {
                            unsignedComparison = true;
                            virtualAssembler.GenerateTwoRegistersFloatInstruction(
                                op1Reg,
                                op2Reg,
                                Assembler.Compare,
                                Assembler.Compare);
                        }
                        else
                        {
                            virtualAssembler.GenerateTwoRegistersInstruction(
                                op1Reg,
                                op2Reg,
                                Assembler.Compare,
                                Assembler.Compare,
                                Assembler.Compare);
                        }

                        JumpCondition condition = JumpCondition.Always;
                        switch (instruction.OpCode)
                        {
                            case OpCodes.BranchEqual:
                                condition = JumpCondition.Equal;
                                break;
                            case OpCodes.BranchNotEqual:
                                condition = JumpCondition.NotEqual;
                                break;
                            case OpCodes.BranchGreaterThan:
                                condition = JumpCondition.GreaterThan;
                                break;
                            case OpCodes.BranchGreaterOrEqual:
                                condition = JumpCondition.GreaterThanOrEqual;
                                break;
                            case OpCodes.BranchLessThan:
                                condition = JumpCondition.LessThan;
                                break;
                            case OpCodes.BranchLessOrEqual:
                                condition = JumpCondition.LessThanOrEqual;
                                break;
                        }

                        Assembler.Jump(generatedCode, condition, 0, unsignedComparison);

                        compilationData.UnresolvedBranches.Add(
                            generatedCode.Count - 6,
                            new UnresolvedBranchTarget(instruction.IntValue, 6));
                    }
                    break;
            }
        }
        /// <summary>
        /// Zeroes the locals
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void ZeroLocals(CompilationData compilationData)
        {
            var func = compilationData.Function;
            if (func.Locals.Count > 0)
            {
                //Zero rax
                Assembler.Xor(func.GeneratedCode, Register.AX, Register.AX);

                for (int i = 0; i < func.Locals.Count; i++)
                {
                    int localOffset = (i + func.Definition.Parameters.Count + 1) * -Assembler.RegisterSize;
                    Assembler.Move(
                        func.GeneratedCode,
                        new MemoryOperand(Register.BP, localOffset),
                        Register.AX); //mov [rbp+local], rax
                }
            }
        }
        /// <summary>
        /// Handles the given function call argument
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="argumentIndex">The index of the argument</param>
        /// <param name="argumentType">The type of the argument</param>
        /// <param name="argumentRegisters">The virtual registers for the arguments</param>
        /// <param name="aliveRegistersStack">The alive registers stack</param>
        /// <param name="toCall">The function to call</param>
        public void CallFunctionArgument(
            CompilationData compilationData,
            int argumentIndex, VMType argumentType,
            IReadOnlyList<VirtualRegister> argumentRegisters,
            IDictionary<HardwareRegister, int> aliveRegistersStack,
            FunctionDefinition toCall)
        {
            var virtualAssembler = compilationData.VirtualAssembler;
            var regAlloc = compilationData.RegisterAllocation;
            var generatedCode = compilationData.Function.GeneratedCode;
            int thisNumArgs = compilationData.Function.Definition.Parameters.Count;
            int numArgs = toCall.Parameters.Count;

            int argsStart = 1 + compilationData.StackSize / Assembler.RegisterSize;

            if (virtualAssembler.NeedSpillRegister)
            {
                argsStart += 1;
            }

            int alignment = this.CalculateStackAlignment(compilationData, toCall.Parameters, aliveRegistersStack.Count);

            var virtualReg = argumentRegisters[numArgs - 1 - argumentIndex];
            var virtualRegStack = regAlloc.GetStackIndex(virtualReg);

            //Check if to pass argument by via the stack
            if (argumentIndex >= numRegisterArguments)
            {
                //Move arguments to the stack
                HardwareRegister spillReg;
                int stackOffset = 0;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    spillReg = virtualAssembler.GetFloatSpillRegister();

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value];
                    }
                }
                else
                {
                    spillReg = virtualAssembler.GetIntSpillRegister();

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value];
                    }
                }

                var argMemory = new MemoryOperand();

                if (virtualRegStack.HasValue)
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        virtualAssembler.CalculateStackOffset(virtualRegStack.Value));
                }
                else
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        -(argsStart + stackOffset)
                        * Assembler.RegisterSize);
                }

                Assembler.Move(generatedCode, spillReg, argMemory);
                Assembler.Push(generatedCode, spillReg);
            }
            else
            {
                HardwareRegister argReg;
                int stackOffset = 0;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    argReg = floatArgumentRegisters[argumentIndex];

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value];
                    }
                }
                else
                {
                    argReg = intArgumentRegisters[argumentIndex];

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value];
                    }
                }

                var argMemory = new MemoryOperand();

                if (virtualRegStack.HasValue)
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        virtualAssembler.CalculateStackOffset(virtualRegStack.Value));
                }
                else
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        -(argsStart + stackOffset)
                        * Assembler.RegisterSize);
                }

                Assembler.Move(generatedCode, argReg, argMemory);
            }
        }
        /// <summary>
        /// Moves an argument to the stack
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="argumentIndex">The argument index</param>
        /// <param name="argumentType">The type of the argument</param>
        private void MoveArgumentToStack(CompilationData compilationData, int argumentIndex, VMType argumentType)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            int argStackOffset = -(1 + argumentIndex) * Assembler.RegisterSize;

            if (argumentIndex >= numRegisterArguments)
            {
                int stackArgumentIndex = this.GetStackArgumentIndex(compilationData, argumentIndex);

                var argStackSource = new MemoryOperand(
                    Register.BP,
                    Assembler.RegisterSize * (6 + stackArgumentIndex));

                HardwareRegister tmpReg;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    tmpReg = compilationData.VirtualAssembler.GetFloatSpillRegister();
                }
                else
                {
                    tmpReg = new IntRegister(Register.AX);
                }

                Assembler.Move(generatedCode, tmpReg, argStackSource);
                Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), tmpReg);
            }
            else
            {
                //var argReg = floatArgumentRegisters[argumentIndex];
                HardwareRegister argReg;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    argReg = floatArgumentRegisters[argumentIndex];
                }
                else
                {
                    argReg = intArgumentRegisters[argumentIndex];
                }

                Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), argReg);
            }
        }
Exemplo n.º 24
0
        private CompilationWithAnalyzers(Compilation compilation, ImmutableArray<DiagnosticAnalyzer> analyzers, CompilationWithAnalyzersOptions analysisOptions, CancellationToken cancellationToken)
        {
            VerifyArguments(compilation, analyzers, analysisOptions);

            compilation = compilation
                .WithOptions(compilation.Options.WithReportSuppressedDiagnostics(analysisOptions.ReportSuppressedDiagnostics))
                .WithEventQueue(new AsyncQueue<CompilationEvent>());
            _compilation = compilation;
            _analyzers = analyzers;
            _analysisOptions = analysisOptions;
            _cancellationToken = cancellationToken;

            _compilationData = new CompilationData(_compilation);
            _analysisState = new AnalysisState(analyzers, _compilationData);
            _analysisResult = new AnalysisResult(analysisOptions.LogAnalyzerExecutionTime, analyzers);
            _driverPool = new ObjectPool<AnalyzerDriver>(() => _compilation.AnalyzerForLanguage(analyzers, AnalyzerManager.Instance));
            _executingConcurrentTreeTasksOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary<SyntaxTree, Tuple<Task, CancellationTokenSource>>() : null;
            _concurrentTreeTaskTokensOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary<Task, int>() : null;
            _executingCompilationOrNonConcurrentTreeTask = null;
        }
Exemplo n.º 25
0
        private async Task<ImmutableArray<Diagnostic>> GetAllDiagnosticsWithoutStateTrackingAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken)
        {
            AsyncQueue<CompilationEvent> eventQueue = _eventQueuePool.Allocate();
            AnalyzerDriver driver = null;

            try
            {
                // Clone the compilation with new event queue.
                var compilation = _compilation.WithEventQueue(eventQueue);
                var compilationData = new CompilationData(compilation);

                // Create and attach the driver to compilation.
                var categorizeDiagnostics = false;
                driver = compilation.AnalyzerForLanguage(analyzers, AnalyzerManager.Instance);
                driver.Initialize(compilation, _analysisOptions, compilationData, categorizeDiagnostics, cancellationToken);
                var analysisScope = new AnalysisScope(compilation, analyzers, concurrentAnalysis: _analysisOptions.ConcurrentAnalysis, categorizeDiagnostics: categorizeDiagnostics);
                driver.AttachQueueAndStartProcessingEvents(compilation.EventQueue, analysisScope, cancellationToken);

                // Force compilation diagnostics and wait for analyzer execution to complete.
                var compDiags = compilation.GetDiagnostics(cancellationToken);
                var analyzerDiags = await driver.GetDiagnosticsAsync(compilation).ConfigureAwait(false);
                return compDiags.AddRange(analyzerDiags);
            }
            finally
            {
                driver?.Dispose();
                FreeEventQueue(eventQueue, _eventQueuePool);
            }
        }
Exemplo n.º 26
0
        private async Task ComputeAnalyzerDiagnosticsWithoutStateTrackingAsync(CancellationToken cancellationToken)
        {
            // Exclude analyzers that have fully executed.
            var analyzers = _analysisResultBuilder.GetPendingAnalyzers(this.Analyzers);
            if (analyzers.IsEmpty)
            {
                return;
            }

            AsyncQueue<CompilationEvent> eventQueue = _eventQueuePool.Allocate();
            AnalyzerDriver driver = null;

            try
            {
                // Clone the compilation with new event queue.
                var compilation = _compilation.WithEventQueue(eventQueue);
                var compilationData = new CompilationData(compilation);

                // Create and attach the driver to compilation.
                var categorizeDiagnostics = true;
                driver = compilation.AnalyzerForLanguage(analyzers, AnalyzerManager.Instance);
                driver.Initialize(compilation, _analysisOptions, compilationData, categorizeDiagnostics, cancellationToken);
                var analysisScope = new AnalysisScope(compilation, analyzers, concurrentAnalysis: _analysisOptions.ConcurrentAnalysis, categorizeDiagnostics: categorizeDiagnostics);
                driver.AttachQueueAndStartProcessingEvents(compilation.EventQueue, analysisScope, cancellationToken);

                // Force compilation diagnostics and wait for analyzer execution to complete.
                var compDiags = compilation.GetDiagnostics(cancellationToken);
                await driver.WhenCompletedTask.ConfigureAwait(false);

                // Get analyzer action counts.
                var analyzerActionCounts = new Dictionary<DiagnosticAnalyzer, AnalyzerActionCounts>(analyzers.Length);
                foreach (var analyzer in analyzers)
                {
                    var actionCounts = await driver.GetAnalyzerActionCountsAsync(analyzer, compilation.Options, cancellationToken).ConfigureAwait(false);
                    analyzerActionCounts.Add(analyzer, actionCounts);
                }
                Func<DiagnosticAnalyzer, AnalyzerActionCounts> getAnalyzerActionCounts = analyzer => analyzerActionCounts[analyzer];

                _analysisResultBuilder.StoreAnalysisResult(analysisScope, driver, compilation, getAnalyzerActionCounts, fullAnalysisResultForAnalyzersInScope: true);
            }
            finally
            {
                driver?.Dispose();
                FreeEventQueue(eventQueue, _eventQueuePool);
            }
        }
Exemplo n.º 27
0
        public bool Save(string path, Core.Version version, ClientFeatures features)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (version == null)
            {
                throw new ArgumentNullException("version");
            }

            if (this.Disposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            if (!this.Loaded || this.Compiling)
            {
                return false;
            }

            if (features == ClientFeatures.None || features == ClientFeatures.Transparency)
            {
                features |= version.Value >= (ushort)DatFormat.Format_755 ? ClientFeatures.PatternZ : features;
                features |= version.Value >= (ushort)DatFormat.Format_960 ? ClientFeatures.Extended : features;
                features |= version.Value >= (ushort)DatFormat.Format_1050 ? ClientFeatures.FrameDurations : features;
                features |= version.Value >= (ushort)DatFormat.Format_1057 ? ClientFeatures.FrameGroups : features;
            }

            string directory = Path.GetDirectoryName(path);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            if (!this.Changed && this.Version.Equals(version) && this.ClientFeatures == features)
            {
                //  just copy the content and reload if nothing has changed.
                if (this.FilePath != null && !this.FilePath.Equals(path))
                {
                    File.Copy(this.FilePath, path, true);

                    if (!this.InternalLoad(path, version, features, true))
                    {
                        return false;
                    }

                    if (this.ProgressChanged != null)
                    {
                        this.ProgressChanged(this, 100);
                    }

                    if (this.StorageCompiled != null)
                    {
                        this.StorageCompiled(this, new EventArgs());
                    }
                }

                return true;
            }

            this.compilationData = new CompilationData();
            this.compilationData.Path = path;
            this.compilationData.TmpPath = Path.Combine(directory, Path.GetFileNameWithoutExtension(path) + ".tmp");
            this.compilationData.Version = version;
            this.compilationData.Features = features;
            this.Compiling = true;
            this.worker.RunWorkerAsync();
            return true;
        }
Exemplo n.º 28
0
        private static LinqExpression Compile(ElementExpression value, CompilationData data)
        {
            data.Cache ??= new Dictionary <CachedExpression, ParameterExpression>();
            data.GroupCache ??= new Dictionary <ExpressionGroup, LinqExpression[]>();
            switch (value)
            {
            case ICLRExpression s:
                return(s.Compile(e => Compile(e, data)));

            case Constant c:
                return(LinqExpression.Constant(c.Value));

            case Binary b:
                var ea = Compile(b.OpA, data);
                var eb = Compile(b.OpB, data);
                if (b.Operation == Binary.Op.Pow)
                {
                    var o = LinqExpression.Call(typeof(Math).GetMethod(nameof(Math.Pow)),
                                                LinqExpression.Convert(ea, typeof(double)), LinqExpression.Convert(eb, typeof(double)));
                    return(LinqExpression.Convert(o, typeof(float)));
                }

                if (b.Operation == Binary.Op.Atan2)
                {
                    var o = LinqExpression.Call(typeof(Math).GetMethod(nameof(Math.Atan2)),
                                                LinqExpression.Convert(ea, typeof(double)), LinqExpression.Convert(eb, typeof(double)));
                    return(LinqExpression.Convert(o, typeof(float)));
                }

                return(BinaryOps[b.Operation](ea, eb));

            case Unary u:
                var input  = Compile(u.Operand, data);
                var output = LinqExpression.Call(MethodOps[u.Operation], LinqExpression.Convert(input, typeof(double)));
                return(LinqExpression.Convert(output, typeof(float)));

            case CachedExpression v:
                if (!data.Cache.TryGetValue(v, out var varExpr))
                {
                    var result = Compile(v.Value, data);
                    data.Cache.Add(v, varExpr = LinqExpression.Parameter(result.Type));
                    data.Statements.Add(LinqExpression.Assign(varExpr, result));
                    data.Variables.Add(varExpr);
                }

                return(varExpr);

            case Mux m:
                if (m.Operands.Count == 2)
                {
                    return(LinqExpression.Condition(
                               LinqExpression.LessThan(Compile(m.Selector, data), LinqExpression.Constant(1f)),
                               Compile(m.Operands[0], data), Compile(m.Operands[1], data)));
                }

                var sel        = LinqExpression.Convert(Compile(m.Selector, data), typeof(int));
                var clampedSel =
                    LinqExpression.Condition(
                        LinqExpression.GreaterThanOrEqual(sel, LinqExpression.Constant(m.Operands.Count)),
                        LinqExpression.Constant(m.Operands.Count - 1), sel);
                var cases = m.Operands.Select(
                    (c, i) => LinqExpression.SwitchCase(Compile(c, data), LinqExpression.Constant(i)))
                            .ToArray();
                return(LinqExpression.Switch(clampedSel, cases[0].Body, cases));

            case State s:
                if (data.ResolveState == null)
                {
                    throw new Exception("Tried to compile a State expression outside of an ExpressionGroup");
                }

                return(data.ResolveState(s));

            case ExpressionGroupElement groupElement:
                if (!data.GroupCache.TryGetValue(groupElement.Group, out var groupList))
                {
                    data.GroupCache.Add(groupElement.Group, groupList = CompileGroup(groupElement.Group, data));
                }

                return(groupList[groupElement.Index]);
            }

            throw new Exception("Unknown expression " + value);
        }
Exemplo n.º 29
0
        private static LinqExpression[] CompileGroup(ExpressionGroup group, CompilationData data)
        {
            switch (group)
            {
            case Persist p:
                foreach (var s in p.State)
                {
                    if (!(s.InitialValue is Constant))
                    {
                        throw new Exception("Persist initial value is not constant");
                    }

                    data.StateValues.Add(((Constant)s.InitialValue).Value);
                }

                var assigns = new List <LinqExpression>();
                // TODO: Resolve parent scopes
                data.ResolveState = s => LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(s.Id));
                for (var i = 0; i < p.NewValue.Count; i++)
                {
                    var newValueExpr = Compile(p.NewValue[i], data);
                    assigns.Add(LinqExpression.Assign(
                                    LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(i)), newValueExpr));
                }

                data.Statements.AddRange(assigns);
                return(Enumerable.Range(0, p.Size)
                       .Select(i => LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(i)))
                       .ToArray());

            case Loop l:
                var stateList = new List <ParameterExpression>();
                foreach (var s in l.State)
                {
                    var initial  = Compile(s.InitialValue, data);
                    var variable = LinqExpression.Variable(initial.Type);
                    data.Statements.Add(LinqExpression.Assign(variable, initial));
                    data.Variables.Add(variable);
                    stateList.Add(variable);
                }

                // TODO: Resolve parent scopes
                data.ResolveState = s => stateList[s.Id];
                var parentStatements = data.Statements;
                // Make a new cache that copies in the old one, but won't leak State expressions
                data.Cache = new Dictionary <CachedExpression, ParameterExpression>(data.Cache);

                // Create a new statements list to put in the loop body
                var s1        = data.Statements = new List <LinqExpression>();
                var condition = Compile(l.Condition, data);
                var s2        = data.Statements = new List <LinqExpression>();
                var newState  = l.Body.Select(e => Compile(e, data)).ToArray();

                // Ensure that the entire state is only set at the end of the loop
                for (var i = 0; i < newState.Length; i++)
                {
                    var s = newState[i];
                    if (!(s is ParameterExpression))
                    {
                        var tmpVar = LinqExpression.Variable(s.Type);
                        data.Variables.Add(tmpVar);
                        s2.Add(LinqExpression.Assign(tmpVar, s));
                        newState[i] = tmpVar;
                    }
                }

                var breakLabel = LinqExpression.Label();
                var body       = LinqExpression.Block(s1
                                                      .Concat(new[]
                {
                    LinqExpression.IfThen(
                        LinqExpression.LessThan(condition, LinqExpression.Constant(1f)),
                        LinqExpression.Break(breakLabel))
                })
                                                      .Concat(s2)
                                                      .Concat(newState.Select((e, i) =>
                                                                              LinqExpression.Assign(stateList[i], e))));
                parentStatements.Add(LinqExpression.Loop(body, breakLabel));
                return(stateList.ToArray());

            default:
                throw new NotSupportedException();
            }
        }
Exemplo n.º 30
0
    public void NewChangeComilationCard(GameObject Parent, Button[] TargetList)
    {
        /* 이전에 사용한 TempCharacterList 및 IndexData 초기화 */
        for (int i = 0; i < TempCharacterList.Count; i++)
        {
            Destroy(TempCharacterList[i]);
        }

        TempCharacterList.Clear();
        IndexData = 0;

        /* 인벤토리를 순회하며 카드에 맞는 이미지로 변경한다 */
        for (int i = 0; i < Inventory.CompilationList.Count; i++)
        {
            Image[] ImageList = TargetList[i].GetComponentsInChildren <Image>();

            for (int j = 0; j < ImageList.Length; j++)
            {
                if (ImageList[j].name == "Property Image")
                {
                    switch (Inventory.CompilationList[i].Property)
                    {
                    case "Red": ImageList[j].sprite = Resources.Load("Sprites/UI/StageSelect/Red Icon", typeof(Sprite)) as Sprite; break;

                    case "Orange": ImageList[j].sprite = Resources.Load("Sprites/UI/StageSelect/Orange Icon", typeof(Sprite)) as Sprite; break;

                    case "Green": ImageList[j].sprite = Resources.Load("Sprites/UI/StageSelect/Green Icon", typeof(Sprite)) as Sprite; break;

                    default: break;
                    }
                }

                if (ImageList[j].name == "Rank")
                {
                    switch (Inventory.CompilationList[i].Rank)
                    {
                    case CardRank.S: ImageList[j].sprite = Resources.Load("Sprites/Compilation/S Rank", typeof(Sprite)) as Sprite; break;

                    case CardRank.A: ImageList[j].sprite = Resources.Load("Sprites/Compilation/A Rank", typeof(Sprite)) as Sprite; break;

                    case CardRank.B: ImageList[j].sprite = Resources.Load("Sprites/Compilation/B Rank", typeof(Sprite)) as Sprite; break;

                    default: ImageList[j].sprite = PanelPrefab; break;
                    }
                }

                if (ImageList[j].name == "Card Image")
                {
                    ImageList[j].sprite = Resources.Load(Inventory.CompilationList[i].Image, typeof(Sprite)) as Sprite;
                }
            }
        }

        /* 부모 오브젝트가 Compilation View일 경우 편성창을 여는 버튼 기능을 추가한다 */
        for (int i = 0; i < TargetList.Length; i++)
        {
            if (Parent.name == "Compilation View")
            {
                Button TempButton = TargetList[i].GetComponent <Button>();
                TempButton.onClick.AddListener(OpenCompilationListTap);

                CompilationData TempData = TargetList[i].GetComponent <CompilationData>();
                TempData.CompilationIndex = IndexData++;
            }
        }
    }
        /// <summary>
        /// Returns the stack argument index for the argument
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="argumentIndex">The argument index</param>
        private int GetStackArgumentIndex(CompilationData compilationData, int argumentIndex)
        {
            int stackArgIndex = 0;
            var parameterTypes = compilationData.Function.Definition.Parameters;

            int index = 0;
            foreach (var parameterType in parameterTypes)
            {
                if (index == argumentIndex)
                {
                    break;
                }

                if (index >= numRegisterArguments)
                {
                    stackArgIndex++;
                }

                index++;
            }

            return stackArgIndex;
        }
Exemplo n.º 32
0
        /// <summary>
        /// Gets a exact error message of the given error collection
        /// </summary>
        /// <param name="errors"></param>
        /// <param name="files"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        internal static string GetMessage(IEnumerable <RazorEngineCompilerError> errors, CompilationData files, string template)
        {
            var str1 = string.Join("\n\t", errors.Select(error =>
                                                         $" - {(error.IsWarning ? "warning" : "error")}: ({ error.Line}, { error.Column}) { error.ErrorText}"));
            string str2 =
                $"The template we tried to compile is: { Separate(template ?? string.Empty)}\n";
            var str3 = string.Empty;

            if (files.TmpFolder != null)
            {
                str3 =
                    $"Temporary files of the compilation can be found in (please delete the folder): { files.TmpFolder}\n";
            }
            var str4 = string.Empty;

            if (files.SourceCode != null)
            {
                str4 =
                    $"The generated source code is: { Separate(files.SourceCode)}\n";
            }
            var str5 = "\nList of loaded Assemblies:\n" + string.Join("\n\tLoaded Assembly: ", new UseCurrentAssembliesReferenceResolver().GetReferences().Select(r => r.GetFile()));

            return
                ("Errors while compiling a Template.\nPlease try the following to solve the situation:\n" +
                 "  * If the problem is about missing/invalid references or multiple defines either try to load \n" +
                 "    the missing references manually (in the compiling appdomain!) or\n" +
                 "    Specify your references manually by providing your own IReferenceResolver implementation.\n" +
                 "    Currently all references have to be available as files!\n" +
                 "  * If you get 'class' does not contain a definition for 'member': \n" +
                 "        try another modelType (for example 'null' to make the model dynamic).\n" +
                 "        NOTE: You CANNOT use typeof(dynamic) to make the model dynamic!\n" +
                 "    Or try to use static instead of anonymous/dynamic types.\n" +
                 "More details about the error:\n" +
                 $"{ str1}\n" +
                 $"{ str3}{ str2}{ str4}{ str5}");
        }
 /// <summary>
 /// Calculates the stack alignment
 /// </summary>
 /// <param name="compilationData">The compilation data</param>
 /// <param name="parameters">The parameters of the function to call</param>
 /// <param name="numSavedRegisters">The number of saved registers</param>
 public int CalculateStackAlignment(CompilationData compilationData, IReadOnlyList<VMType> parameterTypes, int numSavedRegisters)
 {
     int numStackArgs = this.CalculateStackArguments(parameterTypes);
     return ((numStackArgs + numSavedRegisters) % 2) * Assembler.RegisterSize;
 }
Exemplo n.º 34
0
 internal static bool TryGetCachedCompilationData(Compilation compilation, out CompilationData compilationData)
 {
     return s_cachedCompilationData.TryGetTarget(out compilationData) &&
         compilationData?.Compilation == compilation;
 }
        /// <summary>
        /// Generates native code for the given instruction
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="instruction">The current instruction</param>
        /// <param name="index">The index of the instruction</param>
        private void GenerateInstruction(CompilationData compilationData, Instruction instruction, int index)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var operandStack = compilationData.OperandStack;
            var funcDef = compilationData.Function.Definition;
            int stackOffset = 1;

            compilationData.InstructionMapping.Add(generatedCode.Count);

            switch (instruction.OpCode)
            {
                case OpCodes.Pop:
                    operandStack.PopRegister(Register.AX);
                    break;
                case OpCodes.LoadInt:
                    operandStack.PushInt(instruction.IntValue);
                    break;
                case OpCodes.LoadFloat:
                    int floatPattern = BitConverter.ToInt32(BitConverter.GetBytes(instruction.FloatValue), 0);
                    operandStack.PushInt(floatPattern);
                    break;
                case OpCodes.AddInt:
                case OpCodes.SubInt:
                case OpCodes.MulInt:
                case OpCodes.DivInt:
                    operandStack.PopRegister(Register.CX);
                    operandStack.PopRegister(Register.AX);

                    switch (instruction.OpCode)
                    {
                        case OpCodes.AddInt:
                            Assembler.Add(generatedCode, Register.AX, Register.CX);
                            break;
                        case OpCodes.SubInt:
                            Assembler.Sub(generatedCode, Register.AX, Register.CX);
                            break;
                        case OpCodes.MulInt:
                            Assembler.Mult(generatedCode, Register.AX, Register.CX);
                            break;
                        case OpCodes.DivInt:
                            //This sign extends the eax register
                            generatedCode.Add(0x99); //cdq
                            Assembler.Div(generatedCode, Register.CX);
                            break;
                    }

                    operandStack.PushRegister(Register.AX);
                    break;
                case OpCodes.AddFloat:
                case OpCodes.SubFloat:
                case OpCodes.MulFloat:
                case OpCodes.DivFloat:
                    operandStack.PopRegister(FloatRegister.XMM1);
                    operandStack.PopRegister(FloatRegister.XMM0);

                    switch (instruction.OpCode)
                    {
                        case OpCodes.AddFloat:
                            Assembler.Add(generatedCode, FloatRegister.XMM0, FloatRegister.XMM1);
                            break;
                        case OpCodes.SubFloat:
                            Assembler.Sub(generatedCode, FloatRegister.XMM0, FloatRegister.XMM1);
                            break;
                        case OpCodes.MulFloat:
                            Assembler.Mult(generatedCode, FloatRegister.XMM0, FloatRegister.XMM1);
                            break;
                        case OpCodes.DivFloat:
                            Assembler.Div(generatedCode, FloatRegister.XMM0, FloatRegister.XMM1);
                            break;
                    }

                    operandStack.PushRegister(FloatRegister.XMM0);
                    break;
                case OpCodes.Call:
                    {
                        var signature = this.virtualMachine.Binder.FunctionSignature(
                            instruction.StringValue,
                            instruction.Parameters);

                        var funcToCall = this.virtualMachine.Binder.GetFunction(signature);

                        //Align the stack
                        int stackAlignment = this.callingConvetions.CalculateStackAlignment(
                            compilationData,
                            funcToCall.Parameters);

                        if (stackAlignment > 0)
                        {
                            Assembler.Sub(generatedCode, Register.SP, stackAlignment);
                        }

                        //Set the function arguments
                        this.callingConvetions.CallFunctionArguments(compilationData, funcToCall);

                        //Reserve 32 bytes for called function to spill registers
                        Assembler.Sub(generatedCode, Register.SP, 32);

                        //Generate the call
                        if (funcToCall.IsManaged)
                        {
                            //Mark that the function call needs to be patched with the entry point later
                            compilationData.UnresolvedFunctionCalls.Add(new UnresolvedFunctionCall(
                                FunctionCallAddressModes.Relative,
                                funcToCall,
                                generatedCode.Count));

                            Assembler.Call(generatedCode, 0);
                        }
                        else
                        {
                            this.GenerateCall(generatedCode, funcToCall.EntryPoint);
                        }

                        //Unalign the stack
                        Assembler.Add(generatedCode, Register.SP, stackAlignment + 32);

                        //Hande the return value
                        this.callingConvetions.HandleReturnValue(compilationData, funcToCall);
                    }
                    break;
                case OpCodes.Ret:
                    //Handle the return value
                    this.callingConvetions.MakeReturnValue(compilationData);

                    //Restore the base pointer
                    this.CreateEpilog(compilationData);

                    //Make the return
                    Assembler.Return(generatedCode);
                    break;
                case OpCodes.LoadArgument:
                    {
                        //Load rax with the argument
                        int argOffset = (instruction.IntValue + stackOffset) * -Assembler.RegisterSize;

                        Assembler.Move(
                            generatedCode,
                            Register.AX,
                            new MemoryOperand(Register.BP, argOffset)); //mov rax, [rbp+<arg offset>]

                        //Push the loaded value
                        operandStack.PushRegister(Register.AX);
                    }
                    break;
                case OpCodes.LoadLocal:
                case OpCodes.StoreLocal:
                    {
                        //Load rax with the locals offset
                        int localOffset =
                            (stackOffset + instruction.IntValue + funcDef.Parameters.Count)
                            * -Assembler.RegisterSize;

                        if (instruction.OpCode == OpCodes.LoadLocal)
                        {
                            //Load rax with the local
                            Assembler.Move(
                                generatedCode,
                                Register.AX,
                                new MemoryOperand(Register.BP, localOffset)); //mov rax, [rbp+<offset>]

                            //Push the loaded value
                            operandStack.PushRegister(Register.AX);
                        }
                        else
                        {
                            //Pop the top operand
                            operandStack.PopRegister(Register.AX);

                            //Store the operand at the given local
                            Assembler.Move(
                                generatedCode,
                                new MemoryOperand(Register.BP, localOffset),
                                Register.AX); //mov [rbp+<local offset>], rax
                        }
                    }
                    break;
                case OpCodes.Branch:
                    Assembler.Jump(generatedCode, JumpCondition.Always, 0);

                    compilationData.UnresolvedBranches.Add(
                        generatedCode.Count - 5,
                        new UnresolvedBranchTarget(instruction.IntValue, 5));
                    break;
                case OpCodes.BranchEqual:
                case OpCodes.BranchNotEqual:
                case OpCodes.BranchGreaterThan:
                case OpCodes.BranchGreaterOrEqual:
                case OpCodes.BranchLessThan:
                case OpCodes.BranchLessOrEqual:
                    {
                        var opType = compilationData.Function.OperandTypes[index].Last();
                        bool unsignedComparison = false;

                        if (opType.IsPrimitiveType(PrimitiveTypes.Int))
                        {
                            //Pop 2 operands
                            operandStack.PopRegister(Register.CX);
                            operandStack.PopRegister(Register.AX);

                            //Compare
                            Assembler.Compare(generatedCode, Register.AX, Register.CX); //cmp rax, rcx
                        }
                        else if (opType.IsPrimitiveType(PrimitiveTypes.Float))
                        {
                            //Pop 2 operands
                            operandStack.PopRegister(FloatRegister.XMM1);
                            operandStack.PopRegister(FloatRegister.XMM0);

                            //Compare
                            generatedCode.AddRange(new byte[] { 0x0f, 0x2e, 0xc1 }); //ucomiss xmm0, xmm1
                            unsignedComparison = true;
                        }

                        JumpCondition condition = JumpCondition.Always;
                        switch (instruction.OpCode)
                        {
                            case OpCodes.BranchEqual:
                                condition = JumpCondition.Equal;
                                break;
                            case OpCodes.BranchNotEqual:
                                condition = JumpCondition.NotEqual;
                                break;
                            case OpCodes.BranchGreaterThan:
                                condition = JumpCondition.GreaterThan;
                                break;
                            case OpCodes.BranchGreaterOrEqual:
                                condition = JumpCondition.GreaterThanOrEqual;
                                break;
                            case OpCodes.BranchLessThan:
                                condition = JumpCondition.LessThan;
                                break;
                            case OpCodes.BranchLessOrEqual:
                                condition = JumpCondition.LessThanOrEqual;
                                break;
                        }

                        Assembler.Jump(generatedCode, condition, 0, unsignedComparison);

                        compilationData.UnresolvedBranches.Add(
                            generatedCode.Count - 6,
                            new UnresolvedBranchTarget(instruction.IntValue, 6));
                    }
                    break;
            }
        }
Exemplo n.º 36
0
        /// <summary>
        /// Initializes the <see cref="analyzerActions"/> and related actions maps for the analyzer driver.
        /// It kicks off the <see cref="WhenInitializedTask"/> task for initialization.
        /// Note: This method must be invoked exactly once on the driver.
        /// </summary>
        private void Initialize(AnalyzerExecutor analyzerExecutor, DiagnosticQueue diagnosticQueue, CompilationData compilationData, CancellationToken cancellationToken)
        {
            try
            {
                Debug.Assert(_initializeTask == null);

                this.analyzerExecutor = analyzerExecutor;
                this.compilationData = compilationData;
                this.DiagnosticQueue = diagnosticQueue;

                // Compute the set of effective actions based on suppression, and running the initial analyzers
                _initializeTask = Task.Run(async () =>
                {
                    var unsuppressedAnalyzers = GetUnsuppressedAnalyzers(analyzers, analyzerManager, analyzerExecutor);
                    this.analyzerActions = await GetAnalyzerActionsAsync(unsuppressedAnalyzers, analyzerManager, analyzerExecutor).ConfigureAwait(false);
                    _analyzerGateMap = await GetAnalyzerGateMapAsync(unsuppressedAnalyzers, analyzerManager, analyzerExecutor).ConfigureAwait(false);

                    _generatedCodeAnalysisFlagsMap = await GetGeneratedCodeAnalysisFlagsAsync(unsuppressedAnalyzers, analyzerManager, analyzerExecutor).ConfigureAwait(false);
                    _doNotAnalyzeGeneratedCode = ShouldSkipAnalysisOnGeneratedCode(unsuppressedAnalyzers);
                    _treatAllCodeAsNonGeneratedCode = ShouldTreatAllCodeAsNonGeneratedCode(unsuppressedAnalyzers, _generatedCodeAnalysisFlagsMap);
                    _lazyGeneratedCodeFilesMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, bool>();
                    _lazyGeneratedCodeSymbolsMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, ImmutableHashSet<ISymbol>>();
                    _generatedCodeAttribute = analyzerExecutor.Compilation?.GetTypeByMetadataName("System.CodeDom.Compiler.GeneratedCodeAttribute");

                    _symbolActionsByKind = MakeSymbolActionsByKind();
                    _semanticModelActionsMap = MakeSemanticModelActionsByAnalyzer();
                    _syntaxTreeActionsMap = MakeSyntaxTreeActionsByAnalyzer();
                    _compilationActionsMap = MakeCompilationActionsByAnalyzer(this.analyzerActions.CompilationActions);
                    _compilationEndActionsMap = MakeCompilationActionsByAnalyzer(this.analyzerActions.CompilationEndActions);
                }, cancellationToken);

                // create the primary driver task. 
                cancellationToken.ThrowIfCancellationRequested();

                _initializeSucceeded = true;
            }
            finally
            {
                if (_initializeTask == null)
                {
                    // Set initializeTask to be a cancelled task.
                    var tcs = new TaskCompletionSource<int>();
                    tcs.SetCanceled();
                    _initializeTask = tcs.Task;

                    // Set primaryTask to be a cancelled task.
                    tcs = new TaskCompletionSource<int>();
                    tcs.SetCanceled();
                    _primaryTask = tcs.Task;

                    // Try to set the DiagnosticQueue to be complete.
                    this.DiagnosticQueue.TryComplete();
                }
            }
        }
        /// <summary>
        /// Zeroes the locals
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void ZeroLocals(CompilationData compilationData)
        {
            var virtualAssembler = compilationData.VirtualAssembler;
            var func = compilationData.Function;

            if (func.Locals.Count > 0)
            {
                if (virtualAssembler.NeedSpillRegister)
                {
                    //Zero the spill register
                    var spillReg = virtualAssembler.GetIntSpillRegister();
                    Assembler.Xor(func.GeneratedCode, spillReg, spillReg);
                }

                foreach (var localRegister in compilationData.LocalVirtualRegisters)
                {
                    //Zero the local register
                    var localReg = virtualAssembler.GetRegisterForVirtual(localRegister);

                    if (localReg.HasValue)
                    {
                        switch (localReg.Value.Type)
                        {
                            case HardwareRegisterType.Int:
                                Assembler.Xor(func.GeneratedCode, localReg.Value.IntRegister, localReg.Value.IntRegister);
                                break;
                            case HardwareRegisterType.Float:
                                //IntPtr valuePtr = virtualMachine.Compiler.MemoryManager.AllocateReadonly(0);
                                //RawAssembler.MoveMemoryToRegister(func.GeneratedCode, localReg.Value.FloatRegister, valuePtr.ToInt32());
                                Assembler.Push(func.GeneratedCode, 0);
                                Assembler.Pop(func.GeneratedCode, localReg.Value.FloatRegister);
                                break;
                        }
                    }
                    else
                    {
                        var spillReg = virtualAssembler.GetIntSpillRegister();
                        int stackOffset =
                            -Assembler.RegisterSize
                            * (1 + compilationData.RegisterAllocation.GetStackIndex(localRegister) ?? 0);

                        Assembler.Move(func.GeneratedCode, new MemoryOperand(Register.BP, stackOffset), spillReg);
                    }
                }
            }
        }
Exemplo n.º 38
0
 internal static bool TryGetCachedCompilationData(Compilation compilation, out CompilationData compilationData)
 {
     return(s_cachedCompilationData.TryGetTarget(out compilationData) &&
            compilationData?.Compilation == compilation);
 }
 /// <summary>
 /// Handles the given function call arguments
 /// </summary>
 /// <param name="compilationData">The compilation data</param>
 /// <param name="argumentRegisters">The virtual registers for the arguments</param>
 /// <param name="aliveRegistersStack">The alive registers stack</param>
 /// <param name="toCall">The function to call</param>
 public void CallFunctionArguments(
     CompilationData compilationData,
     IReadOnlyList<VirtualRegister> argumentRegisters,
     IDictionary<HardwareRegister, int> aliveRegistersStack, FunctionDefinition toCall)
 {
     for (int arg = toCall.Parameters.Count - 1; arg >= 0; arg--)
     {
         this.CallFunctionArgument(compilationData, arg, toCall.Parameters[arg], argumentRegisters, aliveRegistersStack, toCall);
     }
 }
        /// <summary>
        /// Handles the return value from a function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="toCall">The function to call</param>
        /// <param name="returnValueRegister">The register to store the return value</param>
        public void HandleReturnValue(CompilationData compilationData, FunctionDefinition toCall, VirtualRegister returnValueRegister)
        {
            //If we have passed arguments via the stack, adjust the stack pointer.
            int numStackArgs = this.CalculateStackArguments(toCall.Parameters);
            var virtualAssembler = compilationData.VirtualAssembler;

            if (numStackArgs > 0)
            {
                Assembler.Add(
                    compilationData.Function.GeneratedCode,
                    Register.SP,
                    numStackArgs * Assembler.RegisterSize);
            }

            if (!toCall.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
            {
                if (toCall.ReturnType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    virtualAssembler.GenerateTwoRegisterFixedSourceInstruction(
                        returnValueRegister,
                        FloatRegister.XMM0,
                        Assembler.Move,
                        Assembler.Move,
                        true);
                }
                else
                {
                    virtualAssembler.GenerateTwoRegisterFixedSourceInstruction(
                        returnValueRegister,
                        Register.AX,
                        Assembler.Move,
                        Assembler.Move,
                        true);
                }
            }
        }
Exemplo n.º 41
0
        /// <summary>
        /// Resolves the native labels for the given function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        private void ResolveNativeLabels(CompilationData compilationData)
        {
            //var generatedCode = compilationData.Function.GeneratedCode;
            //long entryPoint = compilationData.Function.Definition.EntryPoint.ToInt64();

            //foreach (var nativeLabel in compilationData.UnresolvedNativeLabels)
            //{
            //    var source = nativeLabel.Key;
            //    var target = nativeLabel.Value.ToInt64();

            //    int nativeTarget = (int)(target - (entryPoint + source - 5));
            //    NativeHelpers.SetInt(generatedCode, source, (int)target);
            //}

            //compilationData.UnresolvedNativeLabels.Clear();
        }
        /// <summary>
        /// Makes the return value for a function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="returnValueRegister">The virtual register where the return value is stored</param>
        public void MakeReturnValue(CompilationData compilationData, VirtualRegister returnValueRegister)
        {
            var def = compilationData.Function.Definition;
            var virtualAssembler = compilationData.VirtualAssembler;

            if (!def.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
            {
                if (def.ReturnType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                       FloatRegister.XMM0,
                       returnValueRegister,
                       Assembler.Move,
                       Assembler.Move,
                       true);
                }
                else
                {
                    virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                       new IntRegister(Register.AX),
                       returnValueRegister,
                       Assembler.Move,
                       Assembler.Move,
                       true);
                }
            }
        }
        /// <summary>
        /// Gets a exact error message of the given error collection
        /// </summary>
        /// <param name="errors"></param>
        /// <param name="files"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        internal static string GetMessage(IEnumerable <RazorEngineCompilerError> errors, CompilationData files, ITemplateSource template)
        {
            var errorMsgs = string.Join("\n\t", errors.Select(error =>
                                                              string.Format(
                                                                  " - {0}: ({1}, {2}) {3}",
                                                                  error.IsWarning ? "warning" : "error",
                                                                  error.Line, error.Column, error.ErrorText)));

            const string rawTemplateFileMsg = "The template-file we tried to compile is: {0}\n";
            const string rawTemplate        = "The template we tried to compile is: {0}\n";
            const string rawTmpFiles        = "Temporary files of the compilation can be found in (please delete the folder): {0}\n";
            const string rawSourceCode      = "The generated source code is: {0}\n";

            string templateFileMsg;

            if (string.IsNullOrEmpty(template.TemplateFile))
            {
                templateFileMsg = string.Format(rawTemplate, Separate(template.Template ?? string.Empty));
            }
            else
            {
                templateFileMsg = string.Format(rawTemplateFileMsg, template.TemplateFile ?? string.Empty);
            }
            string tempFilesMsg = string.Empty;

            if (files.TmpFolder != null)
            {
                tempFilesMsg = string.Format(rawTmpFiles, files.TmpFolder);
            }

            string sourceCodeMessage = string.Empty;

            if (files.SourceCode != null)
            {
                sourceCodeMessage = string.Format(rawSourceCode, Separate(files.SourceCode));
            }

            var rawMessage = @"Errors while compiling a Template.
Please try the following to solve the situation:
  * If the problem is about missing references either try to load the missing references manually (in the compiling appdomain!) or
    Specify your references manually by providing your own IReferenceResolver implementation.
    Currently all references have to be available as files!
  * If you get 'class' does not contain a definition for 'member': 
        try another modelType (for example 'null' or 'typeof(DynamicObject)' to make the model dynamic).
        NOTE: You CANNOT use typeof(dynamic)!
    Or try to use static instead of anonymous/dynamic types.
More details about the error:
{0}
{1}{2}{3}";

            return(string.Format(rawMessage, errorMsgs, tempFilesMsg, templateFileMsg, sourceCodeMessage));
        }
        /// <summary>
        /// Moves the argument to the stack
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        public void MoveArgumentsToStack(CompilationData compilationData)
        {
            var function = compilationData.Function;
            var parameterTypes = function.Definition.Parameters;

            for (int argumentIndex = parameterTypes.Count - 1; argumentIndex >= 0; argumentIndex--)
            {
                this.MoveArgumentToStack(compilationData, argumentIndex, parameterTypes[argumentIndex]);
            }
        }
Exemplo n.º 45
0
        internal static CompilationData GetOrCreateCachedCompilationData(Compilation compilation)
        {
            CompilationData data;
            if (!s_cachedCompilationData.TryGetTarget(out data) || data == null || data.Compilation != compilation)
            {
                data = new CompilationData(compilation);
                s_cachedCompilationData.SetTarget(data);
            }

            return data;
        }
Exemplo n.º 46
0
        internal void Initialize(
           Compilation compilation,
           CompilationWithAnalyzersOptions analysisOptions,
           CompilationData compilationData,
           bool categorizeDiagnostics,
           CancellationToken cancellationToken)
        {
            Debug.Assert(_initializeTask == null);

            var diagnosticQueue = DiagnosticQueue.Create(categorizeDiagnostics);

            Action<Diagnostic> addNotCategorizedDiagnosticOpt = null;
            Action<Diagnostic, DiagnosticAnalyzer, bool> addCategorizedLocalDiagnosticOpt = null;
            Action<Diagnostic, DiagnosticAnalyzer> addCategorizedNonLocalDiagnosticOpt = null;
            if (categorizeDiagnostics)
            {
                addCategorizedLocalDiagnosticOpt = GetDiagnosticSink(diagnosticQueue.EnqueueLocal, compilation);
                addCategorizedNonLocalDiagnosticOpt = GetDiagnosticSink(diagnosticQueue.EnqueueNonLocal, compilation);
            }
            else
            {
                addNotCategorizedDiagnosticOpt = GetDiagnosticSink(diagnosticQueue.Enqueue, compilation);
            }

            // Wrap onAnalyzerException to pass in filtered diagnostic.
            Action<Exception, DiagnosticAnalyzer, Diagnostic> newOnAnalyzerException = (ex, analyzer, diagnostic) =>
            {
                var filteredDiagnostic = GetFilteredDiagnostic(diagnostic, compilation);
                if (filteredDiagnostic != null)
                {
                    if (analysisOptions.OnAnalyzerException != null)
                    {
                        analysisOptions.OnAnalyzerException(ex, analyzer, filteredDiagnostic);
                    }
                    else if (categorizeDiagnostics)
                    {
                        addCategorizedNonLocalDiagnosticOpt(filteredDiagnostic, analyzer);
                    }
                    else
                    {
                        addNotCategorizedDiagnosticOpt(filteredDiagnostic);
                    }
                }
            };

            if (analysisOptions.LogAnalyzerExecutionTime)
            {
                // If we are reporting detailed analyzer performance numbers, then do a dummy invocation of Compilation.GetTypeByMetadataName API upfront.
                // This API seems to cause a severe hit for the first analyzer invoking it and hence introduces lot of noise in the computed analyzer execution times.
                var unused = compilation.GetTypeByMetadataName("System.Object");
            }

            var analyzerExecutor = AnalyzerExecutor.Create(
                compilation, analysisOptions.Options ?? AnalyzerOptions.Empty, addNotCategorizedDiagnosticOpt, newOnAnalyzerException, analysisOptions.AnalyzerExceptionFilter,
                IsCompilerAnalyzer, analyzerManager, ShouldSkipAnalysisOnGeneratedCode, ShouldSuppressGeneratedCodeDiagnostic, GetAnalyzerGate,
                analysisOptions.LogAnalyzerExecutionTime, addCategorizedLocalDiagnosticOpt, addCategorizedNonLocalDiagnosticOpt, cancellationToken);

            Initialize(analyzerExecutor, diagnosticQueue, compilationData, cancellationToken);
        }