Beispiel #1
0
        public Job(CommandLine commandLine)
        {
            commandLine.ApplyTo(this);

            // Build input file list
            _inputFiles = new List <FileInfo>(commandLine.PositionalArguments.Count + (_interactive ? 1 : 0));
            foreach (string filePath in commandLine.PositionalArguments)
            {
                FileInfo tmpFile = new FileInfo(filePath);
                if (!tmpFile.Exists)
                {
                    Diagnostics.Report(Diagnostics.Severity.Error, $"{filePath} does not exist");
                }
                else if (tmpFile.Kind == FileType.Kind.UNCLASSIFIED)
                {
                    Diagnostics.Report(Diagnostics.Severity.Error, $"{filePath} is of unknown type");
                }
                else if (tmpFile.Kind == FileType.Kind.TARGET_ASSEMBLY ||
                         tmpFile.Kind == FileType.Kind.TARGET_OBJECT)
                {
                    Diagnostics.Report(Diagnostics.Severity.Error,
                                       "MonC cannot load target assembly or object files. External tools must be used for these.");
                }
                else
                {
                    _inputFiles.Add(tmpFile);
                }
            }

            // Additional interactive input file if requested
            if (_interactive)
            {
                _inputFiles.Add(FileInfo.Interactive);
            }

            Diagnostics.ThrowIfErrors();

            // Skip run is implied when output path is provided
            if (_outputPath != null)
            {
                _skipRun = true;
            }

            // VM is implied for debugger
            if (_debugger)
            {
                _skipRun = false;
            }

            if (_asm)
            {
                // Relocatable processing is implied for assembly output
                _reloc = true;
            }

            // Relocatable output always skips VM and may only accept one input file
            if (_reloc)
            {
                _skipRun = true;
                if (_inputFiles.Count > 1)
                {
                    throw Diagnostics.ThrowError("-c or -S flag may only be set for one input file");
                }
            }

            // Set output file if provided and not using VM
            _outputFile = _outputPath != null ? new FileInfo(_outputPath) : null;

            // Assembly output defaults to stdout if not specified
            if (_asm && _outputFile == null)
            {
                _outputFile = FileInfo.StdIo;
            }

            // Select toolchain by user request or input files / output file
            _toolChainSelection = SelectToolChain();

            // Construct toolchain
            _toolChain = (ToolChain)Activator.CreateInstance(_toolChainSelection.Value);
            commandLine.ApplyTo(_toolChain);

            // Determine target phase based on output file (if provided) and command line flags
            _targetPhase = SelectTargetPhase();

            if (_reloc && _inputFiles.Count > 1)
            {
                throw Diagnostics.ThrowError("relocatable output only works with one input file");
            }

            // Initialize module phase open set with pre-link phases up to target
            PhaseSet modulePhaseOpenSet =
                _toolChain.FilterPhases(
                    PhaseSet.AllPhasesTo((Phase)Math.Min((int)_targetPhase, (int)Phase.Link - 1)));

            // Visit JobActions for each file; building a chain of tools
            _moduleFileTools = new List <IModuleTool>(_inputFiles.Count);
            foreach (FileInfo inputFile in _inputFiles)
            {
                if (inputFile.IsLinkerInput)
                {
                    _moduleFileTools.Add(_toolChain.BuildLinkerInputFileTool(this, inputFile));
                    continue;
                }

                ITool tool = null;
                foreach (Phase phase in inputFile.PossiblePhases& modulePhaseOpenSet)
                {
                    tool = IJobAction.FromPhase(phase)
                           .Accept(_toolChain, this, tool != null ? (IInput)tool : inputFile);
                    commandLine.ApplyTo(tool);
                }

                if (tool is IModuleTool moduleTool)
                {
                    _moduleFileTools.Add(moduleTool);
                }
                else
                {
                    throw new InvalidOperationException("toolchain did not produce a module input file tool");
                }
            }

            // Set up link and subsequent tools
            if (_targetPhase >= Phase.Link)
            {
                PhaseSet linkPhaseOpenSet =
                    _toolChain.FilterPhases(PhaseSet.AllPhasesTo(_targetPhase) & PhaseSet.AllPhasesFrom(Phase.Link));

                ITool tool = null;
                foreach (Phase phase in linkPhaseOpenSet)
                {
                    tool = IJobAction.FromPhase(phase)
                           .Accept(_toolChain, this, tool != null ? (IInput)tool : this);
                    commandLine.ApplyTo(tool);
                }

                if (tool is IExecutableTool executableTool)
                {
                    _executableTool = executableTool;
                }
                else
                {
                    throw new InvalidOperationException("toolchain did not produce an executable tool");
                }
            }
        }
Beispiel #2
0
 public virtual PhaseSet FilterPhases(PhaseSet phases) => phases;