just shortened to driver), which is a piece of so:ware that allows an opera1ng system to communicate with a hardware device. • େମͷ߹ʮυϥΠόʯͱ͍͏ͱϋʔυΣΞͷੈքΛࢦͯ͠ ͯɺOSͱσόΠεͷΓͱΓΛαϙʔτʢڐՄʣ͢ΔͭͰ • όευϥΠόɾϑΟϧλυϥΠόɾιϑτΣΞυϥΠόʢι ϑτΣΞͷੈքͷઆ໌Ͱͳ͍ʣ... 5
driver is some6mes used to refer to a piece of so'ware that controls or drives some other piece of so'ware. • ιϑτΣΞ։ൃͷੈքͱҰൠతʹɺυϥΠόͱ͍͏ݴ ༿͍͔ͭ͘ͷύʔπʹͳ͍ͬͯΔιϑτΣΞΛࢀরͨ͠ Γɺݺͼग़ͨ͠Γ͢ΔιϑτΣΞͷ͜ͱΛࢦ͢Ͱ 6
Driver (llvmc) is a tool that can be configured to invoke several compiler development tools and related tools, acAng as a single point of access for users of the LLVM set of tools. • ͨͱ͑ɺLLVM Compiler Driver ͍͔ͭ͘ͷίϯύΠϥʢͱͦͷؔ࿈ʣ πʔϧͷݺͼग़͠Λߏ͢ΔͷͰ • Ϣʔβ͔ΒݟͨΒLLVMͷπʔϧ܈ʹΞΫηεͰ͖ΔɺҰͭͷΞΫηεϙΠ ϯτͱͯ͠ৼΔ͏Ͱ 7
driver. As such, it isn't a compiler, op;mizer, or a linker itself but it drives (invokes) other soAware that perform those tasks. If you are familiar with the GNU Compiler Collec;on's gcc tool, llvmc is very similar. • llvmc ࣗମ ίϯύΠϥɾOp;mizerɾϦϯΧࣗ ͡Όͳ͍Ͱ • llvmc υϥΠόͱͯ͠ ίϯύΠϥɾOp;mizerɾϦϯΧࣗ Λಈ͔͢(drivesɾݺͼग़͢)Ͱ 8
TSCUtility var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() intHandler = try InterruptHandler { processSet.terminate() } let (mode, arguments) = try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) if driver.diagnosticEngine.hasErrors { exit(EXIT_FAILURE) } } catch Diagnostics.fatalError { exit(EXIT_FAILURE) } catch let diagnosticData as DiagnosticData { diagnosticsEngine.emit(.error(diagnosticData)) exit(EXIT_FAILURE) } catch { print("error: \(error)") exit(EXIT_FAILURE) } 43
= try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 51
͜͜ if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 52
= try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // ͜͜ // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 54
fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 57
processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 58
fileSystem: localFileSystem, env: ProcessEnv.vars) // ͜͜ var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 60
fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } // ͜͜ let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 62
fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() // ͜͜ try driver.run(jobs: jobs) ... 64