TRAVIS_OS_NAME=osx <<<<<< ENV ./codecov.yml CHANGELOG LICENSE Makefile Package.resolved Package.swift Sources/CommandRegistry/Command.swift Sources/CommandRegistry/CommandRegistry.swift Sources/CommandRegistry/SugarCommand.swift Sources/CommandRegistry/TypeAliases.swift Tests/InternalTests/RegistryTests.swift Tests/InternalTests/XCTestManifests.swift Tests/LinuxMain.swift Tests/PublicTests/CommandTests.swift Tests/PublicTests/CommandWithArgumentTests.swift Tests/PublicTests/SyntaxSugarTests.swift Tests/PublicTests/XCTestManifests.swift Tests/TestTool/Package.swift Tests/TestTool/Sources/TestTool/Commands.swift Tests/TestTool/Sources/TestTool/main.swift Tests/TestTool/Tests/LinuxMain.swift Tests/TestTool/Tests/TestToolTests/TestToolTests.swift Tests/TestTool/Tests/TestToolTests/XCTestManifests.swift <<<<<< network # path=SourceControl.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SourceControl/GitRepository.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Dispatch 13| |import SPMUtility 14| | 15| |public enum GitRepositoryProviderError: Swift.Error { 16| | case gitCloneFailure(errorOutput: String) 17| |} 18| | 19| |/// A `git` repository provider. 20| |public class GitRepositoryProvider: RepositoryProvider { 21| | 22| | /// Reference to process set, if installed. 23| | private let processSet: ProcessSet? 24| | 25| 0| public init(processSet: ProcessSet? = nil) { 26| 0| self.processSet = processSet 27| 0| } 28| | 29| 0| public func fetch(repository: RepositorySpecifier, to path: AbsolutePath) throws { 30| 0| // Perform a bare clone. 31| 0| // 32| 0| // NOTE: We intentionally do not create a shallow clone here; the 33| 0| // expected cost of iterative updates on a full clone is less than on a 34| 0| // shallow clone. 35| 0| 36| 0| precondition(!exists(path)) 37| 0| 38| 0| // FIXME: We need infrastructure in this subsystem for reporting 39| 0| // status information. 40| 0| 41| 0| let process = Process( 42| 0| args: Git.tool, "clone", "--mirror", repository.url, path.pathString, environment: Git.environment) 43| 0| // Add to process set. 44| 0| try processSet?.add(process) 45| 0| // Launch the process. 46| 0| try process.launch() 47| 0| // Block until cloning completes. 48| 0| let result = try process.waitUntilExit() 49| 0| // Throw if cloning failed. 50| 0| guard result.exitStatus == .terminated(code: 0) else { 51| 0| let errorOutput = try (result.utf8Output() + result.utf8stderrOutput()).spm_chuzzle() ?? "" 52| 0| throw GitRepositoryProviderError.gitCloneFailure(errorOutput: errorOutput) 53| 0| } 54| 0| } 55| | 56| 0| public func open(repository: RepositorySpecifier, at path: AbsolutePath) -> Repository { 57| 0| return GitRepository(path: path, isWorkingRepo: false) 58| 0| } 59| | 60| | public func cloneCheckout( 61| | repository: RepositorySpecifier, 62| | at sourcePath: AbsolutePath, 63| | to destinationPath: AbsolutePath, 64| | editable: Bool 65| 0| ) throws { 66| 0| 67| 0| if editable { 68| 0| // For editable clones, i.e. the user is expected to directly work on them, first we create 69| 0| // a clone from our cache of repositories and then we replace the remote to the one originally 70| 0| // present in the bare repository. 71| 0| try Process.checkNonZeroExit(args: 72| 0| Git.tool, "clone", sourcePath.pathString, destinationPath.pathString) 73| 0| // The default name of the remote. 74| 0| let origin = "origin" 75| 0| // In destination repo remove the remote which will be pointing to the source repo. 76| 0| let clone = GitRepository(path: destinationPath) 77| 0| // Set the original remote to the new clone. 78| 0| try clone.setURL(remote: origin, url: repository.url) 79| 0| // FIXME: This is unfortunate that we have to fetch to update remote's data. 80| 0| try clone.fetch() 81| 0| } else { 82| 0| // Clone using a shared object store with the canonical copy. 83| 0| // 84| 0| // We currently expect using shared storage here to be safe because we 85| 0| // only ever expect to attempt to use the working copy to materialize a 86| 0| // revision we selected in response to dependency resolution, and if we 87| 0| // re-resolve such that the objects in this repository changed, we would 88| 0| // only ever expect to get back a revision that remains present in the 89| 0| // object storage. 90| 0| try Process.checkNonZeroExit(args: 91| 0| Git.tool, "clone", "--shared", sourcePath.pathString, destinationPath.pathString) 92| 0| } 93| 0| } 94| | 95| 0| public func checkoutExists(at path: AbsolutePath) throws -> Bool { 96| 0| precondition(exists(path)) 97| 0| 98| 0| let result = try Process.popen(args: Git.tool, "-C", path.pathString, "rev-parse", "--is-bare-repository") 99| 0| return try result.exitStatus == .terminated(code: 0) && result.utf8Output().spm_chomp() == "false" 100| 0| } 101| | 102| 0| public func openCheckout(at path: AbsolutePath) throws -> WorkingCheckout { 103| 0| return GitRepository(path: path) 104| 0| } 105| |} 106| | 107| |enum GitInterfaceError: Swift.Error { 108| | /// This indicates a problem communicating with the `git` tool. 109| | case malformedResponse(String) 110| | 111| | /// This indicates that a fatal error was encountered 112| | case fatalError 113| |} 114| | 115| |// FIXME: Currently, this class is serving two goals, it is the Repository 116| |// interface used by `RepositoryProvider`, but is also a class which can be 117| |// instantiated directly against non-RepositoryProvider controlled 118| |// repositories. This may prove inconvenient if what is currently `Repository` 119| |// becomes inconvenient or incompatible with the ideal interface for this 120| |// class. It is possible we should rename `Repository` to something more 121| |// abstract, and change the provider to just return an adaptor around this 122| |// class. 123| |// 124| |/// A basic `git` repository. This class is thread safe. 125| |public class GitRepository: Repository, WorkingCheckout { 126| | /// A hash object. 127| | struct Hash: Hashable { 128| | // FIXME: We should optimize this representation. 129| | let bytes: ByteString 130| | 131| | /// Create a hash from the given hexadecimal representation. 132| | /// 133| | /// - Returns; The hash, or nil if the identifier is invalid. 134| 0| init?(_ identifier: String) { 135| 0| self.init(asciiBytes: ByteString(encodingAsUTF8: identifier).contents) 136| 0| } 137| | 138| | /// Create a hash from the given ASCII bytes. 139| | /// 140| | /// - Returns; The hash, or nil if the identifier is invalid. 141| 0| init?(asciiBytes bytes: C) where C.Iterator.Element == UInt8 { 142| 0| if bytes.count != 40 { 143| 0| return nil 144| 0| } 145| 0| for byte in bytes { 146| 0| switch byte { 147| 0| case UInt8(ascii: "0")...UInt8(ascii: "9"), 148| 0| UInt8(ascii: "a")...UInt8(ascii: "z"): 149| 0| continue 150| 0| default: 151| 0| return nil 152| 0| } 153| 0| } 154| 0| self.bytes = ByteString(bytes) 155| 0| } 156| | } 157| | 158| | /// A commit object. 159| | struct Commit: Equatable { 160| | /// The object hash. 161| | let hash: Hash 162| | 163| | /// The tree contained in the commit. 164| | let tree: Hash 165| | } 166| | 167| | /// A tree object. 168| | struct Tree { 169| | struct Entry { 170| | enum EntryType { 171| | case blob 172| | case commit 173| | case executableBlob 174| | case symlink 175| | case tree 176| | 177| 0| init?(mode: Int) { 178| 0| // Although the mode is a full UNIX mode mask, there are 179| 0| // only a limited set of allowed values. 180| 0| switch mode { 181| 0| case 0o040000: 182| 0| self = .tree 183| 0| case 0o100644: 184| 0| self = .blob 185| 0| case 0o100755: 186| 0| self = .executableBlob 187| 0| case 0o120000: 188| 0| self = .symlink 189| 0| case 0o160000: 190| 0| self = .commit 191| 0| default: 192| 0| return nil 193| 0| } 194| 0| } 195| | } 196| | 197| | /// The hash of the object. 198| | let hash: Hash 199| | 200| | /// The type of object referenced. 201| | let type: EntryType 202| | 203| | /// The name of the object. 204| | let name: String 205| | } 206| | 207| | /// The object hash. 208| | let hash: Hash 209| | 210| | /// The list of contents. 211| | let contents: [Entry] 212| | } 213| | 214| | /// The path of the repository on disk. 215| | public let path: AbsolutePath 216| | 217| | /// The (serial) queue to execute git cli on. 218| | private let queue = DispatchQueue(label: "org.swift.swiftpm.gitqueue") 219| | 220| | /// If this repo is a work tree repo (checkout) as opposed to a bare repo. 221| | let isWorkingRepo: Bool 222| | 223| 0| public init(path: AbsolutePath, isWorkingRepo: Bool = true) { 224| 0| self.path = path 225| 0| self.isWorkingRepo = isWorkingRepo 226| 0| do { 227| 0| let isBareRepo = try Process.checkNonZeroExit( 228| 0| args: Git.tool, "-C", path.pathString, "rev-parse", "--is-bare-repository").spm_chomp() == "true" 229| 0| assert(isBareRepo != isWorkingRepo) 230| 0| } catch { 231| 0| // Ignore if we couldn't run popen for some reason. 232| 0| } 233| 0| } 234| | 235| | /// Changes URL for the remote. 236| | /// 237| | /// - parameters: 238| | /// - remote: The name of the remote to operate on. It should already be present. 239| | /// - url: The new url of the remote. 240| 0| func setURL(remote: String, url: String) throws { 241| 0| try queue.sync { 242| 0| try Process.checkNonZeroExit( 243| 0| args: Git.tool, "-C", path.pathString, "remote", "set-url", remote, url) 244| 0| return 245| 0| } 246| 0| } 247| | 248| | /// Gets the current list of remotes of the repository. 249| | /// 250| | /// - Returns: An array of tuple containing name and url of the remote. 251| 0| public func remotes() throws -> [(name: String, url: String)] { 252| 0| return try queue.sync { 253| 0| // Get the remote names. 254| 0| let remoteNamesOutput = try Process.checkNonZeroExit( 255| 0| args: Git.tool, "-C", path.pathString, "remote").spm_chomp() 256| 0| let remoteNames = remoteNamesOutput.split(separator: "\n").map(String.init) 257| 0| return try remoteNames.map({ name in 258| 0| // For each remote get the url. 259| 0| let url = try Process.checkNonZeroExit( 260| 0| args: Git.tool, "-C", path.pathString, "config", "--get", "remote.\(name).url").spm_chomp() 261| 0| return (name, url) 262| 0| }) 263| 0| } 264| 0| } 265| | 266| | // MARK: Repository Interface 267| | 268| | /// Returns the tags present in repository. 269| 0| public var tags: [String] { 270| 0| return queue.sync { 271| 0| // Check if we already have the tags cached. 272| 0| if let tags = tagsCache { 273| 0| return tags 274| 0| } 275| 0| tagsCache = getTags() 276| 0| return tagsCache! 277| 0| } 278| 0| } 279| | 280| | /// Cache for the tags. 281| | private var tagsCache: [String]? 282| | 283| | /// Returns the tags present in repository. 284| 0| private func getTags() -> [String] { 285| 0| // FIXME: Error handling. 286| 0| let tagList = try! Process.checkNonZeroExit( 287| 0| args: Git.tool, "-C", path.pathString, "tag", "-l").spm_chomp() 288| 0| return tagList.split(separator: "\n").map(String.init) 289| 0| } 290| | 291| 0| public func resolveRevision(tag: String) throws -> Revision { 292| 0| return try Revision(identifier: resolveHash(treeish: tag, type: "commit").bytes.description) 293| 0| } 294| | 295| 0| public func resolveRevision(identifier: String) throws -> Revision { 296| 0| return try Revision(identifier: resolveHash(treeish: identifier, type: "commit").bytes.description) 297| 0| } 298| | 299| 0| public func fetch() throws { 300| 0| try queue.sync { 301| 0| try Process.checkNonZeroExit( 302| 0| args: Git.tool, "-C", path.pathString, "remote", "update", "-p", environment: Git.environment) 303| 0| self.tagsCache = nil 304| 0| } 305| 0| } 306| | 307| 0| public func hasUncommittedChanges() -> Bool { 308| 0| // Only a work tree can have changes. 309| 0| guard isWorkingRepo else { return false } 310| 0| return queue.sync { 311| 0| // Check nothing has been changed 312| 0| guard let result = try? Process.checkNonZeroExit( 313| 0| args: Git.tool, "-C", path.pathString, "status", "-s") else 314| 0| { 315| 0| return false 316| 0| } 317| 0| return !result.spm_chomp().isEmpty 318| 0| } 319| 0| } 320| | 321| 0| public func openFileView(revision: Revision) throws -> FileSystem { 322| 0| return try GitFileSystemView(repository: self, revision: revision) 323| 0| } 324| | 325| | // MARK: Working Checkout Interface 326| | 327| 0| public func hasUnpushedCommits() throws -> Bool { 328| 0| return try queue.sync { 329| 0| let hasOutput = try Process.checkNonZeroExit( 330| 0| args: Git.tool, "-C", path.pathString, "log", "--branches", "--not", "--remotes").spm_chomp().isEmpty 331| 0| return !hasOutput 332| 0| } 333| 0| } 334| | 335| 0| public func getCurrentRevision() throws -> Revision { 336| 0| return try queue.sync { 337| 0| return try Revision( 338| 0| identifier: Process.checkNonZeroExit( 339| 0| args: Git.tool, "-C", path.pathString, "rev-parse", "--verify", "HEAD").spm_chomp()) 340| 0| } 341| 0| } 342| | 343| 0| public func checkout(tag: String) throws { 344| 0| // FIXME: Audit behavior with off-branch tags in remote repositories, we 345| 0| // may need to take a little more care here. 346| 0| try queue.sync { 347| 0| try Process.checkNonZeroExit( 348| 0| args: Git.tool, "-C", path.pathString, "reset", "--hard", tag) 349| 0| try self.updateSubmoduleAndClean() 350| 0| } 351| 0| } 352| | 353| 0| public func checkout(revision: Revision) throws { 354| 0| // FIXME: Audit behavior with off-branch tags in remote repositories, we 355| 0| // may need to take a little more care here. 356| 0| try queue.sync { 357| 0| try Process.checkNonZeroExit( 358| 0| args: Git.tool, "-C", path.pathString, "checkout", "-f", revision.identifier) 359| 0| try self.updateSubmoduleAndClean() 360| 0| } 361| 0| } 362| | 363| | /// Initializes and updates the submodules, if any, and cleans left over the files and directories using git-clean. 364| 0| private func updateSubmoduleAndClean() throws { 365| 0| try Process.checkNonZeroExit(args: Git.tool, 366| 0| "-C", path.pathString, "submodule", "update", "--init", "--recursive", environment: Git.environment) 367| 0| try Process.checkNonZeroExit(args: Git.tool, 368| 0| "-C", path.pathString, "clean", "-ffdx") 369| 0| } 370| | 371| | /// Returns true if a revision exists. 372| 0| public func exists(revision: Revision) -> Bool { 373| 0| return queue.sync { 374| 0| let result = try? Process.popen( 375| 0| args: Git.tool, "-C", path.pathString, "rev-parse", "--verify", revision.identifier) 376| 0| return result?.exitStatus == .terminated(code: 0) 377| 0| } 378| 0| } 379| | 380| 0| public func checkout(newBranch: String) throws { 381| 0| precondition(isWorkingRepo, "This operation should run in a working repo.") 382| 0| try queue.sync { 383| 0| try Process.checkNonZeroExit( 384| 0| args: Git.tool, "-C", path.pathString, "checkout", "-b", newBranch) 385| 0| return 386| 0| } 387| 0| } 388| | 389| | /// Returns true if there is an alternative object store in the repository and it is valid. 390| 0| public func isAlternateObjectStoreValid() -> Bool { 391| 0| let objectStoreFile = path.appending(components: ".git", "objects", "info", "alternates") 392| 0| guard let bytes = try? localFileSystem.readFileContents(objectStoreFile) else { 393| 0| return false 394| 0| } 395| 0| let split = bytes.contents.split(separator: UInt8(ascii: "\n"), maxSplits: 1, omittingEmptySubsequences: false) 396| 0| guard let firstLine = ByteString(split[0]).validDescription else { 397| 0| return false 398| 0| } 399| 0| return localFileSystem.isDirectory(AbsolutePath(firstLine)) 400| 0| } 401| | 402| | /// Returns true if the file at `path` is ignored by `git` 403| 0| public func areIgnored(_ paths: [AbsolutePath]) throws -> [Bool] { 404| 0| return try queue.sync { 405| 0| let stringPaths = paths.map({ $0.pathString }) 406| 0| 407| 0| let pathsFile = try TemporaryFile() 408| 0| try localFileSystem.writeFileContents(pathsFile.path) { 409| 0| for path in paths { 410| 0| $0 <<< path.pathString <<< "\0" 411| 0| } 412| 0| } 413| 0| 414| 0| let args = [ 415| 0| Git.tool, "-C", self.path.pathString.spm_shellEscaped(), 416| 0| "check-ignore", "-z", "--stdin", 417| 0| "<", pathsFile.path.pathString.spm_shellEscaped() 418| 0| ] 419| 0| let argsWithSh = ["sh", "-c", args.joined(separator: " ")] 420| 0| let result = try Process.popen(arguments: argsWithSh) 421| 0| let output = try result.output.dematerialize() 422| 0| 423| 0| let outputs: [String] = output.split(separator: 0).map({ String(decoding: $0, as: Unicode.UTF8.self) }) 424| 0| 425| 0| guard result.exitStatus == .terminated(code: 0) || result.exitStatus == .terminated(code: 1) else { 426| 0| throw GitInterfaceError.fatalError 427| 0| } 428| 0| 429| 0| return stringPaths.map(outputs.contains) 430| 0| } 431| 0| } 432| | 433| | // MARK: Git Operations 434| | 435| | /// Resolve a "treeish" to a concrete hash. 436| | /// 437| | /// Technically this method can accept much more than a "treeish", it maps 438| | /// to the syntax accepted by `git rev-parse`. 439| 0| func resolveHash(treeish: String, type: String? = nil) throws -> Hash { 440| 0| let specifier: String 441| 0| if let type = type { 442| 0| specifier = treeish + "^{\(type)}" 443| 0| } else { 444| 0| specifier = treeish 445| 0| } 446| 0| let response = try queue.sync { 447| 0| try Process.checkNonZeroExit( 448| 0| args: Git.tool, "-C", path.pathString, "rev-parse", "--verify", specifier).spm_chomp() 449| 0| } 450| 0| if let hash = Hash(response) { 451| 0| return hash 452| 0| } else { 453| 0| throw GitInterfaceError.malformedResponse("expected an object hash in \(response)") 454| 0| } 455| 0| } 456| | 457| | /// Read the commit referenced by `hash`. 458| 0| func read(commit hash: Hash) throws -> Commit { 459| 0| // Currently, we just load the tree, using the typed `rev-parse` syntax. 460| 0| let treeHash = try resolveHash(treeish: hash.bytes.description, type: "tree") 461| 0| 462| 0| return Commit(hash: hash, tree: treeHash) 463| 0| } 464| | 465| | /// Read a tree object. 466| 0| func read(tree hash: Hash) throws -> Tree { 467| 0| // Get the contents using `ls-tree`. 468| 0| let treeInfo = try queue.sync { 469| 0| try Process.checkNonZeroExit( 470| 0| args: Git.tool, "-C", path.pathString, "ls-tree", hash.bytes.description) 471| 0| } 472| 0| 473| 0| var contents: [Tree.Entry] = [] 474| 0| for line in treeInfo.components(separatedBy: "\n") { 475| 0| // Ignore empty lines. 476| 0| if line == "" { continue } 477| 0| 478| 0| // Each line in the response should match: 479| 0| // 480| 0| // `mode type hash\tname` 481| 0| // 482| 0| // where `mode` is the 6-byte octal file mode, `type` is a 4-byte or 6-byte 483| 0| // type ("blob", "tree", "commit"), `hash` is the hash, and the remainder of 484| 0| // the line is the file name. 485| 0| let bytes = ByteString(encodingAsUTF8: line) 486| 0| let expectedBytesCount = 6 + 1 + 4 + 1 + 40 + 1 487| 0| guard bytes.count > expectedBytesCount, 488| 0| bytes.contents[6] == UInt8(ascii: " "), 489| 0| // Search for the second space since `type` is of variable length. 490| 0| let secondSpace = bytes.contents[6 + 1 ..< bytes.contents.endIndex].index(of: UInt8(ascii: " ")), 491| 0| bytes.contents[secondSpace] == UInt8(ascii: " "), 492| 0| bytes.contents[secondSpace + 1 + 40] == UInt8(ascii: "\t") else { 493| 0| throw GitInterfaceError.malformedResponse("unexpected tree entry '\(line)' in '\(treeInfo)'") 494| 0| } 495| 0| 496| 0| // Compute the mode. 497| 0| let mode = bytes.contents[0..<6].reduce(0) { (acc: Int, char: UInt8) in 498| 0| (acc << 3) | (Int(char) - Int(UInt8(ascii: "0"))) 499| 0| } 500| 0| guard let type = Tree.Entry.EntryType(mode: mode), 501| 0| let hash = Hash(asciiBytes: bytes.contents[(secondSpace + 1)..<(secondSpace + 1 + 40)]), 502| 0| let name = ByteString(bytes.contents[(secondSpace + 1 + 40 + 1).. ByteString { 520| 0| return try queue.sync { 521| 0| // Get the contents using `cat-file`. 522| 0| // 523| 0| // FIXME: We need to get the raw bytes back, not a String. 524| 0| let output = try Process.checkNonZeroExit( 525| 0| args: Git.tool, "-C", path.pathString, "cat-file", "-p", hash.bytes.description) 526| 0| return ByteString(encodingAsUTF8: output) 527| 0| } 528| 0| } 529| |} 530| |/// A `git` file system view. 531| |/// 532| |/// The current implementation is based on lazily caching data with no eviction 533| |/// policy, and is very unoptimized. 534| |private class GitFileSystemView: FileSystem { 535| | typealias Hash = GitRepository.Hash 536| | typealias Tree = GitRepository.Tree 537| | 538| | // MARK: Git Object Model 539| | 540| | // The map of loaded trees. 541| | var trees: [Hash: Tree] = [:] 542| | 543| | /// The underlying repository. 544| | let repository: GitRepository 545| | 546| | /// The revision this is a view on. 547| | let revision: Revision 548| | 549| | /// The root tree hash. 550| | let root: GitRepository.Hash 551| | 552| 0| init(repository: GitRepository, revision: Revision) throws { 553| 0| self.repository = repository 554| 0| self.revision = revision 555| 0| self.root = try repository.read(commit: Hash(revision.identifier)!).tree 556| 0| } 557| | 558| | // MARK: FileSystem Implementation 559| | 560| 0| private func getEntry(_ path: AbsolutePath) throws -> Tree.Entry? { 561| 0| // Walk the components resolving the tree (starting with a synthetic 562| 0| // root entry). 563| 0| var current: Tree.Entry = Tree.Entry(hash: root, type: .tree, name: "/") 564| 0| for component in path.components.dropFirst(1) { 565| 0| // Skip the root pseudo-component. 566| 0| if component == "/" { continue } 567| 0| 568| 0| // We have a component to resolve, so the current entry must be a tree. 569| 0| guard current.type == .tree else { 570| 0| throw FileSystemError.notDirectory 571| 0| } 572| 0| 573| 0| // Fetch the tree. 574| 0| let tree = try getTree(current.hash) 575| 0| 576| 0| // Search the tree for the component. 577| 0| // 578| 0| // FIXME: This needs to be optimized, somewhere. 579| 0| guard let index = tree.contents.index(where: { $0.name == component }) else { 580| 0| return nil 581| 0| } 582| 0| 583| 0| current = tree.contents[index] 584| 0| } 585| 0| 586| 0| return current 587| 0| } 588| | 589| 0| private func getTree(_ hash: Hash) throws -> Tree { 590| 0| // Check the cache. 591| 0| if let tree = trees[hash] { 592| 0| return tree 593| 0| } 594| 0| 595| 0| // Otherwise, load it. 596| 0| let tree = try repository.read(tree: hash) 597| 0| trees[hash] = tree 598| 0| return tree 599| 0| } 600| | 601| 0| func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool { 602| 0| do { 603| 0| return try getEntry(path) != nil 604| 0| } catch { 605| 0| return false 606| 0| } 607| 0| } 608| | 609| 0| func isFile(_ path: AbsolutePath) -> Bool { 610| 0| do { 611| 0| if let entry = try getEntry(path), entry.type != .tree { 612| 0| return true 613| 0| } 614| 0| return false 615| 0| } catch { 616| 0| return false 617| 0| } 618| 0| } 619| | 620| 0| func isDirectory(_ path: AbsolutePath) -> Bool { 621| 0| do { 622| 0| if let entry = try getEntry(path), entry.type == .tree { 623| 0| return true 624| 0| } 625| 0| return false 626| 0| } catch { 627| 0| return false 628| 0| } 629| 0| } 630| | 631| 0| func isSymlink(_ path: AbsolutePath) -> Bool { 632| 0| do { 633| 0| if let entry = try getEntry(path), entry.type == .symlink { 634| 0| return true 635| 0| } 636| 0| return false 637| 0| } catch { 638| 0| return false 639| 0| } 640| 0| } 641| | 642| 0| func isExecutableFile(_ path: AbsolutePath) -> Bool { 643| 0| if let entry = try? getEntry(path), entry?.type == .executableBlob { 644| 0| return true 645| 0| } 646| 0| return false 647| 0| } 648| | 649| 0| public var currentWorkingDirectory: AbsolutePath? { 650| 0| return AbsolutePath("/") 651| 0| } 652| | 653| 0| func getDirectoryContents(_ path: AbsolutePath) throws -> [String] { 654| 0| guard let entry = try getEntry(path) else { 655| 0| throw FileSystemError.noEntry 656| 0| } 657| 0| guard entry.type == .tree else { 658| 0| throw FileSystemError.notDirectory 659| 0| } 660| 0| 661| 0| return try getTree(entry.hash).contents.map({ $0.name }) 662| 0| } 663| | 664| 0| func readFileContents(_ path: AbsolutePath) throws -> ByteString { 665| 0| guard let entry = try getEntry(path) else { 666| 0| throw FileSystemError.noEntry 667| 0| } 668| 0| guard entry.type != .tree else { 669| 0| throw FileSystemError.isDirectory 670| 0| } 671| 0| guard entry.type != .symlink else { 672| 0| fatalError("FIXME: not implemented") 673| 0| } 674| 0| return try repository.read(blob: entry.hash) 675| 0| } 676| | 677| | // MARK: Unsupported methods. 678| | 679| 0| public var homeDirectory: AbsolutePath { 680| 0| fatalError("unsupported") 681| 0| } 682| | 683| 0| func createDirectory(_ path: AbsolutePath) throws { 684| 0| throw FileSystemError.unsupported 685| 0| } 686| | 687| 0| func createDirectory(_ path: AbsolutePath, recursive: Bool) throws { 688| 0| throw FileSystemError.unsupported 689| 0| } 690| | 691| 0| func writeFileContents(_ path: AbsolutePath, bytes: ByteString) throws { 692| 0| throw FileSystemError.unsupported 693| 0| } 694| | 695| 0| func removeFileTree(_ path: AbsolutePath) throws { 696| 0| throw FileSystemError.unsupported 697| 0| } 698| | 699| 0| func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws { 700| 0| throw FileSystemError.unsupported 701| 0| } 702| |} 703| | 704| |extension GitRepositoryProviderError: CustomStringConvertible { 705| 0| public var description: String { 706| 0| switch self { 707| 0| case .gitCloneFailure(let errorOutput): 708| 0| return "failed to clone; \(errorOutput)" 709| 0| } 710| 0| } 711| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SourceControl/InMemoryGitRepository.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Dispatch 13| |import SPMUtility 14| |import class Foundation.NSUUID 15| | 16| |/// The error encountered during in memory git repository operations. 17| |public enum InMemoryGitRepositoryError: Swift.Error { 18| | case unknownRevision 19| | case unknownTag 20| | case tagAlreadyPresent 21| |} 22| | 23| |/// A class that implements basic git features on in-memory file system. It takes the path and file system reference 24| |/// where the repository should be created. The class itself is a file system pointing to current revision state 25| |/// i.e. HEAD. All mutations should be made on file system interface of this class and then they can be committed using 26| |/// commit() method. Calls to checkout related methods will checkout the HEAD on the passed file system at the 27| |/// repository path, as well as on the file system interface of this class. 28| |/// Note: This class is intended to be used as testing infrastructure only. 29| |/// Note: This class is not thread safe yet. 30| |public final class InMemoryGitRepository { 31| | /// The revision identifier. 32| | public typealias RevisionIdentifier = String 33| | 34| | /// A struct representing a revision state. Minimally it contains a hash identifier for the revision 35| | /// and the file system state. 36| | fileprivate struct RevisionState { 37| | /// The revision identifier hash. It should be unique amoung all the identifiers. 38| | var hash: RevisionIdentifier 39| | 40| | /// The filesystem state contained in this revision. 41| | let fileSystem: InMemoryFileSystem 42| | 43| | /// Creates copy of the state. 44| 0| func copy() -> RevisionState { 45| 0| return RevisionState(hash: hash, fileSystem: fileSystem.copy()) 46| 0| } 47| | } 48| | 49| | /// THe HEAD i.e. the current checked out state. 50| | fileprivate var head: RevisionState 51| | 52| | /// The history dictionary. 53| | fileprivate var history: [RevisionIdentifier: RevisionState] = [:] 54| | 55| | /// The map containing tag name to revision identifier values. 56| | fileprivate var tagsMap: [String: RevisionIdentifier] = [:] 57| | 58| | /// The array of current tags in the repository. 59| 0| public var tags: [String] { 60| 0| return Array(tagsMap.keys) 61| 0| } 62| | 63| | /// The list of revisions in the repository. 64| 0| public var revisions: [RevisionIdentifier] { 65| 0| return Array(history.keys) 66| 0| } 67| | 68| | /// Indicates whether there are any uncommited changes in the repository. 69| | fileprivate var isDirty = false 70| | 71| | /// The path at which this repository is located. 72| | fileprivate let path: AbsolutePath 73| | 74| | /// The file system in which this repository should be installed. 75| | private let fs: InMemoryFileSystem 76| | 77| | /// Create a new repository at the given path and filesystem. 78| 0| public init(path: AbsolutePath, fs: InMemoryFileSystem) { 79| 0| self.path = path 80| 0| self.fs = fs 81| 0| // Point head to a new revision state with empty hash to begin with. 82| 0| head = RevisionState(hash: "", fileSystem: InMemoryFileSystem()) 83| 0| } 84| | 85| | /// Copy/clone this repository. 86| 0| fileprivate func copy(at newPath: AbsolutePath? = nil) -> InMemoryGitRepository { 87| 0| let path = newPath ?? self.path 88| 0| try! fs.createDirectory(path, recursive: true) 89| 0| let repo = InMemoryGitRepository(path: path, fs: fs) 90| 0| for (revision, state) in history { 91| 0| repo.history[revision] = state.copy() 92| 0| } 93| 0| repo.tagsMap = tagsMap 94| 0| repo.head = head.copy() 95| 0| return repo 96| 0| } 97| | 98| | /// Commits the current state of the repository filesystem and returns the commit identifier. 99| | @discardableResult 100| 0| public func commit() -> String { 101| 0| // Create a fake hash for thie commit. 102| 0| let hash = String((NSUUID().uuidString + NSUUID().uuidString).prefix(40)) 103| 0| head.hash = hash 104| 0| // Store the commit in history. 105| 0| history[hash] = head.copy() 106| 0| // We are not dirty anymore. 107| 0| isDirty = false 108| 0| // Install the current HEAD i.e. this commit to the filesystem that was passed. 109| 0| try! installHead() 110| 0| return hash 111| 0| } 112| | 113| | /// Checks out the provided revision. 114| 0| public func checkout(revision: RevisionIdentifier) throws { 115| 0| guard let state = history[revision] else { 116| 0| throw InMemoryGitRepositoryError.unknownRevision 117| 0| } 118| 0| // Point the head to the revision state. 119| 0| head = state 120| 0| isDirty = false 121| 0| // Install this state on the passed filesystem. 122| 0| try installHead() 123| 0| } 124| | 125| | /// Checks out a given tag. 126| 0| public func checkout(tag: String) throws { 127| 0| guard let hash = tagsMap[tag] else { 128| 0| throw InMemoryGitRepositoryError.unknownTag 129| 0| } 130| 0| // Point the head to the revision state of the tag. 131| 0| // It should be impossible that a tag exisits which doesnot have a state. 132| 0| head = history[hash]! 133| 0| isDirty = false 134| 0| // Install this state on the passed filesystem. 135| 0| try installHead() 136| 0| } 137| | 138| | /// Installs (or checks out) current head on the filesystem on which this repository exists. 139| 0| fileprivate func installHead() throws { 140| 0| // Remove the old state. 141| 0| try fs.removeFileTree(path) 142| 0| // Create the repository directory. 143| 0| try fs.createDirectory(path, recursive: true) 144| 0| // Get the file system state at the HEAD, 145| 0| let headFs = head.fileSystem 146| 0| 147| 0| /// Recursively copies the content at HEAD to fs. 148| 0| func install(at path: AbsolutePath) throws { 149| 0| guard headFs.isDirectory(path) else { return } 150| 0| for entry in try headFs.getDirectoryContents(path) { 151| 0| // The full path of the entry. 152| 0| let entryPath = path.appending(component: entry) 153| 0| if headFs.isFile(entryPath) { 154| 0| // If we have a file just write the file. 155| 0| try fs.writeFileContents(entryPath, bytes: try headFs.readFileContents(entryPath)) 156| 0| } else if headFs.isDirectory(entryPath) { 157| 0| // If we have a directory, create that directory and copy its contents. 158| 0| try fs.createDirectory(entryPath, recursive: false) 159| 0| try install(at: entryPath) 160| 0| } 161| 0| } 162| 0| } 163| 0| // Install at the repository path. 164| 0| try install(at: path) 165| 0| } 166| | 167| | /// Tag the current HEAD with the given name. 168| 0| public func tag(name: String) throws { 169| 0| guard tagsMap[name] == nil else { 170| 0| throw InMemoryGitRepositoryError.tagAlreadyPresent 171| 0| } 172| 0| tagsMap[name] = head.hash 173| 0| } 174| | 175| 0| public func hasUncommittedChanges() -> Bool { 176| 0| return isDirty 177| 0| } 178| | 179| 0| public func fetch() throws { 180| 0| // TODO. 181| 0| } 182| |} 183| | 184| |extension InMemoryGitRepository: FileSystem { 185| | 186| 0| public func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool { 187| 0| return head.fileSystem.exists(path, followSymlink: followSymlink) 188| 0| } 189| | 190| 0| public func isDirectory(_ path: AbsolutePath) -> Bool { 191| 0| return head.fileSystem.isDirectory(path) 192| 0| } 193| | 194| 0| public func isFile(_ path: AbsolutePath) -> Bool { 195| 0| return head.fileSystem.isFile(path) 196| 0| } 197| | 198| 0| public func isSymlink(_ path: AbsolutePath) -> Bool { 199| 0| return head.fileSystem.isSymlink(path) 200| 0| } 201| | 202| 0| public func isExecutableFile(_ path: AbsolutePath) -> Bool { 203| 0| return head.fileSystem.isExecutableFile(path) 204| 0| } 205| | 206| 0| public var currentWorkingDirectory: AbsolutePath? { 207| 0| return AbsolutePath("/") 208| 0| } 209| | 210| 0| public var homeDirectory: AbsolutePath { 211| 0| fatalError("Unsupported") 212| 0| } 213| | 214| 0| public func getDirectoryContents(_ path: AbsolutePath) throws -> [String] { 215| 0| return try head.fileSystem.getDirectoryContents(path) 216| 0| } 217| | 218| 0| public func createDirectory(_ path: AbsolutePath, recursive: Bool) throws { 219| 0| try head.fileSystem.createDirectory(path, recursive: recursive) 220| 0| } 221| | 222| 0| public func readFileContents(_ path: AbsolutePath) throws -> ByteString { 223| 0| return try head.fileSystem.readFileContents(path) 224| 0| } 225| | 226| 0| public func writeFileContents(_ path: AbsolutePath, bytes: ByteString) throws { 227| 0| try head.fileSystem.writeFileContents(path, bytes: bytes) 228| 0| isDirty = true 229| 0| } 230| | 231| 0| public func removeFileTree(_ path: AbsolutePath) throws { 232| 0| try head.fileSystem.removeFileTree(path) 233| 0| } 234| | 235| 0| public func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws { 236| 0| try head.fileSystem.chmod(mode, path: path, options: options) 237| 0| } 238| |} 239| | 240| |extension InMemoryGitRepository: Repository { 241| 0| public func resolveRevision(tag: String) throws -> Revision { 242| 0| return Revision(identifier: tagsMap[tag]!) 243| 0| } 244| | 245| 0| public func resolveRevision(identifier: String) throws -> Revision { 246| 0| return Revision(identifier: tagsMap[identifier] ?? identifier) 247| 0| } 248| | 249| 0| public func exists(revision: Revision) -> Bool { 250| 0| return history[revision.identifier] != nil 251| 0| } 252| | 253| 0| public func openFileView(revision: Revision) throws -> FileSystem { 254| 0| let fs: FileSystem = history[revision.identifier]!.fileSystem 255| 0| return RerootedFileSystemView(fs, rootedAt: path) 256| 0| } 257| |} 258| | 259| |extension InMemoryGitRepository: WorkingCheckout { 260| 0| public func getCurrentRevision() throws -> Revision { 261| 0| return Revision(identifier: head.hash) 262| 0| } 263| | 264| 0| public func checkout(revision: Revision) throws { 265| 0| try checkout(revision: revision.identifier) 266| 0| } 267| | 268| 0| public func hasUnpushedCommits() throws -> Bool { 269| 0| return false 270| 0| } 271| | 272| 0| public func checkout(newBranch: String) throws { 273| 0| history[newBranch] = head 274| 0| } 275| | 276| 0| public func isAlternateObjectStoreValid() -> Bool { 277| 0| return true 278| 0| } 279| | 280| 0| public func areIgnored(_ paths: [AbsolutePath]) throws -> [Bool] { 281| 0| return [false] 282| 0| } 283| |} 284| | 285| |/// This class implement provider for in memeory git repository. 286| |public final class InMemoryGitRepositoryProvider: RepositoryProvider { 287| | /// Contains the repository added to this provider. 288| | public private(set) var specifierMap = [RepositorySpecifier: InMemoryGitRepository]() 289| | 290| | /// Contains the repositories which are fetched using this provider. 291| | private var fetchedMap = [AbsolutePath: InMemoryGitRepository]() 292| | 293| | /// Contains the repositories which are checked out using this provider. 294| | private var checkoutsMap = [AbsolutePath: InMemoryGitRepository]() 295| | 296| | /// Create a new provider. 297| 0| public init() { 298| 0| } 299| | 300| | /// Add a repository to this provider. Only the repositories added with this interface can be operated on 301| | /// with this provider. 302| 0| public func add(specifier: RepositorySpecifier, repository: InMemoryGitRepository) { 303| 0| // Save the repository in specifer map. 304| 0| specifierMap[specifier] = repository 305| 0| } 306| | 307| | /// This method returns the stored reference to the git repository which was fetched or checked out. 308| 0| public func openRepo(at path: AbsolutePath) -> InMemoryGitRepository { 309| 0| return fetchedMap[path] ?? checkoutsMap[path]! 310| 0| } 311| | 312| | // MARK: - RepositoryProvider conformance 313| | // Note: These methods use force unwrap (instead of throwing) to honor their preconditions. 314| | 315| 0| public func fetch(repository: RepositorySpecifier, to path: AbsolutePath) throws { 316| 0| fetchedMap[path] = specifierMap[repository]!.copy() 317| 0| } 318| | 319| 0| public func open(repository: RepositorySpecifier, at path: AbsolutePath) throws -> Repository { 320| 0| return fetchedMap[path]! 321| 0| } 322| | 323| | public func cloneCheckout( 324| | repository: RepositorySpecifier, 325| | at sourcePath: AbsolutePath, 326| | to destinationPath: AbsolutePath, 327| | editable: Bool 328| 0| ) throws { 329| 0| let checkout = fetchedMap[sourcePath]!.copy(at: destinationPath) 330| 0| checkoutsMap[destinationPath] = checkout 331| 0| try checkout.installHead() 332| 0| } 333| | 334| 0| public func checkoutExists(at path: AbsolutePath) throws -> Bool { 335| 0| return checkoutsMap.keys.contains(path) 336| 0| } 337| | 338| 0| public func openCheckout(at path: AbsolutePath) throws -> WorkingCheckout { 339| 0| return checkoutsMap[path]! 340| 0| } 341| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SourceControl/Repository.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// Specifies a repository address. 14| |public struct RepositorySpecifier: Hashable { 15| | /// The URL of the repository. 16| | public let url: String 17| | 18| | /// Create a specifier. 19| 0| public init(url: String) { 20| 0| self.url = url 21| 0| } 22| | 23| | /// A unique identifier for this specifier. 24| | /// 25| | /// This identifier is suitable for use in a file system path, and 26| | /// unique for each repository. 27| 0| public var fileSystemIdentifier: String { 28| 0| // Use first 8 chars of a stable hash. 29| 0| let hash = SHA256(url).digestString() 30| 0| let suffix = hash.dropLast(hash.count - 8) 31| 0| 32| 0| return basename + "-" + suffix 33| 0| } 34| | 35| | /// Returns the cleaned basename for the specifier. 36| 0| public var basename: String { 37| 0| var basename = url.components(separatedBy: "/").last! 38| 0| if basename.hasSuffix(".git") { 39| 0| basename = String(basename.dropLast(4)) 40| 0| } 41| 0| return basename 42| 0| } 43| |} 44| | 45| |extension RepositorySpecifier: CustomStringConvertible { 46| 0| public var description: String { 47| 0| return url 48| 0| } 49| |} 50| | 51| |extension RepositorySpecifier: JSONMappable, JSONSerializable { 52| 0| public init(json: JSON) throws { 53| 0| guard case .string(let url) = json else { 54| 0| throw JSON.MapError.custom(key: nil, message: "expected string, got \(json)") 55| 0| } 56| 0| self.url = url 57| 0| } 58| | 59| 0| public func toJSON() -> JSON { 60| 0| return .string(url) 61| 0| } 62| |} 63| | 64| |/// A repository provider. 65| |/// 66| |/// This protocol defines the lower level interface used to to access 67| |/// repositories. High-level clients should access repositories via a 68| |/// `RepositoryManager`. 69| |public protocol RepositoryProvider { 70| | /// Fetch the complete repository at the given location to `path`. 71| | /// 72| | /// - Throws: If there is an error fetching the repository. 73| | func fetch(repository: RepositorySpecifier, to path: AbsolutePath) throws 74| | 75| | /// Open the given repository. 76| | /// 77| | /// - Parameters: 78| | /// - repository: The specifier for the repository. 79| | /// - path: The location of the repository on disk, at which the 80| | /// repository has previously been created via `fetch`. 81| | /// - Throws: If the repository is unable to be opened. 82| | func open(repository: RepositorySpecifier, at path: AbsolutePath) throws -> Repository 83| | 84| | /// Clone a managed repository into a working copy at on the local file system. 85| | /// 86| | /// Once complete, the repository can be opened using `openCheckout`. 87| | /// 88| | /// - Parameters: 89| | /// - sourcePath: The location of the repository on disk, at which the 90| | /// repository has previously been created via `fetch`. 91| | /// - destinationPath: The path at which to create the working copy; it is 92| | /// expected to be non-existent when called. 93| | /// - editable: The checkout is expected to be edited by users. 94| | func cloneCheckout( 95| | repository: RepositorySpecifier, 96| | at sourcePath: AbsolutePath, 97| | to destinationPath: AbsolutePath, 98| | editable: Bool) throws 99| | 100| | /// Returns true if a working repository exists at `path` 101| | func checkoutExists(at path: AbsolutePath) throws -> Bool 102| | 103| | /// Open a working repository copy. 104| | /// 105| | /// - Parameters: 106| | /// - path: The location of the repository on disk, at which the 107| | /// repository has previously been created via `cloneCheckout`. 108| | func openCheckout(at path: AbsolutePath) throws -> WorkingCheckout 109| |} 110| | 111| |extension RepositoryProvider { 112| 0| public func checkoutExists(at path: AbsolutePath) throws -> Bool { 113| 0| fatalError("Unimplemented") 114| 0| } 115| |} 116| | 117| |/// Abstract repository operations. 118| |/// 119| |/// This interface provides access to an abstracted representation of a 120| |/// repository which is ultimately owned by a `RepositoryManager`. This interface 121| |/// is designed in such a way as to provide the minimal facilities required by 122| |/// the package manager to gather basic information about a repository, but it 123| |/// does not aim to provide all of the interfaces one might want for working 124| |/// with an editable checkout of a repository on disk. 125| |/// 126| |/// The goal of this design is to allow the `RepositoryManager` a large degree of 127| |/// flexibility in the storage and maintenance of its underlying repositories. 128| |/// 129| |/// This protocol is designed under the assumption that the repository can only 130| |/// be mutated via the functions provided here; thus, e.g., `tags` is expected 131| |/// to be unchanged through the lifetime of an instance except as otherwise 132| |/// documented. The behavior when this assumption is violated is undefined, 133| |/// although the expectation is that implementations should throw or crash when 134| |/// an inconsistency can be detected. 135| |public protocol Repository { 136| | /// Get the list of tags in the repository. 137| | var tags: [String] { get } 138| | 139| | /// Resolve the revision for a specific tag. 140| | /// 141| | /// - Precondition: The `tag` should be a member of `tags`. 142| | /// - Throws: If a error occurs accessing the named tag. 143| | func resolveRevision(tag: String) throws -> Revision 144| | 145| | /// Resolve the revision for an identifier. 146| | /// 147| | /// The identifier can be a branch name or a revision identifier. 148| | /// 149| | /// - Throws: If the identifier can not be resolved. 150| | func resolveRevision(identifier: String) throws -> Revision 151| | 152| | /// Fetch and update the repository from its remote. 153| | /// 154| | /// - Throws: If an error occurs while performing the fetch operation. 155| | func fetch() throws 156| | 157| | /// Returns true if the given revision exists. 158| | func exists(revision: Revision) -> Bool 159| | 160| | /// Open an immutable file system view for a particular revision. 161| | /// 162| | /// This view exposes the contents of the repository at the given revision 163| | /// as a file system rooted inside the repository. The repository must 164| | /// support opening multiple views concurrently, but the expectation is that 165| | /// clients should be prepared for this to be inefficient when performing 166| | /// interleaved accesses across separate views (i.e., the repository may 167| | /// back the view by an actual file system representation of the 168| | /// repository). 169| | /// 170| | /// It is expected behavior that attempts to mutate the given FileSystem 171| | /// will fail or crash. 172| | /// 173| | /// - Throws: If a error occurs accessing the revision. 174| | func openFileView(revision: Revision) throws -> FileSystem 175| |} 176| | 177| |/// An editable checkout of a repository (i.e. a working copy) on the local file 178| |/// system. 179| |public protocol WorkingCheckout { 180| | /// Get the list of tags in the repository. 181| | var tags: [String] { get } 182| | 183| | /// Get the current revision. 184| | func getCurrentRevision() throws -> Revision 185| | 186| | /// Fetch and update the repository from its remote. 187| | /// 188| | /// - Throws: If an error occurs while performing the fetch operation. 189| | func fetch() throws 190| | 191| | /// Query whether the checkout has any commits which are not pushed to its remote. 192| | func hasUnpushedCommits() throws -> Bool 193| | 194| | /// This check for any modified state of the repository and returns true 195| | /// if there are uncommited changes. 196| | func hasUncommittedChanges() -> Bool 197| | 198| | /// Check out the given tag. 199| | func checkout(tag: String) throws 200| | 201| | /// Check out the given revision. 202| | func checkout(revision: Revision) throws 203| | 204| | /// Returns true if the given revision exists. 205| | func exists(revision: Revision) -> Bool 206| | 207| | /// Create a new branch and checkout HEAD to it. 208| | /// 209| | /// Note: It is an error to provide a branch name which already exists. 210| | func checkout(newBranch: String) throws 211| | 212| | /// Returns true if there is an alternative store in the checkout and it is valid. 213| | func isAlternateObjectStoreValid() -> Bool 214| | 215| | /// Returns true if the file at `path` is ignored by `git` 216| | func areIgnored(_ paths: [AbsolutePath]) throws -> [Bool] 217| |} 218| | 219| |extension WorkingCheckout { 220| 0| public func areIgnored(_ paths: [AbsolutePath]) throws -> [Bool] { 221| 0| fatalError("Unimplemented") 222| 0| } 223| |} 224| | 225| |/// A single repository revision. 226| |public struct Revision: Hashable { 227| | /// A precise identifier for a single repository revision, in a repository-specified manner. 228| | /// 229| | /// This string is intended to be opaque to the client, but understandable 230| | /// by a user. For example, a Git repository might supply the SHA1 of a 231| | /// commit, or an SVN repository might supply a string such as 'r123'. 232| | public let identifier: String 233| | 234| 0| public init(identifier: String) { 235| 0| self.identifier = identifier 236| 0| } 237| |} 238| | 239| |extension Revision: JSONMappable { 240| 0| public init(json: JSON) throws { 241| 0| guard case .string(let identifier) = json else { 242| 0| throw JSON.MapError.custom(key: nil, message: "expected string, got \(json)") 243| 0| } 244| 0| self.init(identifier: identifier) 245| 0| } 246| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SourceControl/RepositoryManager.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Dispatch 12| |import class Foundation.OperationQueue 13| | 14| |import Basic 15| |import SPMUtility 16| | 17| |/// Delegate to notify clients about actions being performed by RepositoryManager. 18| |public protocol RepositoryManagerDelegate: class { 19| | /// Called when a repository is about to be fetched. 20| | func fetchingWillBegin(handle: RepositoryManager.RepositoryHandle) 21| | 22| | /// Called when a repository has finished fetching. 23| | func fetchingDidFinish(handle: RepositoryManager.RepositoryHandle, error: Swift.Error?) 24| | 25| | /// Called when a repository has started updating from its remote. 26| | func handleWillUpdate(handle: RepositoryManager.RepositoryHandle) 27| | 28| | /// Called when a repository has finished updating from its remote. 29| | func handleDidUpdate(handle: RepositoryManager.RepositoryHandle) 30| |} 31| | 32| |public extension RepositoryManagerDelegate { 33| 0| func fetchingWillBegin(handle: RepositoryManager.RepositoryHandle) {} 34| 0| func fetchingDidFinish(handle: RepositoryManager.RepositoryHandle, error: Swift.Error?) {} 35| 0| func handleWillUpdate(handle: RepositoryManager.RepositoryHandle) {} 36| 0| func handleDidUpdate(handle: RepositoryManager.RepositoryHandle) {} 37| |} 38| | 39| |/// Manages a collection of bare repositories. 40| |public class RepositoryManager { 41| | 42| | public typealias LookupResult = Result 43| | public typealias LookupCompletion = (LookupResult) -> Void 44| | 45| | /// Handle to a managed repository. 46| | public class RepositoryHandle { 47| | enum Status: String { 48| | /// The repository has not been requested. 49| | case uninitialized 50| | 51| | /// The repository is being fetched. 52| | case pending 53| | 54| | /// The repository is available. 55| | case available 56| | 57| | /// The repository was unable to be fetched. 58| | case error 59| | } 60| | 61| | /// The manager this repository is owned by. 62| | private unowned let manager: RepositoryManager 63| | 64| | /// The repository specifier. 65| | public let repository: RepositorySpecifier 66| | 67| | /// The subpath of the repository within the manager. 68| | /// 69| | /// This is intentionally hidden from the clients so that the manager is 70| | /// allowed to move repositories transparently. 71| | fileprivate let subpath: RelativePath 72| | 73| | /// The status of the repository. 74| | fileprivate var status: Status = .uninitialized 75| | 76| | /// The serial queue to perform the operations like updating the state 77| | /// of the handle and fetching the repositories from its remote. 78| | /// 79| | /// The advantage of having a serial queue in handle is that we don't 80| | /// have to worry about multiple lookups on the same handle as they will 81| | /// be queued automatically. 82| | fileprivate let serialQueue = DispatchQueue(label: "org.swift.swiftpm.repohandle-serial") 83| | 84| | /// Create a handle. 85| 0| fileprivate init(manager: RepositoryManager, repository: RepositorySpecifier, subpath: RelativePath) { 86| 0| self.manager = manager 87| 0| self.repository = repository 88| 0| self.subpath = subpath 89| 0| } 90| | 91| | /// Create a handle from JSON data. 92| 0| fileprivate init(manager: RepositoryManager, json: JSON) throws { 93| 0| self.manager = manager 94| 0| self.repository = try json.get("repositoryURL") 95| 0| self.subpath = try RelativePath(json.get("subpath")) 96| 0| self.status = try Status(rawValue: json.get("status"))! 97| 0| } 98| | 99| | /// Open the given repository. 100| 0| public func open() throws -> Repository { 101| 0| precondition(status == .available, "open() called in invalid state") 102| 0| return try self.manager.open(self) 103| 0| } 104| | 105| | /// Clone into a working copy at on the local file system. 106| | /// 107| | /// - Parameters: 108| | /// - path: The path at which to create the working copy; it is 109| | /// expected to be non-existent when called. 110| | /// 111| | /// - editable: The clone is expected to be edited by user. 112| 0| public func cloneCheckout(to path: AbsolutePath, editable: Bool) throws { 113| 0| precondition(status == .available, "cloneCheckout() called in invalid state") 114| 0| try self.manager.cloneCheckout(self, to: path, editable: editable) 115| 0| } 116| | 117| 0| fileprivate func toJSON() -> JSON { 118| 0| return .init([ 119| 0| "status": status.rawValue, 120| 0| "repositoryURL": repository, 121| 0| "subpath": subpath, 122| 0| ]) 123| 0| } 124| | } 125| | 126| | /// The path under which repositories are stored. 127| | public let path: AbsolutePath 128| | 129| | /// The repository provider. 130| | public let provider: RepositoryProvider 131| | 132| | /// The delegate interface. 133| | private let delegate: RepositoryManagerDelegate? 134| | 135| | // FIXME: We should use a more sophisticated map here, which tracks the 136| | // full specifier but then is capable of efficiently determining if two 137| | // repositories map to the same location. 138| | // 139| | /// The map of registered repositories. 140| | fileprivate var repositories: [String: RepositoryHandle] = [:] 141| | 142| | /// The map of serialized repositories. 143| | /// 144| | /// NOTE: This is to be used only for persistence support. 145| | fileprivate var serializedRepositories: [String: JSON] = [:] 146| | 147| | /// Queue to protect concurrent reads and mutations to repositories registery. 148| | private let serialQueue = DispatchQueue(label: "org.swift.swiftpm.repomanagerqueue-serial") 149| | 150| | /// Queue for dispatching callbacks like delegate and completion block. 151| | private let callbacksQueue = DispatchQueue(label: "org.swift.swiftpm.repomanagerqueue-callback") 152| | 153| | /// Operation queue to do concurrent operations on manager. 154| | /// 155| | /// We use operation queue (and not dispatch queue) to limit the amount of 156| | /// concurrent operations. 157| | private let operationQueue: OperationQueue 158| | 159| | /// The filesystem to operate on. 160| | public let fileSystem: FileSystem 161| | 162| | /// Simple persistence helper. 163| | private let persistence: SimplePersistence 164| | 165| | /// Create a new empty manager. 166| | /// 167| | /// - Parameters: 168| | /// - path: The path under which to store repositories. This should be a 169| | /// directory in which the content can be completely managed by this 170| | /// instance. 171| | /// - provider: The repository provider. 172| | /// - delegate: The repository manager delegate. 173| | /// - fileSystem: The filesystem to operate on. 174| | public init( 175| | path: AbsolutePath, 176| | provider: RepositoryProvider, 177| | delegate: RepositoryManagerDelegate? = nil, 178| | fileSystem: FileSystem = localFileSystem 179| 0| ) { 180| 0| self.path = path 181| 0| self.provider = provider 182| 0| self.delegate = delegate 183| 0| self.fileSystem = fileSystem 184| 0| 185| 0| self.operationQueue = OperationQueue() 186| 0| self.operationQueue.name = "org.swift.swiftpm.repomanagerqueue-concurrent" 187| 0| self.operationQueue.maxConcurrentOperationCount = 10 188| 0| 189| 0| self.persistence = SimplePersistence( 190| 0| fileSystem: fileSystem, 191| 0| schemaVersion: 1, 192| 0| statePath: path.appending(component: "checkouts-state.json")) 193| 0| 194| 0| // Load the state from disk, if possible. 195| 0| do { 196| 0| _ = try self.persistence.restoreState(self) 197| 0| } catch { 198| 0| // State restoration errors are ignored, for now. 199| 0| // 200| 0| // FIXME: We need to do something better here. 201| 0| print("warning: unable to restore checkouts state: \(error)") 202| 0| 203| 0| // Try to save the empty state. 204| 0| try? self.persistence.saveState(self) 205| 0| } 206| 0| } 207| | 208| | /// Get a handle to a repository. 209| | /// 210| | /// This will initiate a clone of the repository automatically, if necessary. 211| | /// 212| | /// Note: Recursive lookups are not supported i.e. calling lookup inside 213| | /// completion block of another lookup will block. 214| | /// 215| | /// - Parameters: 216| | /// - repository: The repository to look up. 217| | /// - skipUpdate: If a repository is availble, skip updating it. 218| | /// - completion: The completion block that should be called after lookup finishes. 219| | public func lookup( 220| | repository: RepositorySpecifier, 221| | skipUpdate: Bool = false, 222| | completion: @escaping LookupCompletion 223| 0| ) { 224| 0| operationQueue.addOperation { 225| 0| // First look for the handle. 226| 0| let handle = self.getHandle(repository: repository) 227| 0| // Dispatch the action we want to take on the serial queue of the handle. 228| 0| handle.serialQueue.sync { 229| 0| let result: LookupResult 230| 0| 231| 0| switch handle.status { 232| 0| case .available: 233| 0| result = LookupResult(anyError: { 234| 0| // Update the repository when it is being looked up. 235| 0| let repo = try handle.open() 236| 0| 237| 0| // Skip update if asked to. 238| 0| if skipUpdate { 239| 0| return handle 240| 0| } 241| 0| 242| 0| self.callbacksQueue.async { 243| 0| self.delegate?.handleWillUpdate(handle: handle) 244| 0| } 245| 0| 246| 0| try repo.fetch() 247| 0| 248| 0| self.callbacksQueue.async { 249| 0| self.delegate?.handleDidUpdate(handle: handle) 250| 0| } 251| 0| 252| 0| return handle 253| 0| }) 254| 0| 255| 0| case .pending, .uninitialized, .error: 256| 0| // Change the state to pending. 257| 0| handle.status = .pending 258| 0| let repositoryPath = self.path.appending(handle.subpath) 259| 0| // Make sure desination is free. 260| 0| try? self.fileSystem.removeFileTree(repositoryPath) 261| 0| 262| 0| // Inform delegate. 263| 0| self.callbacksQueue.async { 264| 0| self.delegate?.fetchingWillBegin(handle: handle) 265| 0| } 266| 0| 267| 0| // Fetch the repo. 268| 0| var fetchError: Swift.Error? = nil 269| 0| do { 270| 0| // Start fetching. 271| 0| try self.provider.fetch(repository: handle.repository, to: repositoryPath) 272| 0| // Update status to available. 273| 0| handle.status = .available 274| 0| result = Result(handle) 275| 0| } catch { 276| 0| handle.status = .error 277| 0| fetchError = error 278| 0| result = Result(error) 279| 0| } 280| 0| 281| 0| // Inform delegate. 282| 0| self.callbacksQueue.async { 283| 0| self.delegate?.fetchingDidFinish(handle: handle, error: fetchError) 284| 0| } 285| 0| 286| 0| // Save the manager state. 287| 0| self.serialQueue.sync { 288| 0| do { 289| 0| // Update the serialized repositories map. 290| 0| // 291| 0| // We do this so we don't have to read the other 292| 0| // handles when saving the sate of this handle. 293| 0| self.serializedRepositories[repository.url] = handle.toJSON() 294| 0| try self.persistence.saveState(self) 295| 0| } catch { 296| 0| // FIXME: Handle failure gracefully, somehow. 297| 0| fatalError("unable to save manager state \(error)") 298| 0| } 299| 0| } 300| 0| } 301| 0| // Call the completion handler. 302| 0| self.callbacksQueue.async { 303| 0| completion(result) 304| 0| } 305| 0| } 306| 0| } 307| 0| } 308| | 309| | /// Returns the handle for repository if available, otherwise creates a new one. 310| | /// 311| | /// Note: This method is thread safe. 312| 0| private func getHandle(repository: RepositorySpecifier) -> RepositoryHandle { 313| 0| return serialQueue.sync { 314| 0| 315| 0| // Reset if the state file was deleted during the lifetime of RepositoryManager. 316| 0| if !self.serializedRepositories.isEmpty && !self.persistence.stateFileExists() { 317| 0| self.unsafeReset() 318| 0| } 319| 0| 320| 0| let handle: RepositoryHandle 321| 0| if let oldHandle = self.repositories[repository.url] { 322| 0| handle = oldHandle 323| 0| } else { 324| 0| let subpath = RelativePath(repository.fileSystemIdentifier) 325| 0| let newHandle = RepositoryHandle(manager: self, repository: repository, subpath: subpath) 326| 0| self.repositories[repository.url] = newHandle 327| 0| handle = newHandle 328| 0| } 329| 0| return handle 330| 0| } 331| 0| } 332| | 333| | /// Open a repository from a handle. 334| 0| private func open(_ handle: RepositoryHandle) throws -> Repository { 335| 0| return try provider.open( 336| 0| repository: handle.repository, at: path.appending(handle.subpath)) 337| 0| } 338| | 339| | /// Clone a repository from a handle. 340| | private func cloneCheckout( 341| | _ handle: RepositoryHandle, 342| | to destinationPath: AbsolutePath, 343| | editable: Bool 344| 0| ) throws { 345| 0| try provider.cloneCheckout( 346| 0| repository: handle.repository, 347| 0| at: path.appending(handle.subpath), 348| 0| to: destinationPath, 349| 0| editable: editable) 350| 0| } 351| | 352| | /// Removes the repository. 353| 0| public func remove(repository: RepositorySpecifier) throws { 354| 0| try serialQueue.sync { 355| 0| // If repository isn't present, we're done. 356| 0| guard let handle = repositories[repository.url] else { 357| 0| return 358| 0| } 359| 0| repositories[repository.url] = nil 360| 0| serializedRepositories[repository.url] = nil 361| 0| let repositoryPath = path.appending(handle.subpath) 362| 0| try fileSystem.removeFileTree(repositoryPath) 363| 0| try self.persistence.saveState(self) 364| 0| } 365| 0| } 366| | 367| | /// Reset the repository manager. 368| | /// 369| | /// Note: This also removes the cloned repositories from the disk. 370| 0| public func reset() { 371| 0| serialQueue.sync { 372| 0| self.unsafeReset() 373| 0| } 374| 0| } 375| | 376| | /// Performs the reset operation without the serial queue. 377| 0| private func unsafeReset() { 378| 0| self.repositories = [:] 379| 0| self.serializedRepositories = [:] 380| 0| try? self.fileSystem.removeFileTree(path) 381| 0| } 382| |} 383| | 384| |// MARK: Persistence 385| |extension RepositoryManager: SimplePersistanceProtocol { 386| | 387| 0| public func restore(from json: JSON) throws { 388| 0| // Update the serialized repositories. 389| 0| // 390| 0| // We will use this to save the state so we don't have to read the other 391| 0| // handles when saving the sate of a handle. 392| 0| self.serializedRepositories = try json.get("repositories") 393| 0| self.repositories = try Dictionary(items: serializedRepositories.map({ 394| 0| try ($0.0, RepositoryHandle(manager: self, json: $0.1)) 395| 0| })) 396| 0| } 397| | 398| 0| public func toJSON() -> JSON { 399| 0| return JSON(["repositories": JSON(self.serializedRepositories)]) 400| 0| } 401| |} 402| | 403| |extension RepositoryManager.RepositoryHandle: CustomStringConvertible { 404| 0| public var description: String { 405| 0| return "<\(type(of: self)) subpath:\(subpath)>" 406| 0| } 407| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SourceControl/SwiftPMConfig.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| | 13| |import Basic 14| |import SPMUtility 15| | 16| |// FIXME: We may want to move this class to some other layer once we start 17| |// supporting more things than just mirrors. 18| |// 19| |/// Manages a package's configuration. 20| |public final class SwiftPMConfig { 21| | 22| | enum Error: Swift.Error, CustomStringConvertible { 23| | case mirrorNotFound 24| | 25| 0| var description: String { 26| 0| return "mirror not found" 27| 0| } 28| | } 29| | 30| | /// Persistence support. 31| | let persistence: SimplePersistence? 32| | 33| | /// The schema version of the config file. 34| | /// 35| | /// * 1: Initial version. 36| | static let schemaVersion: Int = 1 37| | 38| | /// The mirrors. 39| | private var mirrors: [String: Mirror] 40| | 41| 0| public init(path: AbsolutePath, fs: FileSystem = localFileSystem) { 42| 0| self.mirrors = [:] 43| 0| self.persistence = SimplePersistence( 44| 0| fileSystem: fs, schemaVersion: SwiftPMConfig.schemaVersion, 45| 0| statePath: path, prettyPrint: true 46| 0| ) 47| 0| } 48| | 49| 0| public init() { 50| 0| self.mirrors = [:] 51| 0| self.persistence = nil 52| 0| } 53| | 54| | /// Set a mirror URL for the given package URL. 55| 0| public func set(mirrorURL: String, forPackageURL packageURL: String) throws { 56| 0| mirrors[packageURL] = Mirror(original: packageURL, mirror: mirrorURL) 57| 0| try saveState() 58| 0| } 59| | 60| | /// Unset a mirror for the given package or mirror URL. 61| | /// 62| | /// This method will throw if there is no mirror for the given input. 63| 0| public func unset(packageOrMirrorURL: String) throws { 64| 0| if mirrors.keys.contains(packageOrMirrorURL) { 65| 0| mirrors[packageOrMirrorURL] = nil 66| 0| } else if let mirror = mirrors.first(where: { $0.value.mirror == packageOrMirrorURL }) { 67| 0| mirrors[mirror.key] = nil 68| 0| } else { 69| 0| throw Error.mirrorNotFound 70| 0| } 71| 0| try saveState() 72| 0| } 73| | 74| | /// Returns the mirror for the given specificer. 75| 0| public func getMirror(forURL url: String) -> String? { 76| 0| return mirrors[url]?.mirror 77| 0| } 78| | 79| | /// Returns the mirrored url if it exists, otherwise the original url. 80| 0| public func mirroredURL(forURL url: String) -> String { 81| 0| return getMirror(forURL: url) ?? url 82| 0| } 83| | 84| | /// Load the configuration from disk. 85| 0| public func load() throws { 86| 0| _ = try self.persistence?.restoreState(self) 87| 0| } 88| |} 89| | 90| |// MARK: - Persistence. 91| |extension SwiftPMConfig: SimplePersistanceProtocol { 92| | 93| 0| public func saveState() throws { 94| 0| try self.persistence?.saveState(self) 95| 0| } 96| | 97| 0| public func restore(from json: JSON) throws { 98| 0| // FIXME: Find a way to avoid encode-decode dance here. 99| 0| let data = Data(bytes: json.toBytes().contents) 100| 0| let mirrorsData = try JSONDecoder().decode([Mirror].self, from: data) 101| 0| self.mirrors = Dictionary(mirrorsData.map({ ($0.original, $0) }), uniquingKeysWith: { first, _ in first }) 102| 0| } 103| | 104| 0| public func toJSON() -> JSON { 105| 0| // FIXME: Find a way to avoid encode-decode dance here. 106| 0| let jsonData = try! JSONEncoder().encode(mirrors.values.sorted(by: { $0.original < $1.mirror })) 107| 0| return try! JSON(data: jsonData) 108| 0| } 109| |} 110| | 111| |/// An individual repository mirror. 112| |public struct Mirror: Codable { 113| | /// The original repository path. 114| | public let original: String 115| | 116| | /// The mirrored repository path. 117| | public let mirror: String 118| | 119| 0| public init(original: String, mirror: String) { 120| 0| self.original = original 121| 0| self.mirror = mirror 122| 0| } 123| |} <<<<<< EOF # path=SPMLLBuild.framework.coverage.txt 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |// We either export the llbuildSwift shared library or the llbuild framework. 12| |#if canImport(llbuildSwift) 13| |@_exported import llbuildSwift 14| |@_exported import llbuild 15| |#else 16| |@_exported import llbuild 17| |#endif 18| | 19| |import Foundation 20| | 21| |/// An llbuild value. 22| |public protocol LLBuildValue: Codable { 23| |} 24| | 25| |/// An llbuild key. 26| |public protocol LLBuildKey: Codable { 27| | /// The value that this key computes. 28| | associatedtype BuildValue: LLBuildValue 29| | 30| | /// The rule that this key operates on. 31| | associatedtype BuildRule: LLBuildRule 32| |} 33| | 34| |public protocol LLBuildEngineDelegate { 35| | func lookupRule(rule: String, key: Key) -> Rule 36| |} 37| | 38| |public final class LLBuildEngine { 39| | 40| | private final class Delegate: BuildEngineDelegate { 41| | let delegate: LLBuildEngineDelegate 42| | 43| 0| init(_ delegate: LLBuildEngineDelegate) { 44| 0| self.delegate = delegate 45| 0| } 46| | 47| 0| func lookupRule(_ key: Key) -> Rule { 48| 0| let ruleKey = RuleKey(key) 49| 0| return delegate.lookupRule( 50| 0| rule: ruleKey.rule, key: Key(ruleKey.data)) 51| 0| } 52| | } 53| | 54| | private let engine: BuildEngine 55| | 56| 0| public init(delegate: LLBuildEngineDelegate) { 57| 0| engine = BuildEngine(delegate: Delegate(delegate)) 58| 0| } 59| | 60| 0| deinit { 61| 0| engine.close() 62| 0| } 63| | 64| 0| public func build(key: T) -> T.BuildValue { 65| 0| let encodedKey = RuleKey( 66| 0| rule: T.BuildRule.ruleName, data: key.toKey().data).toKey() 67| 0| let value = engine.build(key: encodedKey) 68| 0| return T.BuildValue(value) 69| 0| } 70| | 71| 0| public func attachDB(path: String, schemaVersion: Int = 0) throws { 72| 0| try engine.attachDB(path: path, schemaVersion: schemaVersion) 73| 0| } 74| | 75| 0| public func close() { 76| 0| engine.close() 77| 0| } 78| |} 79| | 80| |// FIXME: Rename to something else. 81| |public class LLTaskBuildEngine { 82| | 83| | let engine: TaskBuildEngine 84| | 85| 0| init(_ engine: TaskBuildEngine) { 86| 0| self.engine = engine 87| 0| } 88| | 89| 0| public func taskNeedsInput(_ key: T, inputID: Int) { 90| 0| let encodedKey = RuleKey( 91| 0| rule: T.BuildRule.ruleName, data: key.toKey().data).toKey() 92| 0| engine.taskNeedsInput(encodedKey, inputID: inputID) 93| 0| } 94| | 95| 0| public func taskIsComplete(_ result: T) { 96| 0| engine.taskIsComplete(result.toValue(), forceChange: false) 97| 0| } 98| |} 99| | 100| |/// An individual build rule. 101| |open class LLBuildRule: Rule, Task { 102| | 103| | /// The name of the rule. 104| | /// 105| | /// This name will be available in the delegate's lookupRule(rule:key:). 106| 0| open class var ruleName: String { 107| 0| fatalError("subclass responsibility") 108| 0| } 109| | 110| 0| public init() { 111| 0| } 112| | 113| 0| public func createTask() -> Task { 114| 0| return self 115| 0| } 116| | 117| 0| public func start(_ engine: TaskBuildEngine) { 118| 0| self.start(LLTaskBuildEngine(engine)) 119| 0| } 120| | 121| 0| public func provideValue(_ engine: TaskBuildEngine, inputID: Int, value: Value) { 122| 0| self.provideValue(LLTaskBuildEngine(engine), inputID: inputID, value: value) 123| 0| } 124| | 125| 0| public func inputsAvailable(_ engine: TaskBuildEngine) { 126| 0| self.inputsAvailable(LLTaskBuildEngine(engine)) 127| 0| } 128| | 129| | // MARK:- 130| | 131| 0| open func isResultValid(_ priorValue: Value) -> Bool { 132| 0| return true 133| 0| } 134| | 135| 0| open func start(_ engine: LLTaskBuildEngine) { 136| 0| } 137| | 138| 0| open func provideValue(_ engine: LLTaskBuildEngine, inputID: Int, value: Value) { 139| 0| } 140| | 141| 0| open func inputsAvailable(_ engine: LLTaskBuildEngine) { 142| 0| } 143| |} 144| | 145| |// MARK:- Helpers 146| | 147| |private struct RuleKey: Codable { 148| | 149| | let rule: String 150| | let data: [UInt8] 151| | 152| 0| init(rule: String, data: [UInt8]) { 153| 0| self.rule = rule 154| 0| self.data = data 155| 0| } 156| | 157| 0| init(_ key: Key) { 158| 0| self.init(key.data) 159| 0| } 160| | 161| 0| init(_ data: [UInt8]) { 162| 0| self = try! fromBytes(data) 163| 0| } 164| | 165| 0| func toKey() -> Key { 166| 0| return try! Key(toBytes(self)) 167| 0| } 168| |} 169| | 170| |public extension LLBuildKey { 171| 0| init(_ key: Key) { 172| 0| self.init(key.data) 173| 0| } 174| | 175| 0| init(_ data: [UInt8]) { 176| 0| self = try! fromBytes(data) 177| 0| } 178| | 179| 0| func toKey() -> Key { 180| 0| return try! Key(toBytes(self)) 181| 0| } 182| |} 183| | 184| |public extension LLBuildValue { 185| 0| init(_ value: Value) { 186| 0| self = try! fromBytes(value.data) 187| 0| } 188| | 189| 0| func toValue() -> Value { 190| 0| return try! Value(toBytes(self)) 191| 0| } 192| |} 193| | 194| 0|private func fromBytes(_ bytes: [UInt8]) throws -> T { 195| 0| var bytes = bytes 196| 0| let data = Data(bytes: &bytes, count: bytes.count) 197| 0| return try JSONDecoder().decode(T.self, from: data) 198| 0|} 199| | 200| 0|private func toBytes(_ value: T) throws -> [UInt8] { 201| 0| let encoder = JSONEncoder() 202| 0| if #available(macOS 10.13, *) { 203| 0| encoder.outputFormatting = [.sortedKeys] 204| 0| } 205| 0| let encoded = try encoder.encode(value) 206| 0| return [UInt8](encoded) 207| 0|} <<<<<< EOF # path=libllbuild.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/BinaryCoding.h: 1| |//===- BinaryCoding.h -------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_BINARYCODING_H 14| |#define LLBUILD_BASIC_BINARYCODING_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/SmallVector.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |#include 23| |#include 24| | 25| |namespace llbuild { 26| |namespace basic { 27| | 28| |template 29| |struct BinaryCodingTraits { 30| | // static inline void encode(const T&, BinaryEncoder&); 31| | // static inline void decode(T&, BinaryDecoder&); 32| |}; 33| | 34| |/// A basic binary encoding utility. 35| |/// 36| |/// This encoder is design for small, relatively efficient, in-memory coding of 37| |/// objects. It is endian-neutral, and should be paired with \see BinaryDecoder 38| |/// for decoding. The specific encoding is not intended to be stable. 39| |/// 40| |/// The utility supports coding of user-defined types via specialization of the 41| |/// BinaryCodeableTraits type. 42| |class BinaryEncoder { 43| |private: 44| | // Copying is disabled. 45| | BinaryEncoder(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 46| | void operator=(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 47| | 48| | /// The encoded data. 49| | // 50| | // FIXME: Parameterize this size? 51| | llvm::SmallVector encdata; 52| | 53| |public: 54| | /// Construct a new binary encoder. 55| 0| BinaryEncoder() {} 56| | 57| | /// Encode a value to the stream. 58| 0| void write(bool value) { 59| 0| encdata.push_back(uint8_t(value)); 60| 0| } 61| | 62| | /// Encode a value to the stream. 63| 0| void write(uint8_t value) { 64| 0| encdata.push_back(value); 65| 0| } 66| | 67| | /// Encode a value to the stream. 68| 0| void write(uint16_t value) { 69| 0| write(uint8_t(value >> 0)); 70| 0| write(uint8_t(value >> 8)); 71| 0| } 72| | 73| | /// Encode a value to the stream. 74| 0| void write(uint32_t value) { 75| 0| write(uint16_t(value >> 0)); 76| 0| write(uint16_t(value >> 16)); 77| 0| } 78| | 79| | /// Encode a value to the stream. 80| 0| void write(uint64_t value) { 81| 0| write(uint32_t(value >> 0)); 82| 0| write(uint32_t(value >> 32)); 83| 0| } 84| | 85| | /// Encode a value to the stream. 86| | /// 87| | /// We do not support encoding values larger than 4GB. 88| 0| void write(const std::string& value) { 89| 0| uint32_t size = uint32_t(value.size()); 90| 0| assert(size == value.size()); 91| 0| write(size); 92| 0| writeBytes(StringRef(value)); 93| 0| } 94| | 95| | /// Encode a sequence of bytes to the stream. 96| 0| void writeBytes(StringRef bytes) { 97| 0| encdata.insert(encdata.end(), bytes.begin(), bytes.end()); 98| 0| } 99| | 100| | /// Encode a value to the stream. 101| | template 102| 0| void write(const T& value) { 103| 0| BinaryCodingTraits::encode(value, *this); 104| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_13FileTimestampEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeIN4llvm9StringRefEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_10StringListEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS_11buildsystem10BuildValue4KindEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_16CommandSignatureEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_8FileInfoEEEvRKT_ ------------------ 105| | 106| | /// Get the encoded binary data. 107| | std::vector contents() { 108| | return std::vector(encdata.begin(), encdata.end()); 109| | } 110| | 111| | /// Get the encoded binary data (in place) 112| | const uint8_t* data() const { 113| | return encdata.data(); 114| | } 115| | 116| | /// Get the size of the encoded binary data 117| | const size_t size() const { 118| | return encdata.size(); 119| | } 120| |}; 121| | 122| |/// A basic binary decoding utility. 123| |/// 124| |/// \see BinaryEncoder. 125| |class BinaryDecoder { 126| |private: 127| | // Copying is disabled. 128| | BinaryDecoder(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 129| | void operator=(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 130| | 131| | /// The data being decoded. 132| | StringRef data; 133| | 134| | /// The current position in the stream. 135| | uint64_t pos = 0; 136| | 137| | uint8_t read8() { return data[pos++]; } 138| | uint16_t read16() { 139| | uint16_t result = read8(); 140| | result |= uint16_t(read8()) << 8; 141| | return result; 142| | } 143| | uint32_t read32() { 144| | uint32_t result = read16(); 145| | result |= uint32_t(read16()) << 16; 146| | return result; 147| | } 148| | uint64_t read64() { 149| | uint64_t result = read32(); 150| | result |= uint64_t(read32()) << 32; 151| | return result; 152| | } 153| | 154| |public: 155| | /// Construct a binary decoder. 156| 0| BinaryDecoder(StringRef data) : data(data) {} 157| | 158| | /// Construct a binary decoder. 159| | /// 160| | /// NOTE: The input data is supplied by reference, and its lifetime must 161| | /// exceed that of the decoder. 162| | BinaryDecoder(const std::vector& data) : BinaryDecoder( 163| 0| StringRef(reinterpret_cast(data.data()), data.size())) {} 164| | 165| | /// Check if the decoder is at the end of the stream. 166| | bool isEmpty() const { 167| | return pos == data.size(); 168| | } 169| | 170| | /// Decode a value from the stream. 171| 0| void read(bool& value) { value = read8() != 0; } 172| | 173| | /// Decode a value from the stream. 174| 0| void read(uint8_t& value) { value = read8(); } 175| | 176| | /// Decode a value from the stream. 177| 0| void read(uint16_t& value) { value = read16(); } 178| | 179| | /// Decode a value from the stream. 180| 0| void read(uint32_t& value) { value = read32(); } 181| | 182| | /// Decode a value from the stream. 183| 0| void read(uint64_t& value) { value = read64(); } 184| | 185| | /// Decode a value from the stream. 186| 0| void read(std::string& value) { 187| 0| uint32_t size; 188| 0| read(size); 189| 0| StringRef contents; 190| 0| readBytes(size, contents); 191| 0| value = contents.str(); 192| 0| } 193| | 194| | /// Decode a byte string from the stream. 195| | /// 196| | /// NOTE: The return value points into the decode stream, and must be copied 197| | /// by clients if it is to last longer than the lifetime of the decoder. 198| | void readBytes(size_t count, StringRef& value) { 199| | assert(pos + count <= data.size()); 200| | value = StringRef(data.begin() + pos, count); 201| | pos += count; 202| | } 203| | 204| | /// Decode a value from the stream. 205| | template 206| 0| void read(T& value) { 207| 0| BinaryCodingTraits::decode(value, *this); 208| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_13FileTimestampEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS_11buildsystem10BuildValue4KindEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_16CommandSignatureEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_8FileInfoEEEvRT_ ------------------ 209| | 210| | /// Finish decoding and clean up. 211| | void finish() { 212| | assert(isEmpty()); 213| | } 214| |}; 215| | 216| |template<> 217| |struct BinaryCodingTraits { 218| 0| static inline void encode(const StringRef& value, BinaryEncoder& coder) { 219| 0| coder.writeBytes(value); 220| 0| } 221| |}; 222| | 223| |} 224| |} 225| | 226| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/ExecutionQueue.h: 1| |//===- ExecutionQueue.h -----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_EXECUTIONQUEUE_H 14| |#define LLBUILD_BASIC_EXECUTIONQUEUE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/Subprocess.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| | namespace basic { 24| | 25| | /// MARK: Execution Queue 26| | 27| | class ExecutionQueueDelegate; 28| | 29| | /// Description of the queue job, used for scheduling and diagnostics. 30| | class JobDescriptor { 31| | public: 32| 0| JobDescriptor() {} 33| | virtual ~JobDescriptor(); 34| | 35| | /// Get a name used for ordering this job 36| | virtual StringRef getOrdinalName() const = 0; 37| | 38| | /// Get a short description of the command, for use in status reporting. 39| | virtual void getShortDescription(SmallVectorImpl &result) const = 0; 40| | 41| | /// Get a verbose description of the command, for use in status reporting. 42| | virtual void getVerboseDescription(SmallVectorImpl &result) const = 0; 43| | }; 44| | 45| | 46| | /// Opaque type which allows the queue implementation to maintain additional 47| | /// state and associate subsequent requests (e.g., \see executeProcess()) 48| | /// with the dispatching job. 49| | class QueueJobContext { 50| | public: 51| | virtual ~QueueJobContext(); 52| | virtual unsigned laneID() const = 0; 53| | }; 54| | 55| | /// Wrapper for individual pieces of work that are added to the execution 56| | /// queue. 57| | class QueueJob { 58| | JobDescriptor* desc = nullptr; 59| | 60| | /// The function to execute to do the work. 61| | typedef std::function work_fn_ty; 62| | work_fn_ty work; 63| | 64| | public: 65| | /// Default constructor, for use as a sentinel. 66| 0| QueueJob() {} 67| | 68| | /// General constructor. 69| | QueueJob(JobDescriptor* desc, work_fn_ty work) 70| 0| : desc(desc), work(work) {} 71| | 72| | JobDescriptor* getDescriptor() const { return desc; } 73| | 74| 0| void execute(QueueJobContext* context) { work(context); } 75| | }; 76| | 77| | /// This abstact class encapsulates the interface needed for contributing 78| | /// work which needs to be executed. 79| | class ExecutionQueue { 80| | // DO NOT COPY 81| | ExecutionQueue(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 82| | void operator=(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 83| | ExecutionQueue& operator=(ExecutionQueue&&) LLBUILD_DELETED_FUNCTION; 84| | 85| | ExecutionQueueDelegate& delegate; 86| | 87| | public: 88| | ExecutionQueue(ExecutionQueueDelegate& delegate); 89| | virtual ~ExecutionQueue(); 90| | 91| | /// @name Accessors 92| | /// @{ 93| | 94| | ExecutionQueueDelegate& getDelegate() { return delegate; } 95| 0| const ExecutionQueueDelegate& getDelegate() const { return delegate; } 96| | 97| | /// @} 98| | 99| | /// Add a job to be executed. 100| | virtual void addJob(QueueJob job) = 0; 101| | 102| | /// Cancel all jobs and subprocesses of this queue. 103| | virtual void cancelAllJobs() = 0; 104| | 105| | 106| | /// @name Execution Interfaces 107| | /// 108| | /// These are additional interfaces provided by the execution queue which 109| | /// can be invoked by the individual \see QueueJob::execute() to perform 110| | /// particular actions. The benefit of delegating to the execution queue 111| | /// to perform these actions is that the queue can potentially do a better 112| | /// job of scheduling activities. 113| | /// 114| | /// @{ 115| | 116| | /// Execute the given command line. 117| | /// 118| | /// This will launch and execute the given command line and wait for it to 119| | /// complete or release its execution lane. 120| | /// 121| | /// \param context The context object passed to the job's worker function. 122| | /// 123| | /// \param commandLine The command line to execute. 124| | /// 125| | /// \param environment The environment to launch with. 126| | /// 127| | /// \param completionFn An optional function that, if supplied, will be 128| | /// run following the completion of the process. This may be run 129| | /// asynchronously from another thread if the executed process asks the 130| | /// system to release its execution lane. Callers should put cleanup and 131| | /// notification work here. 132| | /// 133| | /// \param inheritEnvironment If true, the supplied environment will be 134| | /// overlayed on top base environment supplied when creating the queue. If 135| | /// false, only the supplied environment will be passed to the subprocess. 136| | /// 137| | /// \param attributes Additional attributes for the process to be spawned. 138| | // 139| | // FIXME: This interface will need to get more complicated, and provide the 140| | // command result and facilities for dealing with the output. 141| | virtual void 142| | executeProcess(QueueJobContext* context, 143| | ArrayRef commandLine, 144| | ArrayRef> environment, 145| | bool inheritEnvironment = true, 146| | ProcessAttributes attributes = {true}, 147| | llvm::Optional completionFn = {llvm::None}) = 0; 148| | 149| | /// @} 150| | 151| | /// Execute the given command, using an inherited environment. 152| | ProcessStatus executeProcess(QueueJobContext* context, 153| | ArrayRef commandLine); 154| | 155| | /// Execute the given command using "/bin/sh". 156| | /// 157| | /// This will launch and execute the given command line and wait for it to 158| | /// complete. 159| | /// 160| | /// \param context The context object passed to the job's worker function. 161| | /// \param command The command to execute. 162| | /// \returns True on success. 163| | // 164| | // FIXME: This interface will need to get more complicated, and provide the 165| | // command result and facilities for dealing with the output. 166| | bool executeShellCommand(QueueJobContext* context, StringRef command); 167| | 168| | }; 169| | 170| | /// Delegate interface for execution queue status. 171| | /// 172| | /// All delegate interfaces are invoked synchronously by the execution queue, 173| | /// and should defer any long running operations to avoid blocking the queue 174| | /// unnecessarily. 175| | /// 176| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, which 177| | /// will arrive concurrently and without any specified thread. 178| | class ExecutionQueueDelegate : public ProcessDelegate { 179| | // DO NOT COPY 180| | ExecutionQueueDelegate(const ExecutionQueueDelegate&) 181| | LLBUILD_DELETED_FUNCTION; 182| | void operator=(const ExecutionQueueDelegate&) LLBUILD_DELETED_FUNCTION; 183| | ExecutionQueueDelegate &operator=(ExecutionQueueDelegate&& rhs) 184| | LLBUILD_DELETED_FUNCTION; 185| | 186| | public: 187| 0| ExecutionQueueDelegate() {} 188| | virtual ~ExecutionQueueDelegate(); 189| | 190| | /// Called when a command's job has been started. 191| | /// 192| | /// The queue guarantees that any jobStarted() call will be paired with 193| | /// exactly one \see jobFinished() call. 194| | // 195| | // FIXME: We may eventually want to allow the individual job to provide 196| | // some additional context here, for complex commands. 197| | // 198| | // FIXME: Design a way to communicate the "lane" here, for use in "super 199| | // console" like UIs. 200| | virtual void queueJobStarted(JobDescriptor*) = 0; 201| | 202| | /// Called when a command's job has been finished. 203| | /// 204| | /// NOTE: This callback is invoked by the queue without any understanding 205| | /// of how the command is tied to the engine. In particular, it is almost 206| | /// always the case that the command will have already completed from the 207| | /// perspective of the low-level engine (and its dependents may have 208| | /// started executing). Clients which want to understand when a command is 209| | /// complete before the engine has been notified as such should use \see 210| | /// BuildSystem::commandFinished(). 211| | virtual void queueJobFinished(JobDescriptor*) = 0; 212| | }; 213| | 214| | // MARK: Lane Based Execution Queue 215| | 216| | enum class SchedulerAlgorithm { 217| | /// Name priority queue based scheduling [default] 218| | NamePriority = 0, 219| | 220| | /// First in, first out 221| | FIFO = 1 222| | }; 223| | 224| | /// Create an execution queue that schedules jobs to individual lanes with a 225| | /// capped limit on the number of concurrent lanes. 226| | ExecutionQueue* createLaneBasedExecutionQueue( 227| | ExecutionQueueDelegate& delegate, int numLanes, SchedulerAlgorithm alg, 228| | const char* const* environment); 229| | } 230| |} 231| | 232| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileInfo.h: 1| |//===- FileInfo.h -----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file contains the FileInfo wrapper which is shared by the Ninja and 14| |// BuildSystem libraries. 15| |// 16| |// FIXME: I am ambivalent about this living in Basic, I want all non-functional 17| |// pieces to generally be pretty isolated (and ideally always mediated by a 18| |// delegate access). We may eventually want a specific FileSystem component for 19| |// dealing with efficient and abstracted access to the file system and 20| |// containing other pieces (like stat caching, or dealing with distribution or 21| |// virtualization). 22| |// 23| |//===----------------------------------------------------------------------===// 24| | 25| |#ifndef LLBUILD_BASIC_FILEINFO_H 26| |#define LLBUILD_BASIC_FILEINFO_H 27| | 28| |#include "BinaryCoding.h" 29| | 30| |#include 31| |#include 32| | 33| |namespace llbuild { 34| |namespace basic { 35| | 36| |/// File timestamp wrapper. 37| |struct FileTimestamp { 38| | uint64_t seconds; 39| | uint64_t nanoseconds; 40| | 41| | bool operator==(const FileTimestamp& rhs) const { 42| | return seconds == rhs.seconds && nanoseconds == rhs.nanoseconds; 43| | } 44| 0| bool operator!=(const FileTimestamp& rhs) const { 45| 0| return !(*this == rhs); 46| 0| } 47| 0| bool operator<(const FileTimestamp& rhs) const { 48| 0| return (seconds < rhs.seconds || 49| 0| (seconds == rhs.seconds && nanoseconds < rhs.nanoseconds)); 50| 0| } 51| 0| bool operator<=(const FileTimestamp& rhs) const { 52| 0| return (seconds < rhs.seconds || 53| 0| (seconds == rhs.seconds && nanoseconds <= rhs.nanoseconds)); 54| 0| } 55| 0| bool operator>(const FileTimestamp& rhs) const { 56| 0| return rhs < *this; 57| 0| } 58| 0| bool operator>=(const FileTimestamp& rhs) const { 59| 0| return rhs <= *this; 60| 0| } 61| |}; 62| | 63| |/// File information which is intended to be used as a proxy for when a file has 64| |/// changed. 65| |/// 66| |/// This structure is intentionally sized to have no packing holes. 67| |struct FileInfo { 68| | /// The device number. 69| | uint64_t device; 70| | /// The inode number. 71| | uint64_t inode; 72| | /// The mode flags of the file. 73| | uint64_t mode; 74| | /// The size of the file. 75| | uint64_t size; 76| | /// The modification time of the file. 77| | FileTimestamp modTime; 78| | 79| | /// Check if this is a FileInfo representing a missing file. 80| | bool isMissing() const { 81| | // We use an all-zero FileInfo as a sentinel, under the assumption this can 82| | // never exist in normal circumstances. 83| | return (device == 0 && inode == 0 && mode == 0 && size == 0 && 84| | modTime.seconds == 0 && modTime.nanoseconds == 0); 85| | } 86| | 87| | /// Check if the FileInfo corresponds to a directory. 88| | bool isDirectory() const; 89| | 90| | bool operator==(const FileInfo& rhs) const { 91| | return (device == rhs.device && 92| | inode == rhs.inode && 93| | size == rhs.size && 94| | modTime == rhs.modTime); 95| | } 96| | bool operator!=(const FileInfo& rhs) const { 97| | return !(*this == rhs); 98| | } 99| | 100| | /// Get the information to represent the state of the given node in the file 101| | /// system. 102| | /// 103| | /// \param asLink If yes, checks the information for the file path without 104| | /// looking through symbolic links. 105| | /// 106| | /// \returns The FileInfo for the given path, which will be missing if the 107| | /// path does not exist (or any error was encountered). 108| | static FileInfo getInfoForPath(const std::string& path, bool asLink = false); 109| |}; 110| | 111| |template<> 112| |struct BinaryCodingTraits { 113| 0| static inline void encode(const FileTimestamp& value, BinaryEncoder& coder) { 114| 0| coder.write(value.seconds); 115| 0| coder.write(value.nanoseconds); 116| 0| } 117| 0| static inline void decode(FileTimestamp& value, BinaryDecoder& coder) { 118| 0| coder.read(value.seconds); 119| 0| coder.read(value.nanoseconds); 120| 0| } 121| |}; 122| | 123| |template<> 124| |struct BinaryCodingTraits { 125| 0| static inline void encode(const FileInfo& value, BinaryEncoder& coder) { 126| 0| coder.write(value.device); 127| 0| coder.write(value.inode); 128| 0| coder.write(value.mode); 129| 0| coder.write(value.size); 130| 0| coder.write(value.modTime); 131| 0| } 132| 0| static inline void decode(FileInfo& value, BinaryDecoder& coder) { 133| 0| coder.read(value.device); 134| 0| coder.read(value.inode); 135| 0| coder.read(value.mode); 136| 0| coder.read(value.size); 137| 0| coder.read(value.modTime); 138| 0| } 139| |}; 140| | 141| |} 142| |} 143| | 144| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileSystem.h: 1| |//===- FileSystem.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_FILESYSTEM_H 14| |#define LLBUILD_BASIC_FILESYSTEM_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/FileInfo.h" 18| |#include "llbuild/Basic/LLVM.h" 19| | 20| |#include "llvm/Support/ErrorOr.h" 21| | 22| |#include 23| | 24| |namespace llvm { 25| | 26| |class MemoryBuffer; 27| | 28| |} 29| | 30| |namespace llbuild { 31| |namespace basic { 32| | 33| |// Abstract interface for interacting with a file system. This allows mocking of 34| |// operations for testing, and for clients to provide virtualized interfaces. 35| |class FileSystem { 36| | // DO NOT COPY 37| | FileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 38| | void operator=(const FileSystem&) LLBUILD_DELETED_FUNCTION; 39| | FileSystem &operator=(FileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 40| | 41| |public: 42| 0| FileSystem() {} 43| | virtual ~FileSystem(); 44| | 45| | /// Create the given directory if it does not exist. 46| | /// 47| | /// \returns True on success (the directory was created, or already exists). 48| | virtual bool 49| | createDirectory(const std::string& path) = 0; 50| | 51| | /// Create the given directory (recursively) if it does not exist. 52| | /// 53| | /// \returns True on success (the directory was created, or already exists). 54| | virtual bool 55| | createDirectories(const std::string& path); 56| | 57| | /// Get a memory buffer for a given file on the file system. 58| | /// 59| | /// \returns The file contents, on success, or null on error. 60| | virtual std::unique_ptr 61| | getFileContents(const std::string& path) = 0; 62| | 63| | /// Remove the file or directory at the given path. 64| | /// 65| | /// Directory removal is recursive. 66| | /// 67| | /// \returns True if the item was removed, false otherwise. 68| | virtual bool remove(const std::string& path) = 0; 69| | 70| | /// Get the information to represent the state of the given path in the file 71| | /// system. 72| | /// 73| | /// \returns The FileInfo for the given path, which will be missing if the 74| | /// path does not exist (or any error was encountered). 75| | virtual FileInfo getFileInfo(const std::string& path) = 0; 76| | 77| | /// Get the information to represent the state of the given path in the file 78| | /// system, without looking through symbolic links. 79| | /// 80| | /// \returns The FileInfo for the given path, which will be missing if the 81| | /// path does not exist (or any error was encountered). 82| | virtual FileInfo getLinkInfo(const std::string& path) = 0; 83| |}; 84| | 85| |/// Create a FileSystem instance suitable for accessing the local filesystem. 86| |std::unique_ptr createLocalFileSystem(); 87| | 88| | 89| |/// Device/inode agnostic filesystem wrapper 90| |class DeviceAgnosticFileSystem : public FileSystem { 91| |private: 92| | std::unique_ptr impl; 93| | 94| |public: 95| | explicit DeviceAgnosticFileSystem(std::unique_ptr fs) 96| | : impl(std::move(fs)) 97| 0| { 98| 0| } 99| | 100| | DeviceAgnosticFileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 101| | void operator=(const DeviceAgnosticFileSystem&) LLBUILD_DELETED_FUNCTION; 102| | DeviceAgnosticFileSystem &operator=(DeviceAgnosticFileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 103| | 104| | static std::unique_ptr from(std::unique_ptr fs); 105| | 106| | 107| | virtual bool 108| | createDirectory(const std::string& path) override { 109| | return impl->createDirectory(path); 110| | } 111| | 112| | virtual bool 113| | createDirectories(const std::string& path) override { 114| | return impl->createDirectories(path); 115| | } 116| | 117| | virtual std::unique_ptr 118| | getFileContents(const std::string& path) override; 119| | 120| | virtual bool remove(const std::string& path) override { 121| | return impl->remove(path); 122| | } 123| | 124| | virtual FileInfo getFileInfo(const std::string& path) override { 125| | auto info = impl->getFileInfo(path); 126| | 127| | // Device and inode numbers may (will) change when relocating files to 128| | // another device. Here we explicitly, unconditionally override them with 0, 129| | // enabling an entire build tree to be relocated or copied yet retain the 130| | // ability to perform incremental builds. 131| | info.device = 0; 132| | info.inode = 0; 133| | 134| | return info; 135| | } 136| | 137| | virtual FileInfo getLinkInfo(const std::string& path) override { 138| | auto info = impl->getLinkInfo(path); 139| | 140| | info.device = 0; 141| | info.inode = 0; 142| | 143| | return info; 144| | } 145| |}; 146| | 147| |} 148| |} 149| | 150| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Hashing.h: 1| |//===- Hashing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_HASHING_H 14| |#define LLBUILD_BASIC_HASHING_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/Hashing.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |namespace llbuild { 23| |namespace basic { 24| | 25| |uint64_t hashString(StringRef value); 26| | 27| |class CommandSignature { 28| |public: 29| 0| CommandSignature() = default; 30| 0| CommandSignature(StringRef string) { 31| 0| value = size_t(llvm::hash_value(string)); 32| 0| } 33| 0| explicit CommandSignature(uint64_t sig) : value(sig) {} 34| | CommandSignature(const CommandSignature& other) = default; 35| | CommandSignature(CommandSignature&& other) = default; 36| | CommandSignature& operator=(const CommandSignature& other) = default; 37| | CommandSignature& operator=(CommandSignature&& other) = default; 38| | 39| | bool isNull() const { return value == 0; } 40| | 41| | bool operator==(const CommandSignature& other) const { return value == other.value; } 42| | bool operator!=(const CommandSignature& other) const { return value != other.value; } 43| | 44| 0| CommandSignature& combine(StringRef string) { 45| 0| // FIXME: Use a more appropriate hashing infrastructure. 46| 0| value = llvm::hash_combine(value, string); 47| 0| return *this; 48| 0| } 49| | 50| | CommandSignature& combine(const std::string &string) { 51| | // FIXME: Use a more appropriate hashing infrastructure. 52| | value = llvm::hash_combine(value, string); 53| | return *this; 54| | } 55| | 56| | CommandSignature& combine(bool b) { 57| | // FIXME: Use a more appropriate hashing infrastructure. 58| | value = llvm::hash_combine(value, b); 59| | return *this; 60| | } 61| | 62| | template 63| | CommandSignature& combine(const std::vector& list) { 64| | for (const auto& v: list) { 65| | combine(v); 66| | } 67| | return *this; 68| | } 69| | 70| | uint64_t value = 0; 71| |}; 72| | 73| |template<> 74| |struct BinaryCodingTraits { 75| 0| static inline void encode(const CommandSignature& value, BinaryEncoder& coder) { 76| 0| coder.write(value.value); 77| 0| } 78| 0| static inline void decode(CommandSignature& value, BinaryDecoder& coder) { 79| 0| coder.read(value.value); 80| 0| } 81| |}; 82| | 83| |} 84| |} 85| | 86| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/POSIXEnvironment.h: 1| |//===- POSIXEnvironment.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 14| |#define LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/SmallString.h" 19| |#include "llvm/ADT/StringRef.h" 20| |#include "llvm/ADT/Hashing.h" 21| | 22| |#include 23| |#include 24| |#include 25| | 26| |namespace std { 27| | template<> struct hash { 28| | size_t operator()(const llvm::StringRef& value) const { 29| | return size_t(hash_value(value)); 30| | } 31| | }; 32| |} 33| | 34| |namespace llbuild { 35| |namespace basic { 36| | 37| |/// A helper class for constructing a POSIX-style environment. 38| |class POSIXEnvironment { 39| | /// The actual environment, this is only populated once frozen. 40| | std::vector env; 41| | 42| | /// The underlying string storage. 43| | // 44| | // FIXME: This is not efficient, we could store into a single allocation. 45| | std::vector envStorage; 46| | 47| | /// The list of known keys in the environment. 48| | std::unordered_set keys{}; 49| | 50| | /// Whether the environment pointer has been vended, and assignments can no 51| | /// longer be mutated. 52| | bool isFrozen = false; 53| | 54| |public: 55| 0| POSIXEnvironment() {} 56| | 57| | /// Add a key to the environment, if missing. 58| | /// 59| | /// If the key has already been defined, it will **NOT** be inserted. 60| | void setIfMissing(StringRef key, StringRef value) { 61| | assert(!isFrozen); 62| | if (keys.insert(key).second) { 63| | llvm::SmallString<256> assignment; 64| | assignment += key; 65| | assignment += '='; 66| | assignment += value; 67| | assignment += '\0'; 68| | envStorage.emplace_back(assignment.str()); 69| | } 70| | } 71| | 72| | /// Get the envirnonment pointer. 73| | /// 74| | /// This pointer is only valid for the lifetime of the environment itself. 75| | const char* const* getEnvp() { 76| | isFrozen = true; 77| | 78| | // Form the final environment. 79| | env.clear(); 80| | for (const auto& entry: envStorage) { 81| | env.emplace_back(entry.c_str()); 82| | } 83| | env.emplace_back(nullptr); 84| | return env.data(); 85| | } 86| |}; 87| | 88| |} 89| |} 90| | 91| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/StringList.h: 1| |//===- StringList.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_STRINGLIST_H 14| |#define LLBUILD_BASIC_STRINGLIST_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| | 18| |#include 19| | 20| |namespace llbuild { 21| |namespace basic { 22| | 23| |/// A list of strings particularly suited for use in binary coding 24| |class StringList { 25| |private: 26| | /// The values are packed as a sequence of C strings. 27| | char* contents = nullptr; 28| | 29| | /// The total length of the contents. 30| | uint64_t size = 0; 31| | 32| |public: 33| 0| StringList() {} 34| 0| StringList(basic::BinaryDecoder& decoder) { 35| 0| decoder.read(size); 36| 0| StringRef contents; 37| 0| decoder.readBytes(size, contents); 38| 0| this->contents = new char[size]; 39| 0| memcpy(this->contents, contents.data(), contents.size()); 40| 0| } 41| 0| ~StringList() { 42| 0| if (contents != nullptr) 43| 0| delete [] contents; 44| 0| } 45| | 46| | explicit StringList(StringRef value) { 47| | size = value.size() + 1; 48| | contents = new char[size]; 49| | assert(value.find('\0') == StringRef::npos); 50| | memcpy(contents, value.data(), value.size()); 51| | contents[size - 1] = '\0'; 52| | } 53| | 54| | template 55| | explicit StringList(const ArrayRef values) { 56| | // Construct the concatenated data. 57| | for (auto value: values) { 58| | size += value.size() + 1; 59| | } 60| | // Make sure to allocate at least 1 byte. 61| | char* p = nullptr; 62| | contents = p = new char[size + 1]; 63| | for (auto value: values) { 64| | assert(value.find('\0') == StringRef::npos); 65| | memcpy(p, value.data(), value.size()); 66| | p += value.size(); 67| | *p++ = '\0'; 68| | } 69| | *p = '\0'; 70| | } 71| | 72| | // StringList can only be moved, not copied 73| 0| StringList(StringList&& rhs) : contents(rhs.contents), size(rhs.size) { 74| 0| rhs.size = 0; 75| 0| rhs.contents = nullptr; 76| 0| } 77| | 78| | StringList& operator=(StringList&& rhs) { 79| | if (this != &rhs) { 80| | size = rhs.size; 81| | if (contents != nullptr) 82| | delete [] contents; 83| | contents = rhs.contents; 84| | rhs.contents = nullptr; 85| | } 86| | return *this; 87| | } 88| | 89| | std::vector getValues() const { 90| | std::vector result; 91| | for (uint64_t i = 0; i < size;) { 92| | auto value = StringRef(&contents[i]); 93| | assert(i + value.size() <= size); 94| | result.push_back(value); 95| | i += value.size() + 1; 96| | } 97| | return result; 98| | } 99| | 100| | bool isEmpty() const { return size == 0; } 101| | 102| 0| void encode(BinaryEncoder& coder) const { 103| 0| coder.write(size); 104| 0| coder.writeBytes(StringRef(contents, size)); 105| 0| } 106| |}; 107| | 108| |template<> 109| |struct BinaryCodingTraits { 110| 0| static inline void encode(const StringList& value, BinaryEncoder& coder) { 111| 0| value.encode(coder); 112| 0| } 113| | 114| 0| static inline void decode(StringList& value, BinaryDecoder& coder) { 115| 0| value = StringList(coder); 116| 0| } 117| |}; 118| | 119| |} 120| |} 121| | 122| |#endif /* StringList_h */ 123| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Subprocess.h: 1| |//===- Subprocess.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_SUBPROCESS_H 14| |#define LLBUILD_BASIC_SUBPROCESS_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/POSIXEnvironment.h" 20| | 21| |#include "llvm/ADT/Optional.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| | 29| |namespace llbuild { 30| | namespace basic { 31| | 32| | // MARK: Quality of Service 33| | 34| | enum class QualityOfService { 35| | /// A default quality of service (i.e. what the system would use without 36| | /// other advisement, generally this would be comparable to what would be 37| | /// done by `make`, `ninja`, etc.) 38| | Normal, 39| | 40| | /// User-initiated, high priority work. 41| | UserInitiated, 42| | 43| | /// Batch work performed on behalf of the user. 44| | Utility, 45| | 46| | /// Background work that is not directly visible to the user. 47| | Background 48| | }; 49| | 50| | QualityOfService getDefaultQualityOfService(); 51| | void setDefaultQualityOfService(QualityOfService level); 52| | 53| | void setCurrentThreadQualityOfService(QualityOfService level); 54| | 55| | 56| | // MARK: Process Info 57| | 58| | /// Handle used to communicate information about a launched process. 59| | struct ProcessHandle { 60| | /// Opaque ID. 61| | uint64_t id; 62| | }; 63| | 64| | struct ProcessInfo { 65| | /// Whether the process can be safely interrupted. 66| | bool canSafelyInterrupt; 67| | }; 68| | 69| | 70| | // MARK: Process Group 71| | 72| | class ProcessGroup { 73| | ProcessGroup(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 74| | void operator=(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 75| | ProcessGroup& operator=(ProcessGroup&&) LLBUILD_DELETED_FUNCTION; 76| | 77| | std::unordered_map processes; 78| | std::condition_variable processesCondition; 79| | bool closed = false; 80| | 81| | public: 82| 0| ProcessGroup() {} 83| | ~ProcessGroup(); 84| | 85| | std::mutex mutex; 86| | 87| 0| void close() { closed = true; } 88| | bool isClosed() const { return closed; } 89| | 90| | void add(std::lock_guard&& lock, llbuild_pid_t pid, 91| 0| ProcessInfo info) { 92| 0| processes.emplace(std::make_pair(pid, info)); 93| 0| } 94| | 95| 0| void remove(llbuild_pid_t pid) { 96| 0| { 97| 0| std::lock_guard lock(mutex); 98| 0| processes.erase(pid); 99| 0| } 100| 0| processesCondition.notify_all(); 101| 0| } 102| | 103| | void signalAll(int signal); 104| | }; 105| | 106| | 107| | // MARK: Process Execution 108| | 109| | /// Status of a process execution. 110| | enum class ProcessStatus { 111| | Succeeded = 0, 112| | Failed, 113| | Cancelled, 114| | Skipped, 115| | }; 116| | 117| | /// Result of a process execution. 118| | struct ProcessResult { 119| | 120| | /// The final status of the command 121| | ProcessStatus status; 122| | 123| | /// Process exit code 124| | int exitCode; 125| | 126| | /// Process identifier (can be -1 for failure reasons) 127| | llbuild_pid_t pid; 128| | 129| | /// User time (in us) 130| | uint64_t utime; 131| | 132| | /// System time (in us) 133| | uint64_t stime; 134| | 135| | /// Max RSS (in bytes) 136| | uint64_t maxrss; 137| | 138| | ProcessResult(ProcessStatus status, int exitCode = -1, 139| | llbuild_pid_t pid = (llbuild_pid_t)-1, uint64_t utime = 0, 140| | uint64_t stime = 0, uint64_t maxrss = 0) 141| | : status(status), exitCode(exitCode), pid(pid), utime(utime), 142| 0| stime(stime), maxrss(maxrss) {} 143| | 144| | static ProcessResult makeFailed(int exitCode = -1) { 145| | return ProcessResult(ProcessStatus::Failed, exitCode); 146| | } 147| | 148| | static ProcessResult makeCancelled(int exitCode = -1) { 149| | return ProcessResult(ProcessStatus::Cancelled, exitCode); 150| | } 151| | }; 152| | 153| | 154| | typedef std::function&&)> ProcessReleaseFn; 155| | typedef std::function ProcessCompletionFn; 156| | 157| | 158| | /// Opaque context passed on to the delegate 159| | struct ProcessContext; 160| | 161| | /// Delegate interface for process execution. 162| | /// 163| | /// All delegate interfaces are invoked synchronously by the subprocess 164| | /// methods (as called by the execution queue, for example) and should defer 165| | /// any long running operations to avoid blocking the queue unnecessarily. 166| | /// 167| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, 168| | /// which will arrive concurrently and without any specified thread. 169| | class ProcessDelegate { 170| | // DO NOT COPY 171| | ProcessDelegate(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 172| | void operator=(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 173| | ProcessDelegate& operator=(ProcessDelegate&& rhs) LLBUILD_DELETED_FUNCTION; 174| | 175| | public: 176| 0| ProcessDelegate() {} 177| | virtual ~ProcessDelegate(); 178| | 179| | /// Called when the external process has started executing. 180| | /// 181| | /// The subprocess code guarantees that any processStarted() call will be 182| | /// paired with exactly one \see processFinished() call. 183| | /// 184| | /// \param ctx - Opaque context passed on to the delegate 185| | /// \param handle - A unique handle used in subsequent delegate calls to 186| | /// identify the process. This handle should only be used to associate 187| | /// different status calls relating to the same process. It is only 188| | /// guaranteed to be unique from when it has been provided here to when it 189| | /// has been provided to the \see processFinished() call. 190| | virtual void processStarted(ProcessContext* ctx, ProcessHandle handle) = 0; 191| | 192| | /// Called to report an error in the management of a command process. 193| | /// 194| | /// \param ctx - Opaque context passed on to the delegate 195| | /// \param handle - The process handle. 196| | /// \param message - The error message. 197| | // 198| | // FIXME: Need to move to more structured error handling. 199| | virtual void processHadError(ProcessContext* ctx, ProcessHandle handle, 200| | const Twine& message) = 0; 201| | 202| | /// Called to report a command processes' (merged) standard output and error. 203| | /// 204| | /// \param ctx - Opaque context passed on to the delegate 205| | /// \param handle - The process handle. 206| | /// \param data - The process output. 207| | virtual void processHadOutput(ProcessContext* ctx, ProcessHandle handle, 208| | StringRef data) = 0; 209| | 210| | /// Called when a command's job has finished executing an external process. 211| | /// 212| | /// \param ctx - Opaque context passed on to the delegate 213| | /// \param handle - The handle used to identify the process. This handle 214| | /// will become invalid as soon as the client returns from this API call. 215| | /// \param result - Whether the process suceeded, failed or was cancelled. 216| | // 217| | // FIXME: Need to include additional information on the status here, e.g., the 218| | // signal status, and the process output (if buffering). 219| | virtual void processFinished(ProcessContext* ctx, ProcessHandle handle, 220| | const ProcessResult& result) = 0; 221| | }; 222| | 223| | 224| | struct ProcessAttributes { 225| | /// If true, whether it is safe to attempt to SIGINT the process to cancel 226| | /// it. If false, the process won't be interrupted during cancellation and 227| | /// will be given a chance to complete (if it fails to complete it will 228| | /// ultimately be sent a SIGKILL). 229| | bool canSafelyInterrupt; 230| | 231| | /// If set, the working directory to change into before spawning (support 232| | /// not guaranteed on all platforms). 233| | StringRef workingDir = {}; 234| | 235| | /// If true, exposes a control file descriptor that may be used to 236| | /// communicate with the build system. 237| | bool controlEnabled = true; 238| | }; 239| | 240| | /// Execute the given command line. 241| | /// 242| | /// This will launch and execute the given command line and wait for it to 243| | /// complete or release its execution lane. 244| | /// 245| | /// \param delegate The process delegate. 246| | /// 247| | /// \param ctx The context object passed to the delegate. 248| | /// 249| | /// \param pgrp The process group in which to track this process. 250| | /// 251| | /// \param handle The handle object passed to the delegate. 252| | /// 253| | /// \param commandLine The command line to execute. 254| | /// 255| | /// \param environment The environment to launch with. 256| | /// 257| | /// \param attributes Additional attributes for the process to be spawned. 258| | /// 259| | /// \param releaseFn Functional called when a process wishes to release its 260| | /// exclusive access to build system resources (namely an execution lane). 261| | /// 262| | /// \param completionFn An optional function that, if supplied, will be run 263| | /// following the completion of the process. This may be run asynchronously 264| | /// from another thread if the executed process asks the system to release 265| | /// its execution lane. Callers should put cleanup and notification work 266| | /// here. 267| | /// 268| | // 269| | // FIXME: This interface will need to get more complicated, and provide the 270| | // command result and facilities for dealing with the output. 271| | void spawnProcess(ProcessDelegate& delegate, 272| | ProcessContext* ctx, 273| | ProcessGroup& pgrp, 274| | ProcessHandle handle, 275| | ArrayRef commandLine, 276| | POSIXEnvironment environment, 277| | ProcessAttributes attributes, 278| | ProcessReleaseFn&& releaseFn, 279| | ProcessCompletionFn&& completionFn); 280| | 281| | /// @} 282| | 283| | } 284| |} 285| | 286| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Tracing.h: 1| |//===- Tracing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_TRACING_H 14| |#define LLBUILD_BASIC_TRACING_H 15| | 16| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 17| |#include "llvm/ADT/StringRef.h" 18| | 19| |// os_signpost is included in mac OS 10.14, if that header is not available, we don't trace at all. 20| |#if __has_include() 21| |#include 22| | 23| |/// Returns the singleton instance of os_log_t to use with os_log and os_signpost API. 24| |API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0)) 25| 0|static os_log_t getLog() { 26| 0| static os_log_t generalLog; 27| 0| static dispatch_once_t onceToken; 28| 0| dispatch_once(&onceToken, ^{ 29| 0| generalLog = os_log_create("org.swift.llbuild", "tracing"); 30| 0| }); 31| 0| return generalLog; 32| 0|} 33| | 34| |/// Returns a singleton id to use for all signpost calls during the lifetime of the program. 35| |API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) 36| 0|static os_signpost_id_t signpost_id() { 37| 0| static os_signpost_id_t signpost_id; 38| 0| static dispatch_once_t onceToken; 39| 0| dispatch_once(&onceToken, ^{ 40| 0| signpost_id = os_signpost_id_generate(getLog()); 41| 0| }); 42| 0| return signpost_id; 43| 0|} 44| | 45| |/// Begin an interval if tracing is enabled. 46| |#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { \ 47| |if (__builtin_available(macOS 10.14, *)) os_signpost_interval_begin(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 48| |} 49| | 50| |/// End an interval if tracing is enabled. 51| |#define LLBUILD_TRACE_INTERVAL_END(name, ...) { \ 52| |if (__builtin_available(macOS 10.14, *)) os_signpost_interval_end(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 53| |} 54| | 55| |/// Trace an event without duration at a point in time. 56| |#define LLBUILD_TRACE_POINT(name, ...) { \ 57| |if (__builtin_available(macOS 10.12, *)) os_log(getLog(), ##__VA_ARGS__); \ 58| |} 59| | 60| |#else 61| | 62| |// Define dummy definitions to do nothing 63| |#define LLBUILD_TRACE_POINT(name, ...) { (void)(name); } 64| |#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { (void)(name); } 65| |#define LLBUILD_TRACE_INTERVAL_END(name, ...) { (void)(name); } 66| |#define LLBUILD_TRACING_SET_ENABLED(on) { (void)on; } 67| | 68| |#endif // __has_include() 69| | 70| |namespace llbuild { 71| |extern bool TracingEnabled; 72| | 73| |struct TracingExecutionQueueJob { 74| | TracingExecutionQueueJob(int laneNumber, llvm::StringRef commandName) { 75| | if (!TracingEnabled) return; 76| | LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_job", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 77| | } 78| | 79| | ~TracingExecutionQueueJob() { 80| | if (!TracingEnabled) return; 81| | LLBUILD_TRACE_INTERVAL_END("execution_queue_job"); 82| | } 83| |}; 84| | 85| | 86| |inline void TracingExecutionQueueSubprocessStart(uint32_t laneNumber, 87| | llvm::StringRef commandName) { 88| | if (!TracingEnabled) return; 89| | LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 90| |} 91| | 92| |inline void TracingExecutionQueueSubprocessResult(uint32_t laneNumber, 93| | llbuild_pid_t pid, 94| | uint64_t utime, 95| | uint64_t stime, long maxrss) { 96| | if (!TracingEnabled) return; 97| | LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 98| |} 99| | 100| | 101| |struct TracingExecutionQueueSubprocess { 102| | TracingExecutionQueueSubprocess(uint32_t laneNumber, 103| | llvm::StringRef commandName) 104| 0| : laneNumber(laneNumber), pid(0), utime(0), stime(0), maxrss(0) { 105| 0| if (!TracingEnabled) return; 106| 0| LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 107| 0| } 108| | 109| | TracingExecutionQueueSubprocess(const TracingExecutionQueueSubprocess&) = delete; 110| | TracingExecutionQueueSubprocess(TracingExecutionQueueSubprocess&& t) 111| 0| : laneNumber(t.laneNumber), pid(t.pid), utime(t.utime), stime(t.stime), maxrss(t.maxrss) { 112| 0| t.active = false; 113| 0| } 114| | 115| 0| void update(llbuild_pid_t pid, uint64_t utime, uint64_t stime, long maxrss) { 116| 0| this->pid = pid; 117| 0| this->utime = utime; 118| 0| this->stime = stime; 119| 0| this->maxrss = maxrss; 120| 0| } 121| | 122| 0| ~TracingExecutionQueueSubprocess() { 123| 0| if (!TracingEnabled || !active) return; 124| 0| LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 125| 0| } 126| | 127| |private: 128| | bool active = true; 129| | uint32_t laneNumber; 130| | llbuild_pid_t pid; 131| | uint64_t utime; 132| | uint64_t stime; 133| | long maxrss; 134| |}; 135| | 136| |// Engine Task Callbacks 137| |enum class EngineTaskCallbackKind { 138| | Start = 0, 139| | ProvidePriorValue, 140| | ProvideValue, 141| | InputsAvailable, 142| |}; 143| | 144| |struct TracingEngineTaskCallback { 145| | TracingEngineTaskCallback(EngineTaskCallbackKind kind, uint64_t key) 146| | : key(key) { 147| | if (!TracingEnabled) return; 148| | LLBUILD_TRACE_INTERVAL_BEGIN("engine_task_callback", "key:%llu;kind:%d", key, uint32_t(kind)); 149| | } 150| | 151| | ~TracingEngineTaskCallback() { 152| | if (!TracingEnabled) return; 153| | LLBUILD_TRACE_INTERVAL_END("engine_task_callback", "key:%llu", key); 154| | key = 0; 155| | } 156| |private: 157| | uint64_t key; 158| |}; 159| | 160| |// Engine Queue Processing 161| |enum class EngineQueueItemKind { 162| | RuleToScan = 0, 163| | InputRequest, 164| | FinishedInputRequest, 165| | ReadyTask, 166| | FinishedTask, 167| | Waiting, 168| | FindingCycle, 169| | BreakingCycle, 170| |}; 171| | 172| |struct TracingEngineQueueItemEvent { 173| | TracingEngineQueueItemEvent(EngineQueueItemKind kind, char const *key) 174| | : key(key) { 175| | if (!TracingEnabled) return; 176| | LLBUILD_TRACE_INTERVAL_BEGIN("engine_queue_item_event", "key:%s;kind:%d", key, kind); 177| | } 178| | 179| | ~TracingEngineQueueItemEvent() { 180| | if (!TracingEnabled) return; 181| | LLBUILD_TRACE_INTERVAL_END("engine_queue_item_event", "key:%s", key) 182| | key = nullptr; 183| | } 184| |private: 185| | char const *key; 186| |}; 187| | 188| |inline void TracingExecutionQueueDepth(uint64_t depth) { 189| | if (!TracingEnabled) return; 190| | LLBUILD_TRACE_POINT("execution_queue_depth", "depth:%llu", depth); 191| |} 192| | 193| |} 194| | 195| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildDescription.h: 1| |//===- BuildDescription.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDDESCRIPTION_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDDESCRIPTION_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/ExecutionQueue.h" 18| |#include "llbuild/Basic/LLVM.h" 19| | 20| |#include "llvm/ADT/SmallString.h" 21| |#include "llvm/ADT/StringMap.h" 22| |#include "llvm/ADT/StringRef.h" 23| | 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| | 30| |namespace llbuild { 31| | 32| |namespace core { 33| | 34| |class Task; 35| | 36| |} 37| | 38| |namespace buildsystem { 39| | 40| |/// The type used to pass parsed properties to the delegate. 41| |typedef std::vector> property_list_type; 42| | 43| |class BuildSystem; 44| |class BuildSystemCommandInterface; 45| |class BuildKey; 46| |class BuildValue; 47| |class Command; 48| |class Node; 49| | 50| |/// Context for information that may be needed for a configuration action. 51| |// 52| |// FIXME: This is currently commingled with the build file loading, even though 53| |// it should ideally be possible to create a build description decoupled 54| |// entirely from the build file representation. 55| |struct ConfigureContext; 56| | 57| |/// Abstract tool definition used by the build file. 58| |class Tool { 59| | // DO NOT COPY 60| | Tool(const Tool&) LLBUILD_DELETED_FUNCTION; 61| | void operator=(const Tool&) LLBUILD_DELETED_FUNCTION; 62| | Tool &operator=(Tool&& rhs) LLBUILD_DELETED_FUNCTION; 63| | 64| | std::string name; 65| | 66| |public: 67| 0| explicit Tool(StringRef name) : name(name) {} 68| | virtual ~Tool(); 69| | 70| 0| StringRef getName() const { return name; } 71| | 72| | /// Called by the build file loader to configure a specified tool property. 73| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 74| | StringRef value) = 0; 75| | /// Called by the build file loader to configure a specified tool property. 76| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 77| | ArrayRef values) = 0; 78| | /// Called by the build file loader to configure a specified node property. 79| | virtual bool configureAttribute( 80| | const ConfigureContext&, StringRef name, 81| | ArrayRef> values) = 0; 82| | 83| | /// Called by the build file loader to create a command which uses this tool. 84| | /// 85| | /// \param name - The name of the command. 86| | virtual std::unique_ptr createCommand(StringRef name) = 0; 87| | 88| | /// Called by the build system to create a custom command with the given name. 89| | /// 90| | /// The tool should return null if it does not understand how to create the 91| | /// a custom command for the given key. 92| | /// 93| | /// \param key - The custom build key to create a command for. 94| | /// \returns The command to use, or null. 95| | virtual std::unique_ptr createCustomCommand(const BuildKey& key); 96| |}; 97| | 98| |/// Each Target declares a name that can be used to reference it, and a list of 99| |/// the top-level nodes which must be built to bring that target up to date. 100| |class Target { 101| | /// The name of the target. 102| | std::string name; 103| | 104| | /// The list of nodes that should be computed to build this target. 105| | std::vector nodes; 106| | 107| |public: 108| 0| explicit Target(std::string name) : name(name) { } 109| | 110| | StringRef getName() const { return name; } 111| | 112| | std::vector& getNodes() { return nodes; } 113| 0| const std::vector& getNodes() const { return nodes; } 114| |}; 115| | 116| |/// Abstract definition for a Node used by the build file. 117| |class Node { 118| | // DO NOT COPY 119| | Node(const Node&) LLBUILD_DELETED_FUNCTION; 120| | void operator=(const Node&) LLBUILD_DELETED_FUNCTION; 121| | Node &operator=(Node&& rhs) LLBUILD_DELETED_FUNCTION; 122| | 123| | /// The name used to identify the node. 124| | std::string name; 125| | 126| | /// The list of commands which can produce this node. 127| | // 128| | // FIXME: Optimize for single entry list. 129| | std::vector producers; 130| | 131| |public: 132| 0| explicit Node(StringRef name) : name(name) {} 133| | virtual ~Node(); 134| | 135| 0| StringRef getName() const { return name; } 136| | 137| | std::vector& getProducers() { return producers; } 138| | 139| 0| const std::vector& getProducers() const { return producers; } 140| | 141| | /// Called by the build file loader to configure a specified node property. 142| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 143| | StringRef value) = 0; 144| | /// Called by the build file loader to configure a specified node property. 145| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 146| | ArrayRef values) = 0; 147| | /// Called by the build file loader to configure a specified node property. 148| | virtual bool configureAttribute( 149| | const ConfigureContext&, StringRef name, 150| | ArrayRef> values) = 0; 151| |}; 152| | 153| |/// Abstract command definition used by the build file. 154| |class Command : public basic::JobDescriptor { 155| | // DO NOT COPY 156| | Command(const Command&) LLBUILD_DELETED_FUNCTION; 157| | void operator=(const Command&) LLBUILD_DELETED_FUNCTION; 158| | Command &operator=(Command&& rhs) LLBUILD_DELETED_FUNCTION; 159| | 160| | std::string name; 161| | 162| |public: 163| 0| explicit Command(StringRef name) : name(name) {} 164| | virtual ~Command(); 165| | 166| 0| StringRef getName() const { return name; } 167| | 168| | /// @name Command Information 169| | /// @{ 170| | // 171| | // FIXME: These probably don't belong here, clients generally can just manage 172| | // the information from their commands directly and our predefined interfaces 173| | // won't necessarily match what they want. However, we use them now to allow 174| | // extracting generic status information from the builtin commands. An 175| | // alternate solution would be to simply expose those command classes directly 176| | // and provide some kind of dynamic dispatching mechanism (llvm::cast<>, for 177| | // example) over commands. 178| | 179| | /// Controls whether the default status reporting shows status for the 180| | /// command. 181| 0| virtual bool shouldShowStatus() { return true; } 182| | 183| 0| virtual StringRef getOrdinalName() const override { return getName(); } 184| | 185| | /// Get a short description of the command, for use in status reporting. 186| | virtual void getShortDescription(SmallVectorImpl &result) const override = 0; 187| | 188| | /// Get a verbose description of the command, for use in status reporting. 189| | virtual void getVerboseDescription(SmallVectorImpl &result) const override = 0; 190| | 191| | /// @} 192| | 193| | /// @name File Loading 194| | /// @{ 195| | 196| | /// Called by the build file loader to set the description. 197| | virtual void configureDescription(const ConfigureContext&, 198| | StringRef description) = 0; 199| | 200| | /// Called by the build file loader to pass the list of input nodes. 201| | virtual void configureInputs(const ConfigureContext&, 202| | const std::vector& inputs) = 0; 203| | 204| | /// Called by the build file loader to pass the list of output nodes. 205| | virtual void configureOutputs(const ConfigureContext&, 206| | const std::vector& outputs) = 0; 207| | 208| | /// Called by the build file loader to configure a specified command property. 209| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 210| | StringRef value) = 0; 211| | /// Called by the build file loader to configure a specified command property. 212| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 213| | ArrayRef values) = 0; 214| | /// Called by the build file loader to configure a specified command property. 215| | virtual bool configureAttribute( 216| | const ConfigureContext&, StringRef name, 217| | ArrayRef> values) = 0; 218| | 219| | /// @} 220| | 221| | /// @name Node Interfaces 222| | /// 223| | /// @description These are the interfaces which allow the build system to 224| | /// coordinate between the abstract command and node objects. 225| | // 226| | // FIXME: This feels awkward, maybe this isn't the right way to manage 227| | // this. However, we want the system to be able to provide the plumbing 228| | // between pluggable comands and nodes, so it feels like it has to live 229| | // somewhere. 230| | // 231| | /// @{ 232| | 233| | /// Get the appropriate output for a particular node (known to be produced by 234| | /// this command) given the command's result. 235| | virtual BuildValue getResultForOutput(Node* node, 236| | const BuildValue& value) = 0; 237| | 238| | /// @} 239| | 240| | /// @name Command Execution 241| | /// 242| | /// @description These APIs directly mirror the APIs available in the 243| | /// lower-level BuildEngine, but with additional services provided by the 244| | /// BuildSystem. See the BuildEngine documentation for more information. 245| | /// 246| | /// @{ 247| | 248| | virtual bool isResultValid(BuildSystem& system, const BuildValue& value) = 0; 249| | 250| | virtual void start(BuildSystemCommandInterface&, core::Task*) = 0; 251| | 252| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 253| | const BuildValue& value) = 0; 254| | 255| | virtual void provideValue(BuildSystemCommandInterface&, core::Task*, 256| | uintptr_t inputID, const BuildValue& value) = 0; 257| | 258| | 259| | typedef std::function ResultFn; 260| | 261| | /// Execute the command, and return the value. 262| | /// 263| | /// This method will always be executed on the build execution queue. 264| | /// 265| | /// Note that resultFn may be executed asynchronously on a separate thread. 266| | virtual void execute(BuildSystemCommandInterface&, core::Task*, 267| | basic::QueueJobContext* context, ResultFn resultFn) = 0; 268| | 269| | /// @} 270| |}; 271| | 272| | 273| |/// A complete description of a build. 274| |class BuildDescription { 275| |public: 276| | // FIXME: This is an inefficent map, the string is duplicated. 277| | typedef llvm::StringMap> node_set; 278| | 279| | // FIXME: This is an inefficent map, the string is duplicated. 280| | typedef llvm::StringMap> target_set; 281| | 282| | // FIXME: This is an inefficent map, the string is duplicated. 283| | typedef llvm::StringMap> command_set; 284| | 285| | // FIXME: This is an inefficent map, the string is duplicated. 286| | typedef llvm::StringMap> tool_set; 287| | 288| |private: 289| | node_set nodes; 290| | 291| | target_set targets; 292| | 293| | command_set commands; 294| | 295| | tool_set tools; 296| | 297| | /// The default target. 298| | std::string defaultTarget; 299| | 300| |public: 301| | /// @name Accessors 302| | /// @{ 303| | 304| | /// Get the set of declared nodes for the file. 305| | node_set& getNodes() { return nodes; } 306| | 307| | /// Get the set of declared nodes for the file. 308| | const node_set& getNodes() const { return nodes; } 309| | 310| | /// Get the set of declared targets for the file. 311| | target_set& getTargets() { return targets; } 312| | 313| | /// Get the set of declared targets for the file. 314| | const target_set& getTargets() const { return targets; } 315| | 316| | /// Get the default target. 317| | std::string& getDefaultTarget() { return defaultTarget; } 318| | 319| | /// Get the default target. 320| | const std::string& getDefaultTarget() const { return defaultTarget; } 321| | 322| | /// Get the set of declared commands for the file. 323| | command_set& getCommands() { return commands; } 324| | 325| | /// Get the set of declared commands for the file. 326| | const command_set& getCommands() const { return commands; } 327| | 328| | /// Get the set of all tools used by the file. 329| | tool_set& getTools() { return tools; } 330| | 331| | /// Get the set of all tools used by the file. 332| | const tool_set& getTools() const { return tools; } 333| | 334| | /// @} 335| | /// @name Construction Helpers. 336| | /// @{ 337| | 338| 0| Node& addNode(std::unique_ptr value) { 339| 0| auto& result = *value.get(); 340| 0| getNodes()[value->getName()] = std::move(value); 341| 0| return result; 342| 0| } 343| | 344| 0| Target& addTarget(std::unique_ptr value) { 345| 0| auto& result = *value.get(); 346| 0| getTargets()[value->getName()] = std::move(value); 347| 0| return result; 348| 0| } 349| | 350| 0| Command& addCommand(std::unique_ptr value) { 351| 0| auto& result = *value.get(); 352| 0| getCommands()[value->getName()] = std::move(value); 353| 0| return result; 354| 0| } 355| | 356| 0| Tool& addTool(std::unique_ptr value) { 357| 0| auto& result = *value.get(); 358| 0| getTools()[value->getName()] = std::move(value); 359| 0| return result; 360| 0| } 361| | 362| | /// @} 363| |}; 364| | 365| |} 366| |} 367| | 368| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildKey.h: 1| |//===- BuildKey.h -----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDKEY_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDKEY_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| |#include "llbuild/Basic/Compiler.h" 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/StringList.h" 20| |#include "llbuild/Core/BuildEngine.h" 21| |#include "llbuild/BuildSystem/BuildDescription.h" 22| | 23| |#include "llvm/ADT/StringRef.h" 24| | 25| |namespace llbuild { 26| |namespace buildsystem { 27| | 28| |/// The BuildKey encodes the key space used by the BuildSystem when using the 29| |/// core BuildEngine. 30| |class BuildKey { 31| | using KeyType = core::KeyType; 32| | 33| |public: 34| | enum class Kind { 35| | /// A key used to identify a command. 36| | Command, 37| | 38| | /// A key used to identify a custom task. 39| | CustomTask, 40| | 41| | /// A key used to identify directory contents. 42| | DirectoryContents, 43| | 44| | /// A key used to identify filtered directory contents. 45| | FilteredDirectoryContents, 46| | 47| | /// A key used to identify the signature of a complete directory tree. 48| | DirectoryTreeSignature, 49| | 50| | /// A key used to identify the signature of a complete directory tree 51| | /// structure. 52| | DirectoryTreeStructureSignature, 53| | 54| | /// A key used to identify a node. 55| | Node, 56| | 57| | /// A key used to identify a file system stat info. 58| | Stat, 59| | 60| | /// A key used to identify a target. 61| | Target, 62| | 63| | /// An invalid key kind. 64| | Unknown, 65| | }; 66| | static StringRef stringForKind(Kind); 67| | 68| |private: 69| | /// The actual key data. 70| | KeyType key; 71| | 72| |private: 73| 0| BuildKey(const KeyType& key) : key(key) {} 74| 0| BuildKey(char kindCode, StringRef str) { 75| 0| key.reserve(1 + str.size()); 76| 0| key.push_back(kindCode); 77| 0| key.append(str.begin(), str.end()); 78| 0| } 79| | 80| | template 81| | BuildKey(char kindCode, StringRef name, const BinaryEncodable& data) { 82| | uint32_t nameSize = name.size(); 83| | 84| | // FIXME: Perhaps should use this encoder for the key itself? Right now 85| | // we're manually building the keys and causing some extra memcpy overhead 86| | // here. 87| | basic::BinaryEncoder encoder; 88| | encoder.write(data); 89| | uint32_t dataSize = encoder.contents().size(); 90| | 91| | key.resize(1 + sizeof(uint32_t) + nameSize + dataSize); 92| | uint32_t pos = 0; 93| | key[pos] = kindCode; pos += 1; 94| | memcpy(&key[pos], &nameSize, sizeof(uint32_t)); 95| | pos += sizeof(uint32_t); 96| | memcpy(&key[pos], name.data(), nameSize); 97| | pos += nameSize; 98| | memcpy(&key[pos], encoder.contents().data(), dataSize); 99| | pos += dataSize; 100| | assert(key.size() == pos); 101| | (void)pos; 102| | } 103| | 104| |public: 105| | /// @name Construction Functions 106| | /// @{ 107| | 108| | /// Create a key for computing a command result. 109| | static BuildKey makeCommand(StringRef name) { 110| | return BuildKey('C', name); 111| | } 112| | 113| | /// Create a key for computing a custom task (manged by a particular command). 114| | static BuildKey makeCustomTask(StringRef name, StringRef taskData) { 115| | return BuildKey('X', name, taskData); 116| | } 117| | 118| | /// Create a key for computing the contents of a directory. 119| | static BuildKey makeDirectoryContents(StringRef path) { 120| | return BuildKey('D', path); 121| | } 122| | 123| | /// Create a key for computing the filtered contents of a directory. 124| | static BuildKey makeFilteredDirectoryContents(StringRef path, 125| | const basic::StringList& filters) { 126| | return BuildKey('d', path, filters); 127| | } 128| | 129| | /// Create a key for computing the contents of a directory. 130| | static BuildKey makeDirectoryTreeSignature(StringRef path, 131| | const basic::StringList& filters) { 132| | return BuildKey('S', path, filters); 133| | } 134| | 135| | /// Create a key for computing the structure of a directory. 136| | static BuildKey makeDirectoryTreeStructureSignature(StringRef path) { 137| | return BuildKey('s', path); 138| | } 139| | 140| | /// Create a key for computing a node result. 141| 0| static BuildKey makeNode(StringRef path) { 142| 0| return BuildKey('N', path); 143| 0| } 144| | 145| | /// Create a key for computing a node result. 146| | static BuildKey makeNode(const Node* node) { 147| | return BuildKey('N', node->getName()); 148| | } 149| | 150| | /// Create a key for computing a file system stat info result. 151| | static BuildKey makeStat(StringRef path) { 152| | return BuildKey('I', path); 153| | } 154| | 155| | /// Createa a key for computing a target. 156| | static BuildKey makeTarget(StringRef name) { 157| | return BuildKey('T', name); 158| | } 159| | 160| | /// @} 161| | /// @name Accessors 162| | /// @{ 163| | 164| | const KeyType& getKeyData() const { return key; } 165| | 166| 0| Kind getKind() const { 167| 0| switch (key[0]) { 168| 0| case 'C': return Kind::Command; 169| 0| case 'D': return Kind::DirectoryContents; 170| 0| case 'd': return Kind::FilteredDirectoryContents; 171| 0| case 'N': return Kind::Node; 172| 0| case 'I': return Kind::Stat; 173| 0| case 'S': return Kind::DirectoryTreeSignature; 174| 0| case 's': return Kind::DirectoryTreeStructureSignature; 175| 0| case 'T': return Kind::Target; 176| 0| case 'X': return Kind::CustomTask; 177| 0| default: 178| 0| return Kind::Unknown; 179| 0| } 180| 0| } 181| | 182| 0| bool isCommand() const { return getKind() == Kind::Command; } 183| 0| bool isCustomTask() const { return getKind() == Kind::CustomTask; } 184| 0| bool isDirectoryContents() const { 185| 0| return getKind() == Kind::DirectoryContents; 186| 0| } 187| 0| bool isFilteredDirectoryContents() const { 188| 0| return getKind() == Kind::FilteredDirectoryContents; 189| 0| } 190| 0| bool isDirectoryTreeSignature() const { 191| 0| return getKind() == Kind::DirectoryTreeSignature; 192| 0| } 193| 0| bool isDirectoryTreeStructureSignature() const { 194| 0| return getKind() == Kind::DirectoryTreeStructureSignature; 195| 0| } 196| 0| bool isNode() const { return getKind() == Kind::Node; } 197| 0| bool isStat() const { return getKind() == Kind::Stat; } 198| 0| bool isTarget() const { return getKind() == Kind::Target; } 199| | 200| 0| StringRef getCommandName() const { 201| 0| assert(isCommand()); 202| 0| return StringRef(key.data()+1, key.size()-1); 203| 0| } 204| | 205| 0| StringRef getCustomTaskName() const { 206| 0| assert(isCustomTask()); 207| 0| uint32_t nameSize; 208| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 209| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 210| 0| } 211| | 212| | StringRef getCustomTaskData() const { 213| | assert(isCustomTask()); 214| | uint32_t nameSize; 215| | memcpy(&nameSize, &key[1], sizeof(uint32_t)); 216| | uint32_t dataSize = key.size() - 1 - sizeof(uint32_t) - nameSize; 217| | return StringRef(&key[1 + sizeof(uint32_t) + nameSize], dataSize); 218| | } 219| | 220| 0| StringRef getDirectoryPath() const { 221| 0| assert(isDirectoryContents() || isDirectoryTreeStructureSignature()); 222| 0| return StringRef(key.data()+1, key.size()-1); 223| 0| } 224| | 225| 0| StringRef getDirectoryTreeSignaturePath() const { 226| 0| assert(isDirectoryTreeSignature()); 227| 0| uint32_t nameSize; 228| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 229| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 230| 0| } 231| | 232| 0| StringRef getFilteredDirectoryPath() const { 233| 0| assert(isFilteredDirectoryContents()); 234| 0| uint32_t nameSize; 235| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 236| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 237| 0| } 238| | 239| | StringRef getContentExclusionPatterns() const { 240| | assert(isDirectoryTreeSignature() || isFilteredDirectoryContents()); 241| | uint32_t nameSize; 242| | memcpy(&nameSize, &key[1], sizeof(uint32_t)); 243| | uint32_t dataSize = key.size() - 1 - sizeof(uint32_t) - nameSize; 244| | return StringRef(&key[1 + sizeof(uint32_t) + nameSize], dataSize); 245| | } 246| | 247| 0| StringRef getNodeName() const { 248| 0| assert(isNode()); 249| 0| return StringRef(key.data()+1, key.size()-1); 250| 0| } 251| | 252| 0| StringRef getStatName() const { 253| 0| assert(isStat()); 254| 0| return StringRef(key.data()+1, key.size()-1); 255| 0| } 256| | 257| 0| StringRef getTargetName() const { 258| 0| assert(isTarget()); 259| 0| return StringRef(key.data()+1, key.size()-1); 260| 0| } 261| | 262| | /// @} 263| | 264| | /// @name Conversion to core ValueType. 265| | /// @{ 266| | 267| 0| static BuildKey fromData(const KeyType& key) { 268| 0| auto result = BuildKey(key); 269| 0| assert(result.getKind() != Kind::Unknown && "invalid key"); 270| 0| return result; 271| 0| } 272| | 273| | const core::KeyType toData() const { return getKeyData(); } 274| | 275| | /// @} 276| | 277| | /// @name Debug Support 278| | /// @{ 279| | 280| | void dump(raw_ostream& OS) const; 281| | 282| | /// @} 283| |}; 284| | 285| |} 286| |} 287| | 288| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildNode.h: 1| |//===- BuildNode.h ----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDNODE_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDNODE_H 15| | 16| |#include "BuildDescription.h" 17| | 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/StringList.h" 20| |#include "llbuild/BuildSystem/BuildFile.h" 21| | 22| |#include "llvm/ADT/StringRef.h" 23| | 24| |namespace llbuild { 25| |namespace basic { 26| | 27| |struct FileInfo; 28| |class FileSystem; 29| | 30| |} 31| | 32| |namespace buildsystem { 33| | 34| |// FIXME: Figure out how this is going to be organized. 35| |class BuildNode : public Node { 36| | /// Whether or not this node represents a full directory. 37| | // 38| | // FIXME: We need a type enumeration here. 39| | bool directory; 40| | 41| | /// Whether or not this node represents the full directory structure. 42| | // 43| | // FIXME: We need a type enumeration here. 44| | bool directoryStructure; 45| | 46| | /// Whether or not this node is "virtual" (i.e., not a filesystem path). 47| | bool virtualNode; 48| | 49| | /// Whether this node represents a "command timestamp". 50| | /// 51| | /// Such nodes should always also be virtual. 52| | bool commandTimestamp; 53| | 54| | /// Whether this node is mutated by the build. 55| | /// 56| | /// This flag cannot currently be honored to provide a strongly consistent 57| | /// build, but it is used to detect when the file system information on a node 58| | /// cannot be safely used to track *output* file state. 59| | bool mutated; 60| | 61| | /// Exclusion filters for directory listings 62| | /// 63| | /// Items matching these filter strings are not considered as part of the 64| | /// signature for directory and directory structure nodes. 65| | basic::StringList exclusionPatterns; 66| | 67| |public: 68| | explicit BuildNode(StringRef name, bool isDirectory, 69| | bool isDirectoryStructure, bool isVirtual, 70| | bool isCommandTimestamp, bool isMutated) 71| | : Node(name), directory(isDirectory), 72| | directoryStructure(isDirectoryStructure), virtualNode(isVirtual), 73| 0| commandTimestamp(isCommandTimestamp), mutated(isMutated) {} 74| | 75| | /// Check whether this is a "virtual" (non-filesystem related) node. 76| | bool isVirtual() const { return virtualNode; } 77| | 78| | /// Check whether this node is intended to represent a directory's contents 79| | /// recursively. 80| | bool isDirectory() const { return directory; } 81| | 82| | /// Check whether this node is intended to represent a directory's structure 83| | /// recursively. 84| | bool isDirectoryStructure() const { return directoryStructure; } 85| | 86| | bool isCommandTimestamp() const { return commandTimestamp; } 87| | 88| | bool isMutated() const { return mutated; } 89| | 90| | const basic::StringList& contentExclusionPatterns() const { 91| | return exclusionPatterns; 92| | } 93| | 94| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 95| | StringRef value) override; 96| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 97| | ArrayRef values) override; 98| | virtual bool configureAttribute( 99| | const ConfigureContext& ctx, StringRef name, 100| | ArrayRef> values) override; 101| | 102| | basic::FileInfo getFileInfo(basic::FileSystem&) const; 103| | basic::FileInfo getLinkInfo(basic::FileSystem&) const; 104| |}; 105| | 106| | 107| |class StatNode { 108| | std::string name; 109| | 110| |public: 111| 0| explicit StatNode(StringRef name) : name(name) {} 112| | 113| | const std::string& getName() { return name; } 114| | 115| | basic::FileInfo getFileInfo(basic::FileSystem&) const; 116| | basic::FileInfo getLinkInfo(basic::FileSystem&) const; 117| |}; 118| | 119| | 120| |} 121| |} 122| | 123| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildSystem.h: 1| |//===- BuildSystem.h --------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDSYSTEM_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDSYSTEM_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/Subprocess.h" 19| | 20| |#include "llvm/ADT/Optional.h" 21| |#include "llvm/ADT/StringRef.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |namespace llbuild { 29| |namespace basic { 30| | class ExecutionQueue; 31| | class FileSystem; 32| |} 33| | 34| |namespace buildsystem { 35| | 36| |class BuildDescription; 37| |class BuildKey; 38| |class BuildValue; 39| |class Command; 40| |class Node; 41| |class Tool; 42| | 43| |bool pathIsPrefixedByPath(std::string path, std::string prefixPath); 44| | 45| |class BuildSystemDelegate { 46| | // DO NOT COPY 47| | BuildSystemDelegate(const BuildSystemDelegate&) 48| | LLBUILD_DELETED_FUNCTION; 49| | void operator=(const BuildSystemDelegate&) 50| | LLBUILD_DELETED_FUNCTION; 51| | BuildSystemDelegate &operator=(BuildSystemDelegate&& rhs) 52| | LLBUILD_DELETED_FUNCTION; 53| | 54| |public: 55| | /// Command status change event kinds. 56| | /// 57| | /// This must be kept in sync with core::Rule::StatusKind. 58| | enum class CommandStatusKind { 59| | /// Indicates the command is being scanned. 60| | IsScanning = 0, 61| | 62| | /// Indicates the command is up-to-date, and doesn't need to run. 63| | IsUpToDate = 1, 64| | 65| | /// Indicates the command was run, and is now complete. 66| | IsComplete = 2 67| | }; 68| | 69| | /// Minimal token object representing the range where a diagnostic occurred. 70| | struct Token { 71| | const char* start; 72| | unsigned length; 73| | }; 74| | 75| |private: 76| | std::string name; 77| | uint32_t version; 78| | 79| |public: 80| | /// Configure the client properties. 81| | /// 82| | /// \param name An identifier for the client system. 83| | /// 84| | /// \param version A version number to identify the schema the client is 85| | /// using, and changes to the schema version number will result in 86| | /// invalidation of all cached build results. NOTE: Currently, this is limited 87| | /// to a 16-bit number as an implementation detail. 88| | BuildSystemDelegate(StringRef name, uint32_t version) 89| 0| : name(name), version(version) {} 90| | virtual ~BuildSystemDelegate(); 91| | 92| | /// Called by the build system to get the client name. 93| | StringRef getName() const { return name; } 94| | 95| | /// Called by the build system to get the current client version. 96| | uint32_t getVersion() const { return version; } 97| | 98| | /// Called by the build file loader to register the current file contents. 99| | // 100| | // FIXME: This is a total hack, and should be cleaned up. 101| | virtual void setFileContentsBeingParsed(StringRef buffer) = 0; 102| | 103| | /// Called by the build file loader to report an error. 104| | /// 105| | /// \param filename The file the error occurred in. 106| | /// 107| | /// \param at The token at which the error occurred. The token will be null if 108| | /// no location is associated. 109| | /// 110| | /// \param message The diagnostic message. 111| | virtual void error(StringRef filename, 112| | const Token& at, 113| | const Twine& message) = 0; 114| | 115| | /// Called by the build system to get a tool definition. 116| | /// 117| | /// This method is called to look for all tools, even ones which are built-in 118| | /// to the BuildSystem, in order to give the client an opportunity to override 119| | /// built-in tools. 120| | /// 121| | /// \param name The name of the tool to lookup. 122| | /// \returns The tool to use on success, or otherwise nil. 123| | virtual std::unique_ptr lookupTool(StringRef name) = 0; 124| | 125| | /// Called by the build system to get create the object used to dispatch work. 126| | virtual std::unique_ptr createExecutionQueue() = 0; 127| | 128| | /// Called by the build system to report a command failure. 129| | virtual void hadCommandFailure() = 0; 130| | 131| | /// Called by the build system to report that a declared command's state is 132| | /// changing. 133| | // 134| | // FIXME: This API is now gross, there shouldn't be one generic status changed 135| | // method and three individual other state change methods. 136| | virtual void commandStatusChanged(Command*, CommandStatusKind) = 0; 137| | 138| | /// Called by the build system to report that a declared command is preparing 139| | /// to run. 140| | /// 141| | /// This method is called before the command starts, when the system has 142| | /// identified that it will eventually need to run (after all of its inputs 143| | /// have been satisfied). 144| | /// 145| | /// The system guarantees that all such calls will be paired with a 146| | /// corresponding \see commandFinished() call. 147| | /// 148| | /// The system only makes this callback for commands explicitly declared in 149| | /// the build manifest (i.e., not for any work implicitly spawned by those 150| | /// commands). 151| | virtual void commandPreparing(Command*) = 0; 152| | 153| | /// Called by the build system to allow the delegate to skip a command without 154| | /// implicitly skipping its dependents. 155| | /// 156| | /// WARNING: Clients need to take special care when using this. Skipping 157| | /// commands without considering their dependencies or dependents can easily 158| | /// produce an inconsistent build. 159| | /// 160| | /// This method is called before the command starts, when the system has 161| | /// identified that it will eventually need to run (after all of its inputs 162| | /// have been satisfied). 163| | /// 164| | /// The system guarantees that all such calls will be paired with a 165| | /// corresponding \see commandFinished() call. 166| | virtual bool shouldCommandStart(Command*) = 0; 167| | 168| | /// Called by the build system to report that a declared command has started. 169| | /// 170| | /// The system guarantees that all such calls will be paired with a 171| | /// corresponding \see commandFinished() call. 172| | /// 173| | /// The system only makes this callback for commands explicitly declared in 174| | /// the build manifest (i.e., not for any work implicitly spawned by those 175| | /// commands). 176| | virtual void commandStarted(Command*) = 0; 177| | 178| | /// Called to report an error during the execution of a command. 179| | /// 180| | /// \param data - The error message. 181| | virtual void commandHadError(Command*, StringRef data) = 0; 182| | 183| | /// Called to report a note during the execution of a command. 184| | /// 185| | /// \param data - The note message. 186| | virtual void commandHadNote(Command*, StringRef data) = 0; 187| | 188| | /// Called to report a warning during the execution of a command. 189| | /// 190| | /// \param data - The warning message. 191| | virtual void commandHadWarning(Command*, StringRef data) = 0; 192| | 193| | /// Called by the build system to report a command has completed. 194| | /// 195| | /// \param status - The status of command (e.g. success, failure, etc). 196| | virtual void commandFinished(Command*, basic::ProcessStatus status) = 0; 197| | 198| | /// Called by the build system to report a command could not build due to 199| | /// missing inputs. 200| | virtual void commandCannotBuildOutputDueToMissingInputs(Command*, 201| | Node* output, SmallPtrSet inputs) = 0; 202| | 203| | /// Called by the build system to report a node could not be built 204| | /// because multiple commands are producing it. 205| | virtual void cannotBuildNodeDueToMultipleProducers(Node* output, 206| | std::vector) = 0; 207| |}; 208| | 209| |/// The BuildSystem class is used to perform builds using the native build 210| |/// system. 211| |class BuildSystem { 212| |private: 213| | void *impl; 214| | 215| | // Copying is disabled. 216| | BuildSystem(const BuildSystem&) LLBUILD_DELETED_FUNCTION; 217| | void operator=(const BuildSystem&) LLBUILD_DELETED_FUNCTION; 218| | 219| |public: 220| | /// Create a build system with the given delegate. 221| | BuildSystem(BuildSystemDelegate& delegate, std::unique_ptr fileSystem); 222| | ~BuildSystem(); 223| | 224| | /// Return the delegate the engine was configured with. 225| | BuildSystemDelegate& getDelegate(); 226| | 227| | /// Get the file system to use for access. 228| | basic::FileSystem& getFileSystem(); 229| | 230| | /// @name Client API 231| | /// @{ 232| | 233| | /// Load the build description from a file. 234| | /// 235| | /// \returns True on success. 236| | bool loadDescription(StringRef mainFilename); 237| | 238| | /// Load an explicit build description. from a file. 239| | void loadDescription(std::unique_ptr description); 240| | 241| | /// Attach (or create) the database at the given path. 242| | /// 243| | /// \returns True on success. 244| | bool attachDB(StringRef path, std::string* error_out); 245| | 246| | /// Enable low-level engine tracing into the given output file. 247| | /// 248| | /// \returns True on success. 249| | bool enableTracing(StringRef path, std::string* error_out); 250| | 251| | /// Build the named target. 252| | /// 253| | /// A build description *must* have been loaded before calling this method. 254| | /// 255| | /// \returns True on success, or false if the build was aborted (for example, 256| | /// if a cycle was discovered). 257| | bool build(StringRef target); 258| | 259| | /// Build a specific key directly. 260| | /// 261| | /// A build description *must* have been loaded before calling this method. 262| | /// 263| | /// \returns The result of computing the value, or nil if the build failed. 264| | llvm::Optional build(BuildKey target); 265| | 266| | /// Reset mutable build state before a new build operation. 267| | void resetForBuild(); 268| | 269| | /// Cancel the current build. 270| | void cancel(); 271| | 272| | /// @} 273| |}; 274| | 275| |} 276| |} 277| | 278| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildSystemFrontend.h: 1| |//===- BuildSystemFrontend.h ------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDSYSTEMFRONTEND_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDSYSTEMFRONTEND_H 15| | 16| |#include "llbuild/Basic/ExecutionQueue.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/BuildSystem/BuildSystem.h" 19| |#include "llbuild/BuildSystem/BuildNode.h" 20| |#include "llbuild/Core/BuildEngine.h" 21| | 22| |#include "llvm/ADT/ArrayRef.h" 23| |#include "llvm/ADT/StringRef.h" 24| |#include "llvm/ADT/Optional.h" 25| | 26| |#include 27| |#include 28| |#include 29| | 30| |namespace llvm { 31| | 32| |class SourceMgr; 33| | 34| |} 35| | 36| |namespace llbuild { 37| |namespace basic { 38| | 39| |class FileSystem; 40| | 41| |} 42| | 43| |namespace buildsystem { 44| | 45| |class BuildSystemFrontendDelegate; 46| |class BuildSystemInvocation; 47| |enum class CommandResult; 48| | 49| |/// This provides a standard "frontend" to the build system features, for use in 50| |/// building bespoke build systems that can still take advantage of desirable 51| |/// shared behavior. 52| |/// 53| |/// The frontend glues together various parts of the build system functionality 54| |/// to provide: 55| |/// o Support for common command line options. 56| |/// o Support for parallel, persistent builds. 57| |/// o Support for command line diagnostics and status reporting. 58| |/// 59| |/// NOTE: This class is *NOT* thread safe. 60| |class BuildSystemFrontend { 61| | BuildSystemFrontendDelegate& delegate; 62| | const BuildSystemInvocation& invocation; 63| | std::unique_ptr fileSystem; 64| | llvm::Optional buildSystem; 65| | 66| |private: 67| | 68| | bool setupBuild(); 69| | 70| |public: 71| | BuildSystemFrontend(BuildSystemFrontendDelegate& delegate, 72| | const BuildSystemInvocation& invocation, 73| | std::unique_ptr fileSystem); 74| | 75| | /// @name Accessors 76| | /// @{ 77| | 78| | BuildSystemFrontendDelegate& getDelegate() { return delegate; } 79| 0| const BuildSystemFrontendDelegate& getDelegate() const { return delegate; } 80| | 81| | const BuildSystemInvocation& getInvocation() { return invocation; } 82| | 83| | /// @} 84| | 85| | /// @name Client API 86| | /// @{ 87| | 88| | /// Initialize the build system. 89| | /// 90| | /// This will load the manifest and apply all of the command line options to 91| | /// construct an appropriate underlying `BuildSystem` for use by subsequent 92| | /// build calls. 93| | /// 94| | /// \returns True on success, or false if there were errors. If initialization 95| | /// fails, the frontend is in an indeterminant state and should not be reused. 96| | bool initialize(); 97| | 98| | /// Build the named target using the specified invocation parameters. 99| | /// 100| | /// \returns True on success, or false if there were errors. 101| | bool build(StringRef targetToBuild); 102| | 103| | /// Build a single node using the specified invocation parameters. 104| | /// 105| | /// \returns True on success, or false if there were errors. 106| | bool buildNode(StringRef nodeToBuild); 107| | 108| | /// @} 109| |}; 110| | 111| |/// The frontend-specific delegate, which provides some shared behaviors. 112| |class BuildSystemFrontendDelegate : public BuildSystemDelegate { 113| | friend class BuildSystemFrontend; 114| | 115| |public: 116| | /// Handle used to communicate information about a launched process. 117| | struct ProcessHandle { 118| | /// Opaque ID. 119| | uintptr_t id; 120| | }; 121| | 122| |private: 123| | void* impl; 124| | 125| | /// Default implementation, cannot be overriden by subclasses. 126| | virtual void setFileContentsBeingParsed(StringRef buffer) override; 127| | 128| |public: 129| | /// Create a frontend delegate. 130| | /// 131| | /// \param sourceMgr The source manager to use for reporting diagnostics. 132| | /// \param invocation The invocation parameters. 133| | /// \param name The name of build system client. 134| | /// \param version The version of the build system client. 135| | BuildSystemFrontendDelegate(llvm::SourceMgr& sourceMgr, 136| | const BuildSystemInvocation& invocation, 137| | StringRef name, 138| | uint32_t version); 139| | virtual ~BuildSystemFrontendDelegate(); 140| | 141| | /// Called by the build system to get a tool definition, must be provided by 142| | /// subclasses. 143| | virtual std::unique_ptr lookupTool(StringRef name) override = 0; 144| | 145| | /// Provides an appropriate execution queue based on the invocation options. 146| | virtual std::unique_ptr createExecutionQueue() override; 147| | 148| | /// Cancels the current build. 149| | virtual void cancel(); 150| | 151| | /// Reset mutable build state before a new build operation. 152| | void resetForBuild(); 153| | 154| | /// Provides a default handler. 155| | /// 156| | /// Subclass should call this method if overridden. 157| | virtual void hadCommandFailure() override; 158| | 159| | /// @name Frontend-specific APIs 160| | /// @{ 161| | 162| | /// Report a non-file specific error message. 163| | void error(const Twine& message); 164| | 165| | /// Provides a default error implementation which will delegate to the 166| | /// provided source manager. 167| | virtual void error(StringRef filename, const Token& at, 168| | const Twine& message) override; 169| | 170| | /// @} 171| | 172| | /// @name Status Reporting APIs 173| | /// 174| | /// The frontend provides default implementations of these methods which 175| | /// report the status to stdout. Clients should override if they wish to 176| | /// direct the status elsewhere. 177| | /// 178| | /// @{ 179| | 180| | /// Called by the build system to report that a declared command's state is 181| | /// changing. 182| | virtual void commandStatusChanged(Command*, CommandStatusKind) override; 183| | 184| | /// Called by the build system to report that a declared command is preparing 185| | /// to run. 186| | /// 187| | /// The system guarantees that all such calls will be paired with a 188| | /// corresponding \see commandFinished() call. 189| | virtual void commandPreparing(Command*) override; 190| | 191| | /// Called by the build system to allow the delegate to skip a command without 192| | /// implicitly skipping its dependents. 193| | /// 194| | /// WARNING: Clients need to take special care when using this. Skipping 195| | /// commands without considering their dependencies or dependents can easily 196| | /// produce an inconsistent build. 197| | /// 198| | /// This method is called before the command starts, when the system has 199| | /// identified that it will eventually need to run (after all of its inputs 200| | /// have been satisfied). 201| | /// 202| | /// The system guarantees that all such calls will be paired with a 203| | /// corresponding \see commandFinished() call. 204| | virtual bool shouldCommandStart(Command*) override; 205| | 206| | /// Called by the build system to report that a declared command has started. 207| | /// 208| | /// The system guarantees that all such calls will be paired with a 209| | /// corresponding \see commandFinished() call. 210| | virtual void commandStarted(Command*) override; 211| | 212| | /// Called to report an error during the execution of a command. 213| | /// 214| | /// \param data - The error message. 215| | virtual void commandHadError(Command*, StringRef data) override; 216| | 217| | /// Called to report a note during the execution of a command. 218| | /// 219| | /// \param data - The note message. 220| | virtual void commandHadNote(Command*, StringRef data) override; 221| | 222| | /// Called to report a warning during the execution of a command. 223| | /// 224| | /// \param data - The warning message. 225| | virtual void commandHadWarning(Command*, StringRef data) override; 226| | 227| | /// Called by the build system to report a command has completed. 228| | /// 229| | /// \param result - The result of command (e.g. success, failure, etc). 230| | virtual void commandFinished(Command*, basic::ProcessStatus result) override; 231| | 232| | /// Called by the build system to report a command could not build due to 233| | /// missing inputs. 234| | virtual void commandCannotBuildOutputDueToMissingInputs(Command*, 235| | Node* output, SmallPtrSet inputs) override; 236| | 237| | /// Called by the build system to report a node could not be built 238| | /// because multiple commands are producing it. 239| | virtual void cannotBuildNodeDueToMultipleProducers(Node* output, 240| | std::vector) override; 241| | 242| | /// Called when a command's job has been started. 243| | /// 244| | /// The system guarantees that any commandStart() call will be paired with 245| | /// exactly one \see commandFinished() call. 246| | // 247| | // FIXME: We may eventually want to allow the individual job to provide some 248| | // additional context here, for complex commands. 249| | // 250| | // FIXME: Design a way to communicate the "lane" here, for use in "super 251| | // console" like UIs. 252| | virtual void commandJobStarted(Command*); 253| | 254| | /// Called when a command's job has been finished. 255| | virtual void commandJobFinished(Command*); 256| | 257| | /// Called when a command's job has started executing an external process. 258| | /// 259| | /// The system guarantees that any commandProcessStarted() call will be paired 260| | /// with exactly one \see commandProcessFinished() call. 261| | /// 262| | /// \param handle - A unique handle used in subsequent delegate calls to 263| | /// identify the process. This handle should only be used to associate 264| | /// different status calls relating to the same process. It is only guaranteed 265| | /// to be unique from when it has been provided here to when it has been 266| | /// provided to the \see commandProcessFinished() call. 267| | virtual void commandProcessStarted(Command*, ProcessHandle handle); 268| | 269| | /// Called to report an error in the management of a command process. 270| | /// 271| | /// \param handle - The process handle. 272| | /// \param message - The error message. 273| | // 274| | // FIXME: Need to move to more structured error handling. 275| | virtual void commandProcessHadError(Command*, ProcessHandle handle, 276| | const Twine& message); 277| | 278| | /// Called to report a command processes' (merged) standard output and error. 279| | /// 280| | /// \param handle - The process handle. 281| | /// \param data - The process output. 282| | virtual void commandProcessHadOutput(Command*, ProcessHandle handle, 283| | StringRef data); 284| | 285| | /// Called when a command's job has finished executing an external process. 286| | /// 287| | /// \param handle - The handle used to identify the process. This handle will 288| | /// become invalid as soon as the client returns from this API call. 289| | /// 290| | /// \param result - Whether the process suceeded, failed or was cancelled. 291| | // 292| | // FIXME: Need to include additional information on the status here, e.g., the 293| | // signal status, and the process output (if buffering). 294| | virtual void commandProcessFinished(Command*, ProcessHandle handle, 295| | const basic::ProcessResult& result); 296| | 297| | /// Called when a cycle is detected by the build engine and it cannot make 298| | /// forward progress. 299| | /// 300| | /// \param items The ordered list of items comprising the cycle, starting from 301| | /// the node which was requested to build and ending with the first node in 302| | /// the cycle (i.e., the node participating in the cycle will appear twice). 303| | virtual void cycleDetected(const std::vector& items) = 0; 304| | 305| | /// Called when a cycle is detected by the build engine to check if it should 306| | /// attempt to resolve the cycle and continue 307| | /// 308| | /// \param items The ordered list of items comprising the cycle, starting from 309| | /// the node which was requested to build and ending with the first node in 310| | /// the cycle (i.e., the node participating in the cycle will appear twice). 311| | /// \param candidateRule The rule the engine will use to attempt to break the 312| | /// cycle. 313| | /// \param action The action the engine will take on the candidateRule. 314| | /// \returns True if the engine should attempt to resolve the cycle, false 315| | /// otherwise. Resolution is attempted by either forcing items to be built, or 316| | /// supplying a previously built result to a node in the cycle. The latter 317| | /// action may yield unexpected results and thus this should be opted into 318| | /// with care. 319| | virtual bool shouldResolveCycle(const std::vector& items, 320| | core::Rule* candidateRule, 321| | core::Rule::CycleAction action); 322| | /// @} 323| | 324| | /// @name Accessors 325| | /// @{ 326| | 327| | BuildSystemFrontend& getFrontend(); 328| | 329| | llvm::SourceMgr& getSourceMgr(); 330| | 331| | /// Get the number of reported errors. 332| | unsigned getNumErrors(); 333| | 334| | /// Get the number of failed commands. 335| | unsigned getNumFailedCommands(); 336| | 337| | /// @} 338| |}; 339| | 340| | 341| |/// This class wraps the common options which are used by the frontend. 342| |class BuildSystemInvocation { 343| |public: 344| | /// Whether the command usage should be printed. 345| | bool showUsage = false; 346| | 347| | /// Whether the command version should be printed. 348| | bool showVersion = false; 349| | 350| | /// Whether to show verbose output. 351| | bool showVerboseStatus = false; 352| | 353| | /// Whether to use a serial build. 354| | bool useSerialBuild = false; 355| | 356| | /// The path of the database file to use, if any. 357| | std::string dbPath = "build.db"; 358| | 359| | /// The path of a directory to change into before anything else, if any. 360| | std::string chdirPath = ""; 361| | 362| | /// The path of the build file to use. 363| | std::string buildFilePath = "build.llbuild"; 364| | 365| | /// The path of the build trace output file to use, if any. 366| | std::string traceFilePath = ""; 367| | 368| | basic::SchedulerAlgorithm schedulerAlgorithm = 369| | basic::SchedulerAlgorithm::NamePriority; 370| | 371| | uint32_t schedulerLanes = 0; 372| | 373| | /// The base environment to use when executing subprocesses. 374| | /// 375| | /// The format is expected to match that of `::main()`, i.e. a null-terminated 376| | /// array of pointers to null terminated C strings. 377| | /// 378| | /// If empty, the environment of the calling process will be used. 379| | const char* const* environment = nullptr; 380| | 381| | /// The positional arguments. 382| | std::vector positionalArgs; 383| | 384| | /// Whether there were any parsing errors. 385| | bool hadErrors = false; 386| | 387| |public: 388| | /// Get the appropriate "usage" text to use for the built in arguments. 389| | static void getUsage(int optionWidth, raw_ostream& os); 390| | 391| | /// Parse the invocation parameters from the given arguments. 392| | /// 393| | /// \param sourceMgr The source manager to use for diagnostics. 394| | void parse(ArrayRef args, llvm::SourceMgr& sourceMgr); 395| | 396| | /// Provides a default string representation for a cycle detected by the build engine. 397| | static std::string formatDetectedCycle(const std::vector& cycle); 398| |}; 399| | 400| |} 401| |} 402| | 403| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildValue.h: 1| |//===- BuildValue.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDVALUE_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDVALUE_H 15| | 16| |#include "llbuild/Core/BuildEngine.h" 17| |#include "llbuild/Basic/BinaryCoding.h" 18| |#include "llbuild/Basic/Compiler.h" 19| |#include "llbuild/Basic/FileInfo.h" 20| |#include "llbuild/Basic/Hashing.h" 21| |#include "llbuild/Basic/LLVM.h" 22| |#include "llbuild/Basic/StringList.h" 23| | 24| |#include "llvm/ADT/ArrayRef.h" 25| |#include "llvm/ADT/SmallVector.h" 26| |#include "llvm/ADT/StringRef.h" 27| |#include "llvm/Support/raw_ostream.h" 28| | 29| |#include 30| | 31| |namespace llvm { 32| |class raw_ostream; 33| |} 34| | 35| |namespace llbuild { 36| |namespace buildsystem { 37| | 38| |/// The BuildValue encodes the value space used by the BuildSystem when using 39| |/// the core BuildEngine. 40| |class BuildValue { 41| | using FileInfo = basic::FileInfo; 42| | 43| | enum class Kind : uint32_t { 44| | /// An invalid value, for sentinel purposes. 45| | Invalid = 0, 46| | 47| | /// A value produced by a virtual input. 48| | VirtualInput, 49| | 50| | /// A value produced by an existing input file. 51| | ExistingInput, 52| | 53| | /// A value produced by a missing input file. 54| | MissingInput, 55| | 56| | /// The contents of a directory. 57| | DirectoryContents, 58| | 59| | /// The signature of a directories contents. 60| | DirectoryTreeSignature, 61| | 62| | /// The signature of a directories structure. 63| | DirectoryTreeStructureSignature, 64| | 65| | /// A value produced by stale file removal. 66| | StaleFileRemoval, 67| | 68| | /// A value produced by a command which succeeded, but whose output was 69| | /// missing. 70| | MissingOutput, 71| | 72| | /// A value for a produced output whose command failed or was cancelled. 73| | FailedInput, 74| | 75| | /// A value produced by a successful command. 76| | SuccessfulCommand, 77| | 78| | /// A value produced by a failing command. 79| | FailedCommand, 80| | 81| | /// A value produced by a command which was skipped because one of its 82| | /// dependencies failed. 83| | PropagatedFailureCommand, 84| | 85| | /// A value produced by a command which was cancelled. 86| | CancelledCommand, 87| | 88| | /// A value produced by a command which was skipped. 89| | SkippedCommand, 90| | 91| | /// Sentinel value representing the result of "building" a top-level target. 92| | Target, 93| | 94| | /// The filtered contents of a directory. 95| | FilteredDirectoryContents, 96| | 97| | }; 98| | static StringRef stringForKind(Kind); 99| | 100| | friend struct basic::BinaryCodingTraits; 101| | 102| | /// The kind of value. 103| | Kind kind = Kind::Invalid; 104| | 105| | /// The number of attached output infos. 106| | uint32_t numOutputInfos = 0; 107| | 108| | /// The command hash, for successful commands. 109| | basic::CommandSignature commandSignature; 110| | 111| | union { 112| | /// The file info for the rule output, for existing inputs, successful 113| | /// commands with a single output, and directory contents. 114| | FileInfo asOutputInfo; 115| | 116| | /// The file info for successful commands with multiple outputs. 117| | FileInfo* asOutputInfos; 118| | } valueData = { {} }; 119| | 120| | /// String list storage. 121| | // 122| | // FIXME: We are currently paying the cost for carrying this around on every 123| | // value, which is very wasteful. We need to redesign this type to be 124| | // customized to each exact value. 125| | basic::StringList stringValues; 126| | 127| | bool kindHasCommandSignature() const { 128| | return isSuccessfulCommand() || 129| | isDirectoryTreeSignature() || isDirectoryTreeStructureSignature(); 130| | } 131| | 132| | bool kindHasStringList() const { 133| | return isDirectoryContents() || isFilteredDirectoryContents() || isStaleFileRemoval(); 134| | } 135| | 136| | bool kindHasOutputInfo() const { 137| | return isExistingInput() || isSuccessfulCommand() || isDirectoryContents(); 138| | } 139| | 140| |private: 141| | // Copying is disabled. 142| | BuildValue(const BuildValue&) LLBUILD_DELETED_FUNCTION; 143| | void operator=(const BuildValue&) LLBUILD_DELETED_FUNCTION; 144| | 145| 0| BuildValue() {} 146| | BuildValue(basic::BinaryDecoder& decoder); 147| | BuildValue(Kind kind, basic::CommandSignature commandSignature = basic::CommandSignature()) 148| 0| : kind(kind), commandSignature(commandSignature) { } 149| | BuildValue(Kind kind, ArrayRef outputInfos, 150| | basic::CommandSignature commandSignature = basic::CommandSignature()) 151| | : kind(kind), numOutputInfos(outputInfos.size()), 152| | commandSignature(commandSignature) 153| | { 154| | assert(numOutputInfos >= 1); 155| | if (numOutputInfos == 1) { 156| | valueData.asOutputInfo = outputInfos[0]; 157| | } else { 158| | valueData.asOutputInfos = new FileInfo[numOutputInfos]; 159| | for (uint32_t i = 0; i != numOutputInfos; ++i) { 160| | valueData.asOutputInfos[i] = outputInfos[i]; 161| | } 162| | } 163| | } 164| | 165| | /// Create a build value containing directory contents. 166| | BuildValue(Kind kind, FileInfo directoryInfo, ArrayRef values) 167| | : BuildValue(kind, directoryInfo) 168| 0| { 169| 0| assert(kindHasStringList()); 170| 0| 171| 0| stringValues = basic::StringList(values); 172| 0| } 173| | 174| | BuildValue(Kind kind, ArrayRef values) 175| | : kind(kind), stringValues(values) { 176| | assert(kindHasStringList()); 177| | } 178| | 179| | std::vector getStringListValues() const { 180| | assert(kindHasStringList()); 181| | return stringValues.getValues(); 182| | } 183| | 184| | FileInfo& getNthOutputInfo(unsigned n) { 185| | assert(kindHasOutputInfo() && "invalid call for value kind"); 186| | assert(n < getNumOutputs()); 187| | if (hasMultipleOutputs()) { 188| | return valueData.asOutputInfos[n]; 189| | } else { 190| | assert(n == 0); 191| | return valueData.asOutputInfo; 192| | } 193| | } 194| | 195| |public: 196| | // BuildValues can only be moved, not copied. 197| | BuildValue(BuildValue&& rhs) : numOutputInfos(rhs.numOutputInfos) { 198| | kind = rhs.kind; 199| | numOutputInfos = rhs.numOutputInfos; 200| | commandSignature = rhs.commandSignature; 201| | if (rhs.hasMultipleOutputs()) { 202| | valueData.asOutputInfos = rhs.valueData.asOutputInfos; 203| | rhs.valueData.asOutputInfos = nullptr; 204| | } else { 205| | valueData.asOutputInfo = rhs.valueData.asOutputInfo; 206| | } 207| | if (rhs.kindHasStringList()) { 208| | stringValues = std::move(rhs.stringValues); 209| | } 210| | } 211| | BuildValue& operator=(BuildValue&& rhs) { 212| | if (this != &rhs) { 213| | // Release our resources. 214| | if (hasMultipleOutputs()) 215| | delete[] valueData.asOutputInfos; 216| | 217| | // Move the data. 218| | kind = rhs.kind; 219| | numOutputInfos = rhs.numOutputInfos; 220| | commandSignature = rhs.commandSignature; 221| | if (rhs.hasMultipleOutputs()) { 222| | valueData.asOutputInfos = rhs.valueData.asOutputInfos; 223| | rhs.valueData.asOutputInfos = nullptr; 224| | } else { 225| | valueData.asOutputInfo = rhs.valueData.asOutputInfo; 226| | } 227| | if (rhs.kindHasStringList()) { 228| | stringValues = std::move(rhs.stringValues); 229| | } 230| | } 231| | return *this; 232| | } 233| 0| ~BuildValue() { 234| 0| if (hasMultipleOutputs()) { 235| 0| delete[] valueData.asOutputInfos; 236| 0| } 237| 0| } 238| | 239| | /// @name Construction Functions 240| | /// @{ 241| | 242| | static BuildValue makeInvalid() { 243| | return BuildValue(Kind::Invalid); 244| | } 245| | static BuildValue makeVirtualInput() { 246| | return BuildValue(Kind::VirtualInput); 247| | } 248| | static BuildValue makeExistingInput(FileInfo outputInfo) { 249| | assert(!outputInfo.isMissing()); 250| | return BuildValue(Kind::ExistingInput, outputInfo); 251| | } 252| | static BuildValue makeMissingInput() { 253| | return BuildValue(Kind::MissingInput); 254| | } 255| | static BuildValue makeDirectoryContents(FileInfo directoryInfo, 256| | ArrayRef values) { 257| | return BuildValue(Kind::DirectoryContents, directoryInfo, values); 258| | } 259| | static BuildValue makeDirectoryTreeSignature(basic::CommandSignature signature) { 260| | return BuildValue(Kind::DirectoryTreeSignature, signature); 261| | } 262| | static BuildValue makeDirectoryTreeStructureSignature(basic::CommandSignature signature) { 263| | return BuildValue(Kind::DirectoryTreeStructureSignature, signature); 264| | } 265| | static BuildValue makeMissingOutput() { 266| | return BuildValue(Kind::MissingOutput); 267| | } 268| | static BuildValue makeFailedInput() { 269| | return BuildValue(Kind::FailedInput); 270| | } 271| | static BuildValue makeSuccessfulCommand( 272| | ArrayRef outputInfos, basic::CommandSignature commandSignature) { 273| | return BuildValue(Kind::SuccessfulCommand, outputInfos, commandSignature); 274| | } 275| | static BuildValue makeFailedCommand() { 276| | return BuildValue(Kind::FailedCommand); 277| | } 278| | static BuildValue makePropagatedFailureCommand() { 279| | return BuildValue(Kind::PropagatedFailureCommand); 280| | } 281| | static BuildValue makeCancelledCommand() { 282| | return BuildValue(Kind::CancelledCommand); 283| | } 284| | static BuildValue makeSkippedCommand() { 285| | return BuildValue(Kind::SkippedCommand); 286| | } 287| | static BuildValue makeTarget() { 288| | return BuildValue(Kind::Target); 289| | } 290| | static BuildValue makeStaleFileRemoval(ArrayRef values) { 291| | return BuildValue(Kind::StaleFileRemoval, values); 292| | } 293| | static BuildValue makeFilteredDirectoryContents(ArrayRef values) { 294| | return BuildValue(Kind::FilteredDirectoryContents, values); 295| | } 296| | 297| | /// @} 298| | 299| | /// @name Accessors 300| | /// @{ 301| | 302| | bool isInvalid() const { return kind == Kind::Invalid; } 303| | bool isVirtualInput() const { return kind == Kind::VirtualInput; } 304| | bool isExistingInput() const { return kind == Kind::ExistingInput; } 305| | bool isMissingInput() const { return kind == Kind::MissingInput; } 306| | 307| | bool isDirectoryContents() const { return kind == Kind::DirectoryContents; } 308| | bool isDirectoryTreeSignature() const { 309| | return kind == Kind::DirectoryTreeSignature; 310| | } 311| | bool isDirectoryTreeStructureSignature() const { 312| | return kind == Kind::DirectoryTreeStructureSignature; 313| | } 314| | bool isStaleFileRemoval() const { return kind == Kind::StaleFileRemoval; } 315| | 316| | bool isMissingOutput() const { return kind == Kind::MissingOutput; } 317| | bool isFailedInput() const { return kind == Kind::FailedInput; } 318| | bool isSuccessfulCommand() const {return kind == Kind::SuccessfulCommand; } 319| | bool isFailedCommand() const { return kind == Kind::FailedCommand; } 320| | bool isPropagatedFailureCommand() const { 321| | return kind == Kind::PropagatedFailureCommand; 322| | } 323| | bool isCancelledCommand() const { return kind == Kind::CancelledCommand; } 324| | bool isSkippedCommand() const { return kind == Kind::SkippedCommand; } 325| 0| bool isTarget() const { return kind == Kind::Target; } 326| | bool isFilteredDirectoryContents() const { 327| | return kind == Kind::FilteredDirectoryContents; 328| | } 329| | 330| | std::vector getDirectoryContents() const { 331| | assert((isDirectoryContents() || isFilteredDirectoryContents()) && "invalid call for value kind"); 332| | return getStringListValues(); 333| | } 334| | 335| | std::vector getStaleFileList() const { 336| | assert(isStaleFileRemoval() && "invalid call for value kind"); 337| | return getStringListValues(); 338| | } 339| | 340| 0| basic::CommandSignature getDirectoryTreeSignature() const { 341| 0| assert(isDirectoryTreeSignature() && "invalid call for value kind"); 342| 0| return commandSignature; 343| 0| } 344| | 345| 0| basic::CommandSignature getDirectoryTreeStructureSignature() const { 346| 0| assert(isDirectoryTreeStructureSignature() && 347| 0| "invalid call for value kind"); 348| 0| return commandSignature; 349| 0| } 350| | 351| 0| bool hasMultipleOutputs() const { 352| 0| return numOutputInfos > 1; 353| 0| } 354| | 355| | unsigned getNumOutputs() const { 356| | assert(kindHasOutputInfo() && "invalid call for value kind"); 357| | return numOutputInfos; 358| | } 359| | 360| | const FileInfo& getOutputInfo() const { 361| | assert(kindHasOutputInfo() && "invalid call for value kind"); 362| | assert(!hasMultipleOutputs() && 363| | "invalid call on result with multiple outputs"); 364| | return valueData.asOutputInfo; 365| | } 366| | 367| | const FileInfo& getNthOutputInfo(unsigned n) const { 368| | assert(kindHasOutputInfo() && "invalid call for value kind"); 369| | assert(n < getNumOutputs()); 370| | if (hasMultipleOutputs()) { 371| | return valueData.asOutputInfos[n]; 372| | } else { 373| | assert(n == 0); 374| | return valueData.asOutputInfo; 375| | } 376| | } 377| | 378| | basic::CommandSignature getCommandSignature() const { 379| | assert(isSuccessfulCommand() && "invalid call for value kind"); 380| | return commandSignature; 381| | } 382| | 383| | /// @} 384| | 385| | /// @name Conversion to core ValueType. 386| | /// @{ 387| | 388| | static BuildValue fromData(const core::ValueType& value) { 389| | basic::BinaryDecoder decoder(StringRef((char*)value.data(), value.size())); 390| | return BuildValue(decoder); 391| | } 392| | core::ValueType toData() const; 393| | 394| | /// @} 395| | 396| | /// @name Debug Support 397| | /// @{ 398| | 399| | void dump(raw_ostream& OS) const; 400| | 401| | /// @} 402| |}; 403| | 404| |} 405| | 406| |template<> 407| |struct basic::BinaryCodingTraits { 408| | typedef buildsystem::BuildValue::Kind Kind; 409| | 410| | static inline void encode(const Kind& value, BinaryEncoder& coder) { 411| | uint8_t tmp = uint8_t(value); 412| | assert(value == Kind(tmp)); 413| | coder.write(tmp); 414| | } 415| 0| static inline void decode(Kind& value, BinaryDecoder& coder) { 416| 0| uint8_t tmp; 417| 0| coder.read(tmp); 418| 0| value = Kind(tmp); 419| 0| } 420| |}; 421| | 422| |inline buildsystem::BuildValue::BuildValue(basic::BinaryDecoder& coder) { 423| | // Handle empty decode requests. 424| | if (coder.isEmpty()) { 425| | kind = BuildValue::Kind::Invalid; 426| | return; 427| | } 428| | 429| | coder.read(kind); 430| | if (kindHasCommandSignature()) 431| | coder.read(commandSignature); 432| | if (kindHasOutputInfo()) { 433| | coder.read(numOutputInfos); 434| | if (numOutputInfos > 1) { 435| | valueData.asOutputInfos = new FileInfo[numOutputInfos]; 436| | } 437| | for (uint32_t i = 0; i != numOutputInfos; ++i) { 438| | coder.read(getNthOutputInfo(i)); 439| | } 440| | } 441| | if (kindHasStringList()) { 442| | stringValues = basic::StringList(coder); 443| | } 444| | coder.finish(); 445| |} 446| | 447| |inline core::ValueType buildsystem::BuildValue::toData() const { 448| | basic::BinaryEncoder coder; 449| | coder.write(kind); 450| | if (kindHasCommandSignature()) 451| | coder.write(commandSignature); 452| | if (kindHasOutputInfo()) { 453| | coder.write(numOutputInfos); 454| | for (uint32_t i = 0; i != numOutputInfos; ++i) { 455| | coder.write(getNthOutputInfo(i)); 456| | } 457| | } 458| | if (kindHasStringList()) { 459| | stringValues.encode(coder); 460| | } 461| | return coder.contents(); 462| |} 463| | 464| |} 465| | 466| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/BuildEngine.h: 1| |//===- BuildEngine.h --------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_BUILDENGINE_H 14| |#define LLBUILD_CORE_BUILDENGINE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/ADT/Twine.h" 20| | 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |namespace llbuild { 29| |namespace core { 30| | 31| |// FIXME: Need to abstract KeyType; 32| |typedef std::string KeyType; 33| |typedef uint64_t KeyID; 34| |typedef std::vector ValueType; 35| | 36| |class BuildDB; 37| |class BuildEngine; 38| | 39| |/// A monotonically increasing timestamp identifying which iteration of a build 40| |/// an event occurred during. 41| |typedef uint64_t Timestamp; 42| | 43| |/// This object contains the result of executing a task to produce the value for 44| |/// a key. 45| |struct Result { 46| | /// The last value that resulted from executing the task. 47| | ValueType value = {}; 48| | 49| | /// The build timestamp during which the result \see Value was computed. 50| | uint64_t computedAt = 0; 51| | 52| | /// The build timestamp at which this result was last checked to be 53| | /// up-to-date. 54| | /// 55| | /// \invariant builtAt >= computedAt 56| | // 57| | // FIXME: Think about this representation more. The problem with storing this 58| | // field here in this fashion is that every build will result in bringing all 59| | // of the \see builtAt fields up to date. That is unfortunate from a 60| | // persistence perspective, where it would be ideal if we didn't touch any 61| | // disk state for null builds. 62| | uint64_t builtAt = 0; 63| | 64| | /// The explicit dependencies required by the generation. 65| | // 66| | // FIXME: At some point, figure out the optimal representation for this field, 67| | // which is likely to be a lot of the resident memory size. 68| | std::vector dependencies; 69| |}; 70| | 71| |/// A task object represents an abstract in-progress computation in the build 72| |/// engine. 73| |/// 74| |/// The task represents not just the primary computation, but also the process 75| |/// of starting the computation and necessary input dependencies. Tasks are 76| |/// expected to be created in response to \see BuildEngine requests to initiate 77| |/// the production of particular result value. 78| |/// 79| |/// The creator may use \see BuildEngine::taskNeedsInput() to specify input 80| |/// dependencies on the Task. The Task itself may also specify additional input 81| |/// dependencies dynamically during the execution of \see Task::start() or \see 82| |/// Task::provideValue(). 83| |/// 84| |/// Once a task has been created and registered, the BuildEngine will invoke 85| |/// \see Task::start() to initiate the computation. The BuildEngine will provide 86| |/// the in progress task with its requested inputs via \see 87| |/// Task::provideValue(). 88| |/// 89| |/// After all inputs requested by the Task have been delivered, the BuildEngine 90| |/// will invoke \see Task::inputsAvailable() to instruct the Task it should 91| |/// complete its computation and provide the output. The Task is responsible for 92| |/// providing the engine with the computed value when ready using \see 93| |/// BuildEngine::taskIsComplete(). 94| |/// 95| |/// A task which has been cancelled may be destroyed without any of the above 96| |/// behaviors having been completed. 97| |class Task { 98| |public: 99| 0| Task() {} 100| | virtual ~Task(); 101| | 102| | /// Executed by the build engine when the task should be started. 103| | virtual void start(BuildEngine&) = 0; 104| | 105| | /// Invoked by the build engine to provide the prior result for the task's 106| | /// output, if present. 107| | /// 108| | /// This callback will always be invoked immediately after the task is 109| | /// started, and prior to its receipt of any other callbacks. 110| 0| virtual void providePriorValue(BuildEngine&, const ValueType& value) {}; 111| | 112| | /// Invoked by the build engine to provide an input value as it becomes 113| | /// available. 114| | /// 115| | /// \param inputID The unique identifier provided to the build engine to 116| | /// represent this input when requested in \see 117| | /// BuildEngine::taskNeedsInput(). 118| | /// 119| | /// \param value The computed value for the given input. 120| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 121| | const ValueType& value) = 0; 122| | 123| | /// Executed by the build engine to indicate that all inputs have been 124| | /// provided, and the task should begin its computation. 125| | /// 126| | /// The task is expected to call \see BuildEngine::taskIsComplete() when it is 127| | /// done with its computation. 128| | /// 129| | /// It is an error for any client to request an additional input for a task 130| | /// after the last requested input has been provided by the build engine. 131| | virtual void inputsAvailable(BuildEngine&) = 0; 132| |}; 133| | 134| |/// A rule represents an individual element of computation that can be performed 135| |/// by the build engine. 136| |/// 137| |/// Each rule is identified by a unique key and the value for that key can be 138| |/// computed to produce a result, and supplies a set of callbacks that are used 139| |/// to implement the rule's behavior. 140| |/// 141| |/// The computation for a rule is done by invocation of its \see Action 142| |/// callback, which is responsible for creating a Task object which will manage 143| |/// the computation. 144| |/// 145| |/// All callbacks for the Rule are always invoked synchronously on the primary 146| |/// BuildEngine thread. 147| |// 148| |// FIXME: The intent of having a callback like Rule structure and a decoupled 149| |// (virtual) Task is that the Rule objects (of which there can be very many) can 150| |// be optimized for being lightweight. We don't currently make much of an 151| |// attempt in this direction with the std::functions, but we should investigate 152| |// if this can be lighter weight -- especially since many clients are likely to 153| |// need little more than a place to stuff a context object and register their 154| |// callbacks. 155| |// 156| |// FIXME: We also need to figure out if a richer concurrency model is needed for 157| |// the callbacks. The current intent is that they should be lightweight and 158| |// Tasks should be used when real concurrency is needed. 159| |class Rule { 160| |public: 161| | enum class StatusKind { 162| | /// Indicates the rule is being scanned. 163| | IsScanning = 0, 164| | 165| | /// Indicates the rule is up-to-date, and doesn't need to run. 166| | IsUpToDate = 1, 167| | 168| | /// Indicates the rule was run, and is now complete. 169| | IsComplete = 2 170| | }; 171| | 172| | enum class CycleAction { 173| | /// Indicates a rule will be forced to build 174| | ForceBuild = 0, 175| | 176| | /// Indicates a rule's prior value will be supplied to a downstream rule 177| | SupplyPriorValue = 1 178| | }; 179| | 180| | /// The key computed by the rule. 181| | KeyType key; 182| | 183| | /// Called to create the task to build the rule, when necessary. 184| | std::function action; 185| | 186| | /// Called to check whether the previously computed value for this rule is 187| | /// still valid. 188| | /// 189| | /// This callback is designed for use in synchronizing values which represent 190| | /// state managed externally to the build engine. For example, a rule which 191| | /// computes something on the file system may use this to verify that the 192| | /// computed output has not changed since it was built. 193| | std::function isResultValid; 195| | 196| | /// Called to indicate a change in the rule status. 197| | std::function updateStatus; 198| |}; 199| | 200| |/// Delegate interface for use with the build engine. 201| |class BuildEngineDelegate { 202| |public: 203| | virtual ~BuildEngineDelegate(); 204| | 205| | /// Get the rule to use for the given Key. 206| | /// 207| | /// The delegate *must* provide a rule for any possible key that can be 208| | /// requested (either by a client, through \see BuildEngine::build(), or via a 209| | /// Task through mechanisms such as \see BuildEngine::taskNeedsInput(). If a 210| | /// requested Key cannot be supplied, the delegate should provide a dummy rule 211| | /// that the client can translate into an error. 212| | virtual Rule lookupRule(const KeyType& key) = 0; 213| | 214| | /// Called when a cycle is detected by the build engine to check if it should 215| | /// attempt to resolve the cycle and continue 216| | /// 217| | /// \param items The ordered list of items comprising the cycle, starting from 218| | /// the node which was requested to build and ending with the first node in 219| | /// the cycle (i.e., the node participating in the cycle will appear twice). 220| | /// \param candidateRule The rule the engine will use to attempt to break the 221| | /// cycle. 222| | /// \param action The action the engine will take on the candidateRule. 223| | /// \returns True if the engine should attempt to resolve the cycle, false 224| | /// otherwise. Resolution is attempted by either forcing items to be built, or 225| | /// supplying a previously built result to a node in the cycle. The latter 226| | /// action may yield unexpected results and thus this should be opted into 227| | /// with care. 228| | virtual bool shouldResolveCycle(const std::vector& items, 229| | Rule* candidateRule, 230| | Rule::CycleAction action); 231| | 232| | /// Called when a cycle is detected by the build engine and it cannot make 233| | /// forward progress. 234| | /// 235| | /// \param items The ordered list of items comprising the cycle, starting from 236| | /// the node which was requested to build and ending with the first node in 237| | /// the cycle (i.e., the node participating in the cycle will appear twice). 238| | virtual void cycleDetected(const std::vector& items) = 0; 239| | 240| | /// Called when a fatal error is encountered by the build engine. 241| | /// 242| | /// \param message The diagnostic message. 243| | virtual void error(const llvm::Twine& message) = 0; 244| | 245| |}; 246| | 247| |/// A build engine supports fast, incremental, persistent, and parallel 248| |/// execution of computational graphs. 249| |/// 250| |/// Computational elements in the graph are modeled by \see Rule objects, which 251| |/// are assocated with a specific \see KeyType, and which can be executed to 252| |/// produce an output \see ValueType for that key. 253| |/// 254| |/// Rule objects are evaluated by first invoking their action to produce a \see 255| |/// Task object which is responsible for the live execution of the 256| |/// computation. The Task object can interact with the BuildEngine to request 257| |/// inputs or to notify the engine of its completion, and receives various 258| |/// callbacks from the engine as the computation progresses. 259| |/// 260| |/// The engine itself executes using a deterministic, serial operation, but it 261| |/// supports parallel computation by allowing the individual Task objects to 262| |/// defer their own computation to signal the BuildEngine of its completion on 263| |/// alternate threads. 264| |/// 265| |/// To support persistence, the engine allows attaching a database (\see 266| |/// attachDB()) which can be used to record the prior results of evaluating Rule 267| |/// instances. 268| |class BuildEngine { 269| | void *impl; 270| | 271| | // Copying is disabled. 272| | BuildEngine(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 273| | void operator=(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 274| | 275| |public: 276| | /// Create a build engine with the given delegate. 277| | explicit BuildEngine(BuildEngineDelegate& delegate); 278| | ~BuildEngine(); 279| | 280| | /// Return the delegate the engine was configured with. 281| | BuildEngineDelegate* getDelegate(); 282| | 283| | /// Get the current build timestamp used by the engine. 284| | /// 285| | /// The timestamp is a monotonically increasing value which is incremented 286| | /// with each requested build. 287| | Timestamp getCurrentTimestamp(); 288| | 289| | /// @name Rule Definition 290| | /// @{ 291| | 292| | /// Add a rule which the engine can use to produce outputs. 293| | void addRule(Rule&& rule); 294| | 295| | /// @} 296| | 297| | /// @name Client API 298| | /// @{ 299| | 300| | /// Build the result for a particular key. 301| | /// 302| | /// \returns The result of computing the key, or the empty value if the key 303| | /// could not be computed; the latter case only happens if a cycle was 304| | /// discovered currently. 305| | const ValueType& build(const KeyType& key); 306| | 307| | /// Cancel the currently running build. 308| | /// 309| | /// The engine guarantees that it will not *start* any task after processing 310| | /// the current engine work loop iteration after it has been cancelled. 311| | /// 312| | /// This method is thread-safe. 313| | /// 314| | /// This method should only be used when a build is actively running. Invoking 315| | /// this method before a build has started will have no effect. 316| | // 317| | // FIXME: This method is hard to use correctly, we should modify build to 318| | // return an explicit object to represent an in-flight build, and then expose 319| | // cancellation on that. 320| | void cancelBuild(); 321| | 322| | /// Attach a database for persisting build state. 323| | /// 324| | /// A database should only be attached immediately after creating the engine, 325| | /// it is an error to attach a database after adding rules or initiating any 326| | /// builds, or to attempt to attach multiple databases. 327| | /// 328| | /// \param error_out [out] Error string if return value is false. 329| | /// \returns false if the build database could not be attached. 330| | bool attachDB(std::unique_ptr database, std::string* error_out); 331| | 332| | /// Enable tracing into the given output file. 333| | /// 334| | /// \returns True on success. 335| | bool enableTracing(const std::string& path, std::string* error_out); 336| | 337| | /// Dump the build state to a file in Graphviz DOT format. 338| | void dumpGraphToFile(const std::string &path); 339| | 340| | /// @} 341| | 342| | /// @name Task Management APIs 343| | /// @{ 344| | 345| | /// Register the given task, in response to a Rule evaluation. 346| | /// 347| | /// The engine tasks ownership of the \arg Task, and it is expected to 348| | /// subsequently be returned as the task to execute for a Rule evaluation. 349| | /// 350| | /// \returns The provided task, for the convenience of the client. 351| | Task* registerTask(Task* task); 352| | 353| | /// The maximum allowed input ID. 354| | static const uintptr_t kMaximumInputID = ~(uintptr_t)0xFF; 355| | 356| | /// Specify the given \arg Task depends upon the result of computing \arg Key. 357| | /// 358| | /// The result, when available, will be provided to the task via \see 359| | /// Task::provideValue(), supplying the provided \arg InputID to allow the 360| | /// task to identify the particular input. 361| | /// 362| | /// NOTE: It is an unchecked error for a task to request the same input value 363| | /// multiple times. 364| | /// 365| | /// \param inputID An arbitrary value that may be provided by the client to 366| | /// use in efficiently associating this input. The range of this parameter is 367| | /// intentionally chosen to allow a pointer to be provided, but note that all 368| | /// input IDs greater than \see kMaximumInputID are reserved for internal use 369| | /// by the engine. 370| | void taskNeedsInput(Task* task, const KeyType& key, uintptr_t inputID); 371| | 372| | /// Specify that the given \arg Task must be built subsequent to the 373| | /// computation of \arg Key. 374| | /// 375| | /// The value of the computation of \arg Key is not available to the task, and 376| | /// the only guarantee the engine provides is that if \arg Key is computed 377| | /// during a build, then \arg Task will not be computed until after it. 378| | void taskMustFollow(Task* task, const KeyType& key); 379| | 380| | /// Inform the engine of an input dependency that was discovered by the task 381| | /// during its execution, a la compiler generated dependency files. 382| | /// 383| | /// This call may only be made after a task has received all of its inputs; 384| | /// inputs discovered prior to that point should simply be requested as normal 385| | /// input dependencies. 386| | /// 387| | /// Such a dependency is not used to provide additional input to the task, 388| | /// rather it is a way for the task to report an additional input which should 389| | /// be considered the next time the rule is evaluated. The expected use case 390| | /// for a discovered dependency is is when a processing task cannot predict 391| | /// all of its inputs prior to being run, but can presume that any unknown 392| | /// inputs already exist. In such cases, the task can go ahead and run and can 393| | /// report the all of the discovered inputs as it executes. Once the task is 394| | /// complete, these inputs will be recorded as being dependencies of the task 395| | /// so that it will be recomputed when any of the inputs change. 396| | /// 397| | /// It is legal to call this method from any thread, but the caller is 398| | /// responsible for ensuring that it is never called concurrently for the same 399| | /// task. 400| | void taskDiscoveredDependency(Task* task, const KeyType& key); 401| | 402| | /// Called by a task to indicate it has completed and to provide its value. 403| | /// 404| | /// It is legal to call this method from any thread. 405| | /// 406| | /// \param value The new value for the task's rule. 407| | /// 408| | /// \param forceChange If true, treat the value as changed and trigger 409| | /// dependents to rebuild, even if the value itself is not different from the 410| | /// prior result. 411| | void taskIsComplete(Task* task, ValueType&& value, bool forceChange = false); 412| | 413| | /// @} 414| |}; 415| | 416| |} 417| |} 418| | 419| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/DependencyInfoParser.h: 1| |//===- DependencyInfoParser.h -----------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_DEPENDENCYINFOPARSER_H 14| |#define LLBUILD_CORE_DEPENDENCYINFOPARSER_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| |namespace core { 24| | 25| |/// Interface for parsing the "dependency info" format used by Darwin tools. 26| |class DependencyInfoParser { 27| |public: 28| | /// Delegate interface for parser behavior. 29| | struct ParseActions { 30| | virtual ~ParseActions(); 31| | 32| | /// Called if an error is encountered in parsing the input. 33| | /// 34| | /// \param message A C-string text message including information on the 35| | /// error. 36| | /// 37| | /// \param position The approximate position of the error in the input 38| | /// buffer. 39| | virtual void error(const char* message, uint64_t position) = 0; 40| | 41| | /// Called when the version information is found. 42| | /// 43| | /// There can only ever be one version info record in the file. 44| | virtual void actOnVersion(StringRef) = 0; 45| | 46| | /// Called when an input is found. 47| | virtual void actOnInput(StringRef) = 0; 48| | 49| | /// Called when an output is found. 50| | virtual void actOnOutput(StringRef) = 0; 51| | 52| | /// Called when a missing file entry is found. 53| | /// 54| | /// These entries indicate a file which was looked for by the tool, but not 55| | /// found, and can be used to track anti-dependencies. 56| | virtual void actOnMissing(StringRef) = 0; 57| | }; 58| | 59| | StringRef data; 60| | ParseActions& actions; 61| | 62| |public: 63| | DependencyInfoParser(StringRef data, ParseActions& actions) 64| 0| : data(data), actions(actions) {} 65| | 66| | void parse(); 67| |}; 68| | 69| |} 70| |} 71| | 72| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Hashing.h: 1| |//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the newly proposed standard C++ interfaces for hashing 11| |// arbitrary data and building hash functions for user-defined types. This 12| |// interface was originally proposed in N3333[1] and is currently under review 13| |// for inclusion in a future TR and/or standard. 14| |// 15| |// The primary interfaces provide are comprised of one type and three functions: 16| |// 17| |// -- 'hash_code' class is an opaque type representing the hash code for some 18| |// data. It is the intended product of hashing, and can be used to implement 19| |// hash tables, checksumming, and other common uses of hashes. It is not an 20| |// integer type (although it can be converted to one) because it is risky 21| |// to assume much about the internals of a hash_code. In particular, each 22| |// execution of the program has a high probability of producing a different 23| |// hash_code for a given input. Thus their values are not stable to save or 24| |// persist, and should only be used during the execution for the 25| |// construction of hashing datastructures. 26| |// 27| |// -- 'hash_value' is a function designed to be overloaded for each 28| |// user-defined type which wishes to be used within a hashing context. It 29| |// should be overloaded within the user-defined type's namespace and found 30| |// via ADL. Overloads for primitive types are provided by this library. 31| |// 32| |// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid 33| |// programmers in easily and intuitively combining a set of data into 34| |// a single hash_code for their object. They should only logically be used 35| |// within the implementation of a 'hash_value' routine or similar context. 36| |// 37| |// Note that 'hash_combine_range' contains very special logic for hashing 38| |// a contiguous array of integers or pointers. This logic is *extremely* fast, 39| |// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were 40| |// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys 41| |// under 32-bytes. 42| |// 43| |//===----------------------------------------------------------------------===// 44| | 45| |#ifndef LLVM_ADT_HASHING_H 46| |#define LLVM_ADT_HASHING_H 47| | 48| |#include "llvm/Support/DataTypes.h" 49| |#include "llvm/Support/Host.h" 50| |#include "llvm/Support/SwapByteOrder.h" 51| |#include "llvm/Support/type_traits.h" 52| |#include 53| |#include 54| |#include 55| |#include 56| |#include 57| | 58| |namespace llvm { 59| | 60| |/// \brief An opaque object representing a hash code. 61| |/// 62| |/// This object represents the result of hashing some entity. It is intended to 63| |/// be used to implement hashtables or other hashing-based data structures. 64| |/// While it wraps and exposes a numeric value, this value should not be 65| |/// trusted to be stable or predictable across processes or executions. 66| |/// 67| |/// In order to obtain the hash_code for an object 'x': 68| |/// \code 69| |/// using llvm::hash_value; 70| |/// llvm::hash_code code = hash_value(x); 71| |/// \endcode 72| |class hash_code { 73| | size_t value; 74| | 75| |public: 76| | /// \brief Default construct a hash_code. 77| | /// Note that this leaves the value uninitialized. 78| 0| hash_code() {} 79| | 80| | /// \brief Form a hash code directly from a numerical value. 81| 0| hash_code(size_t value) : value(value) {} 82| | 83| | /// \brief Convert the hash code to its numerical value for use. 84| 0| /*explicit*/ operator size_t() const { return value; } 85| | 86| 0| friend bool operator==(const hash_code &lhs, const hash_code &rhs) { 87| 0| return lhs.value == rhs.value; 88| 0| } 89| 0| friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { 90| 0| return lhs.value != rhs.value; 91| 0| } 92| | 93| | /// \brief Allow a hash_code to be directly run through hash_value. 94| | friend size_t hash_value(const hash_code &code) { return code.value; } 95| |}; 96| | 97| |/// \brief Compute a hash_code for any integer value. 98| |/// 99| |/// Note that this function is intended to compute the same hash_code for 100| |/// a particular value without regard to the pre-promotion type. This is in 101| |/// contrast to hash_combine which may produce different hash_codes for 102| |/// differing argument types even if they would implicit promote to a common 103| |/// type without changing the value. 104| |template 105| |typename std::enable_if::value, hash_code>::type 106| |hash_value(T value); 107| | 108| |/// \brief Compute a hash_code for a pointer's address. 109| |/// 110| |/// N.B.: This hashes the *address*. Not the value and not the type. 111| |template hash_code hash_value(const T *ptr); 112| | 113| |/// \brief Compute a hash_code for a pair of objects. 114| |template 115| |hash_code hash_value(const std::pair &arg); 116| | 117| |/// \brief Compute a hash_code for a standard string. 118| |template 119| |hash_code hash_value(const std::basic_string &arg); 120| | 121| | 122| |/// \brief Override the execution seed with a fixed value. 123| |/// 124| |/// This hashing library uses a per-execution seed designed to change on each 125| |/// run with high probability in order to ensure that the hash codes are not 126| |/// attackable and to ensure that output which is intended to be stable does 127| |/// not rely on the particulars of the hash codes produced. 128| |/// 129| |/// That said, there are use cases where it is important to be able to 130| |/// reproduce *exactly* a specific behavior. To that end, we provide a function 131| |/// which will forcibly set the seed to a fixed value. This must be done at the 132| |/// start of the program, before any hashes are computed. Also, it cannot be 133| |/// undone. This makes it thread-hostile and very hard to use outside of 134| |/// immediately on start of a simple program designed for reproducible 135| |/// behavior. 136| |void set_fixed_execution_hash_seed(size_t fixed_value); 137| | 138| | 139| |// All of the implementation details of actually computing the various hash 140| |// code values are held within this namespace. These routines are included in 141| |// the header file mainly to allow inlining and constant propagation. 142| |namespace hashing { 143| |namespace detail { 144| | 145| 0|inline uint64_t fetch64(const char *p) { 146| 0| uint64_t result; 147| 0| memcpy(&result, p, sizeof(result)); 148| 0| if (sys::IsBigEndianHost) 149| 0| sys::swapByteOrder(result); 150| 0| return result; 151| 0|} 152| | 153| 0|inline uint32_t fetch32(const char *p) { 154| 0| uint32_t result; 155| 0| memcpy(&result, p, sizeof(result)); 156| 0| if (sys::IsBigEndianHost) 157| 0| sys::swapByteOrder(result); 158| 0| return result; 159| 0|} 160| | 161| |/// Some primes between 2^63 and 2^64 for various uses. 162| |static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; 163| |static const uint64_t k1 = 0xb492b66fbe98f273ULL; 164| |static const uint64_t k2 = 0x9ae16a3b2f90404fULL; 165| |static const uint64_t k3 = 0xc949d7c7509e6557ULL; 166| | 167| |/// \brief Bitwise right rotate. 168| |/// Normally this will compile to a single instruction, especially if the 169| |/// shift is a manifest constant. 170| 0|inline uint64_t rotate(uint64_t val, size_t shift) { 171| 0| // Avoid shifting by 64: doing so yields an undefined result. 172| 0| return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); 173| 0|} 174| | 175| 0|inline uint64_t shift_mix(uint64_t val) { 176| 0| return val ^ (val >> 47); 177| 0|} 178| | 179| 0|inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { 180| 0| // Murmur-inspired hashing. 181| 0| const uint64_t kMul = 0x9ddfea08eb382d69ULL; 182| 0| uint64_t a = (low ^ high) * kMul; 183| 0| a ^= (a >> 47); 184| 0| uint64_t b = (high ^ a) * kMul; 185| 0| b ^= (b >> 47); 186| 0| b *= kMul; 187| 0| return b; 188| 0|} 189| | 190| 0|inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { 191| 0| uint8_t a = s[0]; 192| 0| uint8_t b = s[len >> 1]; 193| 0| uint8_t c = s[len - 1]; 194| 0| uint32_t y = static_cast(a) + (static_cast(b) << 8); 195| 0| uint32_t z = len + (static_cast(c) << 2); 196| 0| return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; 197| 0|} 198| | 199| 0|inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { 200| 0| uint64_t a = fetch32(s); 201| 0| return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); 202| 0|} 203| | 204| 0|inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { 205| 0| uint64_t a = fetch64(s); 206| 0| uint64_t b = fetch64(s + len - 8); 207| 0| return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; 208| 0|} 209| | 210| 0|inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { 211| 0| uint64_t a = fetch64(s) * k1; 212| 0| uint64_t b = fetch64(s + 8); 213| 0| uint64_t c = fetch64(s + len - 8) * k2; 214| 0| uint64_t d = fetch64(s + len - 16) * k0; 215| 0| return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, 216| 0| a + rotate(b ^ k3, 20) - c + len + seed); 217| 0|} 218| | 219| 0|inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { 220| 0| uint64_t z = fetch64(s + 24); 221| 0| uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; 222| 0| uint64_t b = rotate(a + z, 52); 223| 0| uint64_t c = rotate(a, 37); 224| 0| a += fetch64(s + 8); 225| 0| c += rotate(a, 7); 226| 0| a += fetch64(s + 16); 227| 0| uint64_t vf = a + z; 228| 0| uint64_t vs = b + rotate(a, 31) + c; 229| 0| a = fetch64(s + 16) + fetch64(s + len - 32); 230| 0| z = fetch64(s + len - 8); 231| 0| b = rotate(a + z, 52); 232| 0| c = rotate(a, 37); 233| 0| a += fetch64(s + len - 24); 234| 0| c += rotate(a, 7); 235| 0| a += fetch64(s + len - 16); 236| 0| uint64_t wf = a + z; 237| 0| uint64_t ws = b + rotate(a, 31) + c; 238| 0| uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); 239| 0| return shift_mix((seed ^ (r * k0)) + vs) * k2; 240| 0|} 241| | 242| 0|inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { 243| 0| if (length >= 4 && length <= 8) 244| 0| return hash_4to8_bytes(s, length, seed); 245| 0| if (length > 8 && length <= 16) 246| 0| return hash_9to16_bytes(s, length, seed); 247| 0| if (length > 16 && length <= 32) 248| 0| return hash_17to32_bytes(s, length, seed); 249| 0| if (length > 32) 250| 0| return hash_33to64_bytes(s, length, seed); 251| 0| if (length != 0) 252| 0| return hash_1to3_bytes(s, length, seed); 253| 0| 254| 0| return k2 ^ seed; 255| 0|} 256| | 257| |/// \brief The intermediate state used during hashing. 258| |/// Currently, the algorithm for computing hash codes is based on CityHash and 259| |/// keeps 56 bytes of arbitrary state. 260| |struct hash_state { 261| | uint64_t h0, h1, h2, h3, h4, h5, h6; 262| | 263| | /// \brief Create a new hash_state structure and initialize it based on the 264| | /// seed and the first 64-byte chunk. 265| | /// This effectively performs the initial mix. 266| 0| static hash_state create(const char *s, uint64_t seed) { 267| 0| hash_state state = { 268| 0| 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), 269| 0| seed * k1, shift_mix(seed), 0 }; 270| 0| state.h6 = hash_16_bytes(state.h4, state.h5); 271| 0| state.mix(s); 272| 0| return state; 273| 0| } 274| | 275| | /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' 276| | /// and 'b', including whatever is already in 'a' and 'b'. 277| 0| static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { 278| 0| a += fetch64(s); 279| 0| uint64_t c = fetch64(s + 24); 280| 0| b = rotate(b + a + c, 21); 281| 0| uint64_t d = a; 282| 0| a += fetch64(s + 8) + fetch64(s + 16); 283| 0| b += rotate(a, 44) + d; 284| 0| a += c; 285| 0| } 286| | 287| | /// \brief Mix in a 64-byte buffer of data. 288| | /// We mix all 64 bytes even when the chunk length is smaller, but we 289| | /// record the actual length. 290| 0| void mix(const char *s) { 291| 0| h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; 292| 0| h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; 293| 0| h0 ^= h6; 294| 0| h1 += h3 + fetch64(s + 40); 295| 0| h2 = rotate(h2 + h5, 33) * k1; 296| 0| h3 = h4 * k1; 297| 0| h4 = h0 + h5; 298| 0| mix_32_bytes(s, h3, h4); 299| 0| h5 = h2 + h6; 300| 0| h6 = h1 + fetch64(s + 16); 301| 0| mix_32_bytes(s + 32, h5, h6); 302| 0| std::swap(h2, h0); 303| 0| } 304| | 305| | /// \brief Compute the final 64-bit hash code value based on the current 306| | /// state and the length of bytes hashed. 307| 0| uint64_t finalize(size_t length) { 308| 0| return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, 309| 0| hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); 310| 0| } 311| |}; 312| | 313| | 314| |/// \brief A global, fixed seed-override variable. 315| |/// 316| |/// This variable can be set using the \see llvm::set_fixed_execution_seed 317| |/// function. See that function for details. Do not, under any circumstances, 318| |/// set or read this variable. 319| |extern size_t fixed_seed_override; 320| | 321| 0|inline size_t get_execution_seed() { 322| 0| // FIXME: This needs to be a per-execution seed. This is just a placeholder 323| 0| // implementation. Switching to a per-execution seed is likely to flush out 324| 0| // instability bugs and so will happen as its own commit. 325| 0| // 326| 0| // However, if there is a fixed seed override set the first time this is 327| 0| // called, return that instead of the per-execution seed. 328| 0| const uint64_t seed_prime = 0xff51afd7ed558ccdULL; 329| 0| static size_t seed = fixed_seed_override ? fixed_seed_override 330| 0| : (size_t)seed_prime; 331| 0| return seed; 332| 0|} 333| | 334| | 335| |/// \brief Trait to indicate whether a type's bits can be hashed directly. 336| |/// 337| |/// A type trait which is true if we want to combine values for hashing by 338| |/// reading the underlying data. It is false if values of this type must 339| |/// first be passed to hash_value, and the resulting hash_codes combined. 340| |// 341| |// FIXME: We want to replace is_integral_or_enum and is_pointer here with 342| |// a predicate which asserts that comparing the underlying storage of two 343| |// values of the type for equality is equivalent to comparing the two values 344| |// for equality. For all the platforms we care about, this holds for integers 345| |// and pointers, but there are platforms where it doesn't and we would like to 346| |// support user-defined types which happen to satisfy this property. 347| |template struct is_hashable_data 348| | : std::integral_constant::value || 349| | std::is_pointer::value) && 350| | 64 % sizeof(T) == 0)> {}; 351| | 352| |// Special case std::pair to detect when both types are viable and when there 353| |// is no alignment-derived padding in the pair. This is a bit of a lie because 354| |// std::pair isn't truly POD, but it's close enough in all reasonable 355| |// implementations for our use case of hashing the underlying data. 356| |template struct is_hashable_data > 357| | : std::integral_constant::value && 358| | is_hashable_data::value && 359| | (sizeof(T) + sizeof(U)) == 360| | sizeof(std::pair))> {}; 361| | 362| |/// \brief Helper to get the hashable data representation for a type. 363| |/// This variant is enabled when the type itself can be used. 364| |template 365| |typename std::enable_if::value, T>::type 366| 0|get_hashable_data(const T &value) { 367| 0| return value; 368| 0|} 369| |/// \brief Helper to get the hashable data representation for a type. 370| |/// This variant is enabled when we must first call hash_value and use the 371| |/// result as our data. 372| |template 373| |typename std::enable_if::value, size_t>::type 374| 0|get_hashable_data(const T &value) { 375| 0| using ::llvm::hash_value; 376| 0| return hash_value(value); 377| 0|} 378| | 379| |/// \brief Helper to store data from a value into a buffer and advance the 380| |/// pointer into that buffer. 381| |/// 382| |/// This routine first checks whether there is enough space in the provided 383| |/// buffer, and if not immediately returns false. If there is space, it 384| |/// copies the underlying bytes of value into the buffer, advances the 385| |/// buffer_ptr past the copied bytes, and returns true. 386| |template 387| |bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, 388| 0| size_t offset = 0) { 389| 0| size_t store_size = sizeof(value) - offset; 390| 0| if (buffer_ptr + store_size > buffer_end) 391| 0| return false; 392| 0| const char *value_data = reinterpret_cast(&value); 393| 0| memcpy(buffer_ptr, value_data + offset, store_size); 394| 0| buffer_ptr += store_size; 395| 0| return true; 396| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceIyEEbRPcS3_RKT_m ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceImEEbRPcS3_RKT_m ------------------ 397| | 398| |/// \brief Implement the combining of integral values into a hash_code. 399| |/// 400| |/// This overload is selected when the value type of the iterator is 401| |/// integral. Rather than computing a hash_code for each object and then 402| |/// combining them, this (as an optimization) directly combines the integers. 403| |template 404| |hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { 405| | const size_t seed = get_execution_seed(); 406| | char buffer[64], *buffer_ptr = buffer; 407| | char *const buffer_end = std::end(buffer); 408| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 409| | get_hashable_data(*first))) 410| | ++first; 411| | if (first == last) 412| | return hash_short(buffer, buffer_ptr - buffer, seed); 413| | assert(buffer_ptr == buffer_end); 414| | 415| | hash_state state = state.create(buffer, seed); 416| | size_t length = 64; 417| | while (first != last) { 418| | // Fill up the buffer. We don't clear it, which re-mixes the last round 419| | // when only a partial 64-byte chunk is left. 420| | buffer_ptr = buffer; 421| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 422| | get_hashable_data(*first))) 423| | ++first; 424| | 425| | // Rotate the buffer if we did a partial fill in order to simulate doing 426| | // a mix of the last 64-bytes. That is how the algorithm works when we 427| | // have a contiguous byte sequence, and we want to emulate that here. 428| | std::rotate(buffer, buffer_ptr, buffer_end); 429| | 430| | // Mix this chunk into the current state. 431| | state.mix(buffer); 432| | length += buffer_ptr - buffer; 433| | }; 434| | 435| | return state.finalize(length); 436| |} 437| | 438| |/// \brief Implement the combining of integral values into a hash_code. 439| |/// 440| |/// This overload is selected when the value type of the iterator is integral 441| |/// and when the input iterator is actually a pointer. Rather than computing 442| |/// a hash_code for each object and then combining them, this (as an 443| |/// optimization) directly combines the integers. Also, because the integers 444| |/// are stored in contiguous memory, this routine avoids copying each value 445| |/// and directly reads from the underlying memory. 446| |template 447| |typename std::enable_if::value, hash_code>::type 448| |hash_combine_range_impl(ValueT *first, ValueT *last) { 449| | const size_t seed = get_execution_seed(); 450| | const char *s_begin = reinterpret_cast(first); 451| | const char *s_end = reinterpret_cast(last); 452| | const size_t length = std::distance(s_begin, s_end); 453| | if (length <= 64) 454| | return hash_short(s_begin, length, seed); 455| | 456| | const char *s_aligned_end = s_begin + (length & ~63); 457| | hash_state state = state.create(s_begin, seed); 458| | s_begin += 64; 459| | while (s_begin != s_aligned_end) { 460| | state.mix(s_begin); 461| | s_begin += 64; 462| | } 463| | if (length & 63) 464| | state.mix(s_end - 64); 465| | 466| | return state.finalize(length); 467| |} 468| | 469| |} // namespace detail 470| |} // namespace hashing 471| | 472| | 473| |/// \brief Compute a hash_code for a sequence of values. 474| |/// 475| |/// This hashes a sequence of values. It produces the same hash_code as 476| |/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences 477| |/// and is significantly faster given pointers and types which can be hashed as 478| |/// a sequence of bytes. 479| |template 480| |hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { 481| | return ::llvm::hashing::detail::hash_combine_range_impl(first, last); 482| |} 483| | 484| | 485| |// Implementation details for hash_combine. 486| |namespace hashing { 487| |namespace detail { 488| | 489| |/// \brief Helper class to manage the recursive combining of hash_combine 490| |/// arguments. 491| |/// 492| |/// This class exists to manage the state and various calls involved in the 493| |/// recursive combining of arguments used in hash_combine. It is particularly 494| |/// useful at minimizing the code in the recursive calls to ease the pain 495| |/// caused by a lack of variadic functions. 496| |struct hash_combine_recursive_helper { 497| | char buffer[64]; 498| | hash_state state; 499| | const size_t seed; 500| | 501| |public: 502| | /// \brief Construct a recursive hash combining helper. 503| | /// 504| | /// This sets up the state for a recursive hash combine, including getting 505| | /// the seed and buffer setup. 506| | hash_combine_recursive_helper() 507| 0| : seed(get_execution_seed()) {} 508| | 509| | /// \brief Combine one chunk of data into the current in-flight hash. 510| | /// 511| | /// This merges one chunk of data into the hash. First it tries to buffer 512| | /// the data. If the buffer is full, it hashes the buffer into its 513| | /// hash_state, empties it, and then merges the new chunk in. This also 514| | /// handles cases where the data straddles the end of the buffer. 515| | template 516| 0| char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { 517| 0| if (!store_and_advance(buffer_ptr, buffer_end, data)) { 518| 0| // Check for skew which prevents the buffer from being packed, and do 519| 0| // a partial store into the buffer to fill it. This is only a concern 520| 0| // with the variadic combine because that formation can have varying 521| 0| // argument types. 522| 0| size_t partial_store_size = buffer_end - buffer_ptr; 523| 0| memcpy(buffer_ptr, &data, partial_store_size); 524| 0| 525| 0| // If the store fails, our buffer is full and ready to hash. We have to 526| 0| // either initialize the hash state (on the first full buffer) or mix 527| 0| // this buffer into the existing hash state. Length tracks the *hashed* 528| 0| // length, not the buffered length. 529| 0| if (length == 0) { 530| 0| state = state.create(buffer, seed); 531| 0| length = 64; 532| 0| } else { 533| 0| // Mix this chunk into the current state and bump length up by 64. 534| 0| state.mix(buffer); 535| 0| length += 64; 536| 0| } 537| 0| // Reset the buffer_ptr to the head of the buffer for the next chunk of 538| 0| // data. 539| 0| buffer_ptr = buffer; 540| 0| 541| 0| // Try again to store into the buffer -- this cannot fail as we only 542| 0| // store types smaller than the buffer. 543| 0| if (!store_and_advance(buffer_ptr, buffer_end, data, 544| 0| partial_store_size)) 545| 0| abort(); 546| 0| } 547| 0| return buffer_ptr; 548| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper12combine_dataIyEEPcRmS4_S4_T_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper12combine_dataImEEPcRmS4_S4_T_ ------------------ 549| | 550| | /// \brief Recursive, variadic combining method. 551| | /// 552| | /// This function recurses through each argument, combining that argument 553| | /// into a single hash. 554| | template 555| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, 556| 0| const T &arg, const Ts &...args) { 557| 0| buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); 558| 0| 559| 0| // Recurse to the next argument. 560| 0| return combine(length, buffer_ptr, buffer_end, args...); 561| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIyJNS_9StringRefEEEENS_9hash_codeEmPcS6_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9StringRefEJEEENS_9hash_codeEmPcS6_RKT_DpRKT0_ ------------------ 562| | 563| | /// \brief Base case for recursive, variadic combining. 564| | /// 565| | /// The base case when combining arguments recursively is reached when all 566| | /// arguments have been handled. It flushes the remaining buffer and 567| | /// constructs a hash_code. 568| 0| hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { 569| 0| // Check whether the entire set of values fit in the buffer. If so, we'll 570| 0| // use the optimized short hashing routine and skip state entirely. 571| 0| if (length == 0) 572| 0| return hash_short(buffer, buffer_ptr - buffer, seed); 573| 0| 574| 0| // Mix the final buffer, rotating it if we did a partial fill in order to 575| 0| // simulate doing a mix of the last 64-bytes. That is how the algorithm 576| 0| // works when we have a contiguous byte sequence, and we want to emulate 577| 0| // that here. 578| 0| std::rotate(buffer, buffer_ptr, buffer_end); 579| 0| 580| 0| // Mix this chunk into the current state. 581| 0| state.mix(buffer); 582| 0| length += buffer_ptr - buffer; 583| 0| 584| 0| return state.finalize(length); 585| 0| } 586| |}; 587| | 588| |} // namespace detail 589| |} // namespace hashing 590| | 591| |/// \brief Combine values into a single hash_code. 592| |/// 593| |/// This routine accepts a varying number of arguments of any type. It will 594| |/// attempt to combine them into a single hash_code. For user-defined types it 595| |/// attempts to call a \see hash_value overload (via ADL) for the type. For 596| |/// integer and pointer types it directly combines their data into the 597| |/// resulting hash_code. 598| |/// 599| |/// The result is suitable for returning from a user's hash_value 600| |/// *implementation* for their user-defined type. Consumers of a type should 601| |/// *not* call this routine, they should instead call 'hash_value'. 602| 0|template hash_code hash_combine(const Ts &...args) { 603| 0| // Recursively hash each argument using a helper class. 604| 0| ::llvm::hashing::detail::hash_combine_recursive_helper helper; 605| 0| return helper.combine(0, helper.buffer, helper.buffer + 64, args...); 606| 0|} 607| | 608| |// Implementation details for implementations of hash_value overloads provided 609| |// here. 610| |namespace hashing { 611| |namespace detail { 612| | 613| |/// \brief Helper to hash the value of a single integer. 614| |/// 615| |/// Overloads for smaller integer types are not provided to ensure consistent 616| |/// behavior in the presence of integral promotions. Essentially, 617| |/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. 618| 0|inline hash_code hash_integer_value(uint64_t value) { 619| 0| // Similar to hash_4to8_bytes but using a seed instead of length. 620| 0| const uint64_t seed = get_execution_seed(); 621| 0| const char *s = reinterpret_cast(&value); 622| 0| const uint64_t a = fetch32(s); 623| 0| return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); 624| 0|} 625| | 626| |} // namespace detail 627| |} // namespace hashing 628| | 629| |// Declared and documented above, but defined here so that any of the hashing 630| |// infrastructure is available. 631| |template 632| |typename std::enable_if::value, hash_code>::type 633| |hash_value(T value) { 634| | return ::llvm::hashing::detail::hash_integer_value(value); 635| |} 636| | 637| |// Declared and documented above, but defined here so that any of the hashing 638| |// infrastructure is available. 639| |template hash_code hash_value(const T *ptr) { 640| | return ::llvm::hashing::detail::hash_integer_value( 641| | reinterpret_cast(ptr)); 642| |} 643| | 644| |// Declared and documented above, but defined here so that any of the hashing 645| |// infrastructure is available. 646| |template 647| |hash_code hash_value(const std::pair &arg) { 648| | return hash_combine(arg.first, arg.second); 649| |} 650| | 651| |// Declared and documented above, but defined here so that any of the hashing 652| |// infrastructure is available. 653| |template 654| |hash_code hash_value(const std::basic_string &arg) { 655| | return hash_combine_range(arg.begin(), arg.end()); 656| |} 657| | 658| |} // namespace llvm 659| | 660| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Optional.h: 1| |//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides Optional, a template class modeled in the spirit of 11| |// OCaml's 'opt' variant. The idea is to strongly type whether or not 12| |// a value can be optional. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_ADT_OPTIONAL_H 17| |#define LLVM_ADT_OPTIONAL_H 18| | 19| |#include "llvm/ADT/None.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include "llvm/Support/Compiler.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |template 30| |class Optional { 31| | AlignedCharArrayUnion storage; 32| | bool hasVal; 33| |public: 34| | typedef T value_type; 35| | 36| | Optional(NoneType) : hasVal(false) {} 37| 0| explicit Optional() : hasVal(false) {} 38| | Optional(const T &y) : hasVal(true) { 39| | new (storage.buffer) T(y); 40| | } 41| | Optional(const Optional &O) : hasVal(O.hasVal) { 42| | if (hasVal) 43| | new (storage.buffer) T(*O); 44| | } 45| | 46| | Optional(T &&y) : hasVal(true) { 47| | new (storage.buffer) T(std::forward(y)); 48| | } 49| | Optional(Optional &&O) : hasVal(O) { 50| | if (O) { 51| | new (storage.buffer) T(std::move(*O)); 52| | O.reset(); 53| | } 54| | } 55| | Optional &operator=(T &&y) { 56| | if (hasVal) 57| | **this = std::move(y); 58| | else { 59| | new (storage.buffer) T(std::move(y)); 60| | hasVal = true; 61| | } 62| | return *this; 63| | } 64| | Optional &operator=(Optional &&O) { 65| | if (!O) 66| | reset(); 67| | else { 68| | *this = std::move(*O); 69| | O.reset(); 70| | } 71| | return *this; 72| | } 73| | 74| | /// Create a new object by constructing it in place with the given arguments. 75| | template 76| | void emplace(ArgTypes &&...Args) { 77| | reset(); 78| | hasVal = true; 79| | new (storage.buffer) T(std::forward(Args)...); 80| | } 81| | 82| | static inline Optional create(const T* y) { 83| | return y ? Optional(*y) : Optional(); 84| | } 85| | 86| | // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 87| | // could be made more efficient by passing by value, possibly unifying them 88| | // with the rvalue versions above - but this could place a different set of 89| | // requirements (notably: the existence of a default ctor) when implemented 90| | // in that way. Careful SFINAE to avoid such pitfalls would be required. 91| | Optional &operator=(const T &y) { 92| | if (hasVal) 93| | **this = y; 94| | else { 95| | new (storage.buffer) T(y); 96| | hasVal = true; 97| | } 98| | return *this; 99| | } 100| | 101| | Optional &operator=(const Optional &O) { 102| | if (!O) 103| | reset(); 104| | else 105| | *this = *O; 106| | return *this; 107| | } 108| | 109| 0| void reset() { 110| 0| if (hasVal) { 111| 0| (**this).~T(); 112| 0| hasVal = false; 113| 0| } 114| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEE5resetEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE5resetEv ------------------ 115| | 116| 0| ~Optional() { 117| 0| reset(); 118| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEED2Ev ------------------ 119| | 120| | const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); } 121| 0| T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEE10getPointerEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE10getPointerEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE10getPointerEv ------------------ 122| | const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 123| 0| T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 124| | 125| | explicit operator bool() const { return hasVal; } 126| 0| bool hasValue() const { return hasVal; } 127| | const T* operator->() const { return getPointer(); } 128| | T* operator->() { return getPointer(); } 129| | const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 130| 0| T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEEdeEv ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEdeEv ------------------ 131| | 132| | template 133| | LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { 134| | return hasValue() ? getValue() : std::forward(value); 135| | } 136| | 137| 0| void unwrapIn(std::function fn) { 138| 0| if (hasValue()) 139| 0| fn(getValue()); 140| 0| } 141| | void unwrapIn(std::function fn) const { 142| | if (hasValue()) 143| | fn(getValue()); 144| | } 145| | 146| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 147| | T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 148| | T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 149| | 150| | template 151| | T getValueOr(U &&value) && { 152| | return hasValue() ? std::move(getValue()) : std::forward(value); 153| | } 154| |#endif 155| |}; 156| | 157| |template struct isPodLike; 158| |template struct isPodLike > { 159| | // An Optional is pod-like if T is. 160| | static const bool value = isPodLike::value; 161| |}; 162| | 163| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 164| |/// explicitly compare the underlying values and account for empty \c Optional 165| |/// objects. 166| |/// 167| |/// This routine will never be defined. It returns \c void to help diagnose 168| |/// errors at compile time. 169| |template 170| |void operator==(const Optional &X, const Optional &Y); 171| | 172| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 173| |/// explicitly compare the underlying values and account for empty \c Optional 174| |/// objects. 175| |/// 176| |/// This routine will never be defined. It returns \c void to help diagnose 177| |/// errors at compile time. 178| |template 179| |void operator!=(const Optional &X, const Optional &Y); 180| | 181| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 182| |/// explicitly compare the underlying values and account for empty \c Optional 183| |/// objects. 184| |/// 185| |/// This routine will never be defined. It returns \c void to help diagnose 186| |/// errors at compile time. 187| |template 188| |void operator<(const Optional &X, const Optional &Y); 189| | 190| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 191| |/// explicitly compare the underlying values and account for empty \c Optional 192| |/// objects. 193| |/// 194| |/// This routine will never be defined. It returns \c void to help diagnose 195| |/// errors at compile time. 196| |template 197| |void operator<=(const Optional &X, const Optional &Y); 198| | 199| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 200| |/// explicitly compare the underlying values and account for empty \c Optional 201| |/// objects. 202| |/// 203| |/// This routine will never be defined. It returns \c void to help diagnose 204| |/// errors at compile time. 205| |template 206| |void operator>=(const Optional &X, const Optional &Y); 207| | 208| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 209| |/// explicitly compare the underlying values and account for empty \c Optional 210| |/// objects. 211| |/// 212| |/// This routine will never be defined. It returns \c void to help diagnose 213| |/// errors at compile time. 214| |template 215| |void operator>(const Optional &X, const Optional &Y); 216| | 217| |} // end llvm namespace 218| | 219| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallPtrSet.h: 1| |//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallPtrSet class. See the doxygen comment for 11| |// SmallPtrSetImplBase for more details on the algorithm used. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_ADT_SMALLPTRSET_H 16| |#define LLVM_ADT_SMALLPTRSET_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include "llvm/Support/PointerLikeTypeTraits.h" 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |class SmallPtrSetIteratorImpl; 30| | 31| |/// SmallPtrSetImplBase - This is the common code shared among all the 32| |/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one 33| |/// for small and one for large sets. 34| |/// 35| |/// Small sets use an array of pointers allocated in the SmallPtrSet object, 36| |/// which is treated as a simple array of pointers. When a pointer is added to 37| |/// the set, the array is scanned to see if the element already exists, if not 38| |/// the element is 'pushed back' onto the array. If we run out of space in the 39| |/// array, we grow into the 'large set' case. SmallSet should be used when the 40| |/// sets are often small. In this case, no memory allocation is used, and only 41| |/// light-weight and cache-efficient scanning is used. 42| |/// 43| |/// Large sets use a classic exponentially-probed hash table. Empty buckets are 44| |/// represented with an illegal pointer value (-1) to allow null pointers to be 45| |/// inserted. Tombstones are represented with another illegal pointer value 46| |/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or 47| |/// more. When this happens, the table is doubled in size. 48| |/// 49| |class SmallPtrSetImplBase { 50| | friend class SmallPtrSetIteratorImpl; 51| |protected: 52| | /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. 53| | const void **SmallArray; 54| | /// CurArray - This is the current set of buckets. If equal to SmallArray, 55| | /// then the set is in 'small mode'. 56| | const void **CurArray; 57| | /// CurArraySize - The allocated size of CurArray, always a power of two. 58| | unsigned CurArraySize; 59| | 60| | // If small, this is # elts allocated consecutively 61| | unsigned NumElements; 62| | unsigned NumTombstones; 63| | 64| | // Helpers to copy and move construct a SmallPtrSet. 65| | SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that); 66| | SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize, 67| | SmallPtrSetImplBase &&that); 68| | explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) : 69| 0| SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { 70| 0| assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && 71| 0| "Initial size must be a power of two!"); 72| 0| clear(); 73| 0| } 74| | ~SmallPtrSetImplBase(); 75| | 76| |public: 77| | typedef unsigned size_type; 78| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } 79| 0| size_type size() const { return NumElements; } 80| | 81| 0| void clear() { 82| 0| // If the capacity of the array is huge, and the # elements used is small, 83| 0| // shrink the array. 84| 0| if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) 85| 0| return shrink_and_clear(); 86| 0| 87| 0| // Fill the array with empty markers. 88| 0| memset(CurArray, -1, CurArraySize*sizeof(void*)); 89| 0| NumElements = 0; 90| 0| NumTombstones = 0; 91| 0| } 92| | 93| |protected: 94| 0| static void *getTombstoneMarker() { return reinterpret_cast(-2); } 95| 0| static void *getEmptyMarker() { 96| 0| // Note that -1 is chosen to make clear() efficiently implementable with 97| 0| // memset and because it's not a valid pointer value. 98| 0| return reinterpret_cast(-1); 99| 0| } 100| | 101| | /// insert_imp - This returns true if the pointer was new to the set, false if 102| | /// it was already in the set. This is hidden from the client so that the 103| | /// derived class can check that the right type of pointer is passed in. 104| | std::pair insert_imp(const void *Ptr); 105| | 106| | /// erase_imp - If the set contains the specified pointer, remove it and 107| | /// return true, otherwise return false. This is hidden from the client so 108| | /// that the derived class can check that the right type of pointer is passed 109| | /// in. 110| | bool erase_imp(const void * Ptr); 111| | 112| 0| bool count_imp(const void * Ptr) const { 113| 0| if (isSmall()) { 114| 0| // Linear search for the item. 115| 0| for (const void *const *APtr = SmallArray, 116| 0| *const *E = SmallArray+NumElements; APtr != E; ++APtr) 117| 0| if (*APtr == Ptr) 118| 0| return true; 119| 0| return false; 120| 0| } 121| 0| 122| 0| // Big set case. 123| 0| return *FindBucketFor(Ptr) == Ptr; 124| 0| } 125| | 126| |private: 127| 0| bool isSmall() const { return CurArray == SmallArray; } 128| | 129| | const void * const *FindBucketFor(const void *Ptr) const; 130| | void shrink_and_clear(); 131| | 132| | /// Grow - Allocate a larger backing store for the buckets and move it over. 133| | void Grow(unsigned NewSize); 134| | 135| | void operator=(const SmallPtrSetImplBase &RHS) = delete; 136| |protected: 137| | /// swap - Swaps the elements of two sets. 138| | /// Note: This method assumes that both sets have the same small size. 139| | void swap(SmallPtrSetImplBase &RHS); 140| | 141| | void CopyFrom(const SmallPtrSetImplBase &RHS); 142| | void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS); 143| |}; 144| | 145| |/// SmallPtrSetIteratorImpl - This is the common base class shared between all 146| |/// instances of SmallPtrSetIterator. 147| |class SmallPtrSetIteratorImpl { 148| |protected: 149| | const void *const *Bucket; 150| | const void *const *End; 151| |public: 152| | explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) 153| 0| : Bucket(BP), End(E) { 154| 0| AdvanceIfNotValid(); 155| 0| } 156| | 157| 0| bool operator==(const SmallPtrSetIteratorImpl &RHS) const { 158| 0| return Bucket == RHS.Bucket; 159| 0| } 160| 0| bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { 161| 0| return Bucket != RHS.Bucket; 162| 0| } 163| | 164| |protected: 165| | /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket 166| | /// that is. This is guaranteed to stop because the end() bucket is marked 167| | /// valid. 168| 0| void AdvanceIfNotValid() { 169| 0| assert(Bucket <= End); 170| 0| while (Bucket != End && 171| 0| (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || 172| 0| *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) 173| 0| ++Bucket; 174| 0| } 175| |}; 176| | 177| |/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. 178| |template 179| |class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { 180| | typedef PointerLikeTypeTraits PtrTraits; 181| | 182| |public: 183| | typedef PtrTy value_type; 184| | typedef PtrTy reference; 185| | typedef PtrTy pointer; 186| | typedef std::ptrdiff_t difference_type; 187| | typedef std::forward_iterator_tag iterator_category; 188| | 189| | explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) 190| 0| : SmallPtrSetIteratorImpl(BP, E) {} 191| | 192| | // Most methods provided by baseclass. 193| | 194| 0| const PtrTy operator*() const { 195| 0| assert(Bucket < End); 196| 0| return PtrTraits::getFromVoidPointer(const_cast(*Bucket)); 197| 0| } 198| | 199| 0| inline SmallPtrSetIterator& operator++() { // Preincrement 200| 0| ++Bucket; 201| 0| AdvanceIfNotValid(); 202| 0| return *this; 203| 0| } 204| | 205| | SmallPtrSetIterator operator++(int) { // Postincrement 206| | SmallPtrSetIterator tmp = *this; ++*this; return tmp; 207| | } 208| |}; 209| | 210| |/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next 211| |/// power of two (which means N itself if N is already a power of two). 212| |template 213| |struct RoundUpToPowerOfTwo; 214| | 215| |/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a 216| |/// helper template used to implement RoundUpToPowerOfTwo. 217| |template 218| |struct RoundUpToPowerOfTwoH { 219| | enum { Val = N }; 220| |}; 221| |template 222| |struct RoundUpToPowerOfTwoH { 223| | enum { 224| | // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets 225| | // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. 226| | Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val 227| | }; 228| |}; 229| | 230| |template 231| |struct RoundUpToPowerOfTwo { 232| | enum { Val = RoundUpToPowerOfTwoH::Val }; 233| |}; 234| | 235| | 236| |/// \brief A templated base class for \c SmallPtrSet which provides the 237| |/// typesafe interface that is common across all small sizes. 238| |/// 239| |/// This is particularly useful for passing around between interface boundaries 240| |/// to avoid encoding a particular small size in the interface boundary. 241| |template 242| |class SmallPtrSetImpl : public SmallPtrSetImplBase { 243| | typedef PointerLikeTypeTraits PtrTraits; 244| | 245| | SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; 246| |protected: 247| | // Constructors that forward to the base. 248| | SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) 249| 0| : SmallPtrSetImplBase(SmallStorage, that) {} 250| | SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, 251| | SmallPtrSetImpl &&that) 252| | : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} 253| | explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) 254| 0| : SmallPtrSetImplBase(SmallStorage, SmallSize) {} 255| | 256| |public: 257| | typedef SmallPtrSetIterator iterator; 258| | typedef SmallPtrSetIterator const_iterator; 259| | 260| | /// Inserts Ptr if and only if there is no element in the container equal to 261| | /// Ptr. The bool component of the returned pair is true if and only if the 262| | /// insertion takes place, and the iterator component of the pair points to 263| | /// the element equal to Ptr. 264| | std::pair insert(PtrType Ptr) { 265| | auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); 266| | return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); 267| | } 268| | 269| | /// erase - If the set contains the specified pointer, remove it and return 270| | /// true, otherwise return false. 271| | bool erase(PtrType Ptr) { 272| | return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); 273| | } 274| | 275| | /// count - Return 1 if the specified pointer is in the set, 0 otherwise. 276| | size_type count(PtrType Ptr) const { 277| | return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; 278| | } 279| | 280| | template 281| | void insert(IterT I, IterT E) { 282| | for (; I != E; ++I) 283| | insert(*I); 284| | } 285| | 286| 0| inline iterator begin() const { 287| 0| return iterator(CurArray, CurArray+CurArraySize); 288| 0| } 289| 0| inline iterator end() const { 290| 0| return iterator(CurArray+CurArraySize, CurArray+CurArraySize); 291| 0| } 292| |}; 293| | 294| |/// SmallPtrSet - This class implements a set which is optimized for holding 295| |/// SmallSize or less elements. This internally rounds up SmallSize to the next 296| |/// power of two if it is not already a power of two. See the comments above 297| |/// SmallPtrSetImplBase for details of the algorithm. 298| |template 299| |class SmallPtrSet : public SmallPtrSetImpl { 300| | typedef SmallPtrSetImpl BaseT; 301| | 302| | // Make sure that SmallSize is a power of two, round up if not. 303| | enum { SmallSizePowTwo = RoundUpToPowerOfTwo::Val }; 304| | /// SmallStorage - Fixed size storage used in 'small mode'. 305| | const void *SmallStorage[SmallSizePowTwo]; 306| |public: 307| 0| SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} 308| 0| SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} 309| | SmallPtrSet(SmallPtrSet &&that) 310| | : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} 311| | 312| | template 313| | SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { 314| | this->insert(I, E); 315| | } 316| | 317| | SmallPtrSet & 318| | operator=(const SmallPtrSet &RHS) { 319| | if (&RHS != this) 320| | this->CopyFrom(RHS); 321| | return *this; 322| | } 323| | 324| | SmallPtrSet& 325| | operator=(SmallPtrSet &&RHS) { 326| | if (&RHS != this) 327| | this->MoveFrom(SmallSizePowTwo, std::move(RHS)); 328| | return *this; 329| | } 330| | 331| | /// swap - Swaps the elements of two sets. 332| | void swap(SmallPtrSet &RHS) { 333| | SmallPtrSetImplBase::swap(RHS); 334| | } 335| |}; 336| | 337| |} 338| | 339| |namespace std { 340| | /// Implement std::swap in terms of SmallPtrSet swap. 341| | template 342| | inline void swap(llvm::SmallPtrSet &LHS, llvm::SmallPtrSet &RHS) { 343| | LHS.swap(RHS); 344| | } 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallString.h: 1| |//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallString class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLSTRING_H 15| |#define LLVM_ADT_SMALLSTRING_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |namespace llvm { 21| | 22| |/// SmallString - A SmallString is just a SmallVector with methods and accessors 23| |/// that make it work better as a string (e.g. operator+ etc). 24| |template 25| |class SmallString : public SmallVector { 26| |public: 27| | /// Default ctor - Initialize to empty. 28| 0| SmallString() {} 29| | 30| | /// Initialize from a StringRef. 31| | SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} 32| | 33| | /// Initialize with a range. 34| | template 35| | SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} 36| | 37| | // Note that in order to add new overloads for append & assign, we have to 38| | // duplicate the inherited versions so as not to inadvertently hide them. 39| | 40| | /// @} 41| | /// @name String Assignment 42| | /// @{ 43| | 44| | /// Assign from a repeated element. 45| | void assign(size_t NumElts, char Elt) { 46| | this->SmallVectorImpl::assign(NumElts, Elt); 47| | } 48| | 49| | /// Assign from an iterator pair. 50| | template 51| | void assign(in_iter S, in_iter E) { 52| | this->clear(); 53| | SmallVectorImpl::append(S, E); 54| | } 55| | 56| | /// Assign from a StringRef. 57| | void assign(StringRef RHS) { 58| | this->clear(); 59| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 60| | } 61| | 62| | /// Assign from a SmallVector. 63| | void assign(const SmallVectorImpl &RHS) { 64| | this->clear(); 65| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 66| | } 67| | 68| | /// @} 69| | /// @name String Concatenation 70| | /// @{ 71| | 72| | /// Append from an iterator pair. 73| | template 74| 0| void append(in_iter S, in_iter E) { 75| 0| SmallVectorImpl::append(S, E); 76| 0| } 77| | 78| | void append(size_t NumInputs, char Elt) { 79| | SmallVectorImpl::append(NumInputs, Elt); 80| | } 81| | 82| | 83| | /// Append from a StringRef. 84| | void append(StringRef RHS) { 85| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 86| | } 87| | 88| | /// Append from a SmallVector. 89| | void append(const SmallVectorImpl &RHS) { 90| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 91| | } 92| | 93| | /// @} 94| | /// @name String Comparison 95| | /// @{ 96| | 97| | /// Check for string equality. This is more efficient than compare() when 98| | /// the relative ordering of inequal strings isn't needed. 99| | bool equals(StringRef RHS) const { 100| | return str().equals(RHS); 101| | } 102| | 103| | /// Check for string equality, ignoring case. 104| | bool equals_lower(StringRef RHS) const { 105| | return str().equals_lower(RHS); 106| | } 107| | 108| | /// Compare two strings; the result is -1, 0, or 1 if this string is 109| | /// lexicographically less than, equal to, or greater than the \p RHS. 110| | int compare(StringRef RHS) const { 111| | return str().compare(RHS); 112| | } 113| | 114| | /// compare_lower - Compare two strings, ignoring case. 115| | int compare_lower(StringRef RHS) const { 116| | return str().compare_lower(RHS); 117| | } 118| | 119| | /// compare_numeric - Compare two strings, treating sequences of digits as 120| | /// numbers. 121| | int compare_numeric(StringRef RHS) const { 122| | return str().compare_numeric(RHS); 123| | } 124| | 125| | /// @} 126| | /// @name String Predicates 127| | /// @{ 128| | 129| | /// startswith - Check if this string starts with the given \p Prefix. 130| | bool startswith(StringRef Prefix) const { 131| | return str().startswith(Prefix); 132| | } 133| | 134| | /// endswith - Check if this string ends with the given \p Suffix. 135| | bool endswith(StringRef Suffix) const { 136| | return str().endswith(Suffix); 137| | } 138| | 139| | /// @} 140| | /// @name String Searching 141| | /// @{ 142| | 143| | /// find - Search for the first character \p C in the string. 144| | /// 145| | /// \return - The index of the first occurrence of \p C, or npos if not 146| | /// found. 147| | size_t find(char C, size_t From = 0) const { 148| | return str().find(C, From); 149| | } 150| | 151| | /// Search for the first string \p Str in the string. 152| | /// 153| | /// \returns The index of the first occurrence of \p Str, or npos if not 154| | /// found. 155| | size_t find(StringRef Str, size_t From = 0) const { 156| | return str().find(Str, From); 157| | } 158| | 159| | /// Search for the last character \p C in the string. 160| | /// 161| | /// \returns The index of the last occurrence of \p C, or npos if not 162| | /// found. 163| | size_t rfind(char C, size_t From = StringRef::npos) const { 164| | return str().rfind(C, From); 165| | } 166| | 167| | /// Search for the last string \p Str in the string. 168| | /// 169| | /// \returns The index of the last occurrence of \p Str, or npos if not 170| | /// found. 171| | size_t rfind(StringRef Str) const { 172| | return str().rfind(Str); 173| | } 174| | 175| | /// Find the first character in the string that is \p C, or npos if not 176| | /// found. Same as find. 177| | size_t find_first_of(char C, size_t From = 0) const { 178| | return str().find_first_of(C, From); 179| | } 180| | 181| | /// Find the first character in the string that is in \p Chars, or npos if 182| | /// not found. 183| | /// 184| | /// Complexity: O(size() + Chars.size()) 185| | size_t find_first_of(StringRef Chars, size_t From = 0) const { 186| | return str().find_first_of(Chars, From); 187| | } 188| | 189| | /// Find the first character in the string that is not \p C or npos if not 190| | /// found. 191| | size_t find_first_not_of(char C, size_t From = 0) const { 192| | return str().find_first_not_of(C, From); 193| | } 194| | 195| | /// Find the first character in the string that is not in the string 196| | /// \p Chars, or npos if not found. 197| | /// 198| | /// Complexity: O(size() + Chars.size()) 199| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const { 200| | return str().find_first_not_of(Chars, From); 201| | } 202| | 203| | /// Find the last character in the string that is \p C, or npos if not 204| | /// found. 205| | size_t find_last_of(char C, size_t From = StringRef::npos) const { 206| | return str().find_last_of(C, From); 207| | } 208| | 209| | /// Find the last character in the string that is in \p C, or npos if not 210| | /// found. 211| | /// 212| | /// Complexity: O(size() + Chars.size()) 213| | size_t find_last_of( 214| | StringRef Chars, size_t From = StringRef::npos) const { 215| | return str().find_last_of(Chars, From); 216| | } 217| | 218| | /// @} 219| | /// @name Helpful Algorithms 220| | /// @{ 221| | 222| | /// Return the number of occurrences of \p C in the string. 223| | size_t count(char C) const { 224| | return str().count(C); 225| | } 226| | 227| | /// Return the number of non-overlapped occurrences of \p Str in the 228| | /// string. 229| | size_t count(StringRef Str) const { 230| | return str().count(Str); 231| | } 232| | 233| | /// @} 234| | /// @name Substring Operations 235| | /// @{ 236| | 237| | /// Return a reference to the substring from [Start, Start + N). 238| | /// 239| | /// \param Start The index of the starting character in the substring; if 240| | /// the index is npos or greater than the length of the string then the 241| | /// empty substring will be returned. 242| | /// 243| | /// \param N The number of characters to included in the substring. If \p N 244| | /// exceeds the number of characters remaining in the string, the string 245| | /// suffix (starting with \p Start) will be returned. 246| | StringRef substr(size_t Start, size_t N = StringRef::npos) const { 247| | return str().substr(Start, N); 248| | } 249| | 250| | /// Return a reference to the substring from [Start, End). 251| | /// 252| | /// \param Start The index of the starting character in the substring; if 253| | /// the index is npos or greater than the length of the string then the 254| | /// empty substring will be returned. 255| | /// 256| | /// \param End The index following the last character to include in the 257| | /// substring. If this is npos, or less than \p Start, or exceeds the 258| | /// number of characters remaining in the string, the string suffix 259| | /// (starting with \p Start) will be returned. 260| | StringRef slice(size_t Start, size_t End) const { 261| | return str().slice(Start, End); 262| | } 263| | 264| | // Extra methods. 265| | 266| | /// Explicit conversion to StringRef. 267| | StringRef str() const { return StringRef(this->begin(), this->size()); } 268| | 269| | // TODO: Make this const, if it's safe... 270| 0| const char* c_str() { 271| 0| this->push_back(0); 272| 0| this->pop_back(); 273| 0| return this->data(); 274| 0| } 275| | 276| | /// Implicit conversion to StringRef. 277| | operator StringRef() const { return str(); } 278| | 279| | // Extra operators. 280| | const SmallString &operator=(StringRef RHS) { 281| | this->clear(); 282| | return *this += RHS; 283| | } 284| | 285| | SmallString &operator+=(StringRef RHS) { 286| | this->append(RHS.begin(), RHS.end()); 287| | return *this; 288| | } 289| | SmallString &operator+=(char C) { 290| | this->push_back(C); 291| | return *this; 292| | } 293| |}; 294| | 295| |} 296| | 297| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallVector.h: 1| |//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLVECTOR_H 15| |#define LLVM_ADT_SMALLVECTOR_H 16| | 17| |#include "llvm/ADT/iterator_range.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/type_traits.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |namespace llvm { 32| | 33| |/// This is all the non-templated stuff common to all SmallVectors. 34| |class SmallVectorBase { 35| |protected: 36| | void *BeginX, *EndX, *CapacityX; 37| | 38| |protected: 39| | SmallVectorBase(void *FirstEl, size_t Size) 40| 0| : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} 41| | 42| | /// This is an implementation of the grow() method which only works 43| | /// on POD-like data types and is out of line to reduce code duplication. 44| | void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); 45| | 46| |public: 47| | /// This returns size()*sizeof(T). 48| | size_t size_in_bytes() const { 49| | return size_t((char*)EndX - (char*)BeginX); 50| | } 51| | 52| | /// capacity_in_bytes - This returns capacity()*sizeof(T). 53| | size_t capacity_in_bytes() const { 54| | return size_t((char*)CapacityX - (char*)BeginX); 55| | } 56| | 57| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } 58| |}; 59| | 60| |template struct SmallVectorStorage; 61| | 62| |/// This is the part of SmallVectorTemplateBase which does not depend on whether 63| |/// the type T is a POD. The extra dummy template argument is used by ArrayRef 64| |/// to avoid unnecessarily requiring T to be complete. 65| |template 66| |class SmallVectorTemplateCommon : public SmallVectorBase { 67| |private: 68| | template friend struct SmallVectorStorage; 69| | 70| | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 71| | // don't want it to be automatically run, so we need to represent the space as 72| | // something else. Use an array of char of sufficient alignment. 73| | typedef llvm::AlignedCharArrayUnion U; 74| | U FirstEl; 75| | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 76| | 77| |protected: 78| 0| SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} 79| | 80| 0| void grow_pod(size_t MinSizeInBytes, size_t TSize) { 81| 0| SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); 82| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE8grow_podEmm ------------------ 83| | 84| | /// Return true if this is a smallvector which has not had dynamic 85| | /// memory allocated for it. 86| 0| bool isSmall() const { 87| 0| return BeginX == static_cast(&FirstEl); 88| 0| } 89| | 90| | /// Put this vector in a state of being small. 91| | void resetToSmall() { 92| | BeginX = EndX = CapacityX = &FirstEl; 93| | } 94| | 95| 0| void setEnd(T *P) { this->EndX = P; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE6setEndEPc ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE6setEndEPh ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE6setEndEPS1_ ------------------ 96| |public: 97| | typedef size_t size_type; 98| | typedef ptrdiff_t difference_type; 99| | typedef T value_type; 100| | typedef T *iterator; 101| | typedef const T *const_iterator; 102| | 103| | typedef std::reverse_iterator const_reverse_iterator; 104| | typedef std::reverse_iterator reverse_iterator; 105| | 106| | typedef T &reference; 107| | typedef const T &const_reference; 108| | typedef T *pointer; 109| | typedef const T *const_pointer; 110| | 111| | // forward iterator creation methods. 112| 0| iterator begin() { return (iterator)this->BeginX; } 113| 0| const_iterator begin() const { return (const_iterator)this->BeginX; } 114| 0| iterator end() { return (iterator)this->EndX; } 115| 0| const_iterator end() const { return (const_iterator)this->EndX; } 116| |protected: 117| | iterator capacity_ptr() { return (iterator)this->CapacityX; } 118| | const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} 119| |public: 120| | 121| | // reverse iterator creation methods. 122| | reverse_iterator rbegin() { return reverse_iterator(end()); } 123| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 124| | reverse_iterator rend() { return reverse_iterator(begin()); } 125| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 126| | 127| 0| size_type size() const { return end()-begin(); } 128| | size_type max_size() const { return size_type(-1) / sizeof(T); } 129| | 130| | /// Return the total number of elements in the currently allocated buffer. 131| | size_t capacity() const { return capacity_ptr() - begin(); } 132| | 133| | /// Return a pointer to the vector's buffer, even if empty(). 134| 0| pointer data() { return pointer(begin()); } 135| | /// Return a pointer to the vector's buffer, even if empty(). 136| | const_pointer data() const { return const_pointer(begin()); } 137| | 138| | reference operator[](size_type idx) { 139| | assert(idx < size()); 140| | return begin()[idx]; 141| | } 142| | const_reference operator[](size_type idx) const { 143| | assert(idx < size()); 144| | return begin()[idx]; 145| | } 146| | 147| | reference front() { 148| | assert(!empty()); 149| | return begin()[0]; 150| | } 151| | const_reference front() const { 152| | assert(!empty()); 153| | return begin()[0]; 154| | } 155| | 156| | reference back() { 157| | assert(!empty()); 158| | return end()[-1]; 159| | } 160| | const_reference back() const { 161| | assert(!empty()); 162| | return end()[-1]; 163| | } 164| |}; 165| | 166| |/// SmallVectorTemplateBase - This is where we put method 167| |/// implementations that are designed to work with non-POD-like T's. 168| |template 169| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 170| |protected: 171| | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 172| | 173| | static void destroy_range(T *S, T *E) { 174| | while (S != E) { 175| | --E; 176| | E->~T(); 177| | } 178| | } 179| | 180| | /// Use move-assignment to move the range [I, E) onto the 181| | /// objects starting with "Dest". This is just 's 182| | /// std::move, but not all stdlibs actually provide that. 183| | template 184| | static It2 move(It1 I, It1 E, It2 Dest) { 185| | for (; I != E; ++I, ++Dest) 186| | *Dest = ::std::move(*I); 187| | return Dest; 188| | } 189| | 190| | /// Use move-assignment to move the range 191| | /// [I, E) onto the objects ending at "Dest", moving objects 192| | /// in reverse order. This is just 's 193| | /// std::move_backward, but not all stdlibs actually provide that. 194| | template 195| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 196| | while (I != E) 197| | *--Dest = ::std::move(*--E); 198| | return Dest; 199| | } 200| | 201| | /// Move the range [I, E) into the uninitialized memory starting with "Dest", 202| | /// constructing elements as needed. 203| | template 204| | static void uninitialized_move(It1 I, It1 E, It2 Dest) { 205| | for (; I != E; ++I, ++Dest) 206| | ::new ((void*) &*Dest) T(::std::move(*I)); 207| | } 208| | 209| | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", 210| | /// constructing elements as needed. 211| | template 212| | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 213| | std::uninitialized_copy(I, E, Dest); 214| | } 215| | 216| | /// Grow the allocated memory (without initializing new elements), doubling 217| | /// the size of the allocated memory. Guarantees space for at least one more 218| | /// element, or MinSize more elements if specified. 219| | void grow(size_t MinSize = 0); 220| | 221| |public: 222| 0| void push_back(const T &Elt) { 223| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 224| 0| this->grow(); 225| 0| ::new ((void*) this->end()) T(Elt); 226| 0| this->setEnd(this->end()+1); 227| 0| } 228| | 229| | void push_back(T &&Elt) { 230| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 231| | this->grow(); 232| | ::new ((void*) this->end()) T(::std::move(Elt)); 233| | this->setEnd(this->end()+1); 234| | } 235| | 236| | void pop_back() { 237| | this->setEnd(this->end()-1); 238| | this->end()->~T(); 239| | } 240| |}; 241| | 242| |// Define this out-of-line to dissuade the C++ compiler from inlining it. 243| |template 244| |void SmallVectorTemplateBase::grow(size_t MinSize) { 245| | size_t CurCapacity = this->capacity(); 246| | size_t CurSize = this->size(); 247| | // Always grow, even from zero. 248| | size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); 249| | if (NewCapacity < MinSize) 250| | NewCapacity = MinSize; 251| | T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); 252| | 253| | // Move the elements over. 254| | this->uninitialized_move(this->begin(), this->end(), NewElts); 255| | 256| | // Destroy the original elements. 257| | destroy_range(this->begin(), this->end()); 258| | 259| | // If this wasn't grown from the inline copy, deallocate the old space. 260| | if (!this->isSmall()) 261| | free(this->begin()); 262| | 263| | this->setEnd(NewElts+CurSize); 264| | this->BeginX = NewElts; 265| | this->CapacityX = this->begin()+NewCapacity; 266| |} 267| | 268| | 269| |/// SmallVectorTemplateBase - This is where we put method 270| |/// implementations that are designed to work with POD-like T's. 271| |template 272| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 273| |protected: 274| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 275| | 276| | // No need to do a destroy loop for POD's. 277| 0| static void destroy_range(T *, T *) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE13destroy_rangeEPcS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE13destroy_rangeEPhS2_ ------------------ 278| | 279| | /// Use move-assignment to move the range [I, E) onto the 280| | /// objects starting with "Dest". For PODs, this is just memcpy. 281| | template 282| | static It2 move(It1 I, It1 E, It2 Dest) { 283| | return ::std::copy(I, E, Dest); 284| | } 285| | 286| | /// Use move-assignment to move the range [I, E) onto the objects ending at 287| | /// "Dest", moving objects in reverse order. 288| | template 289| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 290| | return ::std::copy_backward(I, E, Dest); 291| | } 292| | 293| | /// Move the range [I, E) onto the uninitialized memory 294| | /// starting with "Dest", constructing elements into it as needed. 295| | template 296| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 297| 0| // Just do a copy. 298| 0| uninitialized_copy(I, E, Dest); 299| 0| } 300| | 301| | /// Copy the range [I, E) onto the uninitialized memory 302| | /// starting with "Dest", constructing elements into it as needed. 303| | template 304| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 305| 0| // Arbitrary iterator types; just use the basic implementation. 306| 0| std::uninitialized_copy(I, E, Dest); 307| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyINSt3__113move_iteratorIPhEES5_EEvT_S7_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIPKcPhEEvT_S6_T0_ ------------------ 308| | 309| | /// Copy the range [I, E) onto the uninitialized memory 310| | /// starting with "Dest", constructing elements into it as needed. 311| | template 312| | static void uninitialized_copy( 313| | T1 *I, T1 *E, T2 *Dest, 314| | typename std::enable_if::type, 315| 0| T2>::value>::type * = nullptr) { 316| 0| // Use memcpy for PODs iterated by pointers (which includes SmallVector 317| 0| // iterators): std::uninitialized_copy optimizes to memmove, but we can 318| 0| // use memcpy here. 319| 0| memcpy(Dest, I, (E-I)*sizeof(T)); 320| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIhhEEvPT_S4_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS7_12remove_constIS3_E4typeES5_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIKccEEvPT_S5_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS8_12remove_constIS4_E4typeES6_EE5valueEvE4typeE ------------------ 321| | 322| | /// Double the size of the allocated memory, guaranteeing space for at 323| | /// least one more element or MinSize if specified. 324| 0| void grow(size_t MinSize = 0) { 325| 0| this->grow_pod(MinSize*sizeof(T), sizeof(T)); 326| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE4growEm ------------------ 327| |public: 328| 0| void push_back(const T &Elt) { 329| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 330| 0| this->grow(); 331| 0| memcpy(this->end(), &Elt, sizeof(T)); 332| 0| this->setEnd(this->end()+1); 333| 0| } 334| | 335| 0| void pop_back() { 336| 0| this->setEnd(this->end()-1); 337| 0| } 338| |}; 339| | 340| | 341| |/// This class consists of common code factored out of the SmallVector class to 342| |/// reduce code duplication based on the SmallVector 'N' template parameter. 343| |template 344| |class SmallVectorImpl : public SmallVectorTemplateBase::value> { 345| | typedef SmallVectorTemplateBase::value > SuperClass; 346| | 347| | SmallVectorImpl(const SmallVectorImpl&) = delete; 348| |public: 349| | typedef typename SuperClass::iterator iterator; 350| | typedef typename SuperClass::size_type size_type; 351| | 352| |protected: 353| | // Default ctor - Initialize to empty. 354| | explicit SmallVectorImpl(unsigned N) 355| 0| : SmallVectorTemplateBase::value>(N*sizeof(T)) { 356| 0| } 357| | 358| |public: 359| 0| ~SmallVectorImpl() { 360| 0| // Destroy the constructed elements in the vector. 361| 0| this->destroy_range(this->begin(), this->end()); 362| 0| 363| 0| // If this wasn't grown from the inline copy, deallocate the old space. 364| 0| if (!this->isSmall()) 365| 0| free(this->begin()); 366| 0| } 367| | 368| | 369| | void clear() { 370| | this->destroy_range(this->begin(), this->end()); 371| | this->EndX = this->BeginX; 372| | } 373| | 374| | void resize(size_type N) { 375| | if (N < this->size()) { 376| | this->destroy_range(this->begin()+N, this->end()); 377| | this->setEnd(this->begin()+N); 378| | } else if (N > this->size()) { 379| | if (this->capacity() < N) 380| | this->grow(N); 381| | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) 382| | new (&*I) T(); 383| | this->setEnd(this->begin()+N); 384| | } 385| | } 386| | 387| | void resize(size_type N, const T &NV) { 388| | if (N < this->size()) { 389| | this->destroy_range(this->begin()+N, this->end()); 390| | this->setEnd(this->begin()+N); 391| | } else if (N > this->size()) { 392| | if (this->capacity() < N) 393| | this->grow(N); 394| | std::uninitialized_fill(this->end(), this->begin()+N, NV); 395| | this->setEnd(this->begin()+N); 396| | } 397| | } 398| | 399| | void reserve(size_type N) { 400| | if (this->capacity() < N) 401| | this->grow(N); 402| | } 403| | 404| | T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { 405| | T Result = ::std::move(this->back()); 406| | this->pop_back(); 407| | return Result; 408| | } 409| | 410| | void swap(SmallVectorImpl &RHS); 411| | 412| | /// Add the specified range to the end of the SmallVector. 413| | template 414| | void append(in_iter in_start, in_iter in_end) { 415| | size_type NumInputs = std::distance(in_start, in_end); 416| | // Grow allocated space if needed. 417| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 418| | this->grow(this->size()+NumInputs); 419| | 420| | // Copy the new elements over. 421| | this->uninitialized_copy(in_start, in_end, this->end()); 422| | this->setEnd(this->end() + NumInputs); 423| | } 424| | 425| | /// Add the specified range to the end of the SmallVector. 426| | void append(size_type NumInputs, const T &Elt) { 427| | // Grow allocated space if needed. 428| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 429| | this->grow(this->size()+NumInputs); 430| | 431| | // Copy the new elements over. 432| | std::uninitialized_fill_n(this->end(), NumInputs, Elt); 433| | this->setEnd(this->end() + NumInputs); 434| | } 435| | 436| | void append(std::initializer_list IL) { 437| | append(IL.begin(), IL.end()); 438| | } 439| | 440| | void assign(size_type NumElts, const T &Elt) { 441| | clear(); 442| | if (this->capacity() < NumElts) 443| | this->grow(NumElts); 444| | this->setEnd(this->begin()+NumElts); 445| | std::uninitialized_fill(this->begin(), this->end(), Elt); 446| | } 447| | 448| | void assign(std::initializer_list IL) { 449| | clear(); 450| | append(IL); 451| | } 452| | 453| | iterator erase(iterator I) { 454| | assert(I >= this->begin() && "Iterator to erase is out of bounds."); 455| | assert(I < this->end() && "Erasing at past-the-end iterator."); 456| | 457| | iterator N = I; 458| | // Shift all elts down one. 459| | this->move(I+1, this->end(), I); 460| | // Drop the last elt. 461| | this->pop_back(); 462| | return(N); 463| | } 464| | 465| | iterator erase(iterator S, iterator E) { 466| | assert(S >= this->begin() && "Range to erase is out of bounds."); 467| | assert(S <= E && "Trying to erase invalid range."); 468| | assert(E <= this->end() && "Trying to erase past the end."); 469| | 470| | iterator N = S; 471| | // Shift all elts down. 472| | iterator I = this->move(E, this->end(), S); 473| | // Drop the last elts. 474| | this->destroy_range(I, this->end()); 475| | this->setEnd(I); 476| | return(N); 477| | } 478| | 479| | iterator insert(iterator I, T &&Elt) { 480| | if (I == this->end()) { // Important special case for empty vector. 481| | this->push_back(::std::move(Elt)); 482| | return this->end()-1; 483| | } 484| | 485| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 486| | assert(I <= this->end() && "Inserting past the end of the vector."); 487| | 488| | if (this->EndX >= this->CapacityX) { 489| | size_t EltNo = I-this->begin(); 490| | this->grow(); 491| | I = this->begin()+EltNo; 492| | } 493| | 494| | ::new ((void*) this->end()) T(::std::move(this->back())); 495| | // Push everything else over. 496| | this->move_backward(I, this->end()-1, this->end()); 497| | this->setEnd(this->end()+1); 498| | 499| | // If we just moved the element we're inserting, be sure to update 500| | // the reference. 501| | T *EltPtr = &Elt; 502| | if (I <= EltPtr && EltPtr < this->EndX) 503| | ++EltPtr; 504| | 505| | *I = ::std::move(*EltPtr); 506| | return I; 507| | } 508| | 509| | iterator insert(iterator I, const T &Elt) { 510| | if (I == this->end()) { // Important special case for empty vector. 511| | this->push_back(Elt); 512| | return this->end()-1; 513| | } 514| | 515| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 516| | assert(I <= this->end() && "Inserting past the end of the vector."); 517| | 518| | if (this->EndX >= this->CapacityX) { 519| | size_t EltNo = I-this->begin(); 520| | this->grow(); 521| | I = this->begin()+EltNo; 522| | } 523| | ::new ((void*) this->end()) T(std::move(this->back())); 524| | // Push everything else over. 525| | this->move_backward(I, this->end()-1, this->end()); 526| | this->setEnd(this->end()+1); 527| | 528| | // If we just moved the element we're inserting, be sure to update 529| | // the reference. 530| | const T *EltPtr = &Elt; 531| | if (I <= EltPtr && EltPtr < this->EndX) 532| | ++EltPtr; 533| | 534| | *I = *EltPtr; 535| | return I; 536| | } 537| | 538| | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 539| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 540| | size_t InsertElt = I - this->begin(); 541| | 542| | if (I == this->end()) { // Important special case for empty vector. 543| | append(NumToInsert, Elt); 544| | return this->begin()+InsertElt; 545| | } 546| | 547| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 548| | assert(I <= this->end() && "Inserting past the end of the vector."); 549| | 550| | // Ensure there is enough space. 551| | reserve(this->size() + NumToInsert); 552| | 553| | // Uninvalidate the iterator. 554| | I = this->begin()+InsertElt; 555| | 556| | // If there are more elements between the insertion point and the end of the 557| | // range than there are being inserted, we can use a simple approach to 558| | // insertion. Since we already reserved space, we know that this won't 559| | // reallocate the vector. 560| | if (size_t(this->end()-I) >= NumToInsert) { 561| | T *OldEnd = this->end(); 562| | append(std::move_iterator(this->end() - NumToInsert), 563| | std::move_iterator(this->end())); 564| | 565| | // Copy the existing elements that get replaced. 566| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 567| | 568| | std::fill_n(I, NumToInsert, Elt); 569| | return I; 570| | } 571| | 572| | // Otherwise, we're inserting more elements than exist already, and we're 573| | // not inserting at the end. 574| | 575| | // Move over the elements that we're about to overwrite. 576| | T *OldEnd = this->end(); 577| | this->setEnd(this->end() + NumToInsert); 578| | size_t NumOverwritten = OldEnd-I; 579| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 580| | 581| | // Replace the overwritten part. 582| | std::fill_n(I, NumOverwritten, Elt); 583| | 584| | // Insert the non-overwritten middle part. 585| | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 586| | return I; 587| | } 588| | 589| | template 590| | iterator insert(iterator I, ItTy From, ItTy To) { 591| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 592| | size_t InsertElt = I - this->begin(); 593| | 594| | if (I == this->end()) { // Important special case for empty vector. 595| | append(From, To); 596| | return this->begin()+InsertElt; 597| | } 598| | 599| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 600| | assert(I <= this->end() && "Inserting past the end of the vector."); 601| | 602| | size_t NumToInsert = std::distance(From, To); 603| | 604| | // Ensure there is enough space. 605| | reserve(this->size() + NumToInsert); 606| | 607| | // Uninvalidate the iterator. 608| | I = this->begin()+InsertElt; 609| | 610| | // If there are more elements between the insertion point and the end of the 611| | // range than there are being inserted, we can use a simple approach to 612| | // insertion. Since we already reserved space, we know that this won't 613| | // reallocate the vector. 614| | if (size_t(this->end()-I) >= NumToInsert) { 615| | T *OldEnd = this->end(); 616| | append(std::move_iterator(this->end() - NumToInsert), 617| | std::move_iterator(this->end())); 618| | 619| | // Copy the existing elements that get replaced. 620| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 621| | 622| | std::copy(From, To, I); 623| | return I; 624| | } 625| | 626| | // Otherwise, we're inserting more elements than exist already, and we're 627| | // not inserting at the end. 628| | 629| | // Move over the elements that we're about to overwrite. 630| | T *OldEnd = this->end(); 631| | this->setEnd(this->end() + NumToInsert); 632| | size_t NumOverwritten = OldEnd-I; 633| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 634| | 635| | // Replace the overwritten part. 636| | for (T *J = I; NumOverwritten > 0; --NumOverwritten) { 637| | *J = *From; 638| | ++J; ++From; 639| | } 640| | 641| | // Insert the non-overwritten middle part. 642| | this->uninitialized_copy(From, To, OldEnd); 643| | return I; 644| | } 645| | 646| | void insert(iterator I, std::initializer_list IL) { 647| | insert(I, IL.begin(), IL.end()); 648| | } 649| | 650| | template void emplace_back(ArgTypes &&... Args) { 651| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 652| | this->grow(); 653| | ::new ((void *)this->end()) T(std::forward(Args)...); 654| | this->setEnd(this->end() + 1); 655| | } 656| | 657| | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 658| | 659| | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); 660| | 661| | bool operator==(const SmallVectorImpl &RHS) const { 662| | if (this->size() != RHS.size()) return false; 663| | return std::equal(this->begin(), this->end(), RHS.begin()); 664| | } 665| | bool operator!=(const SmallVectorImpl &RHS) const { 666| | return !(*this == RHS); 667| | } 668| | 669| | bool operator<(const SmallVectorImpl &RHS) const { 670| | return std::lexicographical_compare(this->begin(), this->end(), 671| | RHS.begin(), RHS.end()); 672| | } 673| | 674| | /// Set the array size to \p N, which the current array must have enough 675| | /// capacity for. 676| | /// 677| | /// This does not construct or destroy any elements in the vector. 678| | /// 679| | /// Clients can use this in conjunction with capacity() to write past the end 680| | /// of the buffer when they know that more elements are available, and only 681| | /// update the size later. This avoids the cost of value initializing elements 682| | /// which will only be overwritten. 683| | void set_size(size_type N) { 684| | assert(N <= this->capacity()); 685| | this->setEnd(this->begin() + N); 686| | } 687| |}; 688| | 689| | 690| |template 691| |void SmallVectorImpl::swap(SmallVectorImpl &RHS) { 692| | if (this == &RHS) return; 693| | 694| | // We can only avoid copying elements if neither vector is small. 695| | if (!this->isSmall() && !RHS.isSmall()) { 696| | std::swap(this->BeginX, RHS.BeginX); 697| | std::swap(this->EndX, RHS.EndX); 698| | std::swap(this->CapacityX, RHS.CapacityX); 699| | return; 700| | } 701| | if (RHS.size() > this->capacity()) 702| | this->grow(RHS.size()); 703| | if (this->size() > RHS.capacity()) 704| | RHS.grow(this->size()); 705| | 706| | // Swap the shared elements. 707| | size_t NumShared = this->size(); 708| | if (NumShared > RHS.size()) NumShared = RHS.size(); 709| | for (size_type i = 0; i != NumShared; ++i) 710| | std::swap((*this)[i], RHS[i]); 711| | 712| | // Copy over the extra elts. 713| | if (this->size() > RHS.size()) { 714| | size_t EltDiff = this->size() - RHS.size(); 715| | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 716| | RHS.setEnd(RHS.end()+EltDiff); 717| | this->destroy_range(this->begin()+NumShared, this->end()); 718| | this->setEnd(this->begin()+NumShared); 719| | } else if (RHS.size() > this->size()) { 720| | size_t EltDiff = RHS.size() - this->size(); 721| | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 722| | this->setEnd(this->end() + EltDiff); 723| | this->destroy_range(RHS.begin()+NumShared, RHS.end()); 724| | RHS.setEnd(RHS.begin()+NumShared); 725| | } 726| |} 727| | 728| |template 729| |SmallVectorImpl &SmallVectorImpl:: 730| | operator=(const SmallVectorImpl &RHS) { 731| | // Avoid self-assignment. 732| | if (this == &RHS) return *this; 733| | 734| | // If we already have sufficient space, assign the common elements, then 735| | // destroy any excess. 736| | size_t RHSSize = RHS.size(); 737| | size_t CurSize = this->size(); 738| | if (CurSize >= RHSSize) { 739| | // Assign common elements. 740| | iterator NewEnd; 741| | if (RHSSize) 742| | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 743| | else 744| | NewEnd = this->begin(); 745| | 746| | // Destroy excess elements. 747| | this->destroy_range(NewEnd, this->end()); 748| | 749| | // Trim. 750| | this->setEnd(NewEnd); 751| | return *this; 752| | } 753| | 754| | // If we have to grow to have enough elements, destroy the current elements. 755| | // This allows us to avoid copying them during the grow. 756| | // FIXME: don't do this if they're efficiently moveable. 757| | if (this->capacity() < RHSSize) { 758| | // Destroy current elements. 759| | this->destroy_range(this->begin(), this->end()); 760| | this->setEnd(this->begin()); 761| | CurSize = 0; 762| | this->grow(RHSSize); 763| | } else if (CurSize) { 764| | // Otherwise, use assignment for the already-constructed elements. 765| | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 766| | } 767| | 768| | // Copy construct the new elements in place. 769| | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 770| | this->begin()+CurSize); 771| | 772| | // Set end. 773| | this->setEnd(this->begin()+RHSSize); 774| | return *this; 775| |} 776| | 777| |template 778| |SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { 779| | // Avoid self-assignment. 780| | if (this == &RHS) return *this; 781| | 782| | // If the RHS isn't small, clear this vector and then steal its buffer. 783| | if (!RHS.isSmall()) { 784| | this->destroy_range(this->begin(), this->end()); 785| | if (!this->isSmall()) free(this->begin()); 786| | this->BeginX = RHS.BeginX; 787| | this->EndX = RHS.EndX; 788| | this->CapacityX = RHS.CapacityX; 789| | RHS.resetToSmall(); 790| | return *this; 791| | } 792| | 793| | // If we already have sufficient space, assign the common elements, then 794| | // destroy any excess. 795| | size_t RHSSize = RHS.size(); 796| | size_t CurSize = this->size(); 797| | if (CurSize >= RHSSize) { 798| | // Assign common elements. 799| | iterator NewEnd = this->begin(); 800| | if (RHSSize) 801| | NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); 802| | 803| | // Destroy excess elements and trim the bounds. 804| | this->destroy_range(NewEnd, this->end()); 805| | this->setEnd(NewEnd); 806| | 807| | // Clear the RHS. 808| | RHS.clear(); 809| | 810| | return *this; 811| | } 812| | 813| | // If we have to grow to have enough elements, destroy the current elements. 814| | // This allows us to avoid copying them during the grow. 815| | // FIXME: this may not actually make any sense if we can efficiently move 816| | // elements. 817| | if (this->capacity() < RHSSize) { 818| | // Destroy current elements. 819| | this->destroy_range(this->begin(), this->end()); 820| | this->setEnd(this->begin()); 821| | CurSize = 0; 822| | this->grow(RHSSize); 823| | } else if (CurSize) { 824| | // Otherwise, use assignment for the already-constructed elements. 825| | this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); 826| | } 827| | 828| | // Move-construct the new elements in place. 829| | this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), 830| | this->begin()+CurSize); 831| | 832| | // Set end. 833| | this->setEnd(this->begin()+RHSSize); 834| | 835| | RHS.clear(); 836| | return *this; 837| |} 838| | 839| |/// Storage for the SmallVector elements which aren't contained in 840| |/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' 841| |/// element is in the base class. This is specialized for the N=1 and N=0 cases 842| |/// to avoid allocating unnecessary storage. 843| |template 844| |struct SmallVectorStorage { 845| | typename SmallVectorTemplateCommon::U InlineElts[N - 1]; 846| |}; 847| |template struct SmallVectorStorage {}; 848| |template struct SmallVectorStorage {}; 849| | 850| |/// This is a 'vector' (really, a variable-sized array), optimized 851| |/// for the case when the array is small. It contains some number of elements 852| |/// in-place, which allows it to avoid heap allocation when the actual number of 853| |/// elements is below that threshold. This allows normal "small" cases to be 854| |/// fast without losing generality for large inputs. 855| |/// 856| |/// Note that this does not attempt to be exception safe. 857| |/// 858| |template 859| |class SmallVector : public SmallVectorImpl { 860| | /// Inline space for elements which aren't stored in the base class. 861| | SmallVectorStorage Storage; 862| |public: 863| 0| SmallVector() : SmallVectorImpl(N) { 864| 0| } 865| | 866| | explicit SmallVector(size_t Size, const T &Value = T()) 867| | : SmallVectorImpl(N) { 868| | this->assign(Size, Value); 869| | } 870| | 871| | template 872| | SmallVector(ItTy S, ItTy E) : SmallVectorImpl(N) { 873| | this->append(S, E); 874| | } 875| | 876| | template 877| | explicit SmallVector(const llvm::iterator_range R) 878| | : SmallVectorImpl(N) { 879| | this->append(R.begin(), R.end()); 880| | } 881| | 882| | SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { 883| | this->assign(IL); 884| | } 885| | 886| | SmallVector(const SmallVector &RHS) : SmallVectorImpl(N) { 887| | if (!RHS.empty()) 888| | SmallVectorImpl::operator=(RHS); 889| | } 890| | 891| | const SmallVector &operator=(const SmallVector &RHS) { 892| | SmallVectorImpl::operator=(RHS); 893| | return *this; 894| | } 895| | 896| | SmallVector(SmallVector &&RHS) : SmallVectorImpl(N) { 897| | if (!RHS.empty()) 898| | SmallVectorImpl::operator=(::std::move(RHS)); 899| | } 900| | 901| | const SmallVector &operator=(SmallVector &&RHS) { 902| | SmallVectorImpl::operator=(::std::move(RHS)); 903| | return *this; 904| | } 905| | 906| | SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { 907| | if (!RHS.empty()) 908| | SmallVectorImpl::operator=(::std::move(RHS)); 909| | } 910| | 911| | const SmallVector &operator=(SmallVectorImpl &&RHS) { 912| | SmallVectorImpl::operator=(::std::move(RHS)); 913| | return *this; 914| | } 915| | 916| | const SmallVector &operator=(std::initializer_list IL) { 917| | this->assign(IL); 918| | return *this; 919| | } 920| |}; 921| | 922| |template 923| |static inline size_t capacity_in_bytes(const SmallVector &X) { 924| | return X.capacity_in_bytes(); 925| |} 926| | 927| |} // End llvm namespace 928| | 929| |namespace std { 930| | /// Implement std::swap in terms of SmallVector swap. 931| | template 932| | inline void 933| | swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { 934| | LHS.swap(RHS); 935| | } 936| | 937| | /// Implement std::swap in terms of SmallVector swap. 938| | template 939| | inline void 940| | swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { 941| | LHS.swap(RHS); 942| | } 943| |} 944| | 945| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringMap.h: 1| |//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGMAP_H 15| |#define LLVM_ADT_STRINGMAP_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/Allocator.h" 19| |#include 20| |#include 21| | 22| |namespace llvm { 23| | template 24| | class StringMapConstIterator; 25| | template 26| | class StringMapIterator; 27| | template 28| | class StringMapEntry; 29| | 30| |/// StringMapEntryBase - Shared base class of StringMapEntry instances. 31| |class StringMapEntryBase { 32| | unsigned StrLen; 33| |public: 34| 0| explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 35| | 36| | unsigned getKeyLength() const { return StrLen; } 37| |}; 38| | 39| |/// StringMapImpl - This is the base class of StringMap that is shared among 40| |/// all of its instantiations. 41| |class StringMapImpl { 42| |protected: 43| | // Array of NumBuckets pointers to entries, null pointers are holes. 44| | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 45| | // by an array of the actual hash values as unsigned integers. 46| | StringMapEntryBase **TheTable; 47| | unsigned NumBuckets; 48| | unsigned NumItems; 49| | unsigned NumTombstones; 50| | unsigned ItemSize; 51| |protected: 52| | explicit StringMapImpl(unsigned itemSize) 53| | : TheTable(nullptr), 54| | // Initialize the map with zero buckets to allocation. 55| 0| NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 56| | StringMapImpl(StringMapImpl &&RHS) 57| | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 58| | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 59| 0| ItemSize(RHS.ItemSize) { 60| 0| RHS.TheTable = nullptr; 61| 0| RHS.NumBuckets = 0; 62| 0| RHS.NumItems = 0; 63| 0| RHS.NumTombstones = 0; 64| 0| } 65| | 66| | StringMapImpl(unsigned InitSize, unsigned ItemSize); 67| | unsigned RehashTable(unsigned BucketNo = 0); 68| | 69| | /// LookupBucketFor - Look up the bucket that the specified string should end 70| | /// up in. If it already exists as a key in the map, the Item pointer for the 71| | /// specified bucket will be non-null. Otherwise, it will be null. In either 72| | /// case, the FullHashValue field of the bucket will be set to the hash value 73| | /// of the string. 74| | unsigned LookupBucketFor(StringRef Key); 75| | 76| | /// FindKey - Look up the bucket that contains the specified key. If it exists 77| | /// in the map, return the bucket number of the key. Otherwise return -1. 78| | /// This does not modify the map. 79| | int FindKey(StringRef Key) const; 80| | 81| | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 82| | /// delete it. This aborts if the value isn't in the table. 83| | void RemoveKey(StringMapEntryBase *V); 84| | 85| | /// RemoveKey - Remove the StringMapEntry for the specified key from the 86| | /// table, returning it. If the key is not in the table, this returns null. 87| | StringMapEntryBase *RemoveKey(StringRef Key); 88| |private: 89| | void init(unsigned Size); 90| |public: 91| | static StringMapEntryBase *getTombstoneVal() { 92| | return (StringMapEntryBase*)-1; 93| | } 94| | 95| 0| unsigned getNumBuckets() const { return NumBuckets; } 96| 0| unsigned getNumItems() const { return NumItems; } 97| | 98| | bool empty() const { return NumItems == 0; } 99| 0| unsigned size() const { return NumItems; } 100| | 101| 0| void swap(StringMapImpl &Other) { 102| 0| std::swap(TheTable, Other.TheTable); 103| 0| std::swap(NumBuckets, Other.NumBuckets); 104| 0| std::swap(NumItems, Other.NumItems); 105| 0| std::swap(NumTombstones, Other.NumTombstones); 106| 0| } 107| |}; 108| | 109| |/// StringMapEntry - This is used to represent one value that is inserted into 110| |/// a StringMap. It contains the Value itself and the key: the string length 111| |/// and data. 112| |template 113| |class StringMapEntry : public StringMapEntryBase { 114| | StringMapEntry(StringMapEntry &E) = delete; 115| |public: 116| | ValueTy second; 117| | 118| | explicit StringMapEntry(unsigned strLen) 119| | : StringMapEntryBase(strLen), second() {} 120| | template 121| | StringMapEntry(unsigned strLen, InitTy &&V) 122| | : StringMapEntryBase(strLen), second(std::forward(V)) {} 123| | 124| | StringRef getKey() const { 125| | return StringRef(getKeyData(), getKeyLength()); 126| | } 127| | 128| | const ValueTy &getValue() const { return second; } 129| | ValueTy &getValue() { return second; } 130| | 131| | void setValue(const ValueTy &V) { second = V; } 132| | 133| | /// getKeyData - Return the start of the string data that is the key for this 134| | /// value. The string data is always stored immediately after the 135| | /// StringMapEntry object. 136| | const char *getKeyData() const {return reinterpret_cast(this+1);} 137| | 138| | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 139| | 140| | /// Create - Create a StringMapEntry for the specified key and default 141| | /// construct the value. 142| | template 143| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 144| | InitType &&InitVal) { 145| | unsigned KeyLength = Key.size(); 146| | 147| | // Allocate a new item with space for the string at the end and a null 148| | // terminator. 149| | unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ 150| | KeyLength+1; 151| | unsigned Alignment = alignOf(); 152| | 153| | StringMapEntry *NewItem = 154| | static_cast(Allocator.Allocate(AllocSize,Alignment)); 155| | 156| | // Default construct the value. 157| | new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); 158| | 159| | // Copy the string information. 160| | char *StrBuffer = const_cast(NewItem->getKeyData()); 161| | memcpy(StrBuffer, Key.data(), KeyLength); 162| | StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 163| | return NewItem; 164| | } 165| | 166| | template 167| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 168| | return Create(Key, Allocator, ValueTy()); 169| | } 170| | 171| | /// Create - Create a StringMapEntry with normal malloc/free. 172| | template 173| | static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { 174| | MallocAllocator A; 175| | return Create(Key, A, std::forward(InitVal)); 176| | } 177| | 178| | static StringMapEntry *Create(StringRef Key) { 179| | return Create(Key, ValueTy()); 180| | } 181| | 182| | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 183| | /// into a StringMapEntry, return the StringMapEntry itself. 184| | static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 185| | char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); 186| | return *reinterpret_cast(Ptr); 187| | } 188| | 189| | /// Destroy - Destroy this StringMapEntry, releasing memory back to the 190| | /// specified allocator. 191| | template 192| | void Destroy(AllocatorTy &Allocator) { 193| | // Free memory referenced by the item. 194| | unsigned AllocSize = 195| | static_cast(sizeof(StringMapEntry)) + getKeyLength() + 1; 196| | this->~StringMapEntry(); 197| | Allocator.Deallocate(static_cast(this), AllocSize); 198| | } 199| | 200| | /// Destroy this object, releasing memory back to the malloc allocator. 201| | void Destroy() { 202| | MallocAllocator A; 203| | Destroy(A); 204| | } 205| |}; 206| | 207| | 208| |/// StringMap - This is an unconventional map that is specialized for handling 209| |/// keys that are "strings", which are basically ranges of bytes. This does some 210| |/// funky memory allocation and hashing things to make it extremely efficient, 211| |/// storing the string data *after* the value in the map. 212| |template 213| |class StringMap : public StringMapImpl { 214| | AllocatorTy Allocator; 215| |public: 216| | typedef StringMapEntry MapEntryTy; 217| | 218| | StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} 219| | explicit StringMap(unsigned InitialSize) 220| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} 221| | 222| | explicit StringMap(AllocatorTy A) 223| | : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} 224| | 225| | StringMap(unsigned InitialSize, AllocatorTy A) 226| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), 227| | Allocator(A) {} 228| | 229| | StringMap(StringMap &&RHS) 230| | : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 231| | 232| | StringMap &operator=(StringMap RHS) { 233| | StringMapImpl::swap(RHS); 234| | std::swap(Allocator, RHS.Allocator); 235| | return *this; 236| | } 237| | 238| | // FIXME: Implement copy operations if/when they're needed. 239| | 240| | AllocatorTy &getAllocator() { return Allocator; } 241| | const AllocatorTy &getAllocator() const { return Allocator; } 242| | 243| | typedef const char* key_type; 244| | typedef ValueTy mapped_type; 245| | typedef StringMapEntry value_type; 246| | typedef size_t size_type; 247| | 248| | typedef StringMapConstIterator const_iterator; 249| | typedef StringMapIterator iterator; 250| | 251| | iterator begin() { 252| | return iterator(TheTable, NumBuckets == 0); 253| | } 254| | iterator end() { 255| | return iterator(TheTable+NumBuckets, true); 256| | } 257| | const_iterator begin() const { 258| | return const_iterator(TheTable, NumBuckets == 0); 259| | } 260| | const_iterator end() const { 261| | return const_iterator(TheTable+NumBuckets, true); 262| | } 263| | 264| | iterator find(StringRef Key) { 265| | int Bucket = FindKey(Key); 266| | if (Bucket == -1) return end(); 267| | return iterator(TheTable+Bucket, true); 268| | } 269| | 270| | const_iterator find(StringRef Key) const { 271| | int Bucket = FindKey(Key); 272| | if (Bucket == -1) return end(); 273| | return const_iterator(TheTable+Bucket, true); 274| | } 275| | 276| | /// lookup - Return the entry for the specified key, or a default 277| | /// constructed value if no such entry exists. 278| | ValueTy lookup(StringRef Key) const { 279| | const_iterator it = find(Key); 280| | if (it != end()) 281| | return it->second; 282| | return ValueTy(); 283| | } 284| | 285| | ValueTy &operator[](StringRef Key) { 286| | return insert(std::make_pair(Key, ValueTy())).first->second; 287| | } 288| | 289| | /// count - Return 1 if the element is in the map, 0 otherwise. 290| | size_type count(StringRef Key) const { 291| | return find(Key) == end() ? 0 : 1; 292| | } 293| | 294| | /// insert - Insert the specified key/value pair into the map. If the key 295| | /// already exists in the map, return false and ignore the request, otherwise 296| | /// insert it and return true. 297| | bool insert(MapEntryTy *KeyValue) { 298| | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 299| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 300| | if (Bucket && Bucket != getTombstoneVal()) 301| | return false; // Already exists in map. 302| | 303| | if (Bucket == getTombstoneVal()) 304| | --NumTombstones; 305| | Bucket = KeyValue; 306| | ++NumItems; 307| | assert(NumItems + NumTombstones <= NumBuckets); 308| | 309| | RehashTable(); 310| | return true; 311| | } 312| | 313| | /// insert - Inserts the specified key/value pair into the map if the key 314| | /// isn't already in the map. The bool component of the returned pair is true 315| | /// if and only if the insertion takes place, and the iterator component of 316| | /// the pair points to the element with key equivalent to the key of the pair. 317| | std::pair insert(std::pair KV) { 318| | unsigned BucketNo = LookupBucketFor(KV.first); 319| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 320| | if (Bucket && Bucket != getTombstoneVal()) 321| | return std::make_pair(iterator(TheTable + BucketNo, false), 322| | false); // Already exists in map. 323| | 324| | if (Bucket == getTombstoneVal()) 325| | --NumTombstones; 326| | Bucket = 327| | MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 328| | ++NumItems; 329| | assert(NumItems + NumTombstones <= NumBuckets); 330| | 331| | BucketNo = RehashTable(BucketNo); 332| | return std::make_pair(iterator(TheTable + BucketNo, false), true); 333| | } 334| | 335| | // clear - Empties out the StringMap 336| | void clear() { 337| | if (empty()) return; 338| | 339| | // Zap all values, resetting the keys back to non-present (not tombstone), 340| | // which is safe because we're removing all elements. 341| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 342| | StringMapEntryBase *&Bucket = TheTable[I]; 343| | if (Bucket && Bucket != getTombstoneVal()) { 344| | static_cast(Bucket)->Destroy(Allocator); 345| | } 346| | Bucket = nullptr; 347| | } 348| | 349| | NumItems = 0; 350| | NumTombstones = 0; 351| | } 352| | 353| | /// remove - Remove the specified key/value pair from the map, but do not 354| | /// erase it. This aborts if the key is not in the map. 355| | void remove(MapEntryTy *KeyValue) { 356| | RemoveKey(KeyValue); 357| | } 358| | 359| | void erase(iterator I) { 360| | MapEntryTy &V = *I; 361| | remove(&V); 362| | V.Destroy(Allocator); 363| | } 364| | 365| | bool erase(StringRef Key) { 366| | iterator I = find(Key); 367| | if (I == end()) return false; 368| | erase(I); 369| | return true; 370| | } 371| | 372| | ~StringMap() { 373| | // Delete all the elements in the map, but don't reset the elements 374| | // to default values. This is a copy of clear(), but avoids unnecessary 375| | // work not required in the destructor. 376| | if (!empty()) { 377| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 378| | StringMapEntryBase *Bucket = TheTable[I]; 379| | if (Bucket && Bucket != getTombstoneVal()) { 380| | static_cast(Bucket)->Destroy(Allocator); 381| | } 382| | } 383| | } 384| | free(TheTable); 385| | } 386| |}; 387| | 388| | 389| |template 390| |class StringMapConstIterator { 391| |protected: 392| | StringMapEntryBase **Ptr; 393| |public: 394| | typedef StringMapEntry value_type; 395| | 396| | StringMapConstIterator() : Ptr(nullptr) { } 397| | 398| | explicit StringMapConstIterator(StringMapEntryBase **Bucket, 399| | bool NoAdvance = false) 400| | : Ptr(Bucket) { 401| | if (!NoAdvance) AdvancePastEmptyBuckets(); 402| | } 403| | 404| | const value_type &operator*() const { 405| | return *static_cast*>(*Ptr); 406| | } 407| | const value_type *operator->() const { 408| | return static_cast*>(*Ptr); 409| | } 410| | 411| | bool operator==(const StringMapConstIterator &RHS) const { 412| | return Ptr == RHS.Ptr; 413| | } 414| | bool operator!=(const StringMapConstIterator &RHS) const { 415| | return Ptr != RHS.Ptr; 416| | } 417| | 418| | inline StringMapConstIterator& operator++() { // Preincrement 419| | ++Ptr; 420| | AdvancePastEmptyBuckets(); 421| | return *this; 422| | } 423| | StringMapConstIterator operator++(int) { // Postincrement 424| | StringMapConstIterator tmp = *this; ++*this; return tmp; 425| | } 426| | 427| |private: 428| | void AdvancePastEmptyBuckets() { 429| | while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 430| | ++Ptr; 431| | } 432| |}; 433| | 434| |template 435| |class StringMapIterator : public StringMapConstIterator { 436| |public: 437| | StringMapIterator() {} 438| | explicit StringMapIterator(StringMapEntryBase **Bucket, 439| | bool NoAdvance = false) 440| | : StringMapConstIterator(Bucket, NoAdvance) { 441| | } 442| | StringMapEntry &operator*() const { 443| | return *static_cast*>(*this->Ptr); 444| | } 445| | StringMapEntry *operator->() const { 446| | return static_cast*>(*this->Ptr); 447| | } 448| |}; 449| | 450| |} 451| | 452| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringRef.h: 1| |//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_STRINGREF_H 11| |#define LLVM_ADT_STRINGREF_H 12| | 13| |#include 14| |#include 15| |#include 16| |#include 17| |#include 18| |#include 19| | 20| |namespace llvm { 21| | template 22| | class SmallVectorImpl; 23| | class hash_code; 24| | class StringRef; 25| | 26| | /// Helper functions for StringRef::getAsInteger. 27| | bool getAsUnsignedInteger(StringRef Str, unsigned Radix, 28| | unsigned long long &Result); 29| | 30| | bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); 31| | 32| | /// StringRef - Represent a constant reference to a string, i.e. a character 33| | /// array and a length, which need not be null terminated. 34| | /// 35| | /// This class does not own the string data, it is expected to be used in 36| | /// situations where the character data resides in some other buffer, whose 37| | /// lifetime extends past that of the StringRef. For this reason, it is not in 38| | /// general safe to store a StringRef. 39| | class StringRef { 40| | public: 41| | typedef const char *iterator; 42| | typedef const char *const_iterator; 43| | static const size_t npos = ~size_t(0); 44| | typedef size_t size_type; 45| | 46| | private: 47| | /// The start of the string, in an external buffer. 48| | const char *Data; 49| | 50| | /// The length of the string. 51| | size_t Length; 52| | 53| | // Workaround memcmp issue with null pointers (undefined behavior) 54| | // by providing a specialized version 55| 0| static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { 56| 0| if (Length == 0) { return 0; } 57| 0| return ::memcmp(Lhs,Rhs,Length); 58| 0| } 59| | 60| | public: 61| | /// @name Constructors 62| | /// @{ 63| | 64| | /// Construct an empty string ref. 65| 0| /*implicit*/ StringRef() : Data(nullptr), Length(0) {} 66| | 67| | /// Construct a string ref from a cstring. 68| | /*implicit*/ StringRef(const char *Str) 69| 0| : Data(Str) { 70| 0| assert(Str && "StringRef cannot be built from a NULL argument"); 71| 0| Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior 72| 0| } 73| | 74| | /// Construct a string ref from a pointer and length. 75| | /*implicit*/ StringRef(const char *data, size_t length) 76| 0| : Data(data), Length(length) { 77| 0| assert((data || length == 0) && 78| 0| "StringRef cannot be built from a NULL argument with non-null length"); 79| 0| } 80| | 81| | /// Construct a string ref from an std::string. 82| | /*implicit*/ StringRef(const std::string &Str) 83| 0| : Data(Str.data()), Length(Str.length()) {} 84| | 85| | /// @} 86| | /// @name Iterators 87| | /// @{ 88| | 89| 0| iterator begin() const { return Data; } 90| | 91| 0| iterator end() const { return Data + Length; } 92| | 93| 0| const unsigned char *bytes_begin() const { 94| 0| return reinterpret_cast(begin()); 95| 0| } 96| 0| const unsigned char *bytes_end() const { 97| 0| return reinterpret_cast(end()); 98| 0| } 99| | 100| | /// @} 101| | /// @name String Operations 102| | /// @{ 103| | 104| | /// data - Get a pointer to the start of the string (which may not be null 105| | /// terminated). 106| 0| const char *data() const { return Data; } 107| | 108| | /// empty - Check if the string is empty. 109| | bool empty() const { return Length == 0; } 110| | 111| | /// size - Get the string size. 112| 0| size_t size() const { return Length; } 113| | 114| | /// front - Get the first character in the string. 115| | char front() const { 116| | assert(!empty()); 117| | return Data[0]; 118| | } 119| | 120| | /// back - Get the last character in the string. 121| | char back() const { 122| | assert(!empty()); 123| | return Data[Length-1]; 124| | } 125| | 126| | // copy - Allocate copy in Allocator and return StringRef to it. 127| | template StringRef copy(Allocator &A) const { 128| | char *S = A.template Allocate(Length); 129| | std::copy(begin(), end(), S); 130| | return StringRef(S, Length); 131| | } 132| | 133| | /// equals - Check for string equality, this is more efficient than 134| | /// compare() when the relative ordering of inequal strings isn't needed. 135| 0| bool equals(StringRef RHS) const { 136| 0| return (Length == RHS.Length && 137| 0| compareMemory(Data, RHS.Data, RHS.Length) == 0); 138| 0| } 139| | 140| | /// equals_lower - Check for string equality, ignoring case. 141| | bool equals_lower(StringRef RHS) const { 142| | return Length == RHS.Length && compare_lower(RHS) == 0; 143| | } 144| | 145| | /// compare - Compare two strings; the result is -1, 0, or 1 if this string 146| | /// is lexicographically less than, equal to, or greater than the \p RHS. 147| | int compare(StringRef RHS) const { 148| | // Check the prefix for a mismatch. 149| | if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) 150| | return Res < 0 ? -1 : 1; 151| | 152| | // Otherwise the prefixes match, so we only need to check the lengths. 153| | if (Length == RHS.Length) 154| | return 0; 155| | return Length < RHS.Length ? -1 : 1; 156| | } 157| | 158| | /// compare_lower - Compare two strings, ignoring case. 159| | int compare_lower(StringRef RHS) const; 160| | 161| | /// compare_numeric - Compare two strings, treating sequences of digits as 162| | /// numbers. 163| | int compare_numeric(StringRef RHS) const; 164| | 165| | /// \brief Determine the edit distance between this string and another 166| | /// string. 167| | /// 168| | /// \param Other the string to compare this string against. 169| | /// 170| | /// \param AllowReplacements whether to allow character 171| | /// replacements (change one character into another) as a single 172| | /// operation, rather than as two operations (an insertion and a 173| | /// removal). 174| | /// 175| | /// \param MaxEditDistance If non-zero, the maximum edit distance that 176| | /// this routine is allowed to compute. If the edit distance will exceed 177| | /// that maximum, returns \c MaxEditDistance+1. 178| | /// 179| | /// \returns the minimum number of character insertions, removals, 180| | /// or (if \p AllowReplacements is \c true) replacements needed to 181| | /// transform one of the given strings into the other. If zero, 182| | /// the strings are identical. 183| | unsigned edit_distance(StringRef Other, bool AllowReplacements = true, 184| | unsigned MaxEditDistance = 0) const; 185| | 186| | /// str - Get the contents as an std::string. 187| 0| std::string str() const { 188| 0| if (!Data) return std::string(); 189| 0| return std::string(Data, Length); 190| 0| } 191| | 192| | /// @} 193| | /// @name Operator Overloads 194| | /// @{ 195| | 196| | char operator[](size_t Index) const { 197| | assert(Index < Length && "Invalid index!"); 198| | return Data[Index]; 199| | } 200| | 201| | /// @} 202| | /// @name Type Conversions 203| | /// @{ 204| | 205| 0| operator std::string() const { 206| 0| return str(); 207| 0| } 208| | 209| | /// @} 210| | /// @name String Predicates 211| | /// @{ 212| | 213| | /// Check if this string starts with the given \p Prefix. 214| | bool startswith(StringRef Prefix) const { 215| | return Length >= Prefix.Length && 216| | compareMemory(Data, Prefix.Data, Prefix.Length) == 0; 217| | } 218| | 219| | /// Check if this string starts with the given \p Prefix, ignoring case. 220| | bool startswith_lower(StringRef Prefix) const; 221| | 222| | /// Check if this string ends with the given \p Suffix. 223| | bool endswith(StringRef Suffix) const { 224| | return Length >= Suffix.Length && 225| | compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 226| | } 227| | 228| | /// Check if this string ends with the given \p Suffix, ignoring case. 229| | bool endswith_lower(StringRef Suffix) const; 230| | 231| | /// @} 232| | /// @name String Searching 233| | /// @{ 234| | 235| | /// Search for the first character \p C in the string. 236| | /// 237| | /// \returns The index of the first occurrence of \p C, or npos if not 238| | /// found. 239| | size_t find(char C, size_t From = 0) const { 240| | for (size_t i = std::min(From, Length), e = Length; i != e; ++i) 241| | if (Data[i] == C) 242| | return i; 243| | return npos; 244| | } 245| | 246| | /// Search for the first string \p Str in the string. 247| | /// 248| | /// \returns The index of the first occurrence of \p Str, or npos if not 249| | /// found. 250| | size_t find(StringRef Str, size_t From = 0) const; 251| | 252| | /// Search for the last character \p C in the string. 253| | /// 254| | /// \returns The index of the last occurrence of \p C, or npos if not 255| | /// found. 256| | size_t rfind(char C, size_t From = npos) const { 257| | From = std::min(From, Length); 258| | size_t i = From; 259| | while (i != 0) { 260| | --i; 261| | if (Data[i] == C) 262| | return i; 263| | } 264| | return npos; 265| | } 266| | 267| | /// Search for the last string \p Str in the string. 268| | /// 269| | /// \returns The index of the last occurrence of \p Str, or npos if not 270| | /// found. 271| | size_t rfind(StringRef Str) const; 272| | 273| | /// Find the first character in the string that is \p C, or npos if not 274| | /// found. Same as find. 275| | size_t find_first_of(char C, size_t From = 0) const { 276| | return find(C, From); 277| | } 278| | 279| | /// Find the first character in the string that is in \p Chars, or npos if 280| | /// not found. 281| | /// 282| | /// Complexity: O(size() + Chars.size()) 283| | size_t find_first_of(StringRef Chars, size_t From = 0) const; 284| | 285| | /// Find the first character in the string that is not \p C or npos if not 286| | /// found. 287| | size_t find_first_not_of(char C, size_t From = 0) const; 288| | 289| | /// Find the first character in the string that is not in the string 290| | /// \p Chars, or npos if not found. 291| | /// 292| | /// Complexity: O(size() + Chars.size()) 293| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const; 294| | 295| | /// Find the last character in the string that is \p C, or npos if not 296| | /// found. 297| | size_t find_last_of(char C, size_t From = npos) const { 298| | return rfind(C, From); 299| | } 300| | 301| | /// Find the last character in the string that is in \p C, or npos if not 302| | /// found. 303| | /// 304| | /// Complexity: O(size() + Chars.size()) 305| | size_t find_last_of(StringRef Chars, size_t From = npos) const; 306| | 307| | /// Find the last character in the string that is not \p C, or npos if not 308| | /// found. 309| | size_t find_last_not_of(char C, size_t From = npos) const; 310| | 311| | /// Find the last character in the string that is not in \p Chars, or 312| | /// npos if not found. 313| | /// 314| | /// Complexity: O(size() + Chars.size()) 315| | size_t find_last_not_of(StringRef Chars, size_t From = npos) const; 316| | 317| | /// @} 318| | /// @name Helpful Algorithms 319| | /// @{ 320| | 321| | /// Return the number of occurrences of \p C in the string. 322| 0| size_t count(char C) const { 323| 0| size_t Count = 0; 324| 0| for (size_t i = 0, e = Length; i != e; ++i) 325| 0| if (Data[i] == C) 326| 0| ++Count; 327| 0| return Count; 328| 0| } 329| | 330| | /// Return the number of non-overlapped occurrences of \p Str in 331| | /// the string. 332| | size_t count(StringRef Str) const; 333| | 334| | /// Parse the current string as an integer of the specified radix. If 335| | /// \p Radix is specified as zero, this does radix autosensing using 336| | /// extended C rules: 0 is octal, 0x is hex, 0b is binary. 337| | /// 338| | /// If the string is invalid or if only a subset of the string is valid, 339| | /// this returns true to signify the error. The string is considered 340| | /// erroneous if empty or if it overflows T. 341| | template 342| | typename std::enable_if::is_signed, bool>::type 343| | getAsInteger(unsigned Radix, T &Result) const { 344| | long long LLVal; 345| | if (getAsSignedInteger(*this, Radix, LLVal) || 346| | static_cast(LLVal) != LLVal) 347| | return true; 348| | Result = LLVal; 349| | return false; 350| | } 351| | 352| | template 353| | typename std::enable_if::is_signed, bool>::type 354| | getAsInteger(unsigned Radix, T &Result) const { 355| | unsigned long long ULLVal; 356| | // The additional cast to unsigned long long is required to avoid the 357| | // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type 358| | // 'unsigned __int64' when instantiating getAsInteger with T = bool. 359| | if (getAsUnsignedInteger(*this, Radix, ULLVal) || 360| | static_cast(static_cast(ULLVal)) != ULLVal) 361| | return true; 362| | Result = ULLVal; 363| | return false; 364| | } 365| | 366| | /// @} 367| | /// @name String Operations 368| | /// @{ 369| | 370| | // Convert the given ASCII string to lowercase. 371| | std::string lower() const; 372| | 373| | /// Convert the given ASCII string to uppercase. 374| | std::string upper() const; 375| | 376| | /// @} 377| | /// @name Substring Operations 378| | /// @{ 379| | 380| | /// Return a reference to the substring from [Start, Start + N). 381| | /// 382| | /// \param Start The index of the starting character in the substring; if 383| | /// the index is npos or greater than the length of the string then the 384| | /// empty substring will be returned. 385| | /// 386| | /// \param N The number of characters to included in the substring. If N 387| | /// exceeds the number of characters remaining in the string, the string 388| | /// suffix (starting with \p Start) will be returned. 389| | StringRef substr(size_t Start, size_t N = npos) const { 390| | Start = std::min(Start, Length); 391| | return StringRef(Data + Start, std::min(N, Length - Start)); 392| | } 393| | 394| | /// Return a StringRef equal to 'this' but with the first \p N elements 395| | /// dropped. 396| | StringRef drop_front(size_t N = 1) const { 397| | assert(size() >= N && "Dropping more elements than exist"); 398| | return substr(N); 399| | } 400| | 401| | /// Return a StringRef equal to 'this' but with the last \p N elements 402| | /// dropped. 403| | StringRef drop_back(size_t N = 1) const { 404| | assert(size() >= N && "Dropping more elements than exist"); 405| | return substr(0, size()-N); 406| | } 407| | 408| | /// Return a reference to the substring from [Start, End). 409| | /// 410| | /// \param Start The index of the starting character in the substring; if 411| | /// the index is npos or greater than the length of the string then the 412| | /// empty substring will be returned. 413| | /// 414| | /// \param End The index following the last character to include in the 415| | /// substring. If this is npos, or less than \p Start, or exceeds the 416| | /// number of characters remaining in the string, the string suffix 417| | /// (starting with \p Start) will be returned. 418| | StringRef slice(size_t Start, size_t End) const { 419| | Start = std::min(Start, Length); 420| | End = std::min(std::max(Start, End), Length); 421| | return StringRef(Data + Start, End - Start); 422| | } 423| | 424| | /// Split into two substrings around the first occurrence of a separator 425| | /// character. 426| | /// 427| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 428| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 429| | /// maximal. If \p Separator is not in the string, then the result is a 430| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 431| | /// 432| | /// \param Separator The character to split on. 433| | /// \returns The split substrings. 434| | std::pair split(char Separator) const { 435| | size_t Idx = find(Separator); 436| | if (Idx == npos) 437| | return std::make_pair(*this, StringRef()); 438| | return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 439| | } 440| | 441| | /// Split into two substrings around the first occurrence of a separator 442| | /// string. 443| | /// 444| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 445| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 446| | /// maximal. If \p Separator is not in the string, then the result is a 447| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 448| | /// 449| | /// \param Separator - The string to split on. 450| | /// \return - The split substrings. 451| | std::pair split(StringRef Separator) const { 452| | size_t Idx = find(Separator); 453| | if (Idx == npos) 454| | return std::make_pair(*this, StringRef()); 455| | return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); 456| | } 457| | 458| | /// Split into substrings around the occurrences of a separator string. 459| | /// 460| | /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most 461| | /// \p MaxSplit splits are done and consequently <= \p MaxSplit 462| | /// elements are added to A. 463| | /// If \p KeepEmpty is false, empty strings are not added to \p A. They 464| | /// still count when considering \p MaxSplit 465| | /// An useful invariant is that 466| | /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true 467| | /// 468| | /// \param A - Where to put the substrings. 469| | /// \param Separator - The string to split on. 470| | /// \param MaxSplit - The maximum number of times the string is split. 471| | /// \param KeepEmpty - True if empty substring should be added. 472| | void split(SmallVectorImpl &A, 473| | StringRef Separator, int MaxSplit = -1, 474| | bool KeepEmpty = true) const; 475| | 476| | /// Split into two substrings around the last occurrence of a separator 477| | /// character. 478| | /// 479| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 480| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 481| | /// minimal. If \p Separator is not in the string, then the result is a 482| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 483| | /// 484| | /// \param Separator - The character to split on. 485| | /// \return - The split substrings. 486| 0| std::pair rsplit(char Separator) const { 487| 0| size_t Idx = rfind(Separator); 488| 0| if (Idx == npos) 489| 0| return std::make_pair(*this, StringRef()); 490| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 491| 0| } 492| | 493| | /// Return string with consecutive characters in \p Chars starting from 494| | /// the left removed. 495| | StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { 496| | return drop_front(std::min(Length, find_first_not_of(Chars))); 497| | } 498| | 499| | /// Return string with consecutive characters in \p Chars starting from 500| | /// the right removed. 501| | StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { 502| | return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); 503| | } 504| | 505| | /// Return string with consecutive characters in \p Chars starting from 506| | /// the left and right removed. 507| 0| StringRef trim(StringRef Chars = " \t\n\v\f\r") const { 508| 0| return ltrim(Chars).rtrim(Chars); 509| 0| } 510| | 511| | /// @} 512| | }; 513| | 514| | /// @name StringRef Comparison Operators 515| | /// @{ 516| | 517| 0| inline bool operator==(StringRef LHS, StringRef RHS) { 518| 0| return LHS.equals(RHS); 519| 0| } 520| | 521| | inline bool operator!=(StringRef LHS, StringRef RHS) { 522| | return !(LHS == RHS); 523| | } 524| | 525| | inline bool operator<(StringRef LHS, StringRef RHS) { 526| | return LHS.compare(RHS) == -1; 527| | } 528| | 529| 0| inline bool operator<=(StringRef LHS, StringRef RHS) { 530| 0| return LHS.compare(RHS) != 1; 531| 0| } 532| | 533| 0| inline bool operator>(StringRef LHS, StringRef RHS) { 534| 0| return LHS.compare(RHS) == 1; 535| 0| } 536| | 537| 0| inline bool operator>=(StringRef LHS, StringRef RHS) { 538| 0| return LHS.compare(RHS) != -1; 539| 0| } 540| | 541| | inline std::string &operator+=(std::string &buffer, StringRef string) { 542| | return buffer.append(string.data(), string.size()); 543| | } 544| | 545| | /// @} 546| | 547| | /// \brief Compute a hash_code for a StringRef. 548| | hash_code hash_value(StringRef S); 549| | 550| | // StringRefs can be treated like a POD type. 551| | template struct isPodLike; 552| | template <> struct isPodLike { static const bool value = true; }; 553| |} 554| | 555| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Twine.h: 1| |//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_TWINE_H 11| |#define LLVM_ADT_TWINE_H 12| | 13| |#include "llvm/ADT/StringRef.h" 14| |#include "llvm/Support/DataTypes.h" 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include 17| |#include 18| | 19| |namespace llvm { 20| | template 21| | class SmallVectorImpl; 22| | class StringRef; 23| | class raw_ostream; 24| | 25| | /// Twine - A lightweight data structure for efficiently representing the 26| | /// concatenation of temporary values as strings. 27| | /// 28| | /// A Twine is a kind of rope, it represents a concatenated string using a 29| | /// binary-tree, where the string is the preorder of the nodes. Since the 30| | /// Twine can be efficiently rendered into a buffer when its result is used, 31| | /// it avoids the cost of generating temporary values for intermediate string 32| | /// results -- particularly in cases when the Twine result is never 33| | /// required. By explicitly tracking the type of leaf nodes, we can also avoid 34| | /// the creation of temporary strings for conversions operations (such as 35| | /// appending an integer to a string). 36| | /// 37| | /// A Twine is not intended for use directly and should not be stored, its 38| | /// implementation relies on the ability to store pointers to temporary stack 39| | /// objects which may be deallocated at the end of a statement. Twines should 40| | /// only be used accepted as const references in arguments, when an API wishes 41| | /// to accept possibly-concatenated strings. 42| | /// 43| | /// Twines support a special 'null' value, which always concatenates to form 44| | /// itself, and renders as an empty string. This can be returned from APIs to 45| | /// effectively nullify any concatenations performed on the result. 46| | /// 47| | /// \b Implementation 48| | /// 49| | /// Given the nature of a Twine, it is not possible for the Twine's 50| | /// concatenation method to construct interior nodes; the result must be 51| | /// represented inside the returned value. For this reason a Twine object 52| | /// actually holds two values, the left- and right-hand sides of a 53| | /// concatenation. We also have nullary Twine objects, which are effectively 54| | /// sentinel values that represent empty strings. 55| | /// 56| | /// Thus, a Twine can effectively have zero, one, or two children. The \see 57| | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 58| | /// testing the number of children. 59| | /// 60| | /// We maintain a number of invariants on Twine objects (FIXME: Why): 61| | /// - Nullary twines are always represented with their Kind on the left-hand 62| | /// side, and the Empty kind on the right-hand side. 63| | /// - Unary twines are always represented with the value on the left-hand 64| | /// side, and the Empty kind on the right-hand side. 65| | /// - If a Twine has another Twine as a child, that child should always be 66| | /// binary (otherwise it could have been folded into the parent). 67| | /// 68| | /// These invariants are check by \see isValid(). 69| | /// 70| | /// \b Efficiency Considerations 71| | /// 72| | /// The Twine is designed to yield efficient and small code for common 73| | /// situations. For this reason, the concat() method is inlined so that 74| | /// concatenations of leaf nodes can be optimized into stores directly into a 75| | /// single stack allocated object. 76| | /// 77| | /// In practice, not all compilers can be trusted to optimize concat() fully, 78| | /// so we provide two additional methods (and accompanying operator+ 79| | /// overloads) to guarantee that particularly important cases (cstring plus 80| | /// StringRef) codegen as desired. 81| | class Twine { 82| | /// NodeKind - Represent the type of an argument. 83| | enum NodeKind : unsigned char { 84| | /// An empty string; the result of concatenating anything with it is also 85| | /// empty. 86| | NullKind, 87| | 88| | /// The empty string. 89| | EmptyKind, 90| | 91| | /// A pointer to a Twine instance. 92| | TwineKind, 93| | 94| | /// A pointer to a C string instance. 95| | CStringKind, 96| | 97| | /// A pointer to an std::string instance. 98| | StdStringKind, 99| | 100| | /// A pointer to a StringRef instance. 101| | StringRefKind, 102| | 103| | /// A char value reinterpreted as a pointer, to render as a character. 104| | CharKind, 105| | 106| | /// An unsigned int value reinterpreted as a pointer, to render as an 107| | /// unsigned decimal integer. 108| | DecUIKind, 109| | 110| | /// An int value reinterpreted as a pointer, to render as a signed 111| | /// decimal integer. 112| | DecIKind, 113| | 114| | /// A pointer to an unsigned long value, to render as an unsigned decimal 115| | /// integer. 116| | DecULKind, 117| | 118| | /// A pointer to a long value, to render as a signed decimal integer. 119| | DecLKind, 120| | 121| | /// A pointer to an unsigned long long value, to render as an unsigned 122| | /// decimal integer. 123| | DecULLKind, 124| | 125| | /// A pointer to a long long value, to render as a signed decimal integer. 126| | DecLLKind, 127| | 128| | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 129| | /// integer. 130| | UHexKind 131| | }; 132| | 133| | union Child 134| | { 135| | const Twine *twine; 136| | const char *cString; 137| | const std::string *stdString; 138| | const StringRef *stringRef; 139| | char character; 140| | unsigned int decUI; 141| | int decI; 142| | const unsigned long *decUL; 143| | const long *decL; 144| | const unsigned long long *decULL; 145| | const long long *decLL; 146| | const uint64_t *uHex; 147| | }; 148| | 149| | private: 150| | /// LHS - The prefix in the concatenation, which may be uninitialized for 151| | /// Null or Empty kinds. 152| | Child LHS; 153| | /// RHS - The suffix in the concatenation, which may be uninitialized for 154| | /// Null or Empty kinds. 155| | Child RHS; 156| | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 157| | NodeKind LHSKind; 158| | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). 159| | NodeKind RHSKind; 160| | 161| | private: 162| | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 163| | explicit Twine(NodeKind Kind) 164| | : LHSKind(Kind), RHSKind(EmptyKind) { 165| | assert(isNullary() && "Invalid kind!"); 166| | } 167| | 168| | /// Construct a binary twine. 169| | explicit Twine(const Twine &LHS, const Twine &RHS) 170| 0| : LHSKind(TwineKind), RHSKind(TwineKind) { 171| 0| this->LHS.twine = &LHS; 172| 0| this->RHS.twine = &RHS; 173| 0| assert(isValid() && "Invalid twine!"); 174| 0| } 175| | 176| | /// Construct a twine from explicit values. 177| | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) 178| | : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { 179| | assert(isValid() && "Invalid twine!"); 180| | } 181| | 182| | /// Since the intended use of twines is as temporary objects, assignments 183| | /// when concatenating might cause undefined behavior or stack corruptions 184| | Twine &operator=(const Twine &Other) = delete; 185| | 186| | /// isNull - Check for the null twine. 187| 0| bool isNull() const { 188| 0| return getLHSKind() == NullKind; 189| 0| } 190| | 191| | /// isEmpty - Check for the empty twine. 192| 0| bool isEmpty() const { 193| 0| return getLHSKind() == EmptyKind; 194| 0| } 195| | 196| | /// isNullary - Check if this is a nullary twine (null or empty). 197| 0| bool isNullary() const { 198| 0| return isNull() || isEmpty(); 199| 0| } 200| | 201| | /// isUnary - Check if this is a unary twine. 202| | bool isUnary() const { 203| | return getRHSKind() == EmptyKind && !isNullary(); 204| | } 205| | 206| | /// isBinary - Check if this is a binary twine. 207| 0| bool isBinary() const { 208| 0| return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 209| 0| } 210| | 211| | /// isValid - Check if this is a valid twine (satisfying the invariants on 212| | /// order and number of arguments). 213| 0| bool isValid() const { 214| 0| // Nullary twines always have Empty on the RHS. 215| 0| if (isNullary() && getRHSKind() != EmptyKind) 216| 0| return false; 217| 0| 218| 0| // Null should never appear on the RHS. 219| 0| if (getRHSKind() == NullKind) 220| 0| return false; 221| 0| 222| 0| // The RHS cannot be non-empty if the LHS is empty. 223| 0| if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 224| 0| return false; 225| 0| 226| 0| // A twine child should always be binary. 227| 0| if (getLHSKind() == TwineKind && 228| 0| !LHS.twine->isBinary()) 229| 0| return false; 230| 0| if (getRHSKind() == TwineKind && 231| 0| !RHS.twine->isBinary()) 232| 0| return false; 233| 0| 234| 0| return true; 235| 0| } 236| | 237| | /// getLHSKind - Get the NodeKind of the left-hand side. 238| 0| NodeKind getLHSKind() const { return LHSKind; } 239| | 240| | /// getRHSKind - Get the NodeKind of the right-hand side. 241| 0| NodeKind getRHSKind() const { return RHSKind; } 242| | 243| | /// printOneChild - Print one child from a twine. 244| | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; 245| | 246| | /// printOneChildRepr - Print the representation of one child from a twine. 247| | void printOneChildRepr(raw_ostream &OS, Child Ptr, 248| | NodeKind Kind) const; 249| | 250| | public: 251| | /// @name Constructors 252| | /// @{ 253| | 254| | /// Construct from an empty string. 255| 0| /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 256| 0| assert(isValid() && "Invalid twine!"); 257| 0| } 258| | 259| | Twine(const Twine &) = default; 260| | 261| | /// Construct from a C string. 262| | /// 263| | /// We take care here to optimize "" into the empty twine -- this will be 264| | /// optimized out for string constants. This allows Twine arguments have 265| | /// default "" values, without introducing unnecessary string constants. 266| | /*implicit*/ Twine(const char *Str) 267| | : RHSKind(EmptyKind) { 268| | if (Str[0] != '\0') { 269| | LHS.cString = Str; 270| | LHSKind = CStringKind; 271| | } else 272| | LHSKind = EmptyKind; 273| | 274| | assert(isValid() && "Invalid twine!"); 275| | } 276| | 277| | /// Construct from an std::string. 278| | /*implicit*/ Twine(const std::string &Str) 279| 0| : LHSKind(StdStringKind), RHSKind(EmptyKind) { 280| 0| LHS.stdString = &Str; 281| 0| assert(isValid() && "Invalid twine!"); 282| 0| } 283| | 284| | /// Construct from a StringRef. 285| | /*implicit*/ Twine(const StringRef &Str) 286| | : LHSKind(StringRefKind), RHSKind(EmptyKind) { 287| | LHS.stringRef = &Str; 288| | assert(isValid() && "Invalid twine!"); 289| | } 290| | 291| | /// Construct from a char. 292| | explicit Twine(char Val) 293| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 294| 0| LHS.character = Val; 295| 0| } 296| | 297| | /// Construct from a signed char. 298| | explicit Twine(signed char Val) 299| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 300| 0| LHS.character = static_cast(Val); 301| 0| } 302| | 303| | /// Construct from an unsigned char. 304| | explicit Twine(unsigned char Val) 305| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 306| 0| LHS.character = static_cast(Val); 307| 0| } 308| | 309| | /// Construct a twine to print \p Val as an unsigned decimal integer. 310| | explicit Twine(unsigned Val) 311| 0| : LHSKind(DecUIKind), RHSKind(EmptyKind) { 312| 0| LHS.decUI = Val; 313| 0| } 314| | 315| | /// Construct a twine to print \p Val as a signed decimal integer. 316| | explicit Twine(int Val) 317| 0| : LHSKind(DecIKind), RHSKind(EmptyKind) { 318| 0| LHS.decI = Val; 319| 0| } 320| | 321| | /// Construct a twine to print \p Val as an unsigned decimal integer. 322| | explicit Twine(const unsigned long &Val) 323| 0| : LHSKind(DecULKind), RHSKind(EmptyKind) { 324| 0| LHS.decUL = &Val; 325| 0| } 326| | 327| | /// Construct a twine to print \p Val as a signed decimal integer. 328| | explicit Twine(const long &Val) 329| 0| : LHSKind(DecLKind), RHSKind(EmptyKind) { 330| 0| LHS.decL = &Val; 331| 0| } 332| | 333| | /// Construct a twine to print \p Val as an unsigned decimal integer. 334| | explicit Twine(const unsigned long long &Val) 335| 0| : LHSKind(DecULLKind), RHSKind(EmptyKind) { 336| 0| LHS.decULL = &Val; 337| 0| } 338| | 339| | /// Construct a twine to print \p Val as a signed decimal integer. 340| | explicit Twine(const long long &Val) 341| 0| : LHSKind(DecLLKind), RHSKind(EmptyKind) { 342| 0| LHS.decLL = &Val; 343| 0| } 344| | 345| | // FIXME: Unfortunately, to make sure this is as efficient as possible we 346| | // need extra binary constructors from particular types. We can't rely on 347| | // the compiler to be smart enough to fold operator+()/concat() down to the 348| | // right thing. Yet. 349| | 350| | /// Construct as the concatenation of a C string and a StringRef. 351| | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) 352| | : LHSKind(CStringKind), RHSKind(StringRefKind) { 353| | this->LHS.cString = LHS; 354| | this->RHS.stringRef = &RHS; 355| | assert(isValid() && "Invalid twine!"); 356| | } 357| | 358| | /// Construct as the concatenation of a StringRef and a C string. 359| | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) 360| | : LHSKind(StringRefKind), RHSKind(CStringKind) { 361| | this->LHS.stringRef = &LHS; 362| | this->RHS.cString = RHS; 363| | assert(isValid() && "Invalid twine!"); 364| | } 365| | 366| | /// Create a 'null' string, which is an empty string that always 367| | /// concatenates to form another empty string. 368| 0| static Twine createNull() { 369| 0| return Twine(NullKind); 370| 0| } 371| | 372| | /// @} 373| | /// @name Numeric Conversions 374| | /// @{ 375| | 376| | // Construct a twine to print \p Val as an unsigned hexadecimal integer. 377| | static Twine utohexstr(const uint64_t &Val) { 378| | Child LHS, RHS; 379| | LHS.uHex = &Val; 380| | RHS.twine = nullptr; 381| | return Twine(LHS, UHexKind, RHS, EmptyKind); 382| | } 383| | 384| | /// @} 385| | /// @name Predicate Operations 386| | /// @{ 387| | 388| | /// isTriviallyEmpty - Check if this twine is trivially empty; a false 389| | /// return value does not necessarily mean the twine is empty. 390| | bool isTriviallyEmpty() const { 391| | return isNullary(); 392| | } 393| | 394| | /// isSingleStringRef - Return true if this twine can be dynamically 395| | /// accessed as a single StringRef value with getSingleStringRef(). 396| | bool isSingleStringRef() const { 397| | if (getRHSKind() != EmptyKind) return false; 398| | 399| | switch (getLHSKind()) { 400| | case EmptyKind: 401| | case CStringKind: 402| | case StdStringKind: 403| | case StringRefKind: 404| | return true; 405| | default: 406| | return false; 407| | } 408| | } 409| | 410| | /// @} 411| | /// @name String Operations 412| | /// @{ 413| | 414| | Twine concat(const Twine &Suffix) const; 415| | 416| | /// @} 417| | /// @name Output & Conversion. 418| | /// @{ 419| | 420| | /// str - Return the twine contents as a std::string. 421| | std::string str() const; 422| | 423| | /// toVector - Write the concatenated string into the given SmallString or 424| | /// SmallVector. 425| | void toVector(SmallVectorImpl &Out) const; 426| | 427| | /// getSingleStringRef - This returns the twine as a single StringRef. This 428| | /// method is only valid if isSingleStringRef() is true. 429| | StringRef getSingleStringRef() const { 430| | assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); 431| | switch (getLHSKind()) { 432| | default: llvm_unreachable("Out of sync with isSingleStringRef"); 433| | case EmptyKind: return StringRef(); 434| | case CStringKind: return StringRef(LHS.cString); 435| | case StdStringKind: return StringRef(*LHS.stdString); 436| | case StringRefKind: return *LHS.stringRef; 437| | } 438| | } 439| | 440| | /// toStringRef - This returns the twine as a single StringRef if it can be 441| | /// represented as such. Otherwise the twine is written into the given 442| | /// SmallVector and a StringRef to the SmallVector's data is returned. 443| | StringRef toStringRef(SmallVectorImpl &Out) const; 444| | 445| | /// toNullTerminatedStringRef - This returns the twine as a single null 446| | /// terminated StringRef if it can be represented as such. Otherwise the 447| | /// twine is written into the given SmallVector and a StringRef to the 448| | /// SmallVector's data is returned. 449| | /// 450| | /// The returned StringRef's size does not include the null terminator. 451| | StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; 452| | 453| | /// Write the concatenated string represented by this twine to the 454| | /// stream \p OS. 455| | void print(raw_ostream &OS) const; 456| | 457| | /// Dump the concatenated string represented by this twine to stderr. 458| | void dump() const; 459| | 460| | /// Write the representation of this twine to the stream \p OS. 461| | void printRepr(raw_ostream &OS) const; 462| | 463| | /// Dump the representation of this twine to stderr. 464| | void dumpRepr() const; 465| | 466| | /// @} 467| | }; 468| | 469| | /// @name Twine Inline Implementations 470| | /// @{ 471| | 472| | inline Twine Twine::concat(const Twine &Suffix) const { 473| | // Concatenation with null is null. 474| | if (isNull() || Suffix.isNull()) 475| | return Twine(NullKind); 476| | 477| | // Concatenation with empty yields the other side. 478| | if (isEmpty()) 479| | return Suffix; 480| | if (Suffix.isEmpty()) 481| | return *this; 482| | 483| | // Otherwise we need to create a new node, taking care to fold in unary 484| | // twines. 485| | Child NewLHS, NewRHS; 486| | NewLHS.twine = this; 487| | NewRHS.twine = &Suffix; 488| | NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 489| | if (isUnary()) { 490| | NewLHS = LHS; 491| | NewLHSKind = getLHSKind(); 492| | } 493| | if (Suffix.isUnary()) { 494| | NewRHS = Suffix.LHS; 495| | NewRHSKind = Suffix.getLHSKind(); 496| | } 497| | 498| | return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 499| | } 500| | 501| | inline Twine operator+(const Twine &LHS, const Twine &RHS) { 502| | return LHS.concat(RHS); 503| | } 504| | 505| | /// Additional overload to guarantee simplified codegen; this is equivalent to 506| | /// concat(). 507| | 508| | inline Twine operator+(const char *LHS, const StringRef &RHS) { 509| | return Twine(LHS, RHS); 510| | } 511| | 512| | /// Additional overload to guarantee simplified codegen; this is equivalent to 513| | /// concat(). 514| | 515| | inline Twine operator+(const StringRef &LHS, const char *RHS) { 516| | return Twine(LHS, RHS); 517| | } 518| | 519| | inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 520| | RHS.print(OS); 521| | return OS; 522| | } 523| | 524| | /// @} 525| |} 526| | 527| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Allocator.h: 1| |//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// \file 10| |/// 11| |/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both 12| |/// of these conform to an LLVM "Allocator" concept which consists of an 13| |/// Allocate method accepting a size and alignment, and a Deallocate accepting 14| |/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of 15| |/// Allocate and Deallocate for setting size and alignment based on the final 16| |/// type. These overloads are typically provided by a base class template \c 17| |/// AllocatorBase. 18| |/// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_SUPPORT_ALLOCATOR_H 22| |#define LLVM_SUPPORT_ALLOCATOR_H 23| | 24| |#include "llvm/ADT/SmallVector.h" 25| |#include "llvm/Support/AlignOf.h" 26| |#include "llvm/Support/DataTypes.h" 27| |#include "llvm/Support/MathExtras.h" 28| |#include "llvm/Support/Memory.h" 29| |#include 30| |#include 31| |#include 32| |#include 33| | 34| |namespace llvm { 35| | 36| |/// \brief CRTP base class providing obvious overloads for the core \c 37| |/// Allocate() methods of LLVM-style allocators. 38| |/// 39| |/// This base class both documents the full public interface exposed by all 40| |/// LLVM-style allocators, and redirects all of the overloads to a single core 41| |/// set of methods which the derived class must define. 42| |template class AllocatorBase { 43| |public: 44| | /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method 45| | /// must be implemented by \c DerivedT. 46| | void *Allocate(size_t Size, size_t Alignment) { 47| |#ifdef __clang__ 48| | static_assert(static_cast( 49| | &AllocatorBase::Allocate) != 50| | static_cast( 51| | &DerivedT::Allocate), 52| | "Class derives from AllocatorBase without implementing the " 53| | "core Allocate(size_t, size_t) overload!"); 54| |#endif 55| | return static_cast(this)->Allocate(Size, Alignment); 56| | } 57| | 58| | /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this 59| | /// allocator. 60| | void Deallocate(const void *Ptr, size_t Size) { 61| |#ifdef __clang__ 62| | static_assert(static_cast( 63| | &AllocatorBase::Deallocate) != 64| | static_cast( 65| | &DerivedT::Deallocate), 66| | "Class derives from AllocatorBase without implementing the " 67| | "core Deallocate(void *) overload!"); 68| |#endif 69| | return static_cast(this)->Deallocate(Ptr, Size); 70| | } 71| | 72| | // The rest of these methods are helpers that redirect to one of the above 73| | // core methods. 74| | 75| | /// \brief Allocate space for a sequence of objects without constructing them. 76| | template T *Allocate(size_t Num = 1) { 77| | return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); 78| | } 79| | 80| | /// \brief Deallocate space for a sequence of objects without constructing them. 81| | template 82| | typename std::enable_if< 83| | !std::is_same::type, void>::value, void>::type 84| | Deallocate(T *Ptr, size_t Num = 1) { 85| | Deallocate(static_cast(Ptr), Num * sizeof(T)); 86| | } 87| |}; 88| | 89| |class MallocAllocator : public AllocatorBase { 90| |public: 91| 0| void Reset() {} 92| | 93| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, 94| | size_t /*Alignment*/) { 95| | return malloc(Size); 96| | } 97| | 98| | // Pull in base class overloads. 99| | using AllocatorBase::Allocate; 100| | 101| 0| void Deallocate(const void *Ptr, size_t /*Size*/) { 102| 0| free(const_cast(Ptr)); 103| 0| } 104| | 105| | // Pull in base class overloads. 106| | using AllocatorBase::Deallocate; 107| | 108| 0| void PrintStats() const {} 109| |}; 110| | 111| |namespace detail { 112| | 113| |// We call out to an external function to actually print the message as the 114| |// printing code uses Allocator.h in its implementation. 115| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 116| | size_t TotalMemory); 117| |} // End namespace detail. 118| | 119| |/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. 120| |/// 121| |/// This isn't strictly a bump-pointer allocator as it uses backing slabs of 122| |/// memory rather than relying on a boundless contiguous heap. However, it has 123| |/// bump-pointer semantics in that it is a monotonically growing pool of memory 124| |/// where every allocation is found by merely allocating the next N bytes in 125| |/// the slab, or the next N bytes in the next slab. 126| |/// 127| |/// Note that this also has a threshold for forcing allocations above a certain 128| |/// size into their own slab. 129| |/// 130| |/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator 131| |/// object, which wraps malloc, to allocate memory, but it can be changed to 132| |/// use a custom allocator. 133| |template 135| |class BumpPtrAllocatorImpl 136| | : public AllocatorBase< 137| | BumpPtrAllocatorImpl> { 138| |public: 139| | static_assert(SizeThreshold <= SlabSize, 140| | "The SizeThreshold must be at most the SlabSize to ensure " 141| | "that objects larger than a slab go into their own memory " 142| | "allocation."); 143| | 144| | BumpPtrAllocatorImpl() 145| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} 146| | template 147| | BumpPtrAllocatorImpl(T &&Allocator) 148| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), 149| | Allocator(std::forward(Allocator)) {} 150| | 151| | // Manually implement a move constructor as we must clear the old allocators 152| | // slabs as a matter of correctness. 153| | BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) 154| | : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), 155| | CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), 156| | BytesAllocated(Old.BytesAllocated), 157| | Allocator(std::move(Old.Allocator)) { 158| | Old.CurPtr = Old.End = nullptr; 159| | Old.BytesAllocated = 0; 160| | Old.Slabs.clear(); 161| | Old.CustomSizedSlabs.clear(); 162| | } 163| | 164| | ~BumpPtrAllocatorImpl() { 165| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 166| | DeallocateCustomSizedSlabs(); 167| | } 168| | 169| | BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { 170| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 171| | DeallocateCustomSizedSlabs(); 172| | 173| | CurPtr = RHS.CurPtr; 174| | End = RHS.End; 175| | BytesAllocated = RHS.BytesAllocated; 176| | Slabs = std::move(RHS.Slabs); 177| | CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); 178| | Allocator = std::move(RHS.Allocator); 179| | 180| | RHS.CurPtr = RHS.End = nullptr; 181| | RHS.BytesAllocated = 0; 182| | RHS.Slabs.clear(); 183| | RHS.CustomSizedSlabs.clear(); 184| | return *this; 185| | } 186| | 187| | /// \brief Deallocate all but the current slab and reset the current pointer 188| | /// to the beginning of it, freeing all memory allocated so far. 189| | void Reset() { 190| | if (Slabs.empty()) 191| | return; 192| | 193| | // Reset the state. 194| | BytesAllocated = 0; 195| | CurPtr = (char *)Slabs.front(); 196| | End = CurPtr + SlabSize; 197| | 198| | // Deallocate all but the first slab, and all custome sized slabs. 199| | DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); 200| | Slabs.erase(std::next(Slabs.begin()), Slabs.end()); 201| | DeallocateCustomSizedSlabs(); 202| | CustomSizedSlabs.clear(); 203| | } 204| | 205| | /// \brief Allocate space at the specified alignment. 206| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { 207| | assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); 208| | 209| | // Keep track of how many bytes we've allocated. 210| | BytesAllocated += Size; 211| | 212| | size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); 213| | assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); 214| | 215| | // Check if we have enough space. 216| | if (Adjustment + Size <= size_t(End - CurPtr)) { 217| | char *AlignedPtr = CurPtr + Adjustment; 218| | CurPtr = AlignedPtr + Size; 219| | // Update the allocation point of this memory block in MemorySanitizer. 220| | // Without this, MemorySanitizer messages for values originated from here 221| | // will point to the allocation of the entire slab. 222| | __msan_allocated_memory(AlignedPtr, Size); 223| | return AlignedPtr; 224| | } 225| | 226| | // If Size is really big, allocate a separate slab for it. 227| | size_t PaddedSize = Size + Alignment - 1; 228| | if (PaddedSize > SizeThreshold) { 229| | void *NewSlab = Allocator.Allocate(PaddedSize, 0); 230| | CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); 231| | 232| | uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); 233| | assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); 234| | char *AlignedPtr = (char*)AlignedAddr; 235| | __msan_allocated_memory(AlignedPtr, Size); 236| | return AlignedPtr; 237| | } 238| | 239| | // Otherwise, start a new slab and try again. 240| | StartNewSlab(); 241| | uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); 242| | assert(AlignedAddr + Size <= (uintptr_t)End && 243| | "Unable to allocate memory!"); 244| | char *AlignedPtr = (char*)AlignedAddr; 245| | CurPtr = AlignedPtr + Size; 246| | __msan_allocated_memory(AlignedPtr, Size); 247| | return AlignedPtr; 248| | } 249| | 250| | // Pull in base class overloads. 251| | using AllocatorBase::Allocate; 252| | 253| | void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} 254| | 255| | // Pull in base class overloads. 256| | using AllocatorBase::Deallocate; 257| | 258| | size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } 259| | 260| | size_t getTotalMemory() const { 261| | size_t TotalMemory = 0; 262| | for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) 263| | TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); 264| | for (auto &PtrAndSize : CustomSizedSlabs) 265| | TotalMemory += PtrAndSize.second; 266| | return TotalMemory; 267| | } 268| | 269| | void PrintStats() const { 270| | detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, 271| | getTotalMemory()); 272| | } 273| | 274| |private: 275| | /// \brief The current pointer into the current slab. 276| | /// 277| | /// This points to the next free byte in the slab. 278| | char *CurPtr; 279| | 280| | /// \brief The end of the current slab. 281| | char *End; 282| | 283| | /// \brief The slabs allocated so far. 284| | SmallVector Slabs; 285| | 286| | /// \brief Custom-sized slabs allocated for too-large allocation requests. 287| | SmallVector, 0> CustomSizedSlabs; 288| | 289| | /// \brief How many bytes we've allocated. 290| | /// 291| | /// Used so that we can compute how much space was wasted. 292| | size_t BytesAllocated; 293| | 294| | /// \brief The allocator instance we use to get slabs of memory. 295| | AllocatorT Allocator; 296| | 297| | static size_t computeSlabSize(unsigned SlabIdx) { 298| | // Scale the actual allocated slab size based on the number of slabs 299| | // allocated. Every 128 slabs allocated, we double the allocated size to 300| | // reduce allocation frequency, but saturate at multiplying the slab size by 301| | // 2^30. 302| | return SlabSize * ((size_t)1 << std::min(30, SlabIdx / 128)); 303| | } 304| | 305| | /// \brief Allocate a new slab and move the bump pointers over into the new 306| | /// slab, modifying CurPtr and End. 307| | void StartNewSlab() { 308| | size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); 309| | 310| | void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); 311| | Slabs.push_back(NewSlab); 312| | CurPtr = (char *)(NewSlab); 313| | End = ((char *)NewSlab) + AllocatedSlabSize; 314| | } 315| | 316| | /// \brief Deallocate a sequence of slabs. 317| | void DeallocateSlabs(SmallVectorImpl::iterator I, 318| | SmallVectorImpl::iterator E) { 319| | for (; I != E; ++I) { 320| | size_t AllocatedSlabSize = 321| | computeSlabSize(std::distance(Slabs.begin(), I)); 322| |#ifndef NDEBUG 323| | // Poison the memory so stale pointers crash sooner. Note we must 324| | // preserve the Size and NextPtr fields at the beginning. 325| | if (AllocatedSlabSize != 0) { 326| | sys::Memory::setRangeWritable(*I, AllocatedSlabSize); 327| | memset(*I, 0xCD, AllocatedSlabSize); 328| | } 329| |#endif 330| | Allocator.Deallocate(*I, AllocatedSlabSize); 331| | } 332| | } 333| | 334| | /// \brief Deallocate all memory for custom sized slabs. 335| | void DeallocateCustomSizedSlabs() { 336| | for (auto &PtrAndSize : CustomSizedSlabs) { 337| | void *Ptr = PtrAndSize.first; 338| | size_t Size = PtrAndSize.second; 339| |#ifndef NDEBUG 340| | // Poison the memory so stale pointers crash sooner. Note we must 341| | // preserve the Size and NextPtr fields at the beginning. 342| | sys::Memory::setRangeWritable(Ptr, Size); 343| | memset(Ptr, 0xCD, Size); 344| |#endif 345| | Allocator.Deallocate(Ptr, Size); 346| | } 347| | } 348| | 349| | template friend class SpecificBumpPtrAllocator; 350| |}; 351| | 352| |/// \brief The standard BumpPtrAllocator which just uses the default template 353| |/// paramaters. 354| |typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 355| | 356| |/// \brief A BumpPtrAllocator that allows only elements of a specific type to be 357| |/// allocated. 358| |/// 359| |/// This allows calling the destructor in DestroyAll() and when the allocator is 360| |/// destroyed. 361| |template class SpecificBumpPtrAllocator { 362| | BumpPtrAllocator Allocator; 363| | 364| |public: 365| | SpecificBumpPtrAllocator() : Allocator() {} 366| | SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) 367| | : Allocator(std::move(Old.Allocator)) {} 368| | ~SpecificBumpPtrAllocator() { DestroyAll(); } 369| | 370| | SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { 371| | Allocator = std::move(RHS.Allocator); 372| | return *this; 373| | } 374| | 375| | /// Call the destructor of each allocated object and deallocate all but the 376| | /// current slab and reset the current pointer to the beginning of it, freeing 377| | /// all memory allocated so far. 378| | void DestroyAll() { 379| | auto DestroyElements = [](char *Begin, char *End) { 380| | assert(Begin == (char*)alignAddr(Begin, alignOf())); 381| | for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) 382| | reinterpret_cast(Ptr)->~T(); 383| | }; 384| | 385| | for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; 386| | ++I) { 387| | size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( 388| | std::distance(Allocator.Slabs.begin(), I)); 389| | char *Begin = (char*)alignAddr(*I, alignOf()); 390| | char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr 391| | : (char *)*I + AllocatedSlabSize; 392| | 393| | DestroyElements(Begin, End); 394| | } 395| | 396| | for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { 397| | void *Ptr = PtrAndSize.first; 398| | size_t Size = PtrAndSize.second; 399| | DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); 400| | } 401| | 402| | Allocator.Reset(); 403| | } 404| | 405| | /// \brief Allocate space for an array of objects without constructing them. 406| | T *Allocate(size_t num = 1) { return Allocator.Allocate(num); } 407| |}; 408| | 409| |} // end namespace llvm 410| | 411| |template 412| |void *operator new(size_t Size, 413| | llvm::BumpPtrAllocatorImpl &Allocator) { 415| | struct S { 416| | char c; 417| | union { 418| | double D; 419| | long double LD; 420| | long long L; 421| | void *P; 422| | } x; 423| | }; 424| | return Allocator.Allocate( 425| | Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); 426| |} 427| | 428| |template 429| |void operator delete( 430| | void *, llvm::BumpPtrAllocatorImpl &) { 431| |} 432| | 433| |#endif // LLVM_SUPPORT_ALLOCATOR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/CBindingWrapping.h: 1| |//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the wrapping macros for the C interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H 15| |#define LLVM_SUPPORT_CBINDINGWRAPPING_H 16| | 17| |#include "llvm/Support/Casting.h" 18| | 19| |#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 20| 0| inline ty *unwrap(ref P) { \ 21| 0| return reinterpret_cast(P); \ 22| 0| } \ 23| | \ 24| 0| inline ref wrap(const ty *P) { \ 25| 0| return reinterpret_cast(const_cast(P)); \ 26| 0| } 27| | 28| |#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ 29| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 30| | \ 31| | template \ 32| | inline T *unwrap(ref P) { \ 33| | return cast(unwrap(P)); \ 34| | } 35| | 36| |#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ 37| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 38| | \ 39| | template \ 40| | inline T *unwrap(ref P) { \ 41| | T *Q = (T*)unwrap(P); \ 42| | assert(Q && "Invalid cast!"); \ 43| | return Q; \ 44| | } 45| | 46| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Compiler.h: 1| |//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines several macros, based on the current compiler. This allows 11| |// use of compiler-specific features in a way that remains portable. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_COMPILER_H 16| |#define LLVM_SUPPORT_COMPILER_H 17| | 18| |#include "llvm/Config/llvm-config.h" 19| | 20| |#ifndef __has_feature 21| |# define __has_feature(x) 0 22| |#endif 23| | 24| |#ifndef __has_extension 25| |# define __has_extension(x) 0 26| |#endif 27| | 28| |#ifndef __has_attribute 29| |# define __has_attribute(x) 0 30| |#endif 31| | 32| |#ifndef __has_builtin 33| |# define __has_builtin(x) 0 34| |#endif 35| | 36| |/// \macro LLVM_GNUC_PREREQ 37| |/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't 38| |/// available. 39| |#ifndef LLVM_GNUC_PREREQ 40| |# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 42| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43| | ((maj) << 20) + ((min) << 10) + (patch)) 44| |# elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 46| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47| |# else 48| |# define LLVM_GNUC_PREREQ(maj, min, patch) 0 49| |# endif 50| |#endif 51| | 52| |/// \macro LLVM_MSC_PREREQ 53| |/// \brief Is the compiler MSVC of at least the specified version? 54| |/// The common \param version values to check for are: 55| |/// * 1800: Microsoft Visual Studio 2013 / 12.0 56| |/// * 1900: Microsoft Visual Studio 2015 / 14.0 57| |#ifdef _MSC_VER 58| |#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) 59| | 60| |// We require at least MSVC 2013. 61| |#if !LLVM_MSC_PREREQ(1800) 62| |#error LLVM requires at least MSVC 2013. 63| |#endif 64| | 65| |#else 66| |#define LLVM_MSC_PREREQ(version) 0 67| |#endif 68| | 69| |#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) 70| |#define LLVM_NOEXCEPT noexcept 71| |#else 72| |#define LLVM_NOEXCEPT 73| |#endif 74| | 75| |/// \brief Does the compiler support r-value reference *this? 76| |/// 77| |/// Sadly, this is separate from just r-value reference support because GCC 78| |/// implemented this later than everything else. 79| |#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) 80| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 81| |#else 82| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 83| |#endif 84| | 85| |/// Expands to '&' if r-value references are supported. 86| |/// 87| |/// This can be used to provide l-value/r-value overrides of member functions. 88| |/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS 89| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 90| |#define LLVM_LVALUE_FUNCTION & 91| |#else 92| |#define LLVM_LVALUE_FUNCTION 93| |#endif 94| | 95| |#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) 96| |# define LLVM_CONSTEXPR constexpr 97| |#else 98| |# define LLVM_CONSTEXPR 99| |#endif 100| | 101| |/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked 102| |/// into a shared library, then the class should be private to the library and 103| |/// not accessible from outside it. Can also be used to mark variables and 104| |/// functions, making them private to any shared library they are linked into. 105| |/// On PE/COFF targets, library visibility is the default, so this isn't needed. 106| |#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 107| | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) 108| |#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) 109| |#else 110| |#define LLVM_LIBRARY_VISIBILITY 111| |#endif 112| | 113| |#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) 114| |#define LLVM_END_WITH_NULL __attribute__((sentinel)) 115| |#else 116| |#define LLVM_END_WITH_NULL 117| |#endif 118| | 119| |#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) 120| |#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) 121| |#else 122| |#define LLVM_ATTRIBUTE_USED 123| |#endif 124| | 125| |#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) 126| |#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) 127| |#else 128| |#define LLVM_ATTRIBUTE_UNUSED_RESULT 129| |#endif 130| | 131| |// Some compilers warn about unused functions. When a function is sometimes 132| |// used or not depending on build settings (e.g. a function only called from 133| |// within "assert"), this attribute can be used to suppress such warnings. 134| |// 135| |// However, it shouldn't be used for unused *variables*, as those have a much 136| |// more portable solution: 137| |// (void)unused_var_name; 138| |// Prefer cast-to-void wherever it is sufficient. 139| |#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) 140| |#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) 141| |#else 142| |#define LLVM_ATTRIBUTE_UNUSED 143| |#endif 144| | 145| |// FIXME: Provide this for PE/COFF targets. 146| |#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 147| | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) 148| |#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) 149| |#else 150| |#define LLVM_ATTRIBUTE_WEAK 151| |#endif 152| | 153| |// Prior to clang 3.2, clang did not accept any spelling of 154| |// __has_attribute(const), so assume it is supported. 155| |#if defined(__clang__) || defined(__GNUC__) 156| |// aka 'CONST' but following LLVM Conventions. 157| |#define LLVM_READNONE __attribute__((__const__)) 158| |#else 159| |#define LLVM_READNONE 160| |#endif 161| | 162| |#if __has_attribute(pure) || defined(__GNUC__) 163| |// aka 'PURE' but following LLVM Conventions. 164| |#define LLVM_READONLY __attribute__((__pure__)) 165| |#else 166| |#define LLVM_READONLY 167| |#endif 168| | 169| |#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) 170| |#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) 171| 0|#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) 172| |#else 173| |#define LLVM_LIKELY(EXPR) (EXPR) 174| |#define LLVM_UNLIKELY(EXPR) (EXPR) 175| |#endif 176| | 177| |// C++ doesn't support 'extern template' of template specializations. GCC does, 178| |// but requires __extension__ before it. In the header, use this: 179| |// EXTERN_TEMPLATE_INSTANTIATION(class foo); 180| |// in the .cpp file, use this: 181| |// TEMPLATE_INSTANTIATION(class foo); 182| |#ifdef __GNUC__ 183| |#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X 184| |#define TEMPLATE_INSTANTIATION(X) template X 185| |#else 186| |#define EXTERN_TEMPLATE_INSTANTIATION(X) 187| |#define TEMPLATE_INSTANTIATION(X) 188| |#endif 189| | 190| |/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, 191| |/// mark a method "not for inlining". 192| |#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) 193| |#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) 194| |#elif defined(_MSC_VER) 195| |#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) 196| |#else 197| |#define LLVM_ATTRIBUTE_NOINLINE 198| |#endif 199| | 200| |/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do 201| |/// so, mark a method "always inline" because it is performance sensitive. GCC 202| |/// 3.4 supported this but is buggy in various cases and produces unimplemented 203| |/// errors, just use it in GCC 4.0 and later. 204| |#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) 205| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) 206| |#elif defined(_MSC_VER) 207| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline 208| |#else 209| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE 210| |#endif 211| | 212| |#ifdef __GNUC__ 213| |#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) 214| |#elif defined(_MSC_VER) 215| |#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) 216| |#else 217| |#define LLVM_ATTRIBUTE_NORETURN 218| |#endif 219| | 220| |#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) 221| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 222| |#else 223| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL 224| |#endif 225| | 226| |/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress 227| |/// pedantic diagnostics. 228| |#ifdef __GNUC__ 229| |#define LLVM_EXTENSION __extension__ 230| |#else 231| |#define LLVM_EXTENSION 232| |#endif 233| | 234| |// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") 235| |#if __has_feature(attribute_deprecated_with_message) 236| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 237| | decl __attribute__((deprecated(message))) 238| |#elif defined(__GNUC__) 239| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 240| | decl __attribute__((deprecated)) 241| |#elif defined(_MSC_VER) 242| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 243| | __declspec(deprecated(message)) decl 244| |#else 245| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 246| | decl 247| |#endif 248| | 249| |/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands 250| |/// to an expression which states that it is undefined behavior for the 251| |/// compiler to reach this point. Otherwise is not defined. 252| |#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) 253| |# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() 254| |#elif defined(_MSC_VER) 255| |# define LLVM_BUILTIN_UNREACHABLE __assume(false) 256| |#endif 257| | 258| |/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression 259| |/// which causes the program to exit abnormally. 260| |#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) 261| |# define LLVM_BUILTIN_TRAP __builtin_trap() 262| |#elif defined(_MSC_VER) 263| |// The __debugbreak intrinsic is supported by MSVC, does not require forward 264| |// declarations involving platform-specific typedefs (unlike RaiseException), 265| |// results in a call to vectored exception handlers, and encodes to a short 266| |// instruction that still causes the trapping behavior we want. 267| |# define LLVM_BUILTIN_TRAP __debugbreak() 268| |#else 269| |# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 270| |#endif 271| | 272| |/// \macro LLVM_ASSUME_ALIGNED 273| |/// \brief Returns a pointer with an assumed alignment. 274| |#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) 275| |# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) 276| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 277| |// As of today, clang does not support __builtin_assume_aligned. 278| |# define LLVM_ASSUME_ALIGNED(p, a) \ 279| | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) 280| |#else 281| |# define LLVM_ASSUME_ALIGNED(p, a) (p) 282| |#endif 283| | 284| |/// \macro LLVM_FUNCTION_NAME 285| |/// \brief Expands to __func__ on compilers which support it. Otherwise, 286| |/// expands to a compiler-dependent replacement. 287| |#if defined(_MSC_VER) 288| |# define LLVM_FUNCTION_NAME __FUNCTION__ 289| |#else 290| |# define LLVM_FUNCTION_NAME __func__ 291| |#endif 292| | 293| |/// \macro LLVM_MEMORY_SANITIZER_BUILD 294| |/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. 295| |#if __has_feature(memory_sanitizer) 296| |# define LLVM_MEMORY_SANITIZER_BUILD 1 297| |# include 298| |#else 299| |# define LLVM_MEMORY_SANITIZER_BUILD 0 300| |# define __msan_allocated_memory(p, size) 301| |# define __msan_unpoison(p, size) 302| |#endif 303| | 304| |/// \macro LLVM_ADDRESS_SANITIZER_BUILD 305| |/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. 306| |#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 307| |# define LLVM_ADDRESS_SANITIZER_BUILD 1 308| |#else 309| |# define LLVM_ADDRESS_SANITIZER_BUILD 0 310| |#endif 311| | 312| |/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST 313| |/// \brief Is unaligned memory access fast on the host machine. 314| |/// 315| |/// Don't specialize on alignment for platforms where unaligned memory accesses 316| |/// generates the same code as aligned memory accesses for common types. 317| |#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ 318| | defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ 319| | defined(_X86_) || defined(__i386) || defined(__i386__) 320| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 321| |#else 322| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 323| |#endif 324| | 325| |/// \brief Mark debug helper function definitions like dump() that should not be 326| |/// stripped from debug builds. 327| |// FIXME: Move this to a private config.h as it's not usable in public headers. 328| |#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED 330| |#else 331| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE 332| |#endif 333| | 334| |/// \macro LLVM_THREAD_LOCAL 335| |/// \brief A thread-local storage specifier which can be used with globals, 336| |/// extern globals, and static globals. 337| |/// 338| |/// This is essentially an extremely restricted analog to C++11's thread_local 339| |/// support, and uses that when available. However, it falls back on 340| |/// platform-specific or vendor-provided extensions when necessary. These 341| |/// extensions don't support many of the C++11 thread_local's features. You 342| |/// should only use this for PODs that you can statically initialize to 343| |/// some constant value. In almost all circumstances this is most appropriate 344| |/// for use with a pointer, integer, or small aggregation of pointers and 345| |/// integers. 346| |#if LLVM_ENABLE_THREADS 347| |#if __has_feature(cxx_thread_local) 348| |#define LLVM_THREAD_LOCAL thread_local 349| |#elif defined(_MSC_VER) 350| |// MSVC supports this with a __declspec. 351| |#define LLVM_THREAD_LOCAL __declspec(thread) 352| |#else 353| |// Clang, GCC, and other compatible compilers used __thread prior to C++11 and 354| |// we only need the restricted functionality that provides. 355| |#define LLVM_THREAD_LOCAL __thread 356| |#endif 357| |#else // !LLVM_ENABLE_THREADS 358| |// If threading is disabled entirely, this compiles to nothing and you get 359| |// a normal global variable. 360| |#define LLVM_THREAD_LOCAL 361| |#endif 362| | 363| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorHandling.h: 1| |//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ERRORHANDLING_H 16| |#define LLVM_SUPPORT_ERRORHANDLING_H 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include 21| | 22| |namespace llvm { 23| | class Twine; 24| | 25| | /// An error handler callback. 26| | typedef void (*fatal_error_handler_t)(void *user_data, 27| | const std::string& reason, 28| | bool gen_crash_diag); 29| | 30| | /// install_fatal_error_handler - Installs a new error handler to be used 31| | /// whenever a serious (non-recoverable) error is encountered by LLVM. 32| | /// 33| | /// If no error handler is installed the default is to print the error message 34| | /// to stderr, and call exit(1). If an error handler is installed then it is 35| | /// the handler's responsibility to log the message, it will no longer be 36| | /// printed to stderr. If the error handler returns, then exit(1) will be 37| | /// called. 38| | /// 39| | /// It is dangerous to naively use an error handler which throws an exception. 40| | /// Even though some applications desire to gracefully recover from arbitrary 41| | /// faults, blindly throwing exceptions through unfamiliar code isn't a way to 42| | /// achieve this. 43| | /// 44| | /// \param user_data - An argument which will be passed to the install error 45| | /// handler. 46| | void install_fatal_error_handler(fatal_error_handler_t handler, 47| | void *user_data = nullptr); 48| | 49| | /// Restores default error handling behaviour. 50| | void remove_fatal_error_handler(); 51| | 52| | /// ScopedFatalErrorHandler - This is a simple helper class which just 53| | /// calls install_fatal_error_handler in its constructor and 54| | /// remove_fatal_error_handler in its destructor. 55| | struct ScopedFatalErrorHandler { 56| | explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, 57| 0| void *user_data = nullptr) { 58| 0| install_fatal_error_handler(handler, user_data); 59| 0| } 60| | 61| 0| ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } 62| | }; 63| | 64| | /// Reports a serious error, calling any installed error handler. These 65| | /// functions are intended to be used for error conditions which are outside 66| | /// the control of the compiler (I/O errors, invalid user input, etc.) 67| | /// 68| | /// If no error handler is installed the default is to print the message to 69| | /// standard error, followed by a newline. 70| | /// After the error handler is called this function will call exit(1), it 71| | /// does not return. 72| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, 73| | bool gen_crash_diag = true); 74| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, 75| | bool gen_crash_diag = true); 76| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, 77| | bool gen_crash_diag = true); 78| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, 79| | bool gen_crash_diag = true); 80| | 81| | /// This function calls abort(), and prints the optional message to stderr. 82| | /// Use the llvm_unreachable macro (that adds location info), instead of 83| | /// calling this function directly. 84| | LLVM_ATTRIBUTE_NORETURN void 85| | llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, 86| | unsigned line=0); 87| |} 88| | 89| |/// Marks that the current location is not supposed to be reachable. 90| |/// In !NDEBUG builds, prints the message and location info to stderr. 91| |/// In NDEBUG builds, becomes an optimizer hint that the current location 92| |/// is not supposed to be reachable. On compilers that don't support 93| |/// such hints, prints a reduced message instead. 94| |/// 95| |/// Use this instead of assert(0). It conveys intent more clearly and 96| |/// allows compilers to omit some unnecessary code. 97| |#ifndef NDEBUG 98| |#define llvm_unreachable(msg) \ 99| | ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) 100| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 101| |#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE 102| |#else 103| |#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() 104| |#endif 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MathExtras.h: 1| |//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful for math stuff. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MATHEXTRAS_H 15| |#define LLVM_SUPPORT_MATHEXTRAS_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/SwapByteOrder.h" 19| |#include 20| |#include 21| |#include 22| | 23| |#ifdef _MSC_VER 24| |#include 25| |#endif 26| | 27| |namespace llvm { 28| |/// \brief The behavior an operation has on an input of 0. 29| |enum ZeroBehavior { 30| | /// \brief The returned value is undefined. 31| | ZB_Undefined, 32| | /// \brief The returned value is numeric_limits::max() 33| | ZB_Max, 34| | /// \brief The returned value is numeric_limits::digits 35| | ZB_Width 36| |}; 37| | 38| |namespace detail { 39| |template struct TrailingZerosCounter { 40| | static std::size_t count(T Val, ZeroBehavior) { 41| | if (!Val) 42| | return std::numeric_limits::digits; 43| | if (Val & 0x1) 44| | return 0; 45| | 46| | // Bisection method. 47| | std::size_t ZeroBits = 0; 48| | T Shift = std::numeric_limits::digits >> 1; 49| | T Mask = std::numeric_limits::max() >> Shift; 50| | while (Shift) { 51| | if ((Val & Mask) == 0) { 52| | Val >>= Shift; 53| | ZeroBits |= Shift; 54| | } 55| | Shift >>= 1; 56| | Mask >>= Shift; 57| | } 58| | return ZeroBits; 59| | } 60| |}; 61| | 62| |#if __GNUC__ >= 4 || _MSC_VER 63| |template struct TrailingZerosCounter { 64| | static std::size_t count(T Val, ZeroBehavior ZB) { 65| | if (ZB != ZB_Undefined && Val == 0) 66| | return 32; 67| | 68| |#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) 69| | return __builtin_ctz(Val); 70| |#elif _MSC_VER 71| | unsigned long Index; 72| | _BitScanForward(&Index, Val); 73| | return Index; 74| |#endif 75| | } 76| |}; 77| | 78| |#if !defined(_MSC_VER) || defined(_M_X64) 79| |template struct TrailingZerosCounter { 80| | static std::size_t count(T Val, ZeroBehavior ZB) { 81| | if (ZB != ZB_Undefined && Val == 0) 82| | return 64; 83| | 84| |#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) 85| | return __builtin_ctzll(Val); 86| |#elif _MSC_VER 87| | unsigned long Index; 88| | _BitScanForward64(&Index, Val); 89| | return Index; 90| |#endif 91| | } 92| |}; 93| |#endif 94| |#endif 95| |} // namespace detail 96| | 97| |/// \brief Count number of 0's from the least significant bit to the most 98| |/// stopping at the first 1. 99| |/// 100| |/// Only unsigned integral types are allowed. 101| |/// 102| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 103| |/// valid arguments. 104| |template 105| |std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 106| | static_assert(std::numeric_limits::is_integer && 107| | !std::numeric_limits::is_signed, 108| | "Only unsigned integral types are allowed."); 109| | return detail::TrailingZerosCounter::count(Val, ZB); 110| |} 111| | 112| |namespace detail { 113| |template struct LeadingZerosCounter { 114| | static std::size_t count(T Val, ZeroBehavior) { 115| | if (!Val) 116| | return std::numeric_limits::digits; 117| | 118| | // Bisection method. 119| | std::size_t ZeroBits = 0; 120| | for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) { 121| | T Tmp = Val >> Shift; 122| | if (Tmp) 123| | Val = Tmp; 124| | else 125| | ZeroBits |= Shift; 126| | } 127| | return ZeroBits; 128| | } 129| |}; 130| | 131| |#if __GNUC__ >= 4 || _MSC_VER 132| |template struct LeadingZerosCounter { 133| | static std::size_t count(T Val, ZeroBehavior ZB) { 134| | if (ZB != ZB_Undefined && Val == 0) 135| | return 32; 136| | 137| |#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) 138| | return __builtin_clz(Val); 139| |#elif _MSC_VER 140| | unsigned long Index; 141| | _BitScanReverse(&Index, Val); 142| | return Index ^ 31; 143| |#endif 144| | } 145| |}; 146| | 147| |#if !defined(_MSC_VER) || defined(_M_X64) 148| |template struct LeadingZerosCounter { 149| | static std::size_t count(T Val, ZeroBehavior ZB) { 150| | if (ZB != ZB_Undefined && Val == 0) 151| | return 64; 152| | 153| |#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) 154| | return __builtin_clzll(Val); 155| |#elif _MSC_VER 156| | unsigned long Index; 157| | _BitScanReverse64(&Index, Val); 158| | return Index ^ 63; 159| |#endif 160| | } 161| |}; 162| |#endif 163| |#endif 164| |} // namespace detail 165| | 166| |/// \brief Count number of 0's from the most significant bit to the least 167| |/// stopping at the first 1. 168| |/// 169| |/// Only unsigned integral types are allowed. 170| |/// 171| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 172| |/// valid arguments. 173| |template 174| |std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 175| | static_assert(std::numeric_limits::is_integer && 176| | !std::numeric_limits::is_signed, 177| | "Only unsigned integral types are allowed."); 178| | return detail::LeadingZerosCounter::count(Val, ZB); 179| |} 180| | 181| |/// \brief Get the index of the first set bit starting from the least 182| |/// significant bit. 183| |/// 184| |/// Only unsigned integral types are allowed. 185| |/// 186| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 187| |/// valid arguments. 188| |template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { 189| | if (ZB == ZB_Max && Val == 0) 190| | return std::numeric_limits::max(); 191| | 192| | return countTrailingZeros(Val, ZB_Undefined); 193| |} 194| | 195| |/// \brief Get the index of the last set bit starting from the least 196| |/// significant bit. 197| |/// 198| |/// Only unsigned integral types are allowed. 199| |/// 200| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 201| |/// valid arguments. 202| |template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { 203| | if (ZB == ZB_Max && Val == 0) 204| | return std::numeric_limits::max(); 205| | 206| | // Use ^ instead of - because both gcc and llvm can remove the associated ^ 207| | // in the __builtin_clz intrinsic on x86. 208| | return countLeadingZeros(Val, ZB_Undefined) ^ 209| | (std::numeric_limits::digits - 1); 210| |} 211| | 212| |/// \brief Macro compressed bit reversal table for 256 bits. 213| |/// 214| |/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable 215| |static const unsigned char BitReverseTable256[256] = { 216| |#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 217| |#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) 218| |#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) 219| | R6(0), R6(2), R6(1), R6(3) 220| |#undef R2 221| |#undef R4 222| |#undef R6 223| |}; 224| | 225| |/// \brief Reverse the bits in \p Val. 226| |template 227| |T reverseBits(T Val) { 228| | unsigned char in[sizeof(Val)]; 229| | unsigned char out[sizeof(Val)]; 230| | std::memcpy(in, &Val, sizeof(Val)); 231| | for (unsigned i = 0; i < sizeof(Val); ++i) 232| | out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; 233| | std::memcpy(&Val, out, sizeof(Val)); 234| | return Val; 235| |} 236| | 237| |// NOTE: The following support functions use the _32/_64 extensions instead of 238| |// type overloading so that signed and unsigned integers can be used without 239| |// ambiguity. 240| | 241| |/// Hi_32 - This function returns the high 32 bits of a 64 bit value. 242| 0|inline uint32_t Hi_32(uint64_t Value) { 243| 0| return static_cast(Value >> 32); 244| 0|} 245| | 246| |/// Lo_32 - This function returns the low 32 bits of a 64 bit value. 247| 0|inline uint32_t Lo_32(uint64_t Value) { 248| 0| return static_cast(Value); 249| 0|} 250| | 251| |/// Make_64 - This functions makes a 64-bit integer from a high / low pair of 252| |/// 32-bit integers. 253| 0|inline uint64_t Make_64(uint32_t High, uint32_t Low) { 254| 0| return ((uint64_t)High << 32) | (uint64_t)Low; 255| 0|} 256| | 257| |/// isInt - Checks if an integer fits into the given bit width. 258| |template 259| |inline bool isInt(int64_t x) { 260| | return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 261| |} 262| |// Template specializations to get better code for common cases. 263| |template<> 264| 0|inline bool isInt<8>(int64_t x) { 265| 0| return static_cast(x) == x; 266| 0|} 267| |template<> 268| 0|inline bool isInt<16>(int64_t x) { 269| 0| return static_cast(x) == x; 270| 0|} 271| |template<> 272| 0|inline bool isInt<32>(int64_t x) { 273| 0| return static_cast(x) == x; 274| 0|} 275| | 276| |/// isShiftedInt - Checks if a signed integer is an N bit number shifted 277| |/// left by S. 278| |template 279| |inline bool isShiftedInt(int64_t x) { 280| | return isInt(x) && (x % (1< 285| |inline bool isUInt(uint64_t x) { 286| | return N >= 64 || x < (UINT64_C(1)<<(N)); 287| |} 288| |// Template specializations to get better code for common cases. 289| |template<> 290| 0|inline bool isUInt<8>(uint64_t x) { 291| 0| return static_cast(x) == x; 292| 0|} 293| |template<> 294| 0|inline bool isUInt<16>(uint64_t x) { 295| 0| return static_cast(x) == x; 296| 0|} 297| |template<> 298| 0|inline bool isUInt<32>(uint64_t x) { 299| 0| return static_cast(x) == x; 300| 0|} 301| | 302| |/// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted 303| |/// left by S. 304| |template 305| |inline bool isShiftedUInt(uint64_t x) { 306| | return isUInt(x) && (x % (1<> (64 - N))); 313| 0|} 314| | 315| |/// isIntN - Checks if an signed integer fits into the given (dynamic) 316| |/// bit width. 317| 0|inline bool isIntN(unsigned N, int64_t x) { 318| 0| return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 319| 0|} 320| | 321| |/// isMask_32 - This function returns true if the argument is a sequence of ones 322| |/// starting at the least significant bit with the remainder zero (32 bit 323| |/// version). Ex. isMask_32(0x0000FFFFU) == true. 324| 0|inline bool isMask_32(uint32_t Value) { 325| 0| return Value && ((Value + 1) & Value) == 0; 326| 0|} 327| | 328| |/// isMask_64 - This function returns true if the argument is a sequence of ones 329| |/// starting at the least significant bit with the remainder zero (64 bit 330| |/// version). 331| 0|inline bool isMask_64(uint64_t Value) { 332| 0| return Value && ((Value + 1) & Value) == 0; 333| 0|} 334| | 335| |/// isShiftedMask_32 - This function returns true if the argument contains a 336| |/// sequence of ones with the remainder zero (32 bit version.) 337| |/// Ex. isShiftedMask_32(0x0000FF00U) == true. 338| 0|inline bool isShiftedMask_32(uint32_t Value) { 339| 0| return isMask_32((Value - 1) | Value); 340| 0|} 341| | 342| |/// isShiftedMask_64 - This function returns true if the argument contains a 343| |/// sequence of ones with the remainder zero (64 bit version.) 344| 0|inline bool isShiftedMask_64(uint64_t Value) { 345| 0| return isMask_64((Value - 1) | Value); 346| 0|} 347| | 348| |/// isPowerOf2_32 - This function returns true if the argument is a power of 349| |/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) 350| 0|inline bool isPowerOf2_32(uint32_t Value) { 351| 0| return Value && !(Value & (Value - 1)); 352| 0|} 353| | 354| |/// isPowerOf2_64 - This function returns true if the argument is a power of two 355| |/// > 0 (64 bit edition.) 356| |inline bool isPowerOf2_64(uint64_t Value) { 357| | return Value && !(Value & (Value - int64_t(1L))); 358| |} 359| | 360| |/// ByteSwap_16 - This function returns a byte-swapped representation of the 361| |/// 16-bit argument, Value. 362| 0|inline uint16_t ByteSwap_16(uint16_t Value) { 363| 0| return sys::SwapByteOrder_16(Value); 364| 0|} 365| | 366| |/// ByteSwap_32 - This function returns a byte-swapped representation of the 367| |/// 32-bit argument, Value. 368| 0|inline uint32_t ByteSwap_32(uint32_t Value) { 369| 0| return sys::SwapByteOrder_32(Value); 370| 0|} 371| | 372| |/// ByteSwap_64 - This function returns a byte-swapped representation of the 373| |/// 64-bit argument, Value. 374| 0|inline uint64_t ByteSwap_64(uint64_t Value) { 375| 0| return sys::SwapByteOrder_64(Value); 376| 0|} 377| | 378| |/// \brief Count the number of ones from the most significant bit to the first 379| |/// zero bit. 380| |/// 381| |/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. 382| |/// Only unsigned integral types are allowed. 383| |/// 384| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 385| |/// ZB_Undefined are valid arguments. 386| |template 387| |std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 388| | static_assert(std::numeric_limits::is_integer && 389| | !std::numeric_limits::is_signed, 390| | "Only unsigned integral types are allowed."); 391| | return countLeadingZeros(~Value, ZB); 392| |} 393| | 394| |/// \brief Count the number of ones from the least significant bit to the first 395| |/// zero bit. 396| |/// 397| |/// Ex. countTrailingOnes(0x00FF00FF) == 8. 398| |/// Only unsigned integral types are allowed. 399| |/// 400| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 401| |/// ZB_Undefined are valid arguments. 402| |template 403| |std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 404| | static_assert(std::numeric_limits::is_integer && 405| | !std::numeric_limits::is_signed, 406| | "Only unsigned integral types are allowed."); 407| | return countTrailingZeros(~Value, ZB); 408| |} 409| | 410| |namespace detail { 411| |template struct PopulationCounter { 412| | static unsigned count(T Value) { 413| | // Generic version, forward to 32 bits. 414| | static_assert(SizeOfT <= 4, "Not implemented!"); 415| |#if __GNUC__ >= 4 416| | return __builtin_popcount(Value); 417| |#else 418| | uint32_t v = Value; 419| | v = v - ((v >> 1) & 0x55555555); 420| | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 421| | return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 422| |#endif 423| | } 424| |}; 425| | 426| |template struct PopulationCounter { 427| | static unsigned count(T Value) { 428| |#if __GNUC__ >= 4 429| | return __builtin_popcountll(Value); 430| |#else 431| | uint64_t v = Value; 432| | v = v - ((v >> 1) & 0x5555555555555555ULL); 433| | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 434| | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 435| | return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); 436| |#endif 437| | } 438| |}; 439| |} // namespace detail 440| | 441| |/// \brief Count the number of set bits in a value. 442| |/// Ex. countPopulation(0xF000F000) = 8 443| |/// Returns 0 if the word is zero. 444| |template 445| |inline unsigned countPopulation(T Value) { 446| | static_assert(std::numeric_limits::is_integer && 447| | !std::numeric_limits::is_signed, 448| | "Only unsigned integral types are allowed."); 449| | return detail::PopulationCounter::count(Value); 450| |} 451| | 452| |/// Log2_32 - This function returns the floor log base 2 of the specified value, 453| |/// -1 if the value is zero. (32 bit edition.) 454| |/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 455| 0|inline unsigned Log2_32(uint32_t Value) { 456| 0| return 31 - countLeadingZeros(Value); 457| 0|} 458| | 459| |/// Log2_64 - This function returns the floor log base 2 of the specified value, 460| |/// -1 if the value is zero. (64 bit edition.) 461| 0|inline unsigned Log2_64(uint64_t Value) { 462| 0| return 63 - countLeadingZeros(Value); 463| 0|} 464| | 465| |/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified 466| |/// value, 32 if the value is zero. (32 bit edition). 467| |/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 468| |inline unsigned Log2_32_Ceil(uint32_t Value) { 469| | return 32 - countLeadingZeros(Value - 1); 470| |} 471| | 472| |/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified 473| |/// value, 64 if the value is zero. (64 bit edition.) 474| 0|inline unsigned Log2_64_Ceil(uint64_t Value) { 475| 0| return 64 - countLeadingZeros(Value - 1); 476| 0|} 477| | 478| |/// GreatestCommonDivisor64 - Return the greatest common divisor of the two 479| |/// values using Euclid's algorithm. 480| 0|inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { 481| 0| while (B) { 482| 0| uint64_t T = B; 483| 0| B = A % B; 484| 0| A = T; 485| 0| } 486| 0| return A; 487| 0|} 488| | 489| |/// BitsToDouble - This function takes a 64-bit integer and returns the bit 490| |/// equivalent double. 491| 0|inline double BitsToDouble(uint64_t Bits) { 492| 0| union { 493| 0| uint64_t L; 494| 0| double D; 495| 0| } T; 496| 0| T.L = Bits; 497| 0| return T.D; 498| 0|} 499| | 500| |/// BitsToFloat - This function takes a 32-bit integer and returns the bit 501| |/// equivalent float. 502| 0|inline float BitsToFloat(uint32_t Bits) { 503| 0| union { 504| 0| uint32_t I; 505| 0| float F; 506| 0| } T; 507| 0| T.I = Bits; 508| 0| return T.F; 509| 0|} 510| | 511| |/// DoubleToBits - This function takes a double and returns the bit 512| |/// equivalent 64-bit integer. Note that copying doubles around 513| |/// changes the bits of NaNs on some hosts, notably x86, so this 514| |/// routine cannot be used if these bits are needed. 515| 0|inline uint64_t DoubleToBits(double Double) { 516| 0| union { 517| 0| uint64_t L; 518| 0| double D; 519| 0| } T; 520| 0| T.D = Double; 521| 0| return T.L; 522| 0|} 523| | 524| |/// FloatToBits - This function takes a float and returns the bit 525| |/// equivalent 32-bit integer. Note that copying floats around 526| |/// changes the bits of NaNs on some hosts, notably x86, so this 527| |/// routine cannot be used if these bits are needed. 528| 0|inline uint32_t FloatToBits(float Float) { 529| 0| union { 530| 0| uint32_t I; 531| 0| float F; 532| 0| } T; 533| 0| T.F = Float; 534| 0| return T.I; 535| 0|} 536| | 537| |/// MinAlign - A and B are either alignments or offsets. Return the minimum 538| |/// alignment that may be assumed after adding the two together. 539| 0|inline uint64_t MinAlign(uint64_t A, uint64_t B) { 540| 0| // The largest power of 2 that divides both A and B. 541| 0| // 542| 0| // Replace "-Value" by "1+~Value" in the following commented code to avoid 543| 0| // MSVC warning C4146 544| 0| // return (A | B) & -(A | B); 545| 0| return (A | B) & (1 + ~(A | B)); 546| 0|} 547| | 548| |/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. 549| |/// 550| |/// Alignment should be a power of two. This method rounds up, so 551| |/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. 552| |inline uintptr_t alignAddr(void *Addr, size_t Alignment) { 553| | assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && 554| | "Alignment is not a power of two!"); 555| | 556| | assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); 557| | 558| | return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); 559| |} 560| | 561| |/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment 562| |/// bytes, rounding up. 563| |inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { 564| | return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; 565| |} 566| | 567| |/// NextPowerOf2 - Returns the next power of two (in 64-bits) 568| |/// that is strictly greater than A. Returns zero on overflow. 569| |inline uint64_t NextPowerOf2(uint64_t A) { 570| | A |= (A >> 1); 571| | A |= (A >> 2); 572| | A |= (A >> 4); 573| | A |= (A >> 8); 574| | A |= (A >> 16); 575| | A |= (A >> 32); 576| | return A + 1; 577| |} 578| | 579| |/// Returns the power of two which is less than or equal to the given value. 580| |/// Essentially, it is a floor operation across the domain of powers of two. 581| 0|inline uint64_t PowerOf2Floor(uint64_t A) { 582| 0| if (!A) return 0; 583| 0| return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); 584| 0|} 585| | 586| |/// Returns the next integer (mod 2**64) that is greater than or equal to 587| |/// \p Value and is a multiple of \p Align. \p Align must be non-zero. 588| |/// 589| |/// Examples: 590| |/// \code 591| |/// RoundUpToAlignment(5, 8) = 8 592| |/// RoundUpToAlignment(17, 8) = 24 593| |/// RoundUpToAlignment(~0LL, 8) = 0 594| |/// RoundUpToAlignment(321, 255) = 510 595| |/// \endcode 596| |inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { 597| | return (Value + Align - 1) / Align * Align; 598| |} 599| | 600| |/// Returns the offset to the next integer (mod 2**64) that is greater than 601| |/// or equal to \p Value and is a multiple of \p Align. \p Align must be 602| |/// non-zero. 603| 0|inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { 604| 0| return RoundUpToAlignment(Value, Align) - Value; 605| 0|} 606| | 607| |/// SignExtend32 - Sign extend B-bit number x to 32-bit int. 608| |/// Usage int32_t r = SignExtend32<5>(x); 609| |template inline int32_t SignExtend32(uint32_t x) { 610| | return int32_t(x << (32 - B)) >> (32 - B); 611| |} 612| | 613| |/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. 614| |/// Requires 0 < B <= 32. 615| 0|inline int32_t SignExtend32(uint32_t X, unsigned B) { 616| 0| return int32_t(X << (32 - B)) >> (32 - B); 617| 0|} 618| | 619| |/// SignExtend64 - Sign extend B-bit number x to 64-bit int. 620| |/// Usage int64_t r = SignExtend64<5>(x); 621| |template inline int64_t SignExtend64(uint64_t x) { 622| | return int64_t(x << (64 - B)) >> (64 - B); 623| |} 624| | 625| |/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. 626| |/// Requires 0 < B <= 64. 627| 0|inline int64_t SignExtend64(uint64_t X, unsigned B) { 628| 0| return int64_t(X << (64 - B)) >> (64 - B); 629| 0|} 630| | 631| |extern const float huge_valf; 632| |} // End llvm namespace 633| | 634| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Memory.h: 1| |//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Memory class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORY_H 15| |#define LLVM_SUPPORT_MEMORY_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| | /// This class encapsulates the notion of a memory block which has an address 25| | /// and a size. It is used by the Memory class (a friend) as the result of 26| | /// various memory allocation operations. 27| | /// @see Memory 28| | /// @brief Memory block abstraction. 29| | class MemoryBlock { 30| | public: 31| 0| MemoryBlock() : Address(nullptr), Size(0) { } 32| 0| MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } 33| | void *base() const { return Address; } 34| | size_t size() const { return Size; } 35| | private: 36| | void *Address; ///< Address of first byte of memory area 37| | size_t Size; ///< Size, in bytes of the memory area 38| | friend class Memory; 39| | }; 40| | 41| | /// This class provides various memory handling functions that manipulate 42| | /// MemoryBlock instances. 43| | /// @since 1.4 44| | /// @brief An abstraction for memory operations. 45| | class Memory { 46| | public: 47| | enum ProtectionFlags { 48| | MF_READ = 0x1000000, 49| | MF_WRITE = 0x2000000, 50| | MF_EXEC = 0x4000000 51| | }; 52| | 53| | /// This method allocates a block of memory that is suitable for loading 54| | /// dynamically generated code (e.g. JIT). An attempt to allocate 55| | /// \p NumBytes bytes of virtual memory is made. 56| | /// \p NearBlock may point to an existing allocation in which case 57| | /// an attempt is made to allocate more memory near the existing block. 58| | /// The actual allocated address is not guaranteed to be near the requested 59| | /// address. 60| | /// \p Flags is used to set the initial protection flags for the block 61| | /// of the memory. 62| | /// \p EC [out] returns an object describing any error that occurs. 63| | /// 64| | /// This method may allocate more than the number of bytes requested. The 65| | /// actual number of bytes allocated is indicated in the returned 66| | /// MemoryBlock. 67| | /// 68| | /// The start of the allocated block must be aligned with the 69| | /// system allocation granularity (64K on Windows, page size on Linux). 70| | /// If the address following \p NearBlock is not so aligned, it will be 71| | /// rounded up to the next allocation granularity boundary. 72| | /// 73| | /// \r a non-null MemoryBlock if the function was successful, 74| | /// otherwise a null MemoryBlock is with \p EC describing the error. 75| | /// 76| | /// @brief Allocate mapped memory. 77| | static MemoryBlock allocateMappedMemory(size_t NumBytes, 78| | const MemoryBlock *const NearBlock, 79| | unsigned Flags, 80| | std::error_code &EC); 81| | 82| | /// This method releases a block of memory that was allocated with the 83| | /// allocateMappedMemory method. It should not be used to release any 84| | /// memory block allocated any other way. 85| | /// \p Block describes the memory to be released. 86| | /// 87| | /// \r error_success if the function was successful, or an error_code 88| | /// describing the failure if an error occurred. 89| | /// 90| | /// @brief Release mapped memory. 91| | static std::error_code releaseMappedMemory(MemoryBlock &Block); 92| | 93| | /// This method sets the protection flags for a block of memory to the 94| | /// state specified by /p Flags. The behavior is not specified if the 95| | /// memory was not allocated using the allocateMappedMemory method. 96| | /// \p Block describes the memory block to be protected. 97| | /// \p Flags specifies the new protection state to be assigned to the block. 98| | /// \p ErrMsg [out] returns a string describing any error that occurred. 99| | /// 100| | /// If \p Flags is MF_WRITE, the actual behavior varies 101| | /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the 102| | /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 103| | /// 104| | /// \r error_success if the function was successful, or an error_code 105| | /// describing the failure if an error occurred. 106| | /// 107| | /// @brief Set memory protection state. 108| | static std::error_code protectMappedMemory(const MemoryBlock &Block, 109| | unsigned Flags); 110| | 111| | /// This method allocates a block of Read/Write/Execute memory that is 112| | /// suitable for executing dynamically generated code (e.g. JIT). An 113| | /// attempt to allocate \p NumBytes bytes of virtual memory is made. 114| | /// \p NearBlock may point to an existing allocation in which case 115| | /// an attempt is made to allocate more memory near the existing block. 116| | /// 117| | /// On success, this returns a non-null memory block, otherwise it returns 118| | /// a null memory block and fills in *ErrMsg. 119| | /// 120| | /// @brief Allocate Read/Write/Execute memory. 121| | static MemoryBlock AllocateRWX(size_t NumBytes, 122| | const MemoryBlock *NearBlock, 123| | std::string *ErrMsg = nullptr); 124| | 125| | /// This method releases a block of Read/Write/Execute memory that was 126| | /// allocated with the AllocateRWX method. It should not be used to 127| | /// release any memory block allocated any other way. 128| | /// 129| | /// On success, this returns false, otherwise it returns true and fills 130| | /// in *ErrMsg. 131| | /// @brief Release Read/Write/Execute memory. 132| | static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); 133| | 134| | 135| | /// InvalidateInstructionCache - Before the JIT can run a block of code 136| | /// that has been emitted it must invalidate the instruction cache on some 137| | /// platforms. 138| | static void InvalidateInstructionCache(const void *Addr, size_t Len); 139| | 140| | /// setExecutable - Before the JIT can run a block of code, it has to be 141| | /// given read and executable privilege. Return true if it is already r-x 142| | /// or the system is able to change its previlege. 143| | static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); 144| | 145| | /// setWritable - When adding to a block of code, the JIT may need 146| | /// to mark a block of code as RW since the protections are on page 147| | /// boundaries, and the JIT internal allocations are not page aligned. 148| | static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); 149| | 150| | /// setRangeExecutable - Mark the page containing a range of addresses 151| | /// as executable. 152| | static bool setRangeExecutable(const void *Addr, size_t Size); 153| | 154| | /// setRangeWritable - Mark the page containing a range of addresses 155| | /// as writable. 156| | static bool setRangeWritable(const void *Addr, size_t Size); 157| | }; 158| |} 159| |} 160| | 161| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MemoryBuffer.h: 1| |//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the MemoryBuffer interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORYBUFFER_H 15| |#define LLVM_SUPPORT_MEMORYBUFFER_H 16| | 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/Support/CBindingWrapping.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include "llvm/Support/ErrorOr.h" 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |class MemoryBufferRef; 27| | 28| |/// This interface provides simple read-only access to a block of memory, and 29| |/// provides simple methods for reading files and standard input into a memory 30| |/// buffer. In addition to basic access to the characters in the file, this 31| |/// interface guarantees you can read one character past the end of the file, 32| |/// and that this character will read as '\0'. 33| |/// 34| |/// The '\0' guarantee is needed to support an optimization -- it's intended to 35| |/// be more efficient for clients which are reading all the data to stop 36| |/// reading when they encounter a '\0' than to continually check the file 37| |/// position to see if it has reached the end of the file. 38| |class MemoryBuffer { 39| | const char *BufferStart; // Start of the buffer. 40| | const char *BufferEnd; // End of the buffer. 41| | 42| | MemoryBuffer(const MemoryBuffer &) = delete; 43| | MemoryBuffer &operator=(const MemoryBuffer &) = delete; 44| |protected: 45| 0| MemoryBuffer() {} 46| | void init(const char *BufStart, const char *BufEnd, 47| | bool RequiresNullTerminator); 48| |public: 49| | virtual ~MemoryBuffer(); 50| | 51| 0| const char *getBufferStart() const { return BufferStart; } 52| | const char *getBufferEnd() const { return BufferEnd; } 53| 0| size_t getBufferSize() const { return BufferEnd-BufferStart; } 54| | 55| 0| StringRef getBuffer() const { 56| 0| return StringRef(BufferStart, getBufferSize()); 57| 0| } 58| | 59| | /// Return an identifier for this buffer, typically the filename it was read 60| | /// from. 61| | virtual const char *getBufferIdentifier() const { 62| | return "Unknown buffer"; 63| | } 64| | 65| | /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer 66| | /// if successful, otherwise returning null. If FileSize is specified, this 67| | /// means that the client knows that the file exists and that it has the 68| | /// specified size. 69| | /// 70| | /// \param IsVolatileSize Set to true to indicate that the file size may be 71| | /// changing, e.g. when libclang tries to parse while the user is 72| | /// editing/updating the file. 73| | static ErrorOr> 74| | getFile(const Twine &Filename, int64_t FileSize = -1, 75| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 76| | 77| | /// Given an already-open file descriptor, map some slice of it into a 78| | /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. 79| | /// Since this is in the middle of a file, the buffer is not null terminated. 80| | static ErrorOr> 81| | getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, 82| | int64_t Offset); 83| | 84| | /// Given an already-open file descriptor, read the file and return a 85| | /// MemoryBuffer. 86| | /// 87| | /// \param IsVolatileSize Set to true to indicate that the file size may be 88| | /// changing, e.g. when libclang tries to parse while the user is 89| | /// editing/updating the file. 90| | static ErrorOr> 91| | getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, 92| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 93| | 94| | /// Open the specified memory range as a MemoryBuffer. Note that InputData 95| | /// must be null terminated if RequiresNullTerminator is true. 96| | static std::unique_ptr 97| | getMemBuffer(StringRef InputData, StringRef BufferName = "", 98| | bool RequiresNullTerminator = true); 99| | 100| | static std::unique_ptr 101| | getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); 102| | 103| | /// Open the specified memory range as a MemoryBuffer, copying the contents 104| | /// and taking ownership of it. InputData does not have to be null terminated. 105| | static std::unique_ptr 106| | getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); 107| | 108| | /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note 109| | /// that the caller need not initialize the memory allocated by this method. 110| | /// The memory is owned by the MemoryBuffer object. 111| | static std::unique_ptr 112| | getNewMemBuffer(size_t Size, StringRef BufferName = ""); 113| | 114| | /// Allocate a new MemoryBuffer of the specified size that is not initialized. 115| | /// Note that the caller should initialize the memory allocated by this 116| | /// method. The memory is owned by the MemoryBuffer object. 117| | static std::unique_ptr 118| | getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); 119| | 120| | /// Read all of stdin into a file buffer, and return it. 121| | static ErrorOr> getSTDIN(); 122| | 123| | /// Open the specified file as a MemoryBuffer, or open stdin if the Filename 124| | /// is "-". 125| | static ErrorOr> 126| | getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1); 127| | 128| | /// Map a subrange of the the specified file as a MemoryBuffer. 129| | static ErrorOr> 130| | getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); 131| | 132| | //===--------------------------------------------------------------------===// 133| | // Provided for performance analysis. 134| | //===--------------------------------------------------------------------===// 135| | 136| | /// The kind of memory backing used to support the MemoryBuffer. 137| | enum BufferKind { 138| | MemoryBuffer_Malloc, 139| | MemoryBuffer_MMap 140| | }; 141| | 142| | /// Return information on the memory mechanism used to support the 143| | /// MemoryBuffer. 144| | virtual BufferKind getBufferKind() const = 0; 145| | 146| | MemoryBufferRef getMemBufferRef() const; 147| |}; 148| | 149| |class MemoryBufferRef { 150| | StringRef Buffer; 151| | StringRef Identifier; 152| | 153| |public: 154| 0| MemoryBufferRef() {} 155| | MemoryBufferRef(StringRef Buffer, StringRef Identifier) 156| 0| : Buffer(Buffer), Identifier(Identifier) {} 157| | 158| | StringRef getBuffer() const { return Buffer; } 159| | 160| | StringRef getBufferIdentifier() const { return Identifier; } 161| | 162| | const char *getBufferStart() const { return Buffer.begin(); } 163| | const char *getBufferEnd() const { return Buffer.end(); } 164| 0| size_t getBufferSize() const { return Buffer.size(); } 165| |}; 166| | 167| |// Create wrappers for C Binding types (see CBindingWrapping.h). 168| |typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; 169| |DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) 170| | 171| |} // end namespace llvm 172| | 173| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/PointerLikeTypeTraits.h: 1| |//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the PointerLikeTypeTraits class. This allows data 11| |// structures to reason about pointers and other things that are pointer sized. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 16| |#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 17| | 18| |#include "llvm/Support/DataTypes.h" 19| | 20| |namespace llvm { 21| | 22| |/// PointerLikeTypeTraits - This is a traits object that is used to handle 23| |/// pointer types and things that are just wrappers for pointers as a uniform 24| |/// entity. 25| |template 26| |class PointerLikeTypeTraits { 27| | // getAsVoidPointer 28| | // getFromVoidPointer 29| | // getNumLowBitsAvailable 30| |}; 31| | 32| |// Provide PointerLikeTypeTraits for non-cvr pointers. 33| |template 34| |class PointerLikeTypeTraits { 35| |public: 36| | static inline void *getAsVoidPointer(T* P) { return P; } 37| 0| static inline T *getFromVoidPointer(void *P) { 38| 0| return static_cast(P); 39| 0| } 40| | 41| | /// Note, we assume here that malloc returns objects at least 4-byte aligned. 42| | /// However, this may be wrong, or pointers may be from something other than 43| | /// malloc. In this case, you should specialize this template to reduce this. 44| | /// 45| | /// All clients should use assertions to do a run-time check to ensure that 46| | /// this is actually true. 47| | enum { NumLowBitsAvailable = 2 }; 48| |}; 49| | 50| |// Provide PointerLikeTypeTraits for const pointers. 51| |template 52| |class PointerLikeTypeTraits { 53| | typedef PointerLikeTypeTraits NonConst; 54| | 55| |public: 56| | static inline const void *getAsVoidPointer(const T* P) { 57| | return NonConst::getAsVoidPointer(const_cast(P)); 58| | } 59| | static inline const T *getFromVoidPointer(const void *P) { 60| | return NonConst::getFromVoidPointer(const_cast(P)); 61| | } 62| | enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; 63| |}; 64| | 65| |// Provide PointerLikeTypeTraits for uintptr_t. 66| |template<> 67| |class PointerLikeTypeTraits { 68| |public: 69| 0| static inline void *getAsVoidPointer(uintptr_t P) { 70| 0| return reinterpret_cast(P); 71| 0| } 72| 0| static inline uintptr_t getFromVoidPointer(void *P) { 73| 0| return reinterpret_cast(P); 74| 0| } 75| | // No bits are available! 76| | enum { NumLowBitsAvailable = 0 }; 77| |}; 78| | 79| |} // end namespace llvm 80| | 81| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SMLoc.h: 1| |//===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMLoc class. This class encapsulates a location in 11| |// source code for use in diagnostics. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SMLOC_H 16| |#define LLVM_SUPPORT_SMLOC_H 17| | 18| |#include 19| | 20| |namespace llvm { 21| | 22| |/// Represents a location in source code. 23| |class SMLoc { 24| | const char *Ptr; 25| |public: 26| 0| SMLoc() : Ptr(nullptr) {} 27| | 28| | bool isValid() const { return Ptr != nullptr; } 29| | 30| | bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } 31| | bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } 32| | 33| | const char *getPointer() const { return Ptr; } 34| | 35| | static SMLoc getFromPointer(const char *Ptr) { 36| | SMLoc L; 37| | L.Ptr = Ptr; 38| | return L; 39| | } 40| |}; 41| | 42| |/// Represents a range in source code. 43| |/// 44| |/// SMRange is implemented using a half-open range, as is the convention in C++. 45| |/// In the string "abc", the range (1,3] represents the substring "bc", and the 46| |/// range (2,2] represents an empty range between the characters "b" and "c". 47| |class SMRange { 48| |public: 49| | SMLoc Start, End; 50| | 51| 0| SMRange() {} 52| | SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { 53| | assert(Start.isValid() == End.isValid() && 54| | "Start and end should either both be valid or both be invalid!"); 55| | } 56| | 57| | bool isValid() const { return Start.isValid(); } 58| |}; 59| | 60| |} // end namespace llvm 61| | 62| |#endif 63| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SourceMgr.h: 1| |//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMDiagnostic and SourceMgr classes. This 11| |// provides a simple substrate for diagnostics, #include handling, and other low 12| |// level things for simple parsers. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_SOURCEMGR_H 17| |#define LLVM_SUPPORT_SOURCEMGR_H 18| | 19| |#include "llvm/ADT/ArrayRef.h" 20| |#include "llvm/ADT/StringRef.h" 21| |#include "llvm/ADT/Twine.h" 22| |#include "llvm/Support/MemoryBuffer.h" 23| |#include "llvm/Support/SMLoc.h" 24| |#include 25| | 26| |namespace llvm { 27| | class SourceMgr; 28| | class SMDiagnostic; 29| | class SMFixIt; 30| | class Twine; 31| | class raw_ostream; 32| | 33| |/// This owns the files read by a parser, handles include stacks, 34| |/// and handles diagnostic wrangling. 35| |class SourceMgr { 36| |public: 37| | enum DiagKind { 38| | DK_Error, 39| | DK_Warning, 40| | DK_Note 41| | }; 42| | 43| | /// Clients that want to handle their own diagnostics in a custom way can 44| | /// register a function pointer+context as a diagnostic handler. 45| | /// It gets called each time PrintMessage is invoked. 46| | typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); 47| |private: 48| | struct SrcBuffer { 49| | /// The memory buffer for the file. 50| | std::unique_ptr Buffer; 51| | 52| | /// This is the location of the parent include, or null if at the top level. 53| | SMLoc IncludeLoc; 54| | 55| 0| SrcBuffer() {} 56| | 57| | SrcBuffer(SrcBuffer &&O) 58| 0| : Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {} 59| | }; 60| | 61| | /// This is all of the buffers that we are reading from. 62| | std::vector Buffers; 63| | 64| | // This is the list of directories we should search for include files in. 65| | std::vector IncludeDirectories; 66| | 67| | /// This is a cache for line number queries, its implementation is really 68| | /// private to SourceMgr.cpp. 69| | mutable void *LineNoCache; 70| | 71| | DiagHandlerTy DiagHandler; 72| | void *DiagContext; 73| | 74| | bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } 75| | 76| | SourceMgr(const SourceMgr&) = delete; 77| | void operator=(const SourceMgr&) = delete; 78| |public: 79| | SourceMgr() 80| 0| : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} 81| | ~SourceMgr(); 82| | 83| 0| void setIncludeDirs(const std::vector &Dirs) { 84| 0| IncludeDirectories = Dirs; 85| 0| } 86| | 87| | /// Specify a diagnostic handler to be invoked every time PrintMessage is 88| | /// called. \p Ctx is passed into the handler when it is invoked. 89| 0| void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { 90| 0| DiagHandler = DH; 91| 0| DiagContext = Ctx; 92| 0| } 93| | 94| 0| DiagHandlerTy getDiagHandler() const { return DiagHandler; } 95| 0| void *getDiagContext() const { return DiagContext; } 96| | 97| | const SrcBuffer &getBufferInfo(unsigned i) const { 98| | assert(isValidBufferID(i)); 99| | return Buffers[i - 1]; 100| | } 101| | 102| | const MemoryBuffer *getMemoryBuffer(unsigned i) const { 103| | assert(isValidBufferID(i)); 104| | return Buffers[i - 1].Buffer.get(); 105| | } 106| | 107| 0| unsigned getNumBuffers() const { 108| 0| return Buffers.size(); 109| 0| } 110| | 111| 0| unsigned getMainFileID() const { 112| 0| assert(getNumBuffers()); 113| 0| return 1; 114| 0| } 115| | 116| 0| SMLoc getParentIncludeLoc(unsigned i) const { 117| 0| assert(isValidBufferID(i)); 118| 0| return Buffers[i - 1].IncludeLoc; 119| 0| } 120| | 121| | /// Add a new source buffer to this source manager. This takes ownership of 122| | /// the memory buffer. 123| | unsigned AddNewSourceBuffer(std::unique_ptr F, 124| | SMLoc IncludeLoc) { 125| | SrcBuffer NB; 126| | NB.Buffer = std::move(F); 127| | NB.IncludeLoc = IncludeLoc; 128| | Buffers.push_back(std::move(NB)); 129| | return Buffers.size(); 130| | } 131| | 132| | /// Search for a file with the specified name in the current directory or in 133| | /// one of the IncludeDirs. 134| | /// 135| | /// If no file is found, this returns 0, otherwise it returns the buffer ID 136| | /// of the stacked file. The full path to the included file can be found in 137| | /// \p IncludedFile. 138| | unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, 139| | std::string &IncludedFile); 140| | 141| | /// Return the ID of the buffer containing the specified location. 142| | /// 143| | /// 0 is returned if the buffer is not found. 144| | unsigned FindBufferContainingLoc(SMLoc Loc) const; 145| | 146| | /// Find the line number for the specified location in the specified file. 147| | /// This is not a fast method. 148| | unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { 149| | return getLineAndColumn(Loc, BufferID).first; 150| | } 151| | 152| | /// Find the line and column number for the specified location in the 153| | /// specified file. This is not a fast method. 154| | std::pair getLineAndColumn(SMLoc Loc, 155| | unsigned BufferID = 0) const; 156| | 157| | /// Emit a message about the specified location with the specified string. 158| | /// 159| | /// \param ShowColors Display colored messages if output is a terminal and 160| | /// the default error handler is used. 161| | void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, 162| | const Twine &Msg, 163| | ArrayRef Ranges = None, 164| | ArrayRef FixIts = None, 165| | bool ShowColors = true) const; 166| | 167| | /// Emits a diagnostic to llvm::errs(). 168| | void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 169| | ArrayRef Ranges = None, 170| | ArrayRef FixIts = None, 171| | bool ShowColors = true) const; 172| | 173| | /// Emits a manually-constructed diagnostic to the given output stream. 174| | /// 175| | /// \param ShowColors Display colored messages if output is a terminal and 176| | /// the default error handler is used. 177| | void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, 178| | bool ShowColors = true) const; 179| | 180| | /// Return an SMDiagnostic at the specified location with the specified 181| | /// string. 182| | /// 183| | /// \param Msg If non-null, the kind of message (e.g., "error") which is 184| | /// prefixed to the message. 185| | SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 186| | ArrayRef Ranges = None, 187| | ArrayRef FixIts = None) const; 188| | 189| | /// Prints the names of included files and the line of the file they were 190| | /// included from. A diagnostic handler can use this before printing its 191| | /// custom formatted message. 192| | /// 193| | /// \param IncludeLoc The location of the include. 194| | /// \param OS the raw_ostream to print on. 195| | void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; 196| |}; 197| | 198| | 199| |/// Represents a single fixit, a replacement of one range of text with another. 200| |class SMFixIt { 201| | SMRange Range; 202| | 203| | std::string Text; 204| | 205| |public: 206| | // FIXME: Twine.str() is not very efficient. 207| | SMFixIt(SMLoc Loc, const Twine &Insertion) 208| 0| : Range(Loc, Loc), Text(Insertion.str()) { 209| 0| assert(Loc.isValid()); 210| 0| } 211| | 212| | // FIXME: Twine.str() is not very efficient. 213| | SMFixIt(SMRange R, const Twine &Replacement) 214| 0| : Range(R), Text(Replacement.str()) { 215| 0| assert(R.isValid()); 216| 0| } 217| | 218| | StringRef getText() const { return Text; } 219| | SMRange getRange() const { return Range; } 220| | 221| | bool operator<(const SMFixIt &Other) const { 222| | if (Range.Start.getPointer() != Other.Range.Start.getPointer()) 223| | return Range.Start.getPointer() < Other.Range.Start.getPointer(); 224| | if (Range.End.getPointer() != Other.Range.End.getPointer()) 225| | return Range.End.getPointer() < Other.Range.End.getPointer(); 226| | return Text < Other.Text; 227| | } 228| |}; 229| | 230| | 231| |/// Instances of this class encapsulate one diagnostic report, allowing 232| |/// printing to a raw_ostream as a caret diagnostic. 233| |class SMDiagnostic { 234| | const SourceMgr *SM; 235| | SMLoc Loc; 236| | std::string Filename; 237| | int LineNo, ColumnNo; 238| | SourceMgr::DiagKind Kind; 239| | std::string Message, LineContents; 240| | std::vector > Ranges; 241| | SmallVector FixIts; 242| | 243| |public: 244| | // Null diagnostic. 245| | SMDiagnostic() 246| 0| : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} 247| | // Diagnostic with no location (e.g. file not found, command line arg error). 248| | SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) 249| | : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), 250| 0| Message(Msg) {} 251| | 252| | // Diagnostic with a location. 253| | SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 254| | int Line, int Col, SourceMgr::DiagKind Kind, 255| | StringRef Msg, StringRef LineStr, 256| | ArrayRef > Ranges, 257| | ArrayRef FixIts = None); 258| | 259| 0| const SourceMgr *getSourceMgr() const { return SM; } 260| | SMLoc getLoc() const { return Loc; } 261| 0| StringRef getFilename() const { return Filename; } 262| 0| int getLineNo() const { return LineNo; } 263| 0| int getColumnNo() const { return ColumnNo; } 264| 0| SourceMgr::DiagKind getKind() const { return Kind; } 265| 0| StringRef getMessage() const { return Message; } 266| 0| StringRef getLineContents() const { return LineContents; } 267| 0| ArrayRef > getRanges() const { 268| 0| return Ranges; 269| 0| } 270| | 271| 0| void addFixIt(const SMFixIt &Hint) { 272| 0| FixIts.push_back(Hint); 273| 0| } 274| | 275| 0| ArrayRef getFixIts() const { 276| 0| return FixIts; 277| 0| } 278| | 279| | void print(const char *ProgName, raw_ostream &S, 280| | bool ShowColors = true) const; 281| |}; 282| | 283| |} // end llvm namespace 284| | 285| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SwapByteOrder.h: 1| |//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic and optimized functions to swap the byte order of 11| |// an integral type. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H 16| |#define LLVM_SUPPORT_SWAPBYTEORDER_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| |namespace sys { 25| | 26| |/// SwapByteOrder_16 - This function returns a byte-swapped representation of 27| |/// the 16-bit argument. 28| |inline uint16_t SwapByteOrder_16(uint16_t value) { 29| |#if defined(_MSC_VER) && !defined(_DEBUG) 30| | // The DLL version of the runtime lacks these functions (bug!?), but in a 31| | // release build they're replaced with BSWAP instructions anyway. 32| | return _byteswap_ushort(value); 33| |#else 34| | uint16_t Hi = value << 8; 35| | uint16_t Lo = value >> 8; 36| | return Hi | Lo; 37| |#endif 38| |} 39| | 40| |/// SwapByteOrder_32 - This function returns a byte-swapped representation of 41| |/// the 32-bit argument. 42| 0|inline uint32_t SwapByteOrder_32(uint32_t value) { 43| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 44| 0| return __builtin_bswap32(value); 45| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 46| 0| return _byteswap_ulong(value); 47| 0|#else 48| 0| uint32_t Byte0 = value & 0x000000FF; 49| 0| uint32_t Byte1 = value & 0x0000FF00; 50| 0| uint32_t Byte2 = value & 0x00FF0000; 51| 0| uint32_t Byte3 = value & 0xFF000000; 52| 0| return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 53| 0|#endif 54| 0|} 55| | 56| |/// SwapByteOrder_64 - This function returns a byte-swapped representation of 57| |/// the 64-bit argument. 58| 0|inline uint64_t SwapByteOrder_64(uint64_t value) { 59| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 60| 0| return __builtin_bswap64(value); 61| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 62| 0| return _byteswap_uint64(value); 63| 0|#else 64| 0| uint64_t Hi = SwapByteOrder_32(uint32_t(value)); 65| 0| uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); 66| 0| return (Hi << 32) | Lo; 67| 0|#endif 68| 0|} 69| | 70| 0|inline unsigned char getSwappedBytes(unsigned char C) { return C; } 71| 0|inline signed char getSwappedBytes(signed char C) { return C; } 72| 0|inline char getSwappedBytes(char C) { return C; } 73| | 74| 0|inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } 75| 0|inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } 76| | 77| 0|inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } 78| 0|inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } 79| | 80| |#if __LONG_MAX__ == __INT_MAX__ 81| |inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } 82| |inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } 83| |#elif __LONG_MAX__ == __LONG_LONG_MAX__ 84| 0|inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } 85| 0|inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } 86| |#else 87| |#error "Unknown long size!" 88| |#endif 89| | 90| 0|inline unsigned long long getSwappedBytes(unsigned long long C) { 91| 0| return SwapByteOrder_64(C); 92| 0|} 93| 0|inline signed long long getSwappedBytes(signed long long C) { 94| 0| return SwapByteOrder_64(C); 95| 0|} 96| | 97| 0|inline float getSwappedBytes(float C) { 98| 0| union { 99| 0| uint32_t i; 100| 0| float f; 101| 0| } in, out; 102| 0| in.f = C; 103| 0| out.i = SwapByteOrder_32(in.i); 104| 0| return out.f; 105| 0|} 106| | 107| 0|inline float getSwappedBytes(double C) { 108| 0| union { 109| 0| uint64_t i; 110| 0| double d; 111| 0| } in, out; 112| 0| in.d = C; 113| 0| out.i = SwapByteOrder_64(in.i); 114| 0| return out.d; 115| 0|} 116| | 117| |template 118| 0|inline void swapByteOrder(T &Value) { 119| 0| Value = getSwappedBytes(Value); 120| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIyEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIjEEvRT_ ------------------ 121| | 122| |} // end namespace sys 123| |} // end namespace llvm 124| | 125| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/raw_ostream.h: 1| |//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the raw_ostream class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_RAW_OSTREAM_H 15| |#define LLVM_SUPPORT_RAW_OSTREAM_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include 22| | 23| |namespace llvm { 24| | class format_object_base; 25| | class FormattedString; 26| | class FormattedNumber; 27| | template 28| | class SmallVectorImpl; 29| | 30| | namespace sys { 31| | namespace fs { 32| | enum OpenFlags : unsigned; 33| | } 34| | } 35| | 36| |/// raw_ostream - This class implements an extremely fast bulk output stream 37| |/// that can *only* output to a stream. It does not support seeking, reopening, 38| |/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs 39| |/// a chunk at a time. 40| |class raw_ostream { 41| |private: 42| | void operator=(const raw_ostream &) = delete; 43| | raw_ostream(const raw_ostream &) = delete; 44| | 45| | /// The buffer is handled in such a way that the buffer is 46| | /// uninitialized, unbuffered, or out of space when OutBufCur >= 47| | /// OutBufEnd. Thus a single comparison suffices to determine if we 48| | /// need to take the slow path to write a single character. 49| | /// 50| | /// The buffer is in one of three states: 51| | /// 1. Unbuffered (BufferMode == Unbuffered) 52| | /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). 53| | /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && 54| | /// OutBufEnd - OutBufStart >= 1). 55| | /// 56| | /// If buffered, then the raw_ostream owns the buffer if (BufferMode == 57| | /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is 58| | /// managed by the subclass. 59| | /// 60| | /// If a subclass installs an external buffer using SetBuffer then it can wait 61| | /// for a \see write_impl() call to handle the data which has been put into 62| | /// this buffer. 63| | char *OutBufStart, *OutBufEnd, *OutBufCur; 64| | 65| | enum BufferKind { 66| | Unbuffered = 0, 67| | InternalBuffer, 68| | ExternalBuffer 69| | } BufferMode; 70| | 71| |public: 72| | // color order matches ANSI escape sequence, don't change 73| | enum Colors { 74| | BLACK=0, 75| | RED, 76| | GREEN, 77| | YELLOW, 78| | BLUE, 79| | MAGENTA, 80| | CYAN, 81| | WHITE, 82| | SAVEDCOLOR 83| | }; 84| | 85| | explicit raw_ostream(bool unbuffered=false) 86| | : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { 87| | // Start out ready to flush. 88| | OutBufStart = OutBufEnd = OutBufCur = nullptr; 89| | } 90| | 91| | virtual ~raw_ostream(); 92| | 93| | /// tell - Return the current offset with the file. 94| | uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } 95| | 96| | //===--------------------------------------------------------------------===// 97| | // Configuration Interface 98| | //===--------------------------------------------------------------------===// 99| | 100| | /// SetBuffered - Set the stream to be buffered, with an automatically 101| | /// determined buffer size. 102| | void SetBuffered(); 103| | 104| | /// SetBufferSize - Set the stream to be buffered, using the 105| | /// specified buffer size. 106| 0| void SetBufferSize(size_t Size) { 107| 0| flush(); 108| 0| SetBufferAndMode(new char[Size], Size, InternalBuffer); 109| 0| } 110| | 111| 0| size_t GetBufferSize() const { 112| 0| // If we're supposed to be buffered but haven't actually gotten around 113| 0| // to allocating the buffer yet, return the value that would be used. 114| 0| if (BufferMode != Unbuffered && OutBufStart == nullptr) 115| 0| return preferred_buffer_size(); 116| 0| 117| 0| // Otherwise just return the size of the allocated buffer. 118| 0| return OutBufEnd - OutBufStart; 119| 0| } 120| | 121| | /// SetUnbuffered - Set the stream to be unbuffered. When 122| | /// unbuffered, the stream will flush after every write. This routine 123| | /// will also flush the buffer immediately when the stream is being 124| | /// set to unbuffered. 125| 0| void SetUnbuffered() { 126| 0| flush(); 127| 0| SetBufferAndMode(nullptr, 0, Unbuffered); 128| 0| } 129| | 130| | size_t GetNumBytesInBuffer() const { 131| | return OutBufCur - OutBufStart; 132| | } 133| | 134| | //===--------------------------------------------------------------------===// 135| | // Data Output Interface 136| | //===--------------------------------------------------------------------===// 137| | 138| | void flush() { 139| | if (OutBufCur != OutBufStart) 140| | flush_nonempty(); 141| | } 142| | 143| | raw_ostream &operator<<(char C) { 144| | if (OutBufCur >= OutBufEnd) 145| | return write(C); 146| | *OutBufCur++ = C; 147| | return *this; 148| | } 149| | 150| | raw_ostream &operator<<(unsigned char C) { 151| | if (OutBufCur >= OutBufEnd) 152| | return write(C); 153| | *OutBufCur++ = C; 154| | return *this; 155| | } 156| | 157| 0| raw_ostream &operator<<(signed char C) { 158| 0| if (OutBufCur >= OutBufEnd) 159| 0| return write(C); 160| 0| *OutBufCur++ = C; 161| 0| return *this; 162| 0| } 163| | 164| 0| raw_ostream &operator<<(StringRef Str) { 165| 0| // Inline fast path, particularly for strings with a known length. 166| 0| size_t Size = Str.size(); 167| 0| 168| 0| // Make sure we can use the fast path. 169| 0| if (Size > (size_t)(OutBufEnd - OutBufCur)) 170| 0| return write(Str.data(), Size); 171| 0| 172| 0| memcpy(OutBufCur, Str.data(), Size); 173| 0| OutBufCur += Size; 174| 0| return *this; 175| 0| } 176| | 177| | raw_ostream &operator<<(const char *Str) { 178| | // Inline fast path, particularly for constant strings where a sufficiently 179| | // smart compiler will simplify strlen. 180| | 181| | return this->operator<<(StringRef(Str)); 182| | } 183| | 184| | raw_ostream &operator<<(const std::string &Str) { 185| | // Avoid the fast path, it would only increase code size for a marginal win. 186| | return write(Str.data(), Str.length()); 187| | } 188| | 189| | raw_ostream &operator<<(const llvm::SmallVectorImpl &Str) { 190| | return write(Str.data(), Str.size()); 191| | } 192| | 193| | raw_ostream &operator<<(unsigned long N); 194| | raw_ostream &operator<<(long N); 195| | raw_ostream &operator<<(unsigned long long N); 196| | raw_ostream &operator<<(long long N); 197| | raw_ostream &operator<<(const void *P); 198| | raw_ostream &operator<<(unsigned int N) { 199| | return this->operator<<(static_cast(N)); 200| | } 201| | 202| | raw_ostream &operator<<(int N) { 203| | return this->operator<<(static_cast(N)); 204| | } 205| | 206| | raw_ostream &operator<<(double N); 207| | 208| | /// write_hex - Output \p N in hexadecimal, without any prefix or padding. 209| | raw_ostream &write_hex(unsigned long long N); 210| | 211| | /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and 212| | /// anything that doesn't satisfy std::isprint into an escape sequence. 213| | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); 214| | 215| | raw_ostream &write(unsigned char C); 216| | raw_ostream &write(const char *Ptr, size_t Size); 217| | 218| | // Formatted output, see the format() function in Support/Format.h. 219| | raw_ostream &operator<<(const format_object_base &Fmt); 220| | 221| | // Formatted output, see the leftJustify() function in Support/Format.h. 222| | raw_ostream &operator<<(const FormattedString &); 223| | 224| | // Formatted output, see the formatHex() function in Support/Format.h. 225| | raw_ostream &operator<<(const FormattedNumber &); 226| | 227| | /// indent - Insert 'NumSpaces' spaces. 228| | raw_ostream &indent(unsigned NumSpaces); 229| | 230| | 231| | /// Changes the foreground color of text that will be output from this point 232| | /// forward. 233| | /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to 234| | /// change only the bold attribute, and keep colors untouched 235| | /// @param Bold bold/brighter text, default false 236| | /// @param BG if true change the background, default: change foreground 237| | /// @returns itself so it can be used within << invocations 238| | virtual raw_ostream &changeColor(enum Colors Color, 239| | bool Bold = false, 240| | bool BG = false) { 241| | (void)Color; 242| | (void)Bold; 243| | (void)BG; 244| | return *this; 245| | } 246| | 247| | /// Resets the colors to terminal defaults. Call this when you are done 248| | /// outputting colored text, or before program exit. 249| | virtual raw_ostream &resetColor() { return *this; } 250| | 251| | /// Reverses the forground and background colors. 252| | virtual raw_ostream &reverseColor() { return *this; } 253| | 254| | /// This function determines if this stream is connected to a "tty" or 255| | /// "console" window. That is, the output would be displayed to the user 256| | /// rather than being put on a pipe or stored in a file. 257| | virtual bool is_displayed() const { return false; } 258| | 259| | /// This function determines if this stream is displayed and supports colors. 260| | virtual bool has_colors() const { return is_displayed(); } 261| | 262| | //===--------------------------------------------------------------------===// 263| | // Subclass Interface 264| | //===--------------------------------------------------------------------===// 265| | 266| |private: 267| | /// write_impl - The is the piece of the class that is implemented 268| | /// by subclasses. This writes the \p Size bytes starting at 269| | /// \p Ptr to the underlying stream. 270| | /// 271| | /// This function is guaranteed to only be called at a point at which it is 272| | /// safe for the subclass to install a new buffer via SetBuffer. 273| | /// 274| | /// \param Ptr The start of the data to be written. For buffered streams this 275| | /// is guaranteed to be the start of the buffer. 276| | /// 277| | /// \param Size The number of bytes to be written. 278| | /// 279| | /// \invariant { Size > 0 } 280| | virtual void write_impl(const char *Ptr, size_t Size) = 0; 281| | 282| | // An out of line virtual method to provide a home for the class vtable. 283| | virtual void handle(); 284| | 285| | /// current_pos - Return the current position within the stream, not 286| | /// counting the bytes currently in the buffer. 287| | virtual uint64_t current_pos() const = 0; 288| | 289| |protected: 290| | /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is 291| | /// intended for use only by subclasses which can arrange for the output to go 292| | /// directly into the desired output buffer, instead of being copied on each 293| | /// flush. 294| 0| void SetBuffer(char *BufferStart, size_t Size) { 295| 0| SetBufferAndMode(BufferStart, Size, ExternalBuffer); 296| 0| } 297| | 298| | /// preferred_buffer_size - Return an efficient buffer size for the 299| | /// underlying output mechanism. 300| | virtual size_t preferred_buffer_size() const; 301| | 302| | /// getBufferStart - Return the beginning of the current stream buffer, or 0 303| | /// if the stream is unbuffered. 304| 0| const char *getBufferStart() const { return OutBufStart; } 305| | 306| | //===--------------------------------------------------------------------===// 307| | // Private Interface 308| | //===--------------------------------------------------------------------===// 309| |private: 310| | /// SetBufferAndMode - Install the given buffer and mode. 311| | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); 312| | 313| | /// flush_nonempty - Flush the current buffer, which is known to be 314| | /// non-empty. This outputs the currently buffered data and resets 315| | /// the buffer to empty. 316| | void flush_nonempty(); 317| | 318| | /// copy_to_buffer - Copy data into the buffer. Size must not be 319| | /// greater than the number of unused bytes in the buffer. 320| | void copy_to_buffer(const char *Ptr, size_t Size); 321| |}; 322| | 323| |//===----------------------------------------------------------------------===// 324| |// File Output Streams 325| |//===----------------------------------------------------------------------===// 326| | 327| |/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. 328| |/// 329| |class raw_fd_ostream : public raw_ostream { 330| | int FD; 331| | bool ShouldClose; 332| | 333| | /// Error This flag is true if an error of any kind has been detected. 334| | /// 335| | bool Error; 336| | 337| | /// Controls whether the stream should attempt to use atomic writes, when 338| | /// possible. 339| | bool UseAtomicWrites; 340| | 341| | uint64_t pos; 342| | 343| | /// write_impl - See raw_ostream::write_impl. 344| | void write_impl(const char *Ptr, size_t Size) override; 345| | 346| | /// current_pos - Return the current position within the stream, not 347| | /// counting the bytes currently in the buffer. 348| | uint64_t current_pos() const override { return pos; } 349| | 350| | /// preferred_buffer_size - Determine an efficient buffer size. 351| | size_t preferred_buffer_size() const override; 352| | 353| | /// error_detected - Set the flag indicating that an output error has 354| | /// been encountered. 355| 0| void error_detected() { Error = true; } 356| | 357| |public: 358| | /// Open the specified file for writing. If an error occurs, information 359| | /// about the error is put into EC, and the stream should be immediately 360| | /// destroyed; 361| | /// \p Flags allows optional flags to control how the file will be opened. 362| | /// 363| | /// As a special case, if Filename is "-", then the stream will use 364| | /// STDOUT_FILENO instead of opening a file. Note that it will still consider 365| | /// itself to own the file descriptor. In particular, it will close the 366| | /// file descriptor when it is done (this is necessary to detect 367| | /// output errors). 368| | raw_fd_ostream(StringRef Filename, std::error_code &EC, 369| | sys::fs::OpenFlags Flags); 370| | 371| | /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 372| | /// ShouldClose is true, this closes the file when the stream is destroyed. 373| | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); 374| | 375| | ~raw_fd_ostream(); 376| | 377| | /// close - Manually flush the stream and close the file. 378| | /// Note that this does not call fsync. 379| | void close(); 380| | 381| | /// seek - Flushes the stream and repositions the underlying file descriptor 382| | /// position to the offset specified from the beginning of the file. 383| | uint64_t seek(uint64_t off); 384| | 385| | /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for 386| | /// individual output routines where possible. 387| | /// 388| | /// Note that because raw_ostream's are typically buffered, this flag is only 389| | /// sensible when used on unbuffered streams which will flush their output 390| | /// immediately. 391| 0| void SetUseAtomicWrites(bool Value) { 392| 0| UseAtomicWrites = Value; 393| 0| } 394| | 395| | raw_ostream &changeColor(enum Colors colors, bool bold=false, 396| | bool bg=false) override; 397| | raw_ostream &resetColor() override; 398| | 399| | raw_ostream &reverseColor() override; 400| | 401| | bool is_displayed() const override; 402| | 403| | bool has_colors() const override; 404| | 405| | /// has_error - Return the value of the flag in this raw_fd_ostream indicating 406| | /// whether an output error has been encountered. 407| | /// This doesn't implicitly flush any pending output. Also, it doesn't 408| | /// guarantee to detect all errors unless the stream has been closed. 409| | bool has_error() const { 410| | return Error; 411| | } 412| | 413| | /// clear_error - Set the flag read by has_error() to false. If the error 414| | /// flag is set at the time when this raw_ostream's destructor is called, 415| | /// report_fatal_error is called to report the error. Use clear_error() 416| | /// after handling the error to avoid this behavior. 417| | /// 418| | /// "Errors should never pass silently. 419| | /// Unless explicitly silenced." 420| | /// - from The Zen of Python, by Tim Peters 421| | /// 422| 0| void clear_error() { 423| 0| Error = false; 424| 0| } 425| |}; 426| | 427| |/// outs() - This returns a reference to a raw_ostream for standard output. 428| |/// Use it like: outs() << "foo" << "bar"; 429| |raw_ostream &outs(); 430| | 431| |/// errs() - This returns a reference to a raw_ostream for standard error. 432| |/// Use it like: errs() << "foo" << "bar"; 433| |raw_ostream &errs(); 434| | 435| |/// nulls() - This returns a reference to a raw_ostream which simply discards 436| |/// output. 437| |raw_ostream &nulls(); 438| | 439| |//===----------------------------------------------------------------------===// 440| |// Output Stream Adaptors 441| |//===----------------------------------------------------------------------===// 442| | 443| |/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a 444| |/// simple adaptor class. This class does not encounter output errors. 445| |class raw_string_ostream : public raw_ostream { 446| | std::string &OS; 447| | 448| | /// write_impl - See raw_ostream::write_impl. 449| | void write_impl(const char *Ptr, size_t Size) override; 450| | 451| | /// current_pos - Return the current position within the stream, not 452| | /// counting the bytes currently in the buffer. 453| | uint64_t current_pos() const override { return OS.size(); } 454| |public: 455| 0| explicit raw_string_ostream(std::string &O) : OS(O) {} 456| | ~raw_string_ostream(); 457| | 458| | /// str - Flushes the stream contents to the target string and returns 459| | /// the string's reference. 460| 0| std::string& str() { 461| 0| flush(); 462| 0| return OS; 463| 0| } 464| |}; 465| | 466| |/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or 467| |/// SmallString. This is a simple adaptor class. This class does not 468| |/// encounter output errors. 469| |class raw_svector_ostream : public raw_ostream { 470| | SmallVectorImpl &OS; 471| | 472| | /// write_impl - See raw_ostream::write_impl. 473| | void write_impl(const char *Ptr, size_t Size) override; 474| | 475| | /// current_pos - Return the current position within the stream, not 476| | /// counting the bytes currently in the buffer. 477| | uint64_t current_pos() const override; 478| |public: 479| | /// Construct a new raw_svector_ostream. 480| | /// 481| | /// \param O The vector to write to; this should generally have at least 128 482| | /// bytes free to avoid any extraneous memory overhead. 483| | explicit raw_svector_ostream(SmallVectorImpl &O); 484| | ~raw_svector_ostream(); 485| | 486| | /// resync - This is called when the SmallVector we're appending to is changed 487| | /// outside of the raw_svector_ostream's control. It is only safe to do this 488| | /// if the raw_svector_ostream has previously been flushed. 489| | void resync(); 490| | 491| | /// str - Flushes the stream contents to the target vector and return a 492| | /// StringRef for the vector contents. 493| | StringRef str(); 494| |}; 495| | 496| |/// raw_null_ostream - A raw_ostream that discards all output. 497| |class raw_null_ostream : public raw_ostream { 498| | /// write_impl - See raw_ostream::write_impl. 499| | void write_impl(const char *Ptr, size_t size) override; 500| | 501| | /// current_pos - Return the current position within the stream, not 502| | /// counting the bytes currently in the buffer. 503| | uint64_t current_pos() const override; 504| | 505| |public: 506| 0| explicit raw_null_ostream() {} 507| | ~raw_null_ostream(); 508| |}; 509| | 510| |} // end llvm namespace 511| | 512| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/libllbuild/BuildSystem-C-API.cpp: 1| |//===-- BuildSystem-C-API.cpp ---------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2015 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |// Include the public API. 14| |#include 15| | 16| |#include "llbuild/Basic/FileSystem.h" 17| |#include "llbuild/BuildSystem/BuildFile.h" 18| |#include "llbuild/BuildSystem/BuildKey.h" 19| |#include "llbuild/BuildSystem/BuildSystemCommandInterface.h" 20| |#include "llbuild/BuildSystem/BuildSystemFrontend.h" 21| |#include "llbuild/BuildSystem/ExternalCommand.h" 22| |#include "llbuild/Core/BuildEngine.h" 23| |#include "llbuild/Core/DependencyInfoParser.h" 24| | 25| |#include "llvm/ADT/Hashing.h" 26| |#include "llvm/ADT/SmallString.h" 27| |#include "llvm/Support/SourceMgr.h" 28| |#include "llvm/Support/raw_ostream.h" 29| | 30| |#include 31| |#include 32| |#include 33| | 34| |using namespace llbuild; 35| |using namespace llbuild::basic; 36| |using namespace llbuild::buildsystem; 37| | 38| |/* Build Engine API */ 39| | 40| |namespace { 41| | 42| |class CAPIFileSystem : public basic::FileSystem { 43| | llb_buildsystem_delegate_t cAPIDelegate; 44| | std::unique_ptr localFileSystem; 45| | 46| |public: 47| | CAPIFileSystem(llb_buildsystem_delegate_t delegate) 48| | : cAPIDelegate(delegate), 49| 0| localFileSystem(basic::createLocalFileSystem()) { } 50| | 51| | virtual bool 52| 0| createDirectory(const std::string& path) override { 53| 0| if (!cAPIDelegate.fs_create_directory) { 54| 0| return localFileSystem->createDirectory(path); 55| 0| } 56| 0| 57| 0| return cAPIDelegate.fs_create_directory(cAPIDelegate.context, path.c_str()); 58| 0| } 59| | 60| | virtual std::unique_ptr 61| 0| getFileContents(const std::string& path) override { 62| 0| if (!cAPIDelegate.fs_get_file_contents) { 63| 0| return localFileSystem->getFileContents(path); 64| 0| } 65| 0| 66| 0| llb_data_t data; 67| 0| if (!cAPIDelegate.fs_get_file_contents(cAPIDelegate.context, path.c_str(), 68| 0| &data)) { 69| 0| return nullptr; 70| 0| } 71| 0| 72| 0| // Create a new memory buffer to copy the data to. 73| 0| // 74| 0| // FIXME: This is an unfortunate amount of copying. 75| 0| auto result = llvm::MemoryBuffer::getNewUninitMemBuffer(data.length, path); 76| 0| memcpy((char*)result->getBufferStart(), data.data, data.length); 77| 0| 78| 0| // Release the client memory. 79| 0| // 80| 0| // FIXME: This is gross, come up with a general purpose solution. 81| 0| free((char*)data.data); 82| 0| 83| 0| return result; 84| 0| } 85| | 86| 0| virtual bool remove(const std::string& path) override { 87| 0| if (!cAPIDelegate.fs_remove) { 88| 0| return localFileSystem->remove(path); 89| 0| } 90| 0| 91| 0| return cAPIDelegate.fs_remove(cAPIDelegate.context, path.c_str()); 92| 0| } 93| | 94| 0| virtual basic::FileInfo getFileInfo(const std::string& path) override { 95| 0| if (!cAPIDelegate.fs_get_file_info) { 96| 0| return localFileSystem->getFileInfo(path); 97| 0| } 98| 0| 99| 0| llb_fs_file_info_t file_info; 100| 0| cAPIDelegate.fs_get_file_info(cAPIDelegate.context, path.c_str(), 101| 0| &file_info); 102| 0| 103| 0| basic::FileInfo result{}; 104| 0| result.device = file_info.device; 105| 0| result.inode = file_info.inode; 106| 0| result.mode = file_info.mode; 107| 0| result.size = file_info.size; 108| 0| result.modTime.seconds = file_info.mod_time.seconds;; 109| 0| result.modTime.nanoseconds = file_info.mod_time.nanoseconds; 110| 0| return result; 111| 0| } 112| | 113| 0| virtual basic::FileInfo getLinkInfo(const std::string& path) override { 114| 0| if (!cAPIDelegate.fs_get_link_info && !cAPIDelegate.fs_get_file_info) { 115| 0| return localFileSystem->getLinkInfo(path); 116| 0| } 117| 0| 118| 0| llb_fs_file_info_t file_info; 119| 0| if (cAPIDelegate.fs_get_link_info) { 120| 0| cAPIDelegate.fs_get_link_info(cAPIDelegate.context, path.c_str(), 121| 0| &file_info); 122| 0| } else { 123| 0| cAPIDelegate.fs_get_file_info(cAPIDelegate.context, path.c_str(), 124| 0| &file_info); 125| 0| } 126| 0| 127| 0| basic::FileInfo result{}; 128| 0| result.device = file_info.device; 129| 0| result.inode = file_info.inode; 130| 0| result.mode = file_info.mode; 131| 0| result.size = file_info.size; 132| 0| result.modTime.seconds = file_info.mod_time.seconds;; 133| 0| result.modTime.nanoseconds = file_info.mod_time.nanoseconds; 134| 0| return result; 135| 0| } 136| |}; 137| | 138| |class CAPIBuildSystemFrontendDelegate : public BuildSystemFrontendDelegate { 139| | llb_buildsystem_delegate_t cAPIDelegate; 140| | 141| 0| llb_buildsystem_command_result_t get_command_result(ProcessStatus commandResult) { 142| 0| switch (commandResult) { 143| 0| case ProcessStatus::Succeeded: 144| 0| return llb_buildsystem_command_result_succeeded; 145| 0| case ProcessStatus::Cancelled: 146| 0| return llb_buildsystem_command_result_cancelled; 147| 0| case ProcessStatus::Failed: 148| 0| return llb_buildsystem_command_result_failed; 149| 0| case ProcessStatus::Skipped: 150| 0| return llb_buildsystem_command_result_skipped; 151| 0| default: 152| 0| assert(0 && "unknown command result"); 153| 0| break; 154| 0| } 155| 0| return llb_buildsystem_command_result_failed; 156| 0| } 157| | 158| |public: 159| | CAPIBuildSystemFrontendDelegate(llvm::SourceMgr& sourceMgr, 160| | BuildSystemInvocation& invocation, 161| | llb_buildsystem_delegate_t delegate) 162| | : BuildSystemFrontendDelegate(sourceMgr, invocation, "basic", 0), 163| 0| cAPIDelegate(delegate) { } 164| | 165| 0| virtual std::unique_ptr lookupTool(StringRef name) override { 166| 0| if (!cAPIDelegate.lookup_tool) { 167| 0| return nullptr; 168| 0| } 169| 0| 170| 0| llb_data_t cName{ name.size(), (const uint8_t*) name.data() }; 171| 0| auto tool = cAPIDelegate.lookup_tool(cAPIDelegate.context, &cName); 172| 0| if (!tool) { 173| 0| return nullptr; 174| 0| } 175| 0| 176| 0| return std::unique_ptr((Tool*)tool); 177| 0| } 178| | 179| 0| virtual void hadCommandFailure() override { 180| 0| // Call the base implementation. 181| 0| BuildSystemFrontendDelegate::hadCommandFailure(); 182| 0| 183| 0| // Report the command failure, if the client provided an appropriate 184| 0| // callback. 185| 0| if (cAPIDelegate.had_command_failure) { 186| 0| cAPIDelegate.had_command_failure(cAPIDelegate.context); 187| 0| } else { 188| 0| // Otherwise, the default behavior is to immediately cancel. 189| 0| cancel(); 190| 0| } 191| 0| } 192| | 193| | static llb_buildsystem_command_status_kind_t 194| 0| convertStatusKind(BuildSystemDelegate::CommandStatusKind kind) { 195| 0| switch (kind) { 196| 0| case BuildSystemDelegate::CommandStatusKind::IsScanning: 197| 0| return llb_buildsystem_command_status_kind_is_scanning; 198| 0| case BuildSystemDelegate::CommandStatusKind::IsUpToDate: 199| 0| return llb_buildsystem_command_status_kind_is_up_to_date; 200| 0| case BuildSystemDelegate::CommandStatusKind::IsComplete: 201| 0| return llb_buildsystem_command_status_kind_is_complete; 202| 0| } 203| 0| assert(0 && "unknown status kind"); 204| 0| return llb_buildsystem_command_status_kind_is_scanning; 205| 0| } 206| | 207| | virtual void 208| | commandStatusChanged(Command* command, 209| 0| BuildSystemDelegate::CommandStatusKind kind) override { 210| 0| if (cAPIDelegate.command_status_changed) { 211| 0| cAPIDelegate.command_status_changed( 212| 0| cAPIDelegate.context, (llb_buildsystem_command_t*) command, 213| 0| convertStatusKind(kind)); 214| 0| } 215| 0| } 216| | 217| 0| virtual void commandPreparing(Command* command) override { 218| 0| if (cAPIDelegate.command_preparing) { 219| 0| cAPIDelegate.command_preparing( 220| 0| cAPIDelegate.context, 221| 0| (llb_buildsystem_command_t*) command); 222| 0| } 223| 0| } 224| | 225| 0| virtual bool shouldCommandStart(Command * command) override { 226| 0| if (cAPIDelegate.should_command_start) { 227| 0| return cAPIDelegate.should_command_start( 228| 0| cAPIDelegate.context, (llb_buildsystem_command_t*) command); 229| 0| } else { 230| 0| return true; 231| 0| } 232| 0| } 233| | 234| 0| virtual void commandStarted(Command* command) override { 235| 0| if (cAPIDelegate.command_started) { 236| 0| cAPIDelegate.command_started( 237| 0| cAPIDelegate.context, 238| 0| (llb_buildsystem_command_t*) command); 239| 0| } 240| 0| } 241| | 242| 0| virtual void commandFinished(Command* command, ProcessStatus commandResult) override { 243| 0| if (cAPIDelegate.command_finished) { 244| 0| cAPIDelegate.command_finished( 245| 0| cAPIDelegate.context, 246| 0| (llb_buildsystem_command_t*) command, 247| 0| get_command_result(commandResult)); 248| 0| } 249| 0| } 250| | 251| 0| virtual void commandHadError(Command* command, StringRef message) override { 252| 0| if (cAPIDelegate.command_had_error) { 253| 0| llb_data_t cMessage { message.size(), (const uint8_t*) message.data() }; 254| 0| cAPIDelegate.command_had_error( 255| 0| cAPIDelegate.context, 256| 0| (llb_buildsystem_command_t*) command, 257| 0| &cMessage); 258| 0| } 259| 0| } 260| | 261| 0| virtual void commandHadNote(Command* command, StringRef message) override { 262| 0| if (cAPIDelegate.command_had_note) { 263| 0| llb_data_t cMessage { message.size(), (const uint8_t*) message.data() }; 264| 0| cAPIDelegate.command_had_note( 265| 0| cAPIDelegate.context, 266| 0| (llb_buildsystem_command_t*) command, 267| 0| &cMessage); 268| 0| } 269| 0| } 270| | 271| 0| virtual void commandHadWarning(Command* command, StringRef message) override { 272| 0| if (cAPIDelegate.command_had_warning) { 273| 0| llb_data_t cMessage { message.size(), (const uint8_t*) message.data() }; 274| 0| cAPIDelegate.command_had_warning( 275| 0| cAPIDelegate.context, 276| 0| (llb_buildsystem_command_t*) command, 277| 0| &cMessage); 278| 0| } 279| 0| } 280| | 281| | virtual void commandCannotBuildOutputDueToMissingInputs(Command* command, 282| 0| Node* outputNode, SmallPtrSet inputNodes) override { 283| 0| if (cAPIDelegate.command_cannot_build_output_due_to_missing_inputs) { 284| 0| llb_build_key_t output = { llb_build_key_kind_node, 285| 0| strdup(outputNode->getName().str().c_str()) }; 286| 0| 287| 0| CAPINodesVector inputs(inputNodes); 288| 0| 289| 0| cAPIDelegate.command_cannot_build_output_due_to_missing_inputs( 290| 0| cAPIDelegate.context, 291| 0| (llb_buildsystem_command_t*) command, 292| 0| &output, 293| 0| inputs.data(), 294| 0| inputs.count() 295| 0| ); 296| 0| 297| 0| free((char *)output.key); 298| 0| } 299| 0| } 300| | 301| | class CAPINodesVector { 302| | private: 303| | std::vector keys; 304| | 305| | public: 306| 0| CAPINodesVector(const SmallPtrSet inputNodes) : keys(inputNodes.size()) { 307| 0| int idx = 0; 308| 0| for (auto inputNode : inputNodes) { 309| 0| auto& buildKey = keys[idx++]; 310| 0| buildKey.kind = llb_build_key_kind_node; 311| 0| buildKey.key = strdup(inputNode->getName().str().c_str()); 312| 0| } 313| 0| } 314| | 315| 0| ~CAPINodesVector() { 316| 0| for (auto& key : keys) { 317| 0| free((char *)key.key); 318| 0| } 319| 0| } 320| | 321| 0| llb_build_key_t* data() { return &keys[0]; } 322| 0| uint64_t count() { return keys.size(); } 323| | }; 324| | 325| | virtual void cannotBuildNodeDueToMultipleProducers(Node* outputNode, 326| 0| std::vector commands) override { 327| 0| if (cAPIDelegate.cannot_build_node_due_to_multiple_producers) { 328| 0| llb_build_key_t output = { llb_build_key_kind_node, 329| 0| strdup(outputNode->getName().str().c_str()) }; 330| 0| 331| 0| cAPIDelegate.cannot_build_node_due_to_multiple_producers( 332| 0| cAPIDelegate.context, 333| 0| &output, 334| 0| (llb_buildsystem_command_t**)commands.data(), 335| 0| commands.size() 336| 0| ); 337| 0| } 338| 0| } 339| | 340| | virtual void commandProcessStarted(Command* command, 341| 0| ProcessHandle handle) override { 342| 0| if (cAPIDelegate.command_process_started) { 343| 0| cAPIDelegate.command_process_started( 344| 0| cAPIDelegate.context, 345| 0| (llb_buildsystem_command_t*) command, 346| 0| (llb_buildsystem_process_t*) handle.id); 347| 0| } 348| 0| } 349| | 350| | virtual void commandProcessHadError(Command* command, ProcessHandle handle, 351| 0| const Twine& message) override { 352| 0| if (cAPIDelegate.command_process_had_error) { 353| 0| SmallString<256> data; 354| 0| message.toVector(data); 355| 0| llb_data_t cData{ data.size(), (const uint8_t*) data.data() }; 356| 0| cAPIDelegate.command_process_had_error( 357| 0| cAPIDelegate.context, 358| 0| (llb_buildsystem_command_t*) command, 359| 0| (llb_buildsystem_process_t*) handle.id, 360| 0| &cData); 361| 0| } 362| 0| } 363| | 364| | virtual void commandProcessHadOutput(Command* command, ProcessHandle handle, 365| 0| StringRef data) override { 366| 0| if (cAPIDelegate.command_process_had_output) { 367| 0| llb_data_t cData{ data.size(), (const uint8_t*) data.data() }; 368| 0| cAPIDelegate.command_process_had_output( 369| 0| cAPIDelegate.context, 370| 0| (llb_buildsystem_command_t*) command, 371| 0| (llb_buildsystem_process_t*) handle.id, 372| 0| &cData); 373| 0| } 374| 0| } 375| | 376| | virtual void commandProcessFinished(Command* command, ProcessHandle handle, 377| 0| const ProcessResult& commandResult) override { 378| 0| if (cAPIDelegate.command_process_finished) { 379| 0| llb_buildsystem_command_extended_result_t result; 380| 0| result.result = get_command_result(commandResult.status); 381| 0| result.exit_status = commandResult.exitCode; 382| 0| result.pid = commandResult.pid; 383| 0| result.utime = commandResult.utime; 384| 0| result.stime = commandResult.stime; 385| 0| result.maxrss = commandResult.maxrss; 386| 0| 387| 0| cAPIDelegate.command_process_finished( 388| 0| cAPIDelegate.context, 389| 0| (llb_buildsystem_command_t*) command, 390| 0| (llb_buildsystem_process_t*) handle.id, 391| 0| &result); 392| 0| } 393| 0| } 394| | 395| | /// Request cancellation of any current build. 396| 0| void cancel() override { 397| 0| BuildSystemFrontendDelegate::cancel(); 398| 0| } 399| | 400| | 401| 0| static llb_build_key_t convertBuildKey(const BuildKey& key) { 402| 0| llb_build_key_t buildKey; 403| 0| 404| 0| switch (key.getKind()) { 405| 0| case BuildKey::Kind::Command: 406| 0| buildKey.kind = llb_build_key_kind_command; 407| 0| buildKey.key = strdup(key.getCommandName().str().c_str()); 408| 0| break; 409| 0| case BuildKey::Kind::CustomTask: 410| 0| buildKey.kind = llb_build_key_kind_custom_task; 411| 0| buildKey.key = strdup(key.getCustomTaskName().str().c_str()); 412| 0| break; 413| 0| case BuildKey::Kind::DirectoryContents: 414| 0| buildKey.kind = llb_build_key_kind_directory_contents; 415| 0| buildKey.key = strdup(key.getDirectoryPath().str().c_str()); 416| 0| break; 417| 0| case BuildKey::Kind::FilteredDirectoryContents: 418| 0| buildKey.kind = llb_build_key_kind_filtered_directory_contents; 419| 0| buildKey.key = strdup(key.getFilteredDirectoryPath().str().c_str()); 420| 0| break; 421| 0| case BuildKey::Kind::DirectoryTreeSignature: 422| 0| buildKey.kind = llb_build_key_kind_directory_tree_signature; 423| 0| buildKey.key = strdup(key.getDirectoryTreeSignaturePath().str().c_str()); 424| 0| break; 425| 0| case BuildKey::Kind::DirectoryTreeStructureSignature: 426| 0| buildKey.kind = llb_build_key_kind_directory_tree_structure_signature; 427| 0| buildKey.key = strdup(key.getDirectoryPath().str().c_str()); 428| 0| break; 429| 0| case BuildKey::Kind::Node: 430| 0| buildKey.kind = llb_build_key_kind_node; 431| 0| buildKey.key = strdup(key.getNodeName().str().c_str()); 432| 0| break; 433| 0| case BuildKey::Kind::Stat: 434| 0| buildKey.kind = llb_build_key_kind_stat; 435| 0| buildKey.key = strdup(key.getStatName().str().c_str()); 436| 0| break; 437| 0| case BuildKey::Kind::Target: 438| 0| buildKey.kind = llb_build_key_kind_target; 439| 0| buildKey.key = strdup(key.getTargetName().str().c_str()); 440| 0| break; 441| 0| case BuildKey::Kind::Unknown: 442| 0| buildKey.kind = llb_build_key_kind_unknown; 443| 0| buildKey.key = strdup("((unknown))"); 444| 0| break; 445| 0| } 446| 0| 447| 0| return buildKey; 448| 0| } 449| | 450| | class CAPIRulesVector { 451| | private: 452| | std::vector rules; 453| | 454| | public: 455| 0| CAPIRulesVector(const std::vector& items) : rules(items.size()) { 456| 0| int idx = 0; 457| 0| 458| 0| for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) { 459| 0| core::Rule* rule = *it; 460| 0| auto key = BuildKey::fromData(rule->key); 461| 0| rules[idx++] = convertBuildKey(key); 462| 0| } 463| 0| } 464| | 465| 0| ~CAPIRulesVector() { 466| 0| for (auto& rule : rules) { 467| 0| free((char *)rule.key); 468| 0| } 469| 0| } 470| | 471| 0| llb_build_key_t* data() { return &rules[0]; } 472| 0| uint64_t count() { return rules.size(); } 473| | }; 474| | 475| | 476| 0| virtual void cycleDetected(const std::vector& items) override { 477| 0| CAPIRulesVector rules(items); 478| 0| cAPIDelegate.cycle_detected(cAPIDelegate.context, rules.data(), rules.count()); 479| 0| } 480| | 481| | static llb_cycle_action_t 482| 0| convertCycleAction(core::Rule::CycleAction action) { 483| 0| switch (action) { 484| 0| case core::Rule::CycleAction::ForceBuild: 485| 0| return llb_cycle_action_force_build; 486| 0| case core::Rule::CycleAction::SupplyPriorValue: 487| 0| return llb_cycle_action_supply_prior_value; 488| 0| } 489| 0| assert(0 && "unknown cycle action"); 490| 0| return llb_cycle_action_force_build; 491| 0| } 492| | 493| | virtual bool shouldResolveCycle(const std::vector& items, 494| | core::Rule* candidateRule, 495| 0| core::Rule::CycleAction action) override { 496| 0| if (!cAPIDelegate.should_resolve_cycle) 497| 0| return false; 498| 0| 499| 0| CAPIRulesVector rules(items); 500| 0| auto key = BuildKey::fromData(candidateRule->key); 501| 0| llb_build_key_t candidate = convertBuildKey(key); 502| 0| 503| 0| uint8_t result = cAPIDelegate.should_resolve_cycle(cAPIDelegate.context, 504| 0| rules.data(), 505| 0| rules.count(), 506| 0| candidate, 507| 0| convertCycleAction(action)); 508| 0| 509| 0| free((char *)candidate.key); 510| 0| 511| 0| return (result); 512| 0| } 513| | 514| 0| virtual void error(StringRef filename, const Token& at, const Twine& message) override { 515| 0| if (cAPIDelegate.handle_diagnostic) { 516| 0| cAPIDelegate.handle_diagnostic(cAPIDelegate.context, 517| 0| llb_buildsystem_diagnostic_kind_error, 518| 0| filename.str().c_str(), 519| 0| -1, 520| 0| -1, 521| 0| message.str().c_str()); 522| 0| } else { 523| 0| BuildSystemFrontendDelegate::error(filename, at, message); 524| 0| } 525| 0| } 526| |}; 527| | 528| |class CAPIBuildSystem { 529| | llb_buildsystem_delegate_t cAPIDelegate; 530| | 531| | BuildSystemInvocation invocation; 532| | 533| | llvm::SourceMgr sourceMgr; 534| | 535| | std::unique_ptr frontendDelegate; 536| | std::unique_ptr frontend; 537| | 538| 0| void handleDiagnostic(const llvm::SMDiagnostic& diagnostic) { 539| 0| llb_buildsystem_diagnostic_kind_t kind; 540| 0| switch (diagnostic.getKind()) { 541| 0| case llvm::SourceMgr::DK_Error: 542| 0| kind = llb_buildsystem_diagnostic_kind_error; 543| 0| break; 544| 0| case llvm::SourceMgr::DK_Warning: 545| 0| kind = llb_buildsystem_diagnostic_kind_warning; 546| 0| break; 547| 0| case llvm::SourceMgr::DK_Note: 548| 0| kind = llb_buildsystem_diagnostic_kind_note; 549| 0| break; 550| 0| } 551| 0| 552| 0| // FIXME: We don't currently expose the caret diagnostic information, or 553| 0| // fixits. llbuild does currently make use of the caret diagnostics for 554| 0| // reporting problems in build manifest files... 555| 0| cAPIDelegate.handle_diagnostic( 556| 0| cAPIDelegate.context, kind, 557| 0| diagnostic.getFilename().str().c_str(), 558| 0| diagnostic.getLineNo(), diagnostic.getColumnNo(), 559| 0| diagnostic.getMessage().str().c_str()); 560| 0| } 561| | 562| |public: 563| | CAPIBuildSystem(llb_buildsystem_delegate_t delegate, 564| | llb_buildsystem_invocation_t cAPIInvocation) 565| | : cAPIDelegate(delegate) 566| 0| { 567| 0| // Convert the invocation. 568| 0| invocation.buildFilePath = 569| 0| cAPIInvocation.buildFilePath ? cAPIInvocation.buildFilePath : ""; 570| 0| invocation.dbPath = cAPIInvocation.dbPath ? cAPIInvocation.dbPath : ""; 571| 0| invocation.traceFilePath = ( 572| 0| cAPIInvocation.traceFilePath ? cAPIInvocation.traceFilePath : ""); 573| 0| invocation.environment = cAPIInvocation.environment; 574| 0| invocation.useSerialBuild = cAPIInvocation.useSerialBuild; 575| 0| invocation.showVerboseStatus = cAPIInvocation.showVerboseStatus; 576| 0| 577| 0| // Register a custom diagnostic handler with the source manager. 578| 0| sourceMgr.setDiagHandler([](const llvm::SMDiagnostic& diagnostic, 579| 0| void* context) { 580| 0| auto system = (CAPIBuildSystem*) context; 581| 0| system->handleDiagnostic(diagnostic); 582| 0| }, this); 583| 0| 584| 0| // Allocate the frontend delegate. 585| 0| frontendDelegate.reset( 586| 0| // FIXME: Need to get the client name and schema version from 587| 0| // parameters. 588| 0| new CAPIBuildSystemFrontendDelegate(sourceMgr, invocation, delegate)); 589| 0| 590| 0| // Allocate the file system 591| 0| std::unique_ptr fileSystem(new CAPIFileSystem(delegate)); 592| 0| 593| 0| // Allocate the actual frontend. 594| 0| frontend.reset(new BuildSystemFrontend(*frontendDelegate, invocation, 595| 0| std::move(fileSystem))); 596| 0| } 597| | 598| 0| BuildSystemFrontend& getFrontend() { 599| 0| return *frontend; 600| 0| } 601| | 602| 0| bool initialize() { 603| 0| return getFrontend().initialize(); 604| 0| } 605| | 606| 0| bool build(const core::KeyType& key) { 607| 0| // Reset mutable build state. 608| 0| frontendDelegate->resetForBuild(); 609| 0| 610| 0| // FIXME: We probably should return a context to represent the running 611| 0| // build, instead of keeping state (like cancellation) in the delegate. 612| 0| return getFrontend().build(key); 613| 0| } 614| | 615| 0| bool buildNode(const core::KeyType& key) { 616| 0| frontendDelegate->resetForBuild(); 617| 0| return getFrontend().buildNode(key); 618| 0| } 619| | 620| 0| void cancel() { 621| 0| frontendDelegate->cancel(); 622| 0| } 623| |}; 624| | 625| |class CAPITool : public Tool { 626| | llb_buildsystem_tool_delegate_t cAPIDelegate; 627| | 628| |public: 629| | CAPITool(StringRef name, llb_buildsystem_tool_delegate_t delegate) 630| 0| : Tool(name), cAPIDelegate(delegate) {} 631| | 632| | virtual bool configureAttribute(const ConfigureContext& context, 633| | StringRef name, 634| 0| StringRef value) override { 635| 0| // FIXME: Support custom attributes in client tools. 636| 0| return false; 637| 0| } 638| | 639| | virtual bool configureAttribute(const ConfigureContext& context, 640| | StringRef name, 641| 0| ArrayRef values) override { 642| 0| // FIXME: Support custom attributes in client tools. 643| 0| return false; 644| 0| } 645| | 646| | virtual bool configureAttribute( 647| | const ConfigureContext& ctx, StringRef name, 648| 0| ArrayRef> values) override { 649| 0| // FIXME: Support custom attributes in client tools. 650| 0| return false; 651| 0| } 652| | 653| 0| virtual std::unique_ptr createCommand(StringRef name) override { 654| 0| llb_data_t cName{ name.size(), (const uint8_t*) name.data() }; 655| 0| return std::unique_ptr( 656| 0| (Command*) cAPIDelegate.create_command(cAPIDelegate.context, &cName)); 657| 0| } 658| | 659| | virtual std::unique_ptr 660| 0| createCustomCommand(const BuildKey& key) override { 661| 0| // FIXME: Support dynamic commands in client tools. 662| 0| 663| 0| return Tool::createCustomCommand(key); 664| 0| } 665| |}; 666| | 667| |class CAPIExternalCommand : public ExternalCommand { 668| | // FIXME: This is incredibly wasteful to copy everywhere. Rephrase things so 669| | // that the delegates are const and we just carry the context pointer around. 670| | llb_buildsystem_external_command_delegate_t cAPIDelegate; 671| | 672| | /// The path to the dependency output file, if used. 673| | std::string depsPath; 674| | 675| | bool processDiscoveredDependencies(BuildSystemCommandInterface& bsci, 676| | core::Task* task, 677| 0| QueueJobContext* context) { 678| 0| // Read the dependencies file. 679| 0| auto input = bsci.getFileSystem().getFileContents(depsPath); 680| 0| if (!input) { 681| 0| bsci.getDelegate().commandHadError(this, "unable to open dependencies file (" + depsPath + ")"); 682| 0| return false; 683| 0| } 684| 0| 685| 0| // Parse the output. 686| 0| // 687| 0| // We just ignore the rule, and add any dependency that we encounter in the 688| 0| // file. 689| 0| struct DepsActions : public core::DependencyInfoParser::ParseActions { 690| 0| BuildSystemCommandInterface& bsci; 691| 0| core::Task* task; 692| 0| CAPIExternalCommand* command; 693| 0| StringRef depsPath; 694| 0| unsigned numErrors{0}; 695| 0| 696| 0| DepsActions(BuildSystemCommandInterface& bsci, core::Task* task, 697| 0| CAPIExternalCommand* command, StringRef depsPath) 698| 0| : bsci(bsci), task(task), command(command), depsPath(depsPath) {} 699| 0| 700| 0| virtual void error(const char* message, uint64_t position) override { 701| 0| bsci.getDelegate().commandHadError(command, "error reading dependency file '" + depsPath.str() + "': " + std::string(message)); 702| 0| ++numErrors; 703| 0| } 704| 0| 705| 0| // Ignore everything but actual inputs. 706| 0| virtual void actOnVersion(StringRef) override { } 707| 0| virtual void actOnMissing(StringRef) override { } 708| 0| virtual void actOnOutput(StringRef) override { } 709| 0| virtual void actOnInput(StringRef name) override { 710| 0| bsci.taskDiscoveredDependency(task, BuildKey::makeNode(name)); 711| 0| } 712| 0| }; 713| 0| 714| 0| DepsActions actions(bsci, task, this, depsPath); 715| 0| core::DependencyInfoParser(input->getBuffer(), actions).parse(); 716| 0| return actions.numErrors == 0; 717| 0| } 718| | 719| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 720| 0| StringRef value) override { 721| 0| if (name == "deps") { 722| 0| depsPath = value; 723| 0| } else { 724| 0| return ExternalCommand::configureAttribute(ctx, name, value); 725| 0| } 726| 0| return true; 727| 0| } 728| | 729| | virtual void executeExternalCommand(BuildSystemCommandInterface& bsci, 730| | core::Task* task, 731| | QueueJobContext* job_context, 732| 0| llvm::Optional completionFn) override { 733| 0| auto result = cAPIDelegate.execute_command( 734| 0| cAPIDelegate.context, (llb_buildsystem_command_t*)this, 735| 0| (llb_buildsystem_command_interface_t*)&bsci, 736| 0| (llb_task_t*)task, (llb_buildsystem_queue_job_context_t*)job_context) 737| 0| ? ProcessStatus::Succeeded : ProcessStatus::Failed; 738| 0| 739| 0| if (result != ProcessStatus::Succeeded) { 740| 0| // If the command failed, there is no need to gather dependencies. 741| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 742| 0| return; 743| 0| } 744| 0| 745| 0| // Otherwise, collect the discovered dependencies, if used. 746| 0| if (!depsPath.empty()) { 747| 0| if (!processDiscoveredDependencies(bsci, task, job_context)) { 748| 0| // If we were unable to process the dependencies output, report a 749| 0| // failure. 750| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){fn(ProcessStatus::Failed);}); 751| 0| return; 752| 0| } 753| 0| } 754| 0| 755| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 756| 0| } 757| | 758| |public: 759| | CAPIExternalCommand(StringRef name, 760| | llb_buildsystem_external_command_delegate_t delegate) 761| 0| : ExternalCommand(name), cAPIDelegate(delegate) {} 762| | 763| | 764| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 765| 0| // FIXME: Provide client control. 766| 0| llvm::raw_svector_ostream(result) << getName(); 767| 0| } 768| | 769| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 770| 0| // FIXME: Provide client control. 771| 0| llvm::raw_svector_ostream(result) << getName(); 772| 0| } 773| | 774| 0| virtual llbuild::basic::CommandSignature getSignature() override { 775| 0| auto sig = ExternalCommand::getSignature(); 776| 0| if (cAPIDelegate.get_signature) { 777| 0| llb_data_t data; 778| 0| cAPIDelegate.get_signature(cAPIDelegate.context, (llb_buildsystem_command_t*)this, 779| 0| &data); 780| 0| sig = sig.combine(StringRef((const char*)data.data, data.length)); 781| 0| 782| 0| // Release the client memory. 783| 0| // 784| 0| // FIXME: This is gross, come up with a general purpose solution. 785| 0| free((char*)data.data); 786| 0| } 787| 0| return sig; 788| 0| } 789| |}; 790| | 791| |} 792| | 793| |const char* llb_buildsystem_diagnostic_kind_get_name( 794| 0| llb_buildsystem_diagnostic_kind_t kind) { 795| 0| switch (kind) { 796| 0| case llb_buildsystem_diagnostic_kind_note: 797| 0| return "note"; 798| 0| case llb_buildsystem_diagnostic_kind_warning: 799| 0| return "warning"; 800| 0| case llb_buildsystem_diagnostic_kind_error: 801| 0| return "error"; 802| 0| default: 803| 0| return ""; 804| 0| } 805| 0|} 806| | 807| |llb_buildsystem_t* llb_buildsystem_create( 808| | llb_buildsystem_delegate_t delegate, 809| 0| llb_buildsystem_invocation_t invocation) { 810| 0| // Check that all required methods are provided. 811| 0| assert(delegate.handle_diagnostic); 812| 0| assert(delegate.command_started); 813| 0| assert(delegate.command_finished); 814| 0| assert(delegate.command_process_started); 815| 0| assert(delegate.command_process_had_error); 816| 0| assert(delegate.command_process_had_output); 817| 0| assert(delegate.command_process_finished); 818| 0| 819| 0| return (llb_buildsystem_t*) new CAPIBuildSystem(delegate, invocation); 820| 0|} 821| | 822| 0|void llb_buildsystem_destroy(llb_buildsystem_t* system) { 823| 0| delete (CAPIBuildSystem*)system; 824| 0|} 825| | 826| |llb_buildsystem_tool_t* 827| |llb_buildsystem_tool_create(const llb_data_t* name, 828| 0| llb_buildsystem_tool_delegate_t delegate) { 829| 0| // Check that all required methods are provided. 830| 0| assert(delegate.create_command); 831| 0| return (llb_buildsystem_tool_t*) new CAPITool( 832| 0| StringRef((const char*)name->data, name->length), delegate); 833| 0|} 834| | 835| 0|bool llb_buildsystem_initialize(llb_buildsystem_t* system_p) { 836| 0| CAPIBuildSystem* system = (CAPIBuildSystem*) system_p; 837| 0| return system->initialize(); 838| 0|} 839| | 840| 0|bool llb_buildsystem_build(llb_buildsystem_t* system_p, const llb_data_t* key) { 841| 0| CAPIBuildSystem* system = (CAPIBuildSystem*) system_p; 842| 0| return system->build(core::KeyType((const char*)key->data, key->length)); 843| 0|} 844| | 845| 0|bool llb_buildsystem_build_node(llb_buildsystem_t* system_p, const llb_data_t* key) { 846| 0| CAPIBuildSystem* system = (CAPIBuildSystem*) system_p; 847| 0| return system->buildNode(core::KeyType((const char*)key->data, key->length)); 848| 0|} 849| | 850| 0|void llb_buildsystem_cancel(llb_buildsystem_t* system_p) { 851| 0| CAPIBuildSystem* system = (CAPIBuildSystem*) system_p; 852| 0| system->cancel(); 853| 0|} 854| | 855| |llb_buildsystem_command_t* 856| |llb_buildsystem_external_command_create( 857| | const llb_data_t* name, 858| 0| llb_buildsystem_external_command_delegate_t delegate) { 859| 0| // Check that all required methods are provided. 860| 0| assert(delegate.execute_command); 861| 0| 862| 0| return (llb_buildsystem_command_t*) new CAPIExternalCommand( 863| 0| StringRef((const char*)name->data, name->length), delegate); 864| 0|} 865| | 866| |void llb_buildsystem_command_get_name(llb_buildsystem_command_t* command_p, 867| 0| llb_data_t* key_out) { 868| 0| auto command = (Command*) command_p; 869| 0| 870| 0| auto name = command->getName(); 871| 0| key_out->length = name.size(); 872| 0| key_out->data = (const uint8_t*) name.data(); 873| 0|} 874| | 875| |bool llb_buildsystem_command_should_show_status( 876| 0| llb_buildsystem_command_t* command_p) { 877| 0| auto command = (Command*) command_p; 878| 0| return command->shouldShowStatus(); 879| 0|} 880| | 881| |char* llb_buildsystem_command_get_description( 882| 0| llb_buildsystem_command_t* command_p) { 883| 0| auto command = (Command*) command_p; 884| 0| 885| 0| SmallString<256> result; 886| 0| command->getShortDescription(result); 887| 0| return strdup(result.c_str()); 888| 0|} 889| | 890| |char* llb_buildsystem_command_get_verbose_description( 891| 0| llb_buildsystem_command_t* command_p) { 892| 0| auto command = (Command*) command_p; 893| 0| 894| 0| SmallString<256> result; 895| 0| command->getVerboseDescription(result); 896| 0| return strdup(result.c_str()); 897| 0|} 898| | 899| 0|llb_quality_of_service_t llb_get_quality_of_service() { 900| 0| switch (getDefaultQualityOfService()) { 901| 0| case QualityOfService::Normal: 902| 0| return llb_quality_of_service_default; 903| 0| case QualityOfService::UserInitiated: 904| 0| return llb_quality_of_service_user_initiated; 905| 0| case QualityOfService::Utility: 906| 0| return llb_quality_of_service_utility; 907| 0| case QualityOfService::Background: 908| 0| return llb_quality_of_service_background; 909| 0| default: 910| 0| assert(0 && "unknown quality service level"); 911| 0| return llb_quality_of_service_default; 912| 0| } 913| 0|} 914| | 915| 0|void llb_set_quality_of_service(llb_quality_of_service_t level) { 916| 0| switch (level) { 917| 0| case llb_quality_of_service_default: 918| 0| setDefaultQualityOfService(QualityOfService::Normal); 919| 0| break; 920| 0| case llb_quality_of_service_user_initiated: 921| 0| setDefaultQualityOfService(QualityOfService::UserInitiated); 922| 0| break; 923| 0| case llb_quality_of_service_utility: 924| 0| setDefaultQualityOfService(QualityOfService::Utility); 925| 0| break; 926| 0| case llb_quality_of_service_background: 927| 0| setDefaultQualityOfService(QualityOfService::Background); 928| 0| break; 929| 0| default: 930| 0| assert(0 && "unknown quality service level"); 931| 0| break; 932| 0| } 933| 0|} 934| | 935| 0|void* llb_alloc(size_t size) { return malloc(size); } 936| 0|void llb_free(void* ptr) { free(ptr); } /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/libllbuild/C-API.cpp: 1| |//===-- C-API.cpp ---------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |// Include the public API. 14| |#include 15| | 16| |#include "llbuild/Basic/Version.h" 17| | 18| |using namespace llbuild; 19| | 20| |/* Misc API */ 21| | 22| 0|const char* llb_get_full_version_string(void) { 23| 0| // Use a static local to store the version string, to avoid lifetime issues. 24| 0| static std::string versionString = getLLBuildFullVersion(); 25| 0| 26| 0| return versionString.c_str(); 27| 0|} 28| | 29| 0|int llb_get_api_version(void) { 30| 0| return LLBUILD_C_API_VERSION; 31| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/libllbuild/Core-C-API.cpp: 1| |//===-- Core-C-API.cpp ----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |// Include the public API. 14| |#include 15| | 16| |#include "llbuild/Basic/Tracing.h" 17| |#include "llbuild/Core/BuildDB.h" 18| |#include "llbuild/Core/BuildEngine.h" 19| | 20| |#include 21| |#include 22| | 23| |using namespace llbuild; 24| |using namespace llbuild::core; 25| | 26| |/* Build Engine API */ 27| | 28| |namespace { 29| | 30| |class CAPIBuildEngineDelegate : public BuildEngineDelegate { 31| | llb_buildengine_delegate_t cAPIDelegate; 32| | 33| | friend class CAPITask; 34| | 35| 0| virtual ~CAPIBuildEngineDelegate() { 36| 0| if (cAPIDelegate.destroy_context) { 37| 0| cAPIDelegate.destroy_context(cAPIDelegate.context); 38| 0| } 39| 0| } 40| | 41| 0| virtual Rule lookupRule(const KeyType& key) override { 42| 0| void* engineContext = cAPIDelegate.context; 43| 0| llb_rule_t rule{}; 44| 0| llb_data_t key_data{ key.length(), (const uint8_t*)key.data() }; 45| 0| cAPIDelegate.lookup_rule(cAPIDelegate.context, &key_data, &rule); 46| 0| 47| 0| // FIXME: Check that the client created the rule appropriately. We should 48| 0| // change the API to be type safe here, by forcing the client to return a 49| 0| // handle created by the C API. 50| 0| assert(rule.create_task && "client failed to initialize rule"); 51| 0| 52| 0| std::function isResultValid; 54| 0| if (rule.is_result_valid) { 55| 0| isResultValid = [rule, engineContext] (BuildEngine&, 56| 0| const Rule& nativeRule, 57| 0| const ValueType& value) { 58| 0| // FIXME: Why do we pass the rule here, it is redundant. NativeRule 59| 0| // should be == rule here. 60| 0| llb_data_t value_data{ value.size(), value.data() }; 61| 0| return rule.is_result_valid(rule.context, engineContext, &rule, 62| 0| &value_data); 63| 0| }; 64| 0| } 65| 0| 66| 0| std::function updateStatus; 67| 0| if (rule.update_status) { 68| 0| updateStatus = [rule, engineContext] (BuildEngine&, 69| 0| Rule::StatusKind kind) { 70| 0| return rule.update_status(rule.context, engineContext, 71| 0| (llb_rule_status_kind_t)kind); 72| 0| }; 73| 0| } 74| 0| 75| 0| return Rule{ 76| 0| // FIXME: This is a wasteful copy. 77| 0| key, 78| 0| [rule, engineContext] (BuildEngine& engine) { 79| 0| return (Task*) rule.create_task(rule.context, engineContext); 80| 0| }, 81| 0| isResultValid, 82| 0| updateStatus }; 83| 0| } 84| | 85| 0| virtual void cycleDetected(const std::vector& items) override { 86| 0| // FIXME. 87| 0| assert(0 && "unexpected cycle!"); 88| 0| } 89| | 90| 0| virtual void error(const Twine& message) override { 91| 0| cAPIDelegate.error(cAPIDelegate.context, message.str().c_str()); 92| 0| } 93| | 94| |public: 95| | CAPIBuildEngineDelegate(llb_buildengine_delegate_t delegate) 96| | : cAPIDelegate(delegate) 97| 0| { 98| 0| 99| 0| } 100| |}; 101| | 102| |/// Holds onto the pointers for both the build engine and delegate objects so 103| |/// that both of them can be properly cleaned up when destroy() is called. 104| |struct CAPIBuildEngine { 105| | std::unique_ptr delegate; 106| | std::unique_ptr engine; 107| |}; 108| | 109| |class CAPITask : public Task { 110| | llb_task_delegate_t cAPIDelegate; 111| | 112| |public: 113| 0| CAPITask(llb_task_delegate_t delegate) : cAPIDelegate(delegate) { 114| 0| assert(cAPIDelegate.start && "missing task start function"); 115| 0| assert(cAPIDelegate.provide_value && 116| 0| "missing task provide_value function"); 117| 0| assert(cAPIDelegate.inputs_available && 118| 0| "missing task inputs_available function"); 119| 0| } 120| | 121| 0| virtual ~CAPITask() { 122| 0| if (cAPIDelegate.destroy_context) { 123| 0| cAPIDelegate.destroy_context(cAPIDelegate.context); 124| 0| } 125| 0| } 126| | 127| 0| virtual void start(BuildEngine& engine) override { 128| 0| CAPIBuildEngineDelegate* delegate = 129| 0| static_cast(engine.getDelegate()); 130| 0| cAPIDelegate.start(cAPIDelegate.context, 131| 0| delegate->cAPIDelegate.context, 132| 0| (llb_task_t*)this); 133| 0| } 134| | 135| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 136| 0| const ValueType& value) override { 137| 0| CAPIBuildEngineDelegate* delegate = 138| 0| static_cast(engine.getDelegate()); 139| 0| llb_data_t valueData{ value.size(), value.data() }; 140| 0| cAPIDelegate.provide_value(cAPIDelegate.context, 141| 0| delegate->cAPIDelegate.context, 142| 0| (llb_task_t*)this, 143| 0| inputID, &valueData); 144| 0| } 145| | 146| 0| virtual void inputsAvailable(BuildEngine& engine) override { 147| 0| CAPIBuildEngineDelegate* delegate = 148| 0| static_cast(engine.getDelegate()); 149| 0| cAPIDelegate.inputs_available(cAPIDelegate.context, 150| 0| delegate->cAPIDelegate.context, 151| 0| (llb_task_t*)this); 152| 0| } 153| |}; 154| | 155| |}; 156| | 157| 0|llb_buildengine_t* llb_buildengine_create(llb_buildengine_delegate_t delegate) { 158| 0| CAPIBuildEngine* capi_engine = new CAPIBuildEngine; 159| 0| capi_engine->delegate = std::unique_ptr( 160| 0| new CAPIBuildEngineDelegate(delegate)); 161| 0| capi_engine->engine = std::unique_ptr( 162| 0| new BuildEngine(*capi_engine->delegate)); 163| 0| return (llb_buildengine_t*) capi_engine; 164| 0|} 165| | 166| 0|void llb_buildengine_destroy(llb_buildengine_t* engine) { 167| 0| // FIXME: Delegate is lost. 168| 0| delete (CAPIBuildEngine*)engine; 169| 0|} 170| | 171| |bool llb_buildengine_attach_db(llb_buildengine_t* engine_p, 172| | const llb_data_t* path, 173| | uint32_t schema_version, 174| 0| char** error_out) { 175| 0| BuildEngine& engine = *((CAPIBuildEngine*) engine_p)->engine; 176| 0| 177| 0| std::string error; 178| 0| std::unique_ptr db(createSQLiteBuildDB( 179| 0| std::string((char*)path->data, 180| 0| path->length), 181| 0| schema_version, 182| 0| &error)); 183| 0| if (!db) { 184| 0| *error_out = strdup(error.c_str()); 185| 0| return false; 186| 0| } 187| 0| 188| 0| bool result = engine.attachDB(std::move(db), &error); 189| 0| *error_out = strdup(error.c_str()); 190| 0| return result; 191| 0|} 192| | 193| |void llb_buildengine_build(llb_buildengine_t* engine_p, const llb_data_t* key, 194| 0| llb_data_t* result_out) { 195| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 196| 0| 197| 0| auto& result = engine->build(KeyType((const char*)key->data, key->length)); 198| 0| 199| 0| *result_out = llb_data_t{ result.size(), result.data() }; 200| 0|} 201| | 202| |llb_task_t* llb_buildengine_register_task(llb_buildengine_t* engine_p, 203| 0| llb_task_t* task) { 204| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 205| 0| engine->registerTask((Task*)task); 206| 0| return task; 207| 0|} 208| | 209| |void llb_buildengine_task_needs_input(llb_buildengine_t* engine_p, 210| | llb_task_t* task, 211| | const llb_data_t* key, 212| 0| uintptr_t input_id) { 213| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 214| 0| engine->taskNeedsInput((Task*)task, 215| 0| KeyType((const char*)key->data, key->length), 216| 0| input_id); 217| 0|} 218| | 219| |void llb_buildengine_task_must_follow(llb_buildengine_t* engine_p, 220| | llb_task_t* task, 221| 0| const llb_data_t* key) { 222| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 223| 0| engine->taskMustFollow((Task*)task, 224| 0| KeyType((const char*)key->data, key->length)); 225| 0|} 226| | 227| |void llb_buildengine_task_discovered_dependency(llb_buildengine_t* engine_p, 228| | llb_task_t* task, 229| 0| const llb_data_t* key) { 230| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 231| 0| engine->taskDiscoveredDependency((Task*)task, 232| 0| KeyType((const char*)key->data, 233| 0| key->length)); 234| 0|} 235| | 236| |void llb_buildengine_task_is_complete(llb_buildengine_t* engine_p, 237| | llb_task_t* task, 238| | const llb_data_t* value, 239| 0| bool force_change) { 240| 0| auto& engine = ((CAPIBuildEngine*) engine_p)->engine; 241| 0| std::vector result(value->length); 242| 0| memcpy(result.data(), value->data, value->length); 243| 0| engine->taskIsComplete((Task*)task, std::move(result)); 244| 0|} 245| | 246| 0|llb_task_t* llb_task_create(llb_task_delegate_t delegate) { 247| 0| return (llb_task_t*) new CAPITask(delegate); 248| 0|} 249| | 250| 0|void llb_enable_tracing() { 251| 0| TracingEnabled = true; 252| 0|} 253| | 254| 0|void llb_disable_tracing() { 255| 0| TracingEnabled = false; 256| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/libllbuild/include/llbuild/llbuild.h: 1| |//===- llbuild.h --------------------------------------------------*- C -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// These are the C API interfaces to the llbuild library. 14| |// 15| |//===----------------------------------------------------------------------===// 16| | 17| |#ifndef LLBUILD_PUBLIC_LLBUILD_H 18| |#define LLBUILD_PUBLIC_LLBUILD_H 19| | 20| |#if defined(__cplusplus) 21| |#if defined(_WIN32) 22| |#define LLBUILD_EXPORT extern "C" __declspec(dllexport) 23| |#else 24| |#define LLBUILD_EXPORT extern "C" __attribute__((visibility("default"))) 25| |#endif 26| |#elif __GNUC__ 27| |#define LLBUILD_EXPORT extern __attribute__((visibility("default"))) 28| |#elif defined(_WIN32) 29| |#define LLBUILD_EXPORT extern __declspec(dllexport) 30| |#else 31| |#define LLBUILD_EXPORT extern 32| |#endif 33| | 34| |#ifndef __has_attribute 35| |#define __has_attribute(x) 0 36| |#endif 37| | 38| |#if __has_attribute(swift_name) 39| |# define LLBUILD_SWIFT_NAME(_name) __attribute__((swift_name(#_name))) 40| |#else 41| |# define LLBUILD_SWIFT_NAME(_name) 42| |#endif 43| | 44| |#if __has_attribute(enum_extensibility) 45| |#define LLBUILD_ENUM_ATTRIBUTES __attribute__((enum_extensibility(open))) 46| |#else 47| |#define LLBUILD_ENUM_ATTRIBUTES 48| |#endif 49| | 50| |/// A monotonically increasing indicator of the llbuild API version. 51| |/// 52| |/// The llbuild API is *not* stable. This value allows clients to conditionally 53| |/// compile for multiple versions of the API. 54| |/// 55| |/// Version History: 56| |/// 57| |/// 8: Move scheduler algorithm and lanes into llb_buildsystem_invocation_t 58| |/// 59| |/// 7: Added destroy_context task delegate method. 60| |/// 61| |/// 6: Added delegate methods for specific diagnostics. 62| |/// 63| |/// 5: Added `llb_buildsystem_command_extended_result_t`, changed command_process_finished signature. 64| |/// 65| |/// 4: Added llb_buildsystem_build_node. 66| |/// 67| |/// 3: Added command_had_error, command_had_note and command_had_warning delegate methods. 68| |/// 69| |/// 2: Added `llb_buildsystem_command_result_t` parameter to command_finished. 70| |/// 71| |/// 1: Added `environment` parameter to llb_buildsystem_invocation_t. 72| |/// 73| |/// 0: Pre-history 74| 0|#define LLBUILD_C_API_VERSION 8 75| | 76| |/// Get the full version of the llbuild library. 77| |LLBUILD_EXPORT const char* llb_get_full_version_string(void); 78| | 79| |/// Get the C API version number. 80| |LLBUILD_EXPORT int llb_get_api_version(void); 81| | 82| |// The Core component. 83| |#include "core.h" 84| | 85| |// The BuildSystem component. 86| |#include "buildsystem.h" 87| | 88| |#endif <<<<<< EOF # path=clibc.framework.coverage.txt 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |// Stub method to avoid no debug symbol warning from compiler. 12| 0|int swiftpm_clibc_anchor() { 13| 0| return 0; 14| 0|} <<<<<< EOF # path=SPMUtility.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/ArgumentParser.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Foundation 13| |import func POSIX.exit 14| | 15| |/// Errors which may be encountered when running argument parser. 16| |public enum ArgumentParserError: Swift.Error { 17| | 18| | /// An unknown option is encountered. 19| | case unknownOption(String) 20| | 21| | /// The value of an argument is invalid. 22| | case invalidValue(argument: String, error: ArgumentConversionError) 23| | 24| | /// Expected a value from the option. 25| | case expectedValue(option: String) 26| | 27| | /// An unexpected positional argument encountered. 28| | case unexpectedArgument(String) 29| | 30| | /// Expected these positional arguments but not found. 31| | case expectedArguments(ArgumentParser, [String]) 32| |} 33| | 34| |extension ArgumentParserError: CustomStringConvertible { 35| 0| public var description: String { 36| 0| switch self { 37| 0| case .unknownOption(let option): 38| 0| return "unknown option \(option); use --help to list available options" 39| 0| case .invalidValue(let argument, let error): 40| 0| return "\(error) for argument \(argument); use --help to print usage" 41| 0| case .expectedValue(let option): 42| 0| return "option \(option) requires a value; provide a value using '\(option) ' or '\(option)='" 43| 0| case .unexpectedArgument(let argument): 44| 0| return "unexpected argument \(argument); use --help to list available arguments" 45| 0| case .expectedArguments(_, let arguments): 46| 0| return "expected arguments: \(arguments.joined(separator: ", "))" 47| 0| } 48| 0| } 49| |} 50| | 51| |/// Conversion errors that can be returned from `ArgumentKind`'s failable 52| |/// initializer. 53| |public enum ArgumentConversionError: Swift.Error { 54| | 55| | /// The value is unknown. 56| | case unknown(value: String) 57| | 58| | /// The value could not be converted to the target type. 59| | case typeMismatch(value: String, expectedType: Any.Type) 60| | 61| | /// Custom reason for conversion failure. 62| | case custom(String) 63| |} 64| | 65| |extension ArgumentConversionError: CustomStringConvertible { 66| 0| public var description: String { 67| 0| switch self { 68| 0| case .unknown(let value): 69| 0| return "unknown value '\(value)'" 70| 0| case .typeMismatch(let value, let expectedType): 71| 0| return "'\(value)' is not convertible to \(expectedType)" 72| 0| case .custom(let reason): 73| 0| return reason 74| 0| } 75| 0| } 76| |} 77| | 78| |extension ArgumentConversionError: Equatable { 79| 0| public static func ==(lhs: ArgumentConversionError, rhs: ArgumentConversionError) -> Bool { 80| 0| switch (lhs, rhs) { 81| 0| case (.unknown(let lhsValue), .unknown(let rhsValue)): 82| 0| return lhsValue == rhsValue 83| 0| case (.unknown, _): 84| 0| return false 85| 0| case (.typeMismatch(let lhsValue, let lhsType), .typeMismatch(let rhsValue, let rhsType)): 86| 0| return lhsValue == rhsValue && lhsType == rhsType 87| 0| case (.typeMismatch, _): 88| 0| return false 89| 0| case (.custom(let lhsReason), .custom(let rhsReason)): 90| 0| return lhsReason == rhsReason 91| 0| case (.custom, _): 92| 0| return false 93| 0| } 94| 0| } 95| |} 96| | 97| |/// Different shells for which we can generate shell scripts. 98| |public enum Shell: String, StringEnumArgument { 99| | case bash 100| | case zsh 101| | 102| | public static var completion: ShellCompletion = .values([ 103| | (bash.rawValue, "generate completion script for Bourne-again shell"), 104| | (zsh.rawValue, "generate completion script for Z shell"), 105| | ]) 106| |} 107| | 108| |/// Various shell completions modes supplied by ArgumentKind. 109| |public enum ShellCompletion { 110| | /// Offers no completions at all; e.g. for a string identifier. 111| | case none 112| | 113| | /// No specific completions, will offer tool's completions. 114| | case unspecified 115| | 116| | /// Offers filename completions. 117| | case filename 118| | 119| | /// Custom function for generating completions. Must be provided in the script's scope. 120| | case function(String) 121| | 122| | /// Offers completions from predefined list. A description can be provided which is shown in some shells, like zsh. 123| | case values([(value: String, description: String)]) 124| |} 125| | 126| |/// A protocol representing the possible types of arguments. 127| |/// 128| |/// Conforming to this protocol will qualify the type to act as 129| |/// positional and option arguments in the argument parser. 130| |public protocol ArgumentKind { 131| | /// Throwable convertion initializer. 132| | init(argument: String) throws 133| | 134| | /// Type of shell completion to provide for this argument. 135| | static var completion: ShellCompletion { get } 136| |} 137| | 138| |// MARK: - ArgumentKind conformance for common types 139| | 140| |extension String: ArgumentKind { 141| 12| public init(argument: String) throws { 142| 12| self = argument 143| 12| } 144| | 145| | public static let completion: ShellCompletion = .none 146| |} 147| | 148| |extension Int: ArgumentKind { 149| 0| public init(argument: String) throws { 150| 0| guard let int = Int(argument) else { 151| 0| throw ArgumentConversionError.typeMismatch(value: argument, expectedType: Int.self) 152| 0| } 153| 0| 154| 0| self = int 155| 0| } 156| | 157| | public static let completion: ShellCompletion = .none 158| |} 159| | 160| |extension Bool: ArgumentKind { 161| 0| public init(argument: String) throws { 162| 0| switch argument { 163| 0| case "true": 164| 0| self = true 165| 0| case "false": 166| 0| self = false 167| 0| default: 168| 0| throw ArgumentConversionError.unknown(value: argument) 169| 0| } 170| 0| } 171| | 172| | public static var completion: ShellCompletion = .unspecified 173| |} 174| | 175| |/// A protocol which implements ArgumentKind for string initializable enums. 176| |/// 177| |/// Conforming to this protocol will automatically make an enum with is 178| |/// String initializable conform to ArgumentKind. 179| |public protocol StringEnumArgument: ArgumentKind { 180| | init?(rawValue: String) 181| |} 182| | 183| |extension StringEnumArgument { 184| 0| public init(argument: String) throws { 185| 0| guard let value = Self.init(rawValue: argument) else { 186| 0| throw ArgumentConversionError.unknown(value: argument) 187| 0| } 188| 0| 189| 0| self = value 190| 0| } 191| |} 192| | 193| |/// An argument representing a path (file / directory). 194| |/// 195| |/// The path is resolved in the current working directory. 196| |public struct PathArgument: ArgumentKind { 197| | public let path: AbsolutePath 198| | 199| 0| public init(argument: String) throws { 200| 0| // FIXME: This should check for invalid paths. 201| 0| if let cwd = localFileSystem.currentWorkingDirectory { 202| 0| path = AbsolutePath(argument, relativeTo: cwd) 203| 0| } else { 204| 0| path = try AbsolutePath(validating: argument) 205| 0| } 206| 0| } 207| | 208| | public static var completion: ShellCompletion = .filename 209| |} 210| | 211| |/// An enum representing the strategy to parse argument values. 212| |public enum ArrayParsingStrategy { 213| | /// Will parse only the next argument and append all values together: `-Xcc -Lfoo -Xcc -Lbar`. 214| | case oneByOne 215| | 216| | /// Will parse all values up to the next option argument: `--files file1 file2 --verbosity 1`. 217| | case upToNextOption 218| | 219| | /// Will parse all remaining arguments, usually for executable commands: `swift run exe --option 1`. 220| | case remaining 221| | 222| | /// Function that parses the current arguments iterator based on the strategy 223| | /// and returns the parsed values. 224| 5| func parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 225| 5| var values: [ArgumentKind] = [] 226| 5| 227| 5| switch self { 228| 5| case .oneByOne: 229| 0| guard let nextArgument = parser.next() else { 230| 0| throw ArgumentParserError.expectedValue(option: parser.currentArgument) 231| 0| } 232| 0| 233| 0| try values.append(kind.init(argument: nextArgument)) 234| 5| 235| 5| case .upToNextOption: 236| 5| /// Iterate over arguments until the end or an optional argument 237| 7| while let nextArgument = parser.peek(), isPositional(argument: nextArgument) { 238| 7| /// We need to call next to consume the argument. The peek above did not. 239| 7| _ = parser.next() 240| 7| try values.append(kind.init(argument: nextArgument)) 241| 7| } 242| 5| 243| 5| case .remaining: 244| 0| while let nextArgument = parser.next() { 245| 0| try values.append(kind.init(argument: nextArgument)) 246| 5| } 247| 5| } 248| 5| 249| 5| return values 250| 5| } 251| |} 252| | 253| |/// A protocol representing positional or options argument. 254| |protocol ArgumentProtocol: Hashable { 255| | // FIXME: This should be constrained to ArgumentKind but Array can't conform 256| | // to it: `extension of type 'Array' with constraints cannot have an 257| | // inheritance clause`. 258| | // 259| | /// The argument kind of this argument for eg String, Bool etc. 260| | associatedtype ArgumentKindTy 261| | 262| | /// Name of the argument which will be parsed by the parser. 263| | var name: String { get } 264| | 265| | /// Short name of the argument, this is usually used in options arguments 266| | /// for a short names for e.g: `--help` -> `-h`. 267| | var shortName: String? { get } 268| | 269| | /// The parsing strategy to adopt when parsing values. 270| | var strategy: ArrayParsingStrategy { get } 271| | 272| | /// Defines is the argument is optional 273| | var isOptional: Bool { get } 274| | 275| | /// The usage text associated with this argument. Used to generate complete help string. 276| | var usage: String? { get } 277| | 278| | /// The shell completions to offer as values for this argument. 279| | var completion: ShellCompletion { get } 280| | 281| | // FIXME: Because `ArgumentKindTy`` can't conform to `ArgumentKind`, this 282| | // function has to be provided a kind (which will be different from 283| | // ArgumentKindTy for arrays). Once the generics feature exists we can 284| | // improve this API. 285| | // 286| | /// Parses and returns the argument values from the parser. 287| | func parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] 288| |} 289| | 290| |extension ArgumentProtocol { 291| | // MARK: - Conformance for Hashable 292| | 293| 0| public func hash(into hasher: inout Hasher) { 294| 0| return hasher.combine(name) 295| 0| } 296| | 297| 0| public static func == (_ lhs: Self, _ rhs: Self) -> Bool { 298| 0| return lhs.name == rhs.name && lhs.usage == rhs.usage 299| 0| } 300| |} 301| | 302| |/// Returns true if the given argument does not starts with '-' i.e. it is 303| |/// a positional argument, otherwise it is an options argument. 304| 26|fileprivate func isPositional(argument: String) -> Bool { 305| 26| return !argument.hasPrefix("-") 306| 26|} 307| | 308| |/// A class representing option arguments. These are optional arguments which may 309| |/// or may not be provided in the command line. They are always prefixed by their 310| |/// name. For e.g. --verbosity true. 311| |public final class OptionArgument: ArgumentProtocol { 312| | typealias ArgumentKindTy = Kind 313| | 314| | let name: String 315| | 316| | let shortName: String? 317| | 318| | // Option arguments are always optional. 319| 0| var isOptional: Bool { return true } 320| | 321| | let strategy: ArrayParsingStrategy 322| | 323| | let usage: String? 324| | 325| | let completion: ShellCompletion 326| | 327| 0| init(name: String, shortName: String?, strategy: ArrayParsingStrategy, usage: String?, completion: ShellCompletion) { 328| 0| precondition(!isPositional(argument: name)) 329| 0| self.name = name 330| 0| self.shortName = shortName 331| 0| self.strategy = strategy 332| 0| self.usage = usage 333| 0| self.completion = completion 334| 0| } 335| | 336| 0| func parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 337| 0| do { 338| 0| return try _parse(kind, with: &parser) 339| 0| } catch let conversionError as ArgumentConversionError { 340| 0| throw ArgumentParserError.invalidValue(argument: name, error: conversionError) 341| 0| } 342| 0| } 343| | 344| 0| func _parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 345| 0| // When we have an associated value, we ignore the strategy and only 346| 0| // parse that value. 347| 0| if let associatedArgument = parser.associatedArgumentValue { 348| 0| return try [kind.init(argument: associatedArgument)] 349| 0| } 350| 0| 351| 0| // As a special case, Bool options don't consume arguments. 352| 0| if kind == Bool.self && strategy == .oneByOne { 353| 0| return [true] 354| 0| } 355| 0| 356| 0| let values = try strategy.parse(kind, with: &parser) 357| 0| guard !values.isEmpty else { 358| 0| throw ArgumentParserError.expectedValue(option: name) 359| 0| } 360| 0| 361| 0| return values 362| 0| } 363| |} 364| | 365| |/// A class representing positional arguments. These arguments must be present 366| |/// and in the same order as they are added in the parser. 367| |public final class PositionalArgument: ArgumentProtocol { 368| | 369| | typealias ArgumentKindTy = Kind 370| | 371| | let name: String 372| | 373| | // Postional arguments don't need short names. 374| 7| var shortName: String? { return nil } 375| | 376| | let strategy: ArrayParsingStrategy 377| | 378| | let isOptional: Bool 379| | 380| | let usage: String? 381| | 382| | let completion: ShellCompletion 383| | 384| 7| init(name: String, strategy: ArrayParsingStrategy, optional: Bool, usage: String?, completion: ShellCompletion) { 385| 7| precondition(isPositional(argument: name)) 386| 7| self.name = name 387| 7| self.strategy = strategy 388| 7| self.isOptional = optional 389| 7| self.usage = usage 390| 7| self.completion = completion 391| 7| } 392| | 393| 5| func parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 394| 5| do { 395| 5| return try _parse(kind, with: &parser) 396| 5| } catch let conversionError as ArgumentConversionError { 397| 0| throw ArgumentParserError.invalidValue(argument: name, error: conversionError) 398| 0| } 399| 0| } 400| | 401| 5| func _parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 402| 5| let value = try kind.init(argument: parser.currentArgument) 403| 5| 404| 5| var values = [value] 405| 5| 406| 5| switch strategy { 407| 5| case .oneByOne: 408| 0| // We shouldn't apply the strategy with `.oneByOne` because we 409| 0| // already have one, the parsed `parser.currentArgument`. 410| 0| break 411| 5| 412| 5| case .upToNextOption, .remaining: 413| 5| try values.append(contentsOf: strategy.parse(kind, with: &parser)) 414| 5| } 415| 5| 416| 5| return values 417| 5| } 418| |} 419| | 420| |/// A type-erased argument. 421| |/// 422| |/// Note: Only used for argument parsing purpose. 423| |final class AnyArgument: ArgumentProtocol, CustomStringConvertible { 424| | typealias ArgumentKindTy = Any 425| | 426| | let name: String 427| | 428| | let shortName: String? 429| | 430| | let strategy: ArrayParsingStrategy 431| | 432| | let isOptional: Bool 433| | 434| | let usage: String? 435| | 436| | let completion: ShellCompletion 437| | 438| | /// The argument kind this holds, used while initializing that argument. 439| | let kind: ArgumentKind.Type 440| | 441| | /// True if the argument kind is of array type. 442| | let isArray: Bool 443| | 444| | /// A type-erased wrapper around the argument's `parse` function. 445| | private let parseClosure: (ArgumentKind.Type, inout ArgumentParserProtocol) throws -> [ArgumentKind] 446| | 447| 0| init(_ argument: T) { 448| 0| self.kind = T.ArgumentKindTy.self as! ArgumentKind.Type 449| 0| self.name = argument.name 450| 0| self.shortName = argument.shortName 451| 0| self.strategy = argument.strategy 452| 0| self.isOptional = argument.isOptional 453| 0| self.usage = argument.usage 454| 0| self.completion = argument.completion 455| 0| self.parseClosure = argument.parse(_:with:) 456| 0| isArray = false 457| 0| } 458| | 459| | /// Initializer for array arguments. 460| 7| init(_ argument: T) where T.ArgumentKindTy: Sequence { 461| 7| self.kind = T.ArgumentKindTy.Element.self as! ArgumentKind.Type 462| 7| self.name = argument.name 463| 7| self.shortName = argument.shortName 464| 7| self.strategy = argument.strategy 465| 7| self.isOptional = argument.isOptional 466| 7| self.usage = argument.usage 467| 7| self.completion = argument.completion 468| 7| self.parseClosure = argument.parse(_:with:) 469| 7| isArray = true 470| 7| } 471| | 472| 0| var description: String { 473| 0| return "Argument(\(name))" 474| 0| } 475| | 476| 0| func parse(_ kind: ArgumentKind.Type, with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 477| 0| return try self.parseClosure(kind, &parser) 478| 0| } 479| | 480| 5| func parse(with parser: inout ArgumentParserProtocol) throws -> [ArgumentKind] { 481| 5| return try self.parseClosure(self.kind, &parser) 482| 5| } 483| |} 484| | 485| |// FIXME: We probably don't need this protocol anymore and should convert this to a class. 486| |// 487| |/// Argument parser protocol passed in initializers of ArgumentKind to manipulate 488| |/// parser as needed by the argument. 489| |public protocol ArgumentParserProtocol { 490| | /// The current argument being parsed. 491| | var currentArgument: String { get } 492| | 493| | /// The associated value in a `--foo=bar` style argument. 494| | var associatedArgumentValue: String? { get } 495| | 496| | /// Provides (consumes) and returns the next argument. Returns `nil` if there are not arguments left. 497| | mutating func next() -> String? 498| | 499| | /// Peek at the next argument without consuming it. 500| | func peek() -> String? 501| |} 502| | 503| |/// Argument parser struct responsible to parse the provided array of arguments 504| |/// and return the parsed result. 505| |public final class ArgumentParser { 506| | 507| | /// A class representing result of the parsed arguments. 508| | public class Result: CustomStringConvertible { 509| | /// Internal representation of arguments mapped to their values. 510| | private var results = [String: Any]() 511| | 512| | /// Result of the parent parent parser, if any. 513| | private var parentResult: Result? 514| | 515| | /// Reference to the parser this result belongs to. 516| | private let parser: ArgumentParser 517| | 518| | /// The subparser command chosen. 519| | fileprivate var subparser: String? 520| | 521| | /// Create a result with a parser and parent result. 522| 14| init(parser: ArgumentParser, parent: Result?) { 523| 14| self.parser = parser 524| 14| self.parentResult = parent 525| 14| } 526| | 527| | /// Adds a result. 528| | /// 529| | /// - Parameters: 530| | /// - values: The associated values of the argument. 531| | /// - argument: The argument for which this result is being added. 532| | /// - Note: 533| | /// While it may seem more fragile to use an array as input in the 534| | /// case of single-value arguments, this design choice allows major 535| | /// simplifications in the parsing code. 536| 5| fileprivate func add(_ values: [ArgumentKind], for argument: AnyArgument) throws { 537| 5| if argument.isArray { 538| 5| var array = results[argument.name] as? [ArgumentKind] ?? [] 539| 5| array.append(contentsOf: values) 540| 5| results[argument.name] = array 541| 5| } else { 542| 0| // We expect only one value for non-array arguments. 543| 0| guard let value = values.spm_only else { 544| 0| assertionFailure() 545| 0| return 546| 0| } 547| 0| results[argument.name] = value 548| 5| } 549| 5| } 550| | 551| | /// Get an option argument's value from the results. 552| | /// 553| | /// Since the options are optional, their result may or may not be present. 554| 0| public func get(_ argument: OptionArgument) -> T? { 555| 0| return (results[argument.name] as? T) ?? parentResult?.get(argument) 556| 0| } 557| | 558| | /// Array variant for option argument's get(_:). 559| 0| public func get(_ argument: OptionArgument<[T]>) -> [T]? { 560| 0| return (results[argument.name] as? [T]) ?? parentResult?.get(argument) 561| 0| } 562| | 563| | /// Get a positional argument's value. 564| 0| public func get(_ argument: PositionalArgument) -> T? { 565| 0| return results[argument.name] as? T 566| 0| } 567| | 568| | /// Array variant for positional argument's get(_:). 569| 7| public func get(_ argument: PositionalArgument<[T]>) -> [T]? { 570| 7| return results[argument.name] as? [T] 571| 7| } 572| | 573| | /// Get an argument's value using its name. 574| | /// - throws: An ArgumentParserError.invalidValue error if the parsed argument does not match the expected type. 575| 0| public func get(_ name: String) throws -> T? { 576| 0| guard let value = results[name] else { 577| 0| // if we have a parent and this is an option argument, look in the parent result 578| 0| if let parentResult = parentResult, name.hasPrefix("-") { 579| 0| return try parentResult.get(name) 580| 0| } else { 581| 0| return nil 582| 0| } 583| 0| } 584| 0| guard let typedValue = value as? T else { 585| 0| throw ArgumentParserError.invalidValue(argument: name, error: .typeMismatch(value: String(describing: value), expectedType: T.self)) 586| 0| } 587| 0| return typedValue 588| 0| } 589| | 590| | /// Get the subparser which was chosen for the given parser. 591| 21| public func subparser(_ parser: ArgumentParser) -> String? { 592| 21| if parser === self.parser { 593| 14| return subparser 594| 14| } 595| 7| return parentResult?.subparser(parser) 596| 21| } 597| | 598| 0| public var description: String { 599| 0| var description = "ArgParseResult(\(results))" 600| 0| if let parent = parentResult { 601| 0| description += " -> " + parent.description 602| 0| } 603| 0| return description 604| 0| } 605| | } 606| | 607| | /// The mapping of subparsers to their subcommand. 608| | private(set) var subparsers: [String: ArgumentParser] = [:] 609| | 610| | /// List of arguments added to this parser. 611| | private(set) var optionArguments: [AnyArgument] = [] 612| | private(set) var positionalArguments: [AnyArgument] = [] 613| | 614| | // If provided, will be substituted instead of arg0 in usage text. 615| | let commandName: String? 616| | 617| | /// Usage string of this parser. 618| | let usage: String 619| | 620| | /// Overview text of this parser. 621| | let overview: String 622| | 623| | /// See more text of this parser. 624| | let seeAlso: String? 625| | 626| | /// If this parser is a subparser. 627| | private let isSubparser: Bool 628| | 629| | /// Boolean specifying if the parser can accept further positional 630| | /// arguments (false if it already has a positional argument with 631| | /// `isOptional` set to `true` or strategy set to `.remaining`). 632| | private var canAcceptPositionalArguments: Bool = true 633| | 634| | /// Create an argument parser. 635| | /// 636| | /// - Parameters: 637| | /// - commandName: If provided, this will be substitued in "usage" line of the generated usage text. 638| | /// Otherwise, first command line argument will be used. 639| | /// - usage: The "usage" line of the generated usage text. 640| | /// - overview: The "overview" line of the generated usage text. 641| | /// - seeAlso: The "see also" line of generated usage text. 642| 11| public init(commandName: String? = nil, usage: String, overview: String, seeAlso: String? = nil) { 643| 11| self.isSubparser = false 644| 11| self.commandName = commandName 645| 11| self.usage = usage 646| 11| self.overview = overview 647| 11| self.seeAlso = seeAlso 648| 11| } 649| | 650| | /// Create a subparser with its help text. 651| 10| private init(subparser overview: String) { 652| 10| self.isSubparser = true 653| 10| self.commandName = nil 654| 10| self.usage = "" 655| 10| self.overview = overview 656| 10| self.seeAlso = nil 657| 10| } 658| | 659| | /// Adds an option to the parser. 660| | public func add( 661| | option: String, 662| | shortName: String? = nil, 663| | kind: T.Type, 664| | usage: String? = nil, 665| | completion: ShellCompletion? = nil 666| 0| ) -> OptionArgument { 667| 0| assert(!optionArguments.contains(where: { $0.name == option }), "Can not define an option twice") 668| 0| 669| 0| let argument = OptionArgument(name: option, shortName: shortName, strategy: .oneByOne, usage: usage, completion: completion ?? T.completion) 670| 0| optionArguments.append(AnyArgument(argument)) 671| 0| return argument 672| 0| } 673| | 674| | /// Adds an array argument type. 675| | public func add( 676| | option: String, 677| | shortName: String? = nil, 678| | kind: [T].Type, 679| | strategy: ArrayParsingStrategy = .upToNextOption, 680| | usage: String? = nil, 681| | completion: ShellCompletion? = nil 682| 0| ) -> OptionArgument<[T]> { 683| 0| assert(!optionArguments.contains(where: { $0.name == option }), "Can not define an option twice") 684| 0| 685| 0| let argument = OptionArgument<[T]>(name: option, shortName: shortName, strategy: strategy, usage: usage, completion: completion ?? T.completion) 686| 0| optionArguments.append(AnyArgument(argument)) 687| 0| return argument 688| 0| } 689| | 690| | /// Adds an argument to the parser. 691| | /// 692| | /// Note: Only one positional argument is allowed if optional setting is enabled. 693| | public func add( 694| | positional: String, 695| | kind: T.Type, 696| | optional: Bool = false, 697| | usage: String? = nil, 698| | completion: ShellCompletion? = nil 699| 0| ) -> PositionalArgument { 700| 0| precondition(subparsers.isEmpty, "Positional arguments are not supported with subparsers") 701| 0| precondition(canAcceptPositionalArguments, "Can not accept more positional arguments") 702| 0| 703| 0| if optional { 704| 0| canAcceptPositionalArguments = false 705| 0| } 706| 0| 707| 0| let argument = PositionalArgument(name: positional, strategy: .oneByOne, optional: optional, usage: usage, completion: completion ?? T.completion) 708| 0| positionalArguments.append(AnyArgument(argument)) 709| 0| return argument 710| 0| } 711| | 712| | /// Adds an argument to the parser. 713| | /// 714| | /// Note: Only one multiple-value positional argument is allowed. 715| | public func add( 716| | positional: String, 717| | kind: [T].Type, 718| | optional: Bool = false, 719| | strategy: ArrayParsingStrategy = .upToNextOption, 720| | usage: String? = nil, 721| | completion: ShellCompletion? = nil 722| 7| ) -> PositionalArgument<[T]> { 723| 7| precondition(subparsers.isEmpty, "Positional arguments are not supported with subparsers") 724| 7| precondition(canAcceptPositionalArguments, "Can not accept more positional arguments") 725| 7| 726| 7| if optional || strategy == .remaining { 727| 7| canAcceptPositionalArguments = false 728| 7| } 729| 7| 730| 7| let argument = PositionalArgument<[T]>(name: positional, strategy: strategy, optional: optional, usage: usage, completion: completion ?? T.completion) 731| 7| positionalArguments.append(AnyArgument(argument)) 732| 7| return argument 733| 7| } 734| | 735| | /// Add a parser with a subcommand name and its corresponding overview. 736| | @discardableResult 737| 10| public func add(subparser command: String, overview: String) -> ArgumentParser { 738| 10| precondition(positionalArguments.isEmpty, "Subparsers are not supported with positional arguments") 739| 10| let parser = ArgumentParser(subparser: overview) 740| 10| subparsers[command] = parser 741| 10| return parser 742| 10| } 743| | 744| | // MARK: - Parsing 745| | 746| | /// A wrapper struct to pass to the ArgumentKind initializers. 747| | struct Parser: ArgumentParserProtocol { 748| | let currentArgument: String 749| | private(set) var associatedArgumentValue: String? 750| | 751| | /// The iterator used to iterate arguments. 752| | fileprivate var argumentsIterator: IndexingIterator<[String]> 753| | 754| 5| init(associatedArgumentValue: String?, argumentsIterator: IndexingIterator<[String]>, currentArgument: String) { 755| 5| self.associatedArgumentValue = associatedArgumentValue 756| 5| self.argumentsIterator = argumentsIterator 757| 5| self.currentArgument = currentArgument 758| 5| } 759| | 760| 7| mutating func next() -> String? { 761| 7| return argumentsIterator.next() 762| 7| } 763| | 764| 12| func peek() -> String? { 765| 12| var iteratorCopy = argumentsIterator 766| 12| let nextArgument = iteratorCopy.next() 767| 12| return nextArgument 768| 12| } 769| | } 770| | 771| | /// Parses the provided array and return the result. 772| 7| public func parse(_ arguments: [String] = []) throws -> Result { 773| 7| return try parse(arguments, parent: nil) 774| 7| } 775| | 776| 14| private func parse(_ arguments: [String] = [], parent: Result?) throws -> Result { 777| 14| let result = Result(parser: self, parent: parent) 778| 14| // Create options map to quickly look up the arguments. 779| 14| let optionsTuple = optionArguments.flatMap({ option -> [(String, AnyArgument)] in 780| 0| var result = [(option.name, option)] 781| 0| // Add the short names too, if we have them. 782| 0| if let shortName = option.shortName { 783| 0| result += [(shortName, option)] 784| 0| } 785| 0| return result 786| 0| }) 787| 14| let optionsMap = Dictionary(items: optionsTuple) 788| 14| 789| 14| // Create iterators. 790| 14| var positionalArgumentIterator = positionalArguments.makeIterator() 791| 14| var argumentsIterator = arguments.makeIterator() 792| 14| 793| 14| while let argumentString = argumentsIterator.next() { 794| 12| let argument: AnyArgument 795| 12| let parser: Parser 796| 12| 797| 12| // If argument is help then just print usage and exit. 798| 12| if argumentString == "-h" || argumentString == "-help" || argumentString == "--help" { 799| 0| printUsage(on: stdoutStream) 800| 0| exit(0) 801| 12| } else if isPositional(argument: argumentString) { 802| 12| /// If this parser has subparsers, we allow only one positional argument which is the subparser command. 803| 12| if !subparsers.isEmpty { 804| 7| // Make sure this argument has a subparser. 805| 7| guard let subparser = subparsers[argumentString] else { 806| 0| throw ArgumentParserError.expectedArguments(self, Array(subparsers.keys)) 807| 7| } 808| 7| // Save which subparser was chosen. 809| 7| result.subparser = argumentString 810| 7| // Parse reset of the arguments with the subparser. 811| 7| return try subparser.parse(Array(argumentsIterator), parent: result) 812| 7| } 813| 5| 814| 5| // Get the next positional argument we are expecting. 815| 5| guard let positionalArgument = positionalArgumentIterator.next() else { 816| 0| throw ArgumentParserError.unexpectedArgument(argumentString) 817| 5| } 818| 5| 819| 5| argument = positionalArgument 820| 5| parser = Parser( 821| 5| associatedArgumentValue: nil, 822| 5| argumentsIterator: argumentsIterator, 823| 5| currentArgument: argumentString) 824| 5| } else { 825| 0| let (argumentString, value) = argumentString.spm_split(around: "=") 826| 0| // Get the corresponding option for the option argument. 827| 0| guard let optionArgument = optionsMap[argumentString] else { 828| 0| throw ArgumentParserError.unknownOption(argumentString) 829| 0| } 830| 0| 831| 0| argument = optionArgument 832| 0| parser = Parser( 833| 0| associatedArgumentValue: value, 834| 0| argumentsIterator: argumentsIterator, 835| 0| currentArgument: argumentString) 836| 5| } 837| 5| 838| 5| // Update results. 839| 5| var parserProtocol = parser as ArgumentParserProtocol 840| 5| let values = try argument.parse(with: &parserProtocol) 841| 5| try result.add(values, for: argument) 842| 5| // Restore the argument iterator state. 843| 5| argumentsIterator = (parserProtocol as! Parser).argumentsIterator 844| 7| } 845| 7| // Report if there are any non-optional positional arguments left which were not present in the arguments. 846| 7| let leftOverArguments = Array(positionalArgumentIterator) 847| 7| if leftOverArguments.contains(where: { !$0.isOptional }) { 848| 0| throw ArgumentParserError.expectedArguments(self, leftOverArguments.map({ $0.name })) 849| 7| } 850| 7| return result 851| 7| } 852| | 853| | /// Prints usage text for this parser on the provided stream. 854| 2| public func printUsage(on stream: OutputByteStream) { 855| 2| /// Space settings. 856| 2| let maxWidthDefault = 24 857| 2| let padding = 2 858| 2| 859| 2| let maxWidth: Int 860| 2| // Determine the max width based on argument length or choose the 861| 2| // default width if max width is longer than the default width. 862| 2| if let maxArgument = (positionalArguments + optionArguments).map({ 863| 0| [$0.name, $0.shortName].compactMap({ $0 }).joined(separator: ", ").count 864| 0| }).max(), maxArgument < maxWidthDefault { 865| 0| maxWidth = maxArgument + padding + 1 866| 2| } else { 867| 2| maxWidth = maxWidthDefault 868| 2| } 869| 2| 870| 2| /// Prints an argument on a stream if it has usage. 871| 2| func print(formatted argument: String, usage: String, on stream: OutputByteStream) { 872| 0| // Start with a new line and add some padding. 873| 0| stream <<< "\n" <<< Format.asRepeating(string: " ", count: padding) 874| 0| let count = argument.count 875| 0| // If the argument is longer than the max width, print the usage 876| 0| // on a new line. Otherwise, print the usage on the same line. 877| 0| if count >= maxWidth - padding { 878| 0| stream <<< argument <<< "\n" 879| 0| // Align full width because usage is to be printed on a new line. 880| 0| stream <<< Format.asRepeating(string: " ", count: maxWidth + padding) 881| 0| } else { 882| 0| stream <<< argument 883| 0| // Align to the remaining empty space on the line. 884| 0| stream <<< Format.asRepeating(string: " ", count: maxWidth - count) 885| 0| } 886| 0| stream <<< usage 887| 0| } 888| 2| 889| 2| stream <<< "OVERVIEW: " <<< overview 890| 2| 891| 2| // We only print command usage for top level parsers. 892| 2| if !isSubparser { 893| 1| stream <<< "\n\n" 894| 1| // Get the binary name from command line arguments. 895| 1| let defaultCommandName = CommandLine.arguments[0].components(separatedBy: "/").last! 896| 1| stream <<< "USAGE: " <<< (commandName ?? defaultCommandName) <<< " " <<< usage 897| 2| } 898| 2| 899| 2| if optionArguments.count > 0 { 900| 0| stream <<< "\n\n" 901| 0| stream <<< "OPTIONS:" 902| 0| for argument in optionArguments.lazy.sorted(by: { $0.name < $1.name }) { 903| 0| guard let usage = argument.usage else { continue } 904| 0| // Create name with its shortname, if available. 905| 0| let name = [argument.name, argument.shortName].compactMap({ $0 }).joined(separator: ", ") 906| 0| print(formatted: name, usage: usage, on: stream) 907| 0| } 908| 0| 909| 0| // Print help option, if this is a top level command. 910| 0| if !isSubparser { 911| 0| print(formatted: "--help", usage: "Display available options", on: stream) 912| 0| } 913| 2| } 914| 2| 915| 2| if subparsers.keys.count > 0 { 916| 0| stream <<< "\n\n" 917| 0| stream <<< "SUBCOMMANDS:" 918| 0| for (command, parser) in subparsers.sorted(by: { $0.key < $1.key }) { 919| 0| // Special case for hidden subcommands. 920| 0| guard !parser.overview.isEmpty else { continue } 921| 0| print(formatted: command, usage: parser.overview, on: stream) 922| 0| } 923| 2| } 924| 2| 925| 2| if positionalArguments.count > 0 { 926| 0| stream <<< "\n\n" 927| 0| stream <<< "POSITIONAL ARGUMENTS:" 928| 0| for argument in positionalArguments { 929| 0| guard let usage = argument.usage else { continue } 930| 0| print(formatted: argument.name, usage: usage, on: stream) 931| 0| } 932| 2| } 933| 2| 934| 2| if let seeAlso = seeAlso { 935| 0| stream <<< "\n\n" 936| 0| stream <<< "SEE ALSO: \(seeAlso)" 937| 2| } 938| 2| 939| 2| stream <<< "\n" 940| 2| stream.flush() 941| 2| } 942| |} 943| | 944| |/// A class to bind ArgumentParser's arguments to an option structure. 945| |public final class ArgumentBinder { 946| | /// The signature of body closure. 947| | private typealias BodyClosure = (inout Options, ArgumentParser.Result) throws -> Void 948| | 949| | /// This array holds the closures which should be executed to fill the options structure. 950| | private var bodies = [BodyClosure]() 951| | 952| | /// Create a binder. 953| 0| public init() { 954| 0| } 955| | 956| | /// Bind an option argument. 957| | public func bind( 958| | option: OptionArgument, 959| | to body: @escaping (inout Options, T) throws -> Void 960| 0| ) { 961| 0| addBody { 962| 0| guard let result = $1.get(option) else { return } 963| 0| try body(&$0, result) 964| 0| } 965| 0| } 966| | 967| | /// Bind an array option argument. 968| | public func bindArray( 969| | option: OptionArgument<[T]>, 970| | to body: @escaping (inout Options, [T]) throws -> Void 971| 0| ) { 972| 0| addBody { 973| 0| guard let result = $1.get(option) else { return } 974| 0| try body(&$0, result) 975| 0| } 976| 0| } 977| | 978| | /// Bind a positional argument. 979| | public func bind( 980| | positional: PositionalArgument, 981| | to body: @escaping (inout Options, T) throws -> Void 982| 0| ) { 983| 0| addBody { 984| 0| // All the positional argument will always be present. 985| 0| guard let result = $1.get(positional) else { return } 986| 0| try body(&$0, result) 987| 0| } 988| 0| } 989| | 990| | /// Bind an array positional argument. 991| | public func bindArray( 992| | positional: PositionalArgument<[T]>, 993| | to body: @escaping (inout Options, [T]) throws -> Void 994| 0| ) { 995| 0| addBody { 996| 0| // All the positional argument will always be present. 997| 0| guard let result = $1.get(positional) else { return } 998| 0| try body(&$0, result) 999| 0| } 1000| 0| } 1001| | 1002| | /// Bind two positional arguments. 1003| | public func bindPositional( 1004| | _ first: PositionalArgument, 1005| | _ second: PositionalArgument, 1006| | to body: @escaping (inout Options, T, U) throws -> Void 1007| 0| ) { 1008| 0| addBody { 1009| 0| // All the positional arguments will always be present. 1010| 0| guard let first = $1.get(first) else { return } 1011| 0| guard let second = $1.get(second) else { return } 1012| 0| try body(&$0, first, second) 1013| 0| } 1014| 0| } 1015| | 1016| | /// Bind three positional arguments. 1017| | public func bindPositional( 1018| | _ first: PositionalArgument, 1019| | _ second: PositionalArgument, 1020| | _ third: PositionalArgument, 1021| | to body: @escaping (inout Options, T, U, V) throws -> Void 1022| 0| ) { 1023| 0| addBody { 1024| 0| // All the positional arguments will always be present. 1025| 0| guard let first = $1.get(first) else { return } 1026| 0| guard let second = $1.get(second) else { return } 1027| 0| guard let third = $1.get(third) else { return } 1028| 0| try body(&$0, first, second, third) 1029| 0| } 1030| 0| } 1031| | 1032| | /// Bind two options. 1033| | public func bind( 1034| | _ first: OptionArgument, 1035| | _ second: OptionArgument, 1036| | to body: @escaping (inout Options, T?, U?) throws -> Void 1037| 0| ) { 1038| 0| addBody { 1039| 0| try body(&$0, $1.get(first), $1.get(second)) 1040| 0| } 1041| 0| } 1042| | 1043| | /// Bind three options. 1044| | public func bind( 1045| | _ first: OptionArgument, 1046| | _ second: OptionArgument, 1047| | _ third: OptionArgument, 1048| | to body: @escaping (inout Options, T?, U?, V?) throws -> Void 1049| 0| ) { 1050| 0| addBody { 1051| 0| try body(&$0, $1.get(first), $1.get(second), $1.get(third)) 1052| 0| } 1053| 0| } 1054| | 1055| | /// Bind two array options. 1056| | public func bindArray( 1057| | _ first: OptionArgument<[T]>, 1058| | _ second: OptionArgument<[U]>, 1059| | to body: @escaping (inout Options, [T], [U]) throws -> Void 1060| 0| ) { 1061| 0| addBody { 1062| 0| try body(&$0, $1.get(first) ?? [], $1.get(second) ?? []) 1063| 0| } 1064| 0| } 1065| | 1066| | /// Add three array option and call the final closure with their values. 1067| | public func bindArray( 1068| | _ first: OptionArgument<[T]>, 1069| | _ second: OptionArgument<[U]>, 1070| | _ third: OptionArgument<[V]>, 1071| | to body: @escaping (inout Options, [T], [U], [V]) throws -> Void 1072| 0| ) { 1073| 0| addBody { 1074| 0| try body(&$0, $1.get(first) ?? [], $1.get(second) ?? [], $1.get(third) ?? []) 1075| 0| } 1076| 0| } 1077| | 1078| | /// Bind a subparser. 1079| | public func bind( 1080| | parser: ArgumentParser, 1081| | to body: @escaping (inout Options, String) throws -> Void 1082| 0| ) { 1083| 0| addBody { 1084| 0| guard let result = $1.subparser(parser) else { return } 1085| 0| try body(&$0, result) 1086| 0| } 1087| 0| } 1088| | 1089| | /// Appends a closure to bodies array. 1090| 0| private func addBody(_ body: @escaping BodyClosure) { 1091| 0| bodies.append(body) 1092| 0| } 1093| | 1094| | /// Fill the result into the options structure, 1095| | /// throwing if one of the user-provided binder function throws. 1096| 0| public func fill(parseResult result: ArgumentParser.Result, into options: inout Options) throws { 1097| 0| try bodies.forEach { try $0(&options, result) } 1098| 0| } 1099| | 1100| | /// Fill the result into the options structure. 1101| | @available(*, deprecated, renamed: "fill(parseResult:into:)") 1102| 0| public func fill(_ result: ArgumentParser.Result, into options: inout Options) { 1103| 0| try! fill(parseResult: result, into: &options) 1104| 0| } 1105| | 1106| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/ArgumentParserShellCompletion.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright 2016 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| |import Basic 13| | 14| |fileprivate let removeDefaultRegex = try! NSRegularExpression(pattern: "\\[default: .+?\\]", options: []) 15| | 16| |extension ArgumentParser { 17| | 18| | /// Generates part of a completion script for the given shell. 19| | /// 20| | /// These aren't complete scripts, as some setup code is required. See 21| | /// `Utilities/bash/completions` and `Utilities/zsh/_swift` for example 22| | /// usage. 23| 0| public func generateCompletionScript(for shell: Shell, on stream: OutputByteStream) { 24| 0| guard let commandName = commandName else { abort() } 25| 0| let name = "_\(commandName.replacingOccurrences(of: " ", with: "_"))" 26| 0| 27| 0| switch shell { 28| 0| case .bash: 29| 0| // Information about how to include this function in a completion script. 30| 0| stream <<< """ 31| 0| # Generates completions for \(commandName) 32| 0| # 33| 0| # Parameters 34| 0| # - the start position of this parser; set to 1 if unknown 35| 0| 36| 0| """ 37| 0| generateBashSwiftTool(name: name, on: stream) 38| 0| 39| 0| case .zsh: 40| 0| // Information about how to include this function in a completion script. 41| 0| stream <<< """ 42| 0| # Generates completions for \(commandName) 43| 0| # 44| 0| # In the final compdef file, set the following file header: 45| 0| # 46| 0| # #compdef \(name) 47| 0| # local context state state_descr line 48| 0| # typeset -A opt_args 49| 0| 50| 0| """ 51| 0| 52| 0| generateZshSwiftTool(name: name, on: stream) 53| 0| } 54| 0| stream.flush() 55| 0| } 56| | 57| | // MARK: - BASH 58| | 59| 0| fileprivate func generateBashSwiftTool(name: String, on stream: OutputByteStream) { 60| 0| stream <<< """ 61| 0| function \(name) 62| 0| { 63| 0| 64| 0| """ 65| 0| 66| 0| // Suggest positional arguments. Beware that this forces positional arguments 67| 0| // before options. For example [swift package pin ] expects a name as the 68| 0| // first argument. So no options (like --all) will be suggested. However after 69| 0| // the positional argument; [swift package pin MyPackage ] will list them 70| 0| // just fine. 71| 0| for (index, argument) in positionalArguments.enumerated() { 72| 0| stream <<< " if [[ $COMP_CWORD == $(($1+\(index))) ]]; then\n" 73| 0| generateBashCompletion(argument, on: stream) 74| 0| stream <<< " fi\n" 75| 0| } 76| 0| 77| 0| // Suggest subparsers in addition to other arguments. 78| 0| stream <<< " if [[ $COMP_CWORD == $1 ]]; then\n" 79| 0| var completions = [String]() 80| 0| for (subName, _) in subparsers { 81| 0| completions.append(subName) 82| 0| } 83| 0| for option in optionArguments { 84| 0| completions.append(option.name) 85| 0| if let shortName = option.shortName { 86| 0| completions.append(shortName) 87| 0| } 88| 0| } 89| 0| stream <<< """ 90| 0| COMPREPLY=( $(compgen -W "\(completions.joined(separator: " "))" -- $cur) ) 91| 0| return 92| 0| fi 93| 0| 94| 0| """ 95| 0| 96| 0| // Suggest completions based on previous word. 97| 0| generateBashCasePrev(on: stream) 98| 0| 99| 0| // Forward completions to subparsers. 100| 0| stream <<< " case ${COMP_WORDS[$1]} in\n" 101| 0| for (subName, _) in subparsers { 102| 0| stream <<< """ 103| 0| (\(subName)) 104| 0| \(name)_\(subName) $(($1+1)) 105| 0| return 106| 0| ;; 107| 0| 108| 0| """ 109| 0| } 110| 0| stream <<< " esac\n" 111| 0| 112| 0| // In all other cases (no positional / previous / subparser), suggest 113| 0| // this parsers completions. 114| 0| stream <<< """ 115| 0| COMPREPLY=( $(compgen -W "\(completions.joined(separator: " "))" -- $cur) ) 116| 0| } 117| 0| 118| 0| 119| 0| """ 120| 0| 121| 0| for (subName, subParser) in subparsers { 122| 0| subParser.generateBashSwiftTool(name: "\(name)_\(subName)", on: stream) 123| 0| } 124| 0| } 125| | 126| 0| fileprivate func generateBashCasePrev(on stream: OutputByteStream) { 127| 0| stream <<< " case $prev in\n" 128| 0| for argument in optionArguments { 129| 0| let flags = [argument.name] + (argument.shortName.map({ [$0] }) ?? []) 130| 0| stream <<< " (\(flags.joined(separator: "|")))\n" 131| 0| generateBashCompletion(argument, on: stream) 132| 0| stream <<< " ;;\n" 133| 0| } 134| 0| stream <<< " esac\n" 135| 0| } 136| | 137| 0| fileprivate func generateBashCompletion(_ argument: AnyArgument, on stream: OutputByteStream) { 138| 0| switch argument.completion { 139| 0| case .none: 140| 0| // return; no value to complete 141| 0| stream <<< " return\n" 142| 0| case .unspecified: 143| 0| break 144| 0| case .values(let values): 145| 0| let x = values.map({ $0.value }).joined(separator: " ") 146| 0| stream <<< """ 147| 0| COMPREPLY=( $(compgen -W "\(x)" -- $cur) ) 148| 0| return 149| 0| 150| 0| """ 151| 0| case .filename: 152| 0| stream <<< """ 153| 0| _filedir 154| 0| return 155| 0| 156| 0| """ 157| 0| case .function(let name): 158| 0| stream <<< """ 159| 0| \(name) 160| 0| return 161| 0| 162| 0| """ 163| 0| } 164| 0| } 165| | 166| | // MARK: - ZSH 167| | 168| 0| private func generateZshSwiftTool(name: String, on stream: OutputByteStream) { 169| 0| // Completions are provided by zsh's _arguments builtin. 170| 0| stream <<< """ 171| 0| \(name)() { 172| 0| arguments=( 173| 0| 174| 0| """ 175| 0| for argument in positionalArguments { 176| 0| stream <<< " \"" 177| 0| generateZshCompletion(argument, on: stream) 178| 0| stream <<< "\"\n" 179| 0| } 180| 0| for argument in optionArguments { 181| 0| generateZshArgument(argument, on: stream) 182| 0| } 183| 0| 184| 0| // Use a simple state-machine when dealing with sub parsers. 185| 0| if subparsers.count > 0 { 186| 0| stream <<< """ 187| 0| '(-): :->command' 188| 0| '(-)*:: :->arg' 189| 0| 190| 0| """ 191| 0| } 192| 0| 193| 0| stream <<< """ 194| 0| ) 195| 0| _arguments $arguments && return 196| 0| 197| 0| """ 198| 0| 199| 0| // Handle the state set by the state machine. 200| 0| if subparsers.count > 0 { 201| 0| stream <<< """ 202| 0| case $state in 203| 0| (command) 204| 0| local modes 205| 0| modes=( 206| 0| 207| 0| """ 208| 0| for (subName, subParser) in subparsers { 209| 0| stream <<< """ 210| 0| '\(subName):\(subParser.overview)' 211| 0| 212| 0| """ 213| 0| } 214| 0| stream <<< """ 215| 0| ) 216| 0| _describe "mode" modes 217| 0| ;; 218| 0| (arg) 219| 0| case ${words[1]} in 220| 0| 221| 0| """ 222| 0| for (subName, _) in subparsers { 223| 0| stream <<< """ 224| 0| (\(subName)) 225| 0| \(name)_\(subName) 226| 0| ;; 227| 0| 228| 0| """ 229| 0| } 230| 0| stream <<< """ 231| 0| esac 232| 0| ;; 233| 0| esac 234| 0| 235| 0| """ 236| 0| } 237| 0| stream <<< "}\n\n" 238| 0| 239| 0| for (subName, subParser) in subparsers { 240| 0| subParser.generateZshSwiftTool(name: "\(name)_\(subName)", on: stream) 241| 0| } 242| 0| } 243| | 244| | /// Generates an option argument for `_arguments`, complete with description and completion values. 245| 0| fileprivate func generateZshArgument(_ argument: AnyArgument, on stream: OutputByteStream) { 246| 0| stream <<< " \"" 247| 0| switch argument.shortName { 248| 0| case .none: stream <<< "\(argument.name)" 249| 0| case let shortName?: stream <<< "(\(argument.name) \(shortName))\"{\(argument.name),\(shortName)}\"" 250| 0| } 251| 0| 252| 0| let description = removeDefaultRegex 253| 0| .replace(in: argument.usage ?? "", with: "") 254| 0| .replacingOccurrences(of: "\"", with: "\\\"") 255| 0| .replacingOccurrences(of: "[", with: "\\[") 256| 0| .replacingOccurrences(of: "]", with: "\\]") 257| 0| stream <<< "[\(description)]" 258| 0| 259| 0| generateZshCompletion(argument, on: stream) 260| 0| stream <<< "\"\n" 261| 0| } 262| | 263| | /// Generates completion values, as part of an item for `_arguments`. 264| 0| fileprivate func generateZshCompletion(_ argument: AnyArgument, on stream: OutputByteStream) { 265| 0| let message = removeDefaultRegex 266| 0| .replace(in: argument.usage ?? " ", with: "") 267| 0| .replacingOccurrences(of: "\"", with: "\\\"") 268| 0| 269| 0| switch argument.completion { 270| 0| case .none: stream <<< ":\(message): " 271| 0| case .unspecified: break 272| 0| case .filename: stream <<< ":\(message):_files" 273| 0| case let .values(values): 274| 0| stream <<< ": :{_values ''" 275| 0| for (value, description) in values { 276| 0| stream <<< " '\(value)[\(description)]'" 277| 0| } 278| 0| stream <<< "}" 279| 0| case .function(let name): stream <<< ":\(message):\(name)" 280| 0| } 281| 0| } 282| |} 283| | 284| |fileprivate extension NSRegularExpression { 285| 0| func replace(`in` original: String, with replacement: String) -> String { 286| 0| return stringByReplacingMatches( 287| 0| in: original, 288| 0| options: [], 289| 0| range: NSRange(location: 0, length: original.count), 290| 0| withTemplate: replacement) 291| 0| } 292| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/BuildFlags.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |// FIXME: This belongs somewhere else, but we don't have a layer specifically 12| |// for BuildSupport style logic yet. 13| |// 14| |/// Build-tool independent flags. 15| |public struct BuildFlags { 16| | 17| | /// Flags to pass to the C compiler. 18| | public var cCompilerFlags: [String] 19| | 20| | /// Flags to pass to the C++ compiler. 21| | public var cxxCompilerFlags: [String] 22| | 23| | /// Flags to pass to the linker. 24| | public var linkerFlags: [String] 25| | 26| | /// Flags to pass to the Swift compiler. 27| | public var swiftCompilerFlags: [String] 28| | 29| | public init( 30| | xcc: [String]? = nil, 31| | xcxx: [String]? = nil, 32| | xswiftc: [String]? = nil, 33| | xlinker: [String]? = nil 34| 0| ) { 35| 0| cCompilerFlags = xcc ?? [] 36| 0| cxxCompilerFlags = xcxx ?? [] 37| 0| linkerFlags = xlinker ?? [] 38| 0| swiftCompilerFlags = xswiftc ?? [] 39| 0| } 40| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/CollectionExtensions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |extension Collection where Iterator.Element : Equatable { 12| | /// Split around a delimiting subsequence with maximum number of splits == 2 13| 0| func spm_split(around delimiter: [Iterator.Element]) -> ([Iterator.Element], [Iterator.Element]?) { 14| 0| 15| 0| let orig = Array(self) 16| 0| let end = orig.endIndex 17| 0| let delimCount = delimiter.count 18| 0| 19| 0| var index = orig.startIndex 20| 0| while index+delimCount <= end { 21| 0| let cur = Array(orig[index.." 47| 0| } 48| |} 49| | 50| |extension DiagnosticsEngine { 51| | 52| | /// Emit a diagnostic with an unknown location. 53| 0| public func emit(data: DiagnosticData) { 54| 0| emit(data: data, location: UnknownLocation.location) 55| 0| } 56| | 57| | /// Emit a Swift error. 58| | /// 59| | /// Errors will be converted into diagnostic data if possible. 60| | /// Otherwise, they will be emitted as AnyDiagnostic. 61| | public func emit( 62| | _ error: Swift.Error, 63| | location: DiagnosticLocation = UnknownLocation.location 64| 0| ) { 65| 0| if let diagnosticData = error as? DiagnosticData { 66| 0| emit(data: diagnosticData, location: location) 67| 0| } else if case let convertible as DiagnosticDataConvertible = error { 68| 0| emit(convertible, location: location) 69| 0| } else { 70| 0| emit(data: AnyDiagnostic(error), location: location) 71| 0| } 72| 0| } 73| | 74| | /// Emit a diagnostic data convertible instance. 75| | public func emit( 76| | _ convertible: DiagnosticDataConvertible, 77| | location: DiagnosticLocation = UnknownLocation.location 78| 0| ) { 79| 0| emit(data: convertible.diagnosticData, location: location) 80| 0| } 81| | 82| | /// Wrap a throwing closure, returning an optional value and 83| | /// emitting any thrown errors. 84| | /// 85| | /// - Parameters: 86| | /// - closure: Closure to wrap. 87| | /// - Returns: Returns the return value of the closure wrapped 88| | /// into an optional. If the closure throws, nil is returned. 89| | public func wrap( 90| 0| with constuctLocation: @autoclosure () -> (DiagnosticLocation) = UnknownLocation.location, 91| | _ closure: () throws -> T 92| 0| ) -> T? { 93| 0| do { 94| 0| return try closure() 95| 0| } catch { 96| 0| emit(error, location: constuctLocation()) 97| 0| return nil 98| 0| } 99| 0| } 100| | 101| | /// Wrap a throwing closure, returning a success boolean and 102| | /// emitting any thrown errors. 103| | /// 104| | /// - Parameters: 105| | /// - closure: Closure to wrap. 106| | /// - Returns: Returns true if the wrapped closure did not throw 107| | /// and false otherwise. 108| | @discardableResult 109| | public func wrap( 110| 0| with constuctLocation: @autoclosure () -> (DiagnosticLocation) = UnknownLocation.location, 111| | _ closure: () throws -> Void 112| 0| ) -> Bool { 113| 0| do { 114| 0| try closure() 115| 0| return true 116| 0| } catch { 117| 0| emit(error, location: constuctLocation()) 118| 0| return false 119| 0| } 120| 0| } 121| |} 122| | 123| |/// Namespace for representing diagnostic location of a package. 124| |public enum PackageLocation { 125| | 126| | /// Represents location of a locally available package. This could be root 127| | /// package, edited dependency or checked out dependency. 128| | public struct Local: DiagnosticLocation { 129| | 130| | /// The name of the package, if known. 131| | public let name: String? 132| | 133| | /// The path to the package. 134| | public let packagePath: AbsolutePath 135| | 136| 0| public init(name: String? = nil, packagePath: AbsolutePath) { 137| 0| self.name = name 138| 0| self.packagePath = packagePath 139| 0| } 140| | 141| 0| public var localizedDescription: String { 142| 0| let stream = BufferedOutputByteStream() 143| 0| if let name = name { 144| 0| stream <<< "'\(name)' " 145| 0| } 146| 0| stream <<< packagePath.pathString 147| 0| return stream.bytes.description 148| 0| } 149| | } 150| | 151| | /// Represents location a remote package with no checkout on disk. 152| | public struct Remote: DiagnosticLocation { 153| | 154| | /// The URL of the package. 155| | public let url: String 156| | 157| | /// The source control reference of the package. It could be version, branch, revision etc. 158| | public let reference: String 159| | 160| 0| public init(url: String, reference: String) { 161| 0| self.url = url 162| 0| self.reference = reference 163| 0| } 164| | 165| 0| public var localizedDescription: String { 166| 0| return url + " @ " + reference 167| 0| } 168| | } 169| |} 170| | 171| |/// An Swift error enum that can be used as a stub to early exit from a method. 172| |/// 173| |/// It is not expected for this enum to contain any payload or information about the 174| |/// error. The actual errors and warnings are supposed to be added using the Diagnostics 175| |/// engine. 176| |public enum Diagnostics: Swift.Error { 177| | case fatalError 178| |} 179| | 180| |/// Diagnostic for the process execution failure. 181| |public struct ProcessExecutionError: DiagnosticData { 182| | public static let id = DiagnosticID( 183| | type: ProcessExecutionError.self, 184| | name: "org.swift.diags.process.execution", 185| 0| description: { 186| 0| $0 <<< { "The '" + $0.result.arguments[0] + "' subprocess exited with" } 187| 0| $0 <<< .substitution({ 188| 0| let `self` = $0 as! ProcessExecutionError 189| 0| switch self.result.exitStatus { 190| 0| case .terminated(let code): 191| 0| return "termination code \(code)" 192| 0| case .signalled(let signal): 193| 0| return "signal \(signal)" 194| 0| } 195| 0| }) 196| 0| $0 <<< ".\n" 197| 0| 198| 0| $0 <<< "stdout: " <<< .substitution({ 199| 0| (try? ($0 as! ProcessExecutionError).result.utf8Output()) ?? "" 200| 0| }) <<< "\n" 201| 0| $0 <<< "stderr: " <<< .substitution({ 202| 0| (try? ($0 as! ProcessExecutionError).result.utf8stderrOutput()) ?? "" 203| 0| }) <<< "\n" 204| 0| } 205| | ) 206| | 207| | /// The process result. 208| | public let result: ProcessResult 209| | 210| 0| public init(_ result: ProcessResult) { 211| 0| self.result = result 212| 0| } 213| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/FSWatch.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Dispatch 13| |import Foundation 14| |import SPMLibc 15| | 16| |public protocol FSWatchDelegate { 17| | // FIXME: We need to provide richer information about the events. 18| | func pathsDidReceiveEvent(_ paths: [AbsolutePath]) 19| |} 20| | 21| |/// FSWatch is a cross-platform filesystem watching utility. 22| |public class FSWatch { 23| | 24| | /// Delegate for handling events from the underling watcher. 25| | fileprivate class _WatcherDelegate { 26| | 27| | /// Back reference to the fswatch instance. 28| | unowned let fsWatch: FSWatch 29| | 30| 0| init(_ fsWatch: FSWatch) { 31| 0| self.fsWatch = fsWatch 32| 0| } 33| | 34| 0| func pathsDidReceiveEvent(_ paths: [AbsolutePath]) { 35| 0| fsWatch.delegate.pathsDidReceiveEvent(paths) 36| 0| } 37| | } 38| | 39| | /// The paths being watched. 40| | public let paths: [AbsolutePath] 41| | 42| | /// The delegate for reporting received events. 43| | let delegate: FSWatchDelegate 44| | 45| | /// The underlying file watching utility. 46| | /// 47| | /// This is FSEventStream on macOS and inotify on linux. 48| | private var _watcher: _FileWatcher! 49| | 50| | /// The number of seconds the watcher should wait before passing the 51| | /// collected events to the clients. 52| | let latency: Double 53| | 54| | /// Create an instance with given paths. 55| | /// 56| | /// Paths can be files or directories. Directories are watched recursively. 57| 0| public init(paths: [AbsolutePath], latency: Double = 1, delegate: FSWatchDelegate) { 58| 0| precondition(!paths.isEmpty) 59| 0| self.paths = paths 60| 0| self.delegate = delegate 61| 0| self.latency = latency 62| 0| 63| 0| #if canImport(Glibc) 64| 0| var ipaths: [AbsolutePath: Inotify.WatchOptions] = [:] 65| 0| 66| 0| // FIXME: We need to recurse here. 67| 0| for path in paths { 68| 0| if localFileSystem.isDirectory(path) { 69| 0| ipaths[path] = .defaultDirectoryWatchOptions 70| 0| } else if localFileSystem.isFile(path) { 71| 0| ipaths[path] = .defaultFileWatchOptions 72| 0| // Watch files. 73| 0| } else { 74| 0| // FIXME: Report errors 75| 0| } 76| 0| } 77| 0| 78| 0| self._watcher = Inotify(paths: ipaths, latency: latency, delegate: _WatcherDelegate(self)) 79| 0| #elseif canImport(Darwin) 80| 0| self._watcher = FSEventStream(paths: paths, latency: latency, delegate: _WatcherDelegate(self)) 81| 0| #else 82| 0| fatalError("Unsupported platform") 83| 0| #endif 84| 0| } 85| | 86| | /// Start watching the filesystem for events. 87| | /// 88| | /// This method should be called only once. 89| 0| public func start() throws { 90| 0| // FIXME: Write precondition to ensure its called only once. 91| 0| try _watcher.start() 92| 0| } 93| | 94| | /// Stop watching the filesystem. 95| | /// 96| | /// This method should be called after start() and the object should be thrown away. 97| 0| public func stop() { 98| 0| // FIXME: Write precondition to ensure its called after start() and once only. 99| 0| _watcher.stop() 100| 0| } 101| |} 102| | 103| |/// Protocol to which the different file watcher implementations should conform. 104| |private protocol _FileWatcher { 105| | func start() throws 106| | func stop() 107| |} 108| | 109| |#if canImport(Glibc) 110| |extension FSWatch._WatcherDelegate: InotifyDelegate {} 111| |extension Inotify: _FileWatcher{} 112| |#else 113| |extension FSWatch._WatcherDelegate: FSEventStreamDelegate {} 114| |extension FSEventStream: _FileWatcher{} 115| |#endif 116| | 117| |// MARK:- inotify 118| | 119| |#if canImport(Glibc) 120| | 121| |/// The delegate for receiving inotify events. 122| |public protocol InotifyDelegate { 123| | func pathsDidReceiveEvent(_ paths: [AbsolutePath]) 124| |} 125| | 126| |/// Bindings for inotify C APIs. 127| |public final class Inotify { 128| | 129| | /// The errors encountered during inotify operations. 130| | public enum Error: Swift.Error { 131| | case invalidFD 132| | case failedToWatch(AbsolutePath) 133| | } 134| | 135| | /// The available options for a particular path. 136| | public struct WatchOptions: OptionSet { 137| | public let rawValue: Int32 138| | 139| | public init(rawValue: Int32) { 140| | self.rawValue = rawValue 141| | } 142| | 143| | // File/directory created in watched directory (e.g., open(2) 144| | // O_CREAT, mkdir(2), link(2), symlink(2), bind(2) on a UNIX 145| | // domain socket). 146| | public static let create = WatchOptions(rawValue: IN_CREATE) 147| | 148| | // File/directory deleted from watched directory. 149| | public static let delete = WatchOptions(rawValue: IN_DELETE) 150| | 151| | // Watched file/directory was itself deleted. (This event 152| | // also occurs if an object is moved to another filesystem, 153| | // since mv(1) in effect copies the file to the other 154| | // filesystem and then deletes it from the original filesys‐ 155| | // tem.) In addition, an IN_IGNORED event will subsequently 156| | // be generated for the watch descriptor. 157| | public static let deleteSelf = WatchOptions(rawValue: IN_DELETE_SELF) 158| | 159| | public static let move = WatchOptions(rawValue: IN_MOVE) 160| | 161| | /// Watched file/directory was itself moved. 162| | public static let moveSelf = WatchOptions(rawValue: IN_MOVE_SELF) 163| | 164| | /// File was modified (e.g., write(2), truncate(2)). 165| | public static let modify = WatchOptions(rawValue: IN_MODIFY) 166| | 167| | // File or directory was opened. 168| | public static let open = WatchOptions(rawValue: IN_OPEN) 169| | 170| | // Metadata changed—for example, permissions (e.g., 171| | // chmod(2)), timestamps (e.g., utimensat(2)), extended 172| | // attributes (setxattr(2)), link count (since Linux 2.6.25; 173| | // e.g., for the target of link(2) and for unlink(2)), and 174| | // user/group ID (e.g., chown(2)). 175| | public static let attrib = WatchOptions(rawValue: IN_ATTRIB) 176| | 177| | // File opened for writing was closed. 178| | public static let closeWrite = WatchOptions(rawValue: IN_CLOSE_WRITE) 179| | 180| | // File or directory not opened for writing was closed. 181| | public static let closeNoWrite = WatchOptions(rawValue: IN_CLOSE_NOWRITE) 182| | 183| | // File was accessed (e.g., read(2), execve(2)). 184| | public static let access = WatchOptions(rawValue: IN_ACCESS) 185| | 186| | /// The list of default options that can be used for watching files. 187| | public static let defaultFileWatchOptions: WatchOptions = [.deleteSelf, .moveSelf, .modify] 188| | 189| | /// The list of default options that can be used for watching directories. 190| | public static let defaultDirectoryWatchOptions: WatchOptions = [.create, .delete, .deleteSelf, .move, .moveSelf] 191| | 192| | /// List of all available events. 193| | public static let all: [WatchOptions] = [ 194| | .create, 195| | .delete, 196| | .deleteSelf, 197| | .move, 198| | .moveSelf, 199| | .modify, 200| | .open, 201| | .attrib, 202| | .closeWrite, 203| | .closeNoWrite, 204| | .access, 205| | ] 206| | } 207| | 208| | // Sizeof inotify_event + max len of filepath + 1 (for null char). 209| | private static let eventSize = MemoryLayout.size + Int(NAME_MAX) + 1 210| | 211| | /// The paths being watched. 212| | public let paths: [AbsolutePath: WatchOptions] 213| | 214| | /// The delegate. 215| | private let delegate: InotifyDelegate? 216| | 217| | /// The settle period (in seconds). 218| | public let settle: Double 219| | 220| | /// Internal properties. 221| | private var fd: Int32? 222| | 223| | /// The list of watched directories/files. 224| | private var wds: [Int32: AbsolutePath] = [:] 225| | 226| | /// The queue on which we read the events. 227| | private let readQueue = DispatchQueue(label: "org.swift.swiftpm.\(Inotify.self).read)") 228| | 229| | /// Callback queue for the delegate. 230| | private let callbacksQueue = DispatchQueue(label: "org.swift.swiftpm.\(Inotify.self).callback)") 231| | 232| | /// Condition for handling event reporting. 233| | private var reportCondition = Condition() 234| | 235| | // Should be read or written to using the report condition only. 236| | private var collectedEvents: [AbsolutePath] = [] 237| | 238| | // Should be read or written to using the report condition only. 239| | private var lastEventTime: Date? = nil 240| | 241| | // Should be read or written to using the report condition only. 242| | private var cancelled = false 243| | 244| | /// Pipe for waking up the read loop. 245| | private var cancellationPipe: [Int32] = [0, 0] 246| | 247| | /// Create a inotify instance. 248| | /// 249| | /// The paths are not watched recursively. 250| | public init(paths: [AbsolutePath: WatchOptions], latency: Double, delegate: InotifyDelegate? = nil) { 251| | self.paths = paths 252| | self.delegate = delegate 253| | self.settle = latency 254| | } 255| | 256| | /// Start the watch operation. 257| | public func start() throws { 258| | 259| | // All paths need to exist. 260| | for (path, _) in paths { 261| | guard localFileSystem.exists(path) else { 262| | throw Error.failedToWatch(path) 263| | } 264| | } 265| | 266| | // Create the file descriptor. 267| | let fd = inotify_init1(Int32(IN_NONBLOCK)) 268| | 269| | guard fd != -1 else { 270| | throw Error.invalidFD 271| | } 272| | self.fd = fd 273| | 274| | /// Add watch for each path. 275| | for (path, options) in paths { 276| | 277| | let wd = inotify_add_watch(fd, path.description, UInt32(options.rawValue)) 278| | guard wd != -1 else { 279| | throw Error.failedToWatch(path) 280| | } 281| | 282| | self.wds[wd] = path 283| | } 284| | 285| | // Start the report thread. 286| | startReportThread() 287| | 288| | readQueue.async { 289| | self.startRead() 290| | } 291| | } 292| | 293| | /// End the watch operation. 294| | public func stop() { 295| | // FIXME: Write precondition to ensure this is called only once. 296| | guard let fd = fd else { 297| | assertionFailure("end called without a fd") 298| | return 299| | } 300| | 301| | // Shutdown the report thread. 302| | reportCondition.whileLocked { 303| | cancelled = true 304| | reportCondition.signal() 305| | } 306| | 307| | // Wakeup the read loop by writing on the cancellation pipe. 308| | let writtenData = write(cancellationPipe[1], "", 1) 309| | assert(writtenData == 1) 310| | 311| | // FIXME: We need to remove the watches. 312| | close(fd) 313| | } 314| | 315| | private func startRead() { 316| | guard let fd = fd else { 317| | fatalError("unexpected call to startRead without fd") 318| | } 319| | 320| | // Create a pipe that we can use to get notified when we're cancelled. 321| | let pipeRv = pipe(&cancellationPipe) 322| | // FIXME: We don't see pipe2 for some reason. 323| | let f = fcntl(cancellationPipe[0], F_SETFL, O_NONBLOCK) 324| | assert(f != -1) 325| | assert(pipeRv == 0) 326| | 327| | while true { 328| | // The read fd set. Contains the inotify and cancellation fd. 329| | var rfds = fd_set() 330| | FD_ZERO(&rfds) 331| | 332| | FD_SET(fd, &rfds) 333| | FD_SET(cancellationPipe[0], &rfds) 334| | 335| | let nfds = [fd, cancellationPipe[0]].reduce(0, max) + 1 336| | // num fds, read fds, write fds, except fds, timeout 337| | let selectRet = select(nfds, &rfds, nil, nil, nil) 338| | // FIXME: Check for int signal. 339| | assert(selectRet != -1) 340| | 341| | // Return if we're cancelled. 342| | if FD_ISSET(cancellationPipe[0], &rfds) { 343| | return 344| | } 345| | assert(FD_ISSET(fd, &rfds)) 346| | 347| | let buf = UnsafeMutablePointer.allocate(capacity: Inotify.eventSize) 348| | // FIXME: We need to free the buffer. 349| | 350| | let readLength = read(fd, buf, Inotify.eventSize) 351| | // FIXME: Check for int signal. 352| | 353| | // Consume events. 354| | var idx = 0 355| | while idx < readLength { 356| | let event = withUnsafePointer(to: &buf[idx]) { 357| | $0.withMemoryRebound(to: inotify_event.self, capacity: 1) { 358| | $0.pointee 359| | } 360| | } 361| | 362| | // Get the associated with the event. 363| | var path = wds[event.wd]! 364| | 365| | // FIXME: We need extract information from the event mask and 366| | // create a data structure. 367| | // FIXME: Do we need to detect and remove watch for directories 368| | // that are deleted? 369| | 370| | // Get the relative base name from the event if present. 371| | if event.len > 0 { 372| | // Get the basename of the file that had the event. 373| | let basename = String(cString: buf + idx + MemoryLayout.size) 374| | 375| | // Construct the full path. 376| | // FIXME: We should report this path separately. 377| | path = path.appending(component: basename) 378| | } 379| | 380| | // Signal the reporter. 381| | reportCondition.whileLocked { 382| | lastEventTime = Date() 383| | collectedEvents.append(path) 384| | reportCondition.signal() 385| | } 386| | 387| | idx += MemoryLayout.size + Int(event.len) 388| | } 389| | } 390| | } 391| | 392| | /// Spawns a thread that collects events and reports them after the settle period. 393| | private func startReportThread() { 394| | let thread = Basic.Thread { 395| | var endLoop = false 396| | while !endLoop { 397| | 398| | // Block until we timeout or get signalled. 399| | self.reportCondition.whileLocked { 400| | var performReport = false 401| | 402| | // Block until timeout expires or wait forever until we get some event. 403| | if let lastEventTime = self.lastEventTime { 404| | let timeout = lastEventTime + Double(self.settle) 405| | let timeLimitReached = !self.reportCondition.wait(until: timeout) 406| | 407| | if timeLimitReached { 408| | self.lastEventTime = nil 409| | performReport = true 410| | } 411| | } else { 412| | self.reportCondition.wait() 413| | } 414| | 415| | // If we're cancelled, just return. 416| | if self.cancelled { 417| | endLoop = true 418| | return 419| | } 420| | 421| | // Report the events if we're asked to. 422| | if performReport && !self.collectedEvents.isEmpty { 423| | let events = self.collectedEvents 424| | self.collectedEvents = [] 425| | self.callbacksQueue.async { 426| | self.report(events) 427| | } 428| | } 429| | } 430| | } 431| | } 432| | 433| | thread.start() 434| | } 435| | 436| | private func report(_ paths: [AbsolutePath]) { 437| | delegate?.pathsDidReceiveEvent(paths) 438| | } 439| |} 440| | 441| |// FIXME: Swift should provide shims for FD_ macros 442| | 443| |private func FD_ZERO(_ set: inout fd_set) { 444| | set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 445| |} 446| | 447| |private func FD_SET(_ fd: Int32, _ set: inout fd_set) { 448| | let intOffset = Int(fd / 16) 449| | let bitOffset = Int(fd % 16) 450| | let mask = 1 << bitOffset 451| | switch intOffset { 452| | case 0: set.__fds_bits.0 = set.__fds_bits.0 | mask 453| | case 1: set.__fds_bits.1 = set.__fds_bits.1 | mask 454| | case 2: set.__fds_bits.2 = set.__fds_bits.2 | mask 455| | case 3: set.__fds_bits.3 = set.__fds_bits.3 | mask 456| | case 4: set.__fds_bits.4 = set.__fds_bits.4 | mask 457| | case 5: set.__fds_bits.5 = set.__fds_bits.5 | mask 458| | case 6: set.__fds_bits.6 = set.__fds_bits.6 | mask 459| | case 7: set.__fds_bits.7 = set.__fds_bits.7 | mask 460| | case 8: set.__fds_bits.8 = set.__fds_bits.8 | mask 461| | case 9: set.__fds_bits.9 = set.__fds_bits.9 | mask 462| | case 10: set.__fds_bits.10 = set.__fds_bits.10 | mask 463| | case 11: set.__fds_bits.11 = set.__fds_bits.11 | mask 464| | case 12: set.__fds_bits.12 = set.__fds_bits.12 | mask 465| | case 13: set.__fds_bits.13 = set.__fds_bits.13 | mask 466| | case 14: set.__fds_bits.14 = set.__fds_bits.14 | mask 467| | case 15: set.__fds_bits.15 = set.__fds_bits.15 | mask 468| | default: break 469| | } 470| |} 471| | 472| |private func FD_ISSET(_ fd: Int32, _ set: inout fd_set) -> Bool { 473| | let intOffset = Int(fd / 32) 474| | let bitOffset = Int(fd % 32) 475| | let mask = 1 << bitOffset 476| | switch intOffset { 477| | case 0: return set.__fds_bits.0 & mask != 0 478| | case 1: return set.__fds_bits.1 & mask != 0 479| | case 2: return set.__fds_bits.2 & mask != 0 480| | case 3: return set.__fds_bits.3 & mask != 0 481| | case 4: return set.__fds_bits.4 & mask != 0 482| | case 5: return set.__fds_bits.5 & mask != 0 483| | case 6: return set.__fds_bits.6 & mask != 0 484| | case 7: return set.__fds_bits.7 & mask != 0 485| | case 8: return set.__fds_bits.8 & mask != 0 486| | case 9: return set.__fds_bits.9 & mask != 0 487| | case 10: return set.__fds_bits.10 & mask != 0 488| | case 11: return set.__fds_bits.11 & mask != 0 489| | case 12: return set.__fds_bits.12 & mask != 0 490| | case 13: return set.__fds_bits.13 & mask != 0 491| | case 14: return set.__fds_bits.14 & mask != 0 492| | case 15: return set.__fds_bits.15 & mask != 0 493| | default: return false 494| | } 495| |} 496| | 497| |#endif 498| | 499| |// MARK:- FSEventStream 500| | 501| |#if canImport(Darwin) 502| | 503| |private func callback( 504| | streamRef: ConstFSEventStreamRef, 505| | clientCallBackInfo: UnsafeMutableRawPointer?, 506| | numEvents: Int, 507| | eventPaths: UnsafeMutableRawPointer, 508| | eventFlags: UnsafePointer, 509| | eventIds: UnsafePointer 510| 0|) { 511| 0| let eventStream = unsafeBitCast(clientCallBackInfo, to: FSEventStream.self) 512| 0| 513| 0| // We expect the paths to be reported in an NSArray because we requested CFTypes. 514| 0| let eventPaths = unsafeBitCast(eventPaths, to: NSArray.self) as? [String] ?? [] 515| 0| 516| 0| // Compute the set of paths that were changed. 517| 0| let paths = eventPaths.map({ AbsolutePath($0) }) 518| 0| 519| 0| eventStream.callbacksQueue.async { 520| 0| eventStream.delegate.pathsDidReceiveEvent(paths) 521| 0| } 522| 0|} 523| | 524| |public protocol FSEventStreamDelegate { 525| | func pathsDidReceiveEvent(_ paths: [AbsolutePath]) 526| |} 527| | 528| |/// Wrapper for Darwin's FSEventStream API. 529| |public final class FSEventStream { 530| | 531| | /// The errors encountered during fs event watching. 532| | public enum Error: Swift.Error { 533| | case unknownError 534| | } 535| | 536| | /// Reference to the underlying event stream. 537| | /// 538| | /// This is var and implicitly unwrapped optional because 539| | /// we need to capture self for the context. 540| | private var stream: FSEventStreamRef! 541| | 542| | /// Reference to the handler that should be called. 543| | let delegate: FSEventStreamDelegate 544| | 545| | /// The thread on which the stream is running. 546| | private var thread: Basic.Thread? 547| | 548| | /// The run loop attached to the stream. 549| | private var runLoop: CFRunLoop? 550| | 551| | /// Callback queue for the delegate. 552| | fileprivate let callbacksQueue = DispatchQueue(label: "org.swift.swiftpm.\(FSEventStream.self).callback)") 553| | 554| | public init( 555| | paths: [AbsolutePath], 556| | latency: Double, 557| | delegate: FSEventStreamDelegate 558| 0| ) { 559| 0| self.delegate = delegate 560| 0| 561| 0| // Create the context that needs to be passed to the callback. 562| 0| var callbackContext = FSEventStreamContext() 563| 0| callbackContext.info = unsafeBitCast(self, to: UnsafeMutableRawPointer.self) 564| 0| 565| 0| // Create the stream. 566| 0| self.stream = FSEventStreamCreate(nil, 567| 0| callback, 568| 0| &callbackContext, 569| 0| paths.map({ $0.pathString }) as CFArray, 570| 0| FSEventStreamEventId(kFSEventStreamEventIdSinceNow), 571| 0| latency, 572| 0| // FIXME: This needs to be customizable. 573| 0| FSEventStreamCreateFlags(kFSEventStreamCreateFlagUseCFTypes) 574| 0| ) 575| 0| } 576| | 577| | // Start the runloop. 578| 0| public func start() throws { 579| 0| let thread = Thread { [weak self] in 580| 0| guard let `self` = self else { return } 581| 0| self.runLoop = CFRunLoopGetCurrent() 582| 0| // Schedule the run loop. 583| 0| FSEventStreamScheduleWithRunLoop( 584| 0| self.stream, 585| 0| CFRunLoopGetCurrent(), 586| 0| CFRunLoopMode.defaultMode.rawValue 587| 0| ) 588| 0| 589| 0| // Start the stream. 590| 0| FSEventStreamScheduleWithRunLoop(self.stream, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue) 591| 0| FSEventStreamStart(self.stream) 592| 0| CFRunLoopRun() 593| 0| 594| 0| // Perform cleanup. 595| 0| FSEventStreamStop(self.stream) 596| 0| FSEventStreamUnscheduleFromRunLoop(self.stream, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue) 597| 0| FSEventStreamInvalidate(self.stream) 598| 0| FSEventStreamRelease(self.stream) 599| 0| } 600| 0| thread.start() 601| 0| self.thread = thread 602| 0| } 603| | 604| | /// Stop watching the events. 605| 0| public func stop() { 606| 0| CFRunLoopStop(runLoop!) 607| 0| } 608| |} 609| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Git.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import class Foundation.ProcessInfo 12| |import Basic 13| | 14| |extension Version { 15| | /// Try a version from a git tag. 16| | /// 17| | /// - Parameter tag: A version string possibly prepended with "v". 18| 0| init?(tag: String) { 19| 0| if tag.first == "v" { 20| 0| self.init(string: String(tag.dropFirst())) 21| 0| } else { 22| 0| self.init(string: tag) 23| 0| } 24| 0| } 25| |} 26| | 27| |public class Git { 28| | /// Compute the version -> tags mapping from a list of input `tags`. 29| 0| public static func convertTagsToVersionMap(_ tags: [String]) -> [Version: [String]] { 30| 0| // First, check if we need to restrict the tag set to version-specific tags. 31| 0| var knownVersions: [Version: [String]] = [:] 32| 0| var versionSpecificKnownVersions: [Version: [String]] = [:] 33| 0| 34| 0| for tag in tags { 35| 0| for versionSpecificKey in Versioning.currentVersionSpecificKeys { 36| 0| if tag.hasSuffix(versionSpecificKey) { 37| 0| let trimmedTag = String(tag.dropLast(versionSpecificKey.count)) 38| 0| if let version = Version(tag: trimmedTag) { 39| 0| versionSpecificKnownVersions[version, default: []].append(tag) 40| 0| } 41| 0| break 42| 0| } 43| 0| } 44| 0| 45| 0| if let version = Version(tag: tag) { 46| 0| knownVersions[version, default: []].append(tag) 47| 0| } 48| 0| } 49| 0| // Check if any version specific tags were found. 50| 0| // If true, then return the version specific tags, 51| 0| // or else return the version independent tags. 52| 0| if !versionSpecificKnownVersions.isEmpty { 53| 0| return versionSpecificKnownVersions 54| 0| } else { 55| 0| return knownVersions 56| 0| } 57| 0| } 58| | 59| | /// A shell command to run for Git. Can be either a name or a path. 60| | public static var tool: String = "git" 61| | 62| | /// Returns true if the git reference name is well formed. 63| 0| public static func checkRefFormat(ref: String) -> Bool { 64| 0| do { 65| 0| let result = try Process.popen(args: tool, "check-ref-format", "--allow-onelevel", ref) 66| 0| return result.exitStatus == .terminated(code: 0) 67| 0| } catch { 68| 0| return false 69| 0| } 70| 0| } 71| | 72| | /// Returns the environment variables for launching the git subprocess. 73| | /// 74| | /// This contains the current environment with custom overrides for using 75| | /// git from swift build. 76| 0| public static var environment: [String: String] { 77| 0| var env = ProcessInfo.processInfo.environment 78| 0| 79| 0| // These variables are inserted into the environment when shelling out 80| 0| // to git if not already present. 81| 0| let underrideVariables = [ 82| 0| // Disable terminal prompts in git. This will make git error out and return 83| 0| // when it needs a user/pass etc instead of hanging the terminal (SR-3981). 84| 0| "GIT_TERMINAL_PROMPT": "0", 85| 0| 86| 0| // The above is env variable is not enough. However, ssh_config's batch 87| 0| // mode is made for this purpose. see: https://linux.die.net/man/5/ssh_config 88| 0| "GIT_SSH_COMMAND": "ssh -oBatchMode=yes", 89| 0| ] 90| 0| 91| 0| for (key, value) in underrideVariables { 92| 0| // Skip this key is already present in the env. 93| 0| if env.keys.contains(key) { continue } 94| 0| 95| 0| env[key] = value 96| 0| } 97| 0| 98| 0| return env 99| 0| } 100| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/InterruptHandler.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright 2016 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| |import enum POSIX.SystemError 13| |import Basic 14| | 15| |/// Interrupt signal handling global variables 16| |private var wasInterrupted = false 17| |private var wasInterruptedLock = Lock() 18| |private var signalWatchingPipe: [Int32] = [0, 0] 19| |private var oldAction = sigaction() 20| | 21| |/// This class can be used by command line tools to install a handler which 22| |/// should be called when a interrupt signal is delivered to the process. 23| |public final class InterruptHandler { 24| | 25| | /// The thread which waits to be notified when a signal is received. 26| | let thread: Thread 27| | 28| | /// Start watching for interrupt signal and call the handler whenever the signal is received. 29| 0| public init(_ handler: @escaping () -> Void) throws { 30| 0| // Create a signal handler. 31| 0| let signalHandler: @convention(c)(Int32) -> Void = { _ in 32| 0| // Turn on the interrupt bool. 33| 0| wasInterruptedLock.withLock { 34| 0| wasInterrupted = true 35| 0| } 36| 0| // Write on pipe to notify the watching thread. 37| 0| var byte: UInt8 = 0 38| 0| write(signalWatchingPipe[1], &byte, 1) 39| 0| } 40| 0| var action = sigaction() 41| 0| #if os(macOS) 42| 0| action.__sigaction_u.__sa_handler = signalHandler 43| 0| #else 44| 0| action.__sigaction_handler = unsafeBitCast( 45| 0| signalHandler, 46| 0| to: sigaction.__Unnamed_union___sigaction_handler.self) 47| 0| #endif 48| 0| // Install the new handler. 49| 0| sigaction(SIGINT, &action, &oldAction) 50| 0| // Create pipe. 51| 0| let rv = SPMLibc.pipe(&signalWatchingPipe) 52| 0| guard rv == 0 else { 53| 0| throw SystemError.pipe(rv) 54| 0| } 55| 0| 56| 0| // This thread waits to be notified via pipe. If something is read from pipe, check the interrupt bool 57| 0| // and send termination signal to all spawned processes in the process group. 58| 0| thread = Thread { 59| 0| while true { 60| 0| var buf: Int8 = 0 61| 0| let n = read(signalWatchingPipe[0], &buf, 1) 62| 0| // Pipe closed, nothing to do. 63| 0| if n == 0 { break } 64| 0| // Read the value of wasInterrupted and set it to false. 65| 0| let wasInt = wasInterruptedLock.withLock { () -> Bool in 66| 0| let oldValue = wasInterrupted 67| 0| wasInterrupted = false 68| 0| return oldValue 69| 0| } 70| 0| // Terminate all processes if was interrupted. 71| 0| if wasInt { 72| 0| handler() 73| 0| } 74| 0| } 75| 0| close(signalWatchingPipe[0]) 76| 0| } 77| 0| thread.start() 78| 0| } 79| | 80| 0| deinit { 81| 0| // Restore the old action and close the write end of pipe. 82| 0| sigaction(SIGINT, &oldAction, nil) 83| 0| close(signalWatchingPipe[1]) 84| 0| thread.join() 85| 0| } 86| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/PkgConfig.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Foundation 13| |import func POSIX.getenv 14| | 15| |public enum PkgConfigError: Swift.Error, CustomStringConvertible { 16| | case couldNotFindConfigFile 17| | case parsingError(String) 18| | case nonWhitelistedFlags(String) 19| | 20| 0| public var description: String { 21| 0| switch self { 22| 0| case .couldNotFindConfigFile: 23| 0| return "couldn't find pc file" 24| 0| case .parsingError(let error): 25| 0| return "parsing error(s): \(error)" 26| 0| case .nonWhitelistedFlags(let flags): 27| 0| return "non whitelisted flag(s): \(flags)" 28| 0| } 29| 0| } 30| |} 31| | 32| |public struct PkgConfigExecutionDiagnostic: DiagnosticData { 33| | public static let id = DiagnosticID( 34| | type: PkgConfigExecutionDiagnostic.self, 35| | name: "org.swift.diags.pkg-config-execution", 36| | defaultBehavior: .warning, 37| | description: { 38| | $0 <<< "failed to retrieve search paths with pkg-config; maybe pkg-config is not installed" 39| | } 40| | ) 41| |} 42| | 43| |struct PCFileFinder { 44| | /// DiagnosticsEngine to emit warnings 45| | let diagnostics: DiagnosticsEngine 46| | 47| | /// Cached results of locations `pkg-config` will search for `.pc` files 48| | private(set) static var pkgConfigPaths: [AbsolutePath]? // FIXME: @testable(internal) 49| | 50| | /// The built-in search path list. 51| | /// 52| | /// By default, this is combined with the search paths inferred from 53| | /// `pkg-config` itself. 54| | static let searchPaths = [ 55| | AbsolutePath("/usr/local/lib/pkgconfig"), 56| | AbsolutePath("/usr/local/share/pkgconfig"), 57| | AbsolutePath("/usr/lib/pkgconfig"), 58| | AbsolutePath("/usr/share/pkgconfig"), 59| | ] 60| | 61| | /// Get search paths from `pkg-config` itself to locate `.pc` files. 62| | /// 63| | /// This is needed because on Linux machines, the search paths can be different 64| | /// from the standard locations that we are currently searching. 65| 0| public init (diagnostics: DiagnosticsEngine, brewPrefix: AbsolutePath?) { 66| 0| self.diagnostics = diagnostics 67| 0| if PCFileFinder.pkgConfigPaths == nil { 68| 0| do { 69| 0| let pkgConfigPath: String 70| 0| if let brewPrefix = brewPrefix { 71| 0| pkgConfigPath = brewPrefix.appending(components: "bin", "pkg-config").pathString 72| 0| } else { 73| 0| pkgConfigPath = "pkg-config" 74| 0| } 75| 0| let searchPaths = try Process.checkNonZeroExit( 76| 0| args: pkgConfigPath, "--variable", "pc_path", "pkg-config").spm_chomp() 77| 0| PCFileFinder.pkgConfigPaths = searchPaths.split(separator: ":").map({ AbsolutePath(String($0)) }) 78| 0| } catch { 79| 0| diagnostics.emit(data: PkgConfigExecutionDiagnostic()) 80| 0| PCFileFinder.pkgConfigPaths = [] 81| 0| } 82| 0| } 83| 0| } 84| | 85| | public func locatePCFile( 86| | name: String, 87| | customSearchPaths: [AbsolutePath], 88| | fileSystem: FileSystem 89| 0| ) throws -> AbsolutePath { 90| 0| // FIXME: We should consider building a registry for all items in the 91| 0| // search paths, which is likely to be substantially more efficient if 92| 0| // we end up searching for a reasonably sized number of packages. 93| 0| for path in OrderedSet(customSearchPaths + PCFileFinder.pkgConfigPaths! + PCFileFinder.searchPaths) { 94| 0| let pcFile = path.appending(component: name + ".pc") 95| 0| if fileSystem.isFile(pcFile) { 96| 0| return pcFile 97| 0| } 98| 0| } 99| 0| throw PkgConfigError.couldNotFindConfigFile 100| 0| } 101| |} 102| | 103| |/// Information on an individual `pkg-config` supported package. 104| |public struct PkgConfig { 105| | /// The name of the package. 106| | public let name: String 107| | 108| | /// The path to the definition file. 109| | public let pcFile: AbsolutePath 110| | 111| | /// The list of C compiler flags in the definition. 112| | public let cFlags: [String] 113| | 114| | /// The list of libraries to link. 115| | public let libs: [String] 116| | 117| | /// DiagnosticsEngine to emit diagnostics 118| | let diagnostics: DiagnosticsEngine 119| | 120| | /// Helper to query `pkg-config` for library locations 121| | private let pkgFileFinder: PCFileFinder 122| | 123| | /// Load the information for the named package. 124| | /// 125| | /// It will search `fileSystem` for the pkg config file in the following order: 126| | /// * Paths defined in `PKG_CONFIG_PATH` environment variable 127| | /// * Paths defined in `additionalSearchPaths` argument 128| | /// * Built-in search paths (see `PCFileFinder.searchPaths`) 129| | /// 130| | /// - parameter name: Name of the pkg config file (without file extension). 131| | /// - parameter additionalSearchPaths: Additional paths to search for pkg config file. 132| | /// - parameter fileSystem: The file system to use, defaults to local file system. 133| | /// 134| | /// - throws: PkgConfigError 135| | public init( 136| | name: String, 137| | additionalSearchPaths: [AbsolutePath] = [], 138| | diagnostics: DiagnosticsEngine, 139| | fileSystem: FileSystem = localFileSystem, 140| | brewPrefix: AbsolutePath? 141| 0| ) throws { 142| 0| self.name = name 143| 0| self.pkgFileFinder = PCFileFinder(diagnostics: diagnostics, brewPrefix: brewPrefix) 144| 0| self.pcFile = try pkgFileFinder.locatePCFile( 145| 0| name: name, 146| 0| customSearchPaths: PkgConfig.envSearchPaths + additionalSearchPaths, 147| 0| fileSystem: fileSystem) 148| 0| 149| 0| self.diagnostics = diagnostics 150| 0| var parser = PkgConfigParser(pcFile: pcFile, fileSystem: fileSystem) 151| 0| try parser.parse() 152| 0| 153| 0| var cFlags = parser.cFlags 154| 0| var libs = parser.libs 155| 0| 156| 0| // If parser found dependencies in pc file, get their flags too. 157| 0| if !parser.dependencies.isEmpty { 158| 0| for dep in parser.dependencies { 159| 0| // FIXME: This is wasteful, we should be caching the PkgConfig result. 160| 0| let pkg = try PkgConfig( 161| 0| name: dep, 162| 0| additionalSearchPaths: additionalSearchPaths, 163| 0| diagnostics: self.diagnostics, 164| 0| brewPrefix: brewPrefix 165| 0| ) 166| 0| cFlags += pkg.cFlags 167| 0| libs += pkg.libs 168| 0| } 169| 0| } 170| 0| 171| 0| self.cFlags = cFlags 172| 0| self.libs = libs 173| 0| } 174| | 175| 0| private static var envSearchPaths: [AbsolutePath] { 176| 0| if let configPath = POSIX.getenv("PKG_CONFIG_PATH") { 177| 0| return configPath.split(separator: ":").map({ AbsolutePath(String($0)) }) 178| 0| } 179| 0| return [] 180| 0| } 181| |} 182| | 183| |// FIXME: This is only internal so it can be unit tested. 184| |// 185| |/// Parser for the `pkg-config` `.pc` file format. 186| |/// 187| |/// See: https://www.freedesktop.org/wiki/Software/pkg-config/ 188| |struct PkgConfigParser { 189| | let pcFile: AbsolutePath 190| | private let fileSystem: FileSystem 191| | private(set) var variables = [String: String]() 192| | var dependencies = [String]() 193| | var cFlags = [String]() 194| | var libs = [String]() 195| | 196| 0| init(pcFile: AbsolutePath, fileSystem: FileSystem) { 197| 0| precondition(fileSystem.isFile(pcFile)) 198| 0| self.pcFile = pcFile 199| 0| self.fileSystem = fileSystem 200| 0| } 201| | 202| 0| mutating func parse() throws { 203| 0| func removeComment(line: String) -> String { 204| 0| if let commentIndex = line.index(of: "#") { 205| 0| return String(line[line.startIndex.. [String] { 258| 0| let operators = ["=", "<", ">", "<=", ">="] 259| 0| let separators = [" ", ","] 260| 0| 261| 0| // Look at a char at an index if present. 262| 0| func peek(idx: Int) -> Character? { 263| 0| guard idx <= depString.count - 1 else { return nil } 264| 0| return depString[depString.index(depString.startIndex, offsetBy: idx)] 265| 0| } 266| 0| 267| 0| // This converts the string which can be separated by comma or spaces 268| 0| // into an array of string. 269| 0| func tokenize() -> [String] { 270| 0| var tokens = [String]() 271| 0| var token = "" 272| 0| for (idx, char) in depString.enumerated() { 273| 0| // Encountered a seperator, use the token. 274| 0| if separators.contains(String(char)) { 275| 0| // If next character is a space skip. 276| 0| if let peeked = peek(idx: idx+1), peeked == " " { continue } 277| 0| // Append to array of tokens and reset token variable. 278| 0| tokens.append(token) 279| 0| token = "" 280| 0| } else { 281| 0| token += String(char) 282| 0| } 283| 0| } 284| 0| // Append the last collected token if present. 285| 0| if !token.isEmpty { tokens += [token] } 286| 0| return tokens 287| 0| } 288| 0| 289| 0| var deps = [String]() 290| 0| var it = tokenize().makeIterator() 291| 0| while let arg = it.next() { 292| 0| // If we encounter an operator then we need to skip the next token. 293| 0| if operators.contains(arg) { 294| 0| // We should have a version number next, skip. 295| 0| guard it.next() != nil else { 296| 0| throw PkgConfigError.parsingError(""" 297| 0| Expected version number after \(deps.last.debugDescription) \(arg) in \"\(depString)\" in \ 298| 0| \(pcFile.pathString) 299| 0| """) 300| 0| } 301| 0| } else { 302| 0| // Otherwise it is a dependency. 303| 0| deps.append(arg) 304| 0| } 305| 0| } 306| 0| return deps 307| 0| } 308| | 309| | /// Perform variable expansion on the line by processing the each fragment 310| | /// of the string until complete. 311| | /// 312| | /// Variables occur in form of ${variableName}, we search for a variable 313| | /// linearly in the string and if found, lookup the value of the variable in 314| | /// our dictionary and replace the variable name with its value. 315| 0| private func resolveVariables(_ line: String) throws -> String { 316| 0| // Returns variable name, start index and end index of a variable in a string if present. 317| 0| // We make sure it of form ${name} otherwise it is not a variable. 318| 0| func findVariable(_ fragment: String) 319| 0| -> (name: String, startIndex: String.Index, endIndex: String.Index)? { 320| 0| guard let dollar = fragment.index(of: "$"), 321| 0| dollar != fragment.endIndex && fragment[fragment.index(after: dollar)] == "{", 322| 0| let variableEndIndex = fragment.index(of: "}") 323| 0| else { return nil } 324| 0| return (String(fragment[fragment.index(dollar, offsetBy: 2).. [String] { 357| 0| var splits = [String]() 358| 0| var fragment = [Character]() 359| 0| 360| 0| func saveFragment() { 361| 0| if !fragment.isEmpty { 362| 0| splits.append(String(fragment)) 363| 0| fragment.removeAll() 364| 0| } 365| 0| } 366| 0| 367| 0| var it = line.makeIterator() 368| 0| // Indicates if we're in a quoted fragment, we shouldn't append quote. 369| 0| var inQuotes = false 370| 0| while let char = it.next() { 371| 0| if char == "\"" { 372| 0| inQuotes = !inQuotes 373| 0| } else if char == "\\" { 374| 0| if let next = it.next() { 375| 0| fragment.append(next) 376| 0| } 377| 0| } else if char == " " && !inQuotes { 378| 0| saveFragment() 379| 0| } else { 380| 0| fragment.append(char) 381| 0| } 382| 0| } 383| 0| guard !inQuotes else { 384| 0| throw PkgConfigError.parsingError( 385| 0| "Text ended before matching quote was found in line: \(line) file: \(pcFile)") 386| 0| } 387| 0| saveFragment() 388| 0| return splits 389| 0| } 390| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Platform.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Foundation 13| | 14| |/// Recognized Platform types. 15| |public enum Platform { 16| | case darwin 17| | case linux(LinuxFlavor) 18| | 19| | /// Recognized flavors of linux. 20| | public enum LinuxFlavor { 21| | case debian 22| | } 23| | 24| | /// Lazily checked current platform. 25| | public static var currentPlatform = Platform.findCurrentPlatform() 26| | /// Attempt to match `uname` with recognized platforms. 27| 0| private static func findCurrentPlatform() -> Platform? { 28| 0| guard let uname = try? Process.checkNonZeroExit(args: "uname").spm_chomp().lowercased() else { return nil } 29| 0| switch uname { 30| 0| case "darwin": 31| 0| return .darwin 32| 0| case "linux": 33| 0| if isFile(AbsolutePath("/etc/debian_version")) { 34| 0| return .linux(.debian) 35| 0| } 36| 0| default: 37| 0| return nil 38| 0| } 39| 0| return nil 40| 0| } 41| | 42| | /// Returns the cache directories used in Darwin. 43| 0| public static func darwinCacheDirectories() -> [AbsolutePath] { 44| 0| if let value = Platform._darwinCacheDirectories { 45| 0| return value 46| 0| } 47| 0| var directories = [AbsolutePath]() 48| 0| // Compute the directories. 49| 0| directories.append(AbsolutePath("/private/var/tmp")) 50| 0| (try? Basic.determineTempDirectory()).map{ directories.append($0) } 51| 0| #if os(macOS) 52| 0| getConfstr(_CS_DARWIN_USER_TEMP_DIR).map({ directories.append($0) }) 53| 0| getConfstr(_CS_DARWIN_USER_CACHE_DIR).map({ directories.append($0) }) 54| 0| #endif 55| 0| Platform._darwinCacheDirectories = directories 56| 0| return directories 57| 0| } 58| | private static var _darwinCacheDirectories: [AbsolutePath]? 59| | 60| | /// Returns the value of given path variable using `getconf` utility. 61| | /// 62| | /// - Note: This method returns `nil` if the value is an invalid path. 63| 0| private static func getConfstr(_ name: Int32) -> AbsolutePath? { 64| 0| let len = confstr(name, nil, 0) 65| 0| let tmp = UnsafeMutableBufferPointer(start: UnsafeMutablePointer.allocate(capacity: len), count:len) 66| 0| defer { tmp.deallocate() } 67| 0| guard confstr(name, tmp.baseAddress, len) == len else { return nil } 68| 0| let value = String(cString: tmp.baseAddress!) 69| 0| guard value.hasSuffix(AbsolutePath.root.pathString) else { return nil } 70| 0| return resolveSymlinks(AbsolutePath(value)) 71| 0| } 72| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Process.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| | 13| |extension Process { 14| | @discardableResult 15| 0| static public func checkNonZeroExit(arguments: [String], environment: [String: String] = env, diagnostics: DiagnosticsEngine) throws -> String { 16| 0| let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect) 17| 0| try process.launch() 18| 0| let result = try process.waitUntilExit() 19| 0| // Throw if there was a non zero termination. 20| 0| guard result.exitStatus == .terminated(code: 0) else { 21| 0| diagnostics.emit(data: ProcessExecutionError(result)) 22| 0| throw Diagnostics.fatalError 23| 0| } 24| 0| return try result.utf8Output() 25| 0| } 26| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/ProgressAnimation.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// A protocol to operate on terminal based progress animations. 14| |public protocol ProgressAnimationProtocol { 15| | /// Update the animation with a new step. 16| | /// - Parameters: 17| | /// - step: The index of the operation's current step. 18| | /// - total: The total number of steps before the operation is complete. 19| | /// - text: The description of the current step. 20| | func update(step: Int, total: Int, text: String) 21| | 22| | /// Complete the animation. 23| | /// - Parameters: 24| | /// - success: Defines if the operation the animation represents was succesful. 25| | func complete(success: Bool) 26| | 27| | /// Clear the animation. 28| | func clear() 29| |} 30| | 31| |/// A single line percent-based progress animation. 32| |public final class SingleLinePercentProgressAnimation: ProgressAnimationProtocol { 33| | private let stream: OutputByteStream 34| | private let header: String? 35| | private var displayedPercentages: Set = [] 36| | private var hasDisplayedHeader = false 37| | 38| 0| init(stream: OutputByteStream, header: String?) { 39| 0| self.stream = stream 40| 0| self.header = header 41| 0| } 42| | 43| 0| public func update(step: Int, total: Int, text: String) { 44| 0| if let header = header, !hasDisplayedHeader { 45| 0| stream <<< header 46| 0| stream <<< "\n" 47| 0| stream.flush() 48| 0| hasDisplayedHeader = true 49| 0| } 50| 0| 51| 0| let percentage = step * 100 / total 52| 0| let roundedPercentage = Int(Double(percentage / 10).rounded(.down)) * 10 53| 0| if percentage != 100, !displayedPercentages.contains(roundedPercentage) { 54| 0| stream <<< String(roundedPercentage) <<< ".. " 55| 0| displayedPercentages.insert(roundedPercentage) 56| 0| } 57| 0| 58| 0| stream.flush() 59| 0| } 60| | 61| 0| public func complete(success: Bool) { 62| 0| if success { 63| 0| stream <<< "OK" 64| 0| stream.flush() 65| 0| } 66| 0| } 67| | 68| 0| public func clear() { 69| 0| } 70| |} 71| | 72| |/// A multi-line ninja-like progress animation. 73| |public final class MultiLineNinjaProgressAnimation: ProgressAnimationProtocol { 74| | private let stream: OutputByteStream 75| | 76| 0| init(stream: OutputByteStream) { 77| 0| self.stream = stream 78| 0| } 79| | 80| 0| public func update(step: Int, total: Int, text: String) { 81| 0| assert(step <= total) 82| 0| 83| 0| stream <<< "[\(step)/\(total)] " <<< text 84| 0| stream <<< "\n" 85| 0| stream.flush() 86| 0| } 87| | 88| 0| public func complete(success: Bool) { 89| 0| } 90| | 91| 0| public func clear() { 92| 0| } 93| |} 94| | 95| |/// A redrawing ninja-like progress animation. 96| |public final class RedrawingNinjaProgressAnimation: ProgressAnimationProtocol { 97| | private let terminal: TerminalController 98| | private var hasDisplayedProgress = false 99| | 100| 0| init(terminal: TerminalController) { 101| 0| self.terminal = terminal 102| 0| } 103| | 104| 0| public func update(step: Int, total: Int, text: String) { 105| 0| assert(step <= total) 106| 0| 107| 0| terminal.clearLine() 108| 0| 109| 0| let progressText = "[\(step)/\(total)] \(text)" 110| 0| if progressText.utf8.count > terminal.width { 111| 0| let suffix = "…" 112| 0| terminal.write(String(progressText.prefix(terminal.width - suffix.utf8.count))) 113| 0| terminal.write(suffix) 114| 0| } else { 115| 0| terminal.write(progressText) 116| 0| } 117| 0| 118| 0| hasDisplayedProgress = true 119| 0| } 120| | 121| 0| public func complete(success: Bool) { 122| 0| if hasDisplayedProgress { 123| 0| terminal.endLine() 124| 0| } 125| 0| } 126| | 127| 0| public func clear() { 128| 0| terminal.clearLine() 129| 0| } 130| |} 131| | 132| |/// A ninja-like progress animation that adapts to the provided output stream. 133| |public final class NinjaProgressAnimation: DynamicProgressAnimation { 134| 0| public init(stream: OutputByteStream) { 135| 0| super.init( 136| 0| stream: stream, 137| 0| ttyTerminalAnimationFactory: { RedrawingNinjaProgressAnimation(terminal: $0) }, 138| 0| dumbTerminalAnimationFactory: { SingleLinePercentProgressAnimation(stream: stream, header: nil) }, 139| 0| defaultAnimationFactory: { MultiLineNinjaProgressAnimation(stream: stream) }) 140| 0| } 141| |} 142| | 143| |/// A multi-line percent-based progress animation. 144| |public final class MultiLinePercentProgressAnimation: ProgressAnimationProtocol { 145| | private let stream: OutputByteStream 146| | private let header: String 147| | private var hasDisplayedHeader = false 148| | 149| 0| init(stream: OutputByteStream, header: String) { 150| 0| self.stream = stream 151| 0| self.header = header 152| 0| } 153| | 154| 0| public func update(step: Int, total: Int, text: String) { 155| 0| assert(step <= total) 156| 0| 157| 0| if !hasDisplayedHeader { 158| 0| stream <<< header 159| 0| stream <<< "\n" 160| 0| stream.flush() 161| 0| hasDisplayedHeader = true 162| 0| } 163| 0| 164| 0| let percentage = step * 100 / total 165| 0| stream <<< "\(percentage)%: " <<< text 166| 0| stream <<< "\n" 167| 0| stream.flush() 168| 0| } 169| | 170| 0| public func complete(success: Bool) { 171| 0| } 172| | 173| 0| public func clear() { 174| 0| } 175| |} 176| | 177| |/// A redrawing lit-like progress animation. 178| |public final class RedrawingLitProgressAnimation: ProgressAnimationProtocol { 179| | private let terminal: TerminalController 180| | private let header: String 181| | private var hasDisplayedHeader = false 182| | 183| 0| init(terminal: TerminalController, header: String) { 184| 0| self.terminal = terminal 185| 0| self.header = header 186| 0| } 187| | 188| | /// Creates repeating string for count times. 189| | /// If count is negative, returns empty string. 190| 0| private func repeating(string: String, count: Int) -> String { 191| 0| return String(repeating: string, count: max(count, 0)) 192| 0| } 193| | 194| 0| public func update(step: Int, total: Int, text: String) { 195| 0| assert(step <= total) 196| 0| 197| 0| if !hasDisplayedHeader { 198| 0| let spaceCount = terminal.width / 2 - header.utf8.count / 2 199| 0| terminal.write(repeating(string: " ", count: spaceCount)) 200| 0| terminal.write(header, inColor: .cyan, bold: true) 201| 0| terminal.endLine() 202| 0| hasDisplayedHeader = true 203| 0| } 204| 0| 205| 0| terminal.clearLine() 206| 0| let percentage = step * 100 / total 207| 0| let paddedPercentage = percentage < 10 ? " \(percentage)" : "\(percentage)" 208| 0| let prefix = "\(paddedPercentage)% " + terminal.wrap("[", inColor: .green, bold: true) 209| 0| terminal.write(prefix) 210| 0| 211| 0| let barWidth = terminal.width - prefix.utf8.count 212| 0| let n = Int(Double(barWidth) * Double(percentage) / 100.0) 213| 0| 214| 0| terminal.write(repeating(string: "=", count: n) + repeating(string: "-", count: barWidth - n), inColor: .green) 215| 0| terminal.write("]", inColor: .green, bold: true) 216| 0| terminal.endLine() 217| 0| 218| 0| terminal.clearLine() 219| 0| if text.utf8.count > terminal.width { 220| 0| let prefix = "…" 221| 0| terminal.write(prefix) 222| 0| terminal.write(String(text.suffix(terminal.width - prefix.utf8.count))) 223| 0| } else { 224| 0| terminal.write(text) 225| 0| } 226| 0| 227| 0| terminal.moveCursor(up: 1) 228| 0| } 229| | 230| 0| public func complete(success: Bool) { 231| 0| terminal.endLine() 232| 0| terminal.endLine() 233| 0| } 234| | 235| 0| public func clear() { 236| 0| terminal.clearLine() 237| 0| terminal.moveCursor(up: 1) 238| 0| terminal.clearLine() 239| 0| } 240| |} 241| | 242| |/// A percent-based progress animation that adapts to the provided output stream. 243| |public final class PercentProgressAnimation: DynamicProgressAnimation { 244| 0| public init(stream: OutputByteStream, header: String) { 245| 0| super.init( 246| 0| stream: stream, 247| 0| ttyTerminalAnimationFactory: { RedrawingLitProgressAnimation(terminal: $0, header: header) }, 248| 0| dumbTerminalAnimationFactory: { SingleLinePercentProgressAnimation(stream: stream, header: header) }, 249| 0| defaultAnimationFactory: { MultiLinePercentProgressAnimation(stream: stream, header: header) }) 250| 0| } 251| |} 252| | 253| |/// A progress animation that adapts to the provided output stream. 254| |public class DynamicProgressAnimation: ProgressAnimationProtocol { 255| | private let animation: ProgressAnimationProtocol 256| | 257| | public init( 258| | stream: OutputByteStream, 259| | ttyTerminalAnimationFactory: (TerminalController) -> ProgressAnimationProtocol, 260| | dumbTerminalAnimationFactory: () -> ProgressAnimationProtocol, 261| | defaultAnimationFactory: () -> ProgressAnimationProtocol 262| 0| ) { 263| 0| if let terminal = TerminalController(stream: stream) { 264| 0| animation = ttyTerminalAnimationFactory(terminal) 265| 0| } else if let fileStream = stream as? LocalFileOutputByteStream, 266| 0| TerminalController.terminalType(fileStream) == .dumb 267| 0| { 268| 0| animation = dumbTerminalAnimationFactory() 269| 0| } else { 270| 0| animation = defaultAnimationFactory() 271| 0| } 272| 0| } 273| | 274| 0| public func update(step: Int, total: Int, text: String) { 275| 0| animation.update(step: step, total: total, text: text) 276| 0| } 277| | 278| 0| public func complete(success: Bool) { 279| 0| animation.complete(success: success) 280| 0| } 281| | 282| 0| public func clear() { 283| 0| animation.clear() 284| 0| } 285| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/SimplePersistence.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// A protocol which needs to be implemented by the objects which can be 14| |/// persisted using SimplePersistence 15| |public protocol SimplePersistanceProtocol: class, JSONSerializable { 16| | /// Restores state from the given json object. 17| | func restore(from json: JSON) throws 18| | 19| | /// Restores state from the given json object and supported schema version. 20| | func restore(from json: JSON, supportedSchemaVersion: Int) throws 21| |} 22| | 23| |public extension SimplePersistanceProtocol { 24| 0| func restore(from json: JSON, supportedSchemaVersion: Int) throws {} 25| |} 26| | 27| |extension SimplePersistence.Error: CustomStringConvertible { 28| 0| public var description: String { 29| 0| switch self { 30| 0| case let .invalidSchemaVersion(version): 31| 0| return "unsupported schema version \(version)" 32| 0| 33| 0| case let .restoreFailure(stateFile, error): 34| 0| return "unable to restore state from \(stateFile); \(error)" 35| 0| } 36| 0| } 37| |} 38| | 39| |/// A simple persistence helper. 40| |/// 41| |/// This class can be used to save and restore state of objects in simple JSON 42| |/// format. Note: This class is not thread safe. 43| |public final class SimplePersistence { 44| | /// Describes a SimplePersistence errors. 45| | public enum Error: Swift.Error { 46| | case invalidSchemaVersion(Int) 47| | 48| | case restoreFailure(stateFile: AbsolutePath, error: Swift.Error) 49| | } 50| | 51| | /// The fileSystem to operate on. 52| | private let fileSystem: FileSystem 53| | 54| | /// The schema of the state file. 55| | private let schemaVersion: Int 56| | 57| | /// The schema versions, besides the current schema, that are supported for restoring. 58| | private let supportedSchemaVersions: Set 59| | 60| | /// The path at which we persist the state. 61| | private let statePath: AbsolutePath 62| | 63| | /// Writes the state files with pretty print JSON. 64| | private let prettyPrint: Bool 65| | 66| | public init( 67| | fileSystem: FileSystem, 68| | schemaVersion: Int, 69| | supportedSchemaVersions: Set = [], 70| | statePath: AbsolutePath, 71| | prettyPrint: Bool = false 72| 0| ) { 73| 0| assert(!supportedSchemaVersions.contains(schemaVersion), "Supported schema versions should not include the current schema") 74| 0| self.fileSystem = fileSystem 75| 0| self.schemaVersion = schemaVersion 76| 0| self.supportedSchemaVersions = supportedSchemaVersions 77| 0| self.statePath = statePath 78| 0| self.prettyPrint = prettyPrint 79| 0| } 80| | 81| | @discardableResult 82| 0| public func restoreState(_ object: SimplePersistanceProtocol) throws -> Bool { 83| 0| do { 84| 0| return try _restoreState(object) 85| 0| } catch { 86| 0| throw Error.restoreFailure(stateFile: statePath, error: error) 87| 0| } 88| 0| } 89| | 90| 0| private func _restoreState(_ object: SimplePersistanceProtocol) throws -> Bool { 91| 0| // If the state doesn't exist, don't try to load and fail. 92| 0| if !fileSystem.exists(statePath) { 93| 0| return false 94| 0| } 95| 0| // Load the state. 96| 0| let json = try JSON(bytes: try fileSystem.readFileContents(statePath)) 97| 0| // Get the schema version. 98| 0| let version: Int = try json.get("version") 99| 0| 100| 0| // Restore the state based on the provided schema version. 101| 0| switch version { 102| 0| case schemaVersion: 103| 0| try object.restore(from: json.get("object")) 104| 0| 105| 0| case _ where supportedSchemaVersions.contains(version): 106| 0| try object.restore(from: json.get("object"), supportedSchemaVersion: version) 107| 0| 108| 0| default: 109| 0| throw Error.invalidSchemaVersion(version) 110| 0| } 111| 0| 112| 0| return true 113| 0| } 114| | 115| | /// Merges the two given json if they both are dictionaries. 116| | /// 117| | /// In case of collisions, keep the value from new dictionary. 118| 0| private func merge(old: JSON?, new: JSON) -> JSON { 119| 0| guard case let .dictionary(oldDict)? = old, 120| 0| case var .dictionary(newDict) = new else { 121| 0| return new 122| 0| } 123| 0| 124| 0| // Merge the dictionaries, keeping new values in case of collisions. 125| 0| for (key, value) in oldDict where newDict[key] == nil { 126| 0| newDict[key] = value 127| 0| } 128| 0| 129| 0| return JSON(newDict) 130| 0| } 131| | 132| 0| public func saveState(_ object: SimplePersistanceProtocol) throws { 133| 0| var json = [String: JSON]() 134| 0| 135| 0| // Load the current data. 136| 0| let jsonData = try? JSON(bytes: fileSystem.readFileContents(statePath)) 137| 0| if case let .dictionary(dict)? = jsonData { 138| 0| json = dict 139| 0| } 140| 0| 141| 0| // Set the schema version. 142| 0| json["version"] = self.schemaVersion.toJSON() 143| 0| 144| 0| // Set the object, keeping any keys in object which we don't know about. 145| 0| json["object"] = merge(old: json["object"], new: object.toJSON()) 146| 0| 147| 0| try fileSystem.createDirectory(statePath.parentDirectory, recursive: true) 148| 0| // FIXME: This should write atomically. 149| 0| try fileSystem.writeFileContents( 150| 0| statePath, bytes: JSON(json).toBytes(prettyPrint: self.prettyPrint)) 151| 0| } 152| | 153| | /// Returns true if the state file exists on the filesystem. 154| 0| public func stateFileExists() -> Bool { 155| 0| return fileSystem.exists(statePath) 156| 0| } 157| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/StringExtensions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |extension String { 12| | /** 13| | Remove trailing newline characters. By default chomp removes 14| | all trailing \n (UNIX) or all trailing \r\n (Windows) (it will 15| | not remove mixed occurrences of both separators. 16| | */ 17| 0| public func spm_chomp(separator: String? = nil) -> String { 18| 0| func scrub(_ separator: String) -> String { 19| 0| var E = endIndex 20| 0| while String(self[startIndex.. startIndex { 21| 0| E = index(before: E) 22| 0| } 23| 0| return String(self[startIndex.. String? { 47| 0| var cc = self 48| 0| 49| 0| loop: while true { 50| 0| switch cc.first { 51| 0| case nil: 52| 0| return nil 53| 0| case "\n"?, "\r"?, " "?, "\t"?, "\r\n"?: 54| 0| cc = String(cc.dropFirst()) 55| 0| default: 56| 0| break loop 57| 0| } 58| 0| } 59| 0| 60| 0| loop: while true { 61| 0| switch cc.last { 62| 0| case nil: 63| 0| return nil 64| 0| case "\n"?, "\r"?, " "?, "\t"?, "\r\n"?: 65| 0| cc = String(cc.dropLast()) 66| 0| default: 67| 0| break loop 68| 0| } 69| 0| } 70| 0| 71| 0| return String(cc) 72| 0| } 73| | 74| | /// Splits string around a delimiter string into up to two substrings 75| | /// If delimiter is not found, the second returned substring is nil 76| 0| public func spm_split(around delimiter: String) -> (String, String?) { 77| 0| let comps = self.spm_split(around: Array(delimiter)) 78| 0| let head = String(comps.0) 79| 0| if let tail = comps.1 { 80| 0| return (head, String(tail)) 81| 0| } else { 82| 0| return (head, nil) 83| 0| } 84| 0| } 85| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/StringMangling.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |/// Extensions to `String` to provide various forms of identifier mangling. Many 12| |/// of them are programming-related. 13| |extension String { 14| | 15| | /// Returns a form of the string that is a valid bundle identifier 16| 0| public func spm_mangledToBundleIdentifier() -> String { 17| 0| let mangledUnichars: [UInt16] = self.utf16.map({ 18| 0| switch $0 { 19| 0| case 20| 0| // A-Z 21| 0| 0x0041...0x005A, 22| 0| // a-z 23| 0| 0x0061...0x007A, 24| 0| // 0-9 25| 0| 0x0030...0x0039, 26| 0| // - 27| 0| 0x2D, 28| 0| // . 29| 0| 0x2E: 30| 0| return $0 31| 0| default: 32| 0| return 0x2D 33| 0| } 34| 0| }) 35| 0| 36| 0| return String(utf16CodeUnits: mangledUnichars, count: mangledUnichars.count) 37| 0| } 38| | 39| | /// Returns a form of the string that is valid C99 Extended Identifier (by 40| | /// replacing any invalid characters in an unspecified but consistent way). 41| | /// The output string is guaranteed to be non-empty as long as the input 42| | /// string is non-empty. 43| 0| public func spm_mangledToC99ExtendedIdentifier() -> String { 44| 0| // Map invalid C99-invalid Unicode scalars to a replacement character. 45| 0| let replacementUnichar: UnicodeScalar = "_" 46| 0| var mangledUnichars: [UnicodeScalar] = self.unicodeScalars.map({ 47| 0| switch $0.value { 48| 0| case 49| 0| // A-Z 50| 0| 0x0041...0x005A, 51| 0| // a-z 52| 0| 0x0061...0x007A, 53| 0| // 0-9 54| 0| 0x0030...0x0039, 55| 0| // _ 56| 0| 0x005F, 57| 0| // Latin (1) 58| 0| 0x00AA...0x00AA, 59| 0| // Special characters (1) 60| 0| 0x00B5...0x00B5, 0x00B7...0x00B7, 61| 0| // Latin (2) 62| 0| 0x00BA...0x00BA, 0x00C0...0x00D6, 0x00D8...0x00F6, 63| 0| 0x00F8...0x01F5, 0x01FA...0x0217, 0x0250...0x02A8, 64| 0| // Special characters (2) 65| 0| 0x02B0...0x02B8, 0x02BB...0x02BB, 0x02BD...0x02C1, 66| 0| 0x02D0...0x02D1, 0x02E0...0x02E4, 0x037A...0x037A, 67| 0| // Greek (1) 68| 0| 0x0386...0x0386, 0x0388...0x038A, 0x038C...0x038C, 69| 0| 0x038E...0x03A1, 0x03A3...0x03CE, 0x03D0...0x03D6, 70| 0| 0x03DA...0x03DA, 0x03DC...0x03DC, 0x03DE...0x03DE, 71| 0| 0x03E0...0x03E0, 0x03E2...0x03F3, 72| 0| // Cyrillic 73| 0| 0x0401...0x040C, 0x040E...0x044F, 0x0451...0x045C, 74| 0| 0x045E...0x0481, 0x0490...0x04C4, 0x04C7...0x04C8, 75| 0| 0x04CB...0x04CC, 0x04D0...0x04EB, 0x04EE...0x04F5, 76| 0| 0x04F8...0x04F9, 77| 0| // Armenian (1) 78| 0| 0x0531...0x0556, 79| 0| // Special characters (3) 80| 0| 0x0559...0x0559, 81| 0| // Armenian (2) 82| 0| 0x0561...0x0587, 83| 0| // Hebrew 84| 0| 0x05B0...0x05B9, 0x05BB...0x05BD, 0x05BF...0x05BF, 85| 0| 0x05C1...0x05C2, 0x05D0...0x05EA, 0x05F0...0x05F2, 86| 0| // Arabic (1) 87| 0| 0x0621...0x063A, 0x0640...0x0652, 88| 0| // Digits (1) 89| 0| 0x0660...0x0669, 90| 0| // Arabic (2) 91| 0| 0x0670...0x06B7, 0x06BA...0x06BE, 0x06C0...0x06CE, 92| 0| 0x06D0...0x06DC, 0x06E5...0x06E8, 0x06EA...0x06ED, 93| 0| // Digits (2) 94| 0| 0x06F0...0x06F9, 95| 0| // Devanagari and Special character 0x093D. 96| 0| 0x0901...0x0903, 0x0905...0x0939, 0x093D...0x094D, 97| 0| 0x0950...0x0952, 0x0958...0x0963, 98| 0| // Digits (3) 99| 0| 0x0966...0x096F, 100| 0| // Bengali (1) 101| 0| 0x0981...0x0983, 0x0985...0x098C, 0x098F...0x0990, 102| 0| 0x0993...0x09A8, 0x09AA...0x09B0, 0x09B2...0x09B2, 103| 0| 0x09B6...0x09B9, 0x09BE...0x09C4, 0x09C7...0x09C8, 104| 0| 0x09CB...0x09CD, 0x09DC...0x09DD, 0x09DF...0x09E3, 105| 0| // Digits (4) 106| 0| 0x09E6...0x09EF, 107| 0| // Bengali (2) 108| 0| 0x09F0...0x09F1, 109| 0| // Gurmukhi (1) 110| 0| 0x0A02...0x0A02, 0x0A05...0x0A0A, 0x0A0F...0x0A10, 111| 0| 0x0A13...0x0A28, 0x0A2A...0x0A30, 0x0A32...0x0A33, 112| 0| 0x0A35...0x0A36, 0x0A38...0x0A39, 0x0A3E...0x0A42, 113| 0| 0x0A47...0x0A48, 0x0A4B...0x0A4D, 0x0A59...0x0A5C, 114| 0| 0x0A5E...0x0A5E, 115| 0| // Digits (5) 116| 0| 0x0A66...0x0A6F, 117| 0| // Gurmukhi (2) 118| 0| 0x0A74...0x0A74, 119| 0| // Gujarti 120| 0| 0x0A81...0x0A83, 0x0A85...0x0A8B, 0x0A8D...0x0A8D, 121| 0| 0x0A8F...0x0A91, 0x0A93...0x0AA8, 0x0AAA...0x0AB0, 122| 0| 0x0AB2...0x0AB3, 0x0AB5...0x0AB9, 0x0ABD...0x0AC5, 123| 0| 0x0AC7...0x0AC9, 0x0ACB...0x0ACD, 0x0AD0...0x0AD0, 124| 0| 0x0AE0...0x0AE0, 125| 0| // Digits (6) 126| 0| 0x0AE6...0x0AEF, 127| 0| // Oriya and Special character 0x0B3D 128| 0| 0x0B01...0x0B03, 0x0B05...0x0B0C, 0x0B0F...0x0B10, 129| 0| 0x0B13...0x0B28, 0x0B2A...0x0B30, 0x0B32...0x0B33, 130| 0| 0x0B36...0x0B39, 0x0B3D...0x0B43, 0x0B47...0x0B48, 131| 0| 0x0B4B...0x0B4D, 0x0B5C...0x0B5D, 0x0B5F...0x0B61, 132| 0| // Digits (7) 133| 0| 0x0B66...0x0B6F, 134| 0| // Tamil 135| 0| 0x0B82...0x0B83, 0x0B85...0x0B8A, 0x0B8E...0x0B90, 136| 0| 0x0B92...0x0B95, 0x0B99...0x0B9A, 0x0B9C...0x0B9C, 137| 0| 0x0B9E...0x0B9F, 0x0BA3...0x0BA4, 0x0BA8...0x0BAA, 138| 0| 0x0BAE...0x0BB5, 0x0BB7...0x0BB9, 0x0BBE...0x0BC2, 139| 0| 0x0BC6...0x0BC8, 0x0BCA...0x0BCD, 140| 0| // Digits (8) 141| 0| 0x0BE7...0x0BEF, 142| 0| // Telugu 143| 0| 0x0C01...0x0C03, 0x0C05...0x0C0C, 0x0C0E...0x0C10, 144| 0| 0x0C12...0x0C28, 0x0C2A...0x0C33, 0x0C35...0x0C39, 145| 0| 0x0C3E...0x0C44, 0x0C46...0x0C48, 0x0C4A...0x0C4D, 146| 0| 0x0C60...0x0C61, 147| 0| // Digits (9) 148| 0| 0x0C66...0x0C6F, 149| 0| // Kannada 150| 0| 0x0C82...0x0C83, 0x0C85...0x0C8C, 0x0C8E...0x0C90, 151| 0| 0x0C92...0x0CA8, 0x0CAA...0x0CB3, 0x0CB5...0x0CB9, 152| 0| 0x0CBE...0x0CC4, 0x0CC6...0x0CC8, 0x0CCA...0x0CCD, 153| 0| 0x0CDE...0x0CDE, 0x0CE0...0x0CE1, 154| 0| // Digits (10) 155| 0| 0x0CE6...0x0CEF, 156| 0| // Malayam 157| 0| 0x0D02...0x0D03, 0x0D05...0x0D0C, 0x0D0E...0x0D10, 158| 0| 0x0D12...0x0D28, 0x0D2A...0x0D39, 0x0D3E...0x0D43, 159| 0| 0x0D46...0x0D48, 0x0D4A...0x0D4D, 0x0D60...0x0D61, 160| 0| // Digits (11) 161| 0| 0x0D66...0x0D6F, 162| 0| // Thai...including Digits 0x0E50...0x0E59 } 163| 0| 0x0E01...0x0E3A, 0x0E40...0x0E5B, 164| 0| // Lao (1) 165| 0| 0x0E81...0x0E82, 0x0E84...0x0E84, 0x0E87...0x0E88, 166| 0| 0x0E8A...0x0E8A, 0x0E8D...0x0E8D, 0x0E94...0x0E97, 167| 0| 0x0E99...0x0E9F, 0x0EA1...0x0EA3, 0x0EA5...0x0EA5, 168| 0| 0x0EA7...0x0EA7, 0x0EAA...0x0EAB, 0x0EAD...0x0EAE, 169| 0| 0x0EB0...0x0EB9, 0x0EBB...0x0EBD, 0x0EC0...0x0EC4, 170| 0| 0x0EC6...0x0EC6, 0x0EC8...0x0ECD, 171| 0| // Digits (12) 172| 0| 0x0ED0...0x0ED9, 173| 0| // Lao (2) 174| 0| 0x0EDC...0x0EDD, 175| 0| // Tibetan (1) 176| 0| 0x0F00...0x0F00, 0x0F18...0x0F19, 177| 0| // Digits (13) 178| 0| 0x0F20...0x0F33, 179| 0| // Tibetan (2) 180| 0| 0x0F35...0x0F35, 0x0F37...0x0F37, 0x0F39...0x0F39, 181| 0| 0x0F3E...0x0F47, 0x0F49...0x0F69, 0x0F71...0x0F84, 182| 0| 0x0F86...0x0F8B, 0x0F90...0x0F95, 0x0F97...0x0F97, 183| 0| 0x0F99...0x0FAD, 0x0FB1...0x0FB7, 0x0FB9...0x0FB9, 184| 0| // Georgian 185| 0| 0x10A0...0x10C5, 0x10D0...0x10F6, 186| 0| // Latin (3) 187| 0| 0x1E00...0x1E9B, 0x1EA0...0x1EF9, 188| 0| // Greek (2) 189| 0| 0x1F00...0x1F15, 0x1F18...0x1F1D, 0x1F20...0x1F45, 190| 0| 0x1F48...0x1F4D, 0x1F50...0x1F57, 0x1F59...0x1F59, 191| 0| 0x1F5B...0x1F5B, 0x1F5D...0x1F5D, 0x1F5F...0x1F7D, 192| 0| 0x1F80...0x1FB4, 0x1FB6...0x1FBC, 193| 0| // Special characters (4) 194| 0| 0x1FBE...0x1FBE, 195| 0| // Greek (3) 196| 0| 0x1FC2...0x1FC4, 0x1FC6...0x1FCC, 0x1FD0...0x1FD3, 197| 0| 0x1FD6...0x1FDB, 0x1FE0...0x1FEC, 0x1FF2...0x1FF4, 198| 0| 0x1FF6...0x1FFC, 199| 0| // Special characters (5) 200| 0| 0x203F...0x2040, 201| 0| // Latin (4) 202| 0| 0x207F...0x207F, 203| 0| // Special characters (6) 204| 0| 0x2102...0x2102, 0x2107...0x2107, 0x210A...0x2113, 205| 0| 0x2115...0x2115, 0x2118...0x211D, 0x2124...0x2124, 206| 0| 0x2126...0x2126, 0x2128...0x2128, 0x212A...0x2131, 207| 0| 0x2133...0x2138, 0x2160...0x2182, 0x3005...0x3007, 208| 0| 0x3021...0x3029, 209| 0| // Hiragana 210| 0| 0x3041...0x3093, 0x309B...0x309C, 211| 0| // Katakana 212| 0| 0x30A1...0x30F6, 0x30FB...0x30FC, 213| 0| // Bopmofo [sic] 214| 0| 0x3105...0x312C, 215| 0| // CJK Unified Ideographs 216| 0| 0x4E00...0x9FA5, 217| 0| // Hangul, 218| 0| 0xAC00...0xD7A3: 219| 0| return $0 220| 0| default: 221| 0| return replacementUnichar 222| 0| } 223| 0| }) 224| 0| 225| 0| // Apply further restrictions to the prefix. 226| 0| loop: for (idx, c) in mangledUnichars.enumerated() { 227| 0| switch c.value { 228| 0| case 229| 0| // 0-9 230| 0| 0x0030...0x0039, 231| 0| // Annex D. 232| 0| 0x0660...0x0669, 0x06F0...0x06F9, 0x0966...0x096F, 233| 0| 0x09E6...0x09EF, 0x0A66...0x0A6F, 0x0AE6...0x0AEF, 234| 0| 0x0B66...0x0B6F, 0x0BE7...0x0BEF, 0x0C66...0x0C6F, 235| 0| 0x0CE6...0x0CEF, 0x0D66...0x0D6F, 0x0E50...0x0E59, 236| 0| 0x0ED0...0x0ED9, 0x0F20...0x0F33: 237| 0| mangledUnichars[idx] = replacementUnichar 238| 0| break loop 239| 0| default: 240| 0| break loop 241| 0| } 242| 0| } 243| 0| 244| 0| // Combine the characters as a string again and return it. 245| 0| // FIXME: We should only construct a new string if anything changed. 246| 0| // FIXME: There doesn't seem to be a way to create a string from an 247| 0| // array of Unicode scalars; but there must be a better way. 248| 0| return mangledUnichars.reduce("") { $0 + String($1) } 249| 0| } 250| | 251| | /// Mangles the contents to a valid C99 Extended Identifier. This method 252| | /// is the mutating version of `mangledToC99ExtendedIdentifier()`. 253| 0| public mutating func spm_mangleToC99ExtendedIdentifier() { 254| 0| self = spm_mangledToC99ExtendedIdentifier() 255| 0| } 256| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/URL.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |public struct URL { 12| | 13| | /// Parses the URL type of a git repository 14| | /// e.g. https://github.com/apple/swift returns "https" 15| | /// e.g. git@github.com:apple/swift returns "git" 16| | /// 17| | /// This is *not* a generic URI scheme parser! 18| 0| public static func scheme(_ url: String) -> String? { 19| 0| 20| 0| func prefixOfSplitBy(_ delimiter: String) -> String? { 21| 0| let (head, tail) = url.spm_split(around: delimiter) 22| 0| if tail == nil { 23| 0| //not found 24| 0| return nil 25| 0| } else { 26| 0| //found, return head 27| 0| //lowercase the "scheme", as specified by the URI RFC (just in case) 28| 0| return head.lowercased() 29| 0| } 30| 0| } 31| 0| 32| 0| for delim in ["://", "@"] { 33| 0| if let found = prefixOfSplitBy(delim) { 34| 0| return found 35| 0| } 36| 0| } 37| 0| 38| 0| return nil 39| 0| } 40| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Verbosity.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |public enum Verbosity: Int { 12| | case concise 13| | case verbose 14| | case debug 15| | 16| 0| public init(rawValue: Int) { 17| 0| switch rawValue { 18| 0| case Int.min...0: 19| 0| self = .concise 20| 0| case 1: 21| 0| self = .verbose 22| 0| default: 23| 0| self = .debug 24| 0| } 25| 0| } 26| | 27| 0| public var ccArgs: [String] { 28| 0| switch self { 29| 0| case .concise: 30| 0| return [] 31| 0| case .verbose: 32| 0| // the first level of verbosity is passed to llbuild itself 33| 0| return [] 34| 0| case .debug: 35| 0| return ["-v"] 36| 0| } 37| 0| } 38| |} 39| | 40| |public var verbosity = Verbosity.concise /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Version.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// A struct representing a semver version. 14| |public struct Version: Hashable { 15| | 16| | /// The major version. 17| | public let major: Int 18| | 19| | /// The minor version. 20| | public let minor: Int 21| | 22| | /// The patch version. 23| | public let patch: Int 24| | 25| | /// The pre-release identifier. 26| | public let prereleaseIdentifiers: [String] 27| | 28| | /// The build metadata. 29| | public let buildMetadataIdentifiers: [String] 30| | 31| | /// Create a version object. 32| | public init( 33| | _ major: Int, 34| | _ minor: Int, 35| | _ patch: Int, 36| | prereleaseIdentifiers: [String] = [], 37| | buildMetadataIdentifiers: [String] = [] 38| 0| ) { 39| 0| precondition(major >= 0 && minor >= 0 && patch >= 0, "Negative versioning is invalid.") 40| 0| self.major = major 41| 0| self.minor = minor 42| 0| self.patch = patch 43| 0| self.prereleaseIdentifiers = prereleaseIdentifiers 44| 0| self.buildMetadataIdentifiers = buildMetadataIdentifiers 45| 0| } 46| |} 47| | 48| |extension Version: Comparable { 49| | 50| 0| func isEqualWithoutPrerelease(_ other: Version) -> Bool { 51| 0| return major == other.major && minor == other.minor && patch == other.patch 52| 0| } 53| | 54| 0| public static func < (lhs: Version, rhs: Version) -> Bool { 55| 0| let lhsComparators = [lhs.major, lhs.minor, lhs.patch] 56| 0| let rhsComparators = [rhs.major, rhs.minor, rhs.patch] 57| 0| 58| 0| if lhsComparators != rhsComparators { 59| 0| return lhsComparators.lexicographicallyPrecedes(rhsComparators) 60| 0| } 61| 0| 62| 0| guard lhs.prereleaseIdentifiers.count > 0 else { 63| 0| return false // Non-prerelease lhs >= potentially prerelease rhs 64| 0| } 65| 0| 66| 0| guard rhs.prereleaseIdentifiers.count > 0 else { 67| 0| return true // Prerelease lhs < non-prerelease rhs 68| 0| } 69| 0| 70| 0| let zippedIdentifiers = zip(lhs.prereleaseIdentifiers, rhs.prereleaseIdentifiers) 71| 0| for (lhsPrereleaseIdentifier, rhsPrereleaseIdentifier) in zippedIdentifiers { 72| 0| if lhsPrereleaseIdentifier == rhsPrereleaseIdentifier { 73| 0| continue 74| 0| } 75| 0| 76| 0| let typedLhsIdentifier: Any = Int(lhsPrereleaseIdentifier) ?? lhsPrereleaseIdentifier 77| 0| let typedRhsIdentifier: Any = Int(rhsPrereleaseIdentifier) ?? rhsPrereleaseIdentifier 78| 0| 79| 0| switch (typedLhsIdentifier, typedRhsIdentifier) { 80| 0| case let (int1 as Int, int2 as Int): return int1 < int2 81| 0| case let (string1 as String, string2 as String): return string1 < string2 82| 0| case (is Int, is String): return true // Int prereleases < String prereleases 83| 0| case (is String, is Int): return false 84| 0| default: 85| 0| return false 86| 0| } 87| 0| } 88| 0| 89| 0| return lhs.prereleaseIdentifiers.count < rhs.prereleaseIdentifiers.count 90| 0| } 91| |} 92| | 93| |extension Version: CustomStringConvertible { 94| 0| public var description: String { 95| 0| var base = "\(major).\(minor).\(patch)" 96| 0| if !prereleaseIdentifiers.isEmpty { 97| 0| base += "-" + prereleaseIdentifiers.joined(separator: ".") 98| 0| } 99| 0| if !buildMetadataIdentifiers.isEmpty { 100| 0| base += "+" + buildMetadataIdentifiers.joined(separator: ".") 101| 0| } 102| 0| return base 103| 0| } 104| |} 105| | 106| |public extension Version { 107| | 108| | /// Create a version object from string. 109| | /// 110| | /// - Parameters: 111| | /// - string: The string to parse. 112| 0| init?(string: String) { 113| 0| let prereleaseStartIndex = string.index(of: "-") 114| 0| let metadataStartIndex = string.index(of: "+") 115| 0| 116| 0| let requiredEndIndex = prereleaseStartIndex ?? metadataStartIndex ?? string.endIndex 117| 0| let requiredCharacters = string.prefix(upTo: requiredEndIndex) 118| 0| let requiredComponents = requiredCharacters 119| 0| .split(separator: ".", maxSplits: 2, omittingEmptySubsequences: false) 120| 0| .map(String.init).compactMap({ Int($0) }).filter({ $0 >= 0 }) 121| 0| 122| 0| guard requiredComponents.count == 3 else { return nil } 123| 0| 124| 0| self.major = requiredComponents[0] 125| 0| self.minor = requiredComponents[1] 126| 0| self.patch = requiredComponents[2] 127| 0| 128| 0| func identifiers(start: String.Index?, end: String.Index) -> [String] { 129| 0| guard let start = start else { return [] } 130| 0| let identifiers = string[string.index(after: start).. JSON { 173| 0| return .string(description) 174| 0| } 175| | 176| 0| init(_ version: Version) { 177| 0| self.init( 178| 0| version.major, version.minor, version.patch, 179| 0| prereleaseIdentifiers: version.prereleaseIdentifiers, 180| 0| buildMetadataIdentifiers: version.buildMetadataIdentifiers 181| 0| ) 182| 0| } 183| |} 184| | 185| |extension Version: Codable { 186| 0| public func encode(to encoder: Encoder) throws { 187| 0| var container = encoder.singleValueContainer() 188| 0| try container.encode(description) 189| 0| } 190| | 191| 0| public init(from decoder: Decoder) throws { 192| 0| let container = try decoder.singleValueContainer() 193| 0| let string = try container.decode(String.self) 194| 0| 195| 0| guard let version = Version(string: string) else { 196| 0| throw DecodingError.dataCorrupted(.init( 197| 0| codingPath: decoder.codingPath, 198| 0| debugDescription: "Invalid version string \(string)")) 199| 0| } 200| 0| 201| 0| self.init(version) 202| 0| } 203| |} 204| | 205| |// MARK:- Range operations 206| | 207| |extension ClosedRange where Bound == Version { 208| | /// Marked as unavailable because we have custom rules for contains. 209| 0| public func contains(_ element: Version) -> Bool { 210| 0| // Unfortunately, we can't use unavailable here. 211| 0| fatalError("contains(_:) is unavailable, use contains(version:)") 212| 0| } 213| |} 214| | 215| |// Disabled because compiler hits an assertion https://bugs.swift.org/browse/SR-5014 216| |#if false 217| |extension CountableRange where Bound == Version { 218| | /// Marked as unavailable because we have custom rules for contains. 219| | public func contains(_ element: Version) -> Bool { 220| | // Unfortunately, we can't use unavailable here. 221| | fatalError("contains(_:) is unavailable, use contains(version:)") 222| | } 223| |} 224| |#endif 225| | 226| |extension Range where Bound == Version { 227| | /// Marked as unavailable because we have custom rules for contains. 228| 0| public func contains(_ element: Version) -> Bool { 229| 0| // Unfortunately, we can't use unavailable here. 230| 0| fatalError("contains(_:) is unavailable, use contains(version:)") 231| 0| } 232| |} 233| | 234| |extension Range where Bound == Version { 235| | 236| 0| public func contains(version: Version) -> Bool { 237| 0| // Special cases if version contains prerelease identifiers. 238| 0| if !version.prereleaseIdentifiers.isEmpty { 239| 0| // If the ranage does not contain prerelease identifiers, return false. 240| 0| if lowerBound.prereleaseIdentifiers.isEmpty && upperBound.prereleaseIdentifiers.isEmpty { 241| 0| return false 242| 0| } 243| 0| 244| 0| // At this point, one of the bounds contains prerelease identifiers. 245| 0| // 246| 0| // Reject 2.0.0-alpha when upper bound is 2.0.0. 247| 0| if upperBound.prereleaseIdentifiers.isEmpty && upperBound.isEqualWithoutPrerelease(version) { 248| 0| return false 249| 0| } 250| 0| } 251| 0| 252| 0| // Otherwise, apply normal contains rules. 253| 0| return version >= lowerBound && version < upperBound 254| 0| } 255| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/Versioning.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import clibc 12| | 13| |/// A Swift version number. 14| |/// 15| |/// Note that these are *NOT* semantically versioned numbers. 16| |public struct SwiftVersion { 17| | /// The version number. 18| | public var version: (major: Int, minor: Int, patch: Int) 19| | 20| | /// Whether or not this is a development version. 21| | public var isDevelopment: Bool 22| | 23| | /// Build information, as an unstructured string. 24| | public var buildIdentifier: String? 25| | 26| | /// The major component of the version number. 27| 0| public var major: Int { return version.major } 28| | /// The minor component of the version number. 29| 0| public var minor: Int { return version.minor } 30| | /// The patch component of the version number. 31| 0| public var patch: Int { return version.patch } 32| | 33| | /// The version as a readable string. 34| 0| public var displayString: String { 35| 0| var result = "\(major).\(minor).\(patch)" 36| 0| if isDevelopment { 37| 0| result += "-dev" 38| 0| } 39| 0| if let buildIdentifier = self.buildIdentifier { 40| 0| result += " (" + buildIdentifier + ")" 41| 0| } 42| 0| return result 43| 0| } 44| | 45| | /// The complete product version display string (including the name). 46| 0| public var completeDisplayString: String { 47| 0| var vendorPrefix = String(cString: SPM_VendorNameString()) 48| 0| if !vendorPrefix.isEmpty { 49| 0| vendorPrefix += " " 50| 0| } 51| 0| return vendorPrefix + "Swift Package Manager - Swift " + displayString 52| 0| } 53| | 54| | /// The list of version specific identifiers to search when attempting to 55| | /// load version specific package or version information, in order of 56| | /// preference. 57| 0| public var versionSpecificKeys: [String] { 58| 0| return [ 59| 0| "@swift-\(major).\(minor).\(patch)", 60| 0| "@swift-\(major).\(minor)", 61| 0| "@swift-\(major)", 62| 0| ] 63| 0| } 64| | 65| |} 66| | 67| 0|private func getBuildIdentifier() -> String? { 68| 0| let buildIdentifier = String(cString: SPM_BuildIdentifierString()) 69| 0| return buildIdentifier.isEmpty ? nil : buildIdentifier 70| 0|} 71| | 72| |/// Version support for the package manager. 73| |public struct Versioning { 74| | 75| | /// The current version of the package manager. 76| | public static let currentVersion = SwiftVersion( 77| | version: (5, 0, 0), 78| | isDevelopment: false, 79| | buildIdentifier: getBuildIdentifier()) 80| | 81| | /// The list of version specific "keys" to search when attempting to load 82| | /// version specific package or version information, in order of preference. 83| | public static let currentVersionSpecificKeys = currentVersion.versionSpecificKeys 84| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/SPMUtility/misc.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Foundation 13| | 14| |/// Get clang's version from the given version output string on Ubuntu. 15| 0|public func getClangVersion(versionOutput: String) -> Version? { 16| 0| // Clang outputs version in this format on Ubuntu: 17| 0| // Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0) 18| 0| let versionStringPrefix = "Ubuntu clang version " 19| 0| let versionStrings = versionOutput.utf8.split(separator: UInt8(ascii: "-")).compactMap(String.init) 20| 0| guard let clangVersionString = versionStrings.first, 21| 0| clangVersionString.hasPrefix(versionStringPrefix) else { 22| 0| return nil 23| 0| } 24| 0| let versionStartIndex = clangVersionString.index(clangVersionString.startIndex, 25| 0| offsetBy: versionStringPrefix.utf8.count) 26| 0| let versionString = clangVersionString[versionStartIndex...] 27| 0| // Split major minor patch etc. 28| 0| let versions = versionString.utf8.split(separator: UInt8(ascii: ".")).compactMap(String.init) 29| 0| guard versions.count > 1, let major = Int(versions[0]), let minor = Int(versions[1]) else { 30| 0| return nil 31| 0| } 32| 0| return Version(major, minor, versions.count > 2 ? Int(versions[2]) ?? 0 : 0) 33| 0|} 34| | 35| |/// Prints the time taken to execute a closure. 36| |/// 37| |/// Note: Only for debugging purposes. 38| 0|public func measure(_ label: String = "", _ f: () throws -> (T)) rethrows -> T { 39| 0| let startTime = Date() 40| 0| let result = try f() 41| 0| let endTime = Date().timeIntervalSince(startTime) 42| 0| print("\(label): Time taken", endTime) 43| 0| return result 44| 0|} <<<<<< EOF # path=POSIX.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/Error.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |public enum SystemError: Swift.Error { 12| | case chdir(Int32, String) 13| | case close(Int32) 14| | case dirfd(Int32, String) 15| | case exec(Int32, path: String, args: [String]) 16| | case fgetc(Int32) 17| | case fread(Int32) 18| | case getcwd(Int32) 19| | case mkdir(Int32, String) 20| | case mkdtemp(Int32) 21| | case pipe(Int32) 22| | case popen(Int32, String) 23| | case posix_spawn(Int32, [String]) 24| | case read(Int32) 25| | case readdir(Int32, String) 26| | case realpath(Int32, String) 27| | case rename(Int32, old: String, new: String) 28| | case rmdir(Int32, String) 29| | case setenv(Int32, String) 30| | case stat(Int32, String) 31| | case symlink(Int32, String, dest: String) 32| | case symlinkat(Int32, String) 33| | case unlink(Int32, String) 34| | case unsetenv(Int32, String) 35| | case waitpid(Int32) 36| | case usleep(Int32) 37| |} 38| | 39| |import func SPMLibc.strerror_r 40| |import var SPMLibc.EINVAL 41| |import var SPMLibc.ERANGE 42| | 43| |extension SystemError: CustomStringConvertible { 44| 0| public var description: String { 45| 0| func strerror(_ errno: Int32) -> String { 46| 0| var cap = 64 47| 0| while cap <= 16 * 1024 { 48| 0| var buf = [Int8](repeating: 0, count: cap) 49| 0| let err = SPMLibc.strerror_r(errno, &buf, buf.count) 50| 0| if err == EINVAL { 51| 0| return "Unknown error \(errno)" 52| 0| } 53| 0| if err == ERANGE { 54| 0| cap *= 2 55| 0| continue 56| 0| } 57| 0| if err != 0 { 58| 0| fatalError("strerror_r error: \(err)") 59| 0| } 60| 0| return "\(String(cString: buf)) (\(errno))" 61| 0| } 62| 0| fatalError("strerror_r error: \(ERANGE)") 63| 0| } 64| 0| 65| 0| switch self { 66| 0| case .chdir(let errno, let path): 67| 0| return "chdir error: \(strerror(errno)): \(path)" 68| 0| case .close(let errno): 69| 0| return "close error: \(strerror(errno))" 70| 0| case .dirfd(let errno, _): 71| 0| return "dirfd error: \(strerror(errno))" 72| 0| case .exec(let errno, let path, let args): 73| 0| let joinedArgs = args.joined(separator: " ") 74| 0| return "exec error: \(strerror(errno)): \(path) \(joinedArgs)" 75| 0| case .fgetc(let errno): 76| 0| return "fgetc error: \(strerror(errno))" 77| 0| case .fread(let errno): 78| 0| return "fread error: \(strerror(errno))" 79| 0| case .getcwd(let errno): 80| 0| return "getcwd error: \(strerror(errno))" 81| 0| case .mkdir(let errno, let path): 82| 0| return "mkdir error: \(strerror(errno)): \(path)" 83| 0| case .mkdtemp(let errno): 84| 0| return "mkdtemp error: \(strerror(errno))" 85| 0| case .pipe(let errno): 86| 0| return "pipe error: \(strerror(errno))" 87| 0| case .posix_spawn(let errno, let args): 88| 0| return "posix_spawn error: \(strerror(errno)), `\(args)`" 89| 0| case .popen(let errno, _): 90| 0| return "popen error: \(strerror(errno))" 91| 0| case .read(let errno): 92| 0| return "read error: \(strerror(errno))" 93| 0| case .readdir(let errno, _): 94| 0| return "readdir error: \(strerror(errno))" 95| 0| case .realpath(let errno, let path): 96| 0| return "realpath error: \(strerror(errno)): \(path)" 97| 0| case .rename(let errno, let old, let new): 98| 0| return "rename error: \(strerror(errno)): \(old) -> \(new)" 99| 0| case .rmdir(let errno, let path): 100| 0| return "rmdir error: \(strerror(errno)): \(path)" 101| 0| case .setenv(let errno, let key): 102| 0| return "setenv error: \(strerror(errno)): \(key)" 103| 0| case .stat(let errno, _): 104| 0| return "stat error: \(strerror(errno))" 105| 0| case .symlink(let errno, let path, let dest): 106| 0| return "symlink error: \(strerror(errno)): \(path) -> \(dest)" 107| 0| case .symlinkat(let errno, _): 108| 0| return "symlinkat error: \(strerror(errno))" 109| 0| case .unlink(let errno, let path): 110| 0| return "unlink error: \(strerror(errno)): \(path)" 111| 0| case .unsetenv(let errno, let key): 112| 0| return "unsetenv error: \(strerror(errno)): \(key)" 113| 0| case .waitpid(let errno): 114| 0| return "waitpid error: \(strerror(errno))" 115| 0| case .usleep(let errno): 116| 0| return "usleep error: \(strerror(errno))" 117| 0| } 118| 0| } 119| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/chdir.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import func SPMLibc.chdir 12| |import var SPMLibc.errno 13| | 14| |/** 15| | Causes the named directory to become the current working directory. 16| |*/ 17| 0|public func chdir(_ path: String) throws { 18| 0| if memo == nil { 19| 0| let argv0 = try realpath(CommandLine.arguments.first!) 20| 0| let cwd = try realpath(getcwd()) 21| 0| memo = (argv0: argv0, wd: cwd) 22| 0| } 23| 0| 24| 0| guard SPMLibc.chdir(path) == 0 else { 25| 0| throw SystemError.chdir(errno, path) 26| 0| } 27| 0|} 28| | 29| |private var memo: (argv0: String, wd: String)? 30| | 31| |/** 32| | The initial working directory before any calls to POSIX.chdir. 33| |*/ 34| 0|public func getiwd() -> String { 35| 0| return memo?.wd ?? getcwd() 36| 0|} 37| | 38| 0|public var argv0: String { 39| 0| return memo?.argv0 ?? CommandLine.arguments.first! 40| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/env.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import func SPMLibc.getenv 12| |import func SPMLibc.setenv 13| |import func SPMLibc.unsetenv 14| |import var SPMLibc.errno 15| | 16| 0|public func getenv(_ key: String) -> String? { 17| 0| let out = SPMLibc.getenv(key) 18| 0| return out == nil ? nil : String(validatingUTF8: out!) //FIXME locale may not be UTF8 19| 0|} 20| | 21| 0|public func setenv(_ key: String, value: String) throws { 22| 0| guard SPMLibc.setenv(key, value, 1) == 0 else { 23| 0| throw SystemError.setenv(errno, key) 24| 0| } 25| 0|} 26| | 27| 0|public func unsetenv(_ key: String) throws { 28| 0| guard SPMLibc.unsetenv(key) == 0 else { 29| 0| throw SystemError.unsetenv(errno, key) 30| 0| } 31| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/exit.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| | 13| 0|public func exit(_ status: Int32) -> Never { 14| 0| SPMLibc.exit(status) 15| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/getcwd.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import func SPMLibc.getcwd 12| |import func SPMLibc.free 13| |import func SPMLibc.exit 14| |import func SPMLibc.fputs 15| |import var SPMLibc.PATH_MAX 16| |import var SPMLibc.stderr 17| |import var SPMLibc.errno 18| | 19| |/** 20| | - Returns: The absolute pathname of the current working directory. 21| | - Note: If the current directory does not exist, aborts program, 22| | to deal with this you should `opendir(getcwd())` as soon as your 23| | program starts and then not `chdir()`, `chdir` is an anti-pattern 24| | in tooling anyway. 25| | - Warning: As a result of the above note use of POSIX demands that 26| | the working directory not change during execution. This requires 27| | you to have control over the purity of your dependencies. 28| |*/ 29| 0|public func getcwd() -> String { 30| 0| 31| 0| func error() -> Never { 32| 0| fputs("error: no current directory\n", SPMLibc.stderr) 33| 0| SPMLibc.exit(2) 34| 0| } 35| 0| 36| 0| let cwd = SPMLibc.getcwd(nil, Int(PATH_MAX)) 37| 0| if cwd == nil { error() } 38| 0| defer { free(cwd) } 39| 0| guard let path = String(validatingUTF8: cwd!) else { error() } 40| 0| return path 41| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/isatty.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import func SPMLibc.isatty 12| | 13| 0|public func isatty(_ fildes: Int32) -> Bool { 14| 0| return SPMLibc.isatty(fildes) != 0 15| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/readdir.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| | 13| |extension dirent { 14| | /// Get the directory name. 15| | /// 16| | /// This returns nil if the name is not valid UTF8. 17| 0| public var name: String? { 18| 0| var d_name = self.d_name 19| 0| return withUnsafePointer(to: &d_name) { 20| 0| String(validatingUTF8: UnsafeRawPointer($0).assumingMemoryBound(to: CChar.self)) 21| 0| } 22| 0| } 23| |} 24| | 25| |// Re-export the typealias, for portability. 26| |public typealias dirent = SPMLibc.dirent /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/realpath.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import var SPMLibc.errno 12| |import func SPMLibc.free 13| |import func SPMLibc.realpath 14| | 15| |/** 16| | Resolves all symbolic links, extra "/" characters, and references to /./ 17| | and /../ in the input. 18| | 19| | Resolves both absolute and relative paths and return the absolute 20| | pathname. All components in the provided input must exist when realpath() 21| | is called. 22| |*/ 23| 0|public func realpath(_ path: String) throws -> String { 24| 0| let rv = realpath(path, nil) 25| 0| guard rv != nil else { throw SystemError.realpath(errno, path) } 26| 0| defer { free(rv) } 27| 0| guard let rvv = String(validatingUTF8: rv!) else { throw SystemError.realpath(-1, path) } 28| 0| return rvv 29| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/rename.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import var SPMLibc.errno 12| |import func SPMLibc.rename 13| | 14| 0|public func rename(old: String, new: String) throws { 15| 0| let rv = SPMLibc.rename(old, new) 16| 0| guard rv == 0 else { throw SystemError.rename(errno, old: old, new: new) } 17| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/stat.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| | 13| |/// File system information for a particular file. 14| |public struct FileInfo: Equatable, Codable { 15| | 16| | /// File timestamp wrapper. 17| | public struct FileTimestamp: Equatable, Codable { 18| | public let seconds: UInt64 19| | public let nanoseconds: UInt64 20| | } 21| | 22| | /// File system entity kind. 23| | public enum Kind { 24| | case file, directory, symlink, blockdev, chardev, socket, unknown 25| | 26| 0| fileprivate init(mode: mode_t) { 27| 0| switch mode { 28| 0| case S_IFREG: self = .file 29| 0| case S_IFDIR: self = .directory 30| 0| case S_IFLNK: self = .symlink 31| 0| case S_IFBLK: self = .blockdev 32| 0| case S_IFCHR: self = .chardev 33| 0| case S_IFSOCK: self = .socket 34| 0| default: 35| 0| self = .unknown 36| 0| } 37| 0| } 38| | } 39| | 40| | /// The device number. 41| | public let device: UInt64 42| | 43| | /// The inode number. 44| | public let inode: UInt64 45| | 46| | /// The mode flags of the file. 47| | public let mode: UInt64 48| | 49| | /// The size of the file. 50| | public let size: UInt64 51| | 52| | /// The modification time of the file. 53| | public let modTime: FileTimestamp 54| | 55| | /// Kind of file system entity. 56| 0| public var kind: Kind { 57| 0| return Kind(mode: mode_t(mode) & S_IFMT) 58| 0| } 59| | 60| 0| public init(_ buf: SPMLibc.stat) { 61| 0| self.device = UInt64(buf.st_dev) 62| 0| self.inode = UInt64(buf.st_ino) 63| 0| self.mode = UInt64(buf.st_mode) 64| 0| self.size = UInt64(buf.st_size) 65| 0| 66| 0| #if os(macOS) 67| 0| let seconds = buf.st_mtimespec.tv_sec 68| 0| let nanoseconds = buf.st_mtimespec.tv_nsec 69| 0| #else 70| 0| let seconds = buf.st_mtim.tv_sec 71| 0| let nanoseconds = buf.st_mtim.tv_nsec 72| 0| #endif 73| 0| 74| 0| self.modTime = FileTimestamp( 75| 0| seconds: UInt64(seconds), nanoseconds: UInt64(nanoseconds)) 76| 0| } 77| |} 78| | 79| 0|public func stat(_ path: String) throws -> SPMLibc.stat { 80| 0| var sbuf = SPMLibc.stat() 81| 0| let rv = stat(path, &sbuf) 82| 0| guard rv == 0 else { throw SystemError.stat(errno, path) } 83| 0| return sbuf 84| 0|} 85| | 86| 0|public func lstat(_ path: String) throws -> SPMLibc.stat { 87| 0| var sbuf = SPMLibc.stat() 88| 0| let rv = lstat(path, &sbuf) 89| 0| guard rv == 0 else { throw SystemError.stat(errno, path) } 90| 0| return sbuf 91| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/POSIX/usleep.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| | 13| |/// Suspends execution of the calling thread for the provided microseconds. 14| 0|public func usleep(microSeconds: Int) throws { 15| 0| let rv = usleep(useconds_t(microSeconds)) 16| 0| guard rv == 0 else { throw SystemError.usleep(errno) } 17| 0|} <<<<<< EOF # path=InternalTests.xctest.coverage.txt 1| |import XCTest 2| |import Basic 3| |@testable import SPMUtility 4| |@testable import CommandRegistry 5| | 6| |class RegistryTests: XCTestCase { 7| | 8| 1| func testParserUsage() { 9| 1| let register = CommandRegistry(usage: "usage", overview: "overview") 10| 1| XCTAssertEqual(register.parser.usage, "usage") 11| 1| } 12| | 13| 1| func testParserOverview() { 14| 1| let register = CommandRegistry(usage: "usage", overview: "overview") 15| 1| XCTAssertEqual(register.parser.overview, "overview") 16| 1| } 17| | 18| 1| func testPrintUsage() { 19| 1| let stream = BufferedOutputByteStream() 20| 1| let register = CommandRegistry(usage: "usage", overview: "overview", toolname: "mytool") 21| 1| register.parser.printUsage(on: stream) 22| 1| let expectation = """ 23| 1| OVERVIEW: overview 24| 1| 25| 1| USAGE: mytool usage 26| 1| 27| 1| """ 28| 1| XCTAssertEqual(stream.bytes.description, expectation) 29| 1| } 30| | 31| |} <<<<<< EOF # path=PackageGraph.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/DependencyResolver.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import struct SPMUtility.Version 13| |import class Foundation.NSDate 14| | 15| |public enum DependencyResolverError: Error, Equatable, CustomStringConvertible { 16| | /// The resolver was unable to find a solution to the input constraints. 17| | case unsatisfiable 18| | 19| | /// The resolver found a dependency cycle. 20| | case cycle(AnyPackageContainerIdentifier) 21| | 22| | /// The resolver encountered a versioned container which has a revision dependency. 23| | case incompatibleConstraints( 24| | dependency: (AnyPackageContainerIdentifier, String), 25| | revisions: [(AnyPackageContainerIdentifier, String)]) 26| | 27| 0| public static func == (lhs: DependencyResolverError, rhs: DependencyResolverError) -> Bool { 28| 0| switch (lhs, rhs) { 29| 0| case (.unsatisfiable, .unsatisfiable): 30| 0| return true 31| 0| case (.unsatisfiable, _): 32| 0| return false 33| 0| case (.cycle(let lhs), .cycle(let rhs)): 34| 0| return lhs == rhs 35| 0| case (.cycle, _): 36| 0| return false 37| 0| case (.incompatibleConstraints(let lDependency, let lRevisions), 38| 0| .incompatibleConstraints(let rDependency, let rRevisions)): 39| 0| return lDependency == rDependency && lRevisions == rRevisions 40| 0| case (.incompatibleConstraints, _): 41| 0| return false 42| 0| } 43| 0| } 44| | 45| 0| public var description: String { 46| 0| switch self { 47| 0| case .unsatisfiable: 48| 0| return "unable to resolve dependencies" 49| 0| case .cycle(let package): 50| 0| return "the package \(package.identifier) depends on itself" 51| 0| case let .incompatibleConstraints(dependency, revisions): 52| 0| let stream = BufferedOutputByteStream() 53| 0| stream <<< "the package \(dependency.0.identifier) @ \(dependency.1) contains incompatible dependencies:\n" 54| 0| for (i, revision) in revisions.enumerated() { 55| 0| stream <<< " " 56| 0| stream <<< "\(revision.0.identifier)" <<< " @ " <<< revision.1 57| 0| if i != revisions.count - 1 { 58| 0| stream <<< "\n" 59| 0| } 60| 0| } 61| 0| return stream.bytes.description 62| 0| } 63| 0| } 64| |} 65| | 66| |/// An abstract definition for a set of versions. 67| |public enum VersionSetSpecifier: Hashable, CustomStringConvertible { 68| | /// The universal set. 69| | case any 70| | 71| | /// The empty set. 72| | case empty 73| | 74| | /// A non-empty range of version. 75| | case range(Range) 76| | 77| | /// The exact version that is required. 78| | case exact(Version) 79| | 80| | /// Compute the intersection of two set specifiers. 81| 0| public func intersection(_ rhs: VersionSetSpecifier) -> VersionSetSpecifier { 82| 0| switch (self, rhs) { 83| 0| case (.any, _): 84| 0| return rhs 85| 0| case (_, .any): 86| 0| return self 87| 0| case (.empty, _): 88| 0| return .empty 89| 0| case (_, .empty): 90| 0| return .empty 91| 0| case (.range(let lhs), .range(let rhs)): 92| 0| let start = Swift.max(lhs.lowerBound, rhs.lowerBound) 93| 0| let end = Swift.min(lhs.upperBound, rhs.upperBound) 94| 0| if start < end { 95| 0| return .range(start.. Bool { 114| 0| switch self { 115| 0| case .empty: 116| 0| return false 117| 0| case .range(let range): 118| 0| return range.contains(version: version) 119| 0| case .any: 120| 0| return true 121| 0| case .exact(let v): 122| 0| return v == version 123| 0| } 124| 0| } 125| | 126| 0| public var description: String { 127| 0| switch self { 128| 0| case .any: 129| 0| return "any" 130| 0| case .empty: 131| 0| return "empty" 132| 0| case .range(let range): 133| 0| var upperBound = range.upperBound 134| 0| // Patch the version range representation. This shouldn't be 135| 0| // required once we have custom version range structure. 136| 0| if upperBound.minor == .max && upperBound.patch == .max { 137| 0| upperBound = Version(upperBound.major + 1, 0, 0) 138| 0| } 139| 0| if upperBound.minor != .max && upperBound.patch == .max { 140| 0| upperBound = Version(upperBound.major, upperBound.minor + 1, 0) 141| 0| } 142| 0| return range.lowerBound.description + "..<" + upperBound.description 143| 0| case .exact(let version): 144| 0| return version.description 145| 0| } 146| 0| } 147| |} 148| | 149| |/// A requirement that a package must satisfy. 150| |public enum PackageRequirement: Hashable { 151| | 152| | /// The requirement is specified by the version set. 153| | case versionSet(VersionSetSpecifier) 154| | 155| | /// The requirement is specified by the revision. 156| | /// 157| | /// The revision string (identifier) should be valid and present in the 158| | /// container. Only one revision requirement per container is possible 159| | /// i.e. two revision requirements for same container will lead to 160| | /// unsatisfiable resolution. The revision requirement can either come 161| | /// from initial set of constraints or from dependencies of a revision 162| | /// requirement. 163| | case revision(String) 164| | 165| | /// Un-versioned requirement i.e. a version should not resolved. 166| | case unversioned 167| | 168| | /// Returns if this requirement pins to an exact version, e.g. a specific 169| | /// version or a revision. 170| 0| public var isExact: Bool { 171| 0| switch self { 172| 0| case .versionSet(let vs): 173| 0| if case .exact = vs { 174| 0| return true 175| 0| } 176| 0| return false 177| 0| case .revision: 178| 0| return true 179| 0| case .unversioned: 180| 0| return false 181| 0| } 182| 0| } 183| |} 184| | 185| |/// An identifier which unambiguously references a package container. 186| |/// 187| |/// This identifier is used to abstractly refer to another container when 188| |/// encoding dependencies across packages. 189| |public protocol PackageContainerIdentifier: Hashable { } 190| | 191| |/// A type-erased package container identifier. 192| |public struct AnyPackageContainerIdentifier: PackageContainerIdentifier { 193| | 194| | /// The underlying identifier, represented as AnyHashable. 195| | public let identifier: AnyHashable 196| | 197| | /// Creates a type-erased identifier that wraps up the given instance. 198| 0| init(_ identifier: T) { 199| 0| self.identifier = AnyHashable(identifier) 200| 0| } 201| |} 202| | 203| |/// A container of packages. 204| |/// 205| |/// This is the top-level unit of package resolution, i.e. the unit at which 206| |/// versions are associated. 207| |/// 208| |/// It represents a package container (e.g., a source repository) which can be 209| |/// identified unambiguously and which contains a set of available package 210| |/// versions and the ability to retrieve the dependency constraints for each of 211| |/// those versions. 212| |/// 213| |/// We use the "container" terminology here to differentiate between two 214| |/// conceptual notions of what the package is: (1) informally, the repository 215| |/// containing the package, but from which a package cannot be loaded by itself 216| |/// and (2) the repository at a particular version, at which point the package 217| |/// can be loaded and dependencies enumerated. 218| |/// 219| |/// This is also designed in such a way to extend naturally to multiple packages 220| |/// being contained within a single repository, should we choose to support that 221| |/// later. 222| |public protocol PackageContainer { 223| | /// The type of packages contained. 224| | associatedtype Identifier: PackageContainerIdentifier 225| | 226| | /// The identifier for the package. 227| | var identifier: Identifier { get } 228| | 229| | /// Get the list of versions which are available for the package. 230| | /// 231| | /// The list will be returned in sorted order, with the latest version *first*. 232| | /// All versions will not be requested at once. Resolver will request the next one only 233| | /// if the previous one did not satisfy all constraints. 234| | func versions(filter isIncluded: (Version) -> Bool) -> AnySequence 235| | 236| | // FIXME: We should perhaps define some particularly useful error codes 237| | // here, so the resolver can handle errors more meaningfully. 238| | // 239| | /// Fetch the declared dependencies for a particular version. 240| | /// 241| | /// This property is expected to be efficient to access, and cached by the 242| | /// client if necessary. 243| | /// 244| | /// - Precondition: `versions.contains(version)` 245| | /// - Throws: If the version could not be resolved; this will abort 246| | /// dependency resolution completely. 247| | func getDependencies(at version: Version) throws -> [PackageContainerConstraint] 248| | 249| | /// Fetch the declared dependencies for a particular revision. 250| | /// 251| | /// This property is expected to be efficient to access, and cached by the 252| | /// client if necessary. 253| | /// 254| | /// - Throws: If the revision could not be resolved; this will abort 255| | /// dependency resolution completely. 256| | func getDependencies(at revision: String) throws -> [PackageContainerConstraint] 257| | 258| | /// Fetch the dependencies of an unversioned package container. 259| | /// 260| | /// NOTE: This method should not be called on a versioned container. 261| | func getUnversionedDependencies() throws -> [PackageContainerConstraint] 262| | 263| | /// Get the updated identifier at a bound version. 264| | /// 265| | /// This can be used by the containers to fill in the missing information that is obtained 266| | /// after the container is available. The updated identifier is returned in result of the 267| | /// dependency resolution. 268| | func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> Identifier 269| |} 270| | 271| |/// An interface for resolving package containers. 272| |public protocol PackageContainerProvider { 273| | associatedtype Container: PackageContainer 274| | 275| | /// Get the container for a particular identifier asynchronously. 276| | func getContainer( 277| | for identifier: Container.Identifier, 278| | skipUpdate: Bool, 279| | completion: @escaping (Result) -> Void 280| | ) 281| |} 282| | 283| |/// An individual constraint onto a container. 284| |public struct PackageContainerConstraint: CustomStringConvertible, Equatable { 285| | public typealias Identifier = T 286| | 287| | /// The identifier for the container the constraint is on. 288| | public let identifier: Identifier 289| | 290| | /// The constraint requirement. 291| | public let requirement: PackageRequirement 292| | 293| | /// Create a constraint requiring the given `container` satisfying the 294| | /// `requirement`. 295| 0| public init(container identifier: Identifier, requirement: PackageRequirement) { 296| 0| self.identifier = identifier 297| 0| self.requirement = requirement 298| 0| } 299| | 300| | /// Create a constraint requiring the given `container` satisfying the 301| | /// `versionRequirement`. 302| 0| public init(container identifier: Identifier, versionRequirement: VersionSetSpecifier) { 303| 0| self.init(container: identifier, requirement: .versionSet(versionRequirement)) 304| 0| } 305| | 306| 0| public var description: String { 307| 0| return "Constraint(\(identifier), \(requirement))" 308| 0| } 309| |} 310| | 311| |/// Delegate interface for dependency resoler status. 312| |public protocol DependencyResolverDelegate { 313| | associatedtype Identifier: PackageContainerIdentifier 314| | 315| | /// Collect diagnostic information for a step the resolver takes. 316| | func trace(_ step: TraceStep) 317| |} 318| | 319| |public extension DependencyResolverDelegate { 320| 0| func trace(_ step: TraceStep) { } 321| |} 322| | 323| |// FIXME: This should be nested, but cannot be currently. 324| |// 325| |/// A bound version for a package within an assignment. 326| |public enum BoundVersion: Equatable, CustomStringConvertible { 327| | /// The assignment should not include the package. 328| | /// 329| | /// This is different from the absence of an assignment for a particular 330| | /// package, which only indicates the assignment is agnostic to its 331| | /// version. This value signifies the package *may not* be present. 332| | case excluded 333| | 334| | /// The version of the package to include. 335| | case version(Version) 336| | 337| | /// The package assignment is unversioned. 338| | case unversioned 339| | 340| | /// The package assignment is this revision. 341| | case revision(String) 342| | 343| 0| public var description: String { 344| 0| switch self { 345| 0| case .excluded: 346| 0| return "excluded" 347| 0| case .version(let version): 348| 0| return version.description 349| 0| case .unversioned: 350| 0| return "unversioned" 351| 0| case .revision(let identifier): 352| 0| return identifier 353| 0| } 354| 0| } 355| |} 356| | 357| |// FIXME: Maybe each package should just return this, instead of a list of 358| |// `PackageContainerConstraint`s. That won't work if we decide this should 359| |// eventually map based on the `Container` rather than the `Identifier`, though, 360| |// so they are separate for now. 361| |// 362| |/// A container for constraints for a set of packages. 363| |/// 364| |/// This data structure is only designed to represent satisfiable constraint 365| |/// sets, it cannot represent sets including containers which have an empty 366| |/// constraint. 367| |public struct PackageContainerConstraintSet: Collection, Hashable { 368| | public typealias Container = C 369| | public typealias Identifier = Container.Identifier 370| | public typealias Requirement = PackageRequirement 371| | 372| | public typealias Index = Dictionary.Index 373| | public typealias Element = Dictionary.Element 374| | 375| | /// The set of constraints. 376| | private var constraints: [Identifier: Requirement] 377| | 378| | /// Create an empty constraint set. 379| 0| public init() { 380| 0| self.constraints = [:] 381| 0| } 382| | 383| | /// Create an constraint set from known values. 384| | /// 385| | /// The initial constraints should never be unsatisfiable. 386| 0| init(_ constraints: [Identifier: Requirement]) { 387| 0| assert(constraints.values.filter({ $0 == .versionSet(.empty) }).isEmpty) 388| 0| self.constraints = constraints 389| 0| } 390| | 391| | /// The list of containers with entries in the set. 392| 0| var containerIdentifiers: AnySequence { 393| 0| return AnySequence(constraints.keys) 394| 0| } 395| | 396| | /// Get the version set specifier associated with the given package `identifier`. 397| 0| public subscript(identifier: Identifier) -> Requirement { 398| 0| return constraints[identifier] ?? .versionSet(.any) 399| 0| } 400| | 401| | /// Create a constraint set by merging the `requirement` for container `identifier`. 402| | /// 403| | /// - Returns: The new set, or nil the resulting set is unsatisfiable. 404| | private func merging( 405| | requirement: Requirement, for identifier: Identifier 406| 0| ) -> PackageContainerConstraintSet? { 407| 0| switch (requirement, self[identifier]) { 408| 0| case (.versionSet(let newSet), .versionSet(let currentSet)): 409| 0| // Try to intersect two version set requirements. 410| 0| let intersection = currentSet.intersection(newSet) 411| 0| if intersection == .empty { 412| 0| return nil 413| 0| } 414| 0| var result = self 415| 0| result.constraints[identifier] = .versionSet(intersection) 416| 0| return result 417| 0| 418| 0| case (.unversioned, .unversioned): 419| 0| return self 420| 0| 421| 0| case (.unversioned, _): 422| 0| // Unversioned requirements always *wins*. 423| 0| var result = self 424| 0| result.constraints[identifier] = requirement 425| 0| return result 426| 0| 427| 0| case (_, .unversioned): 428| 0| // Unversioned requirements always *wins*. 429| 0| return self 430| 0| 431| 0| // The revision cases are deliberately placed below the unversioned 432| 0| // cases because unversioned has more priority. 433| 0| case (.revision(let lhs), .revision(let rhs)): 434| 0| // We can merge two revisions if they have the same identifier. 435| 0| if lhs == rhs { return self } 436| 0| return nil 437| 0| 438| 0| // We can merge the revision requiement if it currently does not have a requirement. 439| 0| case (.revision, .versionSet(.any)): 440| 0| var result = self 441| 0| result.constraints[identifier] = requirement 442| 0| return result 443| 0| 444| 0| // Otherwise, we can't merge the revision requirement. 445| 0| case (.revision, _): 446| 0| return nil 447| 0| 448| 0| // Exisiting revision requirements always *wins*. 449| 0| case (_, .revision): 450| 0| return self 451| 0| } 452| 0| } 453| | 454| | /// Create a constraint set by merging `constraint`. 455| | /// 456| | /// - Returns: The new set, or nil the resulting set is unsatisfiable. 457| 0| public func merging(_ constraint: PackageContainerConstraint) -> PackageContainerConstraintSet? { 458| 0| return merging(requirement: constraint.requirement, for: constraint.identifier) 459| 0| } 460| | 461| | /// Create a new constraint set by merging the given constraint set. 462| | /// 463| | /// - Returns: False if the merger has made the set unsatisfiable; i.e. true 464| | /// when the resulting set is satisfiable, if it was already so. 465| | func merging( 466| | _ constraints: PackageContainerConstraintSet 467| 0| ) -> PackageContainerConstraintSet? { 468| 0| var result = self 469| 0| for (key, requirement) in constraints { 470| 0| guard let merged = result.merging(requirement: requirement, for: key) else { 471| 0| return nil 472| 0| } 473| 0| result = merged 474| 0| } 475| 0| return result 476| 0| } 477| | 478| | // MARK: Collection Conformance 479| | 480| 0| public var startIndex: Index { 481| 0| return constraints.startIndex 482| 0| } 483| | 484| 0| public var endIndex: Index { 485| 0| return constraints.endIndex 486| 0| } 487| | 488| 0| public func index(after index: Index) -> Index { 489| 0| return constraints.index(after: index) 490| 0| } 491| | 492| 0| public subscript(position: Index) -> Element { 493| 0| return constraints[position] 494| 0| } 495| |} 496| | 497| |// FIXME: Actually make efficient. 498| |// 499| |/// A container for version assignments for a set of packages, exposed as a 500| |/// sequence of `Container` to `BoundVersion` bindings. 501| |/// 502| |/// This is intended to be an efficient data structure for accumulating a set of 503| |/// version assignments along with efficient access to the derived information 504| |/// about the assignment (for example, the unified set of constraints it 505| |/// induces). 506| |/// 507| |/// The set itself is designed to only ever contain a consistent set of 508| |/// assignments, i.e. each assignment should satisfy the induced 509| |/// `constraints`, but this invariant is not explicitly enforced. 510| |struct VersionAssignmentSet: Equatable, Sequence { 511| | typealias Container = C 512| | typealias Identifier = Container.Identifier 513| | 514| | // FIXME: Does it really make sense to key on the identifier here. Should we 515| | // require referential equality of containers and use that to simplify? 516| | // 517| | /// The assignment records. 518| | fileprivate var assignments: OrderedDictionary 519| | 520| | /// Create an empty assignment. 521| 0| init() { 522| 0| assignments = [:] 523| 0| } 524| | 525| | /// The assignment for the given container `identifier. 526| | subscript(identifier: Identifier) -> BoundVersion? { 527| 0| get { 528| 0| return assignments[identifier]?.binding 529| 0| } 530| | } 531| | 532| | /// The assignment for the given `container`. 533| | subscript(container: Container) -> BoundVersion? { 534| 0| get { 535| 0| return self[container.identifier] 536| 0| } 537| 0| set { 538| 0| // We disallow deletion. 539| 0| let newBinding = newValue! 540| 0| 541| 0| // Validate this is a valid assignment. 542| 0| assert(isValid(binding: newBinding, for: container)) 543| 0| 544| 0| assignments[container.identifier] = (container: container, binding: newBinding) 545| 0| } 546| | } 547| | 548| | /// Create a new assignment set by merging in the bindings from `assignment`. 549| | /// 550| | /// - Returns: The new assignment, or nil if the merge cannot be made (the 551| | /// assignments contain incompatible versions). 552| 0| func merging(_ assignment: VersionAssignmentSet) -> VersionAssignmentSet? { 553| 0| // In order to protect the assignment set, we first have to test whether 554| 0| // the merged constraint sets are satisfiable. 555| 0| // 556| 0| // FIXME: This is very inefficient; we should decide whether it is right 557| 0| // to handle it here or force the main resolver loop to handle the 558| 0| // discovery of this property. 559| 0| guard constraints.merging(assignment.constraints) != nil else { 560| 0| return nil 561| 0| } 562| 0| 563| 0| // The induced constraints are satisfiable, so we *can* union the 564| 0| // assignments without breaking our internal invariant on 565| 0| // satisfiability. 566| 0| var result = self 567| 0| for (container, binding) in assignment { 568| 0| if let existing = result[container] { 569| 0| if existing != binding { 570| 0| return nil 571| 0| } 572| 0| } else { 573| 0| result[container] = binding 574| 0| } 575| 0| } 576| 0| 577| 0| return result 578| 0| } 579| | 580| | // FIXME: We need to cache this. 581| | // 582| | /// The combined version constraints induced by the assignment. 583| | /// 584| | /// This consists of the merged constraints which need to be satisfied on 585| | /// each package as a result of the versions selected in the assignment. 586| | /// 587| | /// The resulting constraint set is guaranteed to be non-empty for each 588| | /// mapping, assuming the invariants on the set are followed. 589| 0| var constraints: PackageContainerConstraintSet { 590| 0| // Collect all of the constraints. 591| 0| var result = PackageContainerConstraintSet() 592| 0| 593| 0| /// Merge the provided constraints into result. 594| 0| func merge(constraints: [PackageContainerConstraint]) { 595| 0| for constraint in constraints { 596| 0| guard let merged = result.merging(constraint) else { 597| 0| preconditionFailure("unsatisfiable constraint set") 598| 0| } 599| 0| result = merged 600| 0| } 601| 0| } 602| 0| 603| 0| for (_, (container: container, binding: binding)) in assignments { 604| 0| switch binding { 605| 0| case .unversioned, .excluded: 606| 0| // If the package is unversioned or excluded, it doesn't contribute. 607| 0| continue 608| 0| 609| 0| case .revision(let identifier): 610| 0| // FIXME: Need caching and error handling here. See the FIXME below. 611| 0| merge(constraints: try! container.getDependencies(at: identifier)) 612| 0| 613| 0| case .version(let version): 614| 0| // If we have a version, add the constraints from that package version. 615| 0| // 616| 0| // FIXME: We should cache this too, possibly at a layer 617| 0| // different than above (like the entry record). 618| 0| // 619| 0| // FIXME: Error handling, except that we probably shouldn't have 620| 0| // needed to refetch the dependencies at this point. 621| 0| merge(constraints: try! container.getDependencies(at: version)) 622| 0| } 623| 0| } 624| 0| return result 625| 0| } 626| | 627| | // FIXME: This is currently very inefficient. 628| | // 629| | /// Check if the given `binding` for `container` is valid within the assignment. 630| 0| func isValid(binding: BoundVersion, for container: Container) -> Bool { 631| 0| switch binding { 632| 0| case .excluded: 633| 0| // A package can be excluded if there are no constraints on the 634| 0| // package (it has not been requested by any other package in the 635| 0| // assignment). 636| 0| return constraints[container.identifier] == .versionSet(.any) 637| 0| 638| 0| case .version(let version): 639| 0| // A version is valid if it is contained in the constraints. 640| 0| if case .versionSet(let versionSet) = constraints[container.identifier] { 641| 0| return versionSet.contains(version) 642| 0| } 643| 0| return false 644| 0| 645| 0| case .revision(let identifier): 646| 0| // If we already have a revision constraint, it should be same as 647| 0| // the one we're trying to set. 648| 0| if case .revision(let existingRevision) = constraints[container.identifier] { 649| 0| return existingRevision == identifier 650| 0| } 651| 0| // Otherwise, it is always valid to set a revision binding. Note 652| 0| // that there are rules that prevents versioned constraints from 653| 0| // having revision constraints, but that is handled by the resolver. 654| 0| return true 655| 0| 656| 0| case .unversioned: 657| 0| // An unversioned binding is always valid. 658| 0| return true 659| 0| } 660| 0| } 661| | 662| | /// Check if the assignment is valid and complete. 663| 0| func checkIfValidAndComplete() -> Bool { 664| 0| // Validity should hold trivially, because it is an invariant of the collection. 665| 0| for (_, assignment) in assignments { 666| 0| if !isValid(binding: assignment.binding, for: assignment.container) { 667| 0| return false 668| 0| } 669| 0| } 670| 0| 671| 0| // Check completeness, by simply looking at all the entries in the induced constraints. 672| 0| for identifier in constraints.containerIdentifiers { 673| 0| // Verify we have a non-excluded entry for this key. 674| 0| switch assignments[identifier]?.binding { 675| 0| case .unversioned?, .version?, .revision?: 676| 0| continue 677| 0| case .excluded?, nil: 678| 0| return false 679| 0| } 680| 0| } 681| 0| 682| 0| return true 683| 0| } 684| | 685| | // MARK: Sequence Conformance 686| | 687| | // FIXME: This should really be a collection, but that takes significantly 688| | // more work given our current backing collection. 689| | 690| | typealias Iterator = AnyIterator<(Container, BoundVersion)> 691| | 692| 0| func makeIterator() -> Iterator { 693| 0| var it = assignments.makeIterator() 694| 0| return AnyIterator { 695| 0| if let (_, next) = it.next() { 696| 0| return (next.container, next.binding) 697| 0| } else { 698| 0| return nil 699| 0| } 700| 0| } 701| 0| } 702| |} 703| | 704| 0|func == (lhs: VersionAssignmentSet, rhs: VersionAssignmentSet) -> Bool { 705| 0| if lhs.assignments.count != rhs.assignments.count { return false } 706| 0| for (container, lhsBinding) in lhs { 707| 0| switch rhs[container] { 708| 0| case let rhsBinding? where lhsBinding == rhsBinding: 709| 0| continue 710| 0| default: 711| 0| return false 712| 0| } 713| 0| } 714| 0| return true 715| 0|} 716| | 717| |/// A general purpose package dependency resolver. 718| |/// 719| |/// This is a general purpose solver for the problem of: 720| |/// 721| |/// Given an input list of constraints, where each constraint identifies a 722| |/// container and version requirements, and, where each container supplies a 723| |/// list of additional constraints ("dependencies") for an individual version, 724| |/// then, choose an assignment of containers to versions such that: 725| |/// 726| |/// 1. The assignment is complete: there exists an assignment for each container 727| |/// listed in the union of the input constraint list and the dependency list for 728| |/// every container in the assignment at the assigned version. 729| |/// 730| |/// 2. The assignment is correct: the assigned version satisfies each constraint 731| |/// referencing its matching container. 732| |/// 733| |/// 3. The assignment is maximal: there is no other assignment satisfying #1 and 734| |/// #2 such that all assigned version are greater than or equal to the versions 735| |/// assigned in the result. 736| |/// 737| |/// NOTE: It does not follow from #3 that this solver attempts to give an 738| |/// "optimal" result. There may be many possible solutions satisfying #1, #2, 739| |/// and #3, and optimality requires additional information (e.g. a 740| |/// prioritization among packages). 741| |/// 742| |/// As described, this problem is NP-complete (*). This solver currently 743| |/// implements a basic depth-first greedy backtracking algorithm, and honoring 744| |/// the order of dependencies as specified in the manifest file. The solver uses 745| |/// persistent data structures to manage the accumulation of state along the 746| |/// traversal, so the backtracking is not explicit, rather it is an implicit 747| |/// side effect of the underlying copy-on-write data structures. 748| |/// 749| |/// The resolver will always merge the complete set of immediate constraints for 750| |/// a package (i.e., the version ranges of its immediate dependencies) into the 751| |/// constraint set *before* traversing into any dependency. This property allows 752| |/// packages to manually work around performance issues in the resolution 753| |/// algorithm by _lifting_ problematic dependency constraints up to be immediate 754| |/// dependencies. 755| |/// 756| |/// There is currently no external control offered by the solver over _which_ 757| |/// solution satisfying the properties above is selected, if more than one are 758| |/// possible. In practice, the algorithm is designed such that it will 759| |/// effectively prefer (i.e., optimize for the newest version of) dependencies 760| |/// which are earliest in the depth-first, pre-order, traversal. 761| |/// 762| |/// (*) Via reduction from 3-SAT: Introduce a package for each variable, with 763| |/// two versions representing true and false. For each clause `C_n`, introduce a 764| |/// package `P(C_n)` representing the clause, with three versions; one for each 765| |/// satisfying assignment of values to a literal with the corresponding precise 766| |/// constraint on the input packages. Finally, construct an input constraint 767| |/// list including a dependency on each clause package `P(C_n)` and an 768| |/// open-ended version constraint. The given input is satisfiable iff the input 769| |/// 3-SAT instance is. 770| |public class DependencyResolver< 771| | P: PackageContainerProvider, 772| | D: DependencyResolverDelegate 773| |> where P.Container.Identifier == D.Identifier { 774| | public typealias Provider = P 775| | public typealias Delegate = D 776| | public typealias Container = Provider.Container 777| | public typealias Identifier = Container.Identifier 778| | public typealias Binding = (container: Identifier, binding: BoundVersion) 779| | 780| | /// The type of the constraints the resolver operates on. 781| | /// 782| | /// Technically this is a container constraint, but that is currently the 783| | /// only kind of constraints we operate on. 784| | public typealias Constraint = PackageContainerConstraint 785| | 786| | /// The type of constraint set the resolver operates on. 787| | typealias ConstraintSet = PackageContainerConstraintSet 788| | 789| | /// The type of assignment the resolver operates on. 790| | typealias AssignmentSet = VersionAssignmentSet 791| | 792| | /// The container provider used to load package containers. 793| | public let provider: Provider 794| | 795| | /// The resolver's delegate. 796| | public let delegate: Delegate? 797| | 798| | /// Should resolver prefetch the containers. 799| | private let isPrefetchingEnabled: Bool 800| | 801| | /// Skip updating containers while fetching them. 802| | private let skipUpdate: Bool 803| | 804| | // FIXME: @testable private 805| | // 806| | /// Contains any error encountered during dependency resolution. 807| | var error: Swift.Error? 808| | 809| | /// Key used to cache a resolved subtree. 810| | private struct ResolveSubtreeCacheKey: Hashable { 811| | let container: Container 812| | let allConstraints: ConstraintSet 813| | 814| 0| func hash(into hasher: inout Hasher) { 815| 0| hasher.combine(container.identifier) 816| 0| hasher.combine(allConstraints) 817| 0| } 818| | 819| 0| static func ==(lhs: ResolveSubtreeCacheKey, rhs: ResolveSubtreeCacheKey) -> Bool { 820| 0| return lhs.container.identifier == rhs.container.identifier && lhs.allConstraints == rhs.allConstraints 821| 0| } 822| | } 823| | 824| | /// Cache for subtree resolutions. 825| | private var _resolveSubtreeCache: [ResolveSubtreeCacheKey: AnySequence] = [:] 826| | 827| | /// Puts the resolver in incomplete mode. 828| | /// 829| | /// In this mode, no new containers will be requested from the provider. 830| | /// Instead, if a container is not already present in the resolver, it will 831| | /// skipped without raising an error. This is useful to avoid cloning 832| | /// repositories from network when trying to partially resolve the constraints. 833| | /// 834| | /// Note that the input constraints will always be fetched. 835| | public var isInIncompleteMode = false 836| | 837| | public init( 838| | _ provider: Provider, 839| | _ delegate: Delegate? = nil, 840| | isPrefetchingEnabled: Bool = false, 841| | skipUpdate: Bool = false 842| 0| ) { 843| 0| self.provider = provider 844| 0| self.delegate = delegate 845| 0| self.isPrefetchingEnabled = isPrefetchingEnabled 846| 0| self.skipUpdate = skipUpdate 847| 0| } 848| | 849| | /// The dependency resolver result. 850| | public enum Result { 851| | /// A valid and complete assignment was found. 852| | case success([Binding]) 853| | 854| | /// The dependency graph was unsatisfiable. 855| | /// 856| | /// The payload may contain conflicting constraints and pins. 857| | /// 858| | /// - parameters: 859| | /// - dependencies: The package dependencies which make the graph unsatisfiable. 860| | /// - pins: The pins which make the graph unsatisfiable. 861| | case unsatisfiable(dependencies: [Constraint], pins: [Constraint]) 862| | 863| | /// The resolver encountered an error during resolution. 864| | case error(Swift.Error) 865| | } 866| | 867| | /// Execute the resolution algorithm to find a valid assignment of versions. 868| | /// 869| | /// If a valid assignment is not found, the resolver will go into incomplete 870| | /// mode and try to find the conflicting constraints. 871| | public func resolve( 872| | dependencies: [Constraint], 873| | pins: [Constraint] 874| 0| ) -> Result { 875| 0| do { 876| 0| // Reset the incomplete mode and run the resolver. 877| 0| self.isInIncompleteMode = false 878| 0| let constraints = dependencies 879| 0| return try .success(resolve(constraints: constraints, pins: pins)) 880| 0| } catch DependencyResolverError.unsatisfiable { 881| 0| // FIXME: can we avoid this do..catch nesting? 882| 0| do { 883| 0| // If the result is unsatisfiable, try to debug. 884| 0| let debugger = ResolverDebugger(self) 885| 0| let badConstraints = try debugger.debug(dependencies: dependencies, pins: pins) 886| 0| return .unsatisfiable(dependencies: badConstraints.dependencies, pins: badConstraints.pins) 887| 0| } catch { 888| 0| return .error(error) 889| 0| } 890| 0| } catch { 891| 0| return .error(error) 892| 0| } 893| 0| } 894| | 895| | /// Execute the resolution algorithm to find a valid assignment of versions. 896| | /// 897| | /// - Parameters: 898| | /// - constraints: The contraints to solve. It is legal to supply multiple 899| | /// constraints for the same container identifier. 900| | /// - Returns: A satisfying assignment of containers and their version binding. 901| | /// - Throws: DependencyResolverError, or errors from the underlying package provider. 902| 0| public func resolve(constraints: [Constraint], pins: [Constraint] = []) throws -> [(container: Identifier, binding: BoundVersion)] { 903| 0| return try resolveAssignment(constraints: constraints, pins: pins).map({ assignment in 904| 0| let (container, binding) = assignment 905| 0| let identifier = try self.isInIncompleteMode ? container.identifier : container.getUpdatedIdentifier(at: binding) 906| 0| // Get the updated identifier from the container. 907| 0| return (identifier, binding) 908| 0| }) 909| 0| } 910| | 911| | /// Execute the resolution algorithm to find a valid assignment of versions. 912| | /// 913| | /// - Parameters: 914| | /// - constraints: The contraints to solve. It is legal to supply multiple 915| | /// constraints for the same container identifier. 916| | /// - Returns: A satisfying assignment of containers and versions. 917| | /// - Throws: DependencyResolverError, or errors from the underlying package provider. 918| 0| func resolveAssignment(constraints: [Constraint], pins: [Constraint] = []) throws -> AssignmentSet { 919| 0| 920| 0| // Create a constraint set with the input pins. 921| 0| var allConstraints = ConstraintSet() 922| 0| for constraint in pins { 923| 0| if let merged = allConstraints.merging(constraint) { 924| 0| allConstraints = merged 925| 0| } else { 926| 0| // FIXME: We should issue a warning if the pins can't be merged 927| 0| // for some reason. 928| 0| } 929| 0| } 930| 0| 931| 0| // Create an assignment for the input constraints. 932| 0| let mergedConstraints = merge( 933| 0| constraints: constraints, 934| 0| into: AssignmentSet(), 935| 0| subjectTo: allConstraints, 936| 0| excluding: [:]) 937| 0| 938| 0| // Prefetch the pins. 939| 0| if !isInIncompleteMode && isPrefetchingEnabled { 940| 0| prefetch(containers: pins.map({ $0.identifier })) 941| 0| } 942| 0| 943| 0| guard let assignment = mergedConstraints.first(where: { _ in true }) else { 944| 0| // Throw any error encountered during resolution. 945| 0| if let error = error { 946| 0| throw error 947| 0| } 948| 0| 949| 0| throw DependencyResolverError.unsatisfiable 950| 0| } 951| 0| 952| 0| return assignment 953| 0| } 954| | 955| | // FIXME: This needs to a way to return information on the failure, or we 956| | // will need to have it call the delegate directly. 957| | // 958| | // FIXME: @testable private 959| | // 960| | /// Resolve an individual container dependency tree. 961| | /// 962| | /// This is the primary method in our bottom-up algorithm for resolving 963| | /// dependencies. The inputs define an active set of constraints and set of 964| | /// versions to exclude (conceptually the latter could be merged with the 965| | /// former, but it is convenient to separate them in our 966| | /// implementation). The result is a sequence of all valid assignments for 967| | /// this container's subtree. 968| | /// 969| | /// - Parameters: 970| | /// - container: The container to resolve. 971| | /// - constraints: The external constraints which must be honored by the solution. 972| | /// - exclusions: The list of individually excluded package versions. 973| | /// - Returns: A sequence of feasible solutions, starting with the most preferable. 974| | func resolveSubtree( 975| | _ container: Container, 976| | subjectTo allConstraints: ConstraintSet, 977| | excluding allExclusions: [Identifier: Set] 978| 0| ) -> AnySequence { 979| 0| // The key that is used to cache this assignement set. 980| 0| let cacheKey = ResolveSubtreeCacheKey(container: container, allConstraints: allConstraints) 981| 0| 982| 0| // Check if we have a cache hit for this subtree resolution. 983| 0| // 984| 0| // Note: We don't include allExclusions in the cache key so we ignore 985| 0| // the cache if its non-empty. 986| 0| // 987| 0| // FIXME: We can improve the cache miss rate here if we have a cached 988| 0| // entry with a broader constraint set. The cached sequence can be 989| 0| // filtered according to the new narrower constraint set. 990| 0| if allExclusions.isEmpty, let assignments = _resolveSubtreeCache[cacheKey] { 991| 0| return assignments 992| 0| } 993| 0| 994| 0| func validVersions(_ container: Container, in versionSet: VersionSetSpecifier) -> AnySequence { 995| 0| let exclusions = allExclusions[container.identifier] ?? Set() 996| 0| return AnySequence(container.versions(filter: { 997| 0| versionSet.contains($0) && !exclusions.contains($0) 998| 0| })) 999| 0| } 1000| 0| 1001| 0| // Helper method to abstract passing common parameters to merge(). 1002| 0| // 1003| 0| // FIXME: We must detect recursion here. 1004| 0| func merge(constraints: [Constraint], binding: BoundVersion) -> AnySequence { 1005| 0| 1006| 0| // Diagnose if this container depends on itself. 1007| 0| if constraints.contains(where: { $0.identifier == container.identifier }) { 1008| 0| error = DependencyResolverError.cycle(AnyPackageContainerIdentifier(container.identifier)) 1009| 0| return AnySequence([]) 1010| 0| } 1011| 0| 1012| 0| // Create an assignment for the container. 1013| 0| var assignment = AssignmentSet() 1014| 0| assignment[container] = binding 1015| 0| 1016| 0| return AnySequence(self.merge( 1017| 0| constraints: constraints, 1018| 0| into: assignment, subjectTo: allConstraints, excluding: allExclusions).lazy.map({ result in 1019| 0| // We might not have a complete result in incomplete mode. 1020| 0| if !self.isInIncompleteMode { 1021| 0| assert(result.checkIfValidAndComplete()) 1022| 0| } 1023| 0| return result 1024| 0| })) 1025| 0| } 1026| 0| 1027| 0| var result: AnySequence 1028| 0| switch allConstraints[container.identifier] { 1029| 0| case .unversioned: 1030| 0| guard let constraints = self.safely({ try container.getUnversionedDependencies() }) else { 1031| 0| return AnySequence([]) 1032| 0| } 1033| 0| // Merge the dependencies of unversioned constraint into the assignment. 1034| 0| result = merge(constraints: constraints, binding: .unversioned) 1035| 0| 1036| 0| case .revision(let identifier): 1037| 0| guard let constraints = self.safely({ try container.getDependencies(at: identifier) }) else { 1038| 0| return AnySequence([]) 1039| 0| } 1040| 0| result = merge(constraints: constraints, binding: .revision(identifier)) 1041| 0| 1042| 0| case .versionSet(let versionSet): 1043| 0| // The previous valid version that was picked. 1044| 0| var previousVersion: Version? = nil 1045| 0| 1046| 0| // Attempt to select each valid version in the preferred order. 1047| 0| result = AnySequence(validVersions(container, in: versionSet).lazy 1048| 0| .flatMap({ version -> AnySequence in 1049| 0| assert(previousVersion != nil ? previousVersion! > version : true, 1050| 0| "container versions are improperly ordered") 1051| 0| previousVersion = version 1052| 0| 1053| 0| // If we had encountered any error, return early. 1054| 0| guard self.error == nil else { return AnySequence([]) } 1055| 0| 1056| 0| // Get the constraints for this container version and update the assignment to include each one. 1057| 0| // FIXME: Making these methods throwing will kill the lazy behavior. 1058| 0| guard var constraints = self.safely({ try container.getDependencies(at: version) }) else { 1059| 0| return AnySequence([]) 1060| 0| } 1061| 0| 1062| 0| // Since we don't want to request additional containers in incomplete 1063| 0| // mode, remove any dependency that we don't already have. 1064| 0| if self.isInIncompleteMode { 1065| 0| constraints = constraints.filter({ self.containers[$0.identifier] != nil }) 1066| 0| } 1067| 0| 1068| 0| // Since this is a versioned container, none of its 1069| 0| // dependencies can have a revision constraints. 1070| 0| let incompatibleConstraints: [(AnyPackageContainerIdentifier, String)] 1071| 0| incompatibleConstraints = constraints.compactMap({ 1072| 0| switch $0.requirement { 1073| 0| case .versionSet: 1074| 0| return nil 1075| 0| case .revision(let revision): 1076| 0| return (AnyPackageContainerIdentifier($0.identifier), revision) 1077| 0| case .unversioned: 1078| 0| // FIXME: Maybe we should have metadata inside unversion to signify 1079| 0| // if its a local or edited dependency. We add edited constraints 1080| 0| // as inputs so it shouldn't really matter because an edited 1081| 0| // requirement can't be specified in the manifest file. 1082| 0| return (AnyPackageContainerIdentifier($0.identifier), "local") 1083| 0| } 1084| 0| }) 1085| 0| // If we have any revision constraints, set the error and abort. 1086| 0| guard incompatibleConstraints.isEmpty else { 1087| 0| self.error = DependencyResolverError.incompatibleConstraints( 1088| 0| dependency: (AnyPackageContainerIdentifier(container.identifier), version.description), 1089| 0| revisions: incompatibleConstraints) 1090| 0| return AnySequence([]) 1091| 0| } 1092| 0| 1093| 0| return merge(constraints: constraints, binding: .version(version)) 1094| 0| })) 1095| 0| } 1096| 0| 1097| 0| if allExclusions.isEmpty { 1098| 0| // Ensure we can cache this sequence. 1099| 0| result = AnySequence(CacheableSequence(result)) 1100| 0| _resolveSubtreeCache[cacheKey] = result 1101| 0| } 1102| 0| return result 1103| 0| } 1104| | 1105| | /// Find all solutions for `constraints` with the results merged into the `assignment`. 1106| | /// 1107| | /// - Parameters: 1108| | /// - constraints: The input list of constraints to solve. 1109| | /// - assignment: The assignment to merge the result into. 1110| | /// - allConstraints: An additional set of constraints on the viable solutions. 1111| | /// - allExclusions: A set of package assignments to exclude from consideration. 1112| | /// - Returns: A sequence of all valid satisfying assignment, in order of preference. 1113| | private func merge( 1114| | constraints: [Constraint], 1115| | into assignment: AssignmentSet, 1116| | subjectTo allConstraints: ConstraintSet, 1117| | excluding allExclusions: [Identifier: Set] 1118| 0| ) -> AnySequence { 1119| 0| var allConstraints = allConstraints 1120| 0| 1121| 0| // Never prefetch when running in incomplete mode. 1122| 0| if !isInIncompleteMode && isPrefetchingEnabled { 1123| 0| prefetch(containers: constraints.map({ $0.identifier })) 1124| 0| } 1125| 0| 1126| 0| // Update the active constraint set to include all active constraints. 1127| 0| // 1128| 0| // We want to put all of these constraints in up front so that we are 1129| 0| // more likely to get back a viable solution. 1130| 0| // 1131| 0| // FIXME: We should have a test for this, probably by adding some kind 1132| 0| // of statistics on the number of backtracks. 1133| 0| for constraint in constraints { 1134| 0| guard let merged = allConstraints.merging(constraint) else { 1135| 0| return AnySequence([]) 1136| 0| } 1137| 0| allConstraints = merged 1138| 0| } 1139| 0| 1140| 0| // Perform an (eager) reduction merging each container into the (lazy) 1141| 0| // sequence of possible assignments. 1142| 0| // 1143| 0| // NOTE: What we are *accumulating* here is a lazy sequence (of 1144| 0| // solutions) satisfying some number of the constraints; the final lazy 1145| 0| // sequence is effectively one which has all of the constraints 1146| 0| // merged. Thus, the reduce itself can be eager since the result is 1147| 0| // lazy. 1148| 0| return AnySequence(constraints 1149| 0| .map({ $0.identifier }) 1150| 0| .reduce(AnySequence([(assignment, allConstraints)]), { 1151| 0| (possibleAssignments, identifier) -> AnySequence<(AssignmentSet, ConstraintSet)> in 1152| 0| // If we had encountered any error, return early. 1153| 0| guard self.error == nil else { return AnySequence([]) } 1154| 0| 1155| 0| // Get the container. 1156| 0| // 1157| 0| // Failures here will immediately abort the solution, although in 1158| 0| // theory one could imagine attempting to find a solution not 1159| 0| // requiring this container. It isn't clear that is something we 1160| 0| // would ever want to handle at this level. 1161| 0| // 1162| 0| // FIXME: Making these methods throwing will kill the lazy behavior, 1163| 0| guard let container = safely({ try getContainer(for: identifier) }) else { 1164| 0| return AnySequence([]) 1165| 0| } 1166| 0| 1167| 0| // Return a new lazy sequence merging all possible subtree solutions into all possible incoming 1168| 0| // assignments. 1169| 0| return AnySequence(possibleAssignments.lazy.flatMap({ value -> AnySequence<(AssignmentSet, ConstraintSet)> in 1170| 0| let (assignment, allConstraints) = value 1171| 0| let subtree = self.resolveSubtree(container, subjectTo: allConstraints, excluding: allExclusions) 1172| 0| return AnySequence(subtree.lazy.compactMap({ subtreeAssignment -> (AssignmentSet, ConstraintSet)? in 1173| 0| // We found a valid subtree assignment, attempt to merge it with the 1174| 0| // current solution. 1175| 0| guard let newAssignment = assignment.merging(subtreeAssignment) else { 1176| 0| // The assignment couldn't be merged with the current 1177| 0| // assignment, or the constraint sets couldn't be merged. 1178| 0| // 1179| 0| // This happens when (a) the subtree has a package overlapping 1180| 0| // with a previous subtree assignment, and (b) the subtrees 1181| 0| // needed to resolve different versions due to constraints not 1182| 0| // present in the top-down constraint set. 1183| 0| return nil 1184| 0| } 1185| 0| 1186| 0| // Update the working assignment and constraint set. 1187| 0| // 1188| 0| // This should always be feasible, because all prior constraints 1189| 0| // were part of the input constraint request (see comment around 1190| 0| // initial `merge` outside the loop). 1191| 0| guard let merged = allConstraints.merging(subtreeAssignment.constraints) else { 1192| 0| preconditionFailure("unsatisfiable constraints while merging subtree") 1193| 0| } 1194| 0| 1195| 0| // We found a valid assignment and updated constraint set. 1196| 0| return (newAssignment, merged) 1197| 0| })) 1198| 0| })) 1199| 0| }) 1200| 0| .lazy 1201| 0| .map({ $0.0 })) 1202| 0| } 1203| | 1204| | /// Executes the body and return the value if the body doesn't throw. 1205| | /// Returns nil if the body throws and save the error. 1206| 0| private func safely(_ body: () throws -> T) -> T? { 1207| 0| do { 1208| 0| return try body() 1209| 0| } catch { 1210| 0| self.error = error 1211| 0| } 1212| 0| return nil 1213| 0| } 1214| | 1215| | // MARK: Container Management 1216| | 1217| | /// Condition for container management structures. 1218| | private let fetchCondition = Condition() 1219| | 1220| | /// The active set of managed containers. 1221| 0| public var containers: [Identifier: Container] { 1222| 0| return fetchCondition.whileLocked({ 1223| 0| _fetchedContainers.spm_flatMapValues({ 1224| 0| try? $0.dematerialize() 1225| 0| }) 1226| 0| }) 1227| 0| } 1228| | 1229| | /// The list of fetched containers. 1230| | private var _fetchedContainers: [Identifier: Basic.Result] = [:] 1231| | 1232| | /// The set of containers requested so far. 1233| | private var _prefetchingContainers: Set = [] 1234| | 1235| | /// Get the container for the given identifier, loading it if necessary. 1236| 0| fileprivate func getContainer(for identifier: Identifier) throws -> Container { 1237| 0| return try fetchCondition.whileLocked { 1238| 0| // Return the cached container, if available. 1239| 0| if let container = _fetchedContainers[identifier] { 1240| 0| return try container.dematerialize() 1241| 0| } 1242| 0| 1243| 0| // If this container is being prefetched, wait for that to complete. 1244| 0| while _prefetchingContainers.contains(identifier) { 1245| 0| fetchCondition.wait() 1246| 0| } 1247| 0| 1248| 0| // The container may now be available in our cache if it was prefetched. 1249| 0| if let container = _fetchedContainers[identifier] { 1250| 0| return try container.dematerialize() 1251| 0| } 1252| 0| 1253| 0| // Otherwise, fetch the container synchronously. 1254| 0| let container = try await { provider.getContainer(for: identifier, skipUpdate: skipUpdate, completion: $0) } 1255| 0| self._fetchedContainers[identifier] = Basic.Result(container) 1256| 0| return container 1257| 0| } 1258| 0| } 1259| | 1260| | /// Starts prefetching the given containers. 1261| 0| private func prefetch(containers identifiers: [Identifier]) { 1262| 0| fetchCondition.whileLocked { 1263| 0| // Process each container. 1264| 0| for identifier in identifiers { 1265| 0| // Skip if we're already have this container or are pre-fetching it. 1266| 0| guard _fetchedContainers[identifier] == nil, 1267| 0| !_prefetchingContainers.contains(identifier) else { 1268| 0| continue 1269| 0| } 1270| 0| 1271| 0| // Otherwise, record that we're prefetching this container. 1272| 0| _prefetchingContainers.insert(identifier) 1273| 0| 1274| 0| provider.getContainer(for: identifier, skipUpdate: skipUpdate) { container in 1275| 0| self.fetchCondition.whileLocked { 1276| 0| // Update the structures and signal any thread waiting 1277| 0| // on prefetching to finish. 1278| 0| self._fetchedContainers[identifier] = container 1279| 0| self._prefetchingContainers.remove(identifier) 1280| 0| self.fetchCondition.signal() 1281| 0| } 1282| 0| } 1283| 0| } 1284| 0| } 1285| 0| } 1286| |} 1287| | 1288| |/// The resolver debugger. 1289| |/// 1290| |/// Finds the constraints which results in graph being unresolvable. 1291| |private struct ResolverDebugger< 1292| | Provider: PackageContainerProvider, 1293| | Delegate: DependencyResolverDelegate 1294| |> where Provider.Container.Identifier == Delegate.Identifier { 1295| | 1296| | typealias Identifier = Provider.Container.Identifier 1297| | typealias Constraint = PackageContainerConstraint 1298| | 1299| | enum Error: Swift.Error { 1300| | /// Reached the time limit without completing the algorithm. 1301| | case reachedTimeLimit 1302| | } 1303| | 1304| | /// Reference to the resolver. 1305| | unowned let resolver: DependencyResolver 1306| | 1307| | /// Create a new debugger. 1308| 0| init(_ resolver: DependencyResolver) { 1309| 0| self.resolver = resolver 1310| 0| } 1311| | 1312| | /// The time limit in seconds after which we abort finding a solution. 1313| | let timeLimit = 10.0 1314| | 1315| | /// Returns the constraints which should be removed in order to make the 1316| | /// graph resolvable. 1317| | /// 1318| | /// We use delta debugging algoritm to find the smallest set of constraints 1319| | /// which can be removed from the input in order to make the graph 1320| | /// satisfiable. 1321| | /// 1322| | /// This algorithm can be exponential, so we abort after the predefined time limit. 1323| | func debug( 1324| | dependencies inputDependencies: [Constraint], 1325| | pins inputPins: [Constraint] 1326| 0| ) throws -> (dependencies: [Constraint], pins: [Constraint]) { 1327| 0| 1328| 0| // Form the dependencies array. 1329| 0| // 1330| 0| // We iterate over the inputs and fetch all the dependencies for 1331| 0| // unversioned requirements as the unversioned requirements are not 1332| 0| // relevant to the dependency resolution. 1333| 0| var dependencies = [Constraint]() 1334| 0| for constraint in inputDependencies { 1335| 0| if constraint.requirement == .unversioned { 1336| 0| // Ignore the errors here. 1337| 0| do { 1338| 0| let container = try resolver.getContainer(for: constraint.identifier) 1339| 0| dependencies += try container.getUnversionedDependencies() 1340| 0| } catch {} 1341| 0| } else { 1342| 0| dependencies.append(constraint) 1343| 0| } 1344| 0| } 1345| 0| 1346| 0| // Form a set of all unversioned dependencies. 1347| 0| let unversionedDependencies = Set(inputDependencies.filter({ $0.requirement == .unversioned }).map({ $0.identifier })) 1348| 0| 1349| 0| // Remove the unversioned constraints from dependencies and pins. 1350| 0| dependencies = dependencies.filter({ !unversionedDependencies.contains($0.identifier) }) 1351| 0| let pins = inputPins.filter({ !unversionedDependencies.contains($0.identifier) }) 1352| 0| 1353| 0| // Put the resolver in incomplete mode to avoid cloning new repositories. 1354| 0| resolver.isInIncompleteMode = true 1355| 0| 1356| 0| let deltaAlgo = DeltaAlgorithm() 1357| 0| let allPackages = Set(dependencies.map({ $0.identifier })) 1358| 0| 1359| 0| // Compute the set of changes. 1360| 0| let allChanges: Set = { 1361| 0| var set = Set() 1362| 0| set.formUnion(dependencies.map({ ResolverChange.allowPackage($0.identifier) })) 1363| 0| set.formUnion(pins.map({ ResolverChange.allowPin($0.identifier) })) 1364| 0| return set 1365| 0| }() 1366| 0| 1367| 0| // Compute the current time. 1368| 0| let startTime = NSDate().timeIntervalSince1970 1369| 0| var timeLimitReached = false 1370| 0| 1371| 0| // Run the delta debugging algorithm. 1372| 0| let badChanges = try deltaAlgo.run(changes: allChanges) { changes in 1373| 0| // Check if we reached the time limits. 1374| 0| timeLimitReached = timeLimitReached || (NSDate().timeIntervalSince1970 - startTime) >= timeLimit 1375| 0| // If we reached the time limit, throw. 1376| 0| if timeLimitReached { 1377| 0| throw Error.reachedTimeLimit 1378| 0| } 1379| 0| 1380| 0| // Find the set of changes we want to allow in this predicate. 1381| 0| let allowedChanges = allChanges.subtracting(changes) 1382| 0| 1383| 0| // Find the packages which are allowed and disallowed to participate 1384| 0| // in this changeset. 1385| 0| let allowedPackages = Set(allowedChanges.compactMap({ $0.allowedPackage })) 1386| 0| let disallowedPackages = allPackages.subtracting(allowedPackages) 1387| 0| 1388| 0| // Start creating constraints. 1389| 0| // 1390| 0| // First, add all the package dependencies. 1391| 0| var constraints = dependencies 1392| 0| 1393| 0| // Set all disallowed packages to unversioned, so they stay out of resolution. 1394| 0| constraints += disallowedPackages.map({ 1395| 0| Constraint(container: $0, requirement: .unversioned) 1396| 0| }) 1397| 0| 1398| 0| let allowedPins = Set(allowedChanges.compactMap({ $0.allowedPin })) 1399| 0| 1400| 0| // It is always a failure if this changeset contains a pin of 1401| 0| // a disallowed package. 1402| 0| if allowedPins.first(where: disallowedPackages.contains) != nil { 1403| 0| return false 1404| 0| } 1405| 0| 1406| 0| // Finally, add the allowed pins. 1407| 0| constraints += pins.filter({ allowedPins.contains($0.identifier) }) 1408| 0| 1409| 0| return try satisfies(constraints) 1410| 0| } 1411| 0| 1412| 0| // Filter the input with found result and return. 1413| 0| let badDependencies = Set(badChanges.compactMap({ $0.allowedPackage })) 1414| 0| let badPins = Set(badChanges.compactMap({ $0.allowedPin })) 1415| 0| return ( 1416| 0| dependencies: dependencies.filter({ badDependencies.contains($0.identifier) }), 1417| 0| pins: pins.filter({ badPins.contains($0.identifier) }) 1418| 0| ) 1419| 0| } 1420| | 1421| | /// Returns true if the constraints are satisfiable. 1422| 0| func satisfies(_ constraints: [Constraint]) throws -> Bool { 1423| 0| do { 1424| 0| _ = try resolver.resolve(constraints: constraints, pins: []) 1425| 0| return true 1426| 0| } catch DependencyResolverError.unsatisfiable { 1427| 0| return false 1428| 0| } 1429| 0| } 1430| | 1431| | /// Represents a single change which should introduced during delta debugging. 1432| | enum ResolverChange: Hashable { 1433| | 1434| | /// Allow the package with the given identifier. 1435| | case allowPackage(Identifier) 1436| | 1437| | /// Allow the pins with the given identifier. 1438| | case allowPin(Identifier) 1439| | 1440| | /// Returns the allowed pin identifier. 1441| 0| var allowedPin: Identifier? { 1442| 0| if case let .allowPin(identifier) = self { 1443| 0| return identifier 1444| 0| } 1445| 0| return nil 1446| 0| } 1447| | 1448| | // Returns the allowed package identifier. 1449| 0| var allowedPackage: Identifier? { 1450| 0| if case let .allowPackage(identifier) = self { 1451| 0| return identifier 1452| 0| } 1453| 0| return nil 1454| 0| } 1455| | } 1456| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraph.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import PackageModel 13| | 14| |/// A collection of packages. 15| |public struct PackageGraph { 16| | /// The root packages. 17| | public let rootPackages: [ResolvedPackage] 18| | 19| | /// The complete list of contained packages, in topological order starting 20| | /// with the root packages. 21| | public let packages: [ResolvedPackage] 22| | 23| | /// The list of all targets reachable from root targets. 24| | public let reachableTargets: Set 25| | 26| | /// The list of all products reachable from root targets. 27| | public let reachableProducts: Set 28| | 29| | /// Returns all the targets in the graph, regardless if they are reachable from the root targets or not. 30| | public let allTargets: Set 31| | 32| | /// Returns all the products in the graph, regardless if they are reachable from the root targets or not. 33| | public let allProducts: Set 34| | 35| | /// The set of package dependencies required for a fully resolved graph. 36| | /// 37| | //// This set will also have references to packages that are currently present 38| | /// in the graph due to loading errors. This set doesn't include the root packages. 39| | public let requiredDependencies: Set 40| | 41| | /// Returns true if a given target is present in root packages. 42| 0| public func isInRootPackages(_ target: ResolvedTarget) -> Bool { 43| 0| // FIXME: This can be easily cached. 44| 0| return rootPackages.flatMap({ $0.targets }).contains(target) 45| 0| } 46| | 47| 0| public func isRootPackage(_ package: ResolvedPackage) -> Bool { 48| 0| // FIXME: This can be easily cached. 49| 0| return rootPackages.contains(package) 50| 0| } 51| | 52| | /// Construct a package graph directly. 53| | public init( 54| | rootPackages: [ResolvedPackage], 55| | rootDependencies: [ResolvedPackage] = [], 56| | requiredDependencies: Set 57| 0| ) { 58| 0| self.rootPackages = rootPackages 59| 0| self.requiredDependencies = requiredDependencies 60| 0| let inputPackages = rootPackages + rootDependencies 61| 0| self.packages = try! topologicalSort(inputPackages, successors: { $0.dependencies }) 62| 0| 63| 0| allTargets = Set(packages.flatMap({ package -> [ResolvedTarget] in 64| 0| if rootPackages.contains(package) { 65| 0| return package.targets 66| 0| } else { 67| 0| // Don't include tests targets from non-root packages so swift-test doesn't 68| 0| // try to run them. 69| 0| return package.targets.filter({ $0.type != .test }) 70| 0| } 71| 0| })) 72| 0| 73| 0| allProducts = Set(packages.flatMap({ package -> [ResolvedProduct] in 74| 0| if rootPackages.contains(package) { 75| 0| return package.products 76| 0| } else { 77| 0| // Don't include tests products from non-root packages so swift-test doesn't 78| 0| // try to run them. 79| 0| return package.products.filter({ $0.type != .test }) 80| 0| } 81| 0| })) 82| 0| 83| 0| // Compute the input targets. 84| 0| let inputTargets = inputPackages.flatMap({ $0.targets }).map(ResolvedTarget.Dependency.target) 85| 0| // Find all the dependencies of the root targets. 86| 0| let dependencies = try! topologicalSort(inputTargets, successors: { $0.dependencies }) 87| 0| 88| 0| // Separate out the products and targets but maintain their topological order. 89| 0| var reachableTargets: Set = [] 90| 0| var reachableProducts = Set(inputPackages.flatMap({ $0.products })) 91| 0| 92| 0| for dependency in dependencies { 93| 0| switch dependency { 94| 0| case .target(let target): 95| 0| reachableTargets.insert(target) 96| 0| case .product(let product): 97| 0| reachableProducts.insert(product) 98| 0| } 99| 0| } 100| 0| 101| 0| self.reachableTargets = reachableTargets 102| 0| self.reachableProducts = reachableProducts 103| 0| } 104| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraphLoader.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import SourceControl 13| |import PackageLoading 14| |import PackageModel 15| |import SPMUtility 16| | 17| |struct UnusedDependencyDiagnostic: DiagnosticData { 18| | static let id = DiagnosticID( 19| | type: UnusedDependencyDiagnostic.self, 20| | name: "org.swift.diags.unused-dependency", 21| | defaultBehavior: .warning, 22| | description: { 23| 0| $0 <<< "dependency" <<< { "'\($0.dependencyName)'" } <<< "is not used by any target" 24| | }) 25| | 26| | public let dependencyName: String 27| |} 28| | 29| |struct ProductHasNoSupportedPlatform: DiagnosticData { 30| | static let id = DiagnosticID( 31| | type: ProductHasNoSupportedPlatform.self, 32| | name: "org.swift.diags.\(ProductHasNoSupportedPlatform.self)", 33| | defaultBehavior: .error, 34| 0| description: { 35| 0| $0 <<< "the product" <<< { "'\($0.productDependency)'" } 36| 0| $0 <<< "doesn't support any of the platform required by" 37| 0| $0 <<< "the target" <<< { "'\($0.target)'" } 38| 0| }) 39| | 40| | public let productDependency: String 41| | public let target: String 42| | 43| 0| init(product: String, target: String) { 44| 0| self.productDependency = product 45| 0| self.target = target 46| 0| } 47| |} 48| | 49| |struct ProductUsesUnsafeFlags: DiagnosticData { 50| | static let id = DiagnosticID( 51| | type: ProductUsesUnsafeFlags.self, 52| | name: "org.swift.diags.\(ProductUsesUnsafeFlags.self)", 53| | defaultBehavior: .error, 54| 0| description: { 55| 0| $0 <<< "the target" <<< { "'\($0.target)'" } 56| 0| $0 <<< "in product" <<< { "'\($0.product)'" } 57| 0| $0 <<< "contains unsafe build flags" 58| 0| }) 59| | 60| | public let product: String 61| | public let target: String 62| | 63| 0| init(product: String, target: String) { 64| 0| self.product = product 65| 0| self.target = target 66| 0| } 67| |} 68| | 69| |enum PackageGraphError: Swift.Error { 70| | /// Indicates a non-root package with no targets. 71| | case noModules(Package) 72| | 73| | /// The package dependency declaration has cycle in it. 74| | case cycleDetected((path: [Manifest], cycle: [Manifest])) 75| | 76| | /// The product dependency not found. 77| | case productDependencyNotFound(name: String, package: String?) 78| | 79| | /// The product dependency was found but the package name did not match. 80| | case productDependencyIncorrectPackage(name: String, package: String) 81| | 82| | /// A product was found in multiple packages. 83| | case duplicateProduct(product: String, packages: [String]) 84| |} 85| | 86| |extension PackageGraphError: CustomStringConvertible { 87| 0| public var description: String { 88| 0| switch self { 89| 0| case .noModules(let package): 90| 0| return "package '\(package)' contains no targets" 91| 0| 92| 0| case .cycleDetected(let cycle): 93| 0| return "cyclic dependency declaration found: " + 94| 0| (cycle.path + cycle.cycle).map({ $0.name }).joined(separator: " -> ") + 95| 0| " -> " + cycle.cycle[0].name 96| 0| 97| 0| case .productDependencyNotFound(let name, _): 98| 0| return "product dependency '\(name)' not found" 99| 0| 100| 0| case .productDependencyIncorrectPackage(let name, let package): 101| 0| return "product dependency '\(name)' in package '\(package)' not found" 102| 0| 103| 0| case .duplicateProduct(let product, let packages): 104| 0| return "multiple products named '\(product)' in: \(packages.joined(separator: ", "))" 105| 0| } 106| 0| } 107| |} 108| | 109| |/// A helper class for loading a package graph. 110| |public struct PackageGraphLoader { 111| | /// Create a package loader. 112| 0| public init() { } 113| | 114| | /// Load the package graph for the given package path. 115| | public func load( 116| | root: PackageGraphRoot, 117| | config: SwiftPMConfig = SwiftPMConfig(), 118| | externalManifests: [Manifest], 119| | requiredDependencies: Set = [], 120| | diagnostics: DiagnosticsEngine, 121| | fileSystem: FileSystem = localFileSystem, 122| | shouldCreateMultipleTestProducts: Bool = false, 123| | createREPLProduct: Bool = false 124| 0| ) -> PackageGraph { 125| 0| 126| 0| // Create a map of the manifests, keyed by their identity. 127| 0| // 128| 0| // FIXME: For now, we have to compute the identity of dependencies from 129| 0| // the URL but that shouldn't be needed after 130| 0| // Ensure that identity and package name are the same once we have an 131| 0| // API to specify identity in the manifest file 132| 0| let manifestMapSequence = root.manifests.map({ ($0.name.lowercased(), $0) }) + 133| 0| externalManifests.map({ (PackageReference.computeIdentity(packageURL: $0.url), $0) }) 134| 0| let manifestMap = Dictionary(uniqueKeysWithValues: manifestMapSequence) 135| 0| let successors: (Manifest) -> [Manifest] = { manifest in 136| 0| manifest.dependencies.compactMap({ 137| 0| let url = config.mirroredURL(forURL: $0.url) 138| 0| return manifestMap[PackageReference.computeIdentity(packageURL: url)] 139| 0| }) 140| 0| } 141| 0| 142| 0| // Construct the root manifest and root dependencies set. 143| 0| let rootManifestSet = Set(root.manifests) 144| 0| let rootDependencies = Set(root.dependencies.compactMap({ 145| 0| manifestMap[PackageReference.computeIdentity(packageURL: $0.url)] 146| 0| })) 147| 0| let inputManifests = root.manifests + rootDependencies 148| 0| 149| 0| // Collect the manifests for which we are going to build packages. 150| 0| let allManifests: [Manifest] 151| 0| 152| 0| // Detect cycles in manifest dependencies. 153| 0| if let cycle = findCycle(inputManifests, successors: successors) { 154| 0| diagnostics.emit(PackageGraphError.cycleDetected(cycle)) 155| 0| // Break the cycle so we can build a partial package graph. 156| 0| allManifests = inputManifests.filter({ $0 != cycle.cycle[0] }) 157| 0| } else { 158| 0| // Sort all manifests toplogically. 159| 0| allManifests = try! topologicalSort(inputManifests, successors: successors) 160| 0| } 161| 0| 162| 0| // Create the packages. 163| 0| var manifestToPackage: [Manifest: Package] = [:] 164| 0| for manifest in allManifests { 165| 0| let isRootPackage = rootManifestSet.contains(manifest) 166| 0| 167| 0| // Derive the path to the package. 168| 0| // 169| 0| // FIXME: Lift this out of the manifest. 170| 0| let packagePath = manifest.path.parentDirectory 171| 0| 172| 0| // Create a package from the manifest and sources. 173| 0| let builder = PackageBuilder( 174| 0| manifest: manifest, 175| 0| path: packagePath, 176| 0| fileSystem: fileSystem, 177| 0| diagnostics: diagnostics, 178| 0| isRootPackage: isRootPackage, 179| 0| shouldCreateMultipleTestProducts: shouldCreateMultipleTestProducts, 180| 0| createREPLProduct: isRootPackage ? createREPLProduct : false 181| 0| ) 182| 0| 183| 0| diagnostics.wrap(with: PackageLocation.Local(name: manifest.name, packagePath: packagePath), { 184| 0| let package = try builder.construct() 185| 0| manifestToPackage[manifest] = package 186| 0| 187| 0| // Throw if any of the non-root package is empty. 188| 0| if package.targets.isEmpty && !isRootPackage { 189| 0| throw PackageGraphError.noModules(package) 190| 0| } 191| 0| }) 192| 0| } 193| 0| 194| 0| // Resolve dependencies and create resolved packages. 195| 0| let resolvedPackages = createResolvedPackages( 196| 0| allManifests: allManifests, 197| 0| config: config, 198| 0| manifestToPackage: manifestToPackage, 199| 0| rootManifestSet: rootManifestSet, 200| 0| diagnostics: diagnostics 201| 0| ) 202| 0| 203| 0| let rootPackages = resolvedPackages.filter({ rootManifestSet.contains($0.manifest) }) 204| 0| 205| 0| checkAllDependenciesAreUsed(rootPackages, diagnostics) 206| 0| 207| 0| return PackageGraph( 208| 0| rootPackages: rootPackages, 209| 0| rootDependencies: resolvedPackages.filter({ rootDependencies.contains($0.manifest) }), 210| 0| requiredDependencies: requiredDependencies 211| 0| ) 212| 0| } 213| |} 214| | 215| 0|private func checkAllDependenciesAreUsed(_ rootPackages: [ResolvedPackage], _ diagnostics: DiagnosticsEngine) { 216| 0| for package in rootPackages { 217| 0| // List all dependency products dependended on by the package targets. 218| 0| let productDependencies: Set = Set(package.targets.flatMap({ target in 219| 0| return target.dependencies.compactMap({ targetDependency in 220| 0| switch targetDependency { 221| 0| case .product(let product): 222| 0| return product 223| 0| case .target: 224| 0| return nil 225| 0| } 226| 0| }) 227| 0| })) 228| 0| 229| 0| for dependency in package.dependencies { 230| 0| // We continue if the dependency contains executable products to make sure we don't 231| 0| // warn on a valid use-case for a lone dependency: swift run dependency executables. 232| 0| guard !dependency.products.contains(where: { $0.type == .executable }) else { 233| 0| continue 234| 0| } 235| 0| // Skip this check if this dependency is a system module because system module packages 236| 0| // have no products. 237| 0| // 238| 0| // FIXME: Do/should we print a warning if a dependency has no products? 239| 0| if dependency.products.isEmpty && dependency.targets.filter({ $0.type == .systemModule }).count == 1 { 240| 0| continue 241| 0| } 242| 0| 243| 0| let dependencyIsUsed = dependency.products.contains(where: productDependencies.contains) 244| 0| if !dependencyIsUsed { 245| 0| diagnostics.emit(data: UnusedDependencyDiagnostic(dependencyName: dependency.name)) 246| 0| } 247| 0| } 248| 0| } 249| 0|} 250| | 251| |/// Create resolved packages from the loaded packages. 252| |private func createResolvedPackages( 253| | allManifests: [Manifest], 254| | config: SwiftPMConfig, 255| | manifestToPackage: [Manifest: Package], 256| | // FIXME: This shouldn't be needed once is fixed. 257| | rootManifestSet: Set, 258| | diagnostics: DiagnosticsEngine 259| 0|) -> [ResolvedPackage] { 260| 0| 261| 0| // Create package builder objects from the input manifests. 262| 0| let packageBuilders: [ResolvedPackageBuilder] = allManifests.compactMap({ 263| 0| guard let package = manifestToPackage[$0] else { 264| 0| return nil 265| 0| } 266| 0| return ResolvedPackageBuilder(package) 267| 0| }) 268| 0| 269| 0| // Create a map of package builders keyed by the package identity. 270| 0| let packageMap: [String: ResolvedPackageBuilder] = packageBuilders.spm_createDictionary({ 271| 0| // FIXME: This shouldn't be needed once is fixed. 272| 0| let identity = rootManifestSet.contains($0.package.manifest) ? $0.package.name.lowercased() : PackageReference.computeIdentity(packageURL: $0.package.manifest.url) 273| 0| return (identity, $0) 274| 0| }) 275| 0| 276| 0| // In the first pass, we wire some basic things. 277| 0| for packageBuilder in packageBuilders { 278| 0| let package = packageBuilder.package 279| 0| 280| 0| // Establish the manifest-declared package dependencies. 281| 0| packageBuilder.dependencies = package.manifest.dependencies.compactMap({ 282| 0| let url = config.mirroredURL(forURL: $0.url) 283| 0| return packageMap[PackageReference.computeIdentity(packageURL: url)] 284| 0| }) 285| 0| 286| 0| // Create target builders for each target in the package. 287| 0| let targetBuilders = package.targets.map({ ResolvedTargetBuilder(target: $0, diagnostics: diagnostics) }) 288| 0| packageBuilder.targets = targetBuilders 289| 0| 290| 0| // Establish dependencies between the targets. A target can only depend on another target present in the same package. 291| 0| let targetMap = targetBuilders.spm_createDictionary({ ($0.target, $0) }) 292| 0| for targetBuilder in targetBuilders { 293| 0| targetBuilder.dependencies += targetBuilder.target.dependencies.map({ targetMap[$0]! }) 294| 0| } 295| 0| 296| 0| // Create product builders for each product in the package. A product can only contain a target present in the same package. 297| 0| packageBuilder.products = package.products.map({ 298| 0| ResolvedProductBuilder(product: $0, targets: $0.targets.map({ targetMap[$0]! })) 299| 0| }) 300| 0| } 301| 0| 302| 0| // Find duplicate products in the package graph. 303| 0| let duplicateProducts = packageBuilders 304| 0| .flatMap({ $0.products }) 305| 0| .map({ $0.product }) 306| 0| .spm_findDuplicateElements(by: \.name) 307| 0| .map({ $0[0].name }) 308| 0| 309| 0| // Emit diagnostics for duplicate products. 310| 0| for productName in duplicateProducts { 311| 0| let packages = packageBuilders 312| 0| .filter({ $0.products.contains(where: { $0.product.name == productName }) }) 313| 0| .map({ $0.package.name }) 314| 0| .sorted() 315| 0| 316| 0| diagnostics.emit(PackageGraphError.duplicateProduct(product: productName, packages: packages)) 317| 0| } 318| 0| 319| 0| // Remove the duplicate products from the builders. 320| 0| for packageBuilder in packageBuilders { 321| 0| packageBuilder.products = packageBuilder.products.filter({ !duplicateProducts.contains($0.product.name) }) 322| 0| } 323| 0| 324| 0| // The set of all target names. 325| 0| var allTargetNames = Set() 326| 0| 327| 0| // Track if multiple targets are found with the same name. 328| 0| var foundDuplicateTarget = false 329| 0| 330| 0| // Do another pass and establish product dependencies of each target. 331| 0| for packageBuilder in packageBuilders { 332| 0| let package = packageBuilder.package 333| 0| 334| 0| // The diagnostics location for this package. 335| 0| let diagnosticLocation = { PackageLocation.Local(name: package.name, packagePath: package.path) } 336| 0| 337| 0| // Get all implicit system library dependencies in this package. 338| 0| let implicitSystemTargetDeps = packageBuilder.dependencies 339| 0| .flatMap({ $0.targets }) 340| 0| .filter({ 341| 0| if case let systemLibrary as SystemLibraryTarget = $0.target { 342| 0| return systemLibrary.isImplicit 343| 0| } 344| 0| return false 345| 0| }) 346| 0| 347| 0| // Get all the products from dependencies of this package. 348| 0| let productDependencies = packageBuilder.dependencies 349| 0| .flatMap({ $0.products }) 350| 0| .filter({ $0.product.type != .test }) 351| 0| let productDependencyMap = productDependencies.spm_createDictionary({ ($0.product.name, $0) }) 352| 0| 353| 0| // Establish dependencies in each target. 354| 0| for targetBuilder in packageBuilder.targets { 355| 0| // Record if we see a duplicate target. 356| 0| foundDuplicateTarget = foundDuplicateTarget || !allTargetNames.insert(targetBuilder.target.name).inserted 357| 0| 358| 0| // Directly add all the system module dependencies. 359| 0| targetBuilder.dependencies += implicitSystemTargetDeps 360| 0| 361| 0| // Establish product dependencies. 362| 0| for productRef in targetBuilder.target.productDependencies { 363| 0| // Find the product in this package's dependency products. 364| 0| guard let product = productDependencyMap[productRef.name] else { 365| 0| // Only emit a diagnostic if there are no other diagnostics. 366| 0| // This avoids flooding the diagnostics with product not 367| 0| // found errors when there are more important errors to 368| 0| // resolve (like authentication issues). 369| 0| if !diagnostics.hasErrors { 370| 0| let error = PackageGraphError.productDependencyNotFound(name: productRef.name, package: productRef.package) 371| 0| diagnostics.emit(error, location: diagnosticLocation()) 372| 0| } 373| 0| continue 374| 0| } 375| 0| 376| 0| // If package name is mentioned, ensure it is valid. 377| 0| if let packageName = productRef.package { 378| 0| // Find the declared package and check that it contains 379| 0| // the product we found above. 380| 0| guard let dependencyPackage = packageMap[packageName.lowercased()], dependencyPackage.products.contains(product) else { 381| 0| let error = PackageGraphError.productDependencyIncorrectPackage( 382| 0| name: productRef.name, package: packageName) 383| 0| diagnostics.emit(error, location: diagnosticLocation()) 384| 0| continue 385| 0| } 386| 0| } 387| 0| 388| 0| targetBuilder.productDeps.append(product) 389| 0| } 390| 0| } 391| 0| } 392| 0| 393| 0| // If a target with similar name was encountered before, we emit a diagnostic. 394| 0| if foundDuplicateTarget { 395| 0| for targetName in allTargetNames.sorted() { 396| 0| // Find the packages this target is present in. 397| 0| let packageNames = packageBuilders 398| 0| .filter({ $0.targets.contains(where: { $0.target.name == targetName }) }) 399| 0| .map({ $0.package.name }) 400| 0| .sorted() 401| 0| if packageNames.count > 1 { 402| 0| diagnostics.emit(ModuleError.duplicateModule(targetName, packageNames)) 403| 0| } 404| 0| } 405| 0| } 406| 0| return packageBuilders.map({ $0.construct() }) 407| 0|} 408| | 409| |/// A generic builder for `Resolved` models. 410| |private class ResolvedBuilder: ObjectIdentifierProtocol { 411| | 412| | /// The constucted object, available after the first call to `constuct()`. 413| | private var _constructedObject: T? 414| | 415| | /// Construct the object with the accumulated data. 416| | /// 417| | /// Note that once the object is constucted, future calls to 418| | /// this method will return the same object. 419| 0| final func construct() -> T { 420| 0| if let constructedObject = _constructedObject { 421| 0| return constructedObject 422| 0| } 423| 0| _constructedObject = constructImpl() 424| 0| return _constructedObject! 425| 0| } 426| | 427| | /// The object construction implementation. 428| 0| func constructImpl() -> T { 429| 0| fatalError("Should be implemented by subclasses") 430| 0| } 431| |} 432| | 433| |/// Builder for resolved product. 434| |private final class ResolvedProductBuilder: ResolvedBuilder { 435| | 436| | /// The product reference. 437| | let product: Product 438| | 439| | /// The target builders in the product. 440| | let targets: [ResolvedTargetBuilder] 441| | 442| 0| init(product: Product, targets: [ResolvedTargetBuilder]) { 443| 0| self.product = product 444| 0| self.targets = targets 445| 0| } 446| | 447| 0| override func constructImpl() -> ResolvedProduct { 448| 0| return ResolvedProduct( 449| 0| product: product, 450| 0| targets: targets.map({ $0.construct() }) 451| 0| ) 452| 0| } 453| |} 454| | 455| |/// Builder for resolved target. 456| |private final class ResolvedTargetBuilder: ResolvedBuilder { 457| | 458| | /// The target reference. 459| | let target: Target 460| | 461| | /// The target dependencies of this target. 462| | var dependencies: [ResolvedTargetBuilder] = [] 463| | 464| | /// The product dependencies of this target. 465| | var productDeps: [ResolvedProductBuilder] = [] 466| | 467| | /// The diagnostics engine. 468| | let diagnostics: DiagnosticsEngine 469| | 470| 0| init(target: Target, diagnostics: DiagnosticsEngine) { 471| 0| self.target = target 472| 0| self.diagnostics = diagnostics 473| 0| } 474| | 475| 0| func validateProductDependency(_ product: ResolvedProduct) { 476| 0| // Diagnose if any target in this product uses an unsafe flag. 477| 0| for target in product.targets { 478| 0| let declarations = target.underlyingTarget.buildSettings.assignments.keys 479| 0| for decl in declarations { 480| 0| if BuildSettings.Declaration.unsafeSettings.contains(decl) { 481| 0| diagnostics.emit(data: ProductUsesUnsafeFlags(product: product.name, target: target.name)) 482| 0| break 483| 0| } 484| 0| } 485| 0| } 486| 0| } 487| | 488| 0| override func constructImpl() -> ResolvedTarget { 489| 0| var deps: [ResolvedTarget.Dependency] = [] 490| 0| for dependency in dependencies { 491| 0| deps.append(.target(dependency.construct())) 492| 0| } 493| 0| for dependency in productDeps { 494| 0| let product = dependency.construct() 495| 0| 496| 0| // FIXME: Should we not add the dependency if validation fails? 497| 0| validateProductDependency(product) 498| 0| 499| 0| deps.append(.product(product)) 500| 0| } 501| 0| 502| 0| return ResolvedTarget( 503| 0| target: target, 504| 0| dependencies: deps 505| 0| ) 506| 0| } 507| |} 508| | 509| |/// Builder for resolved package. 510| |private final class ResolvedPackageBuilder: ResolvedBuilder { 511| | 512| | /// The package reference. 513| | let package: Package 514| | 515| | /// The targets in the package. 516| | var targets: [ResolvedTargetBuilder] = [] 517| | 518| | /// The products in this package. 519| | var products: [ResolvedProductBuilder] = [] 520| | 521| | /// The dependencies of this package. 522| | var dependencies: [ResolvedPackageBuilder] = [] 523| | 524| 0| init(_ package: Package) { 525| 0| self.package = package 526| 0| } 527| | 528| 0| override func constructImpl() -> ResolvedPackage { 529| 0| return ResolvedPackage( 530| 0| package: package, 531| 0| dependencies: dependencies.map({ $0.construct() }), 532| 0| targets: targets.map({ $0.construct() }), 533| 0| products: products.map({ $0.construct() }) 534| 0| ) 535| 0| } 536| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraphRoot.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import SPMUtility 13| | 14| |import PackageModel 15| |import SourceControl 16| | 17| |/// Represents the input to the package graph root. 18| |public struct PackageGraphRootInput { 19| | 20| | public typealias PackageDependency = PackageGraphRoot.PackageDependency 21| | 22| | /// The list of root packages. 23| | public let packages: [AbsolutePath] 24| | 25| | /// Top level dependencies to the graph. 26| | public let dependencies: [PackageDependency] 27| | 28| | /// Create a package graph root. 29| 0| public init(packages: [AbsolutePath], dependencies: [PackageDependency] = []) { 30| 0| self.packages = packages 31| 0| self.dependencies = dependencies 32| 0| } 33| |} 34| | 35| |/// Represents the inputs to the package graph. 36| |public struct PackageGraphRoot { 37| | 38| | // FIXME: We can kill this now. 39| | // 40| | /// Represents a top level package dependencies. 41| | public struct PackageDependency { 42| | 43| | public typealias Requirement = PackageModel.PackageDependencyDescription.Requirement 44| | 45| | // Location of this dependency. 46| | // 47| | // Opaque location object which will be included in any diagnostics 48| | // related to this dependency. Clients can use this identify where this 49| | // dependency is declared. 50| | public let location: String 51| | 52| | /// The URL of the package. 53| | public let url: String 54| | 55| | /// The requirement of the package. 56| | public let requirement: Requirement 57| | 58| | /// Create the package reference object for the dependency. 59| 0| public func createPackageRef(config: SwiftPMConfig) -> PackageReference { 60| 0| let effectiveURL = config.mirroredURL(forURL: self.url) 61| 0| return PackageReference( 62| 0| identity: PackageReference.computeIdentity(packageURL: effectiveURL), 63| 0| path: effectiveURL, 64| 0| isLocal: (requirement == .localPackage) 65| 0| ) 66| 0| } 67| | 68| | public init( 69| | url: String, 70| | requirement: Requirement, 71| | location: String 72| 0| ) { 73| 0| // FIXME: SwiftPM can't handle file URLs with file:// scheme so we need to 74| 0| // strip that. We need to design a URL data structure for SwiftPM. 75| 0| let filePrefix = "file://" 76| 0| if url.hasPrefix(filePrefix) { 77| 0| self.url = AbsolutePath(String(url.dropFirst(filePrefix.count))).pathString 78| 0| } else { 79| 0| self.url = url 80| 0| } 81| 0| self.requirement = requirement 82| 0| self.location = location 83| 0| } 84| | } 85| | 86| | /// The list of root manifests. 87| | public let manifests: [Manifest] 88| | 89| | /// The root package references. 90| | public let packageRefs: [PackageReference] 91| | 92| | /// The top level dependencies. 93| | public let dependencies: [PackageDependency] 94| | 95| | /// Create a package graph root. 96| 0| public init(input: PackageGraphRootInput, manifests: [Manifest]) { 97| 0| self.packageRefs = zip(input.packages, manifests).map { (path, manifest) in 98| 0| PackageReference(identity: manifest.name.lowercased(), path: path.pathString, isLocal: true) 99| 0| } 100| 0| self.manifests = manifests 101| 0| self.dependencies = input.dependencies 102| 0| } 103| | 104| | /// Returns the constraints imposed by root manifests + dependencies. 105| 0| public func constraints(config: SwiftPMConfig) -> [RepositoryPackageConstraint] { 106| 0| let constraints = packageRefs.map({ 107| 0| RepositoryPackageConstraint(container: $0, requirement: .unversioned) 108| 0| }) 109| 0| return constraints + dependencies.map({ 110| 0| RepositoryPackageConstraint( 111| 0| container: $0.createPackageRef(config: config), 112| 0| requirement: $0.requirement.toConstraintRequirement() 113| 0| ) 114| 0| }) 115| 0| } 116| |} 117| | 118| |extension PackageDependencyDescription.Requirement { 119| | 120| | /// Returns the constraint requirement representation. 121| 0| public func toConstraintRequirement() -> PackageRequirement { 122| 0| switch self { 123| 0| case .range(let range): 124| 0| return .versionSet(.range(range)) 125| 0| 126| 0| case .revision(let identifier): 127| 0| assert(Git.checkRefFormat(ref: identifier)) 128| 0| 129| 0| return .revision(identifier) 130| 0| 131| 0| case .branch(let identifier): 132| 0| assert(Git.checkRefFormat(ref: identifier)) 133| 0| 134| 0| return .revision(identifier) 135| 0| 136| 0| case .exact(let version): 137| 0| return .versionSet(.exact(version)) 138| 0| 139| 0| case .localPackage: 140| 0| return .unversioned 141| 0| } 142| 0| } 143| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/Pubgrub.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2019 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import struct SPMUtility.Version 12| |import Basic 13| |import struct PackageModel.PackageReference 14| | 15| |/// A term represents a statement about a package that may be true or false. 16| |public struct Term: Equatable, Hashable { 17| | typealias Requirement = PackageRequirement 18| | 19| | let package: Identifier 20| | let requirement: Requirement 21| | let isPositive: Bool 22| | 23| 0| init(package: Identifier, requirement: Requirement, isPositive: Bool) { 24| 0| self.package = package 25| 0| self.requirement = requirement 26| 0| self.isPositive = isPositive 27| 0| } 28| | 29| 0| init(_ package: Identifier, _ requirement: Requirement) { 30| 0| self.init(package: package, requirement: requirement, isPositive: true) 31| 0| } 32| | 33| | /// Create a new negative term. 34| 0| init(not package: Identifier, _ requirement: Requirement) { 35| 0| self.init(package: package, requirement: requirement, isPositive: false) 36| 0| } 37| | 38| | /// The same term with an inversed `isPositive` value. 39| 0| var inverse: Term { 40| 0| return Term( 41| 0| package: package, 42| 0| requirement: requirement, 43| 0| isPositive: !isPositive) 44| 0| } 45| | 46| | /// Check if this term satisfies another term, e.g. if `self` is true, 47| | /// `other` must also be true. 48| 0| func satisfies(_ other: Term) -> Bool { 49| 0| // TODO: This probably makes more sense as isSatisfied(by:) instead. 50| 0| guard self.package == other.package else { return false } 51| 0| return self.relation(with: other) == .subset 52| 0| } 53| | 54| | /// Create an intersection with another term. 55| 0| func intersect(with other: Term) -> Term? { 56| 0| guard self.package == other.package else { return nil } 57| 0| return intersect(withRequirement: other.requirement, andPolarity: other.isPositive) 58| 0| } 59| | 60| | /// Create an intersection with a requirement and polarity returning a new 61| | /// term which represents the version constraints allowed by both the current 62| | /// and given term. 63| | /// Returns `nil` if an intersection is not possible (possibly due to being 64| | /// constrained on branches, revisions, local, etc. or entirely different packages). 65| 0| func intersect(withRequirement requirement: Requirement, andPolarity isPositive: Bool) -> Term? { 66| 0| // TODO: This needs more tests. 67| 0| guard case .versionSet(let lhs) = self.requirement, case .versionSet(let rhs) = requirement else { return nil } 68| 0| 69| 0| let samePolarity = self.isPositive == isPositive 70| 0| 71| 0| if samePolarity { 72| 0| if case .range(let lhs) = lhs, case .range(let rhs) = rhs { 73| 0| let bothNegative = !self.isPositive && !isPositive 74| 0| if bothNegative { 75| 0| let lower = min(lhs.lowerBound, rhs.lowerBound) 76| 0| let upper = max(lhs.upperBound, rhs.upperBound) 77| 0| return self.with(.versionSet(.range(lower.. Term? { 115| 0| return self.intersect(with: other.inverse) 116| 0| } 117| | 118| 0| private func with(_ requirement: Requirement) -> Term { 119| 0| return Term( 120| 0| package: self.package, 121| 0| requirement: requirement, 122| 0| isPositive: self.isPositive) 123| 0| } 124| | 125| | /// Verify if the term fulfills all requirements to be a valid choice for 126| | /// making a decision in the given partial solution. 127| | /// - There has to exist a positive derivation for it. 128| | /// - There has to be no decision for it. 129| | /// - The package version has to match all assignments. 130| 0| func isValidDecision(for solution: PartialSolution) -> Bool { 131| 0| for assignment in solution.assignments where assignment.term.package == package { 132| 0| assert(!assignment.isDecision, "Expected assignment to be a derivation.") 133| 0| guard satisfies(assignment.term) else { return false } 134| 0| } 135| 0| return true 136| 0| } 137| | 138| 0| func relation(with other: Term) -> SetRelation { 139| 0| // From: https://github.com/dart-lang/pub/blob/master/lib/src/solver/term.dart 140| 0| 141| 0| if self.package != other.package { 142| 0| fatalError("attempting to compute relation between different packages \(self) \(other)") 143| 0| } 144| 0| 145| 0| if other.isPositive { 146| 0| if self.isPositive { 147| 0| // If the second requirement contains all the elements of 148| 0| // the first requirement, then it is a subset relation. 149| 0| if other.requirement.containsAll(self.requirement) { 150| 0| return .subset 151| 0| } 152| 0| 153| 0| // If second requirement contains any requirements of 154| 0| // the first, then the relation is overlapping. 155| 0| if other.requirement.containsAny(self.requirement) { 156| 0| return .overlap 157| 0| } 158| 0| 159| 0| // Otherwise it is disjoint. 160| 0| return .disjoint 161| 0| } else { 162| 0| if self.requirement.containsAll(other.requirement) { 163| 0| return .disjoint 164| 0| } 165| 0| return .overlap 166| 0| } 167| 0| } else { 168| 0| if self.isPositive { 169| 0| if !other.requirement.containsAny(self.requirement) { 170| 0| return .subset 171| 0| } 172| 0| if other.requirement.containsAll(self.requirement) { 173| 0| return .disjoint 174| 0| } 175| 0| return .overlap 176| 0| } else { 177| 0| if self.requirement.containsAll(other.requirement) { 178| 0| return .subset 179| 0| } 180| 0| return .overlap 181| 0| } 182| 0| } 183| 0| } 184| | 185| | enum SetRelation: Equatable { 186| | /// The sets have nothing in common. 187| | case disjoint 188| | /// The sets have elements in common but first set is not a subset of second. 189| | case overlap 190| | /// The second set contains all elements of the first set. 191| | case subset 192| | } 193| |} 194| | 195| |extension PackageRequirement { 196| 0| func containsAll(_ other: PackageRequirement) -> Bool { 197| 0| switch (self, other) { 198| 0| case (.versionSet(let lhs), .versionSet(let rhs)): 199| 0| return lhs.intersection(rhs) == rhs 200| 0| default: 201| 0| fatalError("unhandled \(self), \(other)") 202| 0| } 203| 0| } 204| | 205| 0| func containsAny(_ other: PackageRequirement) -> Bool { 206| 0| switch (self, other) { 207| 0| case (.versionSet(let lhs), .versionSet(let rhs)): 208| 0| return lhs.intersection(rhs) != .empty 209| 0| default: 210| 0| fatalError("unhandled \(self), \(other)") 211| 0| } 212| 0| } 213| |} 214| | 215| |extension Term: CustomStringConvertible { 216| 0| public var description: String { 217| 0| var pkg = "\(package)" 218| 0| if let pkgRef = package as? PackageReference { 219| 0| pkg = pkgRef.identity 220| 0| } 221| 0| 222| 0| var req = "" 223| 0| switch requirement { 224| 0| case .unversioned: 225| 0| req = "unversioned" 226| 0| case .revision(let rev): 227| 0| req = rev 228| 0| case .versionSet(let vs): 229| 0| switch vs { 230| 0| case .any: 231| 0| req = "*" 232| 0| case .empty: 233| 0| req = "()" 234| 0| case .exact(let v): 235| 0| req = v.description 236| 0| case .range(let range): 237| 0| req = range.description 238| 0| } 239| 0| } 240| 0| 241| 0| if !isPositive { 242| 0| return "¬\(pkg) \(req)" 243| 0| } 244| 0| return "\(pkg) \(req)" 245| 0| } 246| |} 247| | 248| |private extension Range where Bound == Version { 249| 0| func contains(_ other: Range) -> Bool { 250| 0| return contains(version: other.lowerBound) && 251| 0| contains(version: other.upperBound) 252| 0| } 253| |} 254| | 255| |/// A set of terms that are incompatible with each other and can therefore not 256| |/// all be true at the same time. In dependency resolution, these are derived 257| |/// from version requirements and when running into unresolvable situations. 258| |public struct Incompatibility: Equatable, Hashable { 259| | let terms: OrderedSet> 260| | let cause: Cause 261| | 262| 0| init(terms: OrderedSet>, cause: Cause) { 263| 0| self.terms = terms 264| 0| self.cause = cause 265| 0| } 266| | 267| 0| init(_ terms: Term..., root: Identifier, cause: Cause = .root) { 268| 0| let termSet = OrderedSet(terms) 269| 0| self.init(termSet, root: root, cause: cause) 270| 0| } 271| | 272| 0| init(_ terms: OrderedSet>, root: Identifier, cause: Cause) { 273| 0| assert(terms.count > 0, "An incompatibility must contain at least one term.") 274| 0| 275| 0| // Remove the root package from generated incompatibilities, since it will 276| 0| // always be selected. 277| 0| var terms = terms 278| 0| if terms.count > 1, 279| 0| case .conflict(conflict: _, other: _) = cause, 280| 0| terms.contains(where: { $0.isPositive && $0.package == root }) 281| 0| { 282| 0| terms = OrderedSet(terms.filter { !$0.isPositive || $0.package != root }) 283| 0| } 284| 0| 285| 0| let termsArray = Array(terms) 286| 0| 287| 0| // If there is only one term or two terms referring to the same package 288| 0| // we can skip the extra work of trying to normalize these. 289| 0| if termsArray.count == 1 || 290| 0| (termsArray.count == 2 && termsArray.first?.package != termsArray.last?.package) 291| 0| { 292| 0| self.init(terms: terms, cause: cause) 293| 0| return 294| 0| } 295| 0| 296| 0| let normalizedTerms = normalize(terms: terms.contents) 297| 0| self.init(terms: OrderedSet(normalizedTerms), cause: cause) 298| 0| } 299| |} 300| | 301| |extension Incompatibility: CustomStringConvertible { 302| 0| public var description: String { 303| 0| let terms = self.terms 304| 0| .map(String.init) 305| 0| .joined(separator: ", ") 306| 0| return "{\(terms)}" 307| 0| } 308| |} 309| | 310| |extension Incompatibility { 311| | /// Every incompatibility has a cause to explain its presence in the 312| | /// derivation graph. Only the root incompatibility uses `.root`. All other 313| | /// incompatibilities are either obtained from dependency constraints, 314| | /// decided upon in decision making or derived during unit propagation or 315| | /// conflict resolution. 316| | /// Using this information we can build up a derivation graph by following 317| | /// the tree of causes. All leaf nodes are external dependencies and all 318| | /// internal nodes are derived incompatibilities. 319| | /// 320| | /// An example graph could look like this: 321| | /// ``` 322| | /// ┌────────────────────────────┐ ┌────────────────────────────┐ 323| | /// │{foo ^1.0.0, not bar ^2.0.0}│ │{bar ^2.0.0, not baz ^3.0.0}│ 324| | /// └─────────────┬──────────────┘ └──────────────┬─────────────┘ 325| | /// │ ┌────────────────────────┘ 326| | /// ▼ ▼ 327| | /// ┌─────────────┴──────┴───────┐ ┌────────────────────────────┐ 328| | /// │{foo ^1.0.0, not baz ^3.0.0}│ │{root 1.0.0, not foo ^1.0.0}│ 329| | /// └─────────────┬──────────────┘ └──────────────┬─────────────┘ 330| | /// │ ┌───────────────────────────┘ 331| | /// ▼ ▼ 332| | /// ┌─────┴───┴──┐ 333| | /// │{root 1.0.0}│ 334| | /// └────────────┘ 335| | /// ``` 336| | indirect enum Cause: Equatable, Hashable { 337| | /// represents the root incompatibility 338| | case root 339| | /// represents a package's dependency 340| | case dependency(package: Identifier) 341| | /// represents an incompatibility derived from two others during 342| | /// conflict resolution 343| | case conflict(conflict: Incompatibility, other: Incompatibility) 344| | // TODO: Figure out what other cases should be represented here. 345| | // - SDK requirements 346| | // - no available versions 347| | // - package not found 348| | 349| 0| var isConflict: Bool { 350| 0| if case .conflict = self { 351| 0| return true 352| 0| } 353| 0| return false 354| 0| } 355| | 356| | /// Returns whether this cause can be represented in a single line of the 357| | /// error output. 358| 0| var isSingleLine: Bool { 359| 0| guard case .conflict(let lhs, let rhs) = self else { 360| 0| // TODO: Sure? 361| 0| return false 362| 0| } 363| 0| if case .conflict = lhs.cause, case .conflict = rhs.cause { 364| 0| return false 365| 0| } 366| 0| return true 367| 0| } 368| | } 369| |} 370| | 371| |/// An assignment that is either decided upon during decision making or derived 372| |/// from previously known incompatibilities during unit propagation. 373| |/// 374| |/// All assignments store a term (a package identifier and a version 375| |/// requirement) and a decision level, which represents the number of decisions 376| |/// at or before it in the partial solution that caused it to be derived. This 377| |/// is later used during conflict resolution to figure out how far back to jump 378| |/// when a conflict is found. 379| |public struct Assignment: Equatable { 380| | let term: Term 381| | let decisionLevel: Int 382| | let cause: Incompatibility? 383| | let isDecision: Bool 384| | 385| | private init( 386| | term: Term, 387| | decisionLevel: Int, 388| | cause: Incompatibility?, 389| | isDecision: Bool 390| 0| ) { 391| 0| self.term = term 392| 0| self.decisionLevel = decisionLevel 393| 0| self.cause = cause 394| 0| self.isDecision = isDecision 395| 0| } 396| | 397| | /// An assignment made during decision making. 398| 0| static func decision(_ term: Term, decisionLevel: Int) -> Assignment { 399| 0| assert(term.requirement.isExact, "Cannot create a decision assignment with a non-exact version selection.") 400| 0| 401| 0| return self.init( 402| 0| term: term, 403| 0| decisionLevel: decisionLevel, 404| 0| cause: nil, 405| 0| isDecision: true) 406| 0| } 407| | 408| | /// An assignment derived from previously known incompatibilities during 409| | /// unit propagation. 410| | static func derivation( 411| | _ term: Term, 412| | cause: Incompatibility, 413| 0| decisionLevel: Int) -> Assignment { 414| 0| return self.init( 415| 0| term: term, 416| 0| decisionLevel: decisionLevel, 417| 0| cause: cause, 418| 0| isDecision: false) 419| 0| } 420| |} 421| | 422| |extension Assignment: CustomStringConvertible { 423| 0| public var description: String { 424| 0| switch self.isDecision { 425| 0| case true: 426| 0| return "[Decision \(decisionLevel): \(term)]" 427| 0| case false: 428| 0| return "[Derivation: \(term) ← \(cause?.description ?? "-")]" 429| 0| } 430| 0| } 431| |} 432| | 433| |/// The partial solution is a constantly updated solution used throughout the 434| |/// dependency resolution process, tracking know assignments. 435| |final class PartialSolution { 436| | var root: Identifier? 437| | 438| | /// All known assigments. 439| | private(set) var assignments: [Assignment] 440| | 441| | /// All known decisions. 442| | private(set) var decisions: [Identifier: Version] = [:] 443| | 444| | /// The intersection of all positive assignments for each package, minus any 445| | /// negative assignments that refer to that package. 446| | private(set) var _positive: [Identifier: Term] = [:] 447| | 448| | /// Union of all negative assignments for a package. 449| | /// 450| | /// Only present if a package has no postive assignment. 451| | private(set) var _negative: [Identifier: Term] = [:] 452| | 453| | /// The current decision level. 454| 0| var decisionLevel: Int { 455| 0| return decisions.count - 1 456| 0| } 457| | 458| 0| init(assignments: [Assignment] = []) { 459| 0| self.assignments = assignments 460| 0| for assignment in assignments { 461| 0| register(assignment) 462| 0| } 463| 0| } 464| | 465| | /// A list of all packages that have been assigned, but are not yet satisfied. 466| 0| var undecided: [Term] { 467| 0| // FIXME: Should we sort this so we have a deterministic results? 468| 0| return _positive.values.filter { !decisions.keys.contains($0.package) } 469| 0| } 470| | 471| | /// Create a new derivation assignment and add it to the partial solution's 472| | /// list of known assignments. 473| 0| func derive(_ term: Term, cause: Incompatibility) { 474| 0| let derivation = Assignment.derivation(term, cause: cause, decisionLevel: decisionLevel) 475| 0| self.assignments.append(derivation) 476| 0| register(derivation) 477| 0| } 478| | 479| | /// Create a new decision assignment and add it to the partial solution's 480| | /// list of known assignments. 481| 0| func decide(_ package: Identifier, atExactVersion version: Version) { 482| 0| decisions[package] = version 483| 0| let term = Term(package, .versionSet(.exact(version))) 484| 0| let decision = Assignment.decision(term, decisionLevel: decisionLevel) 485| 0| self.assignments.append(decision) 486| 0| register(decision) 487| 0| } 488| | 489| | /// Populates the _positive and _negative poperties with the assignment. 490| 0| private func register(_ assignment: Assignment) { 491| 0| let term = assignment.term 492| 0| let pkg = term.package 493| 0| 494| 0| if let positive = _positive[pkg] { 495| 0| _positive[term.package] = positive.intersect(with: term) 496| 0| return 497| 0| } 498| 0| 499| 0| let newTerm = _negative[pkg].flatMap{ term.intersect(with: $0) } ?? term 500| 0| 501| 0| if newTerm.isPositive { 502| 0| _negative[pkg] = nil 503| 0| _positive[pkg] = newTerm 504| 0| } else { 505| 0| _negative[pkg] = newTerm 506| 0| } 507| 0| } 508| | 509| | /// Returns the first Assignment in this solution such that the list of 510| | /// assignments up to and including that entry satisfies term. 511| 0| func satisfier(for term: Term) -> Assignment { 512| 0| var assignedTerm: Term? 513| 0| 514| 0| for assignment in assignments { 515| 0| guard assignment.term.package == term.package else { 516| 0| continue 517| 0| } 518| 0| assignedTerm = assignedTerm.flatMap{ $0.intersect(with: assignment.term) } ?? assignment.term 519| 0| 520| 0| if assignedTerm!.satisfies(term) { 521| 0| return assignment 522| 0| } 523| 0| } 524| 0| 525| 0| fatalError("term \(term) not satisfied") 526| 0| } 527| | 528| | /// Backtrack to a specific decision level by dropping all assignments with 529| | /// a decision level which is greater. 530| 0| func backtrack(toDecisionLevel decisionLevel: Int) { 531| 0| var toBeRemoved: [(Int, Assignment)] = [] 532| 0| 533| 0| for (idx, assignment) in zip(0..., assignments) { 534| 0| // Remove *all* derivations and decisions above the specified level. 535| 0| if assignment.decisionLevel > decisionLevel { 536| 0| toBeRemoved.append((idx, assignment)) 537| 0| } 538| 0| } 539| 0| 540| 0| for (idx, remove) in toBeRemoved.reversed() { 541| 0| let assignment = assignments.remove(at: idx) 542| 0| if assignment.isDecision { 543| 0| decisions.removeValue(forKey: remove.term.package) 544| 0| } 545| 0| } 546| 0| 547| 0| // FIXME: We can optimize this by recomputing only the removed things. 548| 0| _negative.removeAll() 549| 0| _positive.removeAll() 550| 0| for assignment in assignments { 551| 0| register(assignment) 552| 0| } 553| 0| } 554| | 555| | /// Does the solution contain a decision for every derivation meaning 556| | /// that all necessary packages have been found? 557| 0| var isFinished: Bool { 558| 0| for derivation in assignments where !derivation.isDecision { 559| 0| if !self.decisions.keys.contains(derivation.term.package) { 560| 0| return false 561| 0| } 562| 0| } 563| 0| return true 564| 0| } 565| | 566| | /// Returns true if the given term satisfies the partial solution. 567| 0| func satisfies(_ term: Term) -> Bool { 568| 0| return self.relation(with: term) == .subset 569| 0| } 570| | 571| | /// Returns the set relation of the partial solution with the given term. 572| 0| func relation(with term: Term) -> Term.SetRelation { 573| 0| let pkg = term.package 574| 0| if let positive = _positive[pkg] { 575| 0| return positive.relation(with: term) 576| 0| } else if let negative = _negative[pkg] { 577| 0| return negative.relation(with: term) 578| 0| } 579| 0| return .overlap 580| 0| } 581| |} 582| | 583| |/// Normalize terms so that at most one term refers to one package/polarity 584| |/// combination. E.g. we don't want both a^1.0.0 and a^1.5.0 to be terms in the 585| |/// same incompatibility, but have these combined by intersecting their version 586| |/// requirements to a^1.5.0. 587| |fileprivate func normalize( 588| 0| terms: [Term]) -> [Term] { 589| 0| typealias Requirement = PackageRequirement 590| 0| let dict = terms.reduce(into: [Identifier: (req: Requirement, polarity: Bool)]()) { 591| 0| res, term in 592| 0| let previous = res[term.package, default: (term.requirement, term.isPositive)] 593| 0| let intersection = term.intersect(withRequirement: previous.req, 594| 0| andPolarity: previous.polarity) 595| 0| assert(intersection != nil, """ 596| 0| Attempting to create an incompatibility with terms for \(term.package) \ 597| 0| intersecting versions \(previous) and \(term.requirement). These are \ 598| 0| mutually exclusive and can't be intersected, making this incompatibility \ 599| 0| irrelevant. 600| 0| """) 601| 0| res[term.package] = (intersection!.requirement, intersection!.isPositive) 602| 0| } 603| 0| // Sorting the values for deterministic test runs. 604| 0| let sortedKeys = dict.keys.sorted(by: { lhs, rhs in 605| 0| return String(describing: lhs) < String(describing: rhs) 606| 0| }) 607| 0| let newTerms = sortedKeys.map { pkg -> Term in 608| 0| let req = dict[pkg]! 609| 0| return Term(package: pkg, requirement: req.req, isPositive: req.polarity) 610| 0| } 611| 0| return newTerms 612| 0|} 613| | 614| |/// A step the resolver takes to advance its progress, e.g. deriving a new assignment 615| |/// or creating a new incompatibility based on a package's dependencies. 616| |public struct GeneralTraceStep { 617| | /// The traced value, e.g. an incompatibility or term. 618| | public let value: Traceable 619| | /// How this value came to be. 620| | public let type: StepType 621| | /// Where this value was created. 622| | public let location: Location 623| | /// A previous step that caused this step. 624| | public let cause: String? 625| | /// The solution's current decision level. 626| | public let decisionLevel: Int 627| | 628| | /// A step can either store an incompatibility or a decided or derived 629| | /// assignment's term. 630| | public enum StepType: String { 631| | case incompatibility 632| | case decision 633| | case derivation 634| | } 635| | 636| | /// The location a step is created at. 637| | public enum Location: String { 638| | case topLevel = "top level" 639| | case unitPropagation = "unit propagation" 640| | case decisionMaking = "decision making" 641| | case conflictResolution = "conflict resolution" 642| | } 643| |} 644| | 645| |/// A step the resolver takes during conflict resolution. 646| |public struct ConflictResolutionTraceStep { 647| | /// The conflicted incompatibility. 648| | public let incompatibility: Incompatibility 649| | public let term: Term 650| | /// The satisfying assignment. 651| | public let satisfier: Assignment 652| |} 653| | 654| |public enum TraceStep { 655| | case general(GeneralTraceStep) 656| | case conflictResolution(ConflictResolutionTraceStep) 657| |} 658| | 659| |public protocol Traceable: CustomStringConvertible {} 660| |extension Incompatibility: Traceable {} 661| |extension Term: Traceable {} 662| | 663| |/// The solver that is able to transitively resolve a set of package constraints 664| |/// specified by a root package. 665| |public final class PubgrubDependencyResolver< 666| | P: PackageContainerProvider, 667| | D: DependencyResolverDelegate 668| |> where P.Container.Identifier == D.Identifier { 669| | public typealias Provider = P 670| | public typealias Delegate = D 671| | public typealias Container = Provider.Container 672| | public typealias Identifier = Container.Identifier 673| | public typealias Binding = (container: Identifier, binding: BoundVersion) 674| | 675| | /// The type of the constraints the resolver operates on. 676| | /// 677| | /// Technically this is a container constraint, but that is currently the 678| | /// only kind of constraints we operate on. 679| | public typealias Constraint = PackageContainerConstraint 680| | 681| | /// The current best guess for a solution satisfying all requirements. 682| | var solution = PartialSolution() 683| | 684| | /// A collection of all known incompatibilities matched to the packages they 685| | /// refer to. This means an incompatibility can occur several times. 686| | var incompatibilities: [Identifier: [Incompatibility]] = [:] 687| | 688| | /// Find all incompatibilities containing a positive term for a given package. 689| 0| func positiveIncompatibilities(for package: Identifier) -> [Incompatibility]? { 690| 0| guard let all = incompatibilities[package] else { 691| 0| return nil 692| 0| } 693| 0| return all.filter { 694| 0| $0.terms.first { $0.package == package }!.isPositive 695| 0| } 696| 0| } 697| | 698| | /// The root package reference. 699| | private(set) var root: Identifier? 700| | 701| | /// The container provider used to load package containers. 702| | let provider: Provider 703| | 704| | /// The resolver's delegate. 705| | let delegate: Delegate? 706| | 707| | /// Skip updating containers while fetching them. 708| | private let skipUpdate: Bool 709| | 710| | /// Set the package root. 711| 0| func set(_ root: Identifier) { 712| 0| self.root = root 713| 0| self.solution.root = root 714| 0| } 715| | 716| | func trace( 717| | value: Traceable, 718| | type: GeneralTraceStep.StepType, 719| | location: GeneralTraceStep.Location, 720| | cause: String? 721| 0| ) { 722| 0| let step = GeneralTraceStep(value: value, 723| 0| type: type, 724| 0| location: location, 725| 0| cause: cause, 726| 0| decisionLevel: solution.decisionLevel) 727| 0| delegate?.trace(.general(step)) 728| 0| } 729| | 730| | /// Trace a conflict resolution step. 731| | func trace( 732| | incompatibility: Incompatibility, 733| | term: Term, 734| | satisfier: Assignment 735| 0| ) { 736| 0| let step = ConflictResolutionTraceStep(incompatibility: incompatibility, 737| 0| term: term, 738| 0| satisfier: satisfier) 739| 0| delegate?.trace(.conflictResolution(step)) 740| 0| } 741| | 742| 0| func decide(_ package: Identifier, version: Version, location: GeneralTraceStep.Location) { 743| 0| let term = Term(package, .versionSet(.exact(version))) 744| 0| // FIXME: Shouldn't we check this _before_ making a decision? 745| 0| assert(term.isValidDecision(for: solution)) 746| 0| 747| 0| trace(value: term, type: .decision, location: location, cause: nil) 748| 0| solution.decide(package, atExactVersion: version) 749| 0| } 750| | 751| 0| func derive(_ term: Term, cause: Incompatibility, location: GeneralTraceStep.Location) { 752| 0| trace(value: term, type: .derivation, location: location, cause: nil) 753| 0| solution.derive(term, cause: cause) 754| 0| } 755| | 756| | public init( 757| | _ provider: Provider, 758| | _ delegate: Delegate? = nil, 759| | skipUpdate: Bool = false 760| 0| ) { 761| 0| self.provider = provider 762| 0| self.delegate = delegate 763| 0| self.skipUpdate = skipUpdate 764| 0| } 765| | 766| | /// Add a new incompatibility to the list of known incompatibilities. 767| 0| func add(_ incompatibility: Incompatibility, location: GeneralTraceStep.Location) { 768| 0| trace(value: incompatibility, type: .incompatibility, location: location, cause: nil) 769| 0| for package in incompatibility.terms.map({ $0.package }) { 770| 0| if incompatibilities[package] != nil { 771| 0| if !incompatibilities[package]!.contains(incompatibility) { 772| 0| incompatibilities[package]!.append(incompatibility) 773| 0| } 774| 0| } else { 775| 0| incompatibilities[package] = [incompatibility] 776| 0| } 777| 0| } 778| 0| } 779| | 780| | public typealias Result = DependencyResolver.Result 781| | 782| | // TODO: This should be the actual (and probably only) entrypoint to version solving. 783| | /// Run the resolution algorithm on a root package finding a valid assignment of versions. 784| 0| public func solve(root: Identifier, pins: [Constraint]) -> Result { 785| 0| self.set(root) 786| 0| do { 787| 0| return try .success(solve(constraints: [], pins: pins)) 788| 0| } catch { 789| 0| return .error(error) 790| 0| } 791| 0| } 792| | 793| | /// Execute the resolution algorithm to find a valid assignment of versions. 794| 0| public func solve(dependencies: [Constraint], pins: [Constraint]) -> Result { 795| 0| guard let root = dependencies.first?.identifier else { 796| 0| fatalError("expected a root package") 797| 0| } 798| 0| self.root = root 799| 0| return solve(root: root, pins: pins) 800| 0| } 801| | 802| | public enum PubgrubError: Swift.Error, Equatable { 803| | case unresolvable(Incompatibility) 804| | } 805| | 806| | /// Find a set of dependencies that fit the given constraints. If dependency 807| | /// resolution is unable to provide a result, an error is thrown. 808| | /// - Warning: It is expected that the root package reference has been set 809| | /// before this is called. 810| | public func solve( 811| | constraints: [Constraint], pins: [Constraint] 812| 0| ) throws -> [(container: Identifier, binding: BoundVersion)] { 813| 0| // TODO: Handle pins 814| 0| guard let root = self.root else { 815| 0| fatalError("Expected resolver root reference to be set.") 816| 0| } 817| 0| 818| 0| // Handle root, e.g. add dependencies and root decision. 819| 0| // 820| 0| // We add the dependencies before deciding on a version for root 821| 0| // to avoid inserting the wrong decision level. 822| 0| let rootContainer = try getContainer(for: self.root!) 823| 0| for dependency in try rootContainer.getUnversionedDependencies() { 824| 0| let incompatibility = Incompatibility( 825| 0| Term(root, .versionSet(.exact("1.0.0"))), 826| 0| Term(not: dependency.identifier, dependency.requirement), 827| 0| root: root, cause: .root) 828| 0| add(incompatibility, location: .topLevel) 829| 0| } 830| 0| decide(root, version: "1.0.0", location: .topLevel) 831| 0| 832| 0| do { 833| 0| try run() 834| 0| } catch PubgrubError.unresolvable(let conflict) { 835| 0| let description = reportError(for: conflict) 836| 0| print(description) 837| 0| throw PubgrubError.unresolvable(conflict) 838| 0| } catch { 839| 0| fatalError("Unexpected error.") 840| 0| } 841| 0| 842| 0| let decisions = solution.assignments.filter { $0.isDecision } 843| 0| let finalAssignments: [(container: Identifier, binding: BoundVersion)] = decisions.map { assignment in 844| 0| var boundVersion: BoundVersion 845| 0| switch assignment.term.requirement { 846| 0| case .versionSet(.exact(let version)): 847| 0| boundVersion = .version(version) 848| 0| case .revision(let rev): 849| 0| boundVersion = .revision(rev) 850| 0| case .versionSet(.range(_)): 851| 0| // FIXME: A new requirement type that makes having a range here impossible feels like the correct thing to do. 852| 0| fatalError("Solution should not contain version ranges.") 853| 0| case .unversioned, .versionSet(.any): 854| 0| boundVersion = .unversioned 855| 0| case .versionSet(.empty): 856| 0| fatalError("Solution should not contain empty versionSet requirement.") 857| 0| } 858| 0| 859| 0| return (assignment.term.package, boundVersion) 860| 0| } 861| 0| 862| 0| return finalAssignments.filter { $0.container != root } 863| 0| } 864| | 865| | /// Perform unit propagation, resolving conflicts if necessary and making 866| | /// decisions if nothing else is left to be done. 867| | /// After this method returns `solution` is either populated with a list of 868| | /// final version assignments or an error is thrown. 869| 0| func run() throws { 870| 0| var next: Identifier? = root 871| 0| while let nxt = next { 872| 0| try propagate(nxt) 873| 0| 874| 0| // FIXME: Is this really needed here because next should return nil 875| 0| // once version solving has finished. 876| 0| // 877| 0| // If the solution contains a decision for every derivation version 878| 0| // solving is finished. 879| 0| if solution.isFinished { 880| 0| return 881| 0| } 882| 0| 883| 0| // If decision making determines that no more decisions are to be 884| 0| // made, it returns nil to signal that version solving is done. 885| 0| next = try makeDecision() 886| 0| } 887| 0| } 888| | 889| | /// Perform unit propagation to derive new assignments based on the current 890| | /// partial solution. 891| | /// If a conflict is found, the conflicting incompatibility is returned to 892| | /// resolve the conflict on. 893| 0| func propagate(_ package: Identifier) throws { 894| 0| var changed: OrderedSet = [package] 895| 0| 896| 0| while !changed.isEmpty { 897| 0| let package = changed.removeFirst() 898| 0| 899| 0| // According to the experience of pub developers, conflict 900| 0| // resolution produces more general incompatibilities later on 901| 0| // making it advantageous to check those first. 902| 0| loop: for incompatibility in positiveIncompatibilities(for: package)?.reversed() ?? [] { 903| 0| // FIXME: This needs to find set relation for each term in the incompatibility since 904| 0| // that matters. For e.g., 1.1.0..<2.0.0 won't satisfy 1.0.0..<2.0.0 but they're 905| 0| // overlapping. 906| 0| let result = propagate(incompatibility: incompatibility) 907| 0| 908| 0| switch result { 909| 0| case .conflict: 910| 0| let rootCause = try _resolve(conflict: incompatibility) 911| 0| let rootCauseResult = propagate(incompatibility: rootCause) 912| 0| 913| 0| guard case .almostSatisfied(let pkg) = rootCauseResult else { 914| 0| fatalError(""" 915| 0| Expected root cause \(rootCause) to almost satisfy the \ 916| 0| current partial solution: 917| 0| \(solution.assignments.map { " * \($0.description)" }.joined(separator: "\n"))\n 918| 0| """) 919| 0| } 920| 0| 921| 0| changed.removeAll(keepingCapacity: false) 922| 0| changed.append(pkg) 923| 0| 924| 0| break loop 925| 0| case .almostSatisfied(let package): 926| 0| changed.append(package) 927| 0| case .none: 928| 0| break 929| 0| } 930| 0| } 931| 0| } 932| 0| } 933| | 934| 0| func propagate(incompatibility: Incompatibility) -> PropagationResult { 935| 0| var unsatisfied: Term? 936| 0| 937| 0| for term in incompatibility.terms { 938| 0| let relation = solution.relation(with: term) 939| 0| 940| 0| if relation == .disjoint { 941| 0| return .none 942| 0| } else if relation == .overlap { 943| 0| if unsatisfied != nil { 944| 0| return .none 945| 0| } 946| 0| unsatisfied = term 947| 0| } 948| 0| } 949| 0| 950| 0| // We have a conflict if all the terms of the incompatibility were satisfied. 951| 0| guard let unsatisfiedTerm = unsatisfied else { 952| 0| return .conflict 953| 0| } 954| 0| 955| 0| derive(unsatisfiedTerm.inverse, cause: incompatibility, location: .unitPropagation) 956| 0| 957| 0| return .almostSatisfied(package: unsatisfiedTerm.package) 958| 0| } 959| | 960| | enum PropagationResult { 961| | case conflict 962| | case almostSatisfied(package: Identifier) 963| | case none 964| | } 965| | 966| 0| func _resolve(conflict: Incompatibility) throws -> Incompatibility { 967| 0| // Based on: 968| 0| // https://github.com/dart-lang/pub/tree/master/doc/solver.md#conflict-resolution 969| 0| // https://github.com/dart-lang/pub/blob/master/lib/src/solver/version_solver.dart#L201 970| 0| var incompatibility = conflict 971| 0| var createdIncompatibility = false 972| 0| 973| 0| while !isCompleteFailure(incompatibility) { 974| 0| var mostRecentTerm: Term? 975| 0| var mostRecentSatisfier: Assignment? 976| 0| var difference: Term? 977| 0| var previousSatisfierLevel = 0 978| 0| 979| 0| for term in incompatibility.terms { 980| 0| let satisfier = solution.satisfier(for: term) 981| 0| 982| 0| if let _mostRecentSatisfier = mostRecentSatisfier { 983| 0| let mostRecentSatisfierIdx = solution.assignments.index(of: _mostRecentSatisfier)! 984| 0| let satisfierIdx = solution.assignments.index(of: satisfier)! 985| 0| 986| 0| if mostRecentSatisfierIdx < satisfierIdx { 987| 0| previousSatisfierLevel = max(previousSatisfierLevel, _mostRecentSatisfier.decisionLevel) 988| 0| mostRecentTerm = term 989| 0| mostRecentSatisfier = satisfier 990| 0| difference = nil 991| 0| } else { 992| 0| previousSatisfierLevel = max(previousSatisfierLevel, satisfier.decisionLevel) 993| 0| } 994| 0| } else { 995| 0| mostRecentTerm = term 996| 0| mostRecentSatisfier = satisfier 997| 0| } 998| 0| 999| 0| if mostRecentTerm == term { 1000| 0| difference = mostRecentSatisfier?.term.difference(with: term) 1001| 0| if let difference = difference { 1002| 0| previousSatisfierLevel = max(previousSatisfierLevel, solution.satisfier(for: difference.inverse).decisionLevel) 1003| 0| } 1004| 0| } 1005| 0| } 1006| 0| 1007| 0| guard let _mostRecentSatisfier = mostRecentSatisfier else { 1008| 0| fatalError() 1009| 0| } 1010| 0| 1011| 0| if previousSatisfierLevel < _mostRecentSatisfier.decisionLevel || _mostRecentSatisfier.cause == nil { 1012| 0| solution.backtrack(toDecisionLevel: previousSatisfierLevel) 1013| 0| if createdIncompatibility { 1014| 0| add(incompatibility, location: .conflictResolution) 1015| 0| } 1016| 0| return incompatibility 1017| 0| } 1018| 0| 1019| 0| let priorCause = _mostRecentSatisfier.cause! 1020| 0| 1021| 0| var newTerms = incompatibility.terms.filter{ $0 != mostRecentTerm } 1022| 0| newTerms += priorCause.terms.filter({ $0.package != _mostRecentSatisfier.term.package }) 1023| 0| 1024| 0| if let _difference = difference { 1025| 0| newTerms.append(_difference.inverse) 1026| 0| } 1027| 0| 1028| 0| incompatibility = Incompatibility( 1029| 0| OrderedSet(newTerms), 1030| 0| root: root!, 1031| 0| cause: .conflict(conflict: incompatibility, other: priorCause)) 1032| 0| createdIncompatibility = true 1033| 0| } 1034| 0| 1035| 0| throw PubgrubError.unresolvable(incompatibility) 1036| 0| } 1037| | 1038| | /// Does a given incompatibility specify that version solving has entirely 1039| | /// failed, meaning this incompatibility is either empty or only for the root 1040| | /// package. 1041| 0| private func isCompleteFailure(_ incompatibility: Incompatibility) -> Bool { 1042| 0| guard !incompatibility.terms.isEmpty else { return true } 1043| 0| return incompatibility.terms.count == 1 && incompatibility.terms.first?.package == root 1044| 0| } 1045| | 1046| 0| func makeDecision() throws -> Identifier? { 1047| 0| let undecided = solution.undecided 1048| 0| 1049| 0| // If there are no more undecided terms, version solving is complete. 1050| 0| guard !undecided.isEmpty else { 1051| 0| return nil 1052| 0| } 1053| 0| 1054| 0| // FIXME: We should choose a package with least available versions for the 1055| 0| // constraints that we have so far on the package. 1056| 0| let pkgTerm = undecided.first! 1057| 0| 1058| 0| // Get the best available version for this package. 1059| 0| guard let version = try getBestAvailableVersion(for: pkgTerm) else { 1060| 0| // FIXME: It seems wrong to add the incompatibility with cause root here. 1061| 0| add(Incompatibility(pkgTerm, root: root!), location: .decisionMaking) 1062| 0| return pkgTerm.package 1063| 0| } 1064| 0| 1065| 0| // Add all of this version's dependencies as incompatibilities. 1066| 0| let depIncompatibilities = try incompatibilites(for: pkgTerm.package, at: version) 1067| 0| 1068| 0| var haveConflict = false 1069| 0| for incompatibility in depIncompatibilities { 1070| 0| // Add the incompatibility to our partial solution. 1071| 0| add(incompatibility, location: .decisionMaking) 1072| 0| 1073| 0| // Check if this incompatibility will statisfy the solution. 1074| 0| haveConflict = haveConflict || incompatibility.terms.allSatisfy { 1075| 0| // We only need to check if the terms other than this package 1076| 0| // are satisfied because we _know_ that the terms matching 1077| 0| // this package will be satisfied if we make this version 1078| 0| // as a decision. 1079| 0| $0.package == pkgTerm.package || solution.satisfies($0) 1080| 0| } 1081| 0| } 1082| 0| 1083| 0| // Decide this version if there was no conflict with its dependencies. 1084| 0| if !haveConflict { 1085| 0| decide(pkgTerm.package, version: version, location: .decisionMaking) 1086| 0| } 1087| 0| 1088| 0| return pkgTerm.package 1089| 0| } 1090| | 1091| | // MARK: - Error Reporting 1092| | 1093| | private var derivations: [Incompatibility: Int] = [:] 1094| | 1095| 0| func reportError(for incompatibility: Incompatibility) -> String { 1096| 0| /// Populate `derivations`. 1097| 0| func countDerivations(_ i: Incompatibility) { 1098| 0| derivations[i, default: 0] += 1 1099| 0| if case .conflict(let lhs, let rhs) = i.cause { 1100| 0| countDerivations(lhs) 1101| 0| countDerivations(rhs) 1102| 0| } 1103| 0| } 1104| 0| 1105| 0| countDerivations(incompatibility) 1106| 0| 1107| 0| let stream = BufferedOutputByteStream() 1108| 0| visit(incompatibility, stream) 1109| 0| 1110| 0| return stream.bytes.description 1111| 0| } 1112| | 1113| | private func visit( 1114| | _ incompatibility: Incompatibility, 1115| | _ stream: BufferedOutputByteStream, 1116| | isConclusion: Bool = false 1117| 0| ) { 1118| 0| 1119| 0| let isNumbered = isConclusion || derivations[incompatibility]! > 1 1120| 0| 1121| 0| guard case .conflict(let lhs, let rhs) = incompatibility.cause else { 1122| 0| // TODO: Do nothing else here? 1123| 0| return 1124| 0| } 1125| 0| 1126| 0| switch (lhs.cause, rhs.cause) { 1127| 0| case (.conflict, .conflict): 1128| 0| let lhsLine = lineNumbers[lhs] 1129| 0| let rhsLine = lineNumbers[rhs] 1130| 0| 1131| 0| switch (lhsLine, rhsLine) { 1132| 0| case (.some(let lhsLine), .some(let rhsLine)): 1133| 0| write(incompatibility, 1134| 0| message: "Because \(lhs) (\(lhsLine)) and \(rhs) (\(rhsLine), \(incompatibility).", 1135| 0| isNumbered: isNumbered, 1136| 0| toStream: stream) 1137| 0| case (.some(let lhsLine), .none): 1138| 0| visit(incompatibility, stream) 1139| 0| write(incompatibility, 1140| 0| message: "And because \(lhs) (\(lhsLine)), \(incompatibility).", 1141| 0| isNumbered: isNumbered, 1142| 0| toStream: stream) 1143| 0| case (.none, .some(let rhsLine)): 1144| 0| visit(incompatibility, stream) 1145| 0| write(incompatibility, 1146| 0| message: "And because \(rhs) (\(rhsLine)), \(incompatibility).", 1147| 0| isNumbered: isNumbered, 1148| 0| toStream: stream) 1149| 0| case (.none, .none): 1150| 0| let singleLineConflict = lhs.cause.isSingleLine 1151| 0| let singleLineOther = rhs.cause.isSingleLine 1152| 0| 1153| 0| if singleLineOther || singleLineConflict { 1154| 0| let simple = singleLineOther ? lhs : rhs 1155| 0| let complex = singleLineOther ? rhs : lhs 1156| 0| visit(simple, stream) 1157| 0| visit(complex, stream) 1158| 0| write(incompatibility, 1159| 0| message: "Thus, \(incompatibility)", 1160| 0| isNumbered: isNumbered, 1161| 0| toStream: stream) 1162| 0| } else { 1163| 0| visit(lhs, stream, isConclusion: true) 1164| 0| write(incompatibility, 1165| 0| message: "\n", 1166| 0| isNumbered: isNumbered, 1167| 0| toStream: stream) 1168| 0| 1169| 0| visit(rhs, stream) 1170| 0| // TODO: lhsLine will always be nil here... 1171| 0| write(incompatibility, 1172| 0| message: "And because \(lhs) (\(lhsLine ?? -1)), \(incompatibility).", 1173| 0| isNumbered: isNumbered, 1174| 0| toStream: stream) 1175| 0| } 1176| 0| 1177| 0| } 1178| 0| case (.conflict, _), (_, .conflict): 1179| 0| var derived: Incompatibility 1180| 0| var external: Incompatibility 1181| 0| if case .conflict = lhs.cause { 1182| 0| derived = lhs 1183| 0| external = rhs 1184| 0| } else { 1185| 0| derived = rhs 1186| 0| external = lhs 1187| 0| } 1188| 0| 1189| 0| if let derivedLine = lineNumbers[derived] { 1190| 0| write(incompatibility, 1191| 0| message: "Because \(external) and \(derived) (\(derivedLine)), \(incompatibility).", 1192| 0| isNumbered: isNumbered, 1193| 0| toStream: stream) 1194| 0| } else if derivations[incompatibility]! <= 1 { 1195| 0| guard case .conflict(let lhs, let rhs) = derived.cause else { 1196| 0| // FIXME 1197| 0| fatalError("unexpected non-conflict") 1198| 0| } 1199| 0| let collapsedDerived = lhs.cause.isConflict ? rhs : lhs 1200| 0| let collapsedExternal = lhs.cause.isConflict ? rhs : lhs 1201| 0| visit(collapsedDerived, stream) 1202| 0| write(incompatibility, 1203| 0| message: "And because \(collapsedExternal) and \(external), \(incompatibility).", 1204| 0| isNumbered: isNumbered, 1205| 0| toStream: stream) 1206| 0| } else { 1207| 0| visit(derived, stream) 1208| 0| write(incompatibility, 1209| 0| message: "And because \(external), \(incompatibility).", 1210| 0| isNumbered: isNumbered, 1211| 0| toStream: stream) 1212| 0| } 1213| 0| default: 1214| 0| write(incompatibility, 1215| 0| message: "Because \(lhs) and \(rhs), \(incompatibility).", 1216| 0| isNumbered: isNumbered, 1217| 0| toStream: stream) 1218| 0| } 1219| 0| } 1220| | 1221| | private var lineNumbers: [Incompatibility: Int] = [:] 1222| | 1223| | /// Write a given output message to a stream. The message should describe 1224| | /// the incompatibility and how it as derived. If `isNumbered` is true, a 1225| | /// line number will be assigned to this incompatibility so that it can be 1226| | /// referred to again. 1227| | private func write( 1228| | _ i: Incompatibility, 1229| | message: String, 1230| | isNumbered: Bool, 1231| | toStream stream: BufferedOutputByteStream 1232| 0| ) { 1233| 0| if isNumbered { 1234| 0| let number = lineNumbers.count + 1 1235| 0| lineNumbers[i] = number 1236| 0| // TODO: Handle `number` 1237| 0| stream <<< message 1238| 0| } else { 1239| 0| stream <<< message 1240| 0| } 1241| 0| } 1242| | 1243| | // MARK: - Container Management 1244| | 1245| | /// Condition for container management structures. 1246| | private let fetchCondition = Condition() 1247| | 1248| | /// The list of fetched containers. 1249| | private var _fetchedContainers: [Identifier: Basic.Result] = [:] 1250| | 1251| | /// The set of containers requested so far. 1252| | private var _prefetchingContainers: Set = [] 1253| | 1254| | /// Get the container for the given identifier, loading it if necessary. 1255| 0| fileprivate func getContainer(for identifier: Identifier) throws -> Container { 1256| 0| return try fetchCondition.whileLocked { 1257| 0| // Return the cached container, if available. 1258| 0| if let container = _fetchedContainers[identifier] { 1259| 0| return try container.dematerialize() 1260| 0| } 1261| 0| 1262| 0| // If this container is being prefetched, wait for that to complete. 1263| 0| while _prefetchingContainers.contains(identifier) { 1264| 0| fetchCondition.wait() 1265| 0| } 1266| 0| 1267| 0| // The container may now be available in our cache if it was prefetched. 1268| 0| if let container = _fetchedContainers[identifier] { 1269| 0| return try container.dematerialize() 1270| 0| } 1271| 0| 1272| 0| // Otherwise, fetch the container synchronously. 1273| 0| let container = try await { provider.getContainer(for: identifier, skipUpdate: skipUpdate, completion: $0) } 1274| 0| self._fetchedContainers[identifier] = Basic.Result(container) 1275| 0| return container 1276| 0| } 1277| 0| } 1278| | 1279| | /// Returns the best available version for a given term. 1280| 0| func getBestAvailableVersion(for term: Term) throws -> Version? { 1281| 0| assert(term.isPositive, "Expected term to be positive") 1282| 0| let container = try getContainer(for: term.package) 1283| 0| 1284| 0| switch term.requirement { 1285| 0| case .versionSet(let versionSet): 1286| 0| let availableVersions = container.versions(filter: { versionSet.contains($0) } ) 1287| 0| return availableVersions.first{ _ in true } 1288| 0| case .revision: 1289| 0| fatalError() 1290| 0| case .unversioned: 1291| 0| fatalError() 1292| 0| } 1293| 0| } 1294| | 1295| | /// Returns the incompatibilities of a package at the given version. 1296| | func incompatibilites( 1297| | for package: Identifier, 1298| | at version: Version 1299| 0| ) throws -> [Incompatibility] { 1300| 0| let container = try getContainer(for: package) 1301| 0| return try container.getDependencies(at: version).map { dep -> Incompatibility in 1302| 0| var terms: OrderedSet> = [] 1303| 0| 1304| 0| // FIXME: 1305| 0| // 1306| 0| // If the selected version is the latest version, Pubgrub 1307| 0| // represents the term as having an unbounded upper range. 1308| 0| // We can't represent that here (currently), so we're 1309| 0| // pretending that it goes to the next nonexistent major 1310| 0| // version. 1311| 0| let nextMajor = Version(version.major + 1, 0, 0) 1312| 0| terms.append(Term(container.identifier, .versionSet(.range(version.. PackageReference { 17| 0| let effectiveURL = config.mirroredURL(forURL: self.url) 18| 0| return PackageReference( 19| 0| identity: PackageReference.computeIdentity(packageURL: effectiveURL), 20| 0| path: effectiveURL, 21| 0| isLocal: (requirement == .localPackage) 22| 0| ) 23| 0| } 24| |} 25| | 26| |extension Manifest { 27| | 28| | /// Constructs constraints of the dependencies in the raw package. 29| 0| public func dependencyConstraints(config: SwiftPMConfig) -> [RepositoryPackageConstraint] { 30| 0| return dependencies.map({ 31| 0| return RepositoryPackageConstraint( 32| 0| container: $0.createPackageRef(config: config), 33| 0| requirement: $0.requirement.toConstraintRequirement()) 34| 0| }) 35| 0| } 36| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageGraph/RepositoryPackageContainerProvider.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Dispatch 12| | 13| |import Basic 14| |import PackageLoading 15| |import PackageModel 16| |import SourceControl 17| |import SPMUtility 18| | 19| |/// Adaptor for exposing repositories as PackageContainerProvider instances. 20| |/// 21| |/// This is the root class for bridging the manifest & SCM systems into the 22| |/// interfaces used by the `DependencyResolver` algorithm. 23| |public class RepositoryPackageContainerProvider: PackageContainerProvider { 24| | public typealias Container = BasePackageContainer 25| | 26| | let repositoryManager: RepositoryManager 27| | let manifestLoader: ManifestLoaderProtocol 28| | let config: SwiftPMConfig 29| | 30| | /// The tools version currently in use. Only the container versions less than and equal to this will be provided by 31| | /// the container. 32| | let currentToolsVersion: ToolsVersion 33| | 34| | /// The tools version loader. 35| | let toolsVersionLoader: ToolsVersionLoaderProtocol 36| | 37| | /// Queue for callbacks. 38| | private let callbacksQueue = DispatchQueue(label: "org.swift.swiftpm.container-provider") 39| | 40| | /// Create a repository-based package provider. 41| | /// 42| | /// - Parameters: 43| | /// - repositoryManager: The repository manager responsible for providing repositories. 44| | /// - manifestLoader: The manifest loader instance. 45| | /// - currentToolsVersion: The current tools version in use. 46| | /// - toolsVersionLoader: The tools version loader. 47| | public init( 48| | repositoryManager: RepositoryManager, 49| | config: SwiftPMConfig = SwiftPMConfig(), 50| | manifestLoader: ManifestLoaderProtocol, 51| | currentToolsVersion: ToolsVersion = ToolsVersion.currentToolsVersion, 52| | toolsVersionLoader: ToolsVersionLoaderProtocol = ToolsVersionLoader() 53| 0| ) { 54| 0| self.repositoryManager = repositoryManager 55| 0| self.config = config 56| 0| self.manifestLoader = manifestLoader 57| 0| self.currentToolsVersion = currentToolsVersion 58| 0| self.toolsVersionLoader = toolsVersionLoader 59| 0| } 60| | 61| | public func getContainer( 62| | for identifier: Container.Identifier, 63| | skipUpdate: Bool, 64| | completion: @escaping (Result) -> Void 65| 0| ) { 66| 0| // If the container is local, just create and return a local package container. 67| 0| if identifier.isLocal { 68| 0| callbacksQueue.async { 69| 0| let container = LocalPackageContainer(identifier, 70| 0| config: self.config, 71| 0| manifestLoader: self.manifestLoader, 72| 0| toolsVersionLoader: self.toolsVersionLoader, 73| 0| currentToolsVersion: self.currentToolsVersion, 74| 0| fs: self.repositoryManager.fileSystem) 75| 0| completion(Result(container)) 76| 0| } 77| 0| return 78| 0| } 79| 0| 80| 0| // Resolve the container using the repository manager. 81| 0| repositoryManager.lookup(repository: identifier.repository, skipUpdate: skipUpdate) { result in 82| 0| // Create the container wrapper. 83| 0| let container = result.mapAny { handle -> Container in 84| 0| // Open the repository. 85| 0| // 86| 0| // FIXME: Do we care about holding this open for the lifetime of the container. 87| 0| let repository = try handle.open() 88| 0| return RepositoryPackageContainer( 89| 0| identifier: identifier, 90| 0| config: self.config, 91| 0| repository: repository, 92| 0| manifestLoader: self.manifestLoader, 93| 0| toolsVersionLoader: self.toolsVersionLoader, 94| 0| currentToolsVersion: self.currentToolsVersion 95| 0| ) 96| 0| } 97| 0| completion(container) 98| 0| } 99| 0| } 100| |} 101| | 102| |enum RepositoryPackageResolutionError: Swift.Error { 103| | /// A requested repository could not be cloned. 104| | case unavailableRepository 105| |} 106| | 107| |extension PackageReference: PackageContainerIdentifier { 108| | /// The repository of the package. 109| | /// 110| | /// This should only be accessed when the reference is not local. 111| 0| public var repository: RepositorySpecifier { 112| 0| precondition(!isLocal) 113| 0| return RepositorySpecifier(url: path) 114| 0| } 115| |} 116| | 117| |public typealias RepositoryPackageConstraint = PackageContainerConstraint 118| | 119| |/// Base class for the package container. 120| |public class BasePackageContainer: PackageContainer { 121| | public typealias Identifier = PackageReference 122| | 123| | public let identifier: Identifier 124| | 125| | let config: SwiftPMConfig 126| | 127| | /// The manifest loader. 128| | let manifestLoader: ManifestLoaderProtocol 129| | 130| | /// The tools version loader. 131| | let toolsVersionLoader: ToolsVersionLoaderProtocol 132| | 133| | /// The current tools version in use. 134| | let currentToolsVersion: ToolsVersion 135| | 136| 0| public func versions(filter isIncluded: (Version) -> Bool) -> AnySequence { 137| 0| fatalError("This should never be called") 138| 0| } 139| | 140| 0| public func getDependencies(at version: Version) throws -> [PackageContainerConstraint] { 141| 0| fatalError("This should never be called") 142| 0| } 143| | 144| 0| public func getDependencies(at revision: String) throws -> [PackageContainerConstraint] { 145| 0| fatalError("This should never be called") 146| 0| } 147| | 148| 0| public func getUnversionedDependencies() throws -> [PackageContainerConstraint] { 149| 0| fatalError("This should never be called") 150| 0| } 151| | 152| 0| public func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> Identifier { 153| 0| fatalError("This should never be called") 154| 0| } 155| | 156| | fileprivate init( 157| | _ identifier: Identifier, 158| | config: SwiftPMConfig, 159| | manifestLoader: ManifestLoaderProtocol, 160| | toolsVersionLoader: ToolsVersionLoaderProtocol, 161| | currentToolsVersion: ToolsVersion 162| 0| ) { 163| 0| self.identifier = identifier 164| 0| self.config = config 165| 0| self.manifestLoader = manifestLoader 166| 0| self.toolsVersionLoader = toolsVersionLoader 167| 0| self.currentToolsVersion = currentToolsVersion 168| 0| } 169| |} 170| | 171| |/// Local package container. 172| |/// 173| |/// This class represent packages that are referenced locally in the file system. 174| |/// There is no need to perform any git operations on such packages and they 175| |/// should be used as-is. Infact, they might not even have a git repository. 176| |/// Examples: Root packages, local dependencies, edited packages. 177| |public class LocalPackageContainer: BasePackageContainer, CustomStringConvertible { 178| | 179| | /// The file system that shoud be used to load this package. 180| | let fs: FileSystem 181| | 182| | private var _manifest: Manifest? = nil 183| 0| private func loadManifest() throws -> Manifest { 184| 0| if let manifest = _manifest { 185| 0| return manifest 186| 0| } 187| 0| 188| 0| // Load the tools version. 189| 0| let toolsVersion = try toolsVersionLoader.load(at: AbsolutePath(identifier.path), fileSystem: fs) 190| 0| 191| 0| // Ensure current tools supports this package. 192| 0| guard self.currentToolsVersion >= toolsVersion else { 193| 0| // FIXME: Throw from here 194| 0| fatalError() 195| 0| } 196| 0| 197| 0| // Load the manifest. 198| 0| _manifest = try manifestLoader.load( 199| 0| package: AbsolutePath(identifier.path), 200| 0| baseURL: identifier.path, 201| 0| version: nil, 202| 0| manifestVersion: toolsVersion.manifestVersion, 203| 0| fileSystem: fs) 204| 0| return _manifest! 205| 0| } 206| | 207| 0| public override func getUnversionedDependencies() throws -> [PackageContainerConstraint] { 208| 0| return try loadManifest().dependencyConstraints(config: config) 209| 0| } 210| | 211| 0| public override func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> Identifier { 212| 0| assert(boundVersion == .unversioned, "Unexpected bound version \(boundVersion)") 213| 0| let manifest = try loadManifest() 214| 0| return identifier.with(newName: manifest.name) 215| 0| } 216| | 217| | public init( 218| | _ identifier: Identifier, 219| | config: SwiftPMConfig, 220| | manifestLoader: ManifestLoaderProtocol, 221| | toolsVersionLoader: ToolsVersionLoaderProtocol, 222| | currentToolsVersion: ToolsVersion, 223| | fs: FileSystem = localFileSystem 224| 0| ) { 225| 0| assert(URL.scheme(identifier.path) == nil) 226| 0| self.fs = fs 227| 0| super.init( 228| 0| identifier, 229| 0| config: config, 230| 0| manifestLoader: manifestLoader, 231| 0| toolsVersionLoader: toolsVersionLoader, 232| 0| currentToolsVersion: currentToolsVersion 233| 0| ) 234| 0| } 235| | 236| 0| public var description: String { 237| 0| return "LocalPackageContainer(\(identifier.path))" 238| 0| } 239| |} 240| | 241| |/// Adaptor to expose an individual repository as a package container. 242| |public class RepositoryPackageContainer: BasePackageContainer, CustomStringConvertible { 243| | 244| | // A wrapper for getDependencies() errors. This adds additional information 245| | // about the container to identify it for diagnostics. 246| | public struct GetDependenciesErrorWrapper: Swift.Error { 247| | 248| | /// The container which had this error. 249| | public let containerIdentifier: String 250| | 251| | /// The source control reference i.e. version, branch, revsion etc. 252| | public let reference: String 253| | 254| | /// The actual error that occurred. 255| | public let underlyingError: Swift.Error 256| | } 257| | 258| | /// This is used to remember if tools version of a particular version is 259| | /// valid or not. 260| | private(set) var validToolsVersionsCache: [Version: Bool] = [:] 261| | 262| | /// The available version list (in reverse order). 263| 0| public override func versions(filter isIncluded: (Version) -> Bool) -> AnySequence { 264| 0| return AnySequence(reversedVersions.filter(isIncluded).lazy.filter({ 265| 0| // If we have the result cached, return that. 266| 0| if let result = self.validToolsVersionsCache[$0] { 267| 0| return result 268| 0| } 269| 0| 270| 0| // Otherwise, compute and cache the result. 271| 0| let isValid = (try? self.toolsVersion(for: $0)).flatMap({ 272| 0| guard $0 >= ToolsVersion.minimumRequired else { 273| 0| return false 274| 0| } 275| 0| 276| 0| guard self.currentToolsVersion >= $0 else { 277| 0| return false 278| 0| } 279| 0| 280| 0| return true 281| 0| }) ?? false 282| 0| self.validToolsVersionsCache[$0] = isValid 283| 0| 284| 0| return isValid 285| 0| })) 286| 0| } 287| | /// The opened repository. 288| | let repository: Repository 289| | 290| | /// The versions in the repository and their corresponding tags. 291| | let knownVersions: [Version: String] 292| | 293| | /// The versions in the repository sorted by latest first. 294| | let reversedVersions: [Version] 295| | 296| | /// The cached dependency information. 297| | private var dependenciesCache: [String: (Manifest, [RepositoryPackageConstraint])] = [:] 298| | private var dependenciesCacheLock = Lock() 299| | 300| | init( 301| | identifier: PackageReference, 302| | config: SwiftPMConfig, 303| | repository: Repository, 304| | manifestLoader: ManifestLoaderProtocol, 305| | toolsVersionLoader: ToolsVersionLoaderProtocol, 306| | currentToolsVersion: ToolsVersion 307| 0| ) { 308| 0| self.repository = repository 309| 0| 310| 0| // Compute the map of known versions. 311| 0| // 312| 0| // FIXME: Move this utility to a more stable location. 313| 0| let knownVersionsWithDuplicates = Git.convertTagsToVersionMap(repository.tags) 314| 0| 315| 0| let knownVersions = knownVersionsWithDuplicates.mapValues({ tags -> String in 316| 0| if tags.count == 2 { 317| 0| // FIXME: Warn if the two tags point to different git references. 318| 0| return tags.first(where: { !$0.hasPrefix("v") })! 319| 0| } 320| 0| assert(tags.count == 1, "Unexpected number of tags") 321| 0| return tags[0] 322| 0| }) 323| 0| 324| 0| self.knownVersions = knownVersions 325| 0| self.reversedVersions = [Version](knownVersions.keys).sorted().reversed() 326| 0| super.init( 327| 0| identifier, 328| 0| config: config, 329| 0| manifestLoader: manifestLoader, 330| 0| toolsVersionLoader: toolsVersionLoader, 331| 0| currentToolsVersion: currentToolsVersion 332| 0| ) 333| 0| } 334| | 335| 0| public var description: String { 336| 0| return "RepositoryPackageContainer(\(identifier.repository.url.debugDescription))" 337| 0| } 338| | 339| 0| public func getTag(for version: Version) -> String? { 340| 0| return knownVersions[version] 341| 0| } 342| | 343| | /// Returns revision for the given tag. 344| 0| public func getRevision(forTag tag: String) throws -> Revision { 345| 0| return try repository.resolveRevision(tag: tag) 346| 0| } 347| | 348| | /// Returns revision for the given identifier. 349| 0| public func getRevision(forIdentifier identifier: String) throws -> Revision { 350| 0| return try repository.resolveRevision(identifier: identifier) 351| 0| } 352| | 353| | /// Returns the tools version of the given version of the package. 354| 0| private func toolsVersion(for version: Version) throws -> ToolsVersion { 355| 0| let tag = knownVersions[version]! 356| 0| let revision = try repository.resolveRevision(tag: tag) 357| 0| let fs = try repository.openFileView(revision: revision) 358| 0| return try toolsVersionLoader.load(at: .root, fileSystem: fs) 359| 0| } 360| | 361| 0| public override func getDependencies(at version: Version) throws -> [RepositoryPackageConstraint] { 362| 0| do { 363| 0| return try cachedDependencies(forIdentifier: version.description) { 364| 0| let tag = knownVersions[version]! 365| 0| let revision = try repository.resolveRevision(tag: tag) 366| 0| return try getDependencies(at: revision, version: version) 367| 0| }.1 368| 0| } catch { 369| 0| throw GetDependenciesErrorWrapper( 370| 0| containerIdentifier: identifier.repository.url, reference: version.description, underlyingError: error) 371| 0| } 372| 0| } 373| | 374| 0| public override func getDependencies(at revision: String) throws -> [RepositoryPackageConstraint] { 375| 0| do { 376| 0| return try cachedDependencies(forIdentifier: revision) { 377| 0| // resolve the revision identifier and return its dependencies. 378| 0| let revision = try repository.resolveRevision(identifier: revision) 379| 0| return try getDependencies(at: revision) 380| 0| }.1 381| 0| } catch { 382| 0| throw GetDependenciesErrorWrapper( 383| 0| containerIdentifier: identifier.repository.url, reference: revision, underlyingError: error) 384| 0| } 385| 0| } 386| | 387| | private func cachedDependencies( 388| | forIdentifier identifier: String, 389| | getDependencies: () throws -> (Manifest, [RepositoryPackageConstraint]) 390| 0| ) throws -> (Manifest, [RepositoryPackageConstraint]) { 391| 0| return try dependenciesCacheLock.withLock { 392| 0| if let result = dependenciesCache[identifier] { 393| 0| return result 394| 0| } 395| 0| let result = try getDependencies() 396| 0| dependenciesCache[identifier] = result 397| 0| return result 398| 0| } 399| 0| } 400| | 401| | /// Returns dependencies of a container at the given revision. 402| | private func getDependencies( 403| | at revision: Revision, 404| | version: Version? = nil 405| 0| ) throws -> (Manifest, [RepositoryPackageConstraint]) { 406| 0| let fs = try repository.openFileView(revision: revision) 407| 0| 408| 0| // Load the tools version. 409| 0| let toolsVersion = try toolsVersionLoader.load(at: .root, fileSystem: fs) 410| 0| 411| 0| // Load the manifest. 412| 0| let manifest = try manifestLoader.load( 413| 0| package: AbsolutePath.root, 414| 0| baseURL: identifier.repository.url, 415| 0| version: version, 416| 0| manifestVersion: toolsVersion.manifestVersion, 417| 0| fileSystem: fs) 418| 0| 419| 0| return (manifest, manifest.dependencyConstraints(config: config)) 420| 0| } 421| | 422| 0| public override func getUnversionedDependencies() throws -> [PackageContainerConstraint] { 423| 0| // We just return an empty array if requested for unversioned dependencies. 424| 0| return [] 425| 0| } 426| | 427| 0| public override func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> Identifier { 428| 0| let identifier: String 429| 0| switch boundVersion { 430| 0| case .version(let version): 431| 0| identifier = version.description 432| 0| case .revision(let revision): 433| 0| identifier = revision 434| 0| case .unversioned, .excluded: 435| 0| assertionFailure("Unexpected type requirement \(boundVersion)") 436| 0| return self.identifier 437| 0| } 438| 0| 439| 0| // FIXME: We expect by the time this method is called, we would already have the 440| 0| // manifest in the cache. We can probably get rid of this requirement once we implement 441| 0| // proper manifest caching. 442| 0| guard let manifest = dependenciesCache[identifier]?.0 else { 443| 0| assertionFailure("Unexpected missing cache") 444| 0| return self.identifier 445| 0| } 446| 0| return self.identifier.with(newName: manifest.name) 447| 0| } 448| |} <<<<<< EOF # path=llbuildSwift.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/llbuildSwift/BuildSystemBindings.swift: 1| |// This source file is part of the Swift.org open source project 2| |// 3| |// Copyright 2017 Apple Inc. and the Swift project authors 4| |// Licensed under Apache License v2.0 with Runtime Library Exception 5| |// 6| |// See http://swift.org/LICENSE.txt for license information 7| |// See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8| | 9| |// This file contains Swift bindings for the llbuild C API. 10| | 11| |#if os(Linux) 12| |import Glibc 13| |#else 14| |import Darwin.C 15| |#endif 16| | 17| |import Foundation 18| | 19| |// We don't need this import if we're building 20| |// this file as part of the llbuild framework. 21| |#if !LLBUILD_FRAMEWORK 22| |import llbuild 23| |#endif 24| | 25| 0|private func bytesFromData(_ data: llb_data_t) -> [UInt8] { 26| 0| return Array(UnsafeBufferPointer(start: data.data, count: Int(data.length))) 27| 0|} 28| | 29| |/// Create a new `llb_data_t` instance containing an allocated copy of the given `bytes`. 30| 0|private func copiedDataFromBytes(_ bytes: [UInt8]) -> llb_data_t { 31| 0| // Create the data. 32| 0| let buf = UnsafeMutableBufferPointer(start: UnsafeMutablePointer.allocate(capacity: bytes.count), count: bytes.count) 33| 0| 34| 0| // Copy the data. 35| 0| memcpy(buf.baseAddress!, UnsafePointer(bytes), buf.count) 36| 0| 37| 0| // Fill in the result structure. 38| 0| return llb_data_t(length: UInt64(buf.count), data: unsafeBitCast(buf.baseAddress, to: UnsafePointer.self)) 39| 0|} 40| | 41| |// FIXME: We should eventually eliminate the need for this. 42| 0|private func stringFromData(_ data: llb_data_t) -> String { 43| 0| return String(decoding: UnsafeBufferPointer(start: data.data, count: Int(data.length)), as: Unicode.UTF8.self) 44| 0|} 45| | 46| | 47| |public protocol Tool: class { 48| | /// Called to create a specific command instance of this tool. 49| | func createCommand(_ name: String) -> ExternalCommand 50| |} 51| | 52| |private final class ToolWrapper { 53| | let tool: Tool 54| | 55| 0| init(tool: Tool) { 56| 0| self.tool = tool 57| 0| } 58| | 59| | /// The owning list of all created commands. 60| | // 61| | // FIXME: This is lame, we should be able to destroy these naturally. 62| | private var commandWrappers: [CommandWrapper] = [] 63| 0| func createCommand(_ name: UnsafePointer) -> OpaquePointer? { 64| 0| let command = tool.createCommand(stringFromData(name.pointee)) 65| 0| let wrapper = CommandWrapper(command: command) 66| 0| self.commandWrappers.append(wrapper) 67| 0| var _delegate = llb_buildsystem_external_command_delegate_t() 68| 0| _delegate.context = Unmanaged.passUnretained(wrapper).toOpaque() 69| 0| _delegate.get_signature = { return BuildSystem.toCommandWrapper($0!).getSignature($1!, $2!) } 70| 0| _delegate.execute_command = { return BuildSystem.toCommandWrapper($0!).executeCommand($1!, $2!, $3!, $4!) } 71| 0| 72| 0| // Create the low-level command. 73| 0| wrapper._command = Command(llb_buildsystem_external_command_create(name, _delegate)) 74| 0| 75| 0| return wrapper._command.handle 76| 0| } 77| |} 78| | 79| |public protocol ExternalCommand: class { 80| | /// Get a signature used to identify the internal state of the command. 81| | /// 82| | /// This is checked to determine if the command needs to rebuild versus the last time it was run. 83| | func getSignature(_ command: Command) -> [UInt8] 84| | 85| | /// Called to execute the given command. 86| | /// 87| | /// - command: A handle to the executing command. 88| | /// - returns: True on success. 89| | func execute(_ command: Command) -> Bool 90| |} 91| | 92| |// FIXME: The terminology is really confusing here, we have ExternalCommand which is divorced from the actual internal command implementation of the same name. 93| |private final class CommandWrapper { 94| | let command: ExternalCommand 95| | var _command: Command 96| | 97| 0| init(command: ExternalCommand) { 98| 0| self.command = command 99| 0| self._command = Command(nil) 100| 0| } 101| | 102| 0| func getSignature(_: OpaquePointer, _ data: UnsafeMutablePointer) { 103| 0| data.pointee = copiedDataFromBytes(command.getSignature(_command)) 104| 0| } 105| | 106| 0| func executeCommand(_: OpaquePointer, _ bsci: OpaquePointer, _ task: OpaquePointer, _ jobContext: OpaquePointer) -> Bool { 107| 0| return command.execute(_command) 108| 0| } 109| |} 110| | 111| |/// Encapsulates a diagnostic as reported by the build system. 112| |public struct Diagnostic { 113| | public typealias Kind = DiagnosticKind 114| | 115| | /// The kind of diagnostic. 116| | public let kind: Kind 117| | 118| | /// The diagnostic location, if provided. 119| | public let location: (filename: String, line: Int, column: Int)? 120| | 121| | /// The diagnostic text. 122| | public let message: String 123| |} 124| | 125| |extension CommandStatusKind: CustomStringConvertible { 126| 0| public var description: String { 127| 0| switch self { 128| 0| case .isScanning: 129| 0| return "isScanning" 130| 0| case .isUpToDate: 131| 0| return "isUpToDate" 132| 0| case .isComplete: 133| 0| return "isComplete" 134| 0| @unknown default: 135| 0| return "unknown" 136| 0| } 137| 0| } 138| |} 139| | 140| |extension BuildKeyKind: CustomStringConvertible { 141| 0| public var description: String { 142| 0| switch self { 143| 0| case .command: 144| 0| return "command" 145| 0| case .customTask: 146| 0| return "customTask" 147| 0| case .directoryContents: 148| 0| return "directoryContents" 149| 0| case .directoryTreeSignature: 150| 0| return "directoryTreeSignature" 151| 0| case .node: 152| 0| return "node" 153| 0| case .target: 154| 0| return "target" 155| 0| case .unknown: 156| 0| return "unknown" 157| 0| case .directoryTreeStructureSignature: 158| 0| return "directoryTreeStructureSignature" 159| 0| case .filteredDirectoryContents: 160| 0| return "filteredDirectoryContents" 161| 0| case .stat: 162| 0| return "stat" 163| 0| @unknown default: 164| 0| return "unknown-\(rawValue)" 165| 0| } 166| 0| } 167| |} 168| | 169| |extension DiagnosticKind: CustomStringConvertible { 170| 0| public var description: String { 171| 0| switch self { 172| 0| case .note: 173| 0| return "note" 174| 0| case .warning: 175| 0| return "warning" 176| 0| case .error: 177| 0| return "error" 178| 0| @unknown default: 179| 0| return "unknown" 180| 0| } 181| 0| } 182| |} 183| | 184| |extension SchedulerAlgorithm { 185| 0| public init?(rawValue: String) { 186| 0| switch rawValue { 187| 0| case "commandNamePriority": 188| 0| self = .commandNamePriority 189| 0| case "fifo": 190| 0| self = .fifo 191| 0| default: 192| 0| return nil 193| 0| } 194| 0| } 195| |} 196| | 197| |/// Handle for a command as invoked by the low-level BuildSystem. 198| |public struct Command: Hashable, CustomStringConvertible, CustomDebugStringConvertible { 199| | fileprivate let handle: OpaquePointer? 200| | 201| 0| fileprivate init(_ handle: OpaquePointer?) { 202| 0| self.handle = handle 203| 0| } 204| | 205| | /// The command name. 206| | // 207| | // FIXME: We shouldn't need to expose this to use for mapping purposes, we should be able to use something more efficient. 208| 0| public var name: String { 209| 0| var data = llb_data_t() 210| 0| withUnsafeMutablePointer(to: &data) { (ptr: UnsafeMutablePointer) in 211| 0| llb_buildsystem_command_get_name(handle, ptr) 212| 0| } 213| 0| return stringFromData(data) 214| 0| } 215| | 216| | /// Whether the default status reporting shows status for the command. 217| 0| public var shouldShowStatus: Bool { 218| 0| return llb_buildsystem_command_should_show_status(handle) 219| 0| } 220| | 221| | /// The description provided by the command. 222| 0| public var description: String { 223| 0| let name = llb_buildsystem_command_get_description(handle)! 224| 0| defer { free(name) } 225| 0| 226| 0| return String(cString: name) 227| 0| } 228| | 229| | /// The verbose description provided by the command. 230| 0| public var verboseDescription: String { 231| 0| let name = llb_buildsystem_command_get_verbose_description(handle)! 232| 0| defer { free(name) } 233| 0| 234| 0| return String(cString: name) 235| 0| } 236| | 237| | /// The debug description provides the verbose description. 238| 0| public var debugDescription: String { 239| 0| return verboseDescription 240| 0| } 241| | 242| 0| public func hash(into hasher: inout Hasher) { 243| 0| hasher.combine(handle!) 244| 0| } 245| | 246| 0| public static func ==(lhs: Command, rhs: Command) -> Bool { 247| 0| return lhs.handle == rhs.handle 248| 0| } 249| |} 250| | 251| |/// Handle for a process which has been launched by a command. 252| |// 253| |// FIXME: We would like to call this Process, but then it conflicts with Swift's builtin Process. Maybe there is another name? 254| |public struct ProcessHandle: Hashable { 255| | fileprivate let handle: OpaquePointer 256| | 257| 0| fileprivate init(_ handle: OpaquePointer) { 258| 0| self.handle = handle 259| 0| } 260| | 261| 0| public func hash(into hasher: inout Hasher) { 262| 0| hasher.combine(handle.hashValue) 263| 0| } 264| | 265| 0| public static func ==(lhs: ProcessHandle, rhs: ProcessHandle) -> Bool { 266| 0| return lhs.handle == rhs.handle 267| 0| } 268| |} 269| | 270| |public struct CommandMetrics { 271| | public let utime: UInt64 /// User time (in us) 272| | public let stime: UInt64 /// Sys time (in us) 273| | public let maxRSS: UInt64 /// Max RSS (in bytes) 274| | 275| 0| public init(utime: UInt64, stime: UInt64, maxRSS: UInt64) { 276| 0| self.utime = utime 277| 0| self.stime = stime 278| 0| self.maxRSS = maxRSS 279| 0| } 280| |} 281| | 282| |/// Result of a command execution. 283| |public struct CommandExtendedResult { 284| | public let result: CommandResult /// The result of a command execution 285| | public let exitStatus: Int32 /// The exit code 286| | public let pid: llbuild_pid_t? /// The process identifier (nil if failed to create a process) 287| | public let metrics: CommandMetrics? /// Metrics about the executed command 288| | 289| 0| init(_ result: UnsafePointer) { 290| 0| self.result = result.pointee.result 291| 0| self.exitStatus = result.pointee.exit_status 292| 0| if result.pointee.pid >= 0 { 293| 0| self.pid = result.pointee.pid 294| 0| } else { 295| 0| self.pid = nil 296| 0| } 297| 0| switch self.result { 298| 0| case .succeeded, .failed: 299| 0| self.metrics = CommandMetrics(utime: result.pointee.utime, stime: result.pointee.stime, maxRSS: result.pointee.maxrss) 300| 0| default: 301| 0| self.metrics = nil 302| 0| } 303| 0| } 304| | 305| 0| public init(result: CommandResult, exitStatus: Int32, pid: llbuild_pid_t?, metrics: CommandMetrics? = nil) { 306| 0| self.result = result 307| 0| self.exitStatus = exitStatus 308| 0| self.pid = pid 309| 0| self.metrics = metrics 310| 0| } 311| | 312| |} 313| | 314| |/// The BuildKey encodes the key space used by the BuildSystem when using the 315| |/// core BuildEngine. 316| |public struct BuildKey { 317| | public typealias Kind = BuildKeyKind 318| | 319| | /// The kind of key 320| | public let kind: Kind 321| | 322| | /// The actual key data 323| | public let key: String 324| | 325| 0| public init(kind: Kind, key: String) { 326| 0| self.kind = kind 327| 0| self.key = key 328| 0| } 329| | 330| 0| init(key: llb_build_key_t) { 331| 0| self.init(kind: key.kind, key: String(cString: key.key)) 332| 0| } 333| |} 334| | 335| |/// File system information for a particular file. 336| |/// 337| |/// This is a simple wrapper for stat() information. 338| |public protocol FileInfo { 339| | /// Creates a new `FileInfo` object. 340| | init(_ statBuf: stat) 341| | 342| | var statBuf: stat { get } 343| |} 344| | 345| |/// Abstracted access to file system operations. 346| |// FIXME: We want to remove this protocol eventually and use the FileSystem 347| |// protocol from SwiftPM's Basic target. 348| |public protocol FileSystem { 349| | /// Get the contents of a file. 350| | func read(_ path: String) throws -> [UInt8] 351| | 352| | /// Returns the stat of a file at `path`. 353| | func getFileInfo(_ path: String) throws -> FileInfo 354| |} 355| | 356| |/// Delegate interface for use with the build system. 357| |public protocol BuildSystemDelegate { 358| | 359| | /// The FileSystem to use, if any. 360| | /// 361| | /// This is currently very limited. 362| | var fs: FileSystem? { get } 363| | 364| | /// Called in response to requests for new tools. 365| | /// 366| | /// The client should return an appropriate tool implementation if recognized. 367| | func lookupTool(_ name: String) -> Tool? 368| | 369| | /// Called to report any form of command failure. 370| | /// 371| | /// This can may be called to report the failure of a command which has 372| | /// executed, but may also be used to report the inability of a command to 373| | /// run. It is expected to be used by the client in making decisions with 374| | /// regard to cancelling the build. 375| | func hadCommandFailure() 376| | 377| | /// Called to report an unassociated diagnostic from the build system. 378| | func handleDiagnostic(_ diagnostic: Diagnostic) 379| | 380| | /// Called when a command has changed state. 381| | /// 382| | /// The system guarantees that any commandStart() call will be paired with 383| | /// exactly one \see commandFinished() call. 384| | func commandStatusChanged(_ command: Command, kind: CommandStatusKind) 385| | 386| | /// Called when a command is preparing to start. 387| | /// 388| | /// The system guarantees that any commandStart() call will be paired with 389| | /// exactly one \see commandFinished() call. 390| | func commandPreparing(_ command: Command) 391| | 392| | /// Called when a command has been started. 393| | /// 394| | /// The system guarantees that any commandStart() call will be paired with 395| | /// exactly one \see commandFinished() call. 396| | func commandStarted(_ command: Command) 397| | 398| | /// Called to allow the delegate to skip commands without cancelling their 399| | /// dependents. See llbuild's should_command_start. 400| | func shouldCommandStart(_ command: Command) -> Bool 401| | 402| | /// Called when a command has been finished. 403| | func commandFinished(_ command: Command, result: CommandResult) 404| | 405| | /// Called to report an error during the execution of a command. 406| | func commandHadError(_ command: Command, message: String) 407| | 408| | /// Called to report a note during the execution of a command. 409| | func commandHadNote(_ command: Command, message: String) 410| | 411| | /// Called to report a warning during the execution of a command. 412| | func commandHadWarning(_ command: Command, message: String) 413| | 414| | /// Called by the build system to report a command could not build due to 415| | /// missing inputs. 416| | func commandCannotBuildOutputDueToMissingInputs(_ command: Command, output: BuildKey, inputs: [BuildKey]) 417| | 418| | /// Called by the build system to report a node could not be built 419| | /// because multiple commands are producing it. 420| | func cannotBuildNodeDueToMultipleProducers(output: BuildKey, commands: [Command]) 421| | 422| | /// Called when a command's job has started executing an external process. 423| | /// 424| | /// The system guarantees that any commandProcessStarted() call will be paired 425| | /// with exactly one \see commandProcessFinished() call. 426| | /// 427| | /// - parameter process: A unique handle used in subsequent delegate calls 428| | /// to identify the process. This handle should only be used to associate 429| | /// different status calls relating to the same process. It is only 430| | /// guaranteed to be unique from when it has been provided here to when it 431| | /// has been provided to the \see commandProcessFinished() call. 432| | func commandProcessStarted(_ command: Command, process: ProcessHandle) 433| | 434| | /// Called to report an error in the management of a command process. 435| | /// 436| | /// - parameter process: The process handle. 437| | /// - parameter message: The error message. 438| | func commandProcessHadError(_ command: Command, process: ProcessHandle, message: String) 439| | 440| | /// Called to report a command processes' (merged) standard output and error. 441| | /// 442| | /// - parameter process: The process handle. 443| | /// - parameter data: The process output. 444| | func commandProcessHadOutput(_ command: Command, process: ProcessHandle, data: [UInt8]) 445| | 446| | /// Called when a command's job has finished executing an external process. 447| | /// 448| | /// - parameter process: The handle used to identify the process. This 449| | /// handle will become invalid as soon as the client returns from this API 450| | /// call. 451| | /// 452| | /// - parameter result: Whether the process suceeded, failed or was cancelled. 453| | /// - parameter exitStatus: The raw exit status of the process. 454| | func commandProcessFinished(_ command: Command, process: ProcessHandle, result: CommandExtendedResult) 455| | 456| | /// Called when a cycle is detected by the build engine and it cannot make 457| | /// forward progress. 458| | func cycleDetected(rules: [BuildKey]) 459| | 460| | /// Called when a cycle is detected by the build engine to check if it should 461| | /// attempt to resolve the cycle and continue 462| | /// 463| | /// - parameter rules: The ordered list of items comprising the cycle, 464| | /// starting from the node which was requested to build and ending with the 465| | /// first node in the cycle (i.e., the node participating in the cycle will 466| | /// appear twice). 467| | /// - parameter candidate: The rule the engine will use to attempt to break the 468| | /// cycle. 469| | /// - parameter action: The action the engine will take on the candidateRule. 470| | /// 471| | /// Returns true if the engine should attempt to resolve the cycle, false 472| | /// otherwise. Resolution is attempted by either forcing items to be built, or 473| | /// supplying a previously built result to a node in the cycle. The latter 474| | /// action may yield unexpected results and thus this should be opted into 475| | /// with care. 476| | func shouldResolveCycle(rules: [BuildKey], candidate: BuildKey, action: CycleAction) -> Bool 477| |} 478| | 479| |/// Utility class for constructing a C-style environment. 480| |private final class CStyleEnvironment { 481| | /// The list of individual bindings, which must be deallocated. 482| | private let bindings: [UnsafeMutablePointer] 483| | 484| | /// The environment array, which will be a valid C-style environment pointer 485| | /// for the lifetime of the instance. 486| | let envp: [UnsafePointer?] 487| | 488| 0| init(_ environment: [String: String]) { 489| 0| // Allocate the individual binding strings. 490| 0| self.bindings = environment.map{ "\($0.0)=\($0.1)".withCString(strdup)! } 491| 0| 492| 0| // Allocate the envp array. 493| 0| self.envp = self.bindings.map{ UnsafePointer($0) } + [nil] 494| 0| } 495| | 496| 0| deinit { 497| 0| bindings.forEach{ free($0) } 498| 0| } 499| |} 500| | 501| |/// This class allows building using llbuild's native BuildSystem component. 502| |public final class BuildSystem { 503| | /// The build file that the system is configured with. 504| | public let buildFile: String 505| | 506| | /// The delegate used by the system. 507| | public let delegate: BuildSystemDelegate 508| | 509| | /// The internal llbuild build system. 510| | private var _system: OpaquePointer? = nil 511| | 512| | /// The C environment, if used. 513| | private let _cEnvironment: CStyleEnvironment? 514| | 515| | /// The current scheduler algorithm 516| | private static var schedulerAlgorithm : SchedulerAlgorithm = .commandNamePriority 517| | 518| | /// The number of scheduler lanes 519| | private static var schedulerLanes : UInt32 = 0 520| | 521| 0| public init(buildFile: String, databaseFile: String, delegate: BuildSystemDelegate, environment: [String: String]? = nil, serial: Bool = false, traceFile: String? = nil) { 522| 0| 523| 0| // Safety check that we have linked against a compatibile llbuild framework version 524| 0| if llb_get_api_version() != LLBUILD_C_API_VERSION { 525| 0| fatalError("llbuild C API version mismatch, found \(llb_get_api_version()), expect \(LLBUILD_C_API_VERSION)") 526| 0| } 527| 0| 528| 0| self.buildFile = buildFile 529| 0| self.delegate = delegate 530| 0| 531| 0| // Create a stable C string path. 532| 0| let pathPtr = strdup(buildFile) 533| 0| defer { free(pathPtr) } 534| 0| 535| 0| let dbPathPtr = strdup(databaseFile) 536| 0| defer { free(dbPathPtr) } 537| 0| 538| 0| let tracePathPtr = strdup(traceFile ?? "") 539| 0| defer { free(tracePathPtr) } 540| 0| 541| 0| // Allocate a C style environment, if necessary. 542| 0| _cEnvironment = environment.map{ CStyleEnvironment($0) } 543| 0| 544| 0| var _invocation = llb_buildsystem_invocation_t() 545| 0| _invocation.buildFilePath = UnsafePointer(pathPtr) 546| 0| _invocation.dbPath = UnsafePointer(dbPathPtr) 547| 0| _invocation.traceFilePath = UnsafePointer(tracePathPtr) 548| 0| _invocation.environment = _cEnvironment.map{ UnsafePointer($0.envp) } 549| 0| _invocation.showVerboseStatus = true 550| 0| _invocation.useSerialBuild = serial 551| 0| _invocation.schedulerAlgorithm = BuildSystem.schedulerAlgorithm 552| 0| _invocation.schedulerLanes = BuildSystem.schedulerLanes 553| 0| 554| 0| // Construct the system delegate. 555| 0| var _delegate = llb_buildsystem_delegate_t() 556| 0| _delegate.context = Unmanaged.passUnretained(self).toOpaque() 557| 0| if delegate.fs != nil { 558| 0| _delegate.fs_get_file_contents = { BuildSystem.toSystem($0!).fsGetFileContents(String(cString: $1!), $2!) } 559| 0| _delegate.fs_get_file_info = { BuildSystem.toSystem($0!).fsGetFileInfo(String(cString: $1!), $2!) } 560| 0| // FIXME: This should be a separate callback, not shared with getFileInfo (or get FileInfo should take a parameter). 561| 0| _delegate.fs_get_link_info = { BuildSystem.toSystem($0!).fsGetFileInfo(String(cString: $1!), $2!) } 562| 0| } 563| 0| _delegate.lookup_tool = { return BuildSystem.toSystem($0!).lookupTool($1!) } 564| 0| _delegate.had_command_failure = { BuildSystem.toSystem($0!).hadCommandFailure() } 565| 0| _delegate.handle_diagnostic = { BuildSystem.toSystem($0!).handleDiagnostic($1, String(cString: $2!), Int($3), Int($4), String(cString: $5!)) } 566| 0| _delegate.command_status_changed = { BuildSystem.toSystem($0!).commandStatusChanged(Command($1), $2) } 567| 0| _delegate.command_preparing = { BuildSystem.toSystem($0!).commandPreparing(Command($1)) } 568| 0| _delegate.command_started = { BuildSystem.toSystem($0!).commandStarted(Command($1)) } 569| 0| _delegate.should_command_start = { BuildSystem.toSystem($0!).shouldCommandStart(Command($1)) } 570| 0| _delegate.command_finished = { BuildSystem.toSystem($0!).commandFinished(Command($1), $2) } 571| 0| _delegate.command_had_error = { BuildSystem.toSystem($0!).commandHadError(Command($1), $2!) } 572| 0| _delegate.command_had_note = { BuildSystem.toSystem($0!).commandHadNote(Command($1), $2!) } 573| 0| _delegate.command_had_warning = { BuildSystem.toSystem($0!).commandHadWarning(Command($1), $2!) } 574| 0| _delegate.command_cannot_build_output_due_to_missing_inputs = { 575| 0| let inputsPtr = $3! 576| 0| let inputs = (0.. Bool { 623| 0| var data = copiedDataFromBytes([UInt8](node.utf8)) 624| 0| return llb_buildsystem_build_node(_system, &data) 625| 0| } 626| | 627| | /// Build the default target, or optionally a specific target. 628| | /// 629| | /// The client is responsible for ensuring only one build is ever executing concurrently. 630| | /// 631| | /// - parameter target: Optional name of the target to build. 632| | /// - returns: True if the build was successful, false otherwise. 633| 0| public func build(target: String? = nil) -> Bool { 634| 0| var data = target.map({ copiedDataFromBytes([UInt8]($0.utf8)) }) ?? llb_data_t(length: 0, data: nil) 635| 0| return llb_buildsystem_build(_system, &data) 636| 0| } 637| | 638| | /// Cancel any running build. 639| 0| public func cancel() { 640| 0| llb_buildsystem_cancel(_system) 641| 0| } 642| | 643| | /// MARK: Internal Delegate Implementation 644| | 645| | /// Helper function for getting the system from the delegate context. 646| 0| static private func toSystem(_ context: UnsafeMutableRawPointer) -> BuildSystem { 647| 0| return Unmanaged.fromOpaque(UnsafeRawPointer(context)).takeUnretainedValue() 648| 0| } 649| | 650| | /// Helper function for getting the tool wrapper from the delegate context. 651| 0| static private func toToolWrapper(_ context: UnsafeMutableRawPointer) -> ToolWrapper { 652| 0| return Unmanaged.fromOpaque(UnsafeRawPointer(context)).takeUnretainedValue() 653| 0| } 654| | 655| | /// Helper function for getting the command wrapper from the delegate context. 656| 0| static fileprivate func toCommandWrapper(_ context: UnsafeMutableRawPointer) -> CommandWrapper { 657| 0| return Unmanaged.fromOpaque(UnsafeRawPointer(context)).takeUnretainedValue() 658| 0| } 659| | 660| 0| private func fsGetFileContents(_ path: String, _ data: UnsafeMutablePointer) -> Bool { 661| 0| let fs = delegate.fs! 662| 0| 663| 0| // Get the contents for the file. 664| 0| guard let contents = try? fs.read(path) else { 665| 0| return false 666| 0| } 667| 0| 668| 0| data.pointee = copiedDataFromBytes(contents) 669| 0| 670| 0| return true 671| 0| } 672| | 673| 0| private func fsGetFileInfo(_ path: String, _ info: UnsafeMutablePointer) { 674| 0| // Ignore invalid paths. 675| 0| guard path.first == "/" else { 676| 0| info.pointee = llb_fs_file_info_t() 677| 0| return 678| 0| } 679| 0| 680| 0| // If the path doesn't exist, it is missing. 681| 0| let fs = delegate.fs! 682| 0| guard let s = try? fs.getFileInfo(path).statBuf else { 683| 0| info.pointee = llb_fs_file_info_t() 684| 0| return 685| 0| } 686| 0| 687| 0| // Otherwise, we have some kind of file. 688| 0| info.pointee.device = UInt64(s.st_dev) 689| 0| info.pointee.inode = UInt64(s.st_ino) 690| 0| info.pointee.mode = UInt64(s.st_mode) 691| 0| info.pointee.size = UInt64(s.st_size) 692| 0| #if os(macOS) 693| 0| info.pointee.mod_time.seconds = UInt64(s.st_mtimespec.tv_sec) 694| 0| info.pointee.mod_time.nanoseconds = UInt64(s.st_mtimespec.tv_nsec) 695| 0| #else 696| 0| info.pointee.mod_time.seconds = UInt64(s.st_mtim.tv_sec) 697| 0| info.pointee.mod_time.nanoseconds = UInt64(s.st_mtim.tv_nsec) 698| 0| #endif 699| 0| } 700| | 701| 0| private func fsGetLinkInfo(_ path: String, _ info: UnsafeMutablePointer) { 702| 0| // FIXME: We do not support this natively, yet. 703| 0| return fsGetFileInfo(path, info) 704| 0| } 705| | 706| | /// The owning list of all created tools. 707| | // 708| | // FIXME: This is lame, we should be able to destroy these naturally. 709| | private var toolWrappers: [ToolWrapper] = [] 710| 0| private func lookupTool(_ name: UnsafePointer) -> OpaquePointer? { 711| 0| // Look up the named tool. 712| 0| guard let tool = delegate.lookupTool(stringFromData(name.pointee)) else { 713| 0| return nil 714| 0| } 715| 0| 716| 0| // If we got a tool, save it and create an appropriate low-level instance. 717| 0| let wrapper = ToolWrapper(tool: tool) 718| 0| self.toolWrappers.append(wrapper) 719| 0| var _delegate = llb_buildsystem_tool_delegate_t() 720| 0| _delegate.context = Unmanaged.passUnretained(wrapper).toOpaque() 721| 0| _delegate.create_command = { return BuildSystem.toToolWrapper($0!).createCommand($1!) } 722| 0| 723| 0| // Create the tool. 724| 0| return llb_buildsystem_tool_create(name, _delegate) 725| 0| } 726| | 727| 0| private func hadCommandFailure() { 728| 0| delegate.hadCommandFailure() 729| 0| } 730| | 731| 0| private func handleDiagnostic(_ kind: DiagnosticKind, _ filename: String, _ line: Int, _ column: Int, _ message: String) { 732| 0| // Clean up the location. 733| 0| let location: (filename: String, line: Int, column: Int)? 734| 0| if filename == "" || (line == -1 && column == -1) { 735| 0| location = nil 736| 0| } else { 737| 0| location = (filename: filename, line: line, column: column) 738| 0| } 739| 0| 740| 0| delegate.handleDiagnostic(Diagnostic(kind: kind, location: location, message: message)) 741| 0| } 742| | 743| 0| private func commandStatusChanged(_ command: Command, _ kind: CommandStatusKind) { 744| 0| delegate.commandStatusChanged(command, kind: kind) 745| 0| } 746| | 747| 0| private func commandPreparing(_ command: Command) { 748| 0| delegate.commandPreparing(command) 749| 0| } 750| | 751| 0| private func commandStarted(_ command: Command) { 752| 0| delegate.commandStarted(command) 753| 0| } 754| | 755| 0| private func shouldCommandStart(_ command: Command) -> Bool { 756| 0| return delegate.shouldCommandStart(command) 757| 0| } 758| | 759| 0| private func commandFinished(_ command: Command, _ result: CommandResult) { 760| 0| delegate.commandFinished(command, result: result) 761| 0| } 762| | 763| 0| private func commandHadError(_ command: Command, _ data: UnsafePointer) { 764| 0| delegate.commandHadError(command, message: stringFromData(data.pointee)) 765| 0| } 766| | 767| 0| private func commandHadNote(_ command: Command, _ data: UnsafePointer) { 768| 0| delegate.commandHadNote(command, message: stringFromData(data.pointee)) 769| 0| } 770| | 771| 0| private func commandHadWarning(_ command: Command, _ data: UnsafePointer) { 772| 0| delegate.commandHadWarning(command, message: stringFromData(data.pointee)) 773| 0| } 774| | 775| 0| private func commandCannotBuildOutputDueToMissingInputs(_ command: Command, _ output: BuildKey, _ inputs: [BuildKey]) { 776| 0| delegate.commandCannotBuildOutputDueToMissingInputs(command, output: output, inputs: inputs) 777| 0| } 778| | 779| 0| private func cannotBuildNodeDueToMultipleProducers(_ output: BuildKey, _ commands: [Command]) { 780| 0| delegate.cannotBuildNodeDueToMultipleProducers(output: output, commands: commands) 781| 0| } 782| | 783| 0| private func commandProcessStarted(_ command: Command, _ process: ProcessHandle) { 784| 0| delegate.commandProcessStarted(command, process: process) 785| 0| } 786| | 787| 0| private func commandProcessHadError(_ command: Command, _ process: ProcessHandle, _ data: UnsafePointer) { 788| 0| delegate.commandProcessHadError(command, process: process, message: stringFromData(data.pointee)) 789| 0| } 790| | 791| 0| private func commandProcessHadOutput(_ command: Command, _ process: ProcessHandle, _ data: UnsafePointer) { 792| 0| delegate.commandProcessHadOutput(command, process: process, data: bytesFromData(data.pointee)) 793| 0| } 794| | 795| 0| private func commandProcessFinished(_ command: Command, _ process: ProcessHandle, _ result: CommandExtendedResult) { 796| 0| delegate.commandProcessFinished(command, process: process, result: result) 797| 0| } 798| | 799| 0| private func cycleDetected(_ rules: [BuildKey]) { 800| 0| delegate.cycleDetected(rules: rules) 801| 0| } 802| | 803| 0| private func shouldResolveCycle(_ rules: [BuildKey], _ candidate: BuildKey, _ action: CycleAction) -> Bool { 804| 0| return delegate.shouldResolveCycle(rules: rules, candidate: candidate, action: action) 805| 0| } 806| | 807| | 808| | /// Toggle tracing 809| 0| public static func setTracing(enabled: Bool) { 810| 0| if (enabled) { 811| 0| llb_enable_tracing() 812| 0| } else { 813| 0| llb_disable_tracing() 814| 0| } 815| 0| } 816| | 817| | public typealias SchedulerAlgorithm = llbuild.SchedulerAlgorithm 818| | 819| | /// Get the scheduler algorithm 820| 0| public static func getSchedulerAlgorithm() -> SchedulerAlgorithm { 821| 0| return schedulerAlgorithm 822| 0| } 823| | 824| | /// Set scheduler algorithm 825| 0| public static func setSchedulerAlgorithm(_ algorithm: SchedulerAlgorithm) { 826| 0| schedulerAlgorithm = algorithm 827| 0| } 828| | 829| | /// Get scheduler lane width 830| 0| public static func getSchedulerLaneWidth() -> UInt32 { 831| 0| return schedulerLanes 832| 0| } 833| | 834| | /// Set scheduler lane width 835| 0| public static func setSchedulerLaneWidth(width: UInt32) { 836| 0| schedulerLanes = width 837| 0| } 838| |} 839| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/products/llbuildSwift/CoreBindings.swift: 1| |// This source file is part of the Swift.org open source project 2| |// 3| |// Copyright 2015-2017 Apple Inc. and the Swift project authors 4| |// Licensed under Apache License v2.0 with Runtime Library Exception 5| |// 6| |// See http://swift.org/LICENSE.txt for license information 7| |// See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8| | 9| |// This file contains Swift bindings for the llbuild C API. 10| | 11| |import Foundation 12| | 13| |// We don't need this import if we're building 14| |// this file as part of the llbuild framework. 15| |#if !LLBUILD_FRAMEWORK 16| |import llbuild 17| |#endif 18| | 19| |enum DatabaseError: Error { 20| | case AttachFailure(message: String) 21| |} 22| | 23| 0|private func stringFromData(data: llb_data_t) -> String { 24| 0| // Convert as a UTF8 string, if possible. 25| 0| let tmp = Data(UnsafeBufferPointer(start: unsafeBitCast(data.data, to: UnsafePointer.self), count: Int(data.length))) 26| 0| if let str = String(data: tmp, encoding: String.Encoding.utf8) { 27| 0| return str 28| 0| } 29| 0| 30| 0| // Otherwise, return a string representation of the bytes. 31| 0| return String(describing: [UInt8](UnsafeBufferPointer(start: data.data, count: Int(data.length)))) 32| 0|} 33| | 34| 0|private func stringFromUInt8Array(_ data: [UInt8]) -> String { 35| 0| // Convert as a UTF8 string, if possible. 36| 0| if let str = String(data: Data(data), encoding: String.Encoding.utf8) { 37| 0| return str 38| 0| } 39| 0| 40| 0| // Otherwise, return a string representation of the bytes. 41| 0| return String(describing: data) 42| 0|} 43| | 44| |/// Key objects are used to identify rules that can be built. 45| |public struct Key: CustomStringConvertible, Equatable, Hashable { 46| | public let data: [UInt8] 47| | 48| | // MARK: CustomStringConvertible Conformance 49| | 50| 0| public var description: String { 51| 0| return "" 52| 0| } 53| | 54| | // MARK: Hashable Conformance 55| | 56| 0| public func hash(into hasher: inout Hasher) { 57| 0| hasher.combine(data) 58| 0| } 59| | 60| | // MARK: Implementation 61| | 62| 0| public init(_ data: [UInt8]) { self.data = data } 63| 0| public init(_ str: String) { self.init(Array(str.utf8)) } 64| | 65| | /// Convert to a string representation. 66| 0| public func toString() -> String { 67| 0| return stringFromUInt8Array(self.data) 68| 0| } 69| | 70| | /// Create a Key object from an llb_data_t. 71| 0| fileprivate static func fromInternalData(_ data: llb_data_t) -> Key { 72| 0| return Key([UInt8](UnsafeBufferPointer(start: data.data, count: Int(data.length)))) 73| 0| } 74| | 75| | /// Provide a Key contents as an llb_data_t pointer. 76| 0| fileprivate func withInternalDataPtr(closure: (UnsafePointer) -> T) -> T { 77| 0| return data.withUnsafeBufferPointer { (dataPtr: UnsafeBufferPointer) -> T in 78| 0| var value = llb_data_t(length: UInt64(self.data.count), data: dataPtr.baseAddress) 79| 0| return withUnsafePointer(to: &value, closure) 80| 0| } 81| 0| } 82| |} 83| | 84| 0|public func ==(lhs: Key, rhs: Key) -> Bool { 85| 0| return lhs.data == rhs.data 86| 0|} 87| | 88| |/// Value objects are the result of building rules. 89| |public struct Value: CustomStringConvertible { 90| | public let data: [UInt8] 91| | 92| 0| public var description: String { 93| 0| return "" 94| 0| } 95| | 96| 0| public init(_ data: [UInt8]) { self.data = data } 97| 0| public init(_ str: String) { self.init(Array(str.utf8)) } 98| | 99| | /// Convert to a string representation. 100| 0| public func toString() -> String { 101| 0| return stringFromUInt8Array(self.data) 102| 0| } 103| | 104| | /// Create a Value object from an llb_data_t. 105| 0| fileprivate static func fromInternalData(_ data: llb_data_t) -> Value { 106| 0| return Value([UInt8](UnsafeBufferPointer(start: data.data, count: Int(data.length)))) 107| 0| } 108| | 109| | /// Provide a Value contents as an llb_data_t pointer. 110| 0| fileprivate func withInternalDataPtr(closure: (UnsafePointer) -> T) -> T { 111| 0| return data.withUnsafeBufferPointer { (dataPtr: UnsafeBufferPointer) -> T in 112| 0| var value = llb_data_t(length: UInt64(self.data.count), data: dataPtr.baseAddress) 113| 0| return withUnsafePointer(to: &value, closure) 114| 0| } 115| 0| } 116| | 117| | /// Create a Value object by providing an pointer to write the output into. 118| | /// 119| | /// \param closure The closure to execute with a pointer to a llb_data_t to 120| | /// use. The structure *must* be filled in by the closure. 121| | /// 122| | /// \return The output Value. 123| 0| fileprivate static func fromInternalDataOutputPtr(closure: (UnsafeMutablePointer) -> Void) -> Value { 124| 0| var data = llb_data_t() 125| 0| withUnsafeMutablePointer(to: &data, closure) 126| 0| return Value.fromInternalData(data) 127| 0| } 128| |} 129| | 130| |/// A rule represents an individual element of computation that can be performed 131| |/// by the build engine. 132| |/// 133| |/// Each rule is identified by a unique key and the value for that key can be 134| |/// computed to produce a result, and supplies a set of callbacks that are used 135| |/// to implement the rule's behavior. 136| |/// 137| |/// The computation for a rule is done by invocation of its \see Action 138| |/// callback, which is responsible for creating a Task object which will manage 139| |/// the computation. 140| |/// 141| |/// All callbacks for the Rule are always invoked synchronously on the primary 142| |/// BuildEngine thread. 143| |public protocol Rule { 144| | /// Called to create the task to build the rule, when necessary. 145| | func createTask() -> Task 146| | 147| | /// Called to check whether the previously computed value for this rule is 148| | /// still valid. 149| | /// 150| | /// This callback is designed for use in synchronizing values which represent 151| | /// state managed externally to the build engine. For example, a rule which 152| | /// computes something on the file system may use this to verify that the 153| | /// computed output has not changed since it was built. 154| | func isResultValid(_ priorValue: Value) -> Bool 155| | 156| | /// Called to indicate a change in the rule status. 157| | func updateStatus(_ status: RuleStatus) 158| |} 159| | 160| |/// Protocol extension for default Rule methods. 161| |public extension Rule { 162| 0| func isResultValid(_ priorValue: Value) -> Bool { return true } 163| 0| func updateStatus(_ status: RuleStatus) { } 164| |} 165| | 166| |/// A task object represents an abstract in-progress computation in the build 167| |/// engine. 168| |/// 169| |/// The task represents not just the primary computation, but also the process 170| |/// of starting the computation and necessary input dependencies. Tasks are 171| |/// expected to be created in response to \see BuildEngine requests to initiate 172| |/// the production of particular result value. 173| |/// 174| |/// The creator may use \see TaskBuildEngine.taskNeedsInput() to specify input 175| |/// dependencies on the Task. The Task itself may also specify additional input 176| |/// dependencies dynamically during the execution of \see Task.start() or \see 177| |/// Task.provideValue(). 178| |/// 179| |/// Once a task has been created and registered, the BuildEngine will invoke 180| |/// \see Task::start() to initiate the computation. The BuildEngine will provide 181| |/// the in progress task with its requested inputs via \see 182| |/// Task.provideValue(). 183| |/// 184| |/// After all inputs requested by the Task have been delivered, the BuildEngine 185| |/// will invoke \see Task.inputsAvailable() to instruct the Task it should 186| |/// complete its computation and provide the output. The Task is responsible for 187| |/// providing the engine with the computed value when ready using \see 188| |/// TaskBuildEngine.taskIsComplete(). 189| |public protocol Task { 190| | /// Executed by the build engine when the task should be started. 191| | func start(_ engine: TaskBuildEngine) 192| | 193| | /// Invoked by the build engine to provide an input value as it becomes 194| | /// available. 195| | /// 196| | /// \param inputID The unique identifier provided to the build engine to 197| | /// represent this input when requested in \see 198| | /// TaskBuildEngine.taskNeedsInput(). 199| | /// 200| | /// \param value The computed value for the given input. 201| | func provideValue(_ engine: TaskBuildEngine, inputID: Int, value: Value) 202| | 203| | /// Executed by the build engine to indicate that all inputs have been 204| | /// provided, and the task should begin its computation. 205| | /// 206| | /// The task is expected to call \see TaskBuildEngine.taskIsComplete() when it is 207| | /// done with its computation. 208| | /// 209| | /// It is an error for any client to request an additional input for a task 210| | /// after the last requested input has been provided by the build engine. 211| | func inputsAvailable(_ engine: TaskBuildEngine) 212| |} 213| | 214| |/// Delegate interface for use with the build engine. 215| |public protocol BuildEngineDelegate { 216| | /// Get the rule to use for the given Key. 217| | /// 218| | /// The delegate *must* provide a rule for any possible key that can be 219| | /// requested (either by a client, through \see BuildEngine.build(), or via a 220| | /// Task through mechanisms such as \see TaskBuildEngine.taskNeedsInput(). If a 221| | /// requested Key cannot be supplied, the delegate should provide a dummy rule 222| | /// that the client can translate into an error. 223| | func lookupRule(_ key: Key) -> Rule 224| | 225| | /// Handle error message reported by the engine 226| | /// 227| | /// The delegate should handle this, but a default implementation is 228| | /// is provided that does nothing for backward compatiblity. 229| | func error(_ message: String) 230| |} 231| | 232| |public extension BuildEngineDelegate { 233| 0| func error(_ message: String) { 234| 0| } 235| |} 236| | 237| |/// Wrapper to allow passing an opaque pointer to a protocol type. 238| |// 239| |// FIXME: Why do we need this, why can't we get a pointer to the protocol 240| |// typed object? 241| |private class Wrapper { 242| | let item: T 243| 0| init(_ item: T) { self.item = item } 244| |} 245| | 246| |/// This protocol encapsulates the API that a task can use to communicate with 247| |/// the build engine. 248| |public protocol TaskBuildEngine { 249| | var engine: BuildEngine { get } 250| | 251| | /// Specify that the task depends upon the result of computing \arg key. 252| | /// 253| | /// The result, when available, will be provided to the task via \see 254| | /// Task.provideValue(), supplying the provided \arg inputID to allow the task 255| | /// to identify the particular input. 256| | /// 257| | /// NOTE: It is an unchecked error for a task to request the same input value 258| | /// multiple times. 259| | /// 260| | /// \param inputID An arbitrary value that may be provided by the client to 261| | /// use in efficiently associating this input. 262| | func taskNeedsInput(_ key: Key, inputID: Int) 263| | 264| | /// Specify that the task must be built subsequent to the computation of \arg 265| | /// key. 266| | /// 267| | /// The value of the computation of \arg key is not available to the task, and 268| | /// the only guarantee the engine provides is that if \arg key is computed 269| | /// during a build, then task will not be computed until after it. 270| | func taskMustFollow(_ key: Key) 271| | 272| | /// Inform the engine of an input dependency that was discovered by the task 273| | /// during its execution, a la compiler generated dependency files. 274| | /// 275| | /// This call may only be made after a task has received all of its inputs; 276| | /// inputs discovered prior to that point should simply be requested as normal 277| | /// input dependencies. 278| | /// 279| | /// Such a dependency is not used to provide additional input to the task, 280| | /// rather it is a way for the task to report an additional input which should 281| | /// be considered the next time the rule is evaluated. The expected use case 282| | /// for a discovered dependency is is when a processing task cannot predict 283| | /// all of its inputs prior to being run, but can presume that any unknown 284| | /// inputs already exist. In such cases, the task can go ahead and run and can 285| | /// report the all of the discovered inputs as it executes. Once the task is 286| | /// complete, these inputs will be recorded as being dependencies of the task 287| | /// so that it will be recomputed when any of the inputs change. 288| | /// 289| | /// It is legal to call this method from any thread, but the caller is 290| | /// responsible for ensuring that it is never called concurrently for the same 291| | /// task. 292| | func taskDiscoveredDependency(_ key: Key) 293| | 294| | /// Indicate that the task has completed and provide its resulting value. 295| | /// 296| | /// It is legal to call this method from any thread. 297| | /// 298| | /// \param value The new value for the task's rule. 299| | /// 300| | /// \param forceChange If true, treat the value as changed and trigger 301| | /// dependents to rebuild, even if the value itself is not different from the 302| | /// prior result. 303| | func taskIsComplete(_ result: Value, forceChange: Bool) 304| |} 305| | 306| |extension TaskBuildEngine { 307| | /// Indicate that the task has completed and provide its resulting value. 308| | /// 309| | /// It is legal to call this method from any thread. 310| | /// 311| | /// - Parameter result: value The new value for the task's rule. 312| 0| public func taskIsComplete(_ result: Value) { 313| 0| self.taskIsComplete(result, forceChange: false) 314| 0| } 315| |} 316| | 317| |/// Single concrete implementation of the TaskBuildEngine protocol. 318| |private class TaskWrapper: CustomStringConvertible, TaskBuildEngine { 319| | let engine: BuildEngine 320| | let task: Task 321| | var taskInternal: OpaquePointer? 322| | 323| 0| var description: String { 324| 0| return "" 325| 0| } 326| | 327| 0| init(_ engine: BuildEngine, _ task: Task) { 328| 0| self.engine = engine 329| 0| self.task = task 330| 0| } 331| | 332| 0| func taskNeedsInput(_ key: Key, inputID: Int) { 333| 0| engine.taskNeedsInput(self, key: key, inputID: inputID) 334| 0| } 335| | 336| 0| func taskMustFollow(_ key: Key) { 337| 0| engine.taskMustFollow(self, key: key) 338| 0| } 339| | 340| 0| func taskDiscoveredDependency(_ key: Key) { 341| 0| engine.taskDiscoveredDependency(self, key: key) 342| 0| } 343| | 344| 0| func taskIsComplete(_ result: Value, forceChange: Bool = false) { 345| 0| engine.taskIsComplete(self, result: result, forceChange: forceChange) 346| 0| } 347| |} 348| | 349| |/// A build engine supports fast, incremental, persistent, and parallel 350| |/// execution of computational graphs. 351| |/// 352| |/// Computational elements in the graph are modeled by \see Rule objects, which 353| |/// are assocated with a specific \see Key, and which can be executed to produce 354| |/// an output \see Value for that key. 355| |/// 356| |/// Rule objects are evaluated by first invoking their action to produce a \see 357| |/// Task object which is responsible for the live execution of the 358| |/// computation. The Task object can interact with the BuildEngine to request 359| |/// inputs or to notify the engine of its completion, and receives various 360| |/// callbacks from the engine as the computation progresses. 361| |/// 362| |/// The engine itself executes using a deterministic, serial operation, but it 363| |/// supports parallel computation by allowing the individual Task objects to 364| |/// defer their own computation to signal the BuildEngine of its completion on 365| |/// alternate threads. 366| |/// 367| |/// To support persistence, the engine allows attaching a database (\see 368| |/// attachDB()) which can be used to record the prior results of evaluating Rule 369| |/// instances. 370| |public class BuildEngine { 371| | /// The client delegate. 372| | private var delegate: BuildEngineDelegate 373| | 374| | /// The internal llbuild build engine. 375| | private var _engine: OpaquePointer? 376| | 377| | /// Our llbuild engine delegate object. 378| | private var _delegate = llb_buildengine_delegate_t() 379| | 380| | /// The number of rules which have been defined. 381| | public var numRules: Int = 0 382| | 383| 0| public init(delegate: BuildEngineDelegate) { 384| 0| self.delegate = delegate 385| 0| 386| 0| // Initialize the delegate. 387| 0| _delegate.context = unsafeBitCast(Unmanaged.passUnretained(self), to: UnsafeMutableRawPointer.self) 388| 0| 389| 0| _delegate.lookup_rule = { BuildEngine.toEngine($0!).lookupRule($1!, $2!) } 390| 0| // FIXME: Include cycleDetected callback. 391| 0| 392| 0| _delegate.error = { BuildEngine.toEngine($0!).delegate.error(String(cString: $1!)) } 393| 0| 394| 0| // Create the engine. 395| 0| _engine = llb_buildengine_create(_delegate) 396| 0| } 397| | 398| 0| deinit { 399| 0| if _engine != nil { 400| 0| close() 401| 0| } 402| 0| } 403| | 404| 0| public func close() { 405| 0| assert(_engine != nil) 406| 0| llb_buildengine_destroy(_engine) 407| 0| _engine = nil 408| 0| } 409| | 410| | /// Build the result for a particular key. 411| 0| public func build(key: Key) -> Value { 412| 0| return Value.fromInternalDataOutputPtr { resultPtr in 413| 0| key.withInternalDataPtr { llb_buildengine_build(self._engine, $0, resultPtr) } 414| 0| } 415| 0| } 416| | 417| | /// Attach a database for persisting build state. 418| | /// 419| | /// A database should only be attached immediately after creating the engine, 420| | /// it is an error to attach a database after adding rules or initiating any 421| | /// builds, or to attempt to attach multiple databases. 422| 0| public func attachDB(path: String, schemaVersion: Int = 0) throws { 423| 0| let errorPtr = UnsafeMutablePointer?>.allocate(capacity: 1) 424| 0| defer { errorPtr.deallocate() } 425| 0| 426| 0| // FIXME: Why do I have to name the closure signature here? 427| 0| var errorMsgOpt: String? = nil 428| 0| Key(path).withInternalDataPtr { (ptr) -> Void in 429| 0| if !llb_buildengine_attach_db(self._engine, ptr, UInt32(schemaVersion), errorPtr) { 430| 0| // If there was an error, report it. 431| 0| if let errorPointee = errorPtr.pointee { 432| 0| defer { errorPointee.deallocate() } 433| 0| errorMsgOpt = String(cString: errorPointee) 434| 0| } 435| 0| } 436| 0| } 437| 0| // Throw the error, if found. 438| 0| if let errorMsg = errorMsgOpt { 439| 0| throw DatabaseError.AttachFailure(message: errorMsg) 440| 0| } 441| 0| } 442| | 443| | /// MARK: Internal Task-Only API 444| | 445| 0| fileprivate func taskNeedsInput(_ taskWrapper: TaskWrapper, key: Key, inputID: Int) { 446| 0| key.withInternalDataPtr { keyPtr in 447| 0| llb_buildengine_task_needs_input(self._engine, taskWrapper.taskInternal, keyPtr, UInt(inputID)) 448| 0| } 449| 0| } 450| | 451| 0| fileprivate func taskMustFollow(_ taskWrapper: TaskWrapper, key: Key) { 452| 0| key.withInternalDataPtr { keyPtr in 453| 0| llb_buildengine_task_must_follow(self._engine, taskWrapper.taskInternal, keyPtr) 454| 0| } 455| 0| } 456| | 457| 0| fileprivate func taskDiscoveredDependency(_ taskWrapper: TaskWrapper, key: Key) { 458| 0| key.withInternalDataPtr { keyPtr in 459| 0| llb_buildengine_task_discovered_dependency(self._engine, taskWrapper.taskInternal, keyPtr) 460| 0| } 461| 0| } 462| | 463| 0| fileprivate func taskIsComplete(_ taskWrapper: TaskWrapper, result: Value, forceChange: Bool = false) { 464| 0| result.withInternalDataPtr { dataPtr in 465| 0| llb_buildengine_task_is_complete(self._engine, taskWrapper.taskInternal, dataPtr, forceChange) 466| 0| } 467| 0| } 468| | 469| | /// MARK: Internal Delegate Implementation 470| | 471| | /// Helper function for getting the engine from the delegate context. 472| 0| static fileprivate func toEngine(_ context: UnsafeMutableRawPointer) -> BuildEngine { 473| 0| return Unmanaged.fromOpaque(context).takeUnretainedValue() 474| 0| } 475| | 476| | /// Helper function for getting the rule from a rule delegate context. 477| 0| static fileprivate func toRule(_ context: UnsafeMutableRawPointer) -> Rule { 478| 0| return Unmanaged>.fromOpaque(context).takeUnretainedValue().item 479| 0| } 480| | 481| | /// Helper function for getting the task from a task delegate context. 482| 0| static fileprivate func toTaskWrapper(_ context: UnsafeMutableRawPointer) -> TaskWrapper { 483| 0| return Unmanaged.fromOpaque(context).takeUnretainedValue() 484| 0| } 485| | 486| 0| fileprivate func lookupRule(_ key: UnsafePointer, _ ruleOut: UnsafeMutablePointer) { 487| 0| numRules += 1 488| 0| 489| 0| // Get the rule from the client. 490| 0| let rule = delegate.lookupRule(Key.fromInternalData(key.pointee)) 491| 0| 492| 0| // Fill in the output structure. 493| 0| // 494| 0| // FIXME: We need a deallocation callback in order to ensure this is released. 495| 0| ruleOut.pointee.context = unsafeBitCast(Unmanaged.passRetained(Wrapper(rule)), to: UnsafeMutableRawPointer.self) 496| 0| ruleOut.pointee.create_task = { (context, engineContext) -> OpaquePointer? in 497| 0| let rule = BuildEngine.toRule(context!) 498| 0| let engine = BuildEngine.toEngine(engineContext!) 499| 0| return engine.ruleCreateTask(rule) 500| 0| } 501| 0| ruleOut.pointee.is_result_valid = { (context, engineContext, internalRule, value) -> Bool in 502| 0| let rule = BuildEngine.toRule(context!) 503| 0| return rule.isResultValid(Value.fromInternalData(value!.pointee)) 504| 0| } 505| 0| ruleOut.pointee.update_status = { (context, engineContext, status) in 506| 0| let rule = BuildEngine.toRule(context!) 507| 0| return rule.updateStatus(status) 508| 0| } 509| 0| } 510| | 511| 0| private func ruleCreateTask(_ rule: Rule) -> OpaquePointer { 512| 0| // Create the task. 513| 0| let task = rule.createTask() 514| 0| 515| 0| // Create the task wrapper. 516| 0| // 517| 0| // Note that the wrapper here is serving two purposes, it is providing a way 518| 0| // to communicate the internal task object to clients, and it is providing a 519| 0| // way to segregate the Task-only API from the rest of the BuildEngine API. 520| 0| let taskWrapper = TaskWrapper(self, task) 521| 0| 522| 0| // Create the task delegate. 523| 0| // 524| 0| // FIXME: Separate the delegate from the context pointer. 525| 0| var taskDelegate = llb_task_delegate_t() 526| 0| taskDelegate.context = unsafeBitCast(Unmanaged.passRetained(taskWrapper), to: UnsafeMutableRawPointer.self) 527| 0| taskDelegate.destroy_context = { (context) in 528| 0| Unmanaged.fromOpaque(context!).release() 529| 0| } 530| 0| taskDelegate.start = { (context, engineContext, internalTask) in 531| 0| let taskWrapper = BuildEngine.toTaskWrapper(context!) 532| 0| taskWrapper.task.start(taskWrapper) 533| 0| } 534| 0| taskDelegate.provide_value = { (context, engineContext, internalTask, inputID, value) in 535| 0| let taskWrapper = BuildEngine.toTaskWrapper(context!) 536| 0| taskWrapper.task.provideValue(taskWrapper, inputID: Int(inputID), value: Value.fromInternalData(value!.pointee)) 537| 0| } 538| 0| taskDelegate.inputs_available = { (context, engineContext, internalTask) in 539| 0| let taskWrapper = BuildEngine.toTaskWrapper(context!) 540| 0| taskWrapper.task.inputsAvailable(taskWrapper) 541| 0| } 542| 0| 543| 0| // Create the internal task. 544| 0| taskWrapper.taskInternal = llb_task_create(taskDelegate) 545| 0| 546| 0| // FIXME: Why do we have both of these, it is kind of annoying. It makes 547| 0| // some amount of sense in the C++ API, but the C API should probably just 548| 0| // collapse them. 549| 0| return llb_buildengine_register_task(self._engine, taskWrapper.taskInternal) 550| 0| } 551| |} 552| | <<<<<< EOF # path=PackageModel.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/BuildSettings.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |public enum BuildConfiguration: String { 14| | case debug 15| | case release 16| | 17| 0| public var dirname: String { 18| 0| switch self { 19| 0| case .debug: return "debug" 20| 0| case .release: return "release" 21| 0| } 22| 0| } 23| |} 24| | 25| |/// A build setting condition. 26| |public protocol BuildSettingsCondition {} 27| | 28| |/// Namespace for build settings. 29| |public enum BuildSettings { 30| | 31| | /// Build settings declarations. 32| | public struct Declaration: Hashable { 33| | // Swift. 34| | public static let SWIFT_ACTIVE_COMPILATION_CONDITIONS: Declaration = .init("SWIFT_ACTIVE_COMPILATION_CONDITIONS") 35| | public static let OTHER_SWIFT_FLAGS: Declaration = .init("OTHER_SWIFT_FLAGS") 36| | 37| | // C family. 38| | public static let GCC_PREPROCESSOR_DEFINITIONS: Declaration = .init("GCC_PREPROCESSOR_DEFINITIONS") 39| | public static let HEADER_SEARCH_PATHS: Declaration = .init("HEADER_SEARCH_PATHS") 40| | public static let OTHER_CFLAGS: Declaration = .init("OTHER_CFLAGS") 41| | public static let OTHER_CPLUSPLUSFLAGS: Declaration = .init("OTHER_CPLUSPLUSFLAGS") 42| | 43| | // Linker. 44| | public static let OTHER_LDFLAGS: Declaration = .init("OTHER_LDFLAGS") 45| | public static let LINK_LIBRARIES: Declaration = .init("LINK_LIBRARIES") 46| | public static let LINK_FRAMEWORKS: Declaration = .init("LINK_FRAMEWORKS") 47| | 48| | /// The declaration name. 49| | public let name: String 50| | 51| 0| private init(_ name: String) { 52| 0| self.name = name 53| 0| } 54| | 55| | /// The list of settings that are considered as unsafe build settings. 56| | public static let unsafeSettings: Set = [ 57| | OTHER_CFLAGS, OTHER_CPLUSPLUSFLAGS, OTHER_SWIFT_FLAGS, OTHER_LDFLAGS, 58| | ] 59| | } 60| | 61| | /// Platforms condition implies that an assignment is valid on these platforms. 62| | public struct PlatformsCondition: BuildSettingsCondition { 63| | public var platforms: [Platform] { 64| 0| didSet { 65| 0| assert(!platforms.isEmpty, "List of platforms should not be empty") 66| 0| } 67| | } 68| | 69| 0| public init() { 70| 0| self.platforms = [] 71| 0| } 72| | } 73| | 74| | /// A configuration condition implies that an assignment is valid on 75| | /// a particular build configuration. 76| | public struct ConfigurationCondition: BuildSettingsCondition { 77| | public var config: BuildConfiguration 78| | 79| 0| public init(_ config: BuildConfiguration) { 80| 0| self.config = config 81| 0| } 82| | } 83| | 84| | /// An individual build setting assignment. 85| | public struct Assignment { 86| | /// The assignment value. 87| | public var value: [String] 88| | 89| | // FIXME: This should be a set but we need Equatable existential (or AnyEquatable) for that. 90| | /// The condition associated with this assignment. 91| | public var conditions: [BuildSettingsCondition] 92| | 93| 0| public init() { 94| 0| self.conditions = [] 95| 0| self.value = [] 96| 0| } 97| | } 98| | 99| | /// Build setting assignment table which maps a build setting to a list of assignments. 100| | public struct AssignmentTable { 101| | public private(set) var assignments: [Declaration: [Assignment]] 102| | 103| 0| public init() { 104| 0| assignments = [:] 105| 0| } 106| | 107| | /// Add the given assignment to the table. 108| 0| mutating public func add(_ assignment: Assignment, for decl: Declaration) { 109| 0| // FIXME: We should check for duplicate assignments. 110| 0| assignments[decl, default: []].append(assignment) 111| 0| } 112| | } 113| | 114| | /// Provides a view onto assignment table with a given set of bound parameters. 115| | /// 116| | /// This class can be used to get the assignments matching the bound parameters. 117| | public final class Scope { 118| | /// The assignment table. 119| | public let table: AssignmentTable 120| | 121| | /// The bound platform. 122| | public let boundPlatform: Platform 123| | 124| | /// The bound build configuration. 125| | public let boundConfig: BuildConfiguration 126| | 127| 0| public init(_ table: AssignmentTable, boundCondition: (Platform, BuildConfiguration)) { 128| 0| self.table = table 129| 0| self.boundPlatform = boundCondition.0 130| 0| self.boundConfig = boundCondition.1 131| 0| } 132| | 133| | /// Evaluate the given declaration and return the values matching the bound parameters. 134| 0| public func evaluate(_ decl: Declaration) -> [String] { 135| 0| // Return nil if there is no entry for this declaration. 136| 0| guard let assignments = table.assignments[decl] else { 137| 0| return [] 138| 0| } 139| 0| 140| 0| var values: [String] = [] 141| 0| 142| 0| // Add values from each assignment if it satisfies the bound parameters. 143| 0| for assignment in assignments { 144| 0| 145| 0| if let configCondition = assignment.conditions.compactMap({ $0 as? ConfigurationCondition }).first { 146| 0| if configCondition.config != boundConfig { 147| 0| continue 148| 0| } 149| 0| } 150| 0| 151| 0| if let platformsCondition = assignment.conditions.compactMap({ $0 as? PlatformsCondition }).first { 152| 0| if !platformsCondition.platforms.contains(boundPlatform) { 153| 0| continue 154| 0| } 155| 0| } 156| 0| 157| 0| values += assignment.value 158| 0| } 159| 0| 160| 0| return values 161| 0| } 162| | } 163| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/Manifest.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| | 14| |/// The supported manifest versions. 15| |public enum ManifestVersion: String, Codable, CustomStringConvertible { 16| | case v4 17| | case v4_2 18| | case v5 19| | 20| | /// The Swift language version to use when parsing the manifest file. 21| 0| public var swiftLanguageVersion: SwiftLanguageVersion { 22| 0| // FIXME: This is not very scalable. We need to store the tools 23| 0| // version in the manifest and then use that to compute the right 24| 0| // Swift version instead of relying on the manifest version. The 25| 0| // manifest version is just the version that was used to load the 26| 0| // manifest and shouldn't contribute to what Swift version is 27| 0| // chosen. For e.g., we might have a new manifest version 4.3, but 28| 0| // the language version should still be 4.2. 29| 0| switch self { 30| 0| case .v4: return .v4 31| 0| case .v4_2: return .v4_2 32| 0| case .v5: return .v5 33| 0| } 34| 0| } 35| | 36| 0| public var description: String { 37| 0| switch self { 38| 0| case .v4: return "4" 39| 0| case .v4_2: return "4.2" 40| 0| case .v5: return "5" 41| 0| } 42| 0| } 43| | 44| | /// Subpath to the the runtime for this manifest version. 45| 0| public var runtimeSubpath: RelativePath { 46| 0| switch self { 47| 0| case .v4: 48| 0| return RelativePath("4") 49| 0| case .v4_2, .v5: 50| 0| // PackageDescription 4.2 and 5 are source compatible so they're contained in the same dylib. 51| 0| return RelativePath("4_2") 52| 0| } 53| 0| } 54| |} 55| | 56| |/// This contains the declarative specification loaded from package manifest 57| |/// files, and the tools for working with the manifest. 58| |public final class Manifest: ObjectIdentifierProtocol, CustomStringConvertible, Codable { 59| | 60| | /// The standard filename for the manifest. 61| | public static let filename = basename + ".swift" 62| | 63| | /// The standard basename for the manifest. 64| | public static let basename = "Package" 65| | 66| | // FIXME: This doesn't belong here, we want the Manifest to be purely tied 67| | // to the repository state, it shouldn't matter where it is. 68| | // 69| | /// The path of the manifest file. 70| | public let path: AbsolutePath 71| | 72| | // FIXME: This doesn't belong here, we want the Manifest to be purely tied 73| | // to the repository state, it shouldn't matter where it is. 74| | // 75| | /// The repository URL the manifest was loaded from. 76| | public let url: String 77| | 78| | /// The version this package was loaded from, if known. 79| | public let version: Version? 80| | 81| | /// The version of manifest. 82| | public let manifestVersion: ManifestVersion 83| | 84| | /// The name of the package. 85| | public let name: String 86| | 87| | /// The declared platforms in the manifest. 88| | public let platforms: [PlatformDescription] 89| | 90| | /// The declared package dependencies. 91| | public let dependencies: [PackageDependencyDescription] 92| | 93| | /// The targets declared in the manifest. 94| | public let targets: [TargetDescription] 95| | 96| | /// The products declared in the manifest. 97| | public let products: [ProductDescription] 98| | 99| | /// The C language standard flag. 100| | public let cLanguageStandard: String? 101| | 102| | /// The C++ language standard flag. 103| | public let cxxLanguageStandard: String? 104| | 105| | /// The supported Swift language versions of the package. 106| | public let swiftLanguageVersions: [SwiftLanguageVersion]? 107| | 108| | /// The pkg-config name of a system package. 109| | public let pkgConfig: String? 110| | 111| | /// The system package providers of a system package. 112| | public let providers: [SystemPackageProviderDescription]? 113| | 114| | public init( 115| | name: String, 116| | platforms: [PlatformDescription], 117| | path: AbsolutePath, 118| | url: String, 119| | version: SPMUtility.Version? = nil, 120| | manifestVersion: ManifestVersion, 121| | pkgConfig: String? = nil, 122| | providers: [SystemPackageProviderDescription]? = nil, 123| | cLanguageStandard: String? = nil, 124| | cxxLanguageStandard: String? = nil, 125| | swiftLanguageVersions: [SwiftLanguageVersion]? = nil, 126| | dependencies: [PackageDependencyDescription] = [], 127| | products: [ProductDescription] = [], 128| | targets: [TargetDescription] = [] 129| 0| ) { 130| 0| self.name = name 131| 0| self.platforms = platforms 132| 0| self.path = path 133| 0| self.url = url 134| 0| self.version = version 135| 0| self.manifestVersion = manifestVersion 136| 0| self.pkgConfig = pkgConfig 137| 0| self.providers = providers 138| 0| self.cLanguageStandard = cLanguageStandard 139| 0| self.cxxLanguageStandard = cxxLanguageStandard 140| 0| self.swiftLanguageVersions = swiftLanguageVersions 141| 0| self.dependencies = dependencies 142| 0| self.products = products 143| 0| self.targets = targets 144| 0| } 145| | 146| 0| public var description: String { 147| 0| return "" 148| 0| } 149| | 150| | /// Coding user info key for dump-package command. 151| | /// 152| | /// Presence of this key will hide some keys when encoding the Manifest object. 153| | public static let dumpPackageKey: CodingUserInfoKey = CodingUserInfoKey(rawValue: "dumpPackage")! 154| |} 155| | 156| |extension Manifest { 157| 0| public func encode(to encoder: Encoder) throws { 158| 0| var container = encoder.container(keyedBy: CodingKeys.self) 159| 0| try container.encode(name, forKey: .name) 160| 0| 161| 0| // Hide the keys that users shouldn't see when 162| 0| // we're encoding for the dump-package command. 163| 0| if encoder.userInfo[Manifest.dumpPackageKey] == nil { 164| 0| try container.encode(path, forKey: .path) 165| 0| try container.encode(url, forKey: .url) 166| 0| try container.encode(version, forKey: .version) 167| 0| } 168| 0| 169| 0| try container.encode(manifestVersion, forKey: .manifestVersion) 170| 0| try container.encode(pkgConfig, forKey: .pkgConfig) 171| 0| try container.encode(providers, forKey: .providers) 172| 0| try container.encode(cLanguageStandard, forKey: .cLanguageStandard) 173| 0| try container.encode(cxxLanguageStandard, forKey: .cxxLanguageStandard) 174| 0| try container.encode(swiftLanguageVersions, forKey: .swiftLanguageVersions) 175| 0| try container.encode(dependencies, forKey: .dependencies) 176| 0| try container.encode(products, forKey: .products) 177| 0| try container.encode(targets, forKey: .targets) 178| 0| try container.encode(platforms, forKey: .platforms) 179| 0| } 180| |} 181| | 182| |/// The description of an individual target. 183| |public struct TargetDescription: Equatable, Codable { 184| | 185| | /// The target type. 186| | public enum TargetType: String, Equatable, Codable { 187| | case regular 188| | case test 189| | case system 190| | } 191| | 192| | /// Represents a target's dependency on another entity. 193| | public enum Dependency: Equatable, ExpressibleByStringLiteral { 194| | case target(name: String) 195| | case product(name: String, package: String?) 196| | case byName(name: String) 197| | 198| 0| public init(stringLiteral value: String) { 199| 0| self = .byName(name: value) 200| 0| } 201| | 202| 0| public static func product(name: String) -> Dependency { 203| 0| return .product(name: name, package: nil) 204| 0| } 205| | } 206| | 207| | /// The name of the target. 208| | public let name: String 209| | 210| | /// The custom path of the target. 211| | public let path: String? 212| | 213| | /// The custom sources of the target. 214| | public let sources: [String]? 215| | 216| | /// The exclude patterns. 217| | public let exclude: [String] 218| | 219| | // FIXME: Kill this. 220| | // 221| | /// Returns true if the target type is test. 222| 0| public var isTest: Bool { 223| 0| return type == .test 224| 0| } 225| | 226| | /// The declared target dependencies. 227| | public let dependencies: [Dependency] 228| | 229| | /// The custom public headers path. 230| | public let publicHeadersPath: String? 231| | 232| | /// The type of target. 233| | public let type: TargetType 234| | 235| | /// The pkg-config name of a system library target. 236| | public let pkgConfig: String? 237| | 238| | /// The providers of a system library target. 239| | public let providers: [SystemPackageProviderDescription]? 240| | 241| | /// The target-specific build settings declared in this target. 242| | public let settings: [TargetBuildSettingDescription.Setting] 243| | 244| | public init( 245| | name: String, 246| | dependencies: [Dependency] = [], 247| | path: String? = nil, 248| | exclude: [String] = [], 249| | sources: [String]? = nil, 250| | publicHeadersPath: String? = nil, 251| | type: TargetType = .regular, 252| | pkgConfig: String? = nil, 253| | providers: [SystemPackageProviderDescription]? = nil, 254| | settings: [TargetBuildSettingDescription.Setting] = [] 255| 0| ) { 256| 0| switch type { 257| 0| case .regular, .test: 258| 0| precondition(pkgConfig == nil && providers == nil) 259| 0| case .system: break 260| 0| } 261| 0| 262| 0| self.name = name 263| 0| self.dependencies = dependencies 264| 0| self.path = path 265| 0| self.publicHeadersPath = publicHeadersPath 266| 0| self.sources = sources 267| 0| self.exclude = exclude 268| 0| self.type = type 269| 0| self.pkgConfig = pkgConfig 270| 0| self.providers = providers 271| 0| self.settings = settings 272| 0| } 273| |} 274| | 275| |/// The product description 276| |public struct ProductDescription: Equatable, Codable { 277| | 278| | /// The name of the product. 279| | public let name: String 280| | 281| | /// The targets in the product. 282| | public let targets: [String] 283| | 284| | /// The type of product. 285| | public let type: ProductType 286| | 287| | public init( 288| | name: String, 289| | type: ProductType, 290| | targets: [String] 291| 0| ) { 292| 0| precondition(type != .test, "Declaring test products isn't supported: \(name):\(targets)") 293| 0| self.name = name 294| 0| self.type = type 295| 0| self.targets = targets 296| 0| } 297| |} 298| | 299| |/// Represents system package providers. 300| |public enum SystemPackageProviderDescription: Equatable { 301| | case brew([String]) 302| | case apt([String]) 303| |} 304| | 305| |/// Represents a package dependency. 306| |public struct PackageDependencyDescription: Equatable, Codable { 307| | 308| | /// The dependency requirement. 309| | public enum Requirement: Equatable, Hashable, CustomStringConvertible { 310| | case exact(Version) 311| | case range(Range) 312| | case revision(String) 313| | case branch(String) 314| | case localPackage 315| | 316| 0| public static func upToNextMajor(from version: SPMUtility.Version) -> Requirement { 317| 0| return .range(version.. Requirement { 321| 0| return .range(version..= 1, "\(tool) \(name) \(value)") 430| 0| break 431| 0| } 432| 0| 433| 0| self.tool = tool 434| 0| self.name = name 435| 0| self.value = value 436| 0| self.condition = condition 437| 0| } 438| | } 439| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/Package.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| | 14| |// Re-export Version from PackageModel, since it is a key part of the model. 15| |@_exported import struct SPMUtility.Version 16| | 17| |/// The basic package representation. 18| |/// 19| |/// The package manager conceptually works with five different kinds of 20| |/// packages, of which this is only one: 21| |/// 22| |/// 1. Informally, the repository containing a package can be thought of in some 23| |/// sense as the "package". However, this isn't accurate, because the actual 24| |/// Package is derived from its manifest, a Package only actually exists at a 25| |/// particular repository revision (typically a tag). We also may eventually 26| |/// want to support multiple packages within a single repository. 27| |/// 28| |/// 2. The `PackageDescription.Package` as defined inside a manifest is a 29| |/// declarative specification for (part of) the package but not the object that 30| |/// the package manager itself is typically working with internally. Rather, 31| |/// that specification is primarily used to load the package (see the 32| |/// `PackageLoading` target). 33| |/// 34| |/// 3. A loaded `PackageModel.Manifest` is an abstract representation of a 35| |/// package, and is used during package dependency resolution. It contains the 36| |/// loaded PackageDescription and information necessary for dependency 37| |/// resolution, but nothing else. 38| |/// 39| |/// 4. A loaded `PackageModel.Package` which has had dependencies loaded and 40| |/// resolved. This is the result after `Get.get()`. 41| |/// 42| |/// 5. A loaded package, as in #4, for which the targets have also been 43| |/// loaded. There is not currently a data structure for this, but it is the 44| |/// result after `PackageLoading.transmute()`. 45| |public final class Package { 46| | /// The manifest describing the package. 47| | public let manifest: Manifest 48| | 49| | /// The local path of the package. 50| | public let path: AbsolutePath 51| | 52| | /// The name of the package. 53| 0| public var name: String { 54| 0| return manifest.name 55| 0| } 56| | 57| | /// The targets contained in the package. 58| | public let targets: [Target] 59| | 60| | /// The products produced by the package. 61| | public let products: [Product] 62| | 63| | // The directory containing the targets which did not explicitly specify 64| | // their path. If all targets are explicit, this is the preferred path for 65| | // future targets. 66| | public let targetSearchPath: AbsolutePath 67| | 68| | // The directory containing the test targets which did not explicitly specify 69| | // their path. If all test targets are explicit, this is the preferred path 70| | // for future test targets. 71| | public let testTargetSearchPath: AbsolutePath 72| | 73| | public init( 74| | manifest: Manifest, 75| | path: AbsolutePath, 76| | targets: [Target], 77| | products: [Product], 78| | targetSearchPath: AbsolutePath, 79| | testTargetSearchPath: AbsolutePath 80| 0| ) { 81| 0| self.manifest = manifest 82| 0| self.path = path 83| 0| self.targets = targets 84| 0| self.products = products 85| 0| self.targetSearchPath = targetSearchPath 86| 0| self.testTargetSearchPath = testTargetSearchPath 87| 0| } 88| | 89| | public enum Error: Swift.Error, Equatable { 90| | case noManifest(baseURL: String, version: String?) 91| | } 92| |} 93| |extension Package.Error: CustomStringConvertible { 94| 0| public var description: String { 95| 0| switch self { 96| 0| case .noManifest(let baseURL, let version): 97| 0| var string = "\(baseURL) has no manifest" 98| 0| if let version = version { 99| 0| string += " for version \(version)" 100| 0| } 101| 0| return string 102| 0| } 103| 0| } 104| |} 105| | 106| |extension Package: CustomStringConvertible { 107| 0| public var description: String { 108| 0| return name 109| 0| } 110| |} 111| | 112| |extension Package: ObjectIdentifierProtocol { 113| |} 114| | 115| |/// A package reference. 116| |/// 117| |/// This represents a reference to a package containing its identity and location. 118| |public struct PackageReference: JSONMappable, JSONSerializable, CustomStringConvertible { 119| | 120| | /// Compute identity of a package given its URL. 121| 0| public static func computeIdentity(packageURL: String) -> String { 122| 0| // Get the last path component of the URL. 123| 0| var lastComponent = packageURL.split(separator: "/", omittingEmptySubsequences: true).last! 124| 0| 125| 0| // Strip `.git` suffix if present. 126| 0| if lastComponent.hasSuffix(".git") { 127| 0| lastComponent = lastComponent.dropLast(4) 128| 0| } 129| 0| 130| 0| return lastComponent.lowercased() 131| 0| } 132| | 133| | /// The identity of the package. 134| | public let identity: String 135| | 136| | /// The name of the package, if available. 137| | public let name: String? 138| | 139| | /// The path of the package. 140| | /// 141| | /// This could be a remote repository, local repository or local package. 142| | public let path: String 143| | 144| | /// The package reference is a local package, i.e., it does not reference 145| | /// a git repository. 146| | public let isLocal: Bool 147| | 148| | /// Create a package reference given its identity and repository. 149| 0| public init(identity: String, path: String, name: String? = nil, isLocal: Bool = false) { 150| 0| assert(identity == identity.lowercased(), "The identity is expected to be lowercased") 151| 0| self.name = name 152| 0| self.identity = identity 153| 0| self.path = path 154| 0| self.isLocal = isLocal 155| 0| } 156| | 157| 0| public static func ==(lhs: PackageReference, rhs: PackageReference) -> Bool { 158| 0| return lhs.identity == rhs.identity 159| 0| } 160| | 161| 0| public func hash(into hasher: inout Hasher) { 162| 0| hasher.combine(identity) 163| 0| } 164| | 165| 0| public init(json: JSON) throws { 166| 0| self.name = json.get("name") 167| 0| self.identity = try json.get("identity") 168| 0| self.path = try json.get("path") 169| 0| self.isLocal = try json.get("isLocal") 170| 0| } 171| | 172| 0| public func toJSON() -> JSON { 173| 0| return .init([ 174| 0| "name": name.toJSON(), 175| 0| "identity": identity, 176| 0| "path": path, 177| 0| "isLocal": isLocal, 178| 0| ]) 179| 0| } 180| | 181| | /// Create a new package reference object with the given name. 182| 0| public func with(newName: String) -> PackageReference { 183| 0| return PackageReference(identity: identity, path: path, name: newName, isLocal: isLocal) 184| 0| } 185| | 186| 0| public var description: String { 187| 0| return identity + "[\(path)]" 188| 0| } 189| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/PackageModel+Codable.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| |import Basic 13| | 14| |extension ProductType: Codable { 15| | private enum CodingKeys: String, CodingKey { 16| | case library, executable, test 17| | } 18| | 19| 0| public func encode(to encoder: Encoder) throws { 20| 0| var container = encoder.container(keyedBy: CodingKeys.self) 21| 0| switch self { 22| 0| case let .library(a1): 23| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .library) 24| 0| try unkeyedContainer.encode(a1) 25| 0| case .executable: 26| 0| try container.encodeNil(forKey: .executable) 27| 0| case .test: 28| 0| try container.encodeNil(forKey: .test) 29| 0| } 30| 0| } 31| | 32| 0| public init(from decoder: Decoder) throws { 33| 0| let values = try decoder.container(keyedBy: CodingKeys.self) 34| 0| guard let key = values.allKeys.first(where: values.contains) else { 35| 0| throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Did not find a matching key")) 36| 0| } 37| 0| switch key { 38| 0| case .library: 39| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 40| 0| let a1 = try unkeyedValues.decode(ProductType.LibraryType.self) 41| 0| self = .library(a1) 42| 0| case .test: 43| 0| self = .test 44| 0| case .executable: 45| 0| self = .executable 46| 0| } 47| 0| } 48| |} 49| | 50| |extension SystemPackageProviderDescription: Codable { 51| | private enum CodingKeys: String, CodingKey { 52| | case brew, apt 53| | } 54| | 55| 0| public func encode(to encoder: Encoder) throws { 56| 0| var container = encoder.container(keyedBy: CodingKeys.self) 57| 0| switch self { 58| 0| case let .brew(a1): 59| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .brew) 60| 0| try unkeyedContainer.encode(a1) 61| 0| case let .apt(a1): 62| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .apt) 63| 0| try unkeyedContainer.encode(a1) 64| 0| } 65| 0| } 66| | 67| 0| public init(from decoder: Decoder) throws { 68| 0| let values = try decoder.container(keyedBy: CodingKeys.self) 69| 0| guard let key = values.allKeys.first(where: values.contains) else { 70| 0| throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Did not find a matching key")) 71| 0| } 72| 0| switch key { 73| 0| case .brew: 74| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 75| 0| let a1 = try unkeyedValues.decode([String].self) 76| 0| self = .brew(a1) 77| 0| case .apt: 78| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 79| 0| let a1 = try unkeyedValues.decode([String].self) 80| 0| self = .apt(a1) 81| 0| } 82| 0| } 83| |} 84| | 85| |extension PackageDependencyDescription.Requirement: Codable { 86| | private enum CodingKeys: String, CodingKey { 87| | case exact, range, revision, branch, localPackage 88| | } 89| | 90| 0| public func encode(to encoder: Encoder) throws { 91| 0| var container = encoder.container(keyedBy: CodingKeys.self) 92| 0| switch self { 93| 0| case let .exact(a1): 94| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .exact) 95| 0| try unkeyedContainer.encode(a1) 96| 0| case let .range(a1): 97| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .range) 98| 0| try unkeyedContainer.encode(CodableRange(a1)) 99| 0| case let .revision(a1): 100| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .revision) 101| 0| try unkeyedContainer.encode(a1) 102| 0| case let .branch(a1): 103| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .branch) 104| 0| try unkeyedContainer.encode(a1) 105| 0| case .localPackage: 106| 0| try container.encodeNil(forKey: .localPackage) 107| 0| } 108| 0| } 109| | 110| 0| public init(from decoder: Decoder) throws { 111| 0| let values = try decoder.container(keyedBy: CodingKeys.self) 112| 0| guard let key = values.allKeys.first(where: values.contains) else { 113| 0| throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Did not find a matching key")) 114| 0| } 115| 0| switch key { 116| 0| case .exact: 117| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 118| 0| let a1 = try unkeyedValues.decode(Version.self) 119| 0| self = .exact(a1) 120| 0| case .range: 121| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 122| 0| let a1 = try unkeyedValues.decode(CodableRange.self) 123| 0| self = .range(a1.range) 124| 0| case .revision: 125| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 126| 0| let a1 = try unkeyedValues.decode(String.self) 127| 0| self = .revision(a1) 128| 0| case .branch: 129| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 130| 0| let a1 = try unkeyedValues.decode(String.self) 131| 0| self = .branch(a1) 132| 0| case .localPackage: 133| 0| self = .localPackage 134| 0| } 135| 0| } 136| |} 137| | 138| |extension TargetDescription.Dependency: Codable { 139| | private enum CodingKeys: String, CodingKey { 140| | case target, product, byName 141| | } 142| | 143| 0| public func encode(to encoder: Encoder) throws { 144| 0| var container = encoder.container(keyedBy: CodingKeys.self) 145| 0| switch self { 146| 0| case let .target(a1): 147| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .target) 148| 0| try unkeyedContainer.encode(a1) 149| 0| case let .product(a1, a2): 150| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .product) 151| 0| try unkeyedContainer.encode(a1) 152| 0| try unkeyedContainer.encode(a2) 153| 0| case let .byName(a1): 154| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .byName) 155| 0| try unkeyedContainer.encode(a1) 156| 0| } 157| 0| } 158| | 159| 0| public init(from decoder: Decoder) throws { 160| 0| let values = try decoder.container(keyedBy: CodingKeys.self) 161| 0| guard let key = values.allKeys.first(where: values.contains) else { 162| 0| throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Did not find a matching key")) 163| 0| } 164| 0| switch key { 165| 0| case .target: 166| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 167| 0| let a1 = try unkeyedValues.decode(String.self) 168| 0| self = .target(name: a1) 169| 0| case .product: 170| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 171| 0| let a1 = try unkeyedValues.decode(String.self) 172| 0| let a2 = try unkeyedValues.decodeIfPresent(String.self) 173| 0| self = .product(name: a1, package: a2) 174| 0| case .byName: 175| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 176| 0| let a1 = try unkeyedValues.decode(String.self) 177| 0| self = .byName(name: a1) 178| 0| } 179| 0| } 180| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/Platform.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A registry for available platforms. 12| |public final class PlatformRegistry { 13| | 14| | /// The current registery is hardcoded and static so we can just use 15| | /// a singleton for now. 16| | public static let `default`: PlatformRegistry = .init() 17| | 18| | /// The list of known platforms. 19| | public let knownPlatforms: [Platform] 20| | 21| | /// The mapping of platforms to their name. 22| | public let platformByName: [String: Platform] 23| | 24| | /// Create a registry with the given list of platforms. 25| 0| init(platforms: [Platform] = PlatformRegistry._knownPlatforms) { 26| 0| self.knownPlatforms = platforms 27| 0| self.platformByName = Dictionary(uniqueKeysWithValues: knownPlatforms.map({ ($0.name, $0) })) 28| 0| } 29| | 30| | /// The static list of known platforms. 31| 0| private static var _knownPlatforms: [Platform] { 32| 0| return [.macOS, .iOS, .tvOS, .watchOS, .linux] 33| 0| } 34| |} 35| | 36| |/// Represents a platform. 37| |public struct Platform: Equatable, Hashable { 38| | /// The name of the platform. 39| | public let name: String 40| | 41| | /// The oldest supported deployment version by this platform. 42| | /// 43| | /// We currently hardcode this value but we should load it from the 44| | /// SDK's plist file. This value is always present for Apple platforms. 45| | public let oldestSupportedVersion: PlatformVersion 46| | 47| | /// Create a platform. 48| 0| private init(name: String, oldestSupportedVersion: PlatformVersion) { 49| 0| self.name = name 50| 0| self.oldestSupportedVersion = oldestSupportedVersion 51| 0| } 52| | 53| | public static let macOS: Platform = Platform(name: "macos", oldestSupportedVersion: "10.10") 54| | public static let iOS: Platform = Platform(name: "ios", oldestSupportedVersion: "8.0") 55| | public static let tvOS: Platform = Platform(name: "tvos", oldestSupportedVersion: "9.0") 56| | public static let watchOS: Platform = Platform(name: "watchos", oldestSupportedVersion: "2.0") 57| | public static let linux: Platform = Platform(name: "linux", oldestSupportedVersion: .unknown) 58| |} 59| | 60| |/// Represents a platform version. 61| |public struct PlatformVersion: ExpressibleByStringLiteral, Comparable, Hashable { 62| | 63| | /// The unknown platform version. 64| | public static let unknown: PlatformVersion = .init("0.0.0") 65| | 66| | /// The underlying version storage. 67| | private let version: Version 68| | 69| | /// The string representation of the version. 70| 0| public var versionString: String { 71| 0| var str = "\(version.major).\(version.minor)" 72| 0| if version.patch != 0 { 73| 0| str += ".\(version.patch)" 74| 0| } 75| 0| return str 76| 0| } 77| | 78| | /// Create a platform version given a string. 79| | /// 80| | /// The platform version is expected to be in format: X.X.X 81| 0| public init(_ version: String) { 82| 0| let components = version.split(separator: ".").compactMap({ Int($0) }) 83| 0| assert(!components.isEmpty && components.count <= 3, version) 84| 0| switch components.count { 85| 0| case 1: 86| 0| self.version = Version(components[0], 0, 0) 87| 0| case 2: 88| 0| self.version = Version(components[0], components[1], 0) 89| 0| case 3: 90| 0| self.version = Version(components[0], components[1], components[2]) 91| 0| default: 92| 0| fatalError("Unexpected number of components \(components)") 93| 0| } 94| 0| } 95| | 96| | // MARK:- ExpressibleByStringLiteral 97| | 98| 0| public init(stringLiteral value: String) { 99| 0| self.init(value) 100| 0| } 101| | 102| | // MARK:- Comparable 103| | 104| 0| public static func < (lhs: PlatformVersion, rhs: PlatformVersion) -> Bool { 105| 0| return lhs.version < rhs.version 106| 0| } 107| |} 108| | 109| |/// Represents a platform supported by a target. 110| |public struct SupportedPlatform { 111| | /// The platform. 112| | public let platform: Platform 113| | 114| | /// The minimum required version for this platform. 115| | public let version: PlatformVersion 116| | 117| 0| public init(platform: Platform, version: PlatformVersion) { 118| 0| self.platform = platform 119| 0| self.version = version 120| 0| } 121| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/Product.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// The type of product. 14| |public enum ProductType: CustomStringConvertible, Equatable { 15| | 16| | /// The type of library. 17| | public enum LibraryType: String, Codable { 18| | 19| | /// Static library. 20| | case `static` 21| | 22| | /// Dynamic library. 23| | case `dynamic` 24| | 25| | /// The type of library is unspecified and should be decided by package manager. 26| | case automatic 27| | } 28| | 29| | /// A library product. 30| | case library(LibraryType) 31| | 32| | /// An executable product. 33| | case executable 34| | 35| | /// A test product. 36| | case test 37| | 38| 0| public var description: String { 39| 0| switch self { 40| 0| case .executable: 41| 0| return "executable" 42| 0| case .test: 43| 0| return "test" 44| 0| case .library(let type): 45| 0| switch type { 46| 0| case .automatic: 47| 0| return "automatic" 48| 0| case .dynamic: 49| 0| return "dynamic" 50| 0| case .static: 51| 0| return "static" 52| 0| } 53| 0| } 54| 0| } 55| |} 56| | 57| |public class Product { 58| | 59| | /// The name of the product. 60| | public let name: String 61| | 62| | /// The type of product to create. 63| | public let type: ProductType 64| | 65| | /// The list of targets to combine to form the product. 66| | /// 67| | /// This is never empty, and is only the targets which are required to be in 68| | /// the product, but not necessarily their transitive dependencies. 69| | public let targets: [Target] 70| | 71| | /// The path to linux main file. 72| | public let linuxMain: AbsolutePath? 73| | 74| | /// The suffix for REPL product name. 75| | public static let replProductSuffix: String = "__REPL" 76| | 77| 0| public init(name: String, type: ProductType, targets: [Target], linuxMain: AbsolutePath? = nil) { 78| 0| precondition(!targets.isEmpty) 79| 0| if type == .executable { 80| 0| assert(targets.filter({ $0.type == .executable }).count == 1, 81| 0| "Executable products should have exactly one executable target.") 82| 0| } 83| 0| if linuxMain != nil { 84| 0| assert(type == .test, "Linux main should only be set on test products") 85| 0| } 86| 0| self.name = name 87| 0| self.type = type 88| 0| self.targets = targets 89| 0| self.linuxMain = linuxMain 90| 0| } 91| |} 92| | 93| |extension Product: CustomStringConvertible { 94| 0| public var description: String { 95| 0| return "" 96| 0| } 97| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/ResolvedModels.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// Represents a fully resolved target. All the dependencies for the target are resolved. 14| |public final class ResolvedTarget: CustomStringConvertible, ObjectIdentifierProtocol { 15| | 16| | /// Represents dependency of a resolved target. 17| | public enum Dependency: Hashable { 18| | 19| | /// Direct dependency of the target. This target is in the same package and should be statically linked. 20| | case target(ResolvedTarget) 21| | 22| | /// The target depends on this product. 23| | case product(ResolvedProduct) 24| | 25| 0| public var target: ResolvedTarget? { 26| 0| switch self { 27| 0| case .target(let target): return target 28| 0| case .product: return nil 29| 0| } 30| 0| } 31| | 32| 0| public var product: ResolvedProduct? { 33| 0| switch self { 34| 0| case .target: return nil 35| 0| case .product(let product): return product 36| 0| } 37| 0| } 38| | } 39| | 40| | /// The underlying target represented in this resolved target. 41| | public let underlyingTarget: Target 42| | 43| | /// The name of this target. 44| 0| public var name: String { 45| 0| return underlyingTarget.name 46| 0| } 47| | 48| | /// The dependencies of this target. 49| | public let dependencies: [Dependency] 50| | 51| | /// Returns the recursive dependencies filtered by the given platform, if present. 52| 0| public func recursiveDependencies() -> [ResolvedTarget] { 53| 0| return try! topologicalSort(self.dependencies, successors: { 54| 0| switch $0 { 55| 0| case .target(let target): 56| 0| return target.dependencies 57| 0| case .product(let product): 58| 0| return product.targets.map(ResolvedTarget.Dependency.target) 59| 0| } 60| 0| }).compactMap({ $0.target }) 61| 0| } 62| | 63| | /// The language-level target name. 64| 0| public var c99name: String { 65| 0| return underlyingTarget.c99name 66| 0| } 67| | 68| | /// The "type" of target. 69| 0| public var type: Target.Kind { 70| 0| return underlyingTarget.type 71| 0| } 72| | 73| | /// The sources for the target. 74| 0| public var sources: Sources { 75| 0| return underlyingTarget.sources 76| 0| } 77| | 78| | /// Create a target instance. 79| 0| public init(target: Target, dependencies: [Dependency]) { 80| 0| self.underlyingTarget = target 81| 0| self.dependencies = dependencies 82| 0| } 83| | 84| 0| public var description: String { 85| 0| return "" 86| 0| } 87| |} 88| | 89| |/// A fully resolved package. Contains resolved targets, products and dependencies of the package. 90| |public final class ResolvedPackage: CustomStringConvertible, ObjectIdentifierProtocol { 91| | 92| | /// The underlying package reference. 93| | public let underlyingPackage: Package 94| | 95| | /// The manifest describing the package. 96| 0| public var manifest: Manifest { 97| 0| return underlyingPackage.manifest 98| 0| } 99| | 100| | /// The name of the package. 101| 0| public var name: String { 102| 0| return underlyingPackage.name 103| 0| } 104| | 105| | /// The local path of the package. 106| 0| public var path: AbsolutePath { 107| 0| return underlyingPackage.path 108| 0| } 109| | 110| | /// The targets contained in the package. 111| | public let targets: [ResolvedTarget] 112| | 113| | /// The products produced by the package. 114| | public let products: [ResolvedProduct] 115| | 116| | /// The dependencies of the package. 117| | public let dependencies: [ResolvedPackage] 118| | 119| | public init( 120| | package: Package, 121| | dependencies: [ResolvedPackage], 122| | targets: [ResolvedTarget], 123| | products: [ResolvedProduct] 124| 0| ) { 125| 0| self.underlyingPackage = package 126| 0| self.dependencies = dependencies 127| 0| self.targets = targets 128| 0| self.products = products 129| 0| } 130| | 131| 0| public var description: String { 132| 0| return "" 133| 0| } 134| |} 135| | 136| |public final class ResolvedProduct: ObjectIdentifierProtocol, CustomStringConvertible { 137| | 138| | /// The underlying product. 139| | public let underlyingProduct: Product 140| | 141| | /// The name of this product. 142| 0| public var name: String { 143| 0| return underlyingProduct.name 144| 0| } 145| | 146| | /// The top level targets contained in this product. 147| | public let targets: [ResolvedTarget] 148| | 149| | /// The type of this product. 150| 0| public var type: ProductType { 151| 0| return underlyingProduct.type 152| 0| } 153| | 154| | /// Executable target for linux main test manifest file. 155| | public let linuxMainTarget: ResolvedTarget? 156| | 157| | /// The main executable target of product. 158| | /// 159| | /// Note: This property is only valid for executable products. 160| 0| public var executableModule: ResolvedTarget { 161| 0| precondition(type == .executable, "This property should only be called for executable targets") 162| 0| return targets.first(where: { $0.type == .executable })! 163| 0| } 164| | 165| 0| public init(product: Product, targets: [ResolvedTarget]) { 166| 0| assert(product.targets.count == targets.count && product.targets.map({ $0.name }) == targets.map({ $0.name })) 167| 0| self.underlyingProduct = product 168| 0| self.targets = targets 169| 0| 170| 0| self.linuxMainTarget = underlyingProduct.linuxMain.map({ linuxMain in 171| 0| // Create an exectutable resolved target with the linux main, adding product's targets as dependencies. 172| 0| let swiftTarget = SwiftTarget( 173| 0| linuxMain: linuxMain, name: product.name, dependencies: product.targets) 174| 0| return ResolvedTarget(target: swiftTarget, dependencies: targets.map(ResolvedTarget.Dependency.target)) 175| 0| }) 176| 0| } 177| | 178| 0| public var description: String { 179| 0| return "" 180| 0| } 181| |} 182| | 183| |extension ResolvedTarget.Dependency: CustomStringConvertible { 184| | 185| | /// Returns the dependencies of the underlying dependency. 186| 0| public var dependencies: [ResolvedTarget.Dependency] { 187| 0| switch self { 188| 0| case .target(let target): 189| 0| return target.dependencies 190| 0| case .product(let product): 191| 0| return product.targets.map(ResolvedTarget.Dependency.target) 192| 0| } 193| 0| } 194| | 195| | // MARK: - CustomStringConvertible conformance 196| | 197| 0| public var description: String { 198| 0| var str = " = { 60| 0| SupportedLanguageExtension.stringSet(swift) 61| 0| }() 62| | 63| | /// Returns a set of valid c extensions. 64| 0| public static var cExtensions: Set = { 65| 0| SupportedLanguageExtension.stringSet(c, m) 66| 0| }() 67| | 68| | /// Returns a set of valid cpp extensions. 69| 0| public static var cppExtensions: Set = { 70| 0| SupportedLanguageExtension.stringSet(mm, cc, cpp, cxx) 71| 0| }() 72| | 73| | /// Returns a set of valid assembly file extensions. 74| 0| public static var assemblyExtensions: Set = { 75| 0| SupportedLanguageExtension.stringSet(.s, .S) 76| 0| }() 77| | 78| | /// Returns a set of valid extensions in clang targets. 79| 0| public static func clangTargetExtensions(manifestVersion: ManifestVersion) -> Set { 80| 0| let alwaysValidExts = cExtensions.union(cppExtensions) 81| 0| switch manifestVersion { 82| 0| case .v4, .v4_2: 83| 0| return alwaysValidExts 84| 0| case .v5: 85| 0| return alwaysValidExts.union(assemblyExtensions) 86| 0| } 87| 0| } 88| | 89| | /// Returns a set of all file extensions we support. 90| 0| public static func validExtensions(manifestVersion: ManifestVersion) -> Set { 91| 0| return swiftExtensions.union(clangTargetExtensions(manifestVersion: manifestVersion)) 92| 0| } 93| | 94| | /// Converts array of LanguageExtension into a string set representation. 95| | /// 96| | /// - Parameters: 97| | /// - extensions: Array of LanguageExtension to be converted to string set. 98| | /// 99| | /// - Returns: Set of strings. 100| 0| private static func stringSet(_ extensions: SupportedLanguageExtension...) -> Set { 101| 0| return Set(extensions.map({ $0.rawValue })) 102| 0| } 103| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/Target.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |public class Target: ObjectIdentifierProtocol { 14| | /// The target kind. 15| | public enum Kind: String { 16| | case executable 17| | case library 18| | case systemModule = "system-target" 19| | case test 20| | } 21| | 22| | /// The name of the target. 23| | /// 24| | /// NOTE: This name is not the language-level target (i.e., the importable 25| | /// name) name in many cases, instead use c99name if you need uniqueness. 26| | public let name: String 27| | 28| | /// The dependencies of this target. 29| | public let dependencies: [Target] 30| | 31| | /// The product dependencies of this target. 32| | public let productDependencies: [(name: String, package: String?)] 33| | 34| | /// The language-level target name. 35| | public let c99name: String 36| | 37| | /// Suffix that's expected for test targets. 38| | public static let testModuleNameSuffix = "Tests" 39| | 40| | /// The kind of target. 41| | public let type: Kind 42| | 43| | /// The sources for the target. 44| | public let sources: Sources 45| | 46| | /// The list of platforms that are supported by this target. 47| | public let platforms: [SupportedPlatform] 48| | 49| | /// Returns the supported platform instance for the given platform. 50| 0| public func getSupportedPlatform(for platform: Platform) -> SupportedPlatform? { 51| 0| return self.platforms.first(where: { $0.platform == platform }) 52| 0| } 53| | 54| | /// The build settings assignments of this target. 55| | public let buildSettings: BuildSettings.AssignmentTable 56| | 57| | fileprivate init( 58| | name: String, 59| | platforms: [SupportedPlatform], 60| | type: Kind, 61| | sources: Sources, 62| | dependencies: [Target], 63| | productDependencies: [(name: String, package: String?)] = [], 64| | buildSettings: BuildSettings.AssignmentTable 65| 0| ) { 66| 0| self.name = name 67| 0| self.platforms = platforms 68| 0| self.type = type 69| 0| self.sources = sources 70| 0| self.dependencies = dependencies 71| 0| self.productDependencies = productDependencies 72| 0| self.c99name = self.name.spm_mangledToC99ExtendedIdentifier() 73| 0| self.buildSettings = buildSettings 74| 0| } 75| |} 76| | 77| |public class SwiftTarget: Target { 78| | 79| | /// The file name of linux main file. 80| | public static let linuxMainBasename = "LinuxMain.swift" 81| | 82| | /// Create an executable Swift target from linux main test manifest file. 83| 0| init(linuxMain: AbsolutePath, name: String, dependencies: [Target]) { 84| 0| // Look for the first swift test target and use the same swift version 85| 0| // for linux main target. This will need to change if we move to a model 86| 0| // where we allow per target swift language version build settings. 87| 0| let swiftTestTarget = dependencies.first(where: { 88| 0| guard case let target as SwiftTarget = $0 else { return false } 89| 0| return target.type == .test 90| 0| }).flatMap({ $0 as? SwiftTarget }) 91| 0| 92| 0| // FIXME: This is not very correct but doesn't matter much in practice. 93| 0| // We need to select the latest Swift language version that can 94| 0| // satisfy the current tools version but there is not a good way to 95| 0| // do that currently. 96| 0| self.swiftVersion = swiftTestTarget?.swiftVersion ?? SwiftLanguageVersion(string: String(ToolsVersion.currentToolsVersion.major)) ?? .v4 97| 0| let sources = Sources(paths: [linuxMain], root: linuxMain.parentDirectory) 98| 0| 99| 0| let platforms: [SupportedPlatform] = swiftTestTarget?.platforms ?? [] 100| 0| 101| 0| super.init( 102| 0| name: name, 103| 0| platforms: platforms, 104| 0| type: .executable, 105| 0| sources: sources, 106| 0| dependencies: dependencies, 107| 0| buildSettings: .init() 108| 0| 109| 0| ) 110| 0| } 111| | 112| | /// The swift version of this target. 113| | public let swiftVersion: SwiftLanguageVersion 114| | 115| | public init( 116| | name: String, 117| | platforms: [SupportedPlatform] = [], 118| | isTest: Bool = false, 119| | sources: Sources, 120| | dependencies: [Target] = [], 121| | productDependencies: [(name: String, package: String?)] = [], 122| | swiftVersion: SwiftLanguageVersion, 123| | buildSettings: BuildSettings.AssignmentTable = .init() 124| 0| ) { 125| 0| let type: Kind = isTest ? .test : sources.computeTargetType() 126| 0| self.swiftVersion = swiftVersion 127| 0| super.init( 128| 0| name: name, 129| 0| platforms: platforms, 130| 0| type: type, 131| 0| sources: sources, 132| 0| dependencies: dependencies, 133| 0| productDependencies: productDependencies, 134| 0| buildSettings: buildSettings 135| 0| ) 136| 0| } 137| |} 138| | 139| |public class SystemLibraryTarget: Target { 140| | 141| | /// The name of pkgConfig file, if any. 142| | public let pkgConfig: String? 143| | 144| | /// List of system package providers, if any. 145| | public let providers: [SystemPackageProviderDescription]? 146| | 147| | /// The package path. 148| 0| public var path: AbsolutePath { 149| 0| return sources.root 150| 0| } 151| | 152| | /// True if this system library should become implicit target 153| | /// dependency of its dependent packages. 154| | public let isImplicit: Bool 155| | 156| | public init( 157| | name: String, 158| | platforms: [SupportedPlatform] = [], 159| | path: AbsolutePath, 160| | isImplicit: Bool = true, 161| | pkgConfig: String? = nil, 162| | providers: [SystemPackageProviderDescription]? = nil 163| 0| ) { 164| 0| let sources = Sources(paths: [], root: path) 165| 0| self.pkgConfig = pkgConfig 166| 0| self.providers = providers 167| 0| self.isImplicit = isImplicit 168| 0| super.init( 169| 0| name: name, 170| 0| platforms: platforms, 171| 0| type: .systemModule, 172| 0| sources: sources, 173| 0| dependencies: [], 174| 0| buildSettings: .init() 175| 0| ) 176| 0| } 177| |} 178| | 179| |public class ClangTarget: Target { 180| | 181| | /// The default public include directory component. 182| | public static let defaultPublicHeadersComponent = "include" 183| | 184| | /// The path to include directory. 185| | public let includeDir: AbsolutePath 186| | 187| | /// True if this is a C++ target. 188| | public let isCXX: Bool 189| | 190| | /// The C language standard flag. 191| | public let cLanguageStandard: String? 192| | 193| | /// The C++ language standard flag. 194| | public let cxxLanguageStandard: String? 195| | 196| | public init( 197| | name: String, 198| | platforms: [SupportedPlatform] = [], 199| | cLanguageStandard: String?, 200| | cxxLanguageStandard: String?, 201| | includeDir: AbsolutePath, 202| | isTest: Bool = false, 203| | sources: Sources, 204| | dependencies: [Target] = [], 205| | productDependencies: [(name: String, package: String?)] = [], 206| | buildSettings: BuildSettings.AssignmentTable = .init() 207| 0| ) { 208| 0| assert(includeDir.contains(sources.root), "\(includeDir) should be contained in the source root \(sources.root)") 209| 0| let type: Kind = isTest ? .test : sources.computeTargetType() 210| 0| self.isCXX = sources.containsCXXFiles 211| 0| self.cLanguageStandard = cLanguageStandard 212| 0| self.cxxLanguageStandard = cxxLanguageStandard 213| 0| self.includeDir = includeDir 214| 0| super.init( 215| 0| name: name, 216| 0| platforms: platforms, 217| 0| type: type, 218| 0| sources: sources, 219| 0| dependencies: dependencies, 220| 0| productDependencies: productDependencies, 221| 0| buildSettings: buildSettings 222| 0| ) 223| 0| } 224| |} 225| | 226| |extension Target: CustomStringConvertible { 227| 0| public var description: String { 228| 0| return "<\(Swift.type(of: self)): \(name)>" 229| 0| } 230| |} 231| | 232| |extension Sources { 233| | /// Determine target type based on the sources. 234| 0| fileprivate func computeTargetType() -> Target.Kind { 235| 0| let isLibrary = !relativePaths.contains { path in 236| 0| let file = path.basename.lowercased() 237| 0| // Look for a main.xxx file avoiding cases like main.xxx.xxx 238| 0| return file.hasPrefix("main.") && String(file.filter({$0 == "."})).count == 1 239| 0| } 240| 0| return isLibrary ? .library : .executable 241| 0| } 242| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageModel/ToolsVersion.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |import Foundation 14| |import SPMUtility 15| | 16| |/// Tools version represents version of the Swift toolchain. 17| |public struct ToolsVersion: CustomStringConvertible, Comparable, Hashable { 18| | 19| | public static let v3 = ToolsVersion(version: "3.1.0") 20| | public static let v4 = ToolsVersion(version: "4.0.0") 21| | public static let v5 = ToolsVersion(version: "5.0.0") 22| | 23| | /// The current tools version in use. 24| | public static let currentToolsVersion = ToolsVersion(string: 25| | "\(Versioning.currentVersion.major)." + 26| | "\(Versioning.currentVersion.minor)." + 27| | "\(Versioning.currentVersion.patch)")! 28| | 29| | /// The minimum tools version that is required by the package manager. 30| | public static let minimumRequired: ToolsVersion = .v4 31| | 32| | /// Regex pattern to parse tools version. The format is SemVer 2.0 with an 33| | /// addition that specifying the patch version is optional. 34| | static let toolsVersionRegex = try! NSRegularExpression(pattern: "^" + 35| | "(\\d+)\\.(\\d+)(?:\\.(\\d+))?" + 36| | "(" + 37| | "\\-[A-Za-z\\d]+(?:\\.[A-Za-z\\d]+)*" + 38| | ")?" + 39| | "(" + 40| | "\\+[A-Za-z\\d]+(?:\\.[A-Za-z\\d]+)*" + 41| | ")?$", options: []) 42| | 43| | /// The major version number. 44| 0| public var major: Int { 45| 0| return _version.major 46| 0| } 47| | 48| | /// The minor version number. 49| 0| public var minor: Int { 50| 0| return _version.minor 51| 0| } 52| | 53| | /// The patch version number. 54| 0| public var patch: Int { 55| 0| return _version.patch 56| 0| } 57| | 58| | /// The underlying backing store. 59| | fileprivate let _version: Version 60| | 61| | /// Create an instance of tools version from a given string. 62| 0| public init?(string: String) { 63| 0| guard let match = ToolsVersion.toolsVersionRegex.firstMatch( 64| 0| in: string, options: [], range: NSRange(location: 0, length: string.count)) else { 65| 0| return nil 66| 0| } 67| 0| // The regex succeeded, compute individual components. 68| 0| assert(match.numberOfRanges == 6) 69| 0| let string = NSString(string: string) 70| 0| let major = Int(string.substring(with: match.range(at: 1)))! 71| 0| let minor = Int(string.substring(with: match.range(at: 2)))! 72| 0| let patchRange = match.range(at: 3) 73| 0| let patch = patchRange.location != NSNotFound ? Int(string.substring(with: patchRange))! : 0 74| 0| // We ignore storing pre-release and build identifiers for now. 75| 0| _version = Version(major, minor, patch) 76| 0| } 77| | 78| | /// Create instance of tools version from a given version. 79| | /// 80| | /// - precondition: prereleaseIdentifiers and buildMetadataIdentifier should not be present. 81| 0| public init(version: Version) { 82| 0| _version = version 83| 0| } 84| | 85| | // MARK: - CustomStringConvertible 86| | 87| 0| public var description: String { 88| 0| return _version.description 89| 0| } 90| | 91| | // MARK: - Comparable 92| | 93| 0| public static func < (lhs: ToolsVersion, rhs: ToolsVersion) -> Bool { 94| 0| return lhs._version < rhs._version 95| 0| } 96| |} 97| | 98| |/// Represents a Swift language version. 99| |public struct SwiftLanguageVersion: CustomStringConvertible, Comparable { 100| | 101| | /// Swift language version 3. 102| | public static let v3 = SwiftLanguageVersion(uncheckedString: "3") 103| | 104| | /// Swift language version 4. 105| | public static let v4 = SwiftLanguageVersion(uncheckedString: "4") 106| | 107| | /// Swift language version 4.2. 108| | public static let v4_2 = SwiftLanguageVersion(uncheckedString: "4.2") 109| | 110| | /// Swift language version 5. 111| | public static let v5 = SwiftLanguageVersion(uncheckedString: "5") 112| | 113| | /// The list of known Swift language versions. 114| | public static let knownSwiftLanguageVersions = [ 115| | v3, v4, v4_2, v5, 116| | ] 117| | 118| | /// The raw value of the language version. 119| | // 120| | // This should be passed as a value to Swift compiler's -swift-version flag. 121| | public let rawValue: String 122| | 123| | /// The underlying backing store. 124| | private let _version: Version 125| | 126| | /// Regex for parsing the Swift language version. 127| | private static let regex = try! RegEx(pattern: "^(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?$") 128| | 129| | /// Create an instance of Swift language version from the given string. 130| | /// 131| | // The Swift language version is not officially fixed but we require it to 132| | // be a valid SemVer-like string. 133| 0| public init?(string: String) { 134| 0| let parsedVersion = SwiftLanguageVersion.regex.matchGroups(in: string) 135| 0| guard parsedVersion.count == 1, parsedVersion[0].count == 3 else { 136| 0| return nil 137| 0| } 138| 0| let major = Int(parsedVersion[0][0])! 139| 0| let minor = parsedVersion[0][1].isEmpty ? 0 : Int(parsedVersion[0][1])! 140| 0| let patch = parsedVersion[0][2].isEmpty ? 0 : Int(parsedVersion[0][2])! 141| 0| 142| 0| self.rawValue = string 143| 0| self._version = Version(major, minor, patch) 144| 0| } 145| | 146| | /// Create an instance assuming the string is valid. 147| 0| private init(uncheckedString string: String) { 148| 0| self.init(string: string)! 149| 0| } 150| | 151| | // MARK: - CustomStringConvertible 152| | 153| 0| public var description: String { 154| 0| return rawValue 155| 0| } 156| | 157| | // MARK: - Comparable 158| | 159| 0| public static func == (lhs: SwiftLanguageVersion, rhs: SwiftLanguageVersion) -> Bool { 160| 0| return lhs._version == rhs._version 161| 0| } 162| | 163| 0| public static func < (lhs: SwiftLanguageVersion, rhs: SwiftLanguageVersion) -> Bool { 164| 0| return lhs._version < rhs._version 165| 0| } 166| | 167| | // MAKR: - Compare with ToolsVersion 168| | 169| 0| public static func == (lhs: SwiftLanguageVersion, rhs: ToolsVersion) -> Bool { 170| 0| return lhs._version == rhs._version 171| 0| } 172| | 173| 0| public static func < (lhs: SwiftLanguageVersion, rhs: ToolsVersion) -> Bool { 174| 0| return lhs._version < rhs._version 175| 0| } 176| | 177| 0| public static func <= (lhs: SwiftLanguageVersion, rhs: ToolsVersion) -> Bool { 178| 0| return (lhs < rhs) || (lhs == rhs) 179| 0| } 180| |} 181| | 182| |extension SwiftLanguageVersion: Codable { 183| 0| public func encode(to encoder: Encoder) throws { 184| 0| var container = encoder.singleValueContainer() 185| 0| try container.encode(rawValue) 186| 0| } 187| | 188| 0| public init(from decoder: Decoder) throws { 189| 0| let container = try decoder.singleValueContainer() 190| 0| let rawValue = try container.decode(String.self) 191| 0| self.init(uncheckedString: rawValue) 192| 0| } 193| |} <<<<<< EOF # path=Basic.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Await.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Converts an asynchronous method having callback using Result enum to synchronous. 12| |/// 13| |/// - Parameter body: The async method must be called inside this body and closure provided in the parameter 14| |/// should be passed to the async method's completion handler. 15| |/// - Returns: The value wrapped by the async method's result. 16| |/// - Throws: The error wrapped by the async method's result 17| 0|public func await(_ body: (@escaping (Result) -> Void) -> Void) throws -> T { 18| 0| return try await(body).dematerialize() 19| 0|} 20| | 21| 0|public func await(_ body: (@escaping (T) -> Void) -> Void) -> T { 22| 0| let condition = Condition() 23| 0| var result: T? = nil 24| 0| body { theResult in 25| 0| condition.whileLocked { 26| 0| result = theResult 27| 0| condition.signal() 28| 0| } 29| 0| } 30| 0| condition.whileLocked { 31| 0| while result == nil { 32| 0| condition.wait() 33| 0| } 34| 0| } 35| 0| return result! 36| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/ByteString.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A `ByteString` represents a sequence of bytes. 12| |/// 13| |/// This struct provides useful operations for working with buffers of 14| |/// bytes. Conceptually it is just a contiguous array of bytes (UInt8), but it 15| |/// contains methods and default behavor suitable for common operations done 16| |/// using bytes strings. 17| |/// 18| |/// This struct *is not* intended to be used for significant mutation of byte 19| |/// strings, we wish to retain the flexibility to micro-optimize the memory 20| |/// allocation of the storage (for example, by inlining the storage for small 21| |/// strings or and by eliminating wasted space in growable arrays). For 22| |/// construction of byte arrays, clients should use the `OutputByteStream` class 23| |/// and then convert to a `ByteString` when complete. 24| |public struct ByteString: ExpressibleByArrayLiteral, Hashable { 25| | /// The buffer contents. 26| | fileprivate var _bytes: [UInt8] 27| | 28| | /// Create an empty byte string. 29| 0| public init() { 30| 0| _bytes = [] 31| 0| } 32| | 33| | /// Create a byte string from a byte array literal. 34| 0| public init(arrayLiteral contents: UInt8...) { 35| 0| _bytes = contents 36| 0| } 37| | 38| | /// Create a byte string from an array of bytes. 39| 2| public init(_ contents: [UInt8]) { 40| 2| _bytes = contents 41| 2| } 42| | 43| | /// Create a byte string from an byte buffer. 44| 0| public init (_ contents: S) where S.Iterator.Element == UInt8 { 45| 0| _bytes = [UInt8](contents) 46| 0| } 47| | 48| | /// Create a byte string from the UTF8 encoding of a string. 49| 0| public init(encodingAsUTF8 string: String) { 50| 0| _bytes = [UInt8](string.utf8) 51| 0| } 52| | 53| | /// Access the byte string contents as an array. 54| 0| public var contents: [UInt8] { 55| 0| return _bytes 56| 0| } 57| | 58| | /// Return the byte string size. 59| 0| public var count: Int { 60| 0| return _bytes.count 61| 0| } 62| |} 63| | 64| |/// Conform to CustomDebugStringConvertible. 65| |extension ByteString: CustomStringConvertible { 66| | /// Return the string decoded as a UTF8 sequence, or traps if not possible. 67| 2| public var description: String { 68| 2| guard let description = validDescription else { 69| 0| fatalError("invalid byte string: \(cString)") 70| 2| } 71| 2| 72| 2| return description 73| 2| } 74| | 75| | /// Return the string decoded as a UTF8 sequence, if possible. 76| 2| public var validDescription: String? { 77| 2| // FIXME: This is very inefficient, we need a way to pass a buffer. It 78| 2| // is also wrong if the string contains embedded '\0' characters. 79| 2| let tmp = _bytes + [UInt8(0)] 80| 2| return tmp.withUnsafeBufferPointer { ptr in 81| 2| return String(validatingUTF8: unsafeBitCast(ptr.baseAddress, to: UnsafePointer.self)) 82| 2| } 83| 2| } 84| | 85| | /// Return the string decoded as a UTF8 sequence, substituting replacement 86| | /// characters for ill-formed UTF8 sequences. 87| 0| public var cString: String { 88| 0| // FIXME: This is very inefficient, we need a way to pass a buffer. It 89| 0| // is also wrong if the string contains embedded '\0' characters. 90| 0| let tmp = _bytes + [UInt8(0)] 91| 0| return tmp.withUnsafeBufferPointer { ptr in 92| 0| return String(cString: unsafeBitCast(ptr.baseAddress, to: UnsafePointer.self)) 93| 0| } 94| 0| } 95| | 96| | @available(*, deprecated, message: "use description or validDescription instead") 97| 0| public var asString: String? { 98| 0| return validDescription 99| 0| } 100| |} 101| | 102| |/// ByteStreamable conformance for a ByteString. 103| |extension ByteString: ByteStreamable { 104| 0| public func write(to stream: OutputByteStream) { 105| 0| stream.write(_bytes) 106| 0| } 107| |} 108| | 109| |/// StringLiteralConvertable conformance for a ByteString. 110| |extension ByteString: ExpressibleByStringLiteral { 111| | public typealias UnicodeScalarLiteralType = StringLiteralType 112| | public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType 113| | 114| 0| public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { 115| 0| _bytes = [UInt8](value.utf8) 116| 0| } 117| 0| public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { 118| 0| _bytes = [UInt8](value.utf8) 119| 0| } 120| 0| public init(stringLiteral value: StringLiteralType) { 121| 0| _bytes = [UInt8](value.utf8) 122| 0| } 123| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/CStringArray.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import SPMLibc 12| | 13| |/// `CStringArray` represents a C null-terminated array of pointers to C strings. 14| |/// 15| |/// The lifetime of the C strings will correspond to the lifetime of the `CStringArray` 16| |/// instance so be careful about copying the buffer as it may contain dangling pointers. 17| |public final class CStringArray { 18| | /// The null-terminated array of C string pointers. 19| | public let cArray: [UnsafeMutablePointer?] 20| | 21| | /// Creates an instance from an array of strings. 22| 0| public init(_ array: [String]) { 23| 0| cArray = array.map({ $0.withCString({ strdup($0) }) }) + [nil] 24| 0| } 25| | 26| 0| deinit { 27| 0| for case let element? in cArray { 28| 0| free(element) 29| 0| } 30| 0| } 31| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/CacheableSequence.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Wrapper for caching an arbitrary sequence. 12| |public final class CacheableSequence: Sequence { 13| | public typealias Element = T.Element 14| | public typealias Iterator = CacheableSequenceIterator 15| | 16| | /// The list of consumed items. 17| | fileprivate var items: [Element] = [] 18| | 19| | /// An iterator on the underlying sequence, until complete. 20| | fileprivate var it: T.Iterator? 21| | 22| 0| public init(_ sequence: T) { 23| 0| self.it = sequence.makeIterator() 24| 0| } 25| | 26| 0| public func makeIterator() -> Iterator { 27| 0| return CacheableSequenceIterator(self) 28| 0| } 29| | 30| | /// Get the item at the given index. 31| | /// 32| | /// The index must either be at most one past the number of already captured 33| | /// items. 34| 0| fileprivate subscript(_ index: Int) -> Element? { 35| 0| assert(index >= 0 && index <= items.count) 36| 0| if index < items.count { 37| 0| return items[index] 38| 0| } else if self.it != nil { 39| 0| // If we still have an iterator, attempt to consume a new item. 40| 0| guard let item = it!.next() else { 41| 0| // We reached the end of the sequence, we can discard the iterator. 42| 0| self.it = nil 43| 0| return nil 44| 0| } 45| 0| items.append(item) 46| 0| return items[index] 47| 0| } else { 48| 0| return nil 49| 0| } 50| 0| } 51| |} 52| | 53| |/// An iterator for a CacheableSequence. 54| |public final class CacheableSequenceIterator: IteratorProtocol { 55| | public typealias Element = T.Element 56| | 57| | /// The index of the iterator. 58| | var index = 0 59| | 60| | /// The sequence being iterated. 61| | let sequence: CacheableSequence 62| | 63| 0| init(_ sequence: CacheableSequence) { 64| 0| self.sequence = sequence 65| 0| } 66| | 67| 0| public func next() -> Element? { 68| 0| if let item = self.sequence[index] { 69| 0| index += 1 70| 0| return item 71| 0| } 72| 0| return nil 73| 0| } 74| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/CollectionAlgorithms.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |extension Sequence where Iterator.Element: Hashable { 12| | 13| | /// Finds duplicates in given sequence of Hashables. 14| | /// - Returns: duplicated elements in the invoking sequence. 15| 0| public func spm_findDuplicates() -> [Iterator.Element] { 16| 0| var unique: Set = [] 17| 0| return filter { 18| 0| !unique.insert($0).inserted 19| 0| } 20| 0| } 21| |} 22| | 23| |extension Collection where Element: Hashable { 24| | 25| | /// Finds duplicates in given collection of Hashables. 26| 0| public func spm_findDuplicateElements() -> [[Element]] { 27| 0| var table: [Element: [Element]] = [:] 28| 0| for element in self { 29| 0| table[element, default: []].append(element) 30| 0| } 31| 0| return table.values.filter({ $0.count > 1 }) 32| 0| } 33| |} 34| | 35| |extension Sequence { 36| | public func spm_findDuplicateElements( 37| | by keyPath: KeyPath 38| 0| ) -> [[Element]] { 39| 0| return Dictionary(grouping: self, by: { $0[keyPath: keyPath] }) 40| 0| .values 41| 0| .filter({ $0.count > 1 }) 42| 0| } 43| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/CollectionExtensions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |extension Collection { 12| | /// Returns the only element of the collection or nil. 13| 0| public var spm_only: Element? { 14| 0| return count == 1 ? self[startIndex] : nil 15| 0| } 16| | 17| | /// Prints the element of array to standard output stream. 18| | /// 19| | /// This method should be used for debugging only. 20| 0| public func spm_dump() { 21| 0| for element in self { 22| 0| print(element) 23| 0| } 24| 0| } 25| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Condition.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| | 13| |/// Simple wrapper around NSCondition. 14| |/// - SeeAlso: NSCondition 15| |public struct Condition { 16| | private let _condition = NSCondition() 17| | 18| | /// Create a new condition. 19| 0| public init() {} 20| | 21| | /// Wait for the condition to become available. 22| 0| public func wait() { 23| 0| _condition.wait() 24| 0| } 25| | 26| | /// Blocks the current thread until the condition is signaled or the specified time limit is reached. 27| | /// 28| | /// - Returns: true if the condition was signaled; otherwise, false if the time limit was reached. 29| 0| public func wait(until limit: Date) -> Bool { 30| 0| return _condition.wait(until: limit) 31| 0| } 32| | 33| | /// Signal the availability of the condition (awake one thread waiting on 34| | /// the condition). 35| 0| public func signal() { 36| 0| _condition.signal() 37| 0| } 38| | 39| | /// Broadcast the availability of the condition (awake all threads waiting 40| | /// on the condition). 41| 0| public func broadcast() { 42| 0| _condition.broadcast() 43| 0| } 44| | 45| | /// A helper method to execute the given body while condition is locked. 46| | /// - Note: Will ensure condition unlocks even if `body` throws. 47| 0| public func whileLocked(_ body: () throws -> T) rethrows -> T { 48| 0| _condition.lock() 49| 0| defer { _condition.unlock() } 50| 0| return try body() 51| 0| } 52| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/DeltaAlgorithm.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Delta debugging algorithm (A. Zeller '99) for minimizing arbitrary sets 12| |/// using a predicate function. 13| |/// 14| |/// The result of the algorithm is a subset of the input change set which is 15| |/// guaranteed to satisfy the predicate, assuming that the input set did. For 16| |/// well formed predicates, the result set is guaranteed to be such that 17| |/// removing any single element would falsify the predicate. 18| |/// 19| |/// For best results the predicate function *should* (but need not) satisfy 20| |/// certain properties, in particular: 21| |/// 22| |/// 1. The predicate should return false on an empty set and true on the full 23| |/// set. 24| |/// 2. If the predicate returns true for a set of changes, it should return 25| |/// true for all supersets of that set. 26| |/// 27| |/// It is not an error to provide a predicate that does not satisfy these 28| |/// requirements, and the algorithm will generally produce reasonable results. 29| |/// However, it may run substantially more tests than with a good predicate. 30| |public struct DeltaAlgorithm { 31| | 32| 0| public init() {} 33| | 34| | /// Minimizes the set `changes` by executing `predicate` on subsets of 35| | /// changes and returning the smallest set which still satisfies the test 36| | /// predicate. 37| 0| public func run(changes: Set, predicate: (Set) throws -> Bool) rethrows -> Set { 38| 0| // Check empty set first to quickly find poor test functions. 39| 0| if try predicate(Set()) { 40| 0| return Set() 41| 0| } 42| 0| // Run the algorithm. 43| 0| return try delta(changes: changes, changeSets: split(changes), predicate: predicate) 44| 0| } 45| | 46| | /// Partition a set of changes into one or two subsets. 47| 0| func split(_ set: Set) -> [Set] { 48| 0| var lhs = Set() 49| 0| var rhs = Set() 50| 0| let n = set.count / 2 51| 0| for (idx, element) in set.enumerated() { 52| 0| if idx < n { 53| 0| lhs.insert(element) 54| 0| } else { 55| 0| rhs.insert(element) 56| 0| } 57| 0| } 58| 0| var result = [Set]() 59| 0| if !lhs.isEmpty { 60| 0| result.append(lhs) 61| 0| } 62| 0| if !rhs.isEmpty { 63| 0| result.append(rhs) 64| 0| } 65| 0| return result 66| 0| } 67| | 68| | /// Minimizes a set of `changes` which has been partioned into smaller sets, 69| | /// by attempting to remove individual subsets. 70| | func delta( 71| | changes: Set, 72| | changeSets: [Set], 73| | predicate: (Set) throws -> Bool 74| 0| ) rethrows -> Set { 75| 0| // If there is nothing left we can remove, we are done. 76| 0| if changeSets.count <= 1 { 77| 0| return changes 78| 0| } 79| 0| 80| 0| // Look for a passing subset. 81| 0| if let result = try search(changes: changes, changeSets: changeSets, predicate: predicate) { 82| 0| return result 83| 0| } 84| 0| 85| 0| // Otherwise, partition the sets if possible; if not we are done. 86| 0| let splitSets = changeSets.flatMap(split) 87| 0| if splitSets.count == changeSets.count { 88| 0| return changes 89| 0| } 90| 0| return try delta(changes: changes, changeSets: splitSets, predicate: predicate) 91| 0| } 92| | 93| | /// Search for a subset (or subsets) in `changeSets` which can be 94| | /// removed from `changes` while still satisfying the predicate. 95| | /// 96| | /// - Returns: a subset of `changes` which satisfies the predicate. 97| | func search( 98| | changes: Set, 99| | changeSets: [Set], 100| | predicate: (Set) throws -> Bool 101| 0| ) rethrows -> Set? { 102| 0| for (idx, currentSet) in changeSets.enumerated() { 103| 0| // If the test passes on this subset alone, recurse. 104| 0| if try predicate(currentSet) { 105| 0| return try delta( 106| 0| changes: currentSet, changeSets: split(currentSet), predicate: predicate) 107| 0| } 108| 0| 109| 0| // Otherwise, if we have more than two sets, see if test passes on the complement. 110| 0| if changeSets.count > 2 { 111| 0| let compliment = changes.subtracting(currentSet) 112| 0| if try predicate(compliment) { 113| 0| var complimentSets = [Set]() 114| 0| let idxIndex = changeSets.index(changeSets.startIndex, offsetBy: idx) 115| 0| complimentSets += changeSets[changeSets.startIndex.. { 33| | public var fragments: [DiagnosticID.DescriptionFragment] = [] 34| | 35| | func build( 36| | _ body: (DiagnosticDescriptionBuilder) -> Void 37| 0| ) -> [DiagnosticID.DescriptionFragment] { 38| 0| body(self) 39| 0| return fragments 40| 0| } 41| |} 42| | 43| |@discardableResult 44| |public func <<< ( 45| | builder: DiagnosticDescriptionBuilder, 46| | string: String 47| 0|) -> DiagnosticDescriptionBuilder { 48| 0| builder.fragments.append(.literal(string, preference: .default)) 49| 0| return builder 50| 0|} 51| | 52| |@discardableResult 53| |public func <<<( 54| | builder: DiagnosticDescriptionBuilder, 55| | accessor: @escaping (T) -> P 56| 0|) -> DiagnosticDescriptionBuilder { 57| 0| builder.fragments.append(.substitution({ accessor($0 as! T) }, preference: .default)) 58| 0| return builder 59| 0|} 60| | 61| |@discardableResult 62| |public func <<< ( 63| | builder: DiagnosticDescriptionBuilder, 64| | fragment: DiagnosticID.DescriptionFragment 65| 0|) -> DiagnosticDescriptionBuilder { 66| 0| builder.fragments.append(fragment) 67| 0| return builder 68| 0|} 69| | 70| |// FIXME: One thing we should consider is whether we should make the diagnostic 71| |// a protocol and put these properties on the type, which is conceptually the 72| |// right modeling, but might be cumbersome of our desired features don't 73| |// perfectly align with what the language can express. 74| |// 75| |/// A unique identifier for a diagnostic. 76| |/// 77| |/// Diagnostic identifiers are intended to be a stable representation of a 78| |/// particular kind of diagnostic that can be emitted by the client. 79| |/// 80| |/// The stabilty of identifiers is important for use cases where the client 81| |/// (e.g., a command line tool, an IDE, or a web UI) is expecting to receive 82| |/// diagnostics and be able to present additional UI affordances or workflows 83| |/// associated for specific kinds of diagnostics. 84| |public class DiagnosticID: ObjectIdentifierProtocol { 85| | 86| | /// A piece of a diagnostic description. 87| | public enum DescriptionFragment { 88| | /// Represents how important a fragment is. 89| | public enum Preference { 90| | case low, `default`, high 91| | } 92| | 93| | /// A literal string. 94| | case literalItem(String, preference: Preference) 95| | 96| | /// A substitution of a computed value. 97| | case substitutionItem((DiagnosticData) -> DiagnosticParameter, preference: Preference) 98| | 99| | public static func literal( 100| | _ string: String, 101| | preference: Preference = .default 102| 0| ) -> DescriptionFragment { 103| 0| return .literalItem(string, preference: preference) 104| 0| } 105| | 106| | public static func substitution( 107| | _ accessor: @escaping ((DiagnosticData) -> DiagnosticParameter), 108| | preference: Preference = .default 109| 0| ) -> DescriptionFragment { 110| 0| return .substitutionItem(accessor, preference: preference) 111| 0| } 112| | } 113| | 114| | /// The name of the diagnostic, which is expected to be in reverse dotted notation. 115| | public let name: String 116| | 117| | /// The English format string for the diagnostic description. 118| | public let description: [DescriptionFragment] 119| | 120| | /// The default behavior associated with this diagnostic. 121| | public let defaultBehavior: Diagnostic.Behavior 122| | 123| | /// Create a new diagnostic identifier. 124| | /// 125| | /// - Parameters: 126| | /// - type: The type of the payload data, used to help type inference. 127| | /// 128| | /// - name: The name of the identifier. 129| | /// 130| | /// - description: A closure which will compute the description from a 131| | /// builder. We compute descriptions in this fashion in 132| | /// order to take advantage of type inference to make it 133| | /// easy to have type safe accessors for the payload 134| | /// properties. 135| | /// 136| | /// The intended use is to support a convenient inline syntax for defining 137| | /// new diagnostics, for example: 138| | /// 139| | /// struct TooFewLives: DiagnosticData { 140| | /// static var id = DiagnosticID( 141| | /// type: TooFewLives.self, 142| | /// name: "org.swift.diags.too-few-lives", 143| | /// description: { $0 <<< "cannot create a cat with" <<< { $0.count } <<< "lives" } 144| | /// ) 145| | /// 146| | /// let count: Int 147| | /// } 148| | public init( 149| | type: T.Type, 150| | name: String, 151| | defaultBehavior: Diagnostic.Behavior = .error, 152| | description buildDescription: (DiagnosticDescriptionBuilder) -> Void 153| 0| ) { 154| 0| self.name = name 155| 0| self.description = DiagnosticDescriptionBuilder().build(buildDescription) 156| 0| self.defaultBehavior = defaultBehavior 157| 0| } 158| |} 159| | 160| |/// The payload of a diagnostic. 161| |public protocol DiagnosticData: CustomStringConvertible { 162| | /// The identifier of the diagnostic this payload corresponds to. 163| | static var id: DiagnosticID { get } 164| |} 165| | 166| |extension DiagnosticData { 167| 0| public var description: String { 168| 0| return localizedDescription(for: self) 169| 0| } 170| |} 171| | 172| |/// The location of the diagnostic. 173| |public protocol DiagnosticLocation { 174| | /// The human readable summary description for the location. 175| | var localizedDescription: String { get } 176| |} 177| | 178| |public struct Diagnostic { 179| | public typealias Location = DiagnosticLocation 180| | 181| | /// The behavior associated with this diagnostic. 182| | public enum Behavior { 183| | /// An error which will halt the operation. 184| | case error 185| | 186| | /// A warning, but which will not halt the operation. 187| | case warning 188| | 189| | /// An informational message. 190| | case note 191| | 192| | /// A diagnostic which was ignored. 193| | case ignored 194| | } 195| | 196| | /// The diagnostic identifier. 197| 0| public var id: DiagnosticID { 198| 0| return type(of: data).id 199| 0| } 200| | 201| | /// The diagnostic's behavior. 202| | public let behavior: Behavior 203| | 204| | /// The conceptual location of this diagnostic. 205| | /// 206| | /// This could refer to a concrete location in a file, for example, but it 207| | /// could also refer to an abstract location such as "the Git repository at 208| | /// this URL". 209| | public let location: Location 210| | 211| | /// The information on the actual diagnostic. 212| | public let data: DiagnosticData 213| | 214| | // FIXME: Need additional attachment mechanism (backtrace, etc.), or 215| | // extensible handlers (e.g., interactive diagnostics). 216| | 217| | /// Create a new diagnostic. 218| | /// 219| | /// - Parameters: 220| | /// - location: The abstract location of the issue which triggered the diagnostic. 221| | /// - parameters: The parameters to the diagnostic conveying additional information. 222| | /// - Precondition: The bindings must match those declared by the identifier. 223| 0| public init(location: Location, data: DiagnosticData) { 224| 0| // FIXME: Implement behavior overrides. 225| 0| self.behavior = type(of: data).id.defaultBehavior 226| 0| self.location = location 227| 0| self.data = data 228| 0| } 229| | 230| | /// The human readable summary description for the diagnostic. 231| 0| public var localizedDescription: String { 232| 0| return Basic.localizedDescription(for: data) 233| 0| } 234| |} 235| | 236| |/// A scope of diagnostics. 237| |/// 238| |/// The scope provides aggregate information on all of the diagnostics which can 239| |/// be produced by a component. 240| |public protocol DiagnosticsScope { 241| | /// Get a URL for more information on a particular diagnostic ID. 242| | /// 243| | /// This is intended to be used to provide verbose descriptions for diagnostics. 244| | /// 245| | /// - Parameters: 246| | /// - id: The diagnostic ID to describe. 247| | /// - diagnostic: If provided, a specific diagnostic to describe. 248| | /// - Returns: If available, a URL which will give more information about 249| | /// the diagnostic. 250| | func url(describing id: DiagnosticID, for diagnostic: Diagnostic?) -> String? 251| |} 252| | 253| |public class DiagnosticsEngine: CustomStringConvertible { 254| | 255| | public typealias DiagnosticsHandler = (Diagnostic) -> Void 256| | 257| | /// Queue to protect concurrent mutations to the diagnositcs engine. 258| | private let queue = DispatchQueue(label: "\(DiagnosticsEngine.self)") 259| | 260| | /// Queue for dispatching handlers. 261| | private let handlerQueue = DispatchQueue(label: "\(DiagnosticsEngine.self)-callback") 262| | 263| | /// The diagnostics produced by the engine. 264| 0| public var diagnostics: [Diagnostic] { 265| 0| return queue.sync { _diagnostics } 266| 0| } 267| | private var _diagnostics: [Diagnostic] = [] 268| | 269| | /// The list of handlers to run when a diagnostic is emitted. 270| | /// 271| | /// The handler will be called on an unknown queue. 272| | private let handlers: [DiagnosticsHandler] 273| | 274| | /// Returns true if there is an error diagnostics in the engine. 275| 0| public var hasErrors: Bool { 276| 0| return diagnostics.contains(where: { $0.behavior == .error }) 277| 0| } 278| | 279| 0| public init(handlers: [DiagnosticsHandler] = []) { 280| 0| self.handlers = handlers 281| 0| } 282| | 283| 0| public func emit(data: DiagnosticData, location: DiagnosticLocation) { 284| 0| let diagnostic = Diagnostic(location: location, data: data) 285| 0| 286| 0| queue.sync { 287| 0| _diagnostics.append(diagnostic) 288| 0| } 289| 0| 290| 0| // Call the handlers on the background queue, if we have any. 291| 0| if !handlers.isEmpty { 292| 0| // FIXME: We should probably do this async but then we need 293| 0| // a way for clients to be able to wait until all handlers 294| 0| // are called. 295| 0| handlerQueue.sync { 296| 0| for handler in self.handlers { 297| 0| handler(diagnostic) 298| 0| } 299| 0| } 300| 0| } 301| 0| } 302| | 303| | /// Merges contents of given engine. 304| 0| public func merge(_ engine: DiagnosticsEngine) { 305| 0| for diagnostic in engine.diagnostics { 306| 0| emit(data: diagnostic.data, location: diagnostic.location) 307| 0| } 308| 0| } 309| | 310| 0| public var description: String { 311| 0| let stream = BufferedOutputByteStream() 312| 0| stream <<< "[" 313| 0| for diag in diagnostics { 314| 0| stream <<< diag.localizedDescription <<< ", " 315| 0| } 316| 0| stream <<< "]" 317| 0| return stream.bytes.description 318| 0| } 319| |} 320| | 321| |/// Returns localized description of a diagnostic data. 322| 0|fileprivate func localizedDescription(for data: DiagnosticData) -> String { 323| 0| var result = "" 324| 0| for (i, fragment) in type(of: data).id.description.enumerated() { 325| 0| if i != 0 { 326| 0| result += " " 327| 0| } 328| 0| 329| 0| switch fragment { 330| 0| case let .literalItem(string, _): 331| 0| result += string 332| 0| case let .substitutionItem(accessor, _): 333| 0| result += accessor(data).diagnosticDescription 334| 0| } 335| 0| } 336| 0| return result 337| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/DictionaryExtensions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |extension Dictionary { 12| | /// Convenience initializer to create dictionary from tuples. 13| 14| public init(items: S) where S.Iterator.Element == (Key, Value) { 14| 14| self.init(minimumCapacity: items.underestimatedCount) 15| 14| for (key, value) in items { 16| 0| self[key] = value 17| 14| } 18| 14| } 19| | 20| | /// Convenience initializer to create dictionary from tuples. 21| 0| public init(items: S) where S.Iterator.Element == (Key, Optional) { 22| 0| self.init(minimumCapacity: items.underestimatedCount) 23| 0| for (key, value) in items { 24| 0| self[key] = value 25| 0| } 26| 0| } 27| | 28| | /// Returns a new dictionary containing the keys of this dictionary with the 29| | /// values transformed by the given closure, if transformed is not nil. 30| 0| public func spm_flatMapValues(_ transform: (Value) throws -> T?) rethrows -> [Key: T] { 31| 0| var transformed: [Key: T] = [:] 32| 0| for (key, value) in self { 33| 0| if let value = try transform(value) { 34| 0| transformed[key] = value 35| 0| } 36| 0| } 37| 0| return transformed 38| 0| } 39| |} 40| | 41| |extension Array { 42| | /// Create a dictionary with given sequence of elements. 43| | public func spm_createDictionary( 44| | _ uniqueKeysWithValues: (Element) -> (Key, Value) 45| 0| ) -> [Key: Value] { 46| 0| return Dictionary(uniqueKeysWithValues: self.map(uniqueKeysWithValues)) 47| 0| } 48| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/DictionaryLiteralExtensions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |// Can't conform a protocol explicitly with certain where clause for now but it'd be resolved by SE-0143. 12| |// ref: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md 13| |// MARK: CustomStringConvertible 14| |extension DictionaryLiteral where Key: CustomStringConvertible, Value: CustomStringConvertible { 15| | /// A string that represents the contents of the dictionary literal. 16| 0| public var description: String { 17| 0| let lastCount = self.count - 1 18| 0| var desc = "[" 19| 0| for (i, item) in self.enumerated() { 20| 0| desc.append("\(item.key.description): \(item.value.description)") 21| 0| desc.append(i == lastCount ? "]" : ", ") 22| 0| } 23| 0| return desc 24| 0| } 25| |} 26| | 27| |// MARK: Equatable 28| |extension DictionaryLiteral where Key: Equatable, Value: Equatable { 29| 0| public static func ==(lhs: DictionaryLiteral, rhs: DictionaryLiteral) -> Bool { 30| 0| if lhs.count != rhs.count { 31| 0| return false 32| 0| } 33| 0| for i in 0.. Int { 16| 0| let a = Array(first.utf16) 17| 0| let b = Array(second.utf16) 18| 0| var distance = [[Int]](repeating: [Int](repeating: 0, count: b.count + 1), count: a.count + 1) 19| 0| for i in 0...a.count { 20| 0| for j in 0...b.count { 21| 0| if i == 0 { 22| 0| distance[i][j] = j 23| 0| } else if j == 0 { 24| 0| distance[i][j] = i 25| 0| } else if a[i - 1] == b[j - 1] { 26| 0| distance[i][j] = distance[i - 1][j - 1] 27| 0| } else { 28| 0| let insertion = distance[i][ j - 1] 29| 0| let deletion = distance[i - 1][j] 30| 0| let replacement = distance[i - 1][j - 1] 31| 0| distance[i][j] = 1 + min(insertion, deletion, replacement) 32| 0| } 33| 0| } 34| 0| } 35| 0| return distance[a.count][b.count] 36| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/FileSystem.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import POSIX 12| |import SPMLibc 13| |import Foundation 14| | 15| |public enum FileSystemError: Swift.Error { 16| | /// Access to the path is denied. 17| | /// 18| | /// This is used when an operation cannot be completed because a component of 19| | /// the path cannot be accessed. 20| | /// 21| | /// Used in situations that correspond to the POSIX EACCES error code. 22| | case invalidAccess 23| | 24| | /// Invalid encoding 25| | /// 26| | /// This is used when an operation cannot be completed because a path could 27| | /// not be decoded correctly. 28| | case invalidEncoding 29| | 30| | /// IO Error encoding 31| | /// 32| | /// This is used when an operation cannot be completed due to an otherwise 33| | /// unspecified IO error. 34| | case ioError 35| | 36| | /// Is a directory 37| | /// 38| | /// This is used when an operation cannot be completed because a component 39| | /// of the path which was expected to be a file was not. 40| | /// 41| | /// Used in situations that correspond to the POSIX EISDIR error code. 42| | case isDirectory 43| | 44| | /// No such path exists. 45| | /// 46| | /// This is used when a path specified does not exist, but it was expected 47| | /// to. 48| | /// 49| | /// Used in situations that correspond to the POSIX ENOENT error code. 50| | case noEntry 51| | 52| | /// Not a directory 53| | /// 54| | /// This is used when an operation cannot be completed because a component 55| | /// of the path which was expected to be a directory was not. 56| | /// 57| | /// Used in situations that correspond to the POSIX ENOTDIR error code. 58| | case notDirectory 59| | 60| | /// Unsupported operation 61| | /// 62| | /// This is used when an operation is not supported by the concrete file 63| | /// system implementation. 64| | case unsupported 65| | 66| | /// An unspecific operating system error. 67| | case unknownOSError 68| |} 69| | 70| |extension FileSystemError { 71| 0| init(errno: Int32) { 72| 0| switch errno { 73| 0| case SPMLibc.EACCES: 74| 0| self = .invalidAccess 75| 0| case SPMLibc.EISDIR: 76| 0| self = .isDirectory 77| 0| case SPMLibc.ENOENT: 78| 0| self = .noEntry 79| 0| case SPMLibc.ENOTDIR: 80| 0| self = .notDirectory 81| 0| default: 82| 0| self = .unknownOSError 83| 0| } 84| 0| } 85| |} 86| | 87| |/// Defines the file modes. 88| |public enum FileMode { 89| | 90| | public enum Option: Int { 91| | case recursive 92| | case onlyFiles 93| | } 94| | 95| | case userUnWritable 96| | case userWritable 97| | case executable 98| | 99| | /// File mode as it would be passed to `chmod`. 100| 0| public var cliArgument: String { 101| 0| switch self { 102| 0| case .userUnWritable: 103| 0| return "u-w" 104| 0| case .userWritable: 105| 0| return "u+w" 106| 0| case .executable: 107| 0| return "+x" 108| 0| } 109| 0| } 110| |} 111| | 112| |// FIXME: Design an asynchronous story? 113| |// 114| |/// Abstracted access to file system operations. 115| |/// 116| |/// This protocol is used to allow most of the codebase to interact with a 117| |/// natural filesystem interface, while still allowing clients to transparently 118| |/// substitute a virtual file system or redirect file system operations. 119| |/// 120| |/// - Note: All of these APIs are synchronous and can block. 121| |public protocol FileSystem: class { 122| | /// Check whether the given path exists and is accessible. 123| | func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool 124| | 125| | /// Check whether the given path is accessible and a directory. 126| | func isDirectory(_ path: AbsolutePath) -> Bool 127| | 128| | /// Check whether the given path is accessible and a file. 129| | func isFile(_ path: AbsolutePath) -> Bool 130| | 131| | /// Check whether the given path is an accessible and executable file. 132| | func isExecutableFile(_ path: AbsolutePath) -> Bool 133| | 134| | /// Check whether the given path is accessible and is a symbolic link. 135| | func isSymlink(_ path: AbsolutePath) -> Bool 136| | 137| | // FIXME: Actual file system interfaces will allow more efficient access to 138| | // more data than just the name here. 139| | // 140| | /// Get the contents of the given directory, in an undefined order. 141| | func getDirectoryContents(_ path: AbsolutePath) throws -> [String] 142| | 143| | /// Get the current working directory (similar to `getcwd(3)`), which can be 144| | /// different for different (virtualized) implementations of a FileSystem. 145| | /// The current working directory can be empty if e.g. the directory became 146| | /// unavailable while the current process was still working in it. 147| | /// This follows the POSIX `getcwd(3)` semantics. 148| | var currentWorkingDirectory: AbsolutePath? { get } 149| | 150| | /// Get the home directory of current user 151| | var homeDirectory: AbsolutePath { get } 152| | 153| | /// Create the given directory. 154| | func createDirectory(_ path: AbsolutePath) throws 155| | 156| | /// Create the given directory. 157| | /// 158| | /// - recursive: If true, create missing parent directories if possible. 159| | func createDirectory(_ path: AbsolutePath, recursive: Bool) throws 160| | 161| | // FIXME: This is obviously not a very efficient or flexible API. 162| | // 163| | /// Get the contents of a file. 164| | /// 165| | /// - Returns: The file contents as bytes, or nil if missing. 166| | func readFileContents(_ path: AbsolutePath) throws -> ByteString 167| | 168| | // FIXME: This is obviously not a very efficient or flexible API. 169| | // 170| | /// Write the contents of a file. 171| | func writeFileContents(_ path: AbsolutePath, bytes: ByteString) throws 172| | 173| | // FIXME: This is obviously not a very efficient or flexible API. 174| | // 175| | /// Write the contents of a file. 176| | func writeFileContents(_ path: AbsolutePath, bytes: ByteString, atomically: Bool) throws 177| | 178| | /// Recursively deletes the file system entity at `path`. 179| | /// 180| | /// If there is no file system entity at `path`, this function does nothing (in particular, this is not considered 181| | /// to be an error). 182| | func removeFileTree(_ path: AbsolutePath) throws 183| | 184| | /// Change file mode. 185| | func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws 186| | 187| | 188| | /// Returns the file info of the given path. 189| | /// 190| | /// If `followSymlink` is true and the file system entity at `path` is a symbolic link, it is traversed; 191| | /// otherwise it is not (any symbolic links in path components other than the last one are always traversed). 192| | /// 193| | /// The method throws if the underlying stat call fails. 194| | func getFileInfo(_ path: AbsolutePath, followSymlink: Bool) throws -> FileInfo 195| |} 196| | 197| |/// Convenience implementations (default arguments aren't permitted in protocol 198| |/// methods). 199| |public extension FileSystem { 200| | /// exists override with default value. 201| 0| func exists(_ path: AbsolutePath) -> Bool { 202| 0| return exists(path, followSymlink: true) 203| 0| } 204| | 205| | /// Default implementation of createDirectory(_:) 206| 0| func createDirectory(_ path: AbsolutePath) throws { 207| 0| try createDirectory(path, recursive: false) 208| 0| } 209| | 210| | // Change file mode. 211| 0| func chmod(_ mode: FileMode, path: AbsolutePath) throws { 212| 0| try chmod(mode, path: path, options: []) 213| 0| } 214| | 215| | // Unless the file system type provides an override for this method, throw 216| | // if `atomically` is `true`, otherwise fall back to whatever implementation already exists. 217| 0| func writeFileContents(_ path: AbsolutePath, bytes: ByteString, atomically: Bool) throws { 218| 0| guard !atomically else { 219| 0| throw FileSystemError.unsupported 220| 0| } 221| 0| try writeFileContents(path, bytes: bytes) 222| 0| } 223| | 224| | /// Write to a file from a stream producer. 225| 0| func writeFileContents(_ path: AbsolutePath, body: (OutputByteStream) -> Void) throws { 226| 0| let contents = BufferedOutputByteStream() 227| 0| body(contents) 228| 0| try createDirectory(path.parentDirectory, recursive: true) 229| 0| try writeFileContents(path, bytes: contents.bytes) 230| 0| } 231| | 232| 0| func getFileInfo(_ path: AbsolutePath) throws -> FileInfo { 233| 0| return try getFileInfo(path, followSymlink: true) 234| 0| } 235| | 236| 0| func getFileInfo(_ path: AbsolutePath, followSymlink: Bool) throws -> FileInfo { 237| 0| fatalError("This file system currently doesn't support this method") 238| 0| } 239| |} 240| | 241| |/// Concrete FileSystem implementation which communicates with the local file system. 242| |private class LocalFileSystem: FileSystem { 243| | 244| 0| func isExecutableFile(_ path: AbsolutePath) -> Bool { 245| 0| guard let filestat = try? POSIX.stat(path.pathString) else { 246| 0| return false 247| 0| } 248| 0| return filestat.st_mode & SPMLibc.S_IXUSR != 0 && filestat.st_mode & S_IFREG != 0 249| 0| } 250| | 251| 0| func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool { 252| 0| return Basic.exists(path, followSymlink: followSymlink) 253| 0| } 254| | 255| 0| func isDirectory(_ path: AbsolutePath) -> Bool { 256| 0| return Basic.isDirectory(path) 257| 0| } 258| | 259| 0| func isFile(_ path: AbsolutePath) -> Bool { 260| 0| return Basic.isFile(path) 261| 0| } 262| | 263| 0| func isSymlink(_ path: AbsolutePath) -> Bool { 264| 0| return Basic.isSymlink(path) 265| 0| } 266| | 267| 0| func getFileInfo(_ path: AbsolutePath, followSymlink: Bool = true) throws -> FileInfo { 268| 0| let statBuf = try stat(path, followSymlink: followSymlink) 269| 0| return FileInfo(statBuf) 270| 0| } 271| | 272| 0| var currentWorkingDirectory: AbsolutePath? { 273| 0| let cwdStr = FileManager.default.currentDirectoryPath 274| 0| return try? AbsolutePath(validating: cwdStr) 275| 0| } 276| | 277| 0| var homeDirectory: AbsolutePath { 278| 0| if #available(macOS 10.12, *) { 279| 0| return AbsolutePath(FileManager.default.homeDirectoryForCurrentUser.path) 280| 0| } else { 281| 0| return AbsolutePath(NSHomeDirectory()) 282| 0| } 283| 0| } 284| | 285| 0| func getDirectoryContents(_ path: AbsolutePath) throws -> [String] { 286| 0| guard let dir = SPMLibc.opendir(path.pathString) else { 287| 0| throw FileSystemError(errno: errno) 288| 0| } 289| 0| defer { _ = SPMLibc.closedir(dir) } 290| 0| 291| 0| var result: [String] = [] 292| 0| var entry = dirent() 293| 0| 294| 0| while true { 295| 0| var entryPtr: UnsafeMutablePointer? = nil 296| 0| 297| 0| let readdir_rErrno = readdir_r(dir, &entry, &entryPtr) 298| 0| if readdir_rErrno != 0 { 299| 0| throw FileSystemError(errno: readdir_rErrno) 300| 0| } 301| 0| 302| 0| // If the entry pointer is null, we reached the end of the directory. 303| 0| if entryPtr == nil { 304| 0| break 305| 0| } 306| 0| 307| 0| // Otherwise, the entry pointer should point at the storage we provided. 308| 0| assert(entryPtr == &entry) 309| 0| 310| 0| // Add the entry to the result. 311| 0| guard let name = entry.name else { 312| 0| throw FileSystemError.invalidEncoding 313| 0| } 314| 0| 315| 0| // Ignore the pseudo-entries. 316| 0| if name == "." || name == ".." { 317| 0| continue 318| 0| } 319| 0| 320| 0| result.append(name) 321| 0| } 322| 0| 323| 0| return result 324| 0| } 325| | 326| 0| func createDirectory(_ path: AbsolutePath, recursive: Bool) throws { 327| 0| // Try to create the directory. 328| 0| let result = mkdir(path.pathString, SPMLibc.S_IRWXU | SPMLibc.S_IRWXG) 329| 0| 330| 0| // If it succeeded, we are done. 331| 0| if result == 0 { return } 332| 0| 333| 0| // If the failure was because the directory exists, everything is ok. 334| 0| if errno == EEXIST && isDirectory(path) { return } 335| 0| 336| 0| // If it failed due to ENOENT (e.g., a missing parent), and we are 337| 0| // recursive, then attempt to create the parent and retry. 338| 0| if errno == ENOENT && recursive && 339| 0| path != path.parentDirectory /* FIXME: Need Path.isRoot */ { 340| 0| // Attempt to create the parent. 341| 0| try createDirectory(path.parentDirectory, recursive: true) 342| 0| 343| 0| // Re-attempt creation, non-recursively. 344| 0| try createDirectory(path, recursive: false) 345| 0| } else { 346| 0| // Otherwise, we failed due to some other error. Report it. 347| 0| throw FileSystemError(errno: errno) 348| 0| } 349| 0| } 350| | 351| 0| func readFileContents(_ path: AbsolutePath) throws -> ByteString { 352| 0| // Open the file. 353| 0| let fp = fopen(path.pathString, "rb") 354| 0| if fp == nil { 355| 0| throw FileSystemError(errno: errno) 356| 0| } 357| 0| defer { fclose(fp) } 358| 0| 359| 0| // Read the data one block at a time. 360| 0| let data = BufferedOutputByteStream() 361| 0| var tmpBuffer = [UInt8](repeating: 0, count: 1 << 12) 362| 0| while true { 363| 0| let n = fread(&tmpBuffer, 1, tmpBuffer.count, fp) 364| 0| if n < 0 { 365| 0| if errno == EINTR { continue } 366| 0| throw FileSystemError.ioError 367| 0| } 368| 0| if n == 0 { 369| 0| if ferror(fp) != 0 { 370| 0| throw FileSystemError.ioError 371| 0| } 372| 0| break 373| 0| } 374| 0| data <<< tmpBuffer[0..) throws { 428| 0| #if os(macOS) 429| 0| // Get the mode we need to set. 430| 0| guard let setMode = setmode(mode.cliArgument) else { 431| 0| throw FileSystemError(errno: errno) 432| 0| } 433| 0| defer { setMode.deallocate() } 434| 0| 435| 0| let recursive = options.contains(.recursive) 436| 0| // If we're in recursive mode, do physical walk otherwise logical. 437| 0| let ftsOptions = recursive ? FTS_PHYSICAL : FTS_LOGICAL 438| 0| 439| 0| // Get handle to the file hierarchy we want to traverse. 440| 0| let paths = CStringArray([path.pathString]) 441| 0| guard let ftsp = fts_open(paths.cArray, ftsOptions, nil) else { 442| 0| throw FileSystemError(errno: errno) 443| 0| } 444| 0| defer { fts_close(ftsp) } 445| 0| 446| 0| // Start traversing. 447| 0| while let p = fts_read(ftsp) { 448| 0| 449| 0| switch Int32(p.pointee.fts_info) { 450| 0| 451| 0| // A directory being visited in pre-order. 452| 0| case FTS_D: 453| 0| // If we're not recursing, skip the contents of the directory. 454| 0| if !recursive { 455| 0| fts_set(ftsp, p, FTS_SKIP) 456| 0| } 457| 0| continue 458| 0| 459| 0| // A directory couldn't be read. 460| 0| case FTS_DNR: 461| 0| // FIXME: We should warn here. 462| 0| break 463| 0| 464| 0| // There was an error. 465| 0| case FTS_ERR: 466| 0| fallthrough 467| 0| 468| 0| // No stat(2) information was available. 469| 0| case FTS_NS: 470| 0| // FIXME: We should warn here. 471| 0| continue 472| 0| 473| 0| // A symbolic link. 474| 0| case FTS_SL: 475| 0| fallthrough 476| 0| 477| 0| // A symbolic link with a non-existent target. 478| 0| case FTS_SLNONE: 479| 0| // The only symlinks that end up here are ones that don't point 480| 0| // to anything and ones that we found doing a physical walk. 481| 0| continue 482| 0| 483| 0| default: 484| 0| break 485| 0| } 486| 0| 487| 0| // Compute the new mode for this file. 488| 0| let currentMode = mode_t(p.pointee.fts_statp.pointee.st_mode) 489| 0| 490| 0| // Skip if only files should be changed. 491| 0| if options.contains(.onlyFiles) && (currentMode & S_IFMT) == S_IFDIR { 492| 0| continue 493| 0| } 494| 0| 495| 0| // Compute the new mode. 496| 0| let newMode = getmode(setMode, currentMode) 497| 0| if newMode == currentMode { 498| 0| continue 499| 0| } 500| 0| 501| 0| // Update the mode. 502| 0| // 503| 0| // We ignore the errors for now but we should have a way to report back. 504| 0| _ = SPMLibc.chmod(p.pointee.fts_accpath, newMode) 505| 0| } 506| 0| #endif 507| 0| // FIXME: We only support macOS right now. 508| 0| } 509| |} 510| | 511| |// FIXME: This class does not yet support concurrent mutation safely. 512| |// 513| |/// Concrete FileSystem implementation which simulates an empty disk. 514| |public class InMemoryFileSystem: FileSystem { 515| | private class Node { 516| | /// The actual node data. 517| | let contents: NodeContents 518| | 519| 0| init(_ contents: NodeContents) { 520| 0| self.contents = contents 521| 0| } 522| | 523| | /// Creates deep copy of the object. 524| 0| func copy() -> Node { 525| 0| return Node(contents.copy()) 526| 0| } 527| | } 528| | private enum NodeContents { 529| | case file(ByteString) 530| | case directory(DirectoryContents) 531| | 532| | /// Creates deep copy of the object. 533| 0| func copy() -> NodeContents { 534| 0| switch self { 535| 0| case .file(let bytes): 536| 0| return .file(bytes) 537| 0| case .directory(let contents): 538| 0| return .directory(contents.copy()) 539| 0| } 540| 0| } 541| | } 542| | private class DirectoryContents { 543| | var entries: [String: Node] 544| | 545| 0| init(entries: [String: Node] = [:]) { 546| 0| self.entries = entries 547| 0| } 548| | 549| | /// Creates deep copy of the object. 550| 0| func copy() -> DirectoryContents { 551| 0| let contents = DirectoryContents() 552| 0| for (key, node) in entries { 553| 0| contents.entries[key] = node.copy() 554| 0| } 555| 0| return contents 556| 0| } 557| | } 558| | 559| | /// The root filesytem. 560| | private var root: Node 561| | 562| 0| public init() { 563| 0| root = Node(.directory(DirectoryContents())) 564| 0| } 565| | 566| | /// Creates deep copy of the object. 567| 0| public func copy() -> InMemoryFileSystem { 568| 0| let fs = InMemoryFileSystem() 569| 0| fs.root = root.copy() 570| 0| return fs 571| 0| } 572| | 573| | /// Get the node corresponding to the given path. 574| 0| private func getNode(_ path: AbsolutePath) throws -> Node? { 575| 0| func getNodeInternal(_ path: AbsolutePath) throws -> Node? { 576| 0| // If this is the root node, return it. 577| 0| if path.isRoot { 578| 0| return root 579| 0| } 580| 0| 581| 0| // Otherwise, get the parent node. 582| 0| guard let parent = try getNodeInternal(path.parentDirectory) else { 583| 0| return nil 584| 0| } 585| 0| 586| 0| // If we didn't find a directory, this is an error. 587| 0| guard case .directory(let contents) = parent.contents else { 588| 0| throw FileSystemError.notDirectory 589| 0| } 590| 0| 591| 0| // Return the directory entry. 592| 0| return contents.entries[path.basename] 593| 0| } 594| 0| 595| 0| // Get the node that corresponds to the path. 596| 0| return try getNodeInternal(path) 597| 0| } 598| | 599| | // MARK: FileSystem Implementation 600| | 601| 0| public func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool { 602| 0| do { 603| 0| return try getNode(path) != nil 604| 0| } catch { 605| 0| return false 606| 0| } 607| 0| } 608| | 609| 0| public func isDirectory(_ path: AbsolutePath) -> Bool { 610| 0| do { 611| 0| if case .directory? = try getNode(path)?.contents { 612| 0| return true 613| 0| } 614| 0| return false 615| 0| } catch { 616| 0| return false 617| 0| } 618| 0| } 619| | 620| 0| public func isFile(_ path: AbsolutePath) -> Bool { 621| 0| do { 622| 0| if case .file? = try getNode(path)?.contents { 623| 0| return true 624| 0| } 625| 0| return false 626| 0| } catch { 627| 0| return false 628| 0| } 629| 0| } 630| | 631| 0| public func isSymlink(_ path: AbsolutePath) -> Bool { 632| 0| // FIXME: Always return false until in-memory implementation 633| 0| // gets symbolic link semantics. 634| 0| return false 635| 0| } 636| | 637| 0| public func isExecutableFile(_ path: AbsolutePath) -> Bool { 638| 0| // FIXME: Always return false until in-memory implementation 639| 0| // gets permission semantics. 640| 0| return false 641| 0| } 642| | 643| | /// Virtualized current working directory. 644| 0| public var currentWorkingDirectory: AbsolutePath? { 645| 0| return AbsolutePath("/") 646| 0| } 647| | 648| 0| public var homeDirectory: AbsolutePath { 649| 0| // FIXME: Maybe we should allow setting this when creating the fs. 650| 0| return AbsolutePath("/home/user") 651| 0| } 652| | 653| 0| public func getDirectoryContents(_ path: AbsolutePath) throws -> [String] { 654| 0| guard let node = try getNode(path) else { 655| 0| throw FileSystemError.noEntry 656| 0| } 657| 0| guard case .directory(let contents) = node.contents else { 658| 0| throw FileSystemError.notDirectory 659| 0| } 660| 0| 661| 0| // FIXME: Perhaps we should change the protocol to allow lazy behavior. 662| 0| return [String](contents.entries.keys) 663| 0| } 664| | 665| 0| public func createDirectory(_ path: AbsolutePath, recursive: Bool) throws { 666| 0| // Ignore if client passes root. 667| 0| guard !path.isRoot else { 668| 0| return 669| 0| } 670| 0| // Get the parent directory node. 671| 0| let parentPath = path.parentDirectory 672| 0| guard let parent = try getNode(parentPath) else { 673| 0| // If the parent doesn't exist, and we are recursive, then attempt 674| 0| // to create the parent and retry. 675| 0| if recursive && path != parentPath { 676| 0| // Attempt to create the parent. 677| 0| try createDirectory(parentPath, recursive: true) 678| 0| 679| 0| // Re-attempt creation, non-recursively. 680| 0| return try createDirectory(path, recursive: false) 681| 0| } else { 682| 0| // Otherwise, we failed. 683| 0| throw FileSystemError.noEntry 684| 0| } 685| 0| } 686| 0| 687| 0| // Check that the parent is a directory. 688| 0| guard case .directory(let contents) = parent.contents else { 689| 0| // The parent isn't a directory, this is an error. 690| 0| throw FileSystemError.notDirectory 691| 0| } 692| 0| 693| 0| // Check if the node already exists. 694| 0| if let node = contents.entries[path.basename] { 695| 0| // Verify it is a directory. 696| 0| guard case .directory = node.contents else { 697| 0| // The path itself isn't a directory, this is an error. 698| 0| throw FileSystemError.notDirectory 699| 0| } 700| 0| 701| 0| // We are done. 702| 0| return 703| 0| } 704| 0| 705| 0| // Otherwise, the node does not exist, create it. 706| 0| contents.entries[path.basename] = Node(.directory(DirectoryContents())) 707| 0| } 708| | 709| 0| public func readFileContents(_ path: AbsolutePath) throws -> ByteString { 710| 0| // Get the node. 711| 0| guard let node = try getNode(path) else { 712| 0| throw FileSystemError.noEntry 713| 0| } 714| 0| 715| 0| // Check that the node is a file. 716| 0| guard case .file(let contents) = node.contents else { 717| 0| // The path is a directory, this is an error. 718| 0| throw FileSystemError.isDirectory 719| 0| } 720| 0| 721| 0| // Return the file contents. 722| 0| return contents 723| 0| } 724| | 725| 0| public func writeFileContents(_ path: AbsolutePath, bytes: ByteString) throws { 726| 0| // It is an error if this is the root node. 727| 0| let parentPath = path.parentDirectory 728| 0| guard path != parentPath else { 729| 0| throw FileSystemError.isDirectory 730| 0| } 731| 0| 732| 0| // Get the parent node. 733| 0| guard let parent = try getNode(parentPath) else { 734| 0| throw FileSystemError.noEntry 735| 0| } 736| 0| 737| 0| // Check that the parent is a directory. 738| 0| guard case .directory(let contents) = parent.contents else { 739| 0| // The parent isn't a directory, this is an error. 740| 0| throw FileSystemError.notDirectory 741| 0| } 742| 0| 743| 0| // Check if the node exists. 744| 0| if let node = contents.entries[path.basename] { 745| 0| // Verify it is a file. 746| 0| guard case .file = node.contents else { 747| 0| // The path is a directory, this is an error. 748| 0| throw FileSystemError.isDirectory 749| 0| } 750| 0| } 751| 0| 752| 0| // Write the file. 753| 0| contents.entries[path.basename] = Node(.file(bytes)) 754| 0| } 755| | 756| 0| public func writeFileContents(_ path: AbsolutePath, bytes: ByteString, atomically: Bool) throws { 757| 0| // In memory file system's writeFileContents is already atomic, so ignore the parameter here 758| 0| // and just call the base implementation. 759| 0| try writeFileContents(path, bytes: bytes) 760| 0| } 761| | 762| 0| public func removeFileTree(_ path: AbsolutePath) throws { 763| 0| // Ignore root and get the parent node's content if its a directory. 764| 0| guard !path.isRoot, 765| 0| let parent = try? getNode(path.parentDirectory), 766| 0| case .directory(let contents)? = parent?.contents else { 767| 0| return 768| 0| } 769| 0| // Set it to nil to release the contents. 770| 0| contents.entries[path.basename] = nil 771| 0| } 772| | 773| 0| public func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws { 774| 0| // FIXME: We don't have these semantics in InMemoryFileSystem. 775| 0| } 776| |} 777| | 778| |/// A rerooted view on an existing FileSystem. 779| |/// 780| |/// This is a simple wrapper which creates a new FileSystem view into a subtree 781| |/// of an existing filesystem. This is useful for passing to clients which only 782| |/// need access to a subtree of the filesystem but should otherwise remain 783| |/// oblivious to its concrete location. 784| |/// 785| |/// NOTE: The rerooting done here is purely at the API level and does not 786| |/// inherently prevent access outside the rerooted path (e.g., via symlinks). It 787| |/// is designed for situations where a client is only interested in the contents 788| |/// *visible* within a subpath and is agnostic to the actual location of those 789| |/// contents. 790| |public class RerootedFileSystemView: FileSystem { 791| | /// The underlying file system. 792| | private var underlyingFileSystem: FileSystem 793| | 794| | /// The root path within the containing file system. 795| | private let root: AbsolutePath 796| | 797| 0| public init(_ underlyingFileSystem: FileSystem, rootedAt root: AbsolutePath) { 798| 0| self.underlyingFileSystem = underlyingFileSystem 799| 0| self.root = root 800| 0| } 801| | 802| | /// Adjust the input path for the underlying file system. 803| 0| private func formUnderlyingPath(_ path: AbsolutePath) -> AbsolutePath { 804| 0| if path == AbsolutePath.root { 805| 0| return root 806| 0| } else { 807| 0| // FIXME: Optimize? 808| 0| return root.appending(RelativePath(String(path.pathString.dropFirst(1)))) 809| 0| } 810| 0| } 811| | 812| | // MARK: FileSystem Implementation 813| | 814| 0| public func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool { 815| 0| return underlyingFileSystem.exists(formUnderlyingPath(path), followSymlink: followSymlink) 816| 0| } 817| | 818| 0| public func isDirectory(_ path: AbsolutePath) -> Bool { 819| 0| return underlyingFileSystem.isDirectory(formUnderlyingPath(path)) 820| 0| } 821| | 822| 0| public func isFile(_ path: AbsolutePath) -> Bool { 823| 0| return underlyingFileSystem.isFile(formUnderlyingPath(path)) 824| 0| } 825| | 826| 0| public func isSymlink(_ path: AbsolutePath) -> Bool { 827| 0| return underlyingFileSystem.isSymlink(formUnderlyingPath(path)) 828| 0| } 829| | 830| 0| public func isExecutableFile(_ path: AbsolutePath) -> Bool { 831| 0| return underlyingFileSystem.isExecutableFile(formUnderlyingPath(path)) 832| 0| } 833| | 834| | /// Virtualized current working directory. 835| 0| public var currentWorkingDirectory: AbsolutePath? { 836| 0| return AbsolutePath("/") 837| 0| } 838| | 839| 0| public var homeDirectory: AbsolutePath { 840| 0| fatalError("homeDirectory on RerootedFileSystemView is not supported.") 841| 0| } 842| | 843| 0| public func getDirectoryContents(_ path: AbsolutePath) throws -> [String] { 844| 0| return try underlyingFileSystem.getDirectoryContents(formUnderlyingPath(path)) 845| 0| } 846| | 847| 0| public func createDirectory(_ path: AbsolutePath, recursive: Bool) throws { 848| 0| let path = formUnderlyingPath(path) 849| 0| return try underlyingFileSystem.createDirectory(path, recursive: recursive) 850| 0| } 851| | 852| 0| public func readFileContents(_ path: AbsolutePath) throws -> ByteString { 853| 0| return try underlyingFileSystem.readFileContents(formUnderlyingPath(path)) 854| 0| } 855| | 856| 0| public func writeFileContents(_ path: AbsolutePath, bytes: ByteString) throws { 857| 0| let path = formUnderlyingPath(path) 858| 0| return try underlyingFileSystem.writeFileContents(path, bytes: bytes) 859| 0| } 860| | 861| 0| public func removeFileTree(_ path: AbsolutePath) throws { 862| 0| try underlyingFileSystem.removeFileTree(path) 863| 0| } 864| | 865| 0| public func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws { 866| 0| try underlyingFileSystem.chmod(mode, path: path, options: options) 867| 0| } 868| |} 869| | 870| |/// Public access to the local FS proxy. 871| |public var localFileSystem: FileSystem = LocalFileSystem() 872| | 873| |extension FileSystem { 874| | /// Print the filesystem tree of the given path. 875| | /// 876| | /// For debugging only. 877| 0| public func dumpTree(at path: AbsolutePath = .root) { 878| 0| print(".") 879| 0| do { 880| 0| try recurse(fs: self, path: path) 881| 0| } catch { 882| 0| print("\(error)") 883| 0| } 884| 0| } 885| | 886| | /// Helper method to recurse and print the tree. 887| 0| private func recurse(fs: FileSystem, path: AbsolutePath, prefix: String = "") throws { 888| 0| let contents = try fs.getDirectoryContents(path) 889| 0| 890| 0| for (idx, entry) in contents.enumerated() { 891| 0| let isLast = idx == contents.count - 1 892| 0| let line = prefix + (isLast ? "└── " : "├── ") + entry 893| 0| print(line) 894| 0| 895| 0| let entryPath = path.appending(component: entry) 896| 0| if fs.isDirectory(entryPath) { 897| 0| let childPrefix = prefix + (isLast ? " " : "│ ") 898| 0| try recurse(fs: fs, path: entryPath, prefix: String(childPrefix)) 899| 0| } 900| 0| } 901| 0| } 902| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/GraphAlgorithms.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |public enum GraphError: Swift.Error { 12| | /// A cycle was detected in the input. 13| | case unexpectedCycle 14| |} 15| | 16| |/// Compute the transitive closure of an input node set. 17| |/// 18| |/// - Note: The relation is *not* assumed to be reflexive; i.e. the result will 19| |/// not automatically include `nodes` unless present in the relation defined by 20| |/// `successors`. 21| |public func transitiveClosure( 22| | _ nodes: [T], successors: (T) throws -> [T] 23| 0|) rethrows -> Set { 24| 0| var result = Set() 25| 0| 26| 0| // The queue of items to recursively visit. 27| 0| // 28| 0| // We add items post-collation to avoid unnecessary queue operations. 29| 0| var queue = nodes 30| 0| while let node = queue.popLast() { 31| 0| for succ in try successors(node) { 32| 0| if result.insert(succ).inserted { 33| 0| queue.append(succ) 34| 0| } 35| 0| } 36| 0| } 37| 0| 38| 0| return result 39| 0|} 40| | 41| |/// Perform a topological sort of an graph. 42| |/// 43| |/// This function is optimized for use cases where cycles are unexpected, and 44| |/// does not attempt to retain information on the exact nodes in the cycle. 45| |/// 46| |/// - Parameters: 47| |/// - nodes: The list of input nodes to sort. 48| |/// - successors: A closure for fetching the successors of a particular node. 49| |/// 50| |/// - Returns: A list of the transitive closure of nodes reachable from the 51| |/// inputs, ordered such that every node in the list follows all of its 52| |/// predecessors. 53| |/// 54| |/// - Throws: GraphError.unexpectedCycle 55| |/// 56| |/// - Complexity: O(v + e) where (v, e) are the number of vertices and edges 57| |/// reachable from the input nodes via the relation. 58| |public func topologicalSort( 59| | _ nodes: [T], successors: (T) throws -> [T] 60| 0|) throws -> [T] { 61| 0| // Implements a topological sort via recursion and reverse postorder DFS. 62| 0| func visit(_ node: T, 63| 0| _ stack: inout OrderedSet, _ visited: inout Set, _ result: inout [T], 64| 0| _ successors: (T) throws -> [T]) throws { 65| 0| // Mark this node as visited -- we are done if it already was. 66| 0| if !visited.insert(node).inserted { 67| 0| return 68| 0| } 69| 0| 70| 0| // Otherwise, visit each adjacent node. 71| 0| for succ in try successors(node) { 72| 0| guard stack.append(succ) else { 73| 0| // If the successor is already in this current stack, we have found a cycle. 74| 0| // 75| 0| // FIXME: We could easily include information on the cycle we found here. 76| 0| throw GraphError.unexpectedCycle 77| 0| } 78| 0| try visit(succ, &stack, &visited, &result, successors) 79| 0| let popped = stack.removeLast() 80| 0| assert(popped == succ) 81| 0| } 82| 0| 83| 0| // Add to the result. 84| 0| result.append(node) 85| 0| } 86| 0| 87| 0| // FIXME: This should use a stack not recursion. 88| 0| var visited = Set() 89| 0| var result = [T]() 90| 0| var stack = OrderedSet() 91| 0| for node in nodes { 92| 0| precondition(stack.isEmpty) 93| 0| stack.append(node) 94| 0| try visit(node, &stack, &visited, &result, successors) 95| 0| let popped = stack.removeLast() 96| 0| assert(popped == node) 97| 0| } 98| 0| 99| 0| return result.reversed() 100| 0|} 101| | 102| |/// Finds the first cycle encountered in a graph. 103| |/// 104| |/// This method uses DFS to look for a cycle and immediately returns when a 105| |/// cycle is encounted. 106| |/// 107| |/// - Parameters: 108| |/// - nodes: The list of input nodes to sort. 109| |/// - successors: A closure for fetching the successors of a particular node. 110| |/// 111| |/// - Returns: nil if a cycle is not found or a tuple with the path to the start of the cycle and the cycle itself. 112| |public func findCycle( 113| | _ nodes: [T], 114| | successors: (T) throws -> [T] 115| 0|) rethrows -> (path: [T], cycle: [T])? { 116| 0| // Ordered set to hold the current traversed path. 117| 0| var path = OrderedSet() 118| 0| 119| 0| // Function to visit nodes recursively. 120| 0| // FIXME: Convert to stack. 121| 0| func visit(_ node: T, _ successors: (T) throws -> [T]) rethrows -> (path: [T], cycle: [T])? { 122| 0| // If this node is already in the current path then we have found a cycle. 123| 0| if !path.append(node) { 124| 0| let index = path.index(of: node)! 125| 0| return (Array(path[path.startIndex..) 49| |} 50| | 51| |/// A JSON representation of an element. 52| |public protocol JSONSerializable { 53| | 54| | /// Return a JSON representation. 55| | func toJSON() -> JSON 56| |} 57| | 58| |extension JSON: CustomStringConvertible { 59| 0| public var description: Swift.String { 60| 0| switch self { 61| 0| case .null: return "null" 62| 0| case .bool(let value): return value.description 63| 0| case .int(let value): return value.description 64| 0| case .double(let value): return value.description 65| 0| case .string(let value): return value.debugDescription 66| 0| case .array(let values): return values.description 67| 0| case .dictionary(let values): return values.description 68| 0| case .orderedDictionary(let values): return values.description 69| 0| } 70| 0| } 71| |} 72| | 73| |/// Equatable conformance. 74| |extension JSON: Equatable { 75| 0| public static func == (lhs: JSON, rhs: JSON) -> Bool { 76| 0| switch (lhs, rhs) { 77| 0| case (.null, .null): return true 78| 0| case (.null, _): return false 79| 0| case (.bool(let a), .bool(let b)): return a == b 80| 0| case (.bool, _): return false 81| 0| case (.int(let a), .int(let b)): return a == b 82| 0| case (.int, _): return false 83| 0| case (.double(let a), .double(let b)): return a == b 84| 0| case (.double, _): return false 85| 0| case (.string(let a), .string(let b)): return a == b 86| 0| case (.string, _): return false 87| 0| case (.array(let a), .array(let b)): return a == b 88| 0| case (.array, _): return false 89| 0| case (.dictionary(let a), .dictionary(let b)): return a == b 90| 0| case (.dictionary, _): return false 91| 0| case (.orderedDictionary(let a), .orderedDictionary(let b)): return a == b 92| 0| case (.orderedDictionary, _): return false 93| 0| } 94| 0| } 95| |} 96| | 97| |// MARK: JSON Encoding 98| | 99| |extension JSON { 100| | /// Encode a JSON item into a string of bytes. 101| 0| public func toBytes(prettyPrint: Bool = false) -> ByteString { 102| 0| let stream = BufferedOutputByteStream() 103| 0| write(to: stream, indent: prettyPrint ? 0 : nil) 104| 0| if prettyPrint { 105| 0| stream.write("\n") 106| 0| } 107| 0| return stream.bytes 108| 0| } 109| | 110| | /// Encode a JSON item into a JSON string 111| 0| public func toString(prettyPrint: Bool = false) -> String { 112| 0| return toBytes(prettyPrint: prettyPrint).description 113| 0| } 114| |} 115| | 116| |/// Support writing to a byte stream. 117| |extension JSON: ByteStreamable { 118| 0| public func write(to stream: OutputByteStream) { 119| 0| write(to: stream, indent: nil) 120| 0| } 121| | 122| 0| public func write(to stream: OutputByteStream, indent: Int?) { 123| 0| func indentStreamable(offset: Int? = nil) -> ByteStreamable { 124| 0| return Format.asRepeating(string: " ", count: indent.flatMap({ $0 + (offset ?? 0) }) ?? 0) 125| 0| } 126| 0| let shouldIndent = indent != nil 127| 0| switch self { 128| 0| case .null: 129| 0| stream <<< "null" 130| 0| case .bool(let value): 131| 0| stream <<< Format.asJSON(value) 132| 0| case .int(let value): 133| 0| stream <<< Format.asJSON(value) 134| 0| case .double(let value): 135| 0| // FIXME: What happens for NaN, etc.? 136| 0| stream <<< Format.asJSON(value) 137| 0| case .string(let value): 138| 0| stream <<< Format.asJSON(value) 139| 0| case .array(let contents): 140| 0| stream <<< "[" <<< (shouldIndent ? "\n" : "") 141| 0| for (i, item) in contents.enumerated() { 142| 0| if i != 0 { stream <<< "," <<< (shouldIndent ? "\n" : " ") } 143| 0| stream <<< indentStreamable(offset: 2) 144| 0| item.write(to: stream, indent: indent.flatMap({ $0 + 2 })) 145| 0| } 146| 0| stream <<< (shouldIndent ? "\n" : "") <<< indentStreamable() <<< "]" 147| 0| case .dictionary(let contents): 148| 0| // We always output in a deterministic order. 149| 0| stream <<< "{" <<< (shouldIndent ? "\n" : "") 150| 0| for (i, key) in contents.keys.sorted().enumerated() { 151| 0| if i != 0 { stream <<< "," <<< (shouldIndent ? "\n" : " ") } 152| 0| stream <<< indentStreamable(offset: 2) <<< Format.asJSON(key) <<< ": " 153| 0| contents[key]!.write(to: stream, indent: indent.flatMap({ $0 + 2 })) 154| 0| } 155| 0| stream <<< (shouldIndent ? "\n" : "") <<< indentStreamable() <<< "}" 156| 0| case .orderedDictionary(let contents): 157| 0| stream <<< "{" <<< (shouldIndent ? "\n" : "") 158| 0| for (i, item) in contents.enumerated() { 159| 0| if i != 0 { stream <<< "," <<< (shouldIndent ? "\n" : " ") } 160| 0| stream <<< indentStreamable(offset: 2) <<< Format.asJSON(item.key) <<< ": " 161| 0| item.value.write(to: stream, indent: indent.flatMap({ $0 + 2 })) 162| 0| } 163| 0| stream <<< (shouldIndent ? "\n" : "") <<< indentStreamable() <<< "}" 164| 0| } 165| 0| } 166| |} 167| | 168| |// MARK: JSON Decoding 169| | 170| |import Foundation 171| | 172| |enum JSONDecodingError: Swift.Error { 173| | /// The input byte string is malformed. 174| | case malformed 175| |} 176| | 177| |// NOTE: This implementation is carefully crafted to work correctly on both 178| |// Linux and OS X while still compiling for both. Thus, the implementation takes 179| |// Any even though it could take AnyObject on OS X, and it uses converts to 180| |// direct Swift types (for Linux) even though those don't apply on OS X. 181| |// 182| |// This allows the code to be portable, and expose a portable API, but it is not 183| |// very efficient. 184| | 185| |private let nsBooleanType = type(of: NSNumber(value: false)) 186| |extension JSON { 187| 0| private static func convertToJSON(_ object: Any) -> JSON { 188| 0| switch object { 189| 0| case is NSNull: 190| 0| return .null 191| 0| case let value as String: 192| 0| return .string(value) 193| 0| 194| 0| case let value as NSNumber: 195| 0| // Check if this is a boolean. 196| 0| // 197| 0| // FIXME: This is all rather unfortunate and expensive. 198| 0| if type(of: value) === nsBooleanType { 199| 0| return .bool(value != 0) 200| 0| } 201| 0| 202| 0| // Check if this is an exact integer. 203| 0| // 204| 0| // FIXME: This is highly questionable. Aside from the performance of 205| 0| // decoding in this fashion, it means clients which truly have 206| 0| // arrays of real numbers will need to be prepared to see either an 207| 0| // .int or a .double. However, for our specific use case we usually 208| 0| // want to get integers out of JSON, and so it seems an ok tradeoff 209| 0| // versus forcing all clients to cast out of a double. 210| 0| let asInt = value.intValue 211| 0| if NSNumber(value: asInt) == value { 212| 0| return .int(asInt) 213| 0| } 214| 0| 215| 0| // Otherwise, we have a floating point number. 216| 0| return .double(value.doubleValue) 217| 0| case let value as NSArray: 218| 0| return .array(value.map(convertToJSON)) 219| 0| case let value as NSDictionary: 220| 0| var result = [String: JSON]() 221| 0| for (key, val) in value { 222| 0| result[key as! String] = convertToJSON(val) 223| 0| } 224| 0| return .dictionary(result) 225| 0| 226| 0| // On Linux, the JSON deserialization handles this. 227| 0| case let asBool as Bool: // This is true on Linux. 228| 0| return .bool(asBool) 229| 0| case let asInt as Int: // This is true on Linux. 230| 0| return .int(asInt) 231| 0| case let asDouble as Double: // This is true on Linux. 232| 0| return .double(asDouble) 233| 0| case let value as [Any]: 234| 0| return .array(value.map(convertToJSON)) 235| 0| case let value as [String: Any]: 236| 0| var result = [String: JSON]() 237| 0| for (key, val) in value { 238| 0| result[key] = convertToJSON(val) 239| 0| } 240| 0| return .dictionary(result) 241| 0| 242| 0| default: 243| 0| fatalError("unexpected object: \(object) \(type(of: object))") 244| 0| } 245| 0| } 246| | 247| | /// Load a JSON item from a Data object. 248| 0| public init(data: Data) throws { 249| 0| do { 250| 0| let result = try JSONSerialization.jsonObject(with: data, options: [.allowFragments]) 251| 0| 252| 0| // Convert to a native representation. 253| 0| // 254| 0| // FIXME: This is inefficient; eventually, we want a way to do the 255| 0| // loading and not need to copy / traverse all of the data multiple 256| 0| // times. 257| 0| self = JSON.convertToJSON(result) 258| 0| } catch { 259| 0| throw JSONDecodingError.malformed 260| 0| } 261| 0| } 262| | 263| | /// Load a JSON item from a byte string. 264| 0| public init(bytes: ByteString) throws { 265| 0| try self.init(data: Data(bytes: bytes.contents)) 266| 0| } 267| | 268| | /// Convenience initalizer for UTF8 encoded strings. 269| | /// 270| | /// - Throws: JSONDecodingError 271| 0| public init(string: String) throws { 272| 0| let bytes = ByteString(encodingAsUTF8: string) 273| 0| try self.init(bytes: bytes) 274| 0| } 275| |} 276| | 277| |// MARK: - JSONSerializable helpers. 278| | 279| |extension JSON { 280| 0| public init(_ dict: [String: JSONSerializable]) { 281| 0| self = .dictionary(Dictionary(items: dict.map({ ($0.0, $0.1.toJSON()) }))) 282| 0| } 283| |} 284| | 285| |extension Int: JSONSerializable { 286| 0| public func toJSON() -> JSON { 287| 0| return .int(self) 288| 0| } 289| |} 290| | 291| |extension Double: JSONSerializable { 292| 0| public func toJSON() -> JSON { 293| 0| return .double(self) 294| 0| } 295| |} 296| | 297| |extension String: JSONSerializable { 298| 0| public func toJSON() -> JSON { 299| 0| return .string(self) 300| 0| } 301| |} 302| | 303| |extension Bool: JSONSerializable { 304| 0| public func toJSON() -> JSON { 305| 0| return .bool(self) 306| 0| } 307| |} 308| | 309| |extension AbsolutePath: JSONSerializable { 310| 0| public func toJSON() -> JSON { 311| 0| return .string(pathString) 312| 0| } 313| |} 314| | 315| |extension RelativePath: JSONSerializable { 316| 0| public func toJSON() -> JSON { 317| 0| return .string(pathString) 318| 0| } 319| |} 320| | 321| |extension Array: JSONSerializable where Element: JSONSerializable { 322| 0| public func toJSON() -> JSON { 323| 0| return .array(self.map({ $0.toJSON() })) 324| 0| } 325| |} 326| | 327| |extension Dictionary: JSONSerializable where Key == String, Value: JSONSerializable { 328| 0| public func toJSON() -> JSON { 329| 0| return .dictionary(self.mapValues({ $0.toJSON() })) 330| 0| } 331| |} 332| | 333| |extension Optional where Wrapped: JSONSerializable { 334| 0| public func toJSON() -> JSON { 335| 0| switch self { 336| 0| case .some(let wrapped): return wrapped.toJSON() 337| 0| case .none: return .null 338| 0| } 339| 0| } 340| |} 341| | 342| |extension Sequence where Iterator.Element: JSONSerializable { 343| 0| public func toJSON() -> JSON { 344| 0| return .array(map({ $0.toJSON() })) 345| 0| } 346| |} 347| | 348| |extension JSON: JSONSerializable { 349| 0| public func toJSON() -> JSON { 350| 0| return self 351| 0| } 352| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/JSONMapper.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A type which can be mapped from JSON. 12| |public protocol JSONMappable { 13| | /// Create an object from given JSON. 14| | init(json: JSON) throws 15| |} 16| | 17| |extension JSON { 18| | 19| | /// Describes an error occurred during JSON mapping. 20| | public enum MapError: Error { 21| | /// The key is missing in JSON. 22| | case missingKey(String) 23| | 24| | /// Got a different type than expected. 25| | case typeMismatch(key: String, expected: Any.Type, json: JSON) 26| | 27| | /// A custom error. Clients can use this in their mapping method. 28| | case custom(key: String?, message: String) 29| | } 30| | 31| | /// Returns a JSON mappable object from a given key. 32| 0| public func get(_ key: String) throws -> T { 33| 0| let object: JSON = try get(key) 34| 0| return try T(json: object) 35| 0| } 36| | 37| 0| public func get(_ type: T.Type, forKey key: String) throws -> T { 38| 0| let object: JSON = try get(key) 39| 0| return try T(json: object) 40| 0| } 41| | 42| | /// Returns an optional JSON mappable object from a given key. 43| 0| public func get(_ key: String) -> T? { 44| 0| return try? get(key) 45| 0| } 46| | 47| | /// Returns a JSON mappable array from a given key. 48| 0| public func get(_ key: String) throws -> [T] { 49| 0| let array: [JSON] = try get(key) 50| 0| return try array.map(T.init(json:)) 51| 0| } 52| | 53| 0| public func get(_ type: [T].Type, forKey key: String) throws -> [T] { 54| 0| let array: [JSON] = try get(key) 55| 0| return try array.map(T.init(json:)) 56| 0| } 57| | 58| | /// Returns a JSON mappable dictionary from a given key. 59| 0| public func get(_ key: String) throws -> [String: T] { 60| 0| let object: JSON = try get(key) 61| 0| guard case .dictionary(let value) = object else { 62| 0| throw MapError.typeMismatch( 63| 0| key: key, expected: Dictionary.self, json: object) 64| 0| } 65| 0| return try Dictionary(items: value.map({ ($0.0, try T.init(json: $0.1)) })) 66| 0| } 67| | 68| | /// Returns a JSON mappable dictionary from a given key. 69| 0| public func get(_ key: String) throws -> [String: JSON] { 70| 0| let object: JSON = try get(key) 71| 0| guard case .dictionary(let value) = object else { 72| 0| throw MapError.typeMismatch( 73| 0| key: key, expected: Dictionary.self, json: object) 74| 0| } 75| 0| return value 76| 0| } 77| | 78| | /// Returns JSON entry in the dictionary from a given key. 79| 0| public func get(_ key: String) throws -> JSON { 80| 0| guard case .dictionary(let dict) = self else { 81| 0| throw MapError.typeMismatch( 82| 0| key: key, expected: Dictionary.self, json: self) 83| 0| } 84| 0| guard let object = dict[key] else { 85| 0| throw MapError.missingKey(key) 86| 0| } 87| 0| return object 88| 0| } 89| | 90| 0| public func getJSON(_ key: String) throws -> JSON { 91| 0| return try get(key) 92| 0| } 93| | 94| | /// Returns JSON array entry in the dictionary from a given key. 95| 0| public func get(_ key: String) throws -> [JSON] { 96| 0| let object: JSON = try get(key) 97| 0| guard case .array(let array) = object else { 98| 0| throw MapError.typeMismatch(key: key, expected: Array.self, json: object) 99| 0| } 100| 0| return array 101| 0| } 102| | 103| 0| public func getArray(_ key: String) throws -> [JSON] { 104| 0| return try get(key) 105| 0| } 106| | 107| 0| public func getArray() throws -> [JSON] { 108| 0| guard case .array(let array) = self else { 109| 0| throw MapError.typeMismatch(key: "", expected: Array.self, json: self) 110| 0| } 111| 0| return array 112| 0| } 113| |} 114| | 115| |// MARK: - Conformance for basic JSON types. 116| | 117| |extension Int: JSONMappable { 118| 0| public init(json: JSON) throws { 119| 0| guard case .int(let int) = json else { 120| 0| throw JSON.MapError.custom(key: nil, message: "expected int, got \(json)") 121| 0| } 122| 0| self = int 123| 0| } 124| |} 125| | 126| |extension String: JSONMappable { 127| 0| public init(json: JSON) throws { 128| 0| guard case .string(let str) = json else { 129| 0| throw JSON.MapError.custom(key: nil, message: "expected string, got \(json)") 130| 0| } 131| 0| self = str 132| 0| } 133| |} 134| | 135| |extension Bool: JSONMappable { 136| 0| public init(json: JSON) throws { 137| 0| guard case .bool(let bool) = json else { 138| 0| throw JSON.MapError.custom(key: nil, message: "expected bool, got \(json)") 139| 0| } 140| 0| self = bool 141| 0| } 142| |} 143| | 144| |extension Double: JSONMappable { 145| 0| public init(json: JSON) throws { 146| 0| guard case .double(let double) = json else { 147| 0| throw JSON.MapError.custom(key: nil, message: "expected double, got \(json)") 148| 0| } 149| 0| self = double 150| 0| } 151| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/KeyedPair.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Wrapper for exposing an item indexed by some other key type. 12| |/// 13| |/// This is intended to be used when an algorithm wants to temporarily expose 14| |/// some object as hashable based on a derived property (most commonly some 15| |/// member of the object itself), without erasing the underlying object. 16| |/// 17| |/// Example: 18| |/// 19| |/// struct Airport { 20| |/// // The name of the airport. 21| |/// let name: String 22| |/// // The names of destination airports for outgoing flights. 23| |/// let destinations: [String] 24| |/// } 25| |/// 26| |/// func whereCanIGo(from here: Airport) -> [Airport] { 27| |/// let closure = transitiveClosure([KeyedPair(airport, key: airport.name]) { 28| |/// return $0.destinations.map({ KeyedPair($0, key: $0.name) }) 29| |/// } 30| |/// return closure.map({ $0.item }) 31| |/// } 32| |public struct KeyedPair: Hashable { 33| | /// The wrapped item. 34| | public let item: T 35| | 36| | /// The exposed key. 37| | public let key: K 38| | 39| | /// Create a new hashable pair for `item` indexed by `key`. 40| 0| public init(_ item: T, key: K) { 41| 0| self.item = item 42| 0| self.key = key 43| 0| } 44| | 45| 0| public func hash(into hasher: inout Hasher) { 46| 0| hasher.combine(key) 47| 0| } 48| |} 49| 0|public func ==(lhs: KeyedPair, rhs: KeyedPair) -> Bool { 50| 0| return lhs.key == rhs.key 51| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/LazyCache.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |// FIXME: This wrapper could benefit from local static variables, in which case 12| |// we could embed the cache object inside the accessor. 13| |// 14| |/// Thread-safe lazily cached methods. 15| |/// 16| |/// The `lazy` annotation in Swift does not result in a thread-safe accessor, 17| |/// which can make it an easy source of hard-to-find concurrency races. This 18| |/// class defines a wrapper designed to be used as an alternative for 19| |/// `lazy`. Example usage: 20| |/// 21| |/// ``` 22| |/// class Foo { 23| |/// var bar: Int { return barCache.getValue(self) } 24| |/// var barCache = LazyCache(someExpensiveMethod) 25| |/// 26| |/// func someExpensiveMethod() -> Int { ... } 27| |/// } 28| |/// ``` 29| |/// 30| |/// See: https://bugs.swift.org/browse/SR-1042 31| |public struct LazyCache { 32| | // FIXME: It would be nice to avoid a per-instance lock, but this type isn't 33| | // intended for creating large numbers of instances of. We also really want 34| | // a reader-writer lock or something similar here. 35| | private var lock = Lock() 36| | let body: (Class) -> () -> T 37| | var cachedValue: T? 38| | 39| | /// Create a lazy cache from a method value. 40| 0| public init(_ body: @escaping (Class) -> () -> T) { 41| 0| self.body = body 42| 0| } 43| | 44| | /// Get the cached value, computing it if necessary. 45| 0| public mutating func getValue(_ instance: Class) -> T { 46| 0| // FIXME: This is unfortunate, see note w.r.t. the lock. 47| 0| return lock.withLock { 48| 0| if let value = cachedValue { 49| 0| return value 50| 0| } else { 51| 0| let result = body(instance)() 52| 0| cachedValue = result 53| 0| return result 54| 0| } 55| 0| } 56| 0| } 57| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Lock.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| |import SPMLibc 13| | 14| |/// A simple lock wrapper. 15| |public struct Lock { 16| | private let _lock = NSLock() 17| | 18| | /// Create a new lock. 19| 0| public init() { 20| 0| } 21| | 22| | /// Execute the given block while holding the lock. 23| 0| public func withLock (_ body: () throws -> T) rethrows -> T { 24| 0| _lock.lock() 25| 0| defer { _lock.unlock() } 26| 0| return try body() 27| 0| } 28| |} 29| | 30| |enum ProcessLockError: Swift.Error { 31| | case unableToAquireLock(errno: Int32) 32| |} 33| | 34| |/// Provides functionality to aquire a lock on a file via POSIX's flock() method. 35| |/// It can be used for things like serializing concurrent mutations on a shared resource 36| |/// by mutiple instances of a process. The `FileLock` is not thread-safe. 37| |public final class FileLock { 38| | /// File descriptor to the lock file. 39| | private var fd: CInt? 40| | 41| | /// Path to the lock file. 42| | private let lockFile: AbsolutePath 43| | 44| | /// Create an instance of process lock with a name and the path where 45| | /// the lock file can be created. 46| | /// 47| | /// Note: The cache path should be a valid directory. 48| 0| public init(name: String, cachePath: AbsolutePath) { 49| 0| self.lockFile = cachePath.appending(component: name + ".lock") 50| 0| } 51| | 52| | /// Try to aquire a lock. This method will block until lock the already aquired by other process. 53| | /// 54| | /// Note: This method can throw if underlying POSIX methods fail. 55| 0| public func lock() throws { 56| 0| // Open the lock file. 57| 0| if fd == nil { 58| 0| let fd = SPMLibc.open(lockFile.pathString, O_WRONLY | O_CREAT | O_CLOEXEC, 0o666) 59| 0| if fd == -1 { 60| 0| throw FileSystemError(errno: errno) 61| 0| } 62| 0| self.fd = fd 63| 0| } 64| 0| // Aquire lock on the file. 65| 0| while true { 66| 0| if flock(fd!, LOCK_EX) == 0 { 67| 0| break 68| 0| } 69| 0| // Retry if interrupted. 70| 0| if errno == EINTR { continue } 71| 0| throw ProcessLockError.unableToAquireLock(errno: errno) 72| 0| } 73| 0| } 74| | 75| | /// Unlock the held lock. 76| 0| public func unlock() { 77| 0| guard let fd = fd else { return } 78| 0| flock(fd, LOCK_UN) 79| 0| } 80| | 81| 0| deinit { 82| 0| guard let fd = fd else { return } 83| 0| close(fd) 84| 0| } 85| | 86| | /// Execute the given block while holding the lock. 87| 0| public func withLock(_ body: () throws -> T) throws -> T { 88| 0| try lock() 89| 0| defer { unlock() } 90| 0| return try body() 91| 0| } 92| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/ObjectIdentifierProtocol.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A protocol which implements Hashable protocol using ObjectIdentifier. 12| |/// 13| |/// Classes can conform to this protocol to auto-conform to Hashable and Equatable. 14| |public protocol ObjectIdentifierProtocol: class, Hashable {} 15| | 16| |extension ObjectIdentifierProtocol { 17| 0| public func hash(into hasher: inout Hasher) { 18| 0| hasher.combine(ObjectIdentifier(self)) 19| 0| } 20| | 21| 0| public static func == (lhs: Self, rhs: Self) -> Bool { 22| 0| return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) 23| 0| } 24| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/OrderedDictionary.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A generic collection to store key-value pairs in the order they were inserted in. 12| |/// 13| |/// This is modelled after the stdlib's Dictionary. 14| |public struct OrderedDictionary { 15| | 16| | /// The element type of a dictionary: a tuple containing an individual 17| | /// key-value pair. 18| | public typealias Element = (key: Key, value: Value) 19| | 20| | /// The underlying storage for the OrderedDictionary. 21| | fileprivate var array: [Key] 22| | fileprivate var dict: [Key: Value] 23| | 24| | /// Create an empty OrderedDictionary object. 25| 0| public init() { 26| 0| self.array = [] 27| 0| self.dict = [:] 28| 0| } 29| | 30| | /// Accesses the value associated with the given key for reading and writing. 31| | /// 32| | /// This *key-based* subscript returns the value for the given key if the key 33| | /// is found in the dictionary, or `nil` if the key is not found. 34| | public subscript(key: Key) -> Value? { 35| 0| get { 36| 0| return dict[key] 37| 0| } 38| 0| set { 39| 0| if let newValue = newValue { 40| 0| updateValue(newValue, forKey: key) 41| 0| } else { 42| 0| removeValue(forKey: key) 43| 0| } 44| 0| } 45| | } 46| | 47| | /// Updates the value stored in the dictionary for the given key, or adds a 48| | /// new key-value pair if the key does not exist. 49| | /// 50| | /// Use this method instead of key-based subscripting when you need to know 51| | /// whether the new value supplants the value of an existing key. If the 52| | /// value of an existing key is updated, `updateValue(_:forKey:)` returns 53| | /// the original value. 54| | @discardableResult 55| 0| public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { 56| 0| // If there is already a value for this key, replace and return the old value. 57| 0| if let oldValue = dict[key] { 58| 0| dict[key] = value 59| 0| return oldValue 60| 0| } 61| 0| 62| 0| // Otherwise, create a new entry. 63| 0| dict[key] = value 64| 0| array.append(key) 65| 0| return nil 66| 0| } 67| | 68| | /// Removes the given key and its associated value from the dictionary. 69| | /// 70| | /// If the key is found in the dictionary, this method returns the key's 71| | /// associated value. 72| | @discardableResult 73| 0| public mutating func removeValue(forKey key: Key) -> Value? { 74| 0| guard let value = dict[key] else { 75| 0| return nil 76| 0| } 77| 0| dict[key] = nil 78| 0| array.remove(at: array.index(of: key)!) 79| 0| return value 80| 0| } 81| |} 82| | 83| |extension OrderedDictionary: ExpressibleByDictionaryLiteral { 84| 0| public init(dictionaryLiteral elements: (Key, Value)...) { 85| 0| self.init() 86| 0| for element in elements { 87| 0| updateValue(element.1, forKey: element.0) 88| 0| } 89| 0| } 90| |} 91| | 92| |extension OrderedDictionary: CustomStringConvertible { 93| 0| public var description: String { 94| 0| var string = "[" 95| 0| for (idx, key) in array.enumerated() { 96| 0| string += "\(key): \(dict[key]!)" 97| 0| if idx != array.count - 1 { 98| 0| string += ", " 99| 0| } 100| 0| } 101| 0| string += "]" 102| 0| return string 103| 0| } 104| |} 105| | 106| |extension OrderedDictionary: RandomAccessCollection { 107| 0| public var startIndex: Int { return array.startIndex } 108| 0| public var endIndex: Int { return array.endIndex } 109| 0| public subscript(index: Int) -> Element { 110| 0| let key = array[index] 111| 0| let value = dict[key]! 112| 0| return (key, value) 113| 0| } 114| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/OrderedSet.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// An ordered set is an ordered collection of instances of `Element` in which 12| |/// uniqueness of the objects is guaranteed. 13| |public struct OrderedSet: Equatable, Collection { 14| | public typealias Element = E 15| | public typealias Index = Int 16| | 17| | #if swift(>=4.1.50) 18| | public typealias Indices = Range 19| | #else 20| | public typealias Indices = CountableRange 21| | #endif 22| | 23| | private var array: [Element] 24| | private var set: Set 25| | 26| | /// Creates an empty ordered set. 27| 0| public init() { 28| 0| self.array = [] 29| 0| self.set = Set() 30| 0| } 31| | 32| | /// Creates an ordered set with the contents of `array`. 33| | /// 34| | /// If an element occurs more than once in `element`, only the first one 35| | /// will be included. 36| 0| public init(_ array: [Element]) { 37| 0| self.init() 38| 0| for element in array { 39| 0| append(element) 40| 0| } 41| 0| } 42| | 43| | // MARK: Working with an ordered set 44| | 45| | /// The number of elements the ordered set stores. 46| 0| public var count: Int { return array.count } 47| | 48| | /// Returns `true` if the set is empty. 49| 0| public var isEmpty: Bool { return array.isEmpty } 50| | 51| | /// Returns the contents of the set as an array. 52| 0| public var contents: [Element] { return array } 53| | 54| | /// Returns `true` if the ordered set contains `member`. 55| 0| public func contains(_ member: Element) -> Bool { 56| 0| return set.contains(member) 57| 0| } 58| | 59| | /// Adds an element to the ordered set. 60| | /// 61| | /// If it already contains the element, then the set is unchanged. 62| | /// 63| | /// - returns: True if the item was inserted. 64| | @discardableResult 65| 0| public mutating func append(_ newElement: Element) -> Bool { 66| 0| let inserted = set.insert(newElement).inserted 67| 0| if inserted { 68| 0| array.append(newElement) 69| 0| } 70| 0| return inserted 71| 0| } 72| | 73| | /// Remove and return the element at the beginning of the ordered set. 74| 0| public mutating func removeFirst() -> Element { 75| 0| let firstElement = array.removeFirst() 76| 0| set.remove(firstElement) 77| 0| return firstElement 78| 0| } 79| | 80| | /// Remove and return the element at the end of the ordered set. 81| 0| public mutating func removeLast() -> Element { 82| 0| let lastElement = array.removeLast() 83| 0| set.remove(lastElement) 84| 0| return lastElement 85| 0| } 86| | 87| | /// Remove all elements. 88| 0| public mutating func removeAll(keepingCapacity keepCapacity: Bool) { 89| 0| array.removeAll(keepingCapacity: keepCapacity) 90| 0| set.removeAll(keepingCapacity: keepCapacity) 91| 0| } 92| |} 93| | 94| |extension OrderedSet: ExpressibleByArrayLiteral { 95| | /// Create an instance initialized with `elements`. 96| | /// 97| | /// If an element occurs more than once in `element`, only the first one 98| | /// will be included. 99| 0| public init(arrayLiteral elements: Element...) { 100| 0| self.init(elements) 101| 0| } 102| |} 103| | 104| |extension OrderedSet: RandomAccessCollection { 105| 0| public var startIndex: Int { return contents.startIndex } 106| 0| public var endIndex: Int { return contents.endIndex } 107| 0| public subscript(index: Int) -> Element { 108| 0| return contents[index] 109| 0| } 110| |} 111| | 112| 0|public func == (lhs: OrderedSet, rhs: OrderedSet) -> Bool { 113| 0| return lhs.contents == rhs.contents 114| 0|} 115| | 116| |extension OrderedSet: Hashable where Element: Hashable { } /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/OutputByteStream.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| |import Dispatch 13| | 14| |/// Convert an integer in 0..<16 to its hexadecimal ASCII character. 15| 0|private func hexdigit(_ value: UInt8) -> UInt8 { 16| 0| return value < 10 ? (0x30 + value) : (0x41 + value - 10) 17| 0|} 18| | 19| |/// Describes a type which can be written to a byte stream. 20| |public protocol ByteStreamable { 21| | func write(to stream: OutputByteStream) 22| |} 23| | 24| |/// An output byte stream. 25| |/// 26| |/// This protocol is designed to be able to support efficient streaming to 27| |/// different output destinations, e.g., a file or an in memory buffer. This is 28| |/// loosely modeled on LLVM's llvm::raw_ostream class. 29| |/// 30| |/// The stream is generally used in conjunction with the custom streaming 31| |/// operator '<<<'. For example: 32| |/// 33| |/// let stream = BufferedOutputByteStream() 34| |/// stream <<< "Hello, world!" 35| |/// 36| |/// would write the UTF8 encoding of "Hello, world!" to the stream. 37| |/// 38| |/// The stream accepts a number of custom formatting operators which are defined 39| |/// in the `Format` struct (used for namespacing purposes). For example: 40| |/// 41| |/// let items = ["hello", "world"] 42| |/// stream <<< Format.asSeparatedList(items, separator: " ") 43| |/// 44| |/// would write each item in the list to the stream, separating them with a 45| |/// space. 46| |public protocol OutputByteStream: class, TextOutputStream { 47| | /// The current offset within the output stream. 48| | var position: Int { get } 49| | 50| | /// Write an individual byte to the buffer. 51| | func write(_ byte: UInt8) 52| | 53| | /// Write a collection of bytes to the buffer. 54| | func write(_ bytes: C) where C.Element == UInt8 55| | 56| | /// Flush the stream's buffer. 57| | func flush() 58| |} 59| | 60| |extension OutputByteStream { 61| | /// Write a sequence of bytes to the buffer. 62| 0| public func write(sequence: S) where S.Iterator.Element == UInt8 { 63| 0| // Iterate the sequence and append byte by byte since sequence's append 64| 0| // is not performant anyway. 65| 0| for byte in sequence { 66| 0| write(byte) 67| 0| } 68| 0| } 69| | 70| | /// Write a string to the buffer (as UTF8). 71| 0| public func write(_ string: String) { 72| 0| // FIXME(performance): Use `string.utf8._copyContents(initializing:)`. 73| 0| write(string.utf8) 74| 0| } 75| | 76| | /// Write a string (as UTF8) to the buffer, with escaping appropriate for 77| | /// embedding within a JSON document. 78| | /// 79| | /// - Note: This writes the literal data applying JSON string escaping, but 80| | /// does not write any other characters (like the quotes that would surround 81| | /// a JSON string). 82| 0| public func writeJSONEscaped(_ string: String) { 83| 0| // See RFC7159 for reference: https://tools.ietf.org/html/rfc7159 84| 0| for character in string.utf8 { 85| 0| // Handle string escapes; we use constants here to directly match the RFC. 86| 0| switch character { 87| 0| // Literal characters. 88| 0| case 0x20...0x21, 0x23...0x5B, 0x5D...0xFF: 89| 0| write(character) 90| 0| 91| 0| // Single-character escaped characters. 92| 0| case 0x22: // '"' 93| 0| write(0x5C) // '\' 94| 0| write(0x22) // '"' 95| 0| case 0x5C: // '\\' 96| 0| write(0x5C) // '\' 97| 0| write(0x5C) // '\' 98| 0| case 0x08: // '\b' 99| 0| write(0x5C) // '\' 100| 0| write(0x62) // 'b' 101| 0| case 0x0C: // '\f' 102| 0| write(0x5C) // '\' 103| 0| write(0x66) // 'b' 104| 0| case 0x0A: // '\n' 105| 0| write(0x5C) // '\' 106| 0| write(0x6E) // 'n' 107| 0| case 0x0D: // '\r' 108| 0| write(0x5C) // '\' 109| 0| write(0x72) // 'r' 110| 0| case 0x09: // '\t' 111| 0| write(0x5C) // '\' 112| 0| write(0x74) // 't' 113| 0| 114| 0| // Multi-character escaped characters. 115| 0| default: 116| 0| write(0x5C) // '\' 117| 0| write(0x75) // 'u' 118| 0| write(hexdigit(0)) 119| 0| write(hexdigit(0)) 120| 0| write(hexdigit(character >> 4)) 121| 0| write(hexdigit(character & 0xF)) 122| 0| } 123| 0| } 124| 0| } 125| |} 126| | 127| |/// The `OutputByteStream` base class. 128| |/// 129| |/// This class provides a base and efficient implementation of the `OutputByteStream` 130| |/// protocol. It can not be used as is-as subclasses as several functions need to be 131| |/// implemented in subclasses. 132| |public class _OutputByteStreamBase: OutputByteStream { 133| | /// If buffering is enabled 134| | @usableFromInline let _buffered : Bool 135| | 136| | /// The data buffer. 137| | /// - Note: Minimum Buffer size should be one. 138| | @usableFromInline var _buffer: [UInt8] 139| | 140| | /// Default buffer size of the data buffer. 141| | private static let bufferSize = 1024 142| | 143| | /// Queue to protect mutating operation. 144| | fileprivate let queue = DispatchQueue(label: "org.swift.swiftpm.basic.stream") 145| | 146| 2| init(buffered: Bool) { 147| 2| self._buffered = buffered 148| 2| self._buffer = [] 149| 2| 150| 2| // When not buffered we still reserve 1 byte, as it is used by the 151| 2| // by the single byte write() variant. 152| 2| self._buffer.reserveCapacity(buffered ? _OutputByteStreamBase.bufferSize : 1) 153| 2| } 154| | 155| | // MARK: Data Access API 156| | 157| | /// The current offset within the output stream. 158| 0| public var position: Int { 159| 0| return _buffer.count 160| 0| } 161| | 162| | /// Currently available buffer size. 163| 0| @usableFromInline var _availableBufferSize: Int { 164| 0| return _buffer.capacity - _buffer.count 165| 0| } 166| | 167| | /// Clears the buffer maintaining current capacity. 168| 4| @usableFromInline func _clearBuffer() { 169| 4| _buffer.removeAll(keepingCapacity: true) 170| 4| } 171| | 172| | // MARK: Data Output API 173| | 174| 4| public final func flush() { 175| 4| writeImpl(ArraySlice(_buffer)) 176| 4| _clearBuffer() 177| 4| flushImpl() 178| 4| } 179| | 180| 0| @usableFromInline func flushImpl() { 181| 0| // Do nothing. 182| 0| } 183| | 184| 0| @usableFromInline func writeImpl(_ bytes: C) where C.Iterator.Element == UInt8 { 185| 0| fatalError("Subclasses must implement this") 186| 0| } 187| | 188| 0| @usableFromInline func writeImpl(_ bytes: ArraySlice) { 189| 0| fatalError("Subclasses must implement this") 190| 0| } 191| | 192| | /// Write an individual byte to the buffer. 193| 0| public final func write(_ byte: UInt8) { 194| 0| guard _buffered else { 195| 0| _buffer.append(byte) 196| 0| writeImpl(ArraySlice(_buffer)) 197| 0| flushImpl() 198| 0| _clearBuffer() 199| 0| return 200| 0| } 201| 0| 202| 0| // If buffer is full, write and clear it. 203| 0| if _availableBufferSize == 0 { 204| 0| writeImpl(ArraySlice(_buffer)) 205| 0| _clearBuffer() 206| 0| } 207| 0| 208| 0| // This will need to change change if we ever have unbuffered stream. 209| 0| precondition(_availableBufferSize > 0) 210| 0| _buffer.append(byte) 211| 0| } 212| | 213| | /// Write a collection of bytes to the buffer. 214| 11| @inlinable public final func write(_ bytes: C) where C.Element == UInt8 { 215| 11| guard _buffered else { 216| 11| if let b = bytes as? ArraySlice { 217| 0| // Fast path for unbuffered ArraySlice 218| 0| writeImpl(b) 219| 11| } else if let b = bytes as? Array { 220| 0| // Fast path for unbuffered Array 221| 0| writeImpl(ArraySlice(b)) 222| 11| } else { 223| 11| // generic collection unfortunately must be temporarily buffered 224| 11| writeImpl(bytes) 225| 11| } 226| 11| flushImpl() 227| 11| return 228| 11| } 229| 0| 230| 0| // This is based on LLVM's raw_ostream. 231| 0| let availableBufferSize = self._availableBufferSize 232| 0| let byteCount = Int(bytes.count) 233| 0| 234| 0| // If we have to insert more than the available space in buffer. 235| 0| if byteCount > availableBufferSize { 236| 0| // If buffer is empty, start writing and keep the last chunk in buffer. 237| 0| if _buffer.isEmpty { 238| 0| let bytesToWrite = byteCount - (byteCount % availableBufferSize) 239| 0| let writeUptoIndex = bytes.index(bytes.startIndex, offsetBy: numericCast(bytesToWrite)) 240| 0| writeImpl(bytes.prefix(upTo: writeUptoIndex)) 241| 0| 242| 0| // If remaining bytes is more than buffer size write everything. 243| 0| let bytesRemaining = byteCount - bytesToWrite 244| 0| if bytesRemaining > availableBufferSize { 245| 0| writeImpl(bytes.suffix(from: writeUptoIndex)) 246| 0| return 247| 0| } 248| 0| // Otherwise keep remaining in buffer. 249| 0| _buffer += bytes.suffix(from: writeUptoIndex) 250| 0| return 251| 0| } 252| 0| 253| 0| let writeUptoIndex = bytes.index(bytes.startIndex, offsetBy: numericCast(availableBufferSize)) 254| 0| // Append whatever we can accommodate. 255| 0| _buffer += bytes.prefix(upTo: writeUptoIndex) 256| 0| 257| 0| writeImpl(ArraySlice(_buffer)) 258| 0| _clearBuffer() 259| 0| 260| 0| // FIXME: We should start again with remaining chunk but this doesn't work. Write everything for now. 261| 0| //write(collection: bytes.suffix(from: writeUptoIndex)) 262| 0| writeImpl(bytes.suffix(from: writeUptoIndex)) 263| 0| return 264| 0| } 265| 0| _buffer += bytes 266| 0| } 267| |} 268| | 269| |/// The thread-safe wrapper around output byte streams. 270| |/// 271| |/// This class wraps any `OutputByteStream` conforming type to provide a type-safe 272| |/// access to its operations. If the provided stream inherits from `_OutputByteStreamBase`, 273| |/// it will also ensure it is type-safe will all other `ThreadSafeOutputByteStream` instances 274| |/// around the same stream. 275| |public final class ThreadSafeOutputByteStream: OutputByteStream { 276| | private static let defaultQueue = DispatchQueue(label: "org.swift.swiftpm.basic.thread-safe-output-byte-stream") 277| | public let stream: OutputByteStream 278| | private let queue: DispatchQueue 279| | 280| 0| public var position: Int { 281| 0| return queue.sync { 282| 0| stream.position 283| 0| } 284| 0| } 285| | 286| 0| public init(_ stream: OutputByteStream) { 287| 0| self.stream = stream 288| 0| self.queue = (stream as? _OutputByteStreamBase)?.queue ?? ThreadSafeOutputByteStream.defaultQueue 289| 0| } 290| | 291| 0| public func write(_ byte: UInt8) { 292| 0| queue.sync { 293| 0| stream.write(byte) 294| 0| } 295| 0| } 296| | 297| 0| public func write(_ bytes: C) where C.Element == UInt8 { 298| 0| queue.sync { 299| 0| stream.write(bytes) 300| 0| } 301| 0| } 302| | 303| 0| public func flush() { 304| 0| queue.sync { 305| 0| stream.flush() 306| 0| } 307| 0| } 308| | 309| 0| public func write(sequence: S) where S.Iterator.Element == UInt8 { 310| 0| queue.sync { 311| 0| stream.write(sequence: sequence) 312| 0| } 313| 0| } 314| | 315| 0| public func writeJSONEscaped(_ string: String) { 316| 0| queue.sync { 317| 0| stream.writeJSONEscaped(string) 318| 0| } 319| 0| } 320| |} 321| | 322| |/// Define an output stream operator. We need it to be left associative, so we 323| |/// use `<<<`. 324| |infix operator <<< : StreamingPrecedence 325| |precedencegroup StreamingPrecedence { 326| | associativity: left 327| |} 328| | 329| |// MARK: Output Operator Implementations 330| | 331| |// FIXME: This override shouldn't be necesary but removing it causes a 30% performance regression. This problem is 332| |// tracked by the following bug: https://bugs.swift.org/browse/SR-8535 333| |@discardableResult 334| 0|public func <<< (stream: OutputByteStream, value: ArraySlice) -> OutputByteStream { 335| 0| value.write(to: stream) 336| 0| return stream 337| 0|} 338| | 339| |@discardableResult 340| 0|public func <<< (stream: OutputByteStream, value: ByteStreamable) -> OutputByteStream { 341| 0| value.write(to: stream) 342| 0| return stream 343| 0|} 344| | 345| |@discardableResult 346| 0|public func <<< (stream: OutputByteStream, value: CustomStringConvertible) -> OutputByteStream { 347| 0| value.description.write(to: stream) 348| 0| return stream 349| 0|} 350| | 351| |@discardableResult 352| 11|public func <<< (stream: OutputByteStream, value: ByteStreamable & CustomStringConvertible) -> OutputByteStream { 353| 11| value.write(to: stream) 354| 11| return stream 355| 11|} 356| | 357| |extension UInt8: ByteStreamable { 358| 0| public func write(to stream: OutputByteStream) { 359| 0| stream.write(self) 360| 0| } 361| |} 362| | 363| |extension Character: ByteStreamable { 364| 0| public func write(to stream: OutputByteStream) { 365| 0| stream.write(String(self)) 366| 0| } 367| |} 368| | 369| |extension String: ByteStreamable { 370| 11| public func write(to stream: OutputByteStream) { 371| 11| stream.write(self.utf8) 372| 11| } 373| |} 374| | 375| |extension Substring: ByteStreamable { 376| 0| public func write(to stream: OutputByteStream) { 377| 0| stream.write(self.utf8) 378| 0| } 379| |} 380| | 381| |extension StaticString: ByteStreamable { 382| 0| public func write(to stream: OutputByteStream) { 383| 0| withUTF8Buffer { stream.write($0) } 384| 0| } 385| |} 386| | 387| |extension Array: ByteStreamable where Element == UInt8 { 388| 0| public func write(to stream: OutputByteStream) { 389| 0| stream.write(self) 390| 0| } 391| |} 392| | 393| |extension ArraySlice: ByteStreamable where Element == UInt8 { 394| 0| public func write(to stream: OutputByteStream) { 395| 0| stream.write(self) 396| 0| } 397| |} 398| | 399| |extension ContiguousArray: ByteStreamable where Element == UInt8 { 400| 0| public func write(to stream: OutputByteStream) { 401| 0| stream.write(self) 402| 0| } 403| |} 404| | 405| |// MARK: Formatted Streaming Output 406| | 407| |/// Provides operations for returning derived streamable objects to implement various forms of formatted output. 408| |public struct Format { 409| | /// Write the input boolean encoded as a JSON object. 410| 0| static public func asJSON(_ value: Bool) -> ByteStreamable { 411| 0| return JSONEscapedBoolStreamable(value: value) 412| 0| } 413| | private struct JSONEscapedBoolStreamable: ByteStreamable { 414| | let value: Bool 415| | 416| 0| func write(to stream: OutputByteStream) { 417| 0| stream <<< (value ? "true" : "false") 418| 0| } 419| | } 420| | 421| | /// Write the input integer encoded as a JSON object. 422| 0| static public func asJSON(_ value: Int) -> ByteStreamable { 423| 0| return JSONEscapedIntStreamable(value: value) 424| 0| } 425| | private struct JSONEscapedIntStreamable: ByteStreamable { 426| | let value: Int 427| | 428| 0| func write(to stream: OutputByteStream) { 429| 0| // FIXME: Diagnose integers which cannot be represented in JSON. 430| 0| stream <<< value.description 431| 0| } 432| | } 433| | 434| | /// Write the input double encoded as a JSON object. 435| 0| static public func asJSON(_ value: Double) -> ByteStreamable { 436| 0| return JSONEscapedDoubleStreamable(value: value) 437| 0| } 438| | private struct JSONEscapedDoubleStreamable: ByteStreamable { 439| | let value: Double 440| | 441| 0| func write(to stream: OutputByteStream) { 442| 0| // FIXME: What should we do about NaN, etc.? 443| 0| // 444| 0| // FIXME: Is Double.debugDescription the best representation? 445| 0| stream <<< value.debugDescription 446| 0| } 447| | } 448| | 449| | /// Write the input CustomStringConvertible encoded as a JSON object. 450| 0| static public func asJSON(_ value: T) -> ByteStreamable { 451| 0| return JSONEscapedStringStreamable(value: value.description) 452| 0| } 453| | /// Write the input string encoded as a JSON object. 454| 0| static public func asJSON(_ string: String) -> ByteStreamable { 455| 0| return JSONEscapedStringStreamable(value: string) 456| 0| } 457| | private struct JSONEscapedStringStreamable: ByteStreamable { 458| | let value: String 459| | 460| 0| func write(to stream: OutputByteStream) { 461| 0| stream <<< UInt8(ascii: "\"") 462| 0| stream.writeJSONEscaped(value) 463| 0| stream <<< UInt8(ascii: "\"") 464| 0| } 465| | } 466| | 467| | /// Write the input string list encoded as a JSON object. 468| 0| static public func asJSON(_ items: [T]) -> ByteStreamable { 469| 0| return JSONEscapedStringListStreamable(items: items.map({ $0.description })) 470| 0| } 471| | /// Write the input string list encoded as a JSON object. 472| | // 473| | // FIXME: We might be able to make this more generic through the use of a "JSONEncodable" protocol. 474| 0| static public func asJSON(_ items: [String]) -> ByteStreamable { 475| 0| return JSONEscapedStringListStreamable(items: items) 476| 0| } 477| | private struct JSONEscapedStringListStreamable: ByteStreamable { 478| | let items: [String] 479| | 480| 0| func write(to stream: OutputByteStream) { 481| 0| stream <<< UInt8(ascii: "[") 482| 0| for (i, item) in items.enumerated() { 483| 0| if i != 0 { stream <<< "," } 484| 0| stream <<< Format.asJSON(item) 485| 0| } 486| 0| stream <<< UInt8(ascii: "]") 487| 0| } 488| | } 489| | 490| | /// Write the input dictionary encoded as a JSON object. 491| 0| static public func asJSON(_ items: [String: String]) -> ByteStreamable { 492| 0| return JSONEscapedDictionaryStreamable(items: items) 493| 0| } 494| | private struct JSONEscapedDictionaryStreamable: ByteStreamable { 495| | let items: [String: String] 496| | 497| 0| func write(to stream: OutputByteStream) { 498| 0| stream <<< UInt8(ascii: "{") 499| 0| for (offset: i, element: (key: key, value: value)) in items.enumerated() { 500| 0| if i != 0 { stream <<< "," } 501| 0| stream <<< Format.asJSON(key) <<< ":" <<< Format.asJSON(value) 502| 0| } 503| 0| stream <<< UInt8(ascii: "}") 504| 0| } 505| | } 506| | 507| | /// Write the input list (after applying a transform to each item) encoded as a JSON object. 508| | // 509| | // FIXME: We might be able to make this more generic through the use of a "JSONEncodable" protocol. 510| 0| static public func asJSON(_ items: [T], transform: @escaping (T) -> String) -> ByteStreamable { 511| 0| return JSONEscapedTransformedStringListStreamable(items: items, transform: transform) 512| 0| } 513| | private struct JSONEscapedTransformedStringListStreamable: ByteStreamable { 514| | let items: [T] 515| | let transform: (T) -> String 516| | 517| 0| func write(to stream: OutputByteStream) { 518| 0| stream <<< UInt8(ascii: "[") 519| 0| for (i, item) in items.enumerated() { 520| 0| if i != 0 { stream <<< "," } 521| 0| stream <<< Format.asJSON(transform(item)) 522| 0| } 523| 0| stream <<< UInt8(ascii: "]") 524| 0| } 525| | } 526| | 527| | /// Write the input list to the stream with the given separator between items. 528| 0| static public func asSeparatedList(_ items: [T], separator: String) -> ByteStreamable { 529| 0| return SeparatedListStreamable(items: items, separator: separator) 530| 0| } 531| | private struct SeparatedListStreamable: ByteStreamable { 532| | let items: [T] 533| | let separator: String 534| | 535| 0| func write(to stream: OutputByteStream) { 536| 0| for (i, item) in items.enumerated() { 537| 0| // Add the separator, if necessary. 538| 0| if i != 0 { 539| 0| stream <<< separator 540| 0| } 541| 0| 542| 0| stream <<< item 543| 0| } 544| 0| } 545| | } 546| | 547| | /// Write the input list to the stream (after applying a transform to each item) with the given separator between 548| | /// items. 549| | static public func asSeparatedList( 550| | _ items: [T], 551| | transform: @escaping (T) -> ByteStreamable, 552| | separator: String 553| 0| ) -> ByteStreamable { 554| 0| return TransformedSeparatedListStreamable(items: items, transform: transform, separator: separator) 555| 0| } 556| | private struct TransformedSeparatedListStreamable: ByteStreamable { 557| | let items: [T] 558| | let transform: (T) -> ByteStreamable 559| | let separator: String 560| | 561| 0| func write(to stream: OutputByteStream) { 562| 0| for (i, item) in items.enumerated() { 563| 0| if i != 0 { stream <<< separator } 564| 0| stream <<< transform(item) 565| 0| } 566| 0| } 567| | } 568| | 569| 0| static public func asRepeating(string: String, count: Int) -> ByteStreamable { 570| 0| return RepeatingStringStreamable(string: string, count: count) 571| 0| } 572| | private struct RepeatingStringStreamable: ByteStreamable { 573| | let string: String 574| | let count: Int 575| | 576| 0| init(string: String, count: Int) { 577| 0| precondition(count >= 0, "Count should be >= zero") 578| 0| self.string = string 579| 0| self.count = count 580| 0| } 581| | 582| 0| func write(to stream: OutputByteStream) { 583| 0| for _ in 0..(_ bytes: C) where C.Iterator.Element == UInt8 { 620| 11| contents += bytes 621| 11| } 622| 4| override final func writeImpl(_ bytes: ArraySlice) { 623| 4| contents += bytes 624| 4| } 625| |} 626| | 627| |/// Represents a stream which is backed to a file. Not for instantiating. 628| |public class FileOutputByteStream: _OutputByteStreamBase { 629| | 630| | /// Closes the file flushing any buffered data. 631| 0| public final func close() throws { 632| 0| flush() 633| 0| try closeImpl() 634| 0| } 635| | 636| 0| func closeImpl() throws { 637| 0| fatalError("closeImpl() should be implemented by a subclass") 638| 0| } 639| |} 640| | 641| |/// Implements file output stream for local file system. 642| |public final class LocalFileOutputByteStream: FileOutputByteStream { 643| | 644| | /// The pointer to the file. 645| | let filePointer: UnsafeMutablePointer 646| | 647| | /// True if there were any IO error during writing. 648| | private var error: Bool = false 649| | 650| | /// Closes the file on deinit if true. 651| | private var closeOnDeinit: Bool 652| | 653| | /// Instantiate using the file pointer. 654| 0| init(filePointer: UnsafeMutablePointer, closeOnDeinit: Bool = true, buffered: Bool = true) throws { 655| 0| self.filePointer = filePointer 656| 0| self.closeOnDeinit = closeOnDeinit 657| 0| super.init(buffered: buffered) 658| 0| } 659| | 660| | /// Opens the file for writing at the provided path. 661| | /// 662| | /// - Parameters: 663| | /// - path: Path to the file this stream should operate on. 664| | /// - closeOnDeinit: If true closes the file on deinit. clients can use 665| | /// close() if they want to close themselves or catch 666| | /// errors encountered during writing to the file. 667| | /// Default value is true. 668| | /// - buffered: If true buffers writes in memory until full or flush(). 669| | /// Otherwise, writes are processed and flushed immediately. 670| | /// Default value is true. 671| | /// 672| | /// - Throws: FileSystemError 673| 0| public init(_ path: AbsolutePath, closeOnDeinit: Bool = true, buffered: Bool = true) throws { 674| 0| guard let filePointer = fopen(path.pathString, "wb") else { 675| 0| throw FileSystemError(errno: errno) 676| 0| } 677| 0| self.filePointer = filePointer 678| 0| self.closeOnDeinit = closeOnDeinit 679| 0| super.init(buffered: buffered) 680| 0| } 681| | 682| 0| deinit { 683| 0| if closeOnDeinit { 684| 0| fclose(filePointer) 685| 0| } 686| 0| } 687| | 688| 0| func errorDetected() { 689| 0| error = true 690| 0| } 691| | 692| 0| override final func writeImpl(_ bytes: C) where C.Iterator.Element == UInt8 { 693| 0| // FIXME: This will be copying bytes but we don't have option currently. 694| 0| var contents = [UInt8](bytes) 695| 0| while true { 696| 0| let n = fwrite(&contents, 1, contents.count, filePointer) 697| 0| if n < 0 { 698| 0| if errno == EINTR { continue } 699| 0| errorDetected() 700| 0| } else if n != contents.count { 701| 0| errorDetected() 702| 0| } 703| 0| break 704| 0| } 705| 0| } 706| | 707| 0| override final func writeImpl(_ bytes: ArraySlice) { 708| 0| bytes.withUnsafeBytes { bytesPtr in 709| 0| while true { 710| 0| let n = fwrite(bytesPtr.baseAddress, 1, bytesPtr.count, filePointer) 711| 0| if n < 0 { 712| 0| if errno == EINTR { continue } 713| 0| errorDetected() 714| 0| } else if n != bytesPtr.count { 715| 0| errorDetected() 716| 0| } 717| 0| break 718| 0| } 719| 0| } 720| 0| } 721| | 722| 0| override final func flushImpl() { 723| 0| fflush(filePointer) 724| 0| } 725| | 726| 0| override final func closeImpl() throws { 727| 0| defer { 728| 0| fclose(filePointer) 729| 0| // If clients called close we shouldn't call fclose again in deinit. 730| 0| closeOnDeinit = false 731| 0| } 732| 0| // Throw if errors were found during writing. 733| 0| if error { 734| 0| throw FileSystemError.ioError 735| 0| } 736| 0| } 737| |} 738| | 739| |/// Public stdout stream instance. 740| |public var stdoutStream: ThreadSafeOutputByteStream = try! ThreadSafeOutputByteStream(LocalFileOutputByteStream( 741| | filePointer: SPMLibc.stdout, 742| | closeOnDeinit: false)) 743| | 744| |/// Public stderr stream instance. 745| |public var stderrStream: ThreadSafeOutputByteStream = try! ThreadSafeOutputByteStream(LocalFileOutputByteStream( 746| | filePointer: SPMLibc.stderr, 747| | closeOnDeinit: false)) /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Path.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Represents an absolute file system path, independently of what (or whether 12| |/// anything at all) exists at that path in the file system at any given time. 13| |/// An absolute path always starts with a `/` character, and holds a normalized 14| |/// string representation. This normalization is strictly syntactic, and does 15| |/// not access the file system in any way. 16| |/// 17| |/// The absolute path string is normalized by: 18| |/// - Collapsing `..` path components 19| |/// - Removing `.` path components 20| |/// - Removing any trailing path separator 21| |/// - Removing any redundant path separators 22| |/// 23| |/// This string manipulation may change the meaning of a path if any of the 24| |/// path components are symbolic links on disk. However, the file system is 25| |/// never accessed in any way when initializing an AbsolutePath. 26| |/// 27| |/// Note that `~` (home directory resolution) is *not* done as part of path 28| |/// normalization, because it is normally the responsibility of the shell and 29| |/// not the program being invoked (e.g. when invoking `cd ~`, it is the shell 30| |/// that evaluates the tilde; the `cd` command receives an absolute path). 31| |public struct AbsolutePath: Hashable { 32| | /// Check if the given name is a valid individual path component. 33| | /// 34| | /// This only checks with regard to the semantics enforced by `AbsolutePath` 35| | /// and `RelativePath`; particular file systems may have their own 36| | /// additional requirements. 37| 0| static func isValidComponent(_ name: String) -> Bool { 38| 0| return name != "" && name != "." && name != ".." && !name.contains("/") 39| 0| } 40| | 41| | /// Private implementation details, shared with the RelativePath struct. 42| | private let _impl: PathImpl 43| | 44| | /// Private initializer when the backing storage is known. 45| 0| private init(_ impl: PathImpl) { 46| 0| _impl = impl 47| 0| } 48| | 49| | /// Initializes the AbsolutePath from `absStr`, which must be an absolute 50| | /// path (i.e. it must begin with a path separator; this initializer does 51| | /// not interpret leading `~` characters as home directory specifiers). 52| | /// The input string will be normalized if needed, as described in the 53| | /// documentation for AbsolutePath. 54| 0| public init(_ absStr: String) { 55| 0| // Normalize the absolute string. 56| 0| self.init(PathImpl(string: normalize(absolute: absStr))) 57| 0| } 58| | 59| | /// Initializes an AbsolutePath from a string that may be either absolute 60| | /// or relative; if relative, `basePath` is used as the anchor; if absolute, 61| | /// it is used as is, and in this case `basePath` is ignored. 62| 0| public init(_ str: String, relativeTo basePath: AbsolutePath) { 63| 0| if str.hasPrefix("/") { 64| 0| self.init(str) 65| 0| } else { 66| 0| self.init(basePath, RelativePath(str)) 67| 0| } 68| 0| } 69| | 70| | /// Initializes the AbsolutePath by concatenating a relative path to an 71| | /// existing absolute path, and renormalizing if necessary. 72| 0| public init(_ absPath: AbsolutePath, _ relPath: RelativePath) { 73| 0| // Both paths are already normalized. The only case in which we have 74| 0| // to renormalize their concatenation is if the relative path starts 75| 0| // with a `..` path component. 76| 0| let relStr = relPath._impl.string 77| 0| var absStr = absPath._impl.string 78| 0| if absStr != "/" { 79| 0| absStr.append("/") 80| 0| } 81| 0| absStr.append(relStr) 82| 0| 83| 0| // If the relative string starts with `.` or `..`, we need to normalize 84| 0| // the resulting string. 85| 0| // FIXME: We can actually optimize that case, since we know that the 86| 0| // normalization of a relative path can leave `..` path components at 87| 0| // the beginning of the path only. 88| 0| if relStr.hasPrefix(".") { 89| 0| absStr = normalize(absolute: absStr) 90| 0| } 91| 0| 92| 0| // Finally, store the result as our PathImpl. 93| 0| self.init(PathImpl(string: absStr)) 94| 0| } 95| | 96| | /// Convenience initializer that appends a string to a relative path. 97| 0| public init(_ absPath: AbsolutePath, _ relStr: String) { 98| 0| self.init(absPath, RelativePath(relStr)) 99| 0| } 100| | 101| | /// Convenience initializer that verifies that the path is absolute. 102| 0| public init(validating path: String) throws { 103| 0| switch path.first { 104| 0| case "/": 105| 0| self.init(path) 106| 0| case "~": 107| 0| throw PathValidationError.startsWithTilde(path) 108| 0| default: 109| 0| throw PathValidationError.invalidAbsolutePath(path) 110| 0| } 111| 0| } 112| | 113| | /// Directory component. An absolute path always has a non-empty directory 114| | /// component (the directory component of the root path is the root itself). 115| 0| public var dirname: String { 116| 0| return _impl.dirname 117| 0| } 118| | 119| | /// Last path component (including the suffix, if any). it is never empty. 120| 0| public var basename: String { 121| 0| return _impl.basename 122| 0| } 123| | 124| | /// Suffix (including leading `.` character) if any. Note that a basename 125| | /// that starts with a `.` character is not considered a suffix, nor is a 126| | /// trailing `.` character. 127| 0| public var suffix: String? { 128| 0| return _impl.suffix 129| 0| } 130| | 131| | /// Extension of the give path's basename. This follow same rules as 132| | /// suffix except that it doesn't include leading `.` character. 133| 0| public var `extension`: String? { 134| 0| return _impl.extension 135| 0| } 136| | 137| | /// Absolute path of parent directory. This always returns a path, because 138| | /// every directory has a parent (the parent directory of the root directory 139| | /// is considered to be the root directory itself). 140| 0| public var parentDirectory: AbsolutePath { 141| 0| return isRoot ? self : AbsolutePath(_impl.dirname) 142| 0| } 143| | 144| | /// True if the path is the root directory. 145| 0| public var isRoot: Bool { 146| 0| return _impl.string.spm_only == "/" 147| 0| } 148| | 149| | /// Returns the absolute path with the relative path applied. 150| 0| public func appending(_ subpath: RelativePath) -> AbsolutePath { 151| 0| return AbsolutePath(self, subpath) 152| 0| } 153| | 154| | /// Returns the absolute path with an additional literal component appended. 155| | /// 156| | /// This method accepts pseudo-path like '.' or '..', but should not contain "/". 157| 0| public func appending(component name: String) -> AbsolutePath { 158| 0| assert(!name.contains("/"), "\(name) is invalid path component") 159| 0| 160| 0| // Handle pseudo paths. 161| 0| switch name { 162| 0| case "", ".": 163| 0| return self 164| 0| case "..": 165| 0| return self.parentDirectory 166| 0| default: break 167| 0| } 168| 0| 169| 0| if self == AbsolutePath.root { 170| 0| return AbsolutePath(PathImpl(string: "/" + name)) 171| 0| } else { 172| 0| return AbsolutePath(PathImpl(string: _impl.string + "/" + name)) 173| 0| } 174| 0| } 175| | 176| | /// Returns the absolute path with additional literal components appended. 177| | /// 178| | /// This method should only be used in cases where the input is guaranteed 179| | /// to be a valid path component (i.e., it cannot be empty, contain a path 180| | /// separator, or be a pseudo-path like '.' or '..'). 181| 0| public func appending(components names: String...) -> AbsolutePath { 182| 0| // FIXME: This doesn't seem a particularly efficient way to do this. 183| 0| return names.reduce(self, { path, name in 184| 0| path.appending(component: name) 185| 0| }) 186| 0| } 187| | 188| | /// NOTE: We will most likely want to add other `appending()` methods, such 189| | /// as `appending(suffix:)`, and also perhaps `replacing()` methods, 190| | /// such as `replacing(suffix:)` or `replacing(basename:)` for some 191| | /// of the more common path operations. 192| | 193| | /// NOTE: We may want to consider adding operators such as `+` for appending 194| | /// a path component. 195| | 196| | /// NOTE: We will want to add a method to return the lowest common ancestor 197| | /// path. 198| | 199| | /// Root directory (whose string representation is just a path separator). 200| | public static let root = AbsolutePath("/") 201| | 202| | /// Normalized string representation (the normalization rules are described 203| | /// in the documentation of the initializer). This string is never empty. 204| 0| public var pathString: String { 205| 0| return _impl.string 206| 0| } 207| | 208| | /// Returns an array of strings that make up the path components of the 209| | /// absolute path. This is the same sequence of strings as the basenames 210| | /// of each successive path component, starting from the root. Therefore 211| | /// the first path component of an absolute path is always `/`. 212| 0| public var components: [String] { 213| 0| return ["/"] + _impl.components 214| 0| } 215| |} 216| | 217| |/// Represents a relative file system path. A relative path never starts with 218| |/// a `/` character, and holds a normalized string representation. As with 219| |/// AbsolutePath, the normalization is strictly syntactic, and does not access 220| |/// the file system in any way. 221| |/// 222| |/// The relative path string is normalized by: 223| |/// - Collapsing `..` path components that aren't at the beginning 224| |/// - Removing extraneous `.` path components 225| |/// - Removing any trailing path separator 226| |/// - Removing any redundant path separators 227| |/// - Replacing a completely empty path with a `.` 228| |/// 229| |/// This string manipulation may change the meaning of a path if any of the 230| |/// path components are symbolic links on disk. However, the file system is 231| |/// never accessed in any way when initializing a RelativePath. 232| |public struct RelativePath: Hashable { 233| | /// Private implementation details, shared with the AbsolutePath struct. 234| | fileprivate let _impl: PathImpl 235| | 236| | /// Initializes the RelativePath from `str`, which must be a relative path 237| | /// (which means that it must not begin with a path separator or a tilde). 238| | /// An empty input path is allowed, but will be normalized to a single `.` 239| | /// character. The input string will be normalized if needed, as described 240| | /// in the documentation for RelativePath. 241| 0| public init(_ string: String) { 242| 0| // Normalize the relative string and store it as our PathImpl. 243| 0| _impl = PathImpl(string: normalize(relative: string)) 244| 0| } 245| | 246| | /// Convenience initializer that verifies that the path is relative. 247| 0| public init(validating path: String) throws { 248| 0| switch path.first { 249| 0| case "/", "~": 250| 0| throw PathValidationError.invalidRelativePath(path) 251| 0| default: 252| 0| self.init(path) 253| 0| } 254| 0| } 255| | 256| | /// Directory component. For a relative path without any path separators, 257| | /// this is the `.` string instead of the empty string. 258| 0| public var dirname: String { 259| 0| return _impl.dirname 260| 0| } 261| | 262| | /// Last path component (including the suffix, if any). It is never empty. 263| 0| public var basename: String { 264| 0| return _impl.basename 265| 0| } 266| | 267| | /// Suffix (including leading `.` character) if any. Note that a basename 268| | /// that starts with a `.` character is not considered a suffix, nor is a 269| | /// trailing `.` character. 270| 0| public var suffix: String? { 271| 0| return _impl.suffix 272| 0| } 273| | 274| | /// Extension of the give path's basename. This follow same rules as 275| | /// suffix except that it doesn't include leading `.` character. 276| 0| public var `extension`: String? { 277| 0| return _impl.extension 278| 0| } 279| | 280| | /// Normalized string representation (the normalization rules are described 281| | /// in the documentation of the initializer). This string is never empty. 282| 0| public var pathString: String { 283| 0| return _impl.string 284| 0| } 285| | 286| | /// Returns an array of strings that make up the path components of the 287| | /// relative path. This is the same sequence of strings as the basenames 288| | /// of each successive path component. Therefore the returned array of 289| | /// path components is never empty; even an empty path has a single path 290| | /// component: the `.` string. 291| 0| public var components: [String] { 292| 0| return _impl.components 293| 0| } 294| |} 295| | 296| |extension AbsolutePath: Codable { 297| 0| public func encode(to encoder: Encoder) throws { 298| 0| var container = encoder.singleValueContainer() 299| 0| try container.encode(pathString) 300| 0| } 301| | 302| 0| public init(from decoder: Decoder) throws { 303| 0| let container = try decoder.singleValueContainer() 304| 0| try self.init(container.decode(String.self)) 305| 0| } 306| |} 307| | 308| |extension RelativePath: Codable { 309| 0| public func encode(to encoder: Encoder) throws { 310| 0| var container = encoder.singleValueContainer() 311| 0| try container.encode(pathString) 312| 0| } 313| | 314| 0| public init(from decoder: Decoder) throws { 315| 0| let container = try decoder.singleValueContainer() 316| 0| try self.init(container.decode(String.self)) 317| 0| } 318| |} 319| | 320| |// Make absolute paths Comparable. 321| |extension AbsolutePath: Comparable { 322| 0| public static func < (lhs: AbsolutePath, rhs: AbsolutePath) -> Bool { 323| 0| return lhs.pathString < rhs.pathString 324| 0| } 325| |} 326| | 327| |/// Make absolute paths CustomStringConvertible and CustomDebugStringConvertible. 328| |extension AbsolutePath: CustomStringConvertible, CustomDebugStringConvertible { 329| 0| public var description: String { 330| 0| return pathString 331| 0| } 332| | 333| 0| public var debugDescription: String { 334| 0| // FIXME: We should really be escaping backslashes and quotes here. 335| 0| return "" 336| 0| } 337| |} 338| | 339| |/// Make relative paths CustomStringConvertible and CustomDebugStringConvertible. 340| |extension RelativePath: CustomStringConvertible { 341| 0| public var description: String { 342| 0| return _impl.string 343| 0| } 344| | 345| 0| public var debugDescription: String { 346| 0| // FIXME: We should really be escaping backslashes and quotes here. 347| 0| return "" 348| 0| } 349| |} 350| | 351| |/// Private implementation shared between AbsolutePath and RelativePath. It is 352| |/// a little unfortunate that there needs to be duplication at all between the 353| |/// AbsolutePath and RelativePath struct, but PathImpl helps mitigate it. From 354| |/// a type safety perspective, absolute paths and relative paths are genuinely 355| |/// different. 356| |private struct PathImpl: Hashable { 357| | /// Normalized string of the (absolute or relative) path. Never empty. 358| | fileprivate let string: String 359| | 360| | /// Private function that returns the directory part of the stored path 361| | /// string (relying on the fact that it has been normalized). Returns a 362| | /// string consisting of just `.` if there is no directory part (which is 363| | /// the case if and only if there is no path separator). 364| 0| fileprivate var dirname: String { 365| 0| // FIXME: This method seems too complicated; it should be simplified, 366| 0| // if possible, and certainly optimized (using UTF8View). 367| 0| // Find the last path separator. 368| 0| guard let idx = string.lastIndex(of: "/") else { 369| 0| // No path separators, so the directory name is `.`. 370| 0| return "." 371| 0| } 372| 0| // Check if it's the only one in the string. 373| 0| if idx == string.startIndex { 374| 0| // Just one path separator, so the directory name is `/`. 375| 0| return "/" 376| 0| } 377| 0| // Otherwise, it's the string up to (but not including) the last path 378| 0| // separator. 379| 0| return String(string.prefix(upTo: idx)) 380| 0| } 381| | 382| 0| fileprivate var basename: String { 383| 0| // FIXME: This method seems too complicated; it should be simplified, 384| 0| // if possible, and certainly optimized (using UTF8View). 385| 0| // Check for a special case of the root directory. 386| 0| if string.spm_only == "/" { 387| 0| // Root directory, so the basename is a single path separator (the 388| 0| // root directory is special in this regard). 389| 0| return "/" 390| 0| } 391| 0| // Find the last path separator. 392| 0| guard let idx = string.lastIndex(of: "/") else { 393| 0| // No path separators, so the basename is the whole string. 394| 0| return string 395| 0| } 396| 0| // Otherwise, it's the string from (but not including) the last path 397| 0| // separator. 398| 0| return String(string.suffix(from: string.index(after: idx))) 399| 0| } 400| | 401| 0| fileprivate var suffix: String? { 402| 0| return suffix(withDot: true) 403| 0| } 404| | 405| 0| fileprivate var `extension`: String? { 406| 0| return suffix(withDot: false) 407| 0| } 408| | 409| | // FIXME: We should investigate if it would be more efficient to instead 410| | // return a path component iterator that does all its work lazily, moving 411| | // from one path separator to the next on-demand. 412| | // 413| 0| fileprivate var components: [String] { 414| 0| // FIXME: This isn't particularly efficient; needs optimization, and 415| 0| // in fact, it might well be best to return a custom iterator so we 416| 0| // don't have to allocate everything up-front. It would be backed by 417| 0| // the path string and just return a slice at a time. 418| 0| return string.components(separatedBy: "/").filter({ !$0.isEmpty }) 419| 0| } 420| | 421| | /// Returns suffix with leading `.` if withDot is true otherwise without it. 422| 0| private func suffix(withDot: Bool) -> String? { 423| 0| // FIXME: This method seems too complicated; it should be simplified, 424| 0| // if possible, and certainly optimized (using UTF8View). 425| 0| // Find the last path separator, if any. 426| 0| let sIdx = string.lastIndex(of: "/") 427| 0| // Find the start of the basename. 428| 0| let bIdx = (sIdx != nil) ? string.index(after: sIdx!) : string.startIndex 429| 0| // Find the last `.` (if any), starting from the second character of 430| 0| // the basename (a leading `.` does not make the whole path component 431| 0| // a suffix). 432| 0| let fIdx = string.index(bIdx, offsetBy: 1, limitedBy: string.endIndex) ?? string.startIndex 433| 0| if let idx = string[fIdx...].lastIndex(of: ".") { 434| 0| // Unless it's just a `.` at the end, we have found a suffix. 435| 0| if string.distance(from: idx, to: string.endIndex) > 1 { 436| 0| let fromIndex = withDot ? idx : string.index(idx, offsetBy: 1) 437| 0| return String(string.suffix(from: fromIndex)) 438| 0| } else { 439| 0| return nil 440| 0| } 441| 0| } 442| 0| // If we get this far, there is no suffix. 443| 0| return nil 444| 0| } 445| |} 446| | 447| |/// Describes the way in which a path is invalid. 448| |public enum PathValidationError: Error { 449| | case startsWithTilde(String) 450| | case invalidAbsolutePath(String) 451| | case invalidRelativePath(String) 452| |} 453| | 454| |extension PathValidationError: CustomStringConvertible { 455| 0| public var description: String { 456| 0| switch self { 457| 0| case .startsWithTilde(let path): 458| 0| return "invalid absolute path '\(path)'; absolute path must begin with '/'" 459| 0| case .invalidAbsolutePath(let path): 460| 0| return "invalid absolute path '\(path)'" 461| 0| case .invalidRelativePath(let path): 462| 0| return "invalid relative path '\(path)'; relative path should not begin with '/' or '~'" 463| 0| } 464| 0| } 465| |} 466| | 467| |extension AbsolutePath { 468| | /// Returns a relative path that, when concatenated to `base`, yields the 469| | /// callee path itself. If `base` is not an ancestor of the callee, the 470| | /// returned path will begin with one or more `..` path components. 471| | /// 472| | /// Because both paths are absolute, they always have a common ancestor 473| | /// (the root path, if nothing else). Therefore, any path can be made 474| | /// relative to any other path by using a sufficient number of `..` path 475| | /// components. 476| | /// 477| | /// This method is strictly syntactic and does not access the file system 478| | /// in any way. Therefore, it does not take symbolic links into account. 479| 0| public func relative(to base: AbsolutePath) -> RelativePath { 480| 0| let result: RelativePath 481| 0| // Split the two paths into their components. 482| 0| // FIXME: The is needs to be optimized to avoid unncessary copying. 483| 0| let pathComps = self.components 484| 0| let baseComps = base.components 485| 0| 486| 0| // It's common for the base to be an ancestor, so try that first. 487| 0| if pathComps.starts(with: baseComps) { 488| 0| // Special case, which is a plain path without `..` components. It 489| 0| // might be an empty path (when self and the base are equal). 490| 0| let relComps = pathComps.dropFirst(baseComps.count) 491| 0| result = RelativePath(relComps.joined(separator: "/")) 492| 0| } else { 493| 0| // General case, in which we might well need `..` components to go 494| 0| // "up" before we can go "down" the directory tree. 495| 0| var newPathComps = ArraySlice(pathComps) 496| 0| var newBaseComps = ArraySlice(baseComps) 497| 0| while newPathComps.prefix(1) == newBaseComps.prefix(1) { 498| 0| // First component matches, so drop it. 499| 0| newPathComps = newPathComps.dropFirst() 500| 0| newBaseComps = newBaseComps.dropFirst() 501| 0| } 502| 0| // Now construct a path consisting of as many `..`s as are in the 503| 0| // `newBaseComps` followed by what remains in `newPathComps`. 504| 0| var relComps = Array(repeating: "..", count: newBaseComps.count) 505| 0| relComps.append(contentsOf: newPathComps) 506| 0| result = RelativePath(relComps.joined(separator: "/")) 507| 0| } 508| 0| assert(base.appending(result) == self) 509| 0| return result 510| 0| } 511| | 512| | /// Returns true if the path contains the given path. 513| | /// 514| | /// This method is strictly syntactic and does not access the file system 515| | /// in any way. 516| 0| public func contains(_ other: AbsolutePath) -> Bool { 517| 0| return self.components.starts(with: other.components) 518| 0| } 519| | 520| |} 521| | 522| |// FIXME: We should consider whether to merge the two `normalize()` functions. 523| |// The argument for doing so is that some of the code is repeated; the argument 524| |// against doing so is that some of the details are different, and since any 525| |// given path is either absolute or relative, it's wasteful to keep checking 526| |// for whether it's relative or absolute. Possibly we can do both by clever 527| |// use of generics that abstract away the differences. 528| | 529| |/// Private function that normalizes and returns an absolute string. Asserts 530| |/// that `string` starts with a path separator. 531| |/// 532| |/// The normalization rules are as described for the AbsolutePath struct. 533| 0|private func normalize(absolute string: String) -> String { 534| 0| precondition(string.first == "/", "Failure normalizing \(string), absolute paths should start with '/'") 535| 0| 536| 0| // At this point we expect to have a path separator as first character. 537| 0| assert(string.first == "/") 538| 0| 539| 0| // FIXME: Here we should also keep track of whether anything actually has 540| 0| // to be changed in the string, and if not, just return the existing one. 541| 0| 542| 0| // Split the character array into parts, folding components as we go. 543| 0| // As we do so, we count the number of characters we'll end up with in 544| 0| // the normalized string representation. 545| 0| var parts: [String] = [] 546| 0| var capacity = 0 547| 0| for part in string.split(separator: "/") { 548| 0| switch part.count { 549| 0| case 0: 550| 0| // Ignore empty path components. 551| 0| continue 552| 0| case 1 where part.first == ".": 553| 0| // Ignore `.` path components. 554| 0| continue 555| 0| case 2 where part.first == "." && part.last == ".": 556| 0| // If there's a previous part, drop it; otherwise, do nothing. 557| 0| if let prev = parts.last { 558| 0| parts.removeLast() 559| 0| capacity -= prev.count 560| 0| } 561| 0| default: 562| 0| // Any other component gets appended. 563| 0| parts.append(String(part)) 564| 0| capacity += part.count 565| 0| } 566| 0| } 567| 0| capacity += max(parts.count, 1) 568| 0| 569| 0| // Create an output buffer using the capacity we've calculated. 570| 0| // FIXME: Determine the most efficient way to reassemble a string. 571| 0| var result = "" 572| 0| result.reserveCapacity(capacity) 573| 0| 574| 0| // Put the normalized parts back together again. 575| 0| var iter = parts.makeIterator() 576| 0| result.append("/") 577| 0| if let first = iter.next() { 578| 0| result.append(contentsOf: first) 579| 0| while let next = iter.next() { 580| 0| result.append("/") 581| 0| result.append(contentsOf: next) 582| 0| } 583| 0| } 584| 0| 585| 0| // Sanity-check the result (including the capacity we reserved). 586| 0| assert(!result.isEmpty, "unexpected empty string") 587| 0| assert(result.count == capacity, "count: " + 588| 0| "\(result.count), cap: \(capacity)") 589| 0| 590| 0| // Use the result as our stored string. 591| 0| return result 592| 0|} 593| | 594| |/// Private function that normalizes and returns a relative string. Asserts 595| |/// that `string` does not start with a path separator. 596| |/// 597| |/// The normalization rules are as described for the AbsolutePath struct. 598| 0|private func normalize(relative string: String) -> String { 599| 0| precondition(string.first != "/") 600| 0| 601| 0| // FIXME: Here we should also keep track of whether anything actually has 602| 0| // to be changed in the string, and if not, just return the existing one. 603| 0| 604| 0| // Split the character array into parts, folding components as we go. 605| 0| // As we do so, we count the number of characters we'll end up with in 606| 0| // the normalized string representation. 607| 0| var parts: [String] = [] 608| 0| var capacity = 0 609| 0| for part in string.split(separator: "/") { 610| 0| switch part.count { 611| 0| case 0: 612| 0| // Ignore empty path components. 613| 0| continue 614| 0| case 1 where part.first == ".": 615| 0| // Ignore `.` path components. 616| 0| continue 617| 0| case 2 where part.first == "." && part.last == ".": 618| 0| // If at beginning, fall through to treat the `..` literally. 619| 0| guard let prev = parts.last else { 620| 0| fallthrough 621| 0| } 622| 0| // If previous component is anything other than `..`, drop it. 623| 0| if !(prev.count == 2 && prev.first == "." && prev.last == ".") { 624| 0| parts.removeLast() 625| 0| capacity -= prev.count 626| 0| continue 627| 0| } 628| 0| // Otherwise, fall through to treat the `..` literally. 629| 0| fallthrough 630| 0| default: 631| 0| // Any other component gets appended. 632| 0| parts.append(String(part)) 633| 0| capacity += part.count 634| 0| } 635| 0| } 636| 0| capacity += max(parts.count - 1, 0) 637| 0| 638| 0| // Create an output buffer using the capacity we've calculated. 639| 0| // FIXME: Determine the most efficient way to reassemble a string. 640| 0| var result = "" 641| 0| result.reserveCapacity(capacity) 642| 0| 643| 0| // Put the normalized parts back together again. 644| 0| var iter = parts.makeIterator() 645| 0| if let first = iter.next() { 646| 0| result.append(contentsOf: first) 647| 0| while let next = iter.next() { 648| 0| result.append("/") 649| 0| result.append(contentsOf: next) 650| 0| } 651| 0| } 652| 0| 653| 0| // Sanity-check the result (including the capacity we reserved). 654| 0| assert(result.count == capacity, "count: " + 655| 0| "\(result.count), cap: \(capacity)") 656| 0| 657| 0| // If the result is empty, return `.`, otherwise we return it as a string. 658| 0| return result.isEmpty ? "." : result 659| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/PathShims.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | ------------------------------------------------------------------------- 10| | 11| | This file contains temporary shim functions for use during the adoption of 12| | AbsolutePath and RelativePath. The eventual plan is to use the FileSystem 13| | API for all of this, at which time this file will go way. But since it is 14| | important to have a quality FileSystem API, we will evolve it slowly. 15| | 16| | Meanwhile this file bridges the gap to let call sites be as clean as possible, 17| | while making it fairly easy to find those calls later. 18| |*/ 19| | 20| |import SPMLibc 21| |import POSIX 22| |import Foundation 23| | 24| |/// Returns a structure containing information about the file system entity at `path`, or nil 25| |/// if that path doesn't exist in the file system. Read, write or execute permission of the 26| |/// file system entity at `path` itself is not required, but all ancestor directories must be searchable. 27| |/// If they are not, or if any other file system error occurs, this function throws a SystemError. 28| |/// If `followSymlink` is true and the file system entity at `path` is a symbolic link, it is traversed; 29| |/// otherwise it is not (any symbolic links in path components other than the last one are always traversed). 30| |/// If symbolic links are followed and the file system entity at `path` is a symbolic link that points to a 31| |/// non-existent path, then this function returns nil. 32| 0|func stat(_ path: AbsolutePath, followSymlink: Bool = true) throws -> SPMLibc.stat { 33| 0| if followSymlink { 34| 0| return try stat(path.pathString) 35| 0| } 36| 0| return try lstat(path.pathString) 37| 0|} 38| | 39| |/// Returns true if and only if `path` refers to an existent file system entity. 40| |/// If `followSymlink` is true, and the last path component is a symbolic link, the result pertains 41| |/// to the destination of the symlink; otherwise it pertains to the symlink itself. 42| |/// If any file system error other than non-existence occurs, this function throws an error. 43| 0|public func exists(_ path: AbsolutePath, followSymlink: Bool = true) -> Bool { 44| 0| return (try? stat(path, followSymlink: followSymlink)) != nil 45| 0|} 46| | 47| |/// Returns true if and only if `path` refers to an existent file system entity and that entity is a regular file. 48| |/// If `followSymlink` is true, and the last path component is a symbolic link, the result pertains to the destination 49| |/// of the symlink; otherwise it pertains to the symlink itself. If any file system error other than non-existence 50| |/// occurs, this function throws an error. 51| 0|public func isFile(_ path: AbsolutePath, followSymlink: Bool = true) -> Bool { 52| 0| guard let status = try? stat(path, followSymlink: followSymlink), status.st_mode & S_IFMT == S_IFREG else { 53| 0| return false 54| 0| } 55| 0| return true 56| 0|} 57| | 58| |/// Returns true if and only if `path` refers to an existent file system entity and that entity is a directory. 59| |/// If `followSymlink` is true, and the last path component is a symbolic link, the result pertains to the destination 60| |/// of the symlink; otherwise it pertains to the symlink itself. If any file system error other than non-existence 61| |/// occurs, this function throws an error. 62| 0|public func isDirectory(_ path: AbsolutePath, followSymlink: Bool = true) -> Bool { 63| 0| guard let status = try? stat(path, followSymlink: followSymlink), status.st_mode & S_IFMT == S_IFDIR else { 64| 0| return false 65| 0| } 66| 0| return true 67| 0|} 68| | 69| |/// Returns true if and only if `path` refers to an existent file system entity and that entity is a symbolic link. 70| |/// If any file system error other than non-existence occurs, this function throws an error. 71| 0|public func isSymlink(_ path: AbsolutePath) -> Bool { 72| 0| guard let status = try? stat(path, followSymlink: false), status.st_mode & S_IFMT == S_IFLNK else { 73| 0| return false 74| 0| } 75| 0| return true 76| 0|} 77| | 78| |/// Returns the "real path" corresponding to `path` by resolving any symbolic links. 79| 0|public func resolveSymlinks(_ path: AbsolutePath) -> AbsolutePath { 80| 0| let pathStr = path.pathString 81| 0| guard let resolvedPathStr = try? POSIX.realpath(pathStr) else { return path } 82| 0| // FIXME: We should measure if it's really more efficient to compare the strings first. 83| 0| return (resolvedPathStr == pathStr) ? path : AbsolutePath(resolvedPathStr) 84| 0|} 85| | 86| |/// Creates a new, empty directory at `path`. If needed, any non-existent ancestor paths are also created. If there is 87| |/// already a directory at `path`, this function does nothing (in particular, this is not considered to be an error). 88| 0|public func makeDirectories(_ path: AbsolutePath) throws { 89| 0| try FileManager.default.createDirectory(atPath: path.pathString, withIntermediateDirectories: true, attributes: [:]) 90| 0|} 91| | 92| |/// Creates a symbolic link at `path` whose content points to `dest`. If `relative` is true, the symlink contents will 93| |/// be a relative path, otherwise it will be absolute. 94| 0|public func createSymlink(_ path: AbsolutePath, pointingAt dest: AbsolutePath, relative: Bool = true) throws { 95| 0| let destString = relative ? dest.relative(to: path.parentDirectory).pathString : dest.pathString 96| 0| let rv = SPMLibc.symlink(destString, path.pathString) 97| 0| guard rv == 0 else { throw SystemError.symlink(errno, path.pathString, dest: destString) } 98| 0|} 99| | 100| |/// The current working directory of the processs. 101| |@available(*, deprecated, renamed: "localFileSystem.currentWorkingDirectory") 102| 0|public var currentWorkingDirectory: AbsolutePath { 103| 0| let cwdStr = FileManager.default.currentDirectoryPath 104| 0| return AbsolutePath(cwdStr) 105| 0|} 106| | 107| |/** 108| | - Returns: a generator that walks the specified directory producing all 109| | files therein. If recursively is true will enter any directories 110| | encountered recursively. 111| | 112| | - Warning: directories that cannot be entered due to permission problems 113| | are silently ignored. So keep that in mind. 114| | 115| | - Warning: Symbolic links that point to directories are *not* followed. 116| | 117| | - Note: setting recursively to `false` still causes the generator to feed 118| | you the directory; just not its contents. 119| | */ 120| |public func walk( 121| | _ path: AbsolutePath, 122| | fileSystem: FileSystem = localFileSystem, 123| | recursively: Bool = true 124| 0|) throws -> RecursibleDirectoryContentsGenerator { 125| 0| return try RecursibleDirectoryContentsGenerator( 126| 0| path: path, 127| 0| fileSystem: fileSystem, 128| 0| recursionFilter: { _ in recursively }) 129| 0|} 130| | 131| |/** 132| | - Returns: a generator that walks the specified directory producing all 133| | files therein. Directories are recursed based on the return value of 134| | `recursing`. 135| | 136| | - Warning: directories that cannot be entered due to permissions problems 137| | are silently ignored. So keep that in mind. 138| | 139| | - Warning: Symbolic links that point to directories are *not* followed. 140| | 141| | - Note: returning `false` from `recursing` still produces that directory 142| | from the generator; just not its contents. 143| | */ 144| |public func walk( 145| | _ path: AbsolutePath, 146| | fileSystem: FileSystem = localFileSystem, 147| | recursing: @escaping (AbsolutePath) -> Bool 148| 0|) throws -> RecursibleDirectoryContentsGenerator { 149| 0| return try RecursibleDirectoryContentsGenerator(path: path, fileSystem: fileSystem, recursionFilter: recursing) 150| 0|} 151| | 152| |/** 153| | Produced by `walk`. 154| | */ 155| |public class RecursibleDirectoryContentsGenerator: IteratorProtocol, Sequence { 156| | private var current: (path: AbsolutePath, iterator: IndexingIterator<[String]>) 157| | private var towalk = [AbsolutePath]() 158| | 159| | private let shouldRecurse: (AbsolutePath) -> Bool 160| | private let fileSystem: FileSystem 161| | 162| | fileprivate init( 163| | path: AbsolutePath, 164| | fileSystem: FileSystem, 165| | recursionFilter: @escaping (AbsolutePath) -> Bool 166| 0| ) throws { 167| 0| self.fileSystem = fileSystem 168| 0| // FIXME: getDirectoryContents should have an iterator version. 169| 0| current = (path, try fileSystem.getDirectoryContents(path).makeIterator()) 170| 0| shouldRecurse = recursionFilter 171| 0| } 172| | 173| 0| public func next() -> AbsolutePath? { 174| 0| outer: while true { 175| 0| guard let entry = current.iterator.next() else { 176| 0| while !towalk.isEmpty { 177| 0| // FIXME: This looks inefficient. 178| 0| let path = towalk.removeFirst() 179| 0| guard shouldRecurse(path) else { continue } 180| 0| // Ignore if we can't get content for this path. 181| 0| guard let current = try? fileSystem.getDirectoryContents(path).makeIterator() else { continue } 182| 0| self.current = (path, current) 183| 0| continue outer 184| 0| } 185| 0| return nil 186| 0| } 187| 0| 188| 0| let path = current.path.appending(component: entry) 189| 0| if fileSystem.isDirectory(path) && !fileSystem.isSymlink(path) { 190| 0| towalk.append(path) 191| 0| } 192| 0| return path 193| 0| } 194| 0| } 195| |} 196| | 197| |extension AbsolutePath { 198| | /// Returns a path suitable for display to the user (if possible, it is made 199| | /// to be relative to the current working directory). 200| 0| public func prettyPath(cwd: AbsolutePath? = localFileSystem.currentWorkingDirectory) -> String { 201| 0| guard let dir = cwd else { 202| 0| // No current directory, display as is. 203| 0| return self.pathString 204| 0| } 205| 0| // FIXME: Instead of string prefix comparison we should add a proper API 206| 0| // to AbsolutePath to determine ancestry. 207| 0| if self == dir { 208| 0| return "." 209| 0| } else if self.pathString.hasPrefix(dir.pathString + "/") { 210| 0| return "./" + self.relative(to: dir).pathString 211| 0| } else { 212| 0| return self.pathString 213| 0| } 214| 0| } 215| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Process.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import class Foundation.ProcessInfo 12| | 13| |import enum POSIX.SystemError 14| |import func POSIX.getenv 15| |import SPMLibc 16| |import Dispatch 17| | 18| |/// Process result data which is available after process termination. 19| |public struct ProcessResult: CustomStringConvertible { 20| | 21| | public enum Error: Swift.Error { 22| | /// The output is not a valid UTF8 sequence. 23| | case illegalUTF8Sequence 24| | 25| | /// The process had a non zero exit. 26| | case nonZeroExit(ProcessResult) 27| | } 28| | 29| | public enum ExitStatus: Equatable { 30| | /// The process was terminated normally with a exit code. 31| | case terminated(code: Int32) 32| | 33| | /// The process was terminated due to a signal. 34| | case signalled(signal: Int32) 35| | } 36| | 37| | /// The arguments with which the process was launched. 38| | public let arguments: [String] 39| | 40| | /// The exit status of the process. 41| | public let exitStatus: ExitStatus 42| | 43| | /// The output bytes of the process. Available only if the process was 44| | /// asked to redirect its output and no stdout output closure was set. 45| | public let output: Result<[UInt8], AnyError> 46| | 47| | /// The output bytes of the process. Available only if the process was 48| | /// asked to redirect its output and no stderr output closure was set. 49| | public let stderrOutput: Result<[UInt8], AnyError> 50| | 51| | /// Create an instance using a POSIX process exit status code and output result. 52| | /// 53| | /// See `waitpid(2)` for information on the exit status code. 54| | public init( 55| | arguments: [String], 56| | exitStatusCode: Int32, 57| | output: Result<[UInt8], AnyError>, 58| | stderrOutput: Result<[UInt8], AnyError> 59| 0| ) { 60| 0| let exitStatus: ExitStatus 61| 0| if WIFSIGNALED(exitStatusCode) { 62| 0| exitStatus = .signalled(signal: WTERMSIG(exitStatusCode)) 63| 0| } else { 64| 0| precondition(WIFEXITED(exitStatusCode), "unexpected exit status \(exitStatusCode)") 65| 0| exitStatus = .terminated(code: WEXITSTATUS(exitStatusCode)) 66| 0| } 67| 0| self.init(arguments: arguments, exitStatus: exitStatus, output: output, 68| 0| stderrOutput: stderrOutput) 69| 0| } 70| | 71| | /// Create an instance using an exit status and output result. 72| | public init( 73| | arguments: [String], 74| | exitStatus: ExitStatus, 75| | output: Result<[UInt8], AnyError>, 76| | stderrOutput: Result<[UInt8], AnyError> 77| 0| ) { 78| 0| self.arguments = arguments 79| 0| self.output = output 80| 0| self.stderrOutput = stderrOutput 81| 0| self.exitStatus = exitStatus 82| 0| } 83| | 84| | /// Converts stdout output bytes to string, assuming they're UTF8. 85| 0| public func utf8Output() throws -> String { 86| 0| return String(decoding: try output.dematerialize(), as: Unicode.UTF8.self) 87| 0| } 88| | 89| | /// Converts stderr output bytes to string, assuming they're UTF8. 90| 0| public func utf8stderrOutput() throws -> String { 91| 0| return String(decoding: try stderrOutput.dematerialize(), as: Unicode.UTF8.self) 92| 0| } 93| | 94| 0| public var description: String { 95| 0| return """ 96| 0| 99| 0| """ 100| 0| } 101| |} 102| | 103| |/// Process allows spawning new subprocesses and working with them. 104| |/// 105| |/// Note: This class is thread safe. 106| |public final class Process: ObjectIdentifierProtocol { 107| | 108| | /// Errors when attempting to invoke a process 109| | public enum Error: Swift.Error { 110| | /// The program requested to be executed cannot be found on the existing search paths, or is not executable. 111| | case missingExecutableProgram(program: String) 112| | } 113| | 114| | public enum OutputRedirection { 115| | /// Do not redirect the output 116| | case none 117| | /// Collect stdout and stderr output and provide it back via ProcessResult object 118| | case collect 119| | /// Stream stdout and stderr via the corresponding closures 120| | case stream(stdout: OutputClosure, stderr: OutputClosure) 121| | 122| 0| public var redirectsOutput: Bool { 123| 0| switch self { 124| 0| case .none: 125| 0| return false 126| 0| case .collect, .stream: 127| 0| return true 128| 0| } 129| 0| } 130| | 131| 0| public var outputClosures: (stdoutClosure: OutputClosure, stderrClosure: OutputClosure)? { 132| 0| switch self { 133| 0| case .stream(let stdoutClosure, let stderrClosure): 134| 0| return (stdoutClosure: stdoutClosure, stderrClosure: stderrClosure) 135| 0| case .collect, .none: 136| 0| return nil 137| 0| } 138| 0| } 139| | } 140| | 141| | /// Typealias for process id type. 142| | public typealias ProcessID = pid_t 143| | 144| | /// Typealias for stdout/stderr output closure. 145| | public typealias OutputClosure = ([UInt8]) -> Void 146| | 147| | /// Global default setting for verbose. 148| | public static var verbose = false 149| | 150| | /// If true, prints the subprocess arguments before launching it. 151| | public let verbose: Bool 152| | 153| | /// The current environment. 154| 0| static public var env: [String: String] { 155| 0| return ProcessInfo.processInfo.environment 156| 0| } 157| | 158| | /// The arguments to execute. 159| | public let arguments: [String] 160| | 161| | /// The environment with which the process was executed. 162| | public let environment: [String: String] 163| | 164| | /// The process id of the spawned process, available after the process is launched. 165| | public private(set) var processID = ProcessID() 166| | 167| | /// If the subprocess has launched. 168| | /// Note: This property is not protected by the serial queue because it is only mutated in `launch()`, which will be 169| | /// called only once. 170| | public private(set) var launched = false 171| | 172| | /// The result of the process execution. Available after process is terminated. 173| 0| public var result: ProcessResult? { 174| 0| return self.serialQueue.sync { 175| 0| self._result 176| 0| } 177| 0| } 178| | 179| | /// How process redirects its output. 180| | public let outputRedirection: OutputRedirection 181| | 182| | /// The result of the process execution. Available after process is terminated. 183| | private var _result: ProcessResult? 184| | 185| | /// If redirected, stdout result and reference to the thread reading the output. 186| | private var stdout: (result: Result<[UInt8], AnyError>, thread: Thread?) = (Result([]), nil) 187| | 188| | /// If redirected, stderr result and reference to the thread reading the output. 189| | private var stderr: (result: Result<[UInt8], AnyError>, thread: Thread?) = (Result([]), nil) 190| | 191| | /// Queue to protect concurrent reads. 192| | private let serialQueue = DispatchQueue(label: "org.swift.swiftpm.process") 193| | 194| | /// Queue to protect reading/writing on map of validated executables. 195| | private static let executablesQueue = DispatchQueue( 196| | label: "org.swift.swiftpm.process.findExecutable") 197| | 198| | /// Indicates if a new progress group is created for the child process. 199| | private let startNewProcessGroup: Bool 200| | 201| | /// Cache of validated executables. 202| | /// 203| | /// Key: Executable name or path. 204| | /// Value: Path to the executable, if found. 205| | static private var validatedExecutablesMap = [String: AbsolutePath?]() 206| | 207| | /// Create a new process instance. 208| | /// 209| | /// - Parameters: 210| | /// - arguments: The arguments for the subprocess. 211| | /// - environment: The environment to pass to subprocess. By default the current process environment 212| | /// will be inherited. 213| | /// - outputRedirection: How process redirects its output. Default value is .collect. 214| | /// - verbose: If true, launch() will print the arguments of the subprocess before launching it. 215| | /// - startNewProcessGroup: If true, a new progress group is created for the child making it 216| | /// continue running even if the parent is killed or interrupted. Default value is true. 217| | public init( 218| | arguments: [String], 219| | environment: [String: String] = env, 220| | outputRedirection: OutputRedirection = .collect, 221| | verbose: Bool = Process.verbose, 222| | startNewProcessGroup: Bool = true 223| 0| ) { 224| 0| self.arguments = arguments 225| 0| self.environment = environment 226| 0| self.outputRedirection = outputRedirection 227| 0| self.verbose = verbose 228| 0| self.startNewProcessGroup = startNewProcessGroup 229| 0| } 230| | 231| | /// Returns the path of the the given program if found in the search paths. 232| | /// 233| | /// The program can be executable name, relative path or absolute path. 234| 0| public static func findExecutable(_ program: String) -> AbsolutePath? { 235| 0| return Process.executablesQueue.sync { 236| 0| // Check if we already have a value for the program. 237| 0| if let value = Process.validatedExecutablesMap[program] { 238| 0| return value 239| 0| } 240| 0| // FIXME: This can be cached. 241| 0| let envSearchPaths = getEnvSearchPaths( 242| 0| pathString: getenv("PATH"), 243| 0| currentWorkingDirectory: localFileSystem.currentWorkingDirectory 244| 0| ) 245| 0| // Lookup and cache the executable path. 246| 0| let value = lookupExecutablePath( 247| 0| filename: program, searchPaths: envSearchPaths) 248| 0| Process.validatedExecutablesMap[program] = value 249| 0| return value 250| 0| } 251| 0| } 252| | 253| | /// Launch the subprocess. 254| 0| public func launch() throws { 255| 0| precondition(arguments.count > 0 && !arguments[0].isEmpty, "Need at least one argument to launch the process.") 256| 0| precondition(!launched, "It is not allowed to launch the same process object again.") 257| 0| 258| 0| // Set the launch bool to true. 259| 0| launched = true 260| 0| 261| 0| // Print the arguments if we are verbose. 262| 0| if self.verbose { 263| 0| stdoutStream <<< arguments.map({ $0.spm_shellEscaped() }).joined(separator: " ") <<< "\n" 264| 0| stdoutStream.flush() 265| 0| } 266| 0| 267| 0| // Look for executable. 268| 0| guard Process.findExecutable(arguments[0]) != nil else { 269| 0| throw Process.Error.missingExecutableProgram(program: arguments[0]) 270| 0| } 271| 0| 272| 0| // Initialize the spawn attributes. 273| 0| #if os(macOS) 274| 0| var attributes: posix_spawnattr_t? = nil 275| 0| #else 276| 0| var attributes = posix_spawnattr_t() 277| 0| #endif 278| 0| posix_spawnattr_init(&attributes) 279| 0| defer { posix_spawnattr_destroy(&attributes) } 280| 0| 281| 0| // Unmask all signals. 282| 0| var noSignals = sigset_t() 283| 0| sigemptyset(&noSignals) 284| 0| posix_spawnattr_setsigmask(&attributes, &noSignals) 285| 0| 286| 0| // Reset all signals to default behavior. 287| 0| #if os(macOS) 288| 0| var mostSignals = sigset_t() 289| 0| sigfillset(&mostSignals) 290| 0| sigdelset(&mostSignals, SIGKILL) 291| 0| sigdelset(&mostSignals, SIGSTOP) 292| 0| posix_spawnattr_setsigdefault(&attributes, &mostSignals) 293| 0| #else 294| 0| // On Linux, this can only be used to reset signals that are legal to 295| 0| // modify, so we have to take care about the set we use. 296| 0| var mostSignals = sigset_t() 297| 0| sigemptyset(&mostSignals) 298| 0| for i in 1 ..< SIGSYS { 299| 0| if i == SIGKILL || i == SIGSTOP { 300| 0| continue 301| 0| } 302| 0| sigaddset(&mostSignals, i) 303| 0| } 304| 0| posix_spawnattr_setsigdefault(&attributes, &mostSignals) 305| 0| #endif 306| 0| 307| 0| // Set the attribute flags. 308| 0| var flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF 309| 0| if startNewProcessGroup { 310| 0| // Establish a separate process group. 311| 0| flags |= POSIX_SPAWN_SETPGROUP 312| 0| posix_spawnattr_setpgroup(&attributes, 0) 313| 0| } 314| 0| 315| 0| posix_spawnattr_setflags(&attributes, Int16(flags)) 316| 0| 317| 0| // Setup the file actions. 318| 0| #if os(macOS) 319| 0| var fileActions: posix_spawn_file_actions_t? = nil 320| 0| #else 321| 0| var fileActions = posix_spawn_file_actions_t() 322| 0| #endif 323| 0| posix_spawn_file_actions_init(&fileActions) 324| 0| defer { posix_spawn_file_actions_destroy(&fileActions) } 325| 0| 326| 0| // Workaround for https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=89e435f3559c53084498e9baad22172b64429362 327| 0| let devNull = strdup("/dev/null") 328| 0| defer { free(devNull) } 329| 0| // Open /dev/null as stdin. 330| 0| posix_spawn_file_actions_addopen(&fileActions, 0, devNull, O_RDONLY, 0) 331| 0| 332| 0| var outputPipe: [Int32] = [0, 0] 333| 0| var stderrPipe: [Int32] = [0, 0] 334| 0| if outputRedirection.redirectsOutput { 335| 0| // Open the pipes. 336| 0| try open(pipe: &outputPipe) 337| 0| try open(pipe: &stderrPipe) 338| 0| // Open the write end of the pipe as stdout and stderr, if desired. 339| 0| posix_spawn_file_actions_adddup2(&fileActions, outputPipe[1], 1) 340| 0| posix_spawn_file_actions_adddup2(&fileActions, stderrPipe[1], 2) 341| 0| // Close the other ends of the pipe. 342| 0| for pipe in [outputPipe, stderrPipe] { 343| 0| posix_spawn_file_actions_addclose(&fileActions, pipe[0]) 344| 0| posix_spawn_file_actions_addclose(&fileActions, pipe[1]) 345| 0| } 346| 0| } else { 347| 0| posix_spawn_file_actions_adddup2(&fileActions, 1, 1) 348| 0| posix_spawn_file_actions_adddup2(&fileActions, 2, 2) 349| 0| } 350| 0| 351| 0| let argv = CStringArray(arguments) 352| 0| let env = CStringArray(environment.map({ "\($0.0)=\($0.1)" })) 353| 0| let rv = posix_spawnp(&processID, argv.cArray[0], &fileActions, &attributes, argv.cArray, env.cArray) 354| 0| 355| 0| guard rv == 0 else { 356| 0| throw SystemError.posix_spawn(rv, arguments) 357| 0| } 358| 0| 359| 0| if outputRedirection.redirectsOutput { 360| 0| let outputClosures = outputRedirection.outputClosures 361| 0| 362| 0| // Close the write end of the output pipe. 363| 0| try close(fd: &outputPipe[1]) 364| 0| 365| 0| // Create a thread and start reading the output on it. 366| 0| var thread = Thread { [weak self] in 367| 0| if let readResult = self?.readOutput(onFD: outputPipe[0], outputClosure: outputClosures?.stdoutClosure) { 368| 0| self?.stdout.result = readResult 369| 0| } 370| 0| } 371| 0| thread.start() 372| 0| self.stdout.thread = thread 373| 0| 374| 0| // Close the write end of the stderr pipe. 375| 0| try close(fd: &stderrPipe[1]) 376| 0| 377| 0| // Create a thread and start reading the stderr output on it. 378| 0| thread = Thread { [weak self] in 379| 0| if let readResult = self?.readOutput(onFD: stderrPipe[0], outputClosure: outputClosures?.stderrClosure) { 380| 0| self?.stderr.result = readResult 381| 0| } 382| 0| } 383| 0| thread.start() 384| 0| self.stderr.thread = thread 385| 0| } 386| 0| } 387| | 388| | /// Blocks the calling process until the subprocess finishes execution. 389| | @discardableResult 390| 0| public func waitUntilExit() throws -> ProcessResult { 391| 0| return try serialQueue.sync { 392| 0| precondition(launched, "The process is not yet launched.") 393| 0| 394| 0| // If the process has already finsihed, return it. 395| 0| if let existingResult = _result { 396| 0| return existingResult 397| 0| } 398| 0| 399| 0| // If we're reading output, make sure that is finished. 400| 0| stdout.thread?.join() 401| 0| stderr.thread?.join() 402| 0| 403| 0| // Wait until process finishes execution. 404| 0| var exitStatusCode: Int32 = 0 405| 0| var result = waitpid(processID, &exitStatusCode, 0) 406| 0| while result == -1 && errno == EINTR { 407| 0| result = waitpid(processID, &exitStatusCode, 0) 408| 0| } 409| 0| if result == -1 { 410| 0| throw SystemError.waitpid(errno) 411| 0| } 412| 0| 413| 0| // Construct the result. 414| 0| let executionResult = ProcessResult( 415| 0| arguments: arguments, 416| 0| exitStatusCode: exitStatusCode, 417| 0| output: stdout.result, 418| 0| stderrOutput: stderr.result 419| 0| ) 420| 0| self._result = executionResult 421| 0| return executionResult 422| 0| } 423| 0| } 424| | 425| | /// Reads the given fd and returns its result. 426| | /// 427| | /// Closes the fd before returning. 428| 0| private func readOutput(onFD fd: Int32, outputClosure: OutputClosure?) -> Result<[UInt8], AnyError> { 429| 0| // Read all of the data from the output pipe. 430| 0| let N = 4096 431| 0| var buf = [UInt8](repeating: 0, count: N + 1) 432| 0| 433| 0| var out = [UInt8]() 434| 0| var error: Swift.Error? = nil 435| 0| loop: while true { 436| 0| let n = read(fd, &buf, N) 437| 0| switch n { 438| 0| case -1: 439| 0| if errno == EINTR { 440| 0| continue 441| 0| } else { 442| 0| error = SystemError.read(errno) 443| 0| break loop 444| 0| } 445| 0| case 0: 446| 0| break loop 447| 0| default: 448| 0| let data = buf[0.. ProcessResult { 481| 0| let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect) 482| 0| try process.launch() 483| 0| return try process.waitUntilExit() 484| 0| } 485| | 486| | @discardableResult 487| 0| static public func popen(args: String..., environment: [String: String] = env) throws -> ProcessResult { 488| 0| return try Process.popen(arguments: args, environment: environment) 489| 0| } 490| | 491| | /// Execute a subprocess and get its (UTF-8) output if it has a non zero exit. 492| | /// 493| | /// - Parameters: 494| | /// - arguments: The arguments for the subprocess. 495| | /// - environment: The environment to pass to subprocess. By default the current process environment 496| | /// will be inherited. 497| | /// - Returns: The process output (stdout + stderr). 498| | @discardableResult 499| 0| static public func checkNonZeroExit(arguments: [String], environment: [String: String] = env) throws -> String { 500| 0| let process = Process(arguments: arguments, environment: environment, outputRedirection: .collect) 501| 0| try process.launch() 502| 0| let result = try process.waitUntilExit() 503| 0| // Throw if there was a non zero termination. 504| 0| guard result.exitStatus == .terminated(code: 0) else { 505| 0| throw ProcessResult.Error.nonZeroExit(result) 506| 0| } 507| 0| return try result.utf8Output() 508| 0| } 509| | 510| | @discardableResult 511| 0| static public func checkNonZeroExit(args: String..., environment: [String: String] = env) throws -> String { 512| 0| return try checkNonZeroExit(arguments: args, environment: environment) 513| 0| } 514| | 515| 0| public convenience init(args: String..., environment: [String: String] = env, outputRedirection: OutputRedirection = .collect) { 516| 0| self.init(arguments: args, environment: environment, outputRedirection: outputRedirection) 517| 0| } 518| |} 519| | 520| |// MARK: - Private helpers 521| | 522| |#if os(macOS) 523| |private typealias swiftpm_posix_spawn_file_actions_t = posix_spawn_file_actions_t? 524| |#else 525| |private typealias swiftpm_posix_spawn_file_actions_t = posix_spawn_file_actions_t 526| |#endif 527| | 528| 0|private func WIFEXITED(_ status: Int32) -> Bool { 529| 0| return _WSTATUS(status) == 0 530| 0|} 531| | 532| 0|private func _WSTATUS(_ status: Int32) -> Int32 { 533| 0| return status & 0x7f 534| 0|} 535| | 536| 0|private func WIFSIGNALED(_ status: Int32) -> Bool { 537| 0| return (_WSTATUS(status) != 0) && (_WSTATUS(status) != 0x7f) 538| 0|} 539| | 540| 0|private func WEXITSTATUS(_ status: Int32) -> Int32 { 541| 0| return (status >> 8) & 0xff 542| 0|} 543| | 544| 0|private func WTERMSIG(_ status: Int32) -> Int32 { 545| 0| return status & 0x7f 546| 0|} 547| | 548| |/// Open the given pipe. 549| 0|private func open(pipe: inout [Int32]) throws { 550| 0| let rv = SPMLibc.pipe(&pipe) 551| 0| guard rv == 0 else { 552| 0| throw SystemError.pipe(rv) 553| 0| } 554| 0|} 555| | 556| |/// Close the given fd. 557| 0|private func close(fd: inout Int32) throws { 558| 0| let rv = SPMLibc.close(fd) 559| 0| guard rv == 0 else { 560| 0| throw SystemError.close(rv) 561| 0| } 562| 0|} 563| | 564| |extension Process.Error: CustomStringConvertible { 565| 0| public var description: String { 566| 0| switch self { 567| 0| case .missingExecutableProgram(let program): 568| 0| return "could not find executable for '\(program)'" 569| 0| } 570| 0| } 571| |} 572| | 573| |extension ProcessResult.Error: CustomStringConvertible { 574| 0| public var description: String { 575| 0| switch self { 576| 0| case .illegalUTF8Sequence: 577| 0| return "illegal UTF8 sequence output" 578| 0| case .nonZeroExit(let result): 579| 0| let stream = BufferedOutputByteStream() 580| 0| switch result.exitStatus { 581| 0| case .terminated(let code): 582| 0| stream <<< "terminated(\(code)): " 583| 0| 584| 0| case .signalled(let signal): 585| 0| stream <<< "signalled(\(signal)): " 586| 0| } 587| 0| 588| 0| // Strip sandbox information from arguments to keep things pretty. 589| 0| var args = result.arguments 590| 0| // This seems a little fragile. 591| 0| if args.first == "sandbox-exec", args.count > 3 { 592| 0| args = args.suffix(from: 3).map({$0}) 593| 0| } 594| 0| stream <<< args.map({ $0.spm_shellEscaped() }).joined(separator: " ") 595| 0| 596| 0| // Include the output, if present. 597| 0| if let output = try? result.utf8Output() + result.utf8stderrOutput() { 598| 0| // We indent the output to keep it visually separated from everything else. 599| 0| let indentation = " " 600| 0| stream <<< " output:\n" <<< indentation <<< output.replacingOccurrences(of: "\n", with: "\n" + indentation) 601| 0| if !output.hasSuffix("\n") { 602| 0| stream <<< "\n" 603| 0| } 604| 0| } 605| 0| 606| 0| return stream.bytes.description 607| 0| } 608| 0| } 609| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/ProcessSet.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Dispatch 12| |import Foundation 13| | 14| |public enum ProcessSetError: Swift.Error { 15| | /// The process group was cancelled and doesn't allow adding more processes. 16| | case cancelled 17| |} 18| | 19| |/// A process set is a small wrapper for collection of processes. 20| |/// 21| |/// This class is thread safe. 22| |public final class ProcessSet { 23| | 24| | /// Array to hold the processes. 25| | private var processes: Set = [] 26| | 27| | /// Queue to mutate internal states of the process group. 28| | private let serialQueue = DispatchQueue(label: "org.swift.swiftpm.process-set") 29| | 30| | /// If the process group was asked to cancel all active processes. 31| | private var cancelled = false 32| | 33| | /// The timeout (in seconds) after which the processes should be killed if they don't respond to SIGINT. 34| | public let killTimeout: Double 35| | 36| | /// Condition to block kill thread until timeout. 37| | private var killingCondition = Condition() 38| | 39| | /// Boolean predicate for killing condition. 40| | private var shouldKill = false 41| | 42| | /// Create a process set. 43| 0| public init(killTimeout: Double = 5) { 44| 0| self.killTimeout = killTimeout 45| 0| } 46| | 47| | /// Add a process to the process set. This method will throw if the process set is terminated using the terminate() 48| | /// method. 49| | /// 50| | /// Call remove() method to remove the process from set once it has terminated. 51| | /// 52| | /// - Parameters: 53| | /// - process: The process to add. 54| | /// - Throws: ProcessGroupError 55| 0| public func add(_ process: Basic.Process) throws { 56| 0| return try serialQueue.sync { 57| 0| guard !cancelled else { 58| 0| throw ProcessSetError.cancelled 59| 0| } 60| 0| self.processes.insert(process) 61| 0| } 62| 0| } 63| | 64| | /// Terminate all the processes. This method blocks until all processes in the set are terminated. 65| | /// 66| | /// A process set cannot be used once it has been asked to terminate. 67| 0| public func terminate() { 68| 0| // Mark a process set as cancelled. 69| 0| serialQueue.sync { 70| 0| cancelled = true 71| 0| } 72| 0| 73| 0| // Interrupt all processes. 74| 0| signalAll(SIGINT) 75| 0| 76| 0| // Create a thread that will kill all processes after a timeout. 77| 0| let thread = Basic.Thread { 78| 0| // Compute the timeout date. 79| 0| let timeout = Date() + self.killTimeout 80| 0| // Block until we timeout or notification. 81| 0| self.killingCondition.whileLocked { 82| 0| while !self.shouldKill { 83| 0| // Block until timeout expires. 84| 0| let timeLimitReached = !self.killingCondition.wait(until: timeout) 85| 0| // Set should kill to true if time limit was reached. 86| 0| if timeLimitReached { 87| 0| self.shouldKill = true 88| 0| } 89| 0| } 90| 0| } 91| 0| // Send kill signal to all processes. 92| 0| self.signalAll(SIGKILL) 93| 0| } 94| 0| 95| 0| thread.start() 96| 0| 97| 0| // Wait until all processes terminate and notify the kill thread 98| 0| // if everyone exited to avoid waiting till timeout. 99| 0| for process in self.processes { 100| 0| _ = try? process.waitUntilExit() 101| 0| } 102| 0| killingCondition.whileLocked { 103| 0| shouldKill = true 104| 0| killingCondition.signal() 105| 0| } 106| 0| 107| 0| // Join the kill thread so we don't exit before everything terminates. 108| 0| thread.join() 109| 0| } 110| | 111| | /// Sends signal to all processes in the set. 112| 0| private func signalAll(_ signal: Int32) { 113| 0| serialQueue.sync { 114| 0| // Signal all active processes. 115| 0| for process in self.processes { 116| 0| process.signal(signal) 117| 0| } 118| 0| } 119| 0| } 120| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/RegEx.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Foundation 12| | 13| |/// A helpful wrapper around NSRegularExpression. 14| |/// - SeeAlso: NSRegularExpression 15| |public struct RegEx { 16| | private let regex: NSRegularExpression 17| | public typealias Options = NSRegularExpression.Options 18| | 19| | /// Creates a new Regex using `pattern`. 20| | /// 21| | /// - Parameters: 22| | /// - pattern: A valid Regular Expression pattern 23| | /// - options: NSRegularExpression.Options on how the RegEx should be processed. 24| | /// - Note: Deliminators must be double escaped. Once for Swift and once for RegEx. 25| | /// Example, to math a negative integer: `RegEx(pattern: "-\d")` -> `RegEx(pattern: "-\\d")` 26| | /// - SeeAlso: NSRegularExpression 27| | /// - Throws: An Error if `pattern` is an invalid Regular Expression. 28| 0| public init(pattern: String, options: Options = []) throws { 29| 0| self.regex = try NSRegularExpression(pattern: pattern, options: options) 30| 0| } 31| | 32| | /// Returns match groups for every match of the Regex. 33| | /// 34| | /// For every match in the string, it constructs the collection 35| | /// of groups matched. 36| | /// 37| | /// RegEx(pattern: "([a-z]+)([0-9]+)").matchGroups(in: "foo1 bar2 baz3") 38| | /// 39| | /// Returns `[["foo", "1"], ["bar", "2"], ["baz", "3"]]`. 40| | /// 41| | /// - Parameters: 42| | /// - in: A string to check for matches to the whole Regex. 43| | /// - Returns: A collection where each elements is the collection of matched groups. 44| 0| public func matchGroups(in string: String) -> [[String]] { 45| 0| let nsString = NSString(string: string) 46| 0| 47| 0| return regex.matches(in: string, options: [], range: NSMakeRange(0, nsString.length)).map{ match -> [String] in 48| 0| return (1 ..< match.numberOfRanges).map { idx -> String in 49| 0| let range = match.range(at: idx) 50| 0| return range.location == NSNotFound ? "" : nsString.substring(with: range) 51| 0| } 52| 0| } 53| 0| } 54| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Result.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// An simple enum which is either a value or an error. 12| |/// It can be used for error handling in situations where try catch is 13| |/// problematic to use, for eg: asynchronous APIs. 14| |public enum Result { 15| | /// Indicates success with value in the associated object. 16| | case success(Value) 17| | 18| | /// Indicates failure with error inside the associated object. 19| | case failure(ErrorType) 20| | 21| | /// Initialiser for value. 22| 0| public init(_ value: Value) { 23| 0| self = .success(value) 24| 0| } 25| | 26| | /// Initialiser for error. 27| 0| public init(_ error: ErrorType) { 28| 0| self = .failure(error) 29| 0| } 30| | 31| | /// Initialise with something that can throw ErrorType. 32| 0| public init(_ body: () throws -> Value) throws { 33| 0| do { 34| 0| self = .success(try body()) 35| 0| } catch let error as ErrorType { 36| 0| self = .failure(error) 37| 0| } 38| 0| } 39| | 40| | /// Get the value if success else throw the saved error. 41| 0| public func dematerialize() throws -> Value { 42| 0| switch self { 43| 0| case .success(let value): 44| 0| return value 45| 0| case .failure(let error): 46| 0| throw error 47| 0| } 48| 0| } 49| | 50| | /// Evaluates the given closure when this Result instance has a value. 51| 0| public func map(_ transform: (Value) throws -> U) rethrows -> Result { 52| 0| switch self { 53| 0| case .success(let value): 54| 0| return Result(try transform(value)) 55| 0| case .failure(let error): 56| 0| return Result(error) 57| 0| } 58| 0| } 59| | 60| | /// Evaluates the given closure when this Result instance has a value, passing the unwrapped value as a parameter. 61| | /// 62| | /// The closure returns a Result instance itself which can have value or not. 63| 0| public func flatMap(_ transform: (Value) -> Result) -> Result { 64| 0| switch self { 65| 0| case .success(let value): 66| 0| return transform(value) 67| 0| case .failure(let error): 68| 0| return Result(error) 69| 0| } 70| 0| } 71| | 72| |} 73| | 74| |extension Result: CustomStringConvertible { 75| 0| public var description: String { 76| 0| switch self { 77| 0| case .success(let value): 78| 0| return "Result(\(value))" 79| 0| case .failure(let error): 80| 0| return "Result(\(error))" 81| 0| } 82| 0| } 83| |} 84| | 85| |/// A type erased error enum. 86| |public struct AnyError: Swift.Error, CustomStringConvertible { 87| | /// The underlying error. 88| | public let underlyingError: Swift.Error 89| | 90| 0| public init(_ error: Swift.Error) { 91| 0| // If we already have any error, don't nest it. 92| 0| if case let error as AnyError = error { 93| 0| self = error 94| 0| } else { 95| 0| self.underlyingError = error 96| 0| } 97| 0| } 98| | 99| 0| public var description: String { 100| 0| return String(describing: underlyingError) 101| 0| } 102| |} 103| | 104| |/// Represents a string error. 105| |public struct StringError: Equatable, Codable, CustomStringConvertible, Error { 106| | 107| | /// The description of the error. 108| | public let description: String 109| | 110| | /// Create an instance of StringError. 111| 0| public init(_ description: String) { 112| 0| self.description = description 113| 0| } 114| |} 115| | 116| |// AnyError specific helpers. 117| |extension Result where ErrorType == AnyError { 118| | /// Initialise with something that throws AnyError. 119| 0| public init(anyError body: () throws -> Value) { 120| 0| do { 121| 0| self = .success(try body()) 122| 0| } catch { 123| 0| self = .failure(AnyError(error)) 124| 0| } 125| 0| } 126| | 127| | /// Initialise with an error, it will be automatically converted to AnyError. 128| 0| public init(_ error: Swift.Error) { 129| 0| self = .failure(AnyError(error)) 130| 0| } 131| | 132| | /// Evaluates the given throwing closure when this Result instance has a value. 133| | /// 134| | /// The final result will either be the transformed value or any error thrown by the closure. 135| 0| public func mapAny(_ transform: (Value) throws -> U) -> Result { 136| 0| switch self { 137| 0| case .success(let value): 138| 0| do { 139| 0| return Result(try transform(value)) 140| 0| } catch { 141| 0| return Result(error) 142| 0| } 143| 0| case .failure(let error): 144| 0| return Result(error) 145| 0| } 146| 0| } 147| |} 148| | 149| |extension Result where ErrorType == StringError { 150| | /// Create an instance of Result. 151| | /// 152| | /// Errors will be encoded as StringError using their description. 153| 0| public init(string body: () throws -> Value) { 154| 0| do { 155| 0| self = .success(try body()) 156| 0| } catch let error as StringError { 157| 0| self = .failure(error) 158| 0| } catch { 159| 0| self = .failure(StringError(String(describing: error))) 160| 0| } 161| 0| } 162| |} 163| | 164| |extension Result: Equatable where Value: Equatable, ErrorType: Equatable {} 165| | 166| |extension Result: Codable where Value: Codable, ErrorType: Codable { 167| | private enum CodingKeys: String, CodingKey { 168| | case success, failure 169| | } 170| | 171| 0| public func encode(to encoder: Encoder) throws { 172| 0| var container = encoder.container(keyedBy: CodingKeys.self) 173| 0| switch self { 174| 0| case .success(let value): 175| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .success) 176| 0| try unkeyedContainer.encode(value) 177| 0| case .failure(let error): 178| 0| var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .failure) 179| 0| try unkeyedContainer.encode(error) 180| 0| } 181| 0| } 182| | 183| 0| public init(from decoder: Decoder) throws { 184| 0| let values = try decoder.container(keyedBy: CodingKeys.self) 185| 0| guard let key = values.allKeys.first(where: values.contains) else { 186| 0| throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Did not find a matching key")) 187| 0| } 188| 0| switch key { 189| 0| case .success: 190| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 191| 0| let value = try unkeyedValues.decode(Value.self) 192| 0| self = .success(value) 193| 0| case .failure: 194| 0| var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key) 195| 0| let error = try unkeyedValues.decode(ErrorType.self) 196| 0| self = .failure(error) 197| 0| } 198| 0| } 199| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/SHA256.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// SHA-256 implementation from Secure Hash Algorithm 2 (SHA-2) set of 12| |/// cryptographic hash functions (FIPS PUB 180-2). 13| |public final class SHA256 { 14| | 15| | /// The length of the output digest (in bits). 16| | let digestLength = 256 17| | 18| | /// The size of each blocks (in bits). 19| | let blockBitSize = 512 20| | 21| | /// The initial hash value. 22| | private static let initalHashValue: [UInt32] = [ 23| | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 24| | ] 25| | 26| | /// The constants in the algorithm (K). 27| | private static let konstants: [UInt32] = [ 28| | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 29| | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 30| | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 31| | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 32| | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 33| | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 34| | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 35| | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 36| | ] 37| | 38| | /// The hash that is being computed. 39| | private var hash = SHA256.initalHashValue 40| | 41| | /// The input that was provided. It will be padded when computing the digest. 42| | private var input: [UInt8] 43| | 44| | /// The result, once computed. 45| | private var result: [UInt8]? 46| | 47| 0| public init(_ input: [UInt8]) { 48| 0| self.input = input 49| 0| } 50| | 51| 0| public init(_ bytes: ByteString) { 52| 0| self.input = bytes.contents 53| 0| } 54| | 55| 0| public init(_ string: String) { 56| 0| self.input = [UInt8](string.utf8) 57| 0| } 58| | 59| | /// Returns the digest as hexadecimal string. 60| 0| public func digestString() -> String { 61| 0| return digest().reduce("") { 62| 0| var str = String($1, radix: 16) 63| 0| // The above method does not do zero padding. 64| 0| if str.count == 1 { 65| 0| str = "0" + str 66| 0| } 67| 0| return $0 + str 68| 0| } 69| 0| } 70| | 71| | /// Returns the digest. 72| 0| public func digest() -> [UInt8] { 73| 0| 74| 0| // If we already have the result, we're done. 75| 0| if let result = self.result { 76| 0| return result 77| 0| } 78| 0| 79| 0| // Pad the input. 80| 0| pad(&input) 81| 0| 82| 0| // Break the input into N 512-bit blocks. 83| 0| let messageBlocks = input.blocks(size: blockBitSize / 8) 84| 0| 85| 0| // Process each block. 86| 0| for block in messageBlocks { 87| 0| process(block) 88| 0| } 89| 0| 90| 0| // Finally, compute the result. 91| 0| var result = [UInt8](repeating: 0, count: digestLength / 8) 92| 0| for (idx, element) in hash.enumerated() { 93| 0| let pos = idx * 4 94| 0| result[pos + 0] = UInt8((element >> 24) & 0xff) 95| 0| result[pos + 1] = UInt8((element >> 16) & 0xff) 96| 0| result[pos + 2] = UInt8((element >> 8) & 0xff) 97| 0| result[pos + 3] = UInt8(element & 0xff) 98| 0| } 99| 0| 100| 0| self.result = result 101| 0| return result 102| 0| } 103| | 104| | /// Process and compute hash from a block. 105| 0| private func process(_ block: ArraySlice) { 106| 0| 107| 0| // Compute message schedule. 108| 0| var W = [UInt32](repeating: 0, count: SHA256.konstants.count) 109| 0| for t in 0..> 10) 120| 0| let σ0 = W[t-15].rotateRight(by: 7) ^ W[t-15].rotateRight(by: 18) ^ (W[t-15] >> 3) 121| 0| W[t] = σ1 &+ W[t-7] &+ σ0 &+ W[t-16] 122| 0| } 123| 0| } 124| 0| 125| 0| var a = hash[0] 126| 0| var b = hash[1] 127| 0| var c = hash[2] 128| 0| var d = hash[3] 129| 0| var e = hash[4] 130| 0| var f = hash[5] 131| 0| var g = hash[6] 132| 0| var h = hash[7] 133| 0| 134| 0| // Run the main algorithm. 135| 0| for t in 0.. [UInt8] { 194| 0| var value = self.littleEndian 195| 0| return withUnsafeBytes(of: &value, Array.init) 196| 0| } 197| |} 198| | 199| |private extension UInt32 { 200| | /// Rotates self by given amount. 201| 0| func rotateRight(by amount: UInt32) -> UInt32 { 202| 0| return (self >> amount) | (self << (32 - amount)) 203| 0| } 204| |} 205| | 206| |private extension Array { 207| | /// Breaks the array into the given size. 208| 0| func blocks(size: Int) -> AnyIterator> { 209| 0| var currentIndex = startIndex 210| 0| return AnyIterator { 211| 0| if let nextIndex = self.index(currentIndex, offsetBy: size, limitedBy: self.endIndex) { 212| 0| defer { currentIndex = nextIndex } 213| 0| return self[currentIndex..: CustomStringConvertible { 13| | 14| | /// Storage for our elements. 15| | fileprivate var elements: [Element] 16| | 17| | /// A predicate that returns `true` if its first argument should be ordered 18| | /// before its second argument; otherwise, `false`. 19| | fileprivate let areInIncreasingOrder: (Element, Element) -> Bool 20| | 21| | /// Create an empty sorted array with given comparison predicate. 22| 0| public init(areInIncreasingOrder: @escaping (Element, Element) -> Bool) { 23| 0| self.elements = [] 24| 0| self.areInIncreasingOrder = areInIncreasingOrder 25| 0| } 26| | 27| | /// Create a sorted array with the given sequence and comparison predicate. 28| | public init( 29| | _ newElements: S, 30| | areInIncreasingOrder: @escaping (Element, Element) -> Bool) 31| | where S.Iterator.Element == Element 32| 0| { 33| 0| self.elements = newElements.sorted(by: areInIncreasingOrder) 34| 0| self.areInIncreasingOrder = areInIncreasingOrder 35| 0| } 36| | 37| | /// Insert the given element, maintaining the sort order. 38| 0| public mutating func insert(_ newElement: Element) { 39| 0| let index = self.index(for: newElement) 40| 0| elements.insert(newElement, at: index) 41| 0| } 42| | 43| | /// Returns the index to insert the element in the sorted array using binary search. 44| 0| private func index(for element: Element) -> Index { 45| 0| 46| 0| if self.isEmpty { 47| 0| return 0 48| 0| } 49| 0| var (low, high) = (0, self.endIndex - 1) 50| 0| var mid = 0 51| 0| 52| 0| while low < high { 53| 0| mid = (low + high)/2 54| 0| if areInIncreasingOrder(self[mid], element) { 55| 0| low = mid + 1 56| 0| } else { 57| 0| high = mid 58| 0| } 59| 0| } 60| 0| 61| 0| // At this point, low == high, low will never be greater than high, as low is incremented by just one or high is adjusted to mid. 62| 0| 63| 0| if areInIncreasingOrder(element, self[low]) { 64| 0| return low 65| 0| } 66| 0| 67| 0| return high + 1 68| 0| } 69| | 70| | /// Insert the given sequence, maintaining the sort order. 71| 0| public mutating func insert(contentsOf newElements: S) where S.Iterator.Element == Element { 72| 0| let newElements: Array = newElements.sorted(by: areInIncreasingOrder) 73| 0| guard !newElements.isEmpty else { 74| 0| return 75| 0| } 76| 0| guard !elements.isEmpty else { 77| 0| elements = newElements 78| 0| return 79| 0| } 80| 0| 81| 0| var lhsIndex = elements.endIndex - 1 82| 0| var rhsIndex = newElements.endIndex - 1 83| 0| 84| 0| elements.reserveCapacity(elements.count + newElements.count) 85| 0| 86| 0| // NOTE: If SortedArray moves to stdlib an _ArrayBuffer can be used 87| 0| // instead. This append can then be removed as _ArrayBuffer can be 88| 0| // resized without requiring instantiated elements. 89| 0| elements.append(contentsOf: newElements) 90| 0| 91| 0| var lhs = elements[lhsIndex], rhs = newElements[rhsIndex] 92| 0| 93| 0| // Equivalent to a merge sort, "pop" and append the max elemeent of 94| 0| // each array until either array is empty. 95| 0| for index in elements.indices.reversed() { 96| 0| if areInIncreasingOrder(lhs, rhs) { 97| 0| elements[index] = rhs 98| 0| rhsIndex -= 1 99| 0| guard rhsIndex >= newElements.startIndex else { break } 100| 0| rhs = newElements[rhsIndex] 101| 0| } else { 102| 0| elements[index] = lhs 103| 0| lhsIndex -= 1 104| 0| guard lhsIndex >= elements.startIndex else { break } 105| 0| lhs = elements[lhsIndex] 106| 0| } 107| 0| } 108| 0| 109| 0| // Any remaining new elements were smaller than all old elements 110| 0| // so the remaining new elements can safely replace the prefix. 111| 0| if rhsIndex >= newElements.startIndex { 112| 0| elements.replaceSubrange( 113| 0| newElements.startIndex ... rhsIndex, 114| 0| with: newElements[newElements.startIndex ... rhsIndex]) 115| 0| } 116| 0| } 117| | 118| | /// Returns the values as an array. 119| 0| public var values: [Element] { 120| 0| return elements 121| 0| } 122| | 123| 0| public var description: String { 124| 0| return "" 125| 0| } 126| |} 127| | 128| |extension SortedArray: RandomAccessCollection { 129| | public typealias Index = Int 130| | 131| 0| public var startIndex: Index { 132| 0| return elements.startIndex 133| 0| } 134| | 135| 0| public var endIndex: Index { 136| 0| return elements.endIndex 137| 0| } 138| | 139| 0| public func index(after i: Index) -> Index { 140| 0| return elements.index(after: i) 141| 0| } 142| | 143| 0| public func index(before i: Index) -> Index { 144| 0| return elements.index(before: i) 145| 0| } 146| | 147| 0| public subscript(position: Index) -> Element { 148| 0| return elements[position] 149| 0| } 150| |} 151| | 152| |extension SortedArray { 153| 0| public static func +=(lhs: inout SortedArray, rhs: S) where S.Iterator.Element == Element { 154| 0| lhs.insert(contentsOf: rhs) 155| 0| } 156| |} 157| | 158| |extension SortedArray where Element: Comparable { 159| | /// Create an empty sorted array with < as the comparison predicate. 160| 0| public init() { 161| 0| self.init(areInIncreasingOrder: <) 162| 0| } 163| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/StringConversions.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Check if the given code unit needs shell escaping. 12| |// 13| |/// - Parameters: 14| |/// - codeUnit: The code unit to be checked. 15| |/// 16| |/// - Returns: True if shell escaping is not needed. 17| 0|private func inShellWhitelist(_ codeUnit: UInt8) -> Bool { 18| 0| switch codeUnit { 19| 0| case UInt8(ascii: "a")...UInt8(ascii: "z"), 20| 0| UInt8(ascii: "A")...UInt8(ascii: "Z"), 21| 0| UInt8(ascii: "0")...UInt8(ascii: "9"), 22| 0| UInt8(ascii: "-"), 23| 0| UInt8(ascii: "_"), 24| 0| UInt8(ascii: "/"), 25| 0| UInt8(ascii: ":"), 26| 0| UInt8(ascii: "@"), 27| 0| UInt8(ascii: "%"), 28| 0| UInt8(ascii: "+"), 29| 0| UInt8(ascii: "="), 30| 0| UInt8(ascii: "."), 31| 0| UInt8(ascii: ","): 32| 0| return true 33| 0| default: 34| 0| return false 35| 0| } 36| 0|} 37| | 38| |extension String { 39| | 40| | /// Creates a shell escaped string. If the string does not need escaping, returns the original string. 41| | /// Otherwise escapes using single quotes. For example: 42| | /// hello -> hello, hello$world -> 'hello$world', input A -> 'input A' 43| | /// 44| | /// - Returns: Shell escaped string. 45| 0| public func spm_shellEscaped() -> String { 46| 0| 47| 0| // If all the characters in the string are in whitelist then no need to escape. 48| 0| guard let pos = utf8.index(where: { !inShellWhitelist($0) }) else { 49| 0| return self 50| 0| } 51| 0| 52| 0| // If there are no single quotes then we can just wrap the string around single quotes. 53| 0| guard let singleQuotePos = utf8[pos...].index(of: UInt8(ascii: "'")) else { 54| 0| return "'" + self + "'" 55| 0| } 56| 0| 57| 0| // Otherwise iterate and escape all the single quotes. 58| 0| var newString = "'" + String(self[.. String { 92| 0| var result = "" 93| 0| 94| 0| for (i, item) in enumerated() { 95| 0| // Add the separator, if necessary. 96| 0| if i == count - 1 { 97| 0| switch count { 98| 0| case 1: 99| 0| break 100| 0| case 2: 101| 0| result += " \(type.rawValue) " 102| 0| default: 103| 0| result += ", \(type.rawValue) " 104| 0| } 105| 0| } else if i != 0 { 106| 0| result += ", " 107| 0| } 108| 0| 109| 0| result += item 110| 0| } 111| 0| 112| 0| return result 113| 0| } 114| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/SynchronizedQueue.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// This class can be used as a shared queue between multiple threads providing 12| |/// thread safe APIs. 13| |public final class SynchronizedQueue { 14| | /// Storage for queued elements. 15| | private var storage: [Element] 16| | 17| | /// Condition variable to block the thread trying dequeue and queue is empty. 18| | private var notEmptyCondition: Condition 19| | 20| | /// Create a default instance of queue. 21| 0| public init() { 22| 0| storage = [] 23| 0| notEmptyCondition = Condition() 24| 0| } 25| | 26| | /// Safely enqueue an element to end of the queue and signals a thread blocked on dequeue. 27| | /// 28| | /// - Parameters: 29| | /// - element: The element to be enqueued. 30| 0| public func enqueue(_ element: Element) { 31| 0| notEmptyCondition.whileLocked { 32| 0| storage.append(element) 33| 0| // Signal a thread blocked on dequeue. 34| 0| notEmptyCondition.signal() 35| 0| } 36| 0| } 37| | 38| | /// Dequeue an element from front of the queue. Blocks the calling thread until an element is available. 39| | /// 40| | /// - Returns: First element in the queue. 41| 0| public func dequeue() -> Element { 42| 0| return notEmptyCondition.whileLocked { 43| 0| // Wait until we have an element available in the queue. 44| 0| while storage.isEmpty { 45| 0| notEmptyCondition.wait() 46| 0| } 47| 0| 48| 0| // FIXME: This is O(n) operation, optimize. 49| 0| return storage.removeFirst() 50| 0| } 51| 0| } 52| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/TemporaryFile.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| |import func POSIX.getenv 13| |import class Foundation.FileHandle 14| |import class Foundation.FileManager 15| | 16| |public enum TempFileError: Swift.Error { 17| | /// Could not create a unique temporary filename. 18| | case couldNotCreateUniqueName 19| | 20| | // FIXME: This should be factored out into a open error enum. 21| | // 22| | /// Some error thrown defined by posix's open(). 23| | case other(Int32) 24| | 25| | /// Couldn't find a temporary directory. 26| | case couldNotFindTmpDir 27| |} 28| | 29| |private extension TempFileError { 30| 0| init(errno: Int32) { 31| 0| switch errno { 32| 0| case SPMLibc.EEXIST: 33| 0| self = .couldNotCreateUniqueName 34| 0| default: 35| 0| self = .other(errno) 36| 0| } 37| 0| } 38| |} 39| | 40| |/// Determines the directory in which the temporary file should be created. Also makes 41| |/// sure the returning path has a trailing forward slash. 42| |/// 43| |/// - Parameters: 44| |/// - dir: If present this will be the temporary directory. 45| |/// 46| |/// - Returns: Path to directory in which temporary file should be created. 47| 0|public func determineTempDirectory(_ dir: AbsolutePath? = nil) throws -> AbsolutePath { 48| 0| // FIXME: Add other platform specific locations. 49| 0| let tmpDir = dir ?? cachedTempDirectory 50| 0| guard localFileSystem.isDirectory(tmpDir) else { 51| 0| throw TempFileError.couldNotFindTmpDir 52| 0| } 53| 0| return tmpDir 54| 0|} 55| | 56| |/// Returns temporary directory location by searching relevant env variables. 57| |/// Evaluates once per execution. 58| 0|private var cachedTempDirectory: AbsolutePath = { 59| 0| return AbsolutePath(getenv("TMPDIR") ?? getenv("TEMP") ?? getenv("TMP") ?? "/tmp/") 60| 0|}() 61| | 62| |/// This class is basically a wrapper over posix's mkstemps() function to creates disposable files. 63| |/// The file is deleted as soon as the object of this class is deallocated. 64| |public final class TemporaryFile { 65| | /// If specified during init, the temporary file name begins with this prefix. 66| | let prefix: String 67| | 68| | /// If specified during init, the temporary file name ends with this suffix. 69| | let suffix: String 70| | 71| | /// The directory in which the temporary file is created. 72| | public let dir: AbsolutePath 73| | 74| | /// The full path of the temporary file. For safety file operations should be done via the fileHandle instead of 75| | /// using this path. 76| | public let path: AbsolutePath 77| | 78| | /// The file descriptor of the temporary file. It is used to create NSFileHandle which is exposed to clients. 79| | private let fd: Int32 80| | 81| | /// FileHandle of the temporary file, can be used to read/write data. 82| | public let fileHandle: FileHandle 83| | 84| | /// Whether the file should be deleted on dealloc. 85| | public let deleteOnClose: Bool 86| | 87| | /// Creates an instance of Temporary file. The temporary file will live on disk until the instance 88| | /// goes out of scope. 89| | /// 90| | /// - Parameters: 91| | /// - dir: If specified the temporary file will be created in this directory otherwise environment variables 92| | /// TMPDIR, TEMP and TMP will be checked for a value (in that order). If none of the env variables are 93| | /// set, dir will be set to `/tmp/`. 94| | /// - prefix: The prefix to the temporary file name. 95| | /// - suffix: The suffix to the temporary file name. 96| | /// - deleteOnClose: Whether the file should get deleted when the instance is deallocated. 97| | /// 98| | /// - Throws: TempFileError 99| 0| public init(dir: AbsolutePath? = nil, prefix: String = "TemporaryFile", suffix: String = "", deleteOnClose: Bool = true) throws { 100| 0| self.suffix = suffix 101| 0| self.prefix = prefix 102| 0| self.deleteOnClose = deleteOnClose 103| 0| // Determine in which directory to create the temporary file. 104| 0| self.dir = try determineTempDirectory(dir) 105| 0| // Construct path to the temporary file. 106| 0| let path = self.dir.appending(RelativePath(prefix + ".XXXXXX" + suffix)) 107| 0| 108| 0| // Convert path to a C style string terminating with null char to be an valid input 109| 0| // to mkstemps method. The XXXXXX in this string will be replaced by a random string 110| 0| // which will be the actual path to the temporary file. 111| 0| var template = [UInt8](path.pathString.utf8).map({ Int8($0) }) + [Int8(0)] 112| 0| 113| 0| fd = SPMLibc.mkstemps(&template, Int32(suffix.utf8.count)) 114| 0| // If mkstemps failed then throw error. 115| 0| if fd == -1 { throw TempFileError(errno: errno) } 116| 0| 117| 0| self.path = AbsolutePath(String(cString: template)) 118| 0| fileHandle = FileHandle(fileDescriptor: fd, closeOnDealloc: true) 119| 0| } 120| | 121| | /// Remove the temporary file before deallocating. 122| 0| deinit { 123| 0| if deleteOnClose { 124| 0| unlink(path.pathString) 125| 0| } 126| 0| } 127| |} 128| | 129| |extension TemporaryFile: CustomStringConvertible { 130| 0| public var description: String { 131| 0| return "" 132| 0| } 133| |} 134| | 135| |// FIXME: This isn't right place to declare this, probably POSIX or merge with FileSystemError? 136| |// 137| |/// Contains the error which can be thrown while creating a directory using POSIX's mkdir. 138| |public enum MakeDirectoryError: Swift.Error { 139| | /// The given path already exists as a directory, file or symbolic link. 140| | case pathExists 141| | /// The path provided was too long. 142| | case pathTooLong 143| | /// Process does not have permissions to create directory. 144| | /// Note: Includes read-only filesystems or if file system does not support directory creation. 145| | case permissionDenied 146| | /// The path provided is unresolvable because it has too many symbolic links or a path component is invalid. 147| | case unresolvablePathComponent 148| | /// Exceeded user quota or kernel is out of memory. 149| | case outOfMemory 150| | /// All other system errors with their value. 151| | case other(Int32) 152| |} 153| | 154| |private extension MakeDirectoryError { 155| 0| init(errno: Int32) { 156| 0| switch errno { 157| 0| case SPMLibc.EEXIST: 158| 0| self = .pathExists 159| 0| case SPMLibc.ENAMETOOLONG: 160| 0| self = .pathTooLong 161| 0| case SPMLibc.EACCES, SPMLibc.EFAULT, SPMLibc.EPERM, SPMLibc.EROFS: 162| 0| self = .permissionDenied 163| 0| case SPMLibc.ELOOP, SPMLibc.ENOENT, SPMLibc.ENOTDIR: 164| 0| self = .unresolvablePathComponent 165| 0| case SPMLibc.ENOMEM, SPMLibc.EDQUOT: 166| 0| self = .outOfMemory 167| 0| default: 168| 0| self = .other(errno) 169| 0| } 170| 0| } 171| |} 172| | 173| |/// A class to create disposable directories using POSIX's mkdtemp() method. 174| |public final class TemporaryDirectory { 175| | /// If specified during init, the temporary directory name begins with this prefix. 176| | let prefix: String 177| | 178| | /// The full path of the temporary directory. 179| | public let path: AbsolutePath 180| | 181| | /// If true, try to remove the whole directory tree before deallocating. 182| | let shouldRemoveTreeOnDeinit: Bool 183| | 184| | /// Creates a temporary directory which is automatically removed when the object of this class goes out of scope. 185| | /// 186| | /// - Parameters: 187| | /// - dir: If specified the temporary directory will be created in this directory otherwise environment 188| | /// variables TMPDIR, TEMP and TMP will be checked for a value (in that order). If none of the env 189| | /// variables are set, dir will be set to `/tmp/`. 190| | /// - prefix: The prefix to the temporary file name. 191| | /// - removeTreeOnDeinit: If enabled try to delete the whole directory tree otherwise remove only if its empty. 192| | /// 193| | /// - Throws: MakeDirectoryError 194| | public init( 195| | dir: AbsolutePath? = nil, 196| | prefix: String = "TemporaryDirectory", 197| | removeTreeOnDeinit: Bool = false 198| 0| ) throws { 199| 0| self.shouldRemoveTreeOnDeinit = removeTreeOnDeinit 200| 0| self.prefix = prefix 201| 0| // Construct path to the temporary directory. 202| 0| let path = try determineTempDirectory(dir).appending(RelativePath(prefix + ".XXXXXX")) 203| 0| 204| 0| // Convert path to a C style string terminating with null char to be an valid input 205| 0| // to mkdtemp method. The XXXXXX in this string will be replaced by a random string 206| 0| // which will be the actual path to the temporary directory. 207| 0| var template = [UInt8](path.pathString.utf8).map({ Int8($0) }) + [Int8(0)] 208| 0| 209| 0| if SPMLibc.mkdtemp(&template) == nil { 210| 0| throw MakeDirectoryError(errno: errno) 211| 0| } 212| 0| 213| 0| self.path = AbsolutePath(String(cString: template)) 214| 0| } 215| | 216| | /// Remove the temporary file before deallocating. 217| 0| deinit { 218| 0| if shouldRemoveTreeOnDeinit { 219| 0| _ = try? FileManager.default.removeItem(atPath: path.pathString) 220| 0| } else { 221| 0| rmdir(path.pathString) 222| 0| } 223| 0| } 224| |} 225| | 226| |extension TemporaryDirectory: CustomStringConvertible { 227| 0| public var description: String { 228| 0| return "" 229| 0| } 230| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/TerminalController.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| |import func POSIX.getenv 13| | 14| |/// A class to have better control on tty output streams: standard output and standard error. 15| |/// Allows operations like cursor movement and colored text output on tty. 16| |public final class TerminalController { 17| | 18| | /// The type of terminal. 19| | public enum TerminalType { 20| | /// The terminal is a TTY. 21| | case tty 22| | 23| | /// TERM enviornment variable is set to "dumb". 24| | case dumb 25| | 26| | /// The terminal is a file stream. 27| | case file 28| | } 29| | 30| | /// Terminal color choices. 31| | public enum Color { 32| | case noColor 33| | 34| | case red 35| | case green 36| | case yellow 37| | case cyan 38| | 39| | case white 40| | case black 41| | case grey 42| | 43| | /// Returns the color code which can be prefixed on a string to display it in that color. 44| 0| fileprivate var string: String { 45| 0| switch self { 46| 0| case .noColor: return "" 47| 0| case .red: return "\u{001B}[31m" 48| 0| case .green: return "\u{001B}[32m" 49| 0| case .yellow: return "\u{001B}[33m" 50| 0| case .cyan: return "\u{001B}[36m" 51| 0| case .white: return "\u{001B}[37m" 52| 0| case .black: return "\u{001B}[30m" 53| 0| case .grey: return "\u{001B}[30;1m" 54| 0| } 55| 0| } 56| | } 57| | 58| | /// Pointer to output stream to operate on. 59| | private var stream: OutputByteStream 60| | 61| | /// Width of the terminal. 62| | public let width: Int 63| | 64| | /// Code to clear the line on a tty. 65| | private let clearLineString = "\u{001B}[2K" 66| | 67| | /// Code to end any currently active wrapping. 68| | private let resetString = "\u{001B}[0m" 69| | 70| | /// Code to make string bold. 71| | private let boldString = "\u{001B}[1m" 72| | 73| | /// Constructs the instance if the stream is a tty. 74| 0| public init?(stream: OutputByteStream) { 75| 0| let realStream = (stream as? ThreadSafeOutputByteStream)?.stream ?? stream 76| 0| 77| 0| // Make sure it is a file stream and it is tty. 78| 0| guard let fileStream = realStream as? LocalFileOutputByteStream, TerminalController.isTTY(fileStream) else { 79| 0| return nil 80| 0| } 81| 0| 82| 0| // Determine the terminal width otherwise assume a default. 83| 0| if let terminalWidth = TerminalController.terminalWidth(), terminalWidth > 0 { 84| 0| width = terminalWidth 85| 0| } else { 86| 0| width = 80 87| 0| } 88| 0| self.stream = stream 89| 0| } 90| | 91| | /// Checks if passed file stream is tty. 92| 0| public static func isTTY(_ stream: LocalFileOutputByteStream) -> Bool { 93| 0| return terminalType(stream) == .tty 94| 0| } 95| | 96| | /// Computes the terminal type of the stream. 97| 0| public static func terminalType(_ stream: LocalFileOutputByteStream) -> TerminalType { 98| 0| if POSIX.getenv("TERM") == "dumb" { 99| 0| return .dumb 100| 0| } 101| 0| let isTTY = isatty(fileno(stream.filePointer)) != 0 102| 0| return isTTY ? .tty : .file 103| 0| } 104| | 105| | /// Tries to get the terminal width first using COLUMNS env variable and 106| | /// if that fails ioctl method testing on stdout stream. 107| | /// 108| | /// - Returns: Current width of terminal if it was determinable. 109| 0| public static func terminalWidth() -> Int? { 110| 0| // Try to get from environment. 111| 0| if let columns = POSIX.getenv("COLUMNS"), let width = Int(columns) { 112| 0| return width 113| 0| } 114| 0| 115| 0| // Try determining using ioctl. 116| 0| // Following code does not compile on ppc64le well. TIOCGWINSZ is 117| 0| // defined in system ioctl.h file which needs to be used. This is 118| 0| // a temporary arrangement and needs to be fixed. 119| 0|#if !arch(powerpc64le) 120| 0| var ws = winsize() 121| 0| if ioctl(1, UInt(TIOCGWINSZ), &ws) == 0 { 122| 0| return Int(ws.ws_col) 123| 0| } 124| 0|#endif 125| 0| return nil 126| 0| } 127| | 128| | /// Flushes the stream. 129| 0| public func flush() { 130| 0| stream.flush() 131| 0| } 132| | 133| | /// Clears the current line and moves the cursor to beginning of the line.. 134| 0| public func clearLine() { 135| 0| stream <<< clearLineString <<< "\r" 136| 0| flush() 137| 0| } 138| | 139| | /// Moves the cursor y columns up. 140| 0| public func moveCursor(up: Int) { 141| 0| stream <<< "\u{001B}[\(up)A" 142| 0| flush() 143| 0| } 144| | 145| | /// Writes a string to the stream. 146| 0| public func write(_ string: String, inColor color: Color = .noColor, bold: Bool = false) { 147| 0| writeWrapped(string, inColor: color, bold: bold, stream: stream) 148| 0| flush() 149| 0| } 150| | 151| | /// Inserts a new line character into the stream. 152| 0| public func endLine() { 153| 0| stream <<< "\n" 154| 0| flush() 155| 0| } 156| | 157| | /// Wraps the string into the color mentioned. 158| 0| public func wrap(_ string: String, inColor color: Color, bold: Bool = false) -> String { 159| 0| let stream = BufferedOutputByteStream() 160| 0| writeWrapped(string, inColor: color, bold: bold, stream: stream) 161| 0| return stream.bytes.description 162| 0| } 163| | 164| 0| private func writeWrapped(_ string: String, inColor color: Color, bold: Bool = false, stream: OutputByteStream) { 165| 0| // Don't wrap if string is empty or color is no color. 166| 0| guard !string.isEmpty && color != .noColor else { 167| 0| stream <<< string 168| 0| return 169| 0| } 170| 0| stream <<< color.string <<< (bold ? boldString : "") <<< string <<< resetString 171| 0| } 172| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Thread.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Foundation 12| | 13| |/// This class bridges the gap between Darwin and Linux Foundation Threading API. 14| |/// It provides closure based execution and a join method to block the calling thread 15| |/// until the thread is finished executing. 16| |final public class Thread { 17| | 18| | /// The thread implementation which is Foundation.Thread on Linux and 19| | /// a Thread subclass which provides closure support on Darwin. 20| | private var thread: ThreadImpl! 21| | 22| | /// Condition variable to support blocking other threads using join when this thread has not finished executing. 23| | private var finishedCondition: Condition 24| | 25| | /// A boolean variable to track if this thread has finished executing its task. 26| | private var isFinished: Bool 27| | 28| | /// Creates an instance of thread class with closure to be executed when start() is called. 29| 0| public init(task: @escaping () -> Void) { 30| 0| isFinished = false 31| 0| finishedCondition = Condition() 32| 0| 33| 0| // Wrap the task with condition notifying any other threads blocked due to this thread. 34| 0| // Capture self weakly to avoid reference cycle. In case Thread is deinited before the task 35| 0| // runs, skip the use of finishedCondition. 36| 0| let theTask = { [weak self] in 37| 0| if let strongSelf = self { 38| 0| precondition(!strongSelf.isFinished) 39| 0| strongSelf.finishedCondition.whileLocked { 40| 0| task() 41| 0| strongSelf.isFinished = true 42| 0| strongSelf.finishedCondition.broadcast() 43| 0| } 44| 0| } else { 45| 0| // If the containing thread has been destroyed, we can ignore the finished condition and just run the 46| 0| // task. 47| 0| task() 48| 0| } 49| 0| } 50| 0| 51| 0| self.thread = ThreadImpl(block: theTask) 52| 0| } 53| | 54| | /// Starts the thread execution. 55| 0| public func start() { 56| 0| thread.start() 57| 0| } 58| | 59| | /// Blocks the calling thread until this thread is finished execution. 60| 0| public func join() { 61| 0| finishedCondition.whileLocked { 62| 0| while !isFinished { 63| 0| finishedCondition.wait() 64| 0| } 65| 0| } 66| 0| } 67| |} 68| | 69| |#if os(macOS) 70| |/// A helper subclass of Foundation's Thread with closure support. 71| |final private class ThreadImpl: Foundation.Thread { 72| | 73| | /// The task to be executed. 74| | private let task: () -> Void 75| | 76| 0| override func main() { 77| 0| task() 78| 0| } 79| | 80| 0| init(block task: @escaping () -> Void) { 81| 0| self.task = task 82| 0| } 83| |} 84| |#else 85| |// Thread on Linux supports closure so just use it directly. 86| |typealias ThreadImpl = Foundation.Thread 87| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/Tuple.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// Returns true if these arrays of tuple contains the same elements. 12| |public func ==( 13| | lhs: [(A, B)], rhs: [(A, B)] 14| 0|) -> Bool { 15| 0| guard lhs.count == rhs.count else { return false } 16| 0| for (idx, lElement) in lhs.enumerated() { 17| 0| guard lElement == rhs[idx] else { 18| 0| return false 19| 0| } 20| 0| } 21| 0| return true 22| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Basic/misc.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import SPMLibc 12| |import POSIX 13| |import Foundation 14| | 15| |/// Replace the current process image with a new process image. 16| |/// 17| |/// - Parameters: 18| |/// - path: Absolute path to the executable. 19| |/// - args: The executable arguments. 20| 0|public func exec(path: String, args: [String]) throws { 21| 0| let cArgs = CStringArray(args) 22| 0| guard execv(path, cArgs.cArray) != -1 else { 23| 0| throw POSIX.SystemError.exec(errno, path: path, args: args) 24| 0| } 25| 0|} 26| | 27| |// MARK: Utility function for searching for executables 28| | 29| |/// Create a list of AbsolutePath search paths from a string, such as the PATH environment variable. 30| |/// 31| |/// - Parameters: 32| |/// - pathString: The path string to parse. 33| |/// - currentWorkingDirectory: The current working directory, the relative paths will be converted to absolute paths 34| |/// based on this path. 35| |/// - Returns: List of search paths. 36| |public func getEnvSearchPaths( 37| | pathString: String?, 38| | currentWorkingDirectory: AbsolutePath? 39| 0|) -> [AbsolutePath] { 40| 0| // Compute search paths from PATH variable. 41| 0| return (pathString ?? "").split(separator: ":").map(String.init).compactMap({ pathString in 42| 0| // If this is an absolute path, we're done. 43| 0| if pathString.first == "/" { 44| 0| return AbsolutePath(pathString) 45| 0| } 46| 0| // Otherwise convert it into absolute path relative to the working directory. 47| 0| guard let cwd = currentWorkingDirectory else { 48| 0| return nil 49| 0| } 50| 0| return AbsolutePath(pathString, relativeTo: cwd) 51| 0| }) 52| 0|} 53| | 54| |/// Lookup an executable path from an environment variable value, current working 55| |/// directory or search paths. Only return a value that is both found and executable. 56| |/// 57| |/// This method searches in the following order: 58| |/// * If env value is a valid absolute path, return it. 59| |/// * If env value is relative path, first try to locate it in current working directory. 60| |/// * Otherwise, in provided search paths. 61| |/// 62| |/// - Parameters: 63| |/// - filename: The name of the file to find. 64| |/// - currentWorkingDirectory: The current working directory to look in. 65| |/// - searchPaths: The additional search paths to look in if not found in cwd. 66| |/// - Returns: Valid path to executable if present, otherwise nil. 67| |public func lookupExecutablePath( 68| | filename value: String?, 69| | currentWorkingDirectory: AbsolutePath? = localFileSystem.currentWorkingDirectory, 70| | searchPaths: [AbsolutePath] = [] 71| 0|) -> AbsolutePath? { 72| 0| 73| 0| // We should have a value to continue. 74| 0| guard let value = value, !value.isEmpty else { 75| 0| return nil 76| 0| } 77| 0| 78| 0| let path: AbsolutePath 79| 0| if let cwd = currentWorkingDirectory { 80| 0| // We have a value, but it could be an absolute or a relative path. 81| 0| path = AbsolutePath(value, relativeTo: cwd) 82| 0| } else if let absPath = try? AbsolutePath(validating: value) { 83| 0| // Current directory not being available is not a problem 84| 0| // for the absolute-specified paths. 85| 0| path = absPath 86| 0| } else { 87| 0| return nil 88| 0| } 89| 0| 90| 0| if localFileSystem.isExecutableFile(path) { 91| 0| return path 92| 0| } 93| 0| // Ensure the value is not a path. 94| 0| guard !value.contains("/") else { 95| 0| return nil 96| 0| } 97| 0| // Try to locate in search paths. 98| 0| for path in searchPaths { 99| 0| let exec = path.appending(component: value) 100| 0| if localFileSystem.isExecutableFile(exec) { 101| 0| return exec 102| 0| } 103| 0| } 104| 0| return nil 105| 0|} 106| | 107| |/// A wrapper for Range to make it Codable. 108| |/// 109| |/// Technically, we can use conditional conformance and make 110| |/// stdlib's Range Codable but since extensions leak out, it 111| |/// is not a good idea to extend types that you don't own. 112| |/// 113| |/// Range conformance will be added soon to stdlib so we can remove 114| |/// this type in the future. 115| |public struct CodableRange where Bound: Comparable & Codable { 116| | 117| | /// The underlying range. 118| | public let range: Range 119| | 120| | /// Create a CodableRange instance. 121| 0| public init(_ range: Range) { 122| 0| self.range = range 123| 0| } 124| |} 125| | 126| |extension CodableRange: Codable { 127| | private enum CodingKeys: String, CodingKey { 128| | case lowerBound, upperBound 129| | } 130| | 131| 0| public func encode(to encoder: Encoder) throws { 132| 0| var container = encoder.container(keyedBy: CodingKeys.self) 133| 0| try container.encode(range.lowerBound, forKey: .lowerBound) 134| 0| try container.encode(range.upperBound, forKey: .upperBound) 135| 0| } 136| | 137| 0| public init(from decoder: Decoder) throws { 138| 0| let container = try decoder.container(keyedBy: CodingKeys.self) 139| 0| let lowerBound = try container.decode(Bound.self, forKey: .lowerBound) 140| 0| let upperBound = try container.decode(Bound.self, forKey: .upperBound) 141| 0| self.init(Range(uncheckedBounds: (lowerBound, upperBound))) 142| 0| } 143| |} 144| | 145| |extension AbsolutePath { 146| | /// File URL created from the normalized string representation of the path. 147| 0| public var asURL: Foundation.URL { 148| 0| return URL(fileURLWithPath: pathString) 149| 0| } 150| |} <<<<<< EOF # path=CommandRegistry.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/Sources/CommandRegistry/Command.swift: 1| |import Foundation 2| |import SPMUtility 3| |import Basic 4| | 5| |public protocol Command: class { 6| | var command: String { get } 7| | var overview: String { get } 8| | var subparser: ArgumentParser { get } 9| | var subcommands: [Command] { get set } 10| | 11| | init(parser: ArgumentParser) 12| | func run(with arguments: ArgumentParser.Result) throws 13| |} 14| | 15| |extension Command { 16| 1| public func printUsage(on stream: OutputByteStream = stdoutStream) { 17| 1| subparser.printUsage(on: stream) 18| 1| } 19| |} /Users/travis/build/eneko/CommandRegistry/Sources/CommandRegistry/CommandRegistry.swift: 1| |import Foundation 2| |import SPMUtility 3| |import Basic 4| |import Logger 5| | 6| |public struct CommandRegistry { 7| | 8| | let parser: ArgumentParser 9| | var commands: [Command] = [] 10| | 11| | public var version: String? 12| | 13| 8| public init(usage: String, overview: String, toolname: String? = nil) { 14| 8| parser = ArgumentParser(commandName: toolname, usage: usage, overview: overview) 15| 8| } 16| | 17| | @discardableResult 18| 1| public mutating func register(command commandType: Command.Type) -> Command { 19| 1| let command = commandType.init(parser: parser) 20| 1| commands.append(command) 21| 1| return command 22| 1| } 23| | 24| | @discardableResult 25| 0| public mutating func register(subcommand commandType: Command.Type, parent: Command) -> Command { 26| 0| let subcommand = commandType.init(parser: parent.subparser) 27| 0| parent.subcommands.append(subcommand) 28| 0| return subcommand 29| 0| } 30| | 31| 7| public func run(arguments: [String]? = nil) { 32| 7| addVersionFlag() 33| 7| do { 34| 7| let arguments = arguments ?? Array(ProcessInfo.processInfo.arguments.dropFirst()) 35| 7| let parsedArguments = try parse(arguments: arguments) 36| 7| try process(parsedArguments: parsedArguments) 37| 7| } 38| 7| catch let error as ArgumentParserError { 39| 0| Logger.error.log(error.description) 40| 0| } 41| 7| catch DecodingError.keyNotFound(_, let context) { 42| 0| Logger.error.log(context.debugDescription) 43| 0| Logger.error.log(context.codingPath.description) 44| 0| } 45| 7| catch let error { 46| 0| Logger.error.log(error.localizedDescription) 47| 7| } 48| 7| } 49| | 50| 7| private func addVersionFlag() { 51| 7| if version != nil { 52| 0| _ = parser.add(option: "--version", kind: Bool.self) 53| 7| } 54| 7| } 55| | 56| 7| func parse(arguments: [String]) throws -> ArgumentParser.Result { 57| 7| return try parser.parse(arguments) 58| 7| } 59| | 60| 7| func process(parsedArguments: ArgumentParser.Result) throws { 61| 7| // Check for default option flags 62| 7| if let version = version, try parsedArguments.get("--version") == true { 63| 0| Logger.standard.log(version) 64| 0| return 65| 7| } 66| 7| 67| 7| // Navigate subcommands to find the last subcommand entered (tool command subcommandA subcommandB...) 68| 7| var parser = self.parser 69| 7| var commands = self.commands 70| 7| var command: Command? 71| 10| while let commandName = parsedArguments.subparser(parser), let match = commands.first(where: { $0.command == commandName }) { 72| 7| parser = match.subparser 73| 7| commands = match.subcommands 74| 7| command = match 75| 7| } 76| 7| 77| 7| // Execute command, if any, otherwise print usage 78| 7| if let command = command { 79| 7| try command.run(with: parsedArguments) 80| 7| } 81| 7| else { 82| 0| parser.printUsage(on: stdoutStream) 83| 7| } 84| 7| } 85| | 86| |} /Users/travis/build/eneko/CommandRegistry/Sources/CommandRegistry/SugarCommand.swift: 1| |import Foundation 2| |import SPMUtility 3| |import Basic 4| |import Logger 5| | 6| |class SugarCommand: Command { 7| | let command: String 8| | let overview: String 9| | let subparser: ArgumentParser 10| | var subcommands: [Command] = [] 11| | let handler: ([String]) throws -> Void 12| | let positionalArguments: PositionalArgument<[String]> 13| | 14| | init(parser: ArgumentParser, command: String, overview: String, 15| 6| handler: @escaping ([String]) throws -> Void) { 16| 6| self.command = command 17| 6| self.overview = overview 18| 6| self.handler = handler 19| 6| subparser = parser.add(subparser: command, overview: overview) 20| 6| positionalArguments = subparser.add(positional: "params", kind: [String].self, 21| 6| optional: true, usage: "Additional parameters") 22| 6| } 23| | 24| 0| required init(parser: ArgumentParser) { 25| 0| fatalError("Not supported") 26| 0| } 27| | 28| 6| func run(with arguments: ArgumentParser.Result) throws { 29| 6| try handler(arguments.get(positionalArguments) ?? []) 30| 6| } 31| |} 32| | 33| |extension CommandRegistry { 34| 6| public mutating func on(command: String, overview: String = "", handler: @escaping ([String]) throws -> Void) rethrows { 35| 6| let sugar = SugarCommand(parser: parser, command: command, 36| 6| overview: overview, handler: handler) 37| 6| commands.append(sugar) 38| 6| } 39| |} <<<<<< EOF # path=PublicTests.xctest.coverage.txt /Users/travis/build/eneko/CommandRegistry/Tests/PublicTests/CommandTests.swift: 1| |import XCTest 2| |import Basic 3| |import CommandRegistry 4| | 5| |final class CommandTests: XCTestCase { 6| 1| func testCommand() { 7| 1| let parser = ArgumentParser(usage: "usage", overview: "overview") 8| 1| let instance = FooCommand(parser: parser) 9| 1| XCTAssertEqual(instance.command, "foo") 10| 1| } 11| | 12| 1| func testOverview() { 13| 1| let parser = ArgumentParser(usage: "usage", overview: "overview") 14| 1| let instance = FooCommand(parser: parser) 15| 1| XCTAssertEqual(instance.overview, "foo") 16| 1| } 17| | 18| 1| func testPrintCommandUsage() { 19| 1| let stream = BufferedOutputByteStream() 20| 1| let parser = ArgumentParser(usage: "usage", overview: "overview") 21| 1| let instance = FooCommand(parser: parser) 22| 1| instance.printUsage(on: stream) 23| 1| let expectation = """ 24| 1| OVERVIEW: foo 25| 1| 26| 1| """ 27| 1| XCTAssertEqual(stream.bytes.description, expectation) 28| 1| } 29| |} 30| | 31| |class FooCommand: Command { 32| | let command = "foo" 33| | let overview = "foo" 34| | var subparser: ArgumentParser 35| | var subcommands: [Command] = [] 36| | 37| 3| required init(parser: ArgumentParser) { 38| 3| subparser = parser.add(subparser: command, overview: overview) 39| 3| } 40| 0| func run(with arguments: ArgumentParser.Result) throws { 41| 0| // 42| 0| } 43| |} /Users/travis/build/eneko/CommandRegistry/Tests/PublicTests/CommandWithArgumentTests.swift: 1| |import XCTest 2| |import CommandRegistry 3| | 4| |var output = [String: String]() 5| | 6| |class CommandWithArgumentTests: XCTestCase { 7| | 8| 1| func testHello() { 9| 1| let key = UUID().uuidString 10| 1| var registry = CommandRegistry(usage: "foo", overview: "bar") 11| 1| registry.register(command: HelloCommand.self) 12| 1| registry.run(arguments: ["hello", key]) 13| 1| XCTAssertEqual(output[key], "Hello World!") 14| 1| } 15| | 16| |} 17| | 18| |class HelloCommand: Command { 19| | let command = "hello" 20| | let overview = "Says hello" 21| | let subparser: ArgumentParser 22| | var subcommands: [Command] = [] 23| | 24| | var params: PositionalArgument<[String]> 25| | 26| 1| required init(parser: ArgumentParser) { 27| 1| subparser = parser.add(subparser: command, overview: overview) 28| 1| params = subparser.add(positional: "params", kind: [String].self, optional: true) 29| 1| } 30| 1| func run(with arguments: ArgumentParser.Result) throws { 31| 1| let params: [String] = arguments.get(self.params) ?? [] 32| 1| if let key = params.first { 33| 1| output[key] = "Hello World!" 34| 1| } 35| 1| } 36| |} /Users/travis/build/eneko/CommandRegistry/Tests/PublicTests/SyntaxSugarTests.swift: 1| |import XCTest 2| |import CommandRegistry 3| | 4| |final class SyntaxSugarTests: XCTestCase { 5| | 6| 1| func testSugarNoArguments() { 7| 1| var output: String? 8| 1| var registry = CommandRegistry(usage: "foo", overview: "bar") 9| 1| registry.on(command: "hello", overview: "Says hello") { params in 10| 1| output = params.first.flatMap { "Hello \($0)!" } ?? "Hello world!" 11| 1| } 12| 1| 13| 1| registry.run(arguments: ["hello"]) 14| 1| XCTAssertEqual(output, "Hello world!") 15| 1| } 16| | 17| 1| func testSugarSingleArgument() { 18| 1| var output: String? 19| 1| var registry = CommandRegistry(usage: "foo", overview: "bar") 20| 1| registry.on(command: "hello", overview: "Says hello") { params in 21| 1| output = params.first.flatMap { "Hello \($0)!" } ?? "Hello world!" 22| 1| } 23| 1| 24| 1| registry.run(arguments: ["hello", "Bob"]) 25| 1| XCTAssertEqual(output, "Hello Bob!") 26| 1| } 27| | 28| 1| func testSugarMultipleArguments() { 29| 1| var output: String? 30| 1| var registry = CommandRegistry(usage: "foo", overview: "bar") 31| 1| registry.on(command: "hello", overview: "Says hello") { params in 32| 1| output = params.first.flatMap { "Hello \($0)!" } ?? "Hello world!" 33| 1| } 34| 1| 35| 1| registry.run(arguments: ["hello", "1", "2", "3", "4", "5", "6"]) 36| 1| XCTAssertEqual(output, "Hello 1!") 37| 1| } 38| | 39| 1| func testSugarMultipleCommands() { 40| 1| var output: String? 41| 1| var registry = CommandRegistry(usage: "foo", overview: "bar") 42| 1| registry.on(command: "foo") { params in 43| 1| output = "foo \(params.count)" 44| 1| } 45| 1| registry.on(command: "bar") { params in 46| 1| output = "bar \(params.count)" 47| 1| } 48| 1| registry.on(command: "baz") { params in 49| 1| output = "baz \(params.count)" 50| 1| } 51| 1| 52| 1| registry.run(arguments: ["foo"]) 53| 1| XCTAssertEqual(output, "foo 0") 54| 1| 55| 1| registry.run(arguments: ["bar", "1", "2"]) 56| 1| XCTAssertEqual(output, "bar 2") 57| 1| 58| 1| registry.run(arguments: ["baz", "tan", "go"]) 59| 1| XCTAssertEqual(output, "baz 2") 60| 1| } 61| | 62| |} <<<<<< EOF # path=llbuildBuildSystem.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/BinaryCoding.h: 1| |//===- BinaryCoding.h -------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_BINARYCODING_H 14| |#define LLBUILD_BASIC_BINARYCODING_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/SmallVector.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |#include 23| |#include 24| | 25| |namespace llbuild { 26| |namespace basic { 27| | 28| |template 29| |struct BinaryCodingTraits { 30| | // static inline void encode(const T&, BinaryEncoder&); 31| | // static inline void decode(T&, BinaryDecoder&); 32| |}; 33| | 34| |/// A basic binary encoding utility. 35| |/// 36| |/// This encoder is design for small, relatively efficient, in-memory coding of 37| |/// objects. It is endian-neutral, and should be paired with \see BinaryDecoder 38| |/// for decoding. The specific encoding is not intended to be stable. 39| |/// 40| |/// The utility supports coding of user-defined types via specialization of the 41| |/// BinaryCodeableTraits type. 42| |class BinaryEncoder { 43| |private: 44| | // Copying is disabled. 45| | BinaryEncoder(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 46| | void operator=(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 47| | 48| | /// The encoded data. 49| | // 50| | // FIXME: Parameterize this size? 51| | llvm::SmallVector encdata; 52| | 53| |public: 54| | /// Construct a new binary encoder. 55| 0| BinaryEncoder() {} 56| | 57| | /// Encode a value to the stream. 58| 0| void write(bool value) { 59| 0| encdata.push_back(uint8_t(value)); 60| 0| } 61| | 62| | /// Encode a value to the stream. 63| 0| void write(uint8_t value) { 64| 0| encdata.push_back(value); 65| 0| } 66| | 67| | /// Encode a value to the stream. 68| 0| void write(uint16_t value) { 69| 0| write(uint8_t(value >> 0)); 70| 0| write(uint8_t(value >> 8)); 71| 0| } 72| | 73| | /// Encode a value to the stream. 74| 0| void write(uint32_t value) { 75| 0| write(uint16_t(value >> 0)); 76| 0| write(uint16_t(value >> 16)); 77| 0| } 78| | 79| | /// Encode a value to the stream. 80| 0| void write(uint64_t value) { 81| 0| write(uint32_t(value >> 0)); 82| 0| write(uint32_t(value >> 32)); 83| 0| } 84| | 85| | /// Encode a value to the stream. 86| | /// 87| | /// We do not support encoding values larger than 4GB. 88| 0| void write(const std::string& value) { 89| 0| uint32_t size = uint32_t(value.size()); 90| 0| assert(size == value.size()); 91| 0| write(size); 92| 0| writeBytes(StringRef(value)); 93| 0| } 94| | 95| | /// Encode a sequence of bytes to the stream. 96| 0| void writeBytes(StringRef bytes) { 97| 0| encdata.insert(encdata.end(), bytes.begin(), bytes.end()); 98| 0| } 99| | 100| | /// Encode a value to the stream. 101| | template 102| 0| void write(const T& value) { 103| 0| BinaryCodingTraits::encode(value, *this); 104| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_13FileTimestampEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeIN4llvm9StringRefEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_10StringListEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS_11buildsystem10BuildValue4KindEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_16CommandSignatureEEEvRKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryEncoder5writeINS0_8FileInfoEEEvRKT_ ------------------ 105| | 106| | /// Get the encoded binary data. 107| 0| std::vector contents() { 108| 0| return std::vector(encdata.begin(), encdata.end()); 109| 0| } 110| | 111| | /// Get the encoded binary data (in place) 112| | const uint8_t* data() const { 113| | return encdata.data(); 114| | } 115| | 116| | /// Get the size of the encoded binary data 117| | const size_t size() const { 118| | return encdata.size(); 119| | } 120| |}; 121| | 122| |/// A basic binary decoding utility. 123| |/// 124| |/// \see BinaryEncoder. 125| |class BinaryDecoder { 126| |private: 127| | // Copying is disabled. 128| | BinaryDecoder(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 129| | void operator=(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 130| | 131| | /// The data being decoded. 132| | StringRef data; 133| | 134| | /// The current position in the stream. 135| | uint64_t pos = 0; 136| | 137| 0| uint8_t read8() { return data[pos++]; } 138| 0| uint16_t read16() { 139| 0| uint16_t result = read8(); 140| 0| result |= uint16_t(read8()) << 8; 141| 0| return result; 142| 0| } 143| 0| uint32_t read32() { 144| 0| uint32_t result = read16(); 145| 0| result |= uint32_t(read16()) << 16; 146| 0| return result; 147| 0| } 148| 0| uint64_t read64() { 149| 0| uint64_t result = read32(); 150| 0| result |= uint64_t(read32()) << 32; 151| 0| return result; 152| 0| } 153| | 154| |public: 155| | /// Construct a binary decoder. 156| 0| BinaryDecoder(StringRef data) : data(data) {} 157| | 158| | /// Construct a binary decoder. 159| | /// 160| | /// NOTE: The input data is supplied by reference, and its lifetime must 161| | /// exceed that of the decoder. 162| | BinaryDecoder(const std::vector& data) : BinaryDecoder( 163| 0| StringRef(reinterpret_cast(data.data()), data.size())) {} 164| | 165| | /// Check if the decoder is at the end of the stream. 166| 0| bool isEmpty() const { 167| 0| return pos == data.size(); 168| 0| } 169| | 170| | /// Decode a value from the stream. 171| 0| void read(bool& value) { value = read8() != 0; } 172| | 173| | /// Decode a value from the stream. 174| 0| void read(uint8_t& value) { value = read8(); } 175| | 176| | /// Decode a value from the stream. 177| 0| void read(uint16_t& value) { value = read16(); } 178| | 179| | /// Decode a value from the stream. 180| 0| void read(uint32_t& value) { value = read32(); } 181| | 182| | /// Decode a value from the stream. 183| 0| void read(uint64_t& value) { value = read64(); } 184| | 185| | /// Decode a value from the stream. 186| 0| void read(std::string& value) { 187| 0| uint32_t size; 188| 0| read(size); 189| 0| StringRef contents; 190| 0| readBytes(size, contents); 191| 0| value = contents.str(); 192| 0| } 193| | 194| | /// Decode a byte string from the stream. 195| | /// 196| | /// NOTE: The return value points into the decode stream, and must be copied 197| | /// by clients if it is to last longer than the lifetime of the decoder. 198| 0| void readBytes(size_t count, StringRef& value) { 199| 0| assert(pos + count <= data.size()); 200| 0| value = StringRef(data.begin() + pos, count); 201| 0| pos += count; 202| 0| } 203| | 204| | /// Decode a value from the stream. 205| | template 206| 0| void read(T& value) { 207| 0| BinaryCodingTraits::decode(value, *this); 208| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_13FileTimestampEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS_11buildsystem10BuildValue4KindEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_16CommandSignatureEEEvRT_ ------------------ | Unexecuted instantiation: _ZN7llbuild5basic13BinaryDecoder4readINS0_8FileInfoEEEvRT_ ------------------ 209| | 210| | /// Finish decoding and clean up. 211| 0| void finish() { 212| 0| assert(isEmpty()); 213| 0| } 214| |}; 215| | 216| |template<> 217| |struct BinaryCodingTraits { 218| 0| static inline void encode(const StringRef& value, BinaryEncoder& coder) { 219| 0| coder.writeBytes(value); 220| 0| } 221| |}; 222| | 223| |} 224| |} 225| | 226| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/ExecutionQueue.h: 1| |//===- ExecutionQueue.h -----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_EXECUTIONQUEUE_H 14| |#define LLBUILD_BASIC_EXECUTIONQUEUE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/Subprocess.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| | namespace basic { 24| | 25| | /// MARK: Execution Queue 26| | 27| | class ExecutionQueueDelegate; 28| | 29| | /// Description of the queue job, used for scheduling and diagnostics. 30| | class JobDescriptor { 31| | public: 32| 0| JobDescriptor() {} 33| | virtual ~JobDescriptor(); 34| | 35| | /// Get a name used for ordering this job 36| | virtual StringRef getOrdinalName() const = 0; 37| | 38| | /// Get a short description of the command, for use in status reporting. 39| | virtual void getShortDescription(SmallVectorImpl &result) const = 0; 40| | 41| | /// Get a verbose description of the command, for use in status reporting. 42| | virtual void getVerboseDescription(SmallVectorImpl &result) const = 0; 43| | }; 44| | 45| | 46| | /// Opaque type which allows the queue implementation to maintain additional 47| | /// state and associate subsequent requests (e.g., \see executeProcess()) 48| | /// with the dispatching job. 49| | class QueueJobContext { 50| | public: 51| | virtual ~QueueJobContext(); 52| | virtual unsigned laneID() const = 0; 53| | }; 54| | 55| | /// Wrapper for individual pieces of work that are added to the execution 56| | /// queue. 57| | class QueueJob { 58| | JobDescriptor* desc = nullptr; 59| | 60| | /// The function to execute to do the work. 61| | typedef std::function work_fn_ty; 62| | work_fn_ty work; 63| | 64| | public: 65| | /// Default constructor, for use as a sentinel. 66| 0| QueueJob() {} 67| | 68| | /// General constructor. 69| | QueueJob(JobDescriptor* desc, work_fn_ty work) 70| 0| : desc(desc), work(work) {} 71| | 72| | JobDescriptor* getDescriptor() const { return desc; } 73| | 74| 0| void execute(QueueJobContext* context) { work(context); } 75| | }; 76| | 77| | /// This abstact class encapsulates the interface needed for contributing 78| | /// work which needs to be executed. 79| | class ExecutionQueue { 80| | // DO NOT COPY 81| | ExecutionQueue(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 82| | void operator=(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 83| | ExecutionQueue& operator=(ExecutionQueue&&) LLBUILD_DELETED_FUNCTION; 84| | 85| | ExecutionQueueDelegate& delegate; 86| | 87| | public: 88| | ExecutionQueue(ExecutionQueueDelegate& delegate); 89| | virtual ~ExecutionQueue(); 90| | 91| | /// @name Accessors 92| | /// @{ 93| | 94| | ExecutionQueueDelegate& getDelegate() { return delegate; } 95| 0| const ExecutionQueueDelegate& getDelegate() const { return delegate; } 96| | 97| | /// @} 98| | 99| | /// Add a job to be executed. 100| | virtual void addJob(QueueJob job) = 0; 101| | 102| | /// Cancel all jobs and subprocesses of this queue. 103| | virtual void cancelAllJobs() = 0; 104| | 105| | 106| | /// @name Execution Interfaces 107| | /// 108| | /// These are additional interfaces provided by the execution queue which 109| | /// can be invoked by the individual \see QueueJob::execute() to perform 110| | /// particular actions. The benefit of delegating to the execution queue 111| | /// to perform these actions is that the queue can potentially do a better 112| | /// job of scheduling activities. 113| | /// 114| | /// @{ 115| | 116| | /// Execute the given command line. 117| | /// 118| | /// This will launch and execute the given command line and wait for it to 119| | /// complete or release its execution lane. 120| | /// 121| | /// \param context The context object passed to the job's worker function. 122| | /// 123| | /// \param commandLine The command line to execute. 124| | /// 125| | /// \param environment The environment to launch with. 126| | /// 127| | /// \param completionFn An optional function that, if supplied, will be 128| | /// run following the completion of the process. This may be run 129| | /// asynchronously from another thread if the executed process asks the 130| | /// system to release its execution lane. Callers should put cleanup and 131| | /// notification work here. 132| | /// 133| | /// \param inheritEnvironment If true, the supplied environment will be 134| | /// overlayed on top base environment supplied when creating the queue. If 135| | /// false, only the supplied environment will be passed to the subprocess. 136| | /// 137| | /// \param attributes Additional attributes for the process to be spawned. 138| | // 139| | // FIXME: This interface will need to get more complicated, and provide the 140| | // command result and facilities for dealing with the output. 141| | virtual void 142| | executeProcess(QueueJobContext* context, 143| | ArrayRef commandLine, 144| | ArrayRef> environment, 145| | bool inheritEnvironment = true, 146| | ProcessAttributes attributes = {true}, 147| | llvm::Optional completionFn = {llvm::None}) = 0; 148| | 149| | /// @} 150| | 151| | /// Execute the given command, using an inherited environment. 152| | ProcessStatus executeProcess(QueueJobContext* context, 153| | ArrayRef commandLine); 154| | 155| | /// Execute the given command using "/bin/sh". 156| | /// 157| | /// This will launch and execute the given command line and wait for it to 158| | /// complete. 159| | /// 160| | /// \param context The context object passed to the job's worker function. 161| | /// \param command The command to execute. 162| | /// \returns True on success. 163| | // 164| | // FIXME: This interface will need to get more complicated, and provide the 165| | // command result and facilities for dealing with the output. 166| | bool executeShellCommand(QueueJobContext* context, StringRef command); 167| | 168| | }; 169| | 170| | /// Delegate interface for execution queue status. 171| | /// 172| | /// All delegate interfaces are invoked synchronously by the execution queue, 173| | /// and should defer any long running operations to avoid blocking the queue 174| | /// unnecessarily. 175| | /// 176| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, which 177| | /// will arrive concurrently and without any specified thread. 178| | class ExecutionQueueDelegate : public ProcessDelegate { 179| | // DO NOT COPY 180| | ExecutionQueueDelegate(const ExecutionQueueDelegate&) 181| | LLBUILD_DELETED_FUNCTION; 182| | void operator=(const ExecutionQueueDelegate&) LLBUILD_DELETED_FUNCTION; 183| | ExecutionQueueDelegate &operator=(ExecutionQueueDelegate&& rhs) 184| | LLBUILD_DELETED_FUNCTION; 185| | 186| | public: 187| 0| ExecutionQueueDelegate() {} 188| | virtual ~ExecutionQueueDelegate(); 189| | 190| | /// Called when a command's job has been started. 191| | /// 192| | /// The queue guarantees that any jobStarted() call will be paired with 193| | /// exactly one \see jobFinished() call. 194| | // 195| | // FIXME: We may eventually want to allow the individual job to provide 196| | // some additional context here, for complex commands. 197| | // 198| | // FIXME: Design a way to communicate the "lane" here, for use in "super 199| | // console" like UIs. 200| | virtual void queueJobStarted(JobDescriptor*) = 0; 201| | 202| | /// Called when a command's job has been finished. 203| | /// 204| | /// NOTE: This callback is invoked by the queue without any understanding 205| | /// of how the command is tied to the engine. In particular, it is almost 206| | /// always the case that the command will have already completed from the 207| | /// perspective of the low-level engine (and its dependents may have 208| | /// started executing). Clients which want to understand when a command is 209| | /// complete before the engine has been notified as such should use \see 210| | /// BuildSystem::commandFinished(). 211| | virtual void queueJobFinished(JobDescriptor*) = 0; 212| | }; 213| | 214| | // MARK: Lane Based Execution Queue 215| | 216| | enum class SchedulerAlgorithm { 217| | /// Name priority queue based scheduling [default] 218| | NamePriority = 0, 219| | 220| | /// First in, first out 221| | FIFO = 1 222| | }; 223| | 224| | /// Create an execution queue that schedules jobs to individual lanes with a 225| | /// capped limit on the number of concurrent lanes. 226| | ExecutionQueue* createLaneBasedExecutionQueue( 227| | ExecutionQueueDelegate& delegate, int numLanes, SchedulerAlgorithm alg, 228| | const char* const* environment); 229| | } 230| |} 231| | 232| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileInfo.h: 1| |//===- FileInfo.h -----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file contains the FileInfo wrapper which is shared by the Ninja and 14| |// BuildSystem libraries. 15| |// 16| |// FIXME: I am ambivalent about this living in Basic, I want all non-functional 17| |// pieces to generally be pretty isolated (and ideally always mediated by a 18| |// delegate access). We may eventually want a specific FileSystem component for 19| |// dealing with efficient and abstracted access to the file system and 20| |// containing other pieces (like stat caching, or dealing with distribution or 21| |// virtualization). 22| |// 23| |//===----------------------------------------------------------------------===// 24| | 25| |#ifndef LLBUILD_BASIC_FILEINFO_H 26| |#define LLBUILD_BASIC_FILEINFO_H 27| | 28| |#include "BinaryCoding.h" 29| | 30| |#include 31| |#include 32| | 33| |namespace llbuild { 34| |namespace basic { 35| | 36| |/// File timestamp wrapper. 37| |struct FileTimestamp { 38| | uint64_t seconds; 39| | uint64_t nanoseconds; 40| | 41| 0| bool operator==(const FileTimestamp& rhs) const { 42| 0| return seconds == rhs.seconds && nanoseconds == rhs.nanoseconds; 43| 0| } 44| 0| bool operator!=(const FileTimestamp& rhs) const { 45| 0| return !(*this == rhs); 46| 0| } 47| 0| bool operator<(const FileTimestamp& rhs) const { 48| 0| return (seconds < rhs.seconds || 49| 0| (seconds == rhs.seconds && nanoseconds < rhs.nanoseconds)); 50| 0| } 51| 0| bool operator<=(const FileTimestamp& rhs) const { 52| 0| return (seconds < rhs.seconds || 53| 0| (seconds == rhs.seconds && nanoseconds <= rhs.nanoseconds)); 54| 0| } 55| 0| bool operator>(const FileTimestamp& rhs) const { 56| 0| return rhs < *this; 57| 0| } 58| 0| bool operator>=(const FileTimestamp& rhs) const { 59| 0| return rhs <= *this; 60| 0| } 61| |}; 62| | 63| |/// File information which is intended to be used as a proxy for when a file has 64| |/// changed. 65| |/// 66| |/// This structure is intentionally sized to have no packing holes. 67| |struct FileInfo { 68| | /// The device number. 69| | uint64_t device; 70| | /// The inode number. 71| | uint64_t inode; 72| | /// The mode flags of the file. 73| | uint64_t mode; 74| | /// The size of the file. 75| | uint64_t size; 76| | /// The modification time of the file. 77| | FileTimestamp modTime; 78| | 79| | /// Check if this is a FileInfo representing a missing file. 80| 0| bool isMissing() const { 81| 0| // We use an all-zero FileInfo as a sentinel, under the assumption this can 82| 0| // never exist in normal circumstances. 83| 0| return (device == 0 && inode == 0 && mode == 0 && size == 0 && 84| 0| modTime.seconds == 0 && modTime.nanoseconds == 0); 85| 0| } 86| | 87| | /// Check if the FileInfo corresponds to a directory. 88| | bool isDirectory() const; 89| | 90| 0| bool operator==(const FileInfo& rhs) const { 91| 0| return (device == rhs.device && 92| 0| inode == rhs.inode && 93| 0| size == rhs.size && 94| 0| modTime == rhs.modTime); 95| 0| } 96| 0| bool operator!=(const FileInfo& rhs) const { 97| 0| return !(*this == rhs); 98| 0| } 99| | 100| | /// Get the information to represent the state of the given node in the file 101| | /// system. 102| | /// 103| | /// \param asLink If yes, checks the information for the file path without 104| | /// looking through symbolic links. 105| | /// 106| | /// \returns The FileInfo for the given path, which will be missing if the 107| | /// path does not exist (or any error was encountered). 108| | static FileInfo getInfoForPath(const std::string& path, bool asLink = false); 109| |}; 110| | 111| |template<> 112| |struct BinaryCodingTraits { 113| 0| static inline void encode(const FileTimestamp& value, BinaryEncoder& coder) { 114| 0| coder.write(value.seconds); 115| 0| coder.write(value.nanoseconds); 116| 0| } 117| 0| static inline void decode(FileTimestamp& value, BinaryDecoder& coder) { 118| 0| coder.read(value.seconds); 119| 0| coder.read(value.nanoseconds); 120| 0| } 121| |}; 122| | 123| |template<> 124| |struct BinaryCodingTraits { 125| 0| static inline void encode(const FileInfo& value, BinaryEncoder& coder) { 126| 0| coder.write(value.device); 127| 0| coder.write(value.inode); 128| 0| coder.write(value.mode); 129| 0| coder.write(value.size); 130| 0| coder.write(value.modTime); 131| 0| } 132| 0| static inline void decode(FileInfo& value, BinaryDecoder& coder) { 133| 0| coder.read(value.device); 134| 0| coder.read(value.inode); 135| 0| coder.read(value.mode); 136| 0| coder.read(value.size); 137| 0| coder.read(value.modTime); 138| 0| } 139| |}; 140| | 141| |} 142| |} 143| | 144| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileSystem.h: 1| |//===- FileSystem.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_FILESYSTEM_H 14| |#define LLBUILD_BASIC_FILESYSTEM_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/FileInfo.h" 18| |#include "llbuild/Basic/LLVM.h" 19| | 20| |#include "llvm/Support/ErrorOr.h" 21| | 22| |#include 23| | 24| |namespace llvm { 25| | 26| |class MemoryBuffer; 27| | 28| |} 29| | 30| |namespace llbuild { 31| |namespace basic { 32| | 33| |// Abstract interface for interacting with a file system. This allows mocking of 34| |// operations for testing, and for clients to provide virtualized interfaces. 35| |class FileSystem { 36| | // DO NOT COPY 37| | FileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 38| | void operator=(const FileSystem&) LLBUILD_DELETED_FUNCTION; 39| | FileSystem &operator=(FileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 40| | 41| |public: 42| 0| FileSystem() {} 43| | virtual ~FileSystem(); 44| | 45| | /// Create the given directory if it does not exist. 46| | /// 47| | /// \returns True on success (the directory was created, or already exists). 48| | virtual bool 49| | createDirectory(const std::string& path) = 0; 50| | 51| | /// Create the given directory (recursively) if it does not exist. 52| | /// 53| | /// \returns True on success (the directory was created, or already exists). 54| | virtual bool 55| | createDirectories(const std::string& path); 56| | 57| | /// Get a memory buffer for a given file on the file system. 58| | /// 59| | /// \returns The file contents, on success, or null on error. 60| | virtual std::unique_ptr 61| | getFileContents(const std::string& path) = 0; 62| | 63| | /// Remove the file or directory at the given path. 64| | /// 65| | /// Directory removal is recursive. 66| | /// 67| | /// \returns True if the item was removed, false otherwise. 68| | virtual bool remove(const std::string& path) = 0; 69| | 70| | /// Get the information to represent the state of the given path in the file 71| | /// system. 72| | /// 73| | /// \returns The FileInfo for the given path, which will be missing if the 74| | /// path does not exist (or any error was encountered). 75| | virtual FileInfo getFileInfo(const std::string& path) = 0; 76| | 77| | /// Get the information to represent the state of the given path in the file 78| | /// system, without looking through symbolic links. 79| | /// 80| | /// \returns The FileInfo for the given path, which will be missing if the 81| | /// path does not exist (or any error was encountered). 82| | virtual FileInfo getLinkInfo(const std::string& path) = 0; 83| |}; 84| | 85| |/// Create a FileSystem instance suitable for accessing the local filesystem. 86| |std::unique_ptr createLocalFileSystem(); 87| | 88| | 89| |/// Device/inode agnostic filesystem wrapper 90| |class DeviceAgnosticFileSystem : public FileSystem { 91| |private: 92| | std::unique_ptr impl; 93| | 94| |public: 95| | explicit DeviceAgnosticFileSystem(std::unique_ptr fs) 96| | : impl(std::move(fs)) 97| 0| { 98| 0| } 99| | 100| | DeviceAgnosticFileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 101| | void operator=(const DeviceAgnosticFileSystem&) LLBUILD_DELETED_FUNCTION; 102| | DeviceAgnosticFileSystem &operator=(DeviceAgnosticFileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 103| | 104| | static std::unique_ptr from(std::unique_ptr fs); 105| | 106| | 107| | virtual bool 108| | createDirectory(const std::string& path) override { 109| | return impl->createDirectory(path); 110| | } 111| | 112| | virtual bool 113| | createDirectories(const std::string& path) override { 114| | return impl->createDirectories(path); 115| | } 116| | 117| | virtual std::unique_ptr 118| | getFileContents(const std::string& path) override; 119| | 120| | virtual bool remove(const std::string& path) override { 121| | return impl->remove(path); 122| | } 123| | 124| | virtual FileInfo getFileInfo(const std::string& path) override { 125| | auto info = impl->getFileInfo(path); 126| | 127| | // Device and inode numbers may (will) change when relocating files to 128| | // another device. Here we explicitly, unconditionally override them with 0, 129| | // enabling an entire build tree to be relocated or copied yet retain the 130| | // ability to perform incremental builds. 131| | info.device = 0; 132| | info.inode = 0; 133| | 134| | return info; 135| | } 136| | 137| | virtual FileInfo getLinkInfo(const std::string& path) override { 138| | auto info = impl->getLinkInfo(path); 139| | 140| | info.device = 0; 141| | info.inode = 0; 142| | 143| | return info; 144| | } 145| |}; 146| | 147| |} 148| |} 149| | 150| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Hashing.h: 1| |//===- Hashing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_HASHING_H 14| |#define LLBUILD_BASIC_HASHING_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/Hashing.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |namespace llbuild { 23| |namespace basic { 24| | 25| |uint64_t hashString(StringRef value); 26| | 27| |class CommandSignature { 28| |public: 29| 0| CommandSignature() = default; 30| 0| CommandSignature(StringRef string) { 31| 0| value = size_t(llvm::hash_value(string)); 32| 0| } 33| 0| explicit CommandSignature(uint64_t sig) : value(sig) {} 34| | CommandSignature(const CommandSignature& other) = default; 35| | CommandSignature(CommandSignature&& other) = default; 36| | CommandSignature& operator=(const CommandSignature& other) = default; 37| | CommandSignature& operator=(CommandSignature&& other) = default; 38| | 39| 0| bool isNull() const { return value == 0; } 40| | 41| 0| bool operator==(const CommandSignature& other) const { return value == other.value; } 42| 0| bool operator!=(const CommandSignature& other) const { return value != other.value; } 43| | 44| 0| CommandSignature& combine(StringRef string) { 45| 0| // FIXME: Use a more appropriate hashing infrastructure. 46| 0| value = llvm::hash_combine(value, string); 47| 0| return *this; 48| 0| } 49| | 50| 0| CommandSignature& combine(const std::string &string) { 51| 0| // FIXME: Use a more appropriate hashing infrastructure. 52| 0| value = llvm::hash_combine(value, string); 53| 0| return *this; 54| 0| } 55| | 56| 0| CommandSignature& combine(bool b) { 57| 0| // FIXME: Use a more appropriate hashing infrastructure. 58| 0| value = llvm::hash_combine(value, b); 59| 0| return *this; 60| 0| } 61| | 62| | template 63| 0| CommandSignature& combine(const std::vector& list) { 64| 0| for (const auto& v: list) { 65| 0| combine(v); 66| 0| } 67| 0| return *this; 68| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic16CommandSignature7combineIN4llvm9StringRefEEERS1_RKNSt3__16vectorIT_NS6_9allocatorIS8_EEEE ------------------ | Unexecuted instantiation: _ZN7llbuild5basic16CommandSignature7combineINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEERS1_RKNS3_6vectorIT_NS7_ISC_EEEE ------------------ 69| | 70| | uint64_t value = 0; 71| |}; 72| | 73| |template<> 74| |struct BinaryCodingTraits { 75| 0| static inline void encode(const CommandSignature& value, BinaryEncoder& coder) { 76| 0| coder.write(value.value); 77| 0| } 78| 0| static inline void decode(CommandSignature& value, BinaryDecoder& coder) { 79| 0| coder.read(value.value); 80| 0| } 81| |}; 82| | 83| |} 84| |} 85| | 86| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/POSIXEnvironment.h: 1| |//===- POSIXEnvironment.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 14| |#define LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/SmallString.h" 19| |#include "llvm/ADT/StringRef.h" 20| |#include "llvm/ADT/Hashing.h" 21| | 22| |#include 23| |#include 24| |#include 25| | 26| |namespace std { 27| | template<> struct hash { 28| | size_t operator()(const llvm::StringRef& value) const { 29| | return size_t(hash_value(value)); 30| | } 31| | }; 32| |} 33| | 34| |namespace llbuild { 35| |namespace basic { 36| | 37| |/// A helper class for constructing a POSIX-style environment. 38| |class POSIXEnvironment { 39| | /// The actual environment, this is only populated once frozen. 40| | std::vector env; 41| | 42| | /// The underlying string storage. 43| | // 44| | // FIXME: This is not efficient, we could store into a single allocation. 45| | std::vector envStorage; 46| | 47| | /// The list of known keys in the environment. 48| | std::unordered_set keys{}; 49| | 50| | /// Whether the environment pointer has been vended, and assignments can no 51| | /// longer be mutated. 52| | bool isFrozen = false; 53| | 54| |public: 55| 0| POSIXEnvironment() {} 56| | 57| | /// Add a key to the environment, if missing. 58| | /// 59| | /// If the key has already been defined, it will **NOT** be inserted. 60| | void setIfMissing(StringRef key, StringRef value) { 61| | assert(!isFrozen); 62| | if (keys.insert(key).second) { 63| | llvm::SmallString<256> assignment; 64| | assignment += key; 65| | assignment += '='; 66| | assignment += value; 67| | assignment += '\0'; 68| | envStorage.emplace_back(assignment.str()); 69| | } 70| | } 71| | 72| | /// Get the envirnonment pointer. 73| | /// 74| | /// This pointer is only valid for the lifetime of the environment itself. 75| | const char* const* getEnvp() { 76| | isFrozen = true; 77| | 78| | // Form the final environment. 79| | env.clear(); 80| | for (const auto& entry: envStorage) { 81| | env.emplace_back(entry.c_str()); 82| | } 83| | env.emplace_back(nullptr); 84| | return env.data(); 85| | } 86| |}; 87| | 88| |} 89| |} 90| | 91| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/PlatformUtility.h: 1| |//===- PlatformUtility.h ----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file implements small platform compatability wrapper functions for 14| |// common functions. 15| |// 16| |//===----------------------------------------------------------------------===// 17| | 18| |#ifndef LLBUILD_BASIC_PLATFORMUTILITY_H 19| |#define LLBUILD_BASIC_PLATFORMUTILITY_H 20| | 21| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 22| |#include 23| |#include 24| |#include 25| |#if !defined(_WIN32) 26| |#include 27| |#endif 28| | 29| |namespace llbuild { 30| |namespace basic { 31| |namespace sys { 32| | 33| |bool chdir(const char *fileName); 34| |int close(int fileHandle); 35| |bool mkdir(const char *fileName); 36| |int pclose(FILE *stream); 37| |int pipe(int ptHandles[2]); 38| |FILE *popen(const char *command, const char *mode); 39| |int read(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 40| |int rmdir(const char *path); 41| |int symlink(const char *source, const char *target); 42| |int unlink(const char *fileName); 43| |int write(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 44| |std::string strerror(int error); 45| |char *strsep(char **stringp, const char *delim); 46| |// Create a directory in the temporary folder which doesn't exist and return 47| |// it's path. 48| |std::string makeTmpDir(); 49| | 50| |// Return a string containing all valid path separators on the current platform 51| |std::string getPathSeparators(); 52| | 53| |/// Sets the max open file limit to min(max(soft_limit, limit), hard_limit), 54| |/// where soft_limit and hard_limit are gathered from the system. 55| |/// 56| |/// Returns: 0 on success, -1 on failure (check errno). 57| |int raiseOpenFileLimit(llbuild_rlim_t limit = 2048); 58| | 59| |enum MATCH_RESULT { MATCH, NO_MATCH, MATCH_ERROR }; 60| |// Test if a path or filename matches a wildcard pattern 61| |// 62| |// Returns MATCH if a match is detected, NO_MATCH if there is no match, and 63| |// MATCH_ERROR on error. Windows callers may use GetLastError to get additional 64| |// error information. 65| |MATCH_RESULT filenameMatch(const std::string& pattern, const std::string& filename); 66| | 67| |void sleep(int seconds); 68| |template struct FileDescriptorTraits; 69| | 70| |#if defined(_WIN32) 71| |template <> struct FileDescriptorTraits { 72| | static void Close(HANDLE hFile) { CloseHandle(hFile); } 73| | static int Read(HANDLE hFile, void *destinationBuffer, 74| | unsigned int maxCharCount) { 75| | DWORD numBytes; 76| | if (!ReadFile(hFile, destinationBuffer, maxCharCount, &numBytes, nullptr)) { 77| | return -1; 78| | } 79| | return numBytes; 80| | } 81| |}; 82| |#endif 83| |template <> struct FileDescriptorTraits { 84| 0| static void Close(int fd) { close(fd); } 85| | static int Read(int hFile, void *destinationBuffer, 86| | unsigned int maxCharCount) { 87| | return read(hFile, destinationBuffer, maxCharCount); 88| | } 89| |}; 90| |} 91| |} 92| |} 93| | 94| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/StringList.h: 1| |//===- StringList.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_STRINGLIST_H 14| |#define LLBUILD_BASIC_STRINGLIST_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| | 18| |#include 19| | 20| |namespace llbuild { 21| |namespace basic { 22| | 23| |/// A list of strings particularly suited for use in binary coding 24| |class StringList { 25| |private: 26| | /// The values are packed as a sequence of C strings. 27| | char* contents = nullptr; 28| | 29| | /// The total length of the contents. 30| | uint64_t size = 0; 31| | 32| |public: 33| 0| StringList() {} 34| 0| StringList(basic::BinaryDecoder& decoder) { 35| 0| decoder.read(size); 36| 0| StringRef contents; 37| 0| decoder.readBytes(size, contents); 38| 0| this->contents = new char[size]; 39| 0| memcpy(this->contents, contents.data(), contents.size()); 40| 0| } 41| 0| ~StringList() { 42| 0| if (contents != nullptr) 43| 0| delete [] contents; 44| 0| } 45| | 46| 0| explicit StringList(StringRef value) { 47| 0| size = value.size() + 1; 48| 0| contents = new char[size]; 49| 0| assert(value.find('\0') == StringRef::npos); 50| 0| memcpy(contents, value.data(), value.size()); 51| 0| contents[size - 1] = '\0'; 52| 0| } 53| | 54| | template 55| 0| explicit StringList(const ArrayRef values) { 56| 0| // Construct the concatenated data. 57| 0| for (auto value: values) { 58| 0| size += value.size() + 1; 59| 0| } 60| 0| // Make sure to allocate at least 1 byte. 61| 0| char* p = nullptr; 62| 0| contents = p = new char[size + 1]; 63| 0| for (auto value: values) { 64| 0| assert(value.find('\0') == StringRef::npos); 65| 0| memcpy(p, value.data(), value.size()); 66| 0| p += value.size(); 67| 0| *p++ = '\0'; 68| 0| } 69| 0| *p = '\0'; 70| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild5basic10StringListC2IN4llvm9StringRefEEENS3_8ArrayRefIT_EE ------------------ | Unexecuted instantiation: _ZN7llbuild5basic10StringListC2INSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEN4llvm8ArrayRefIT_EE ------------------ 71| | 72| | // StringList can only be moved, not copied 73| 0| StringList(StringList&& rhs) : contents(rhs.contents), size(rhs.size) { 74| 0| rhs.size = 0; 75| 0| rhs.contents = nullptr; 76| 0| } 77| | 78| 0| StringList& operator=(StringList&& rhs) { 79| 0| if (this != &rhs) { 80| 0| size = rhs.size; 81| 0| if (contents != nullptr) 82| 0| delete [] contents; 83| 0| contents = rhs.contents; 84| 0| rhs.contents = nullptr; 85| 0| } 86| 0| return *this; 87| 0| } 88| | 89| 0| std::vector getValues() const { 90| 0| std::vector result; 91| 0| for (uint64_t i = 0; i < size;) { 92| 0| auto value = StringRef(&contents[i]); 93| 0| assert(i + value.size() <= size); 94| 0| result.push_back(value); 95| 0| i += value.size() + 1; 96| 0| } 97| 0| return result; 98| 0| } 99| | 100| 0| bool isEmpty() const { return size == 0; } 101| | 102| 0| void encode(BinaryEncoder& coder) const { 103| 0| coder.write(size); 104| 0| coder.writeBytes(StringRef(contents, size)); 105| 0| } 106| |}; 107| | 108| |template<> 109| |struct BinaryCodingTraits { 110| 0| static inline void encode(const StringList& value, BinaryEncoder& coder) { 111| 0| value.encode(coder); 112| 0| } 113| | 114| 0| static inline void decode(StringList& value, BinaryDecoder& coder) { 115| 0| value = StringList(coder); 116| 0| } 117| |}; 118| | 119| |} 120| |} 121| | 122| |#endif /* StringList_h */ 123| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Subprocess.h: 1| |//===- Subprocess.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_SUBPROCESS_H 14| |#define LLBUILD_BASIC_SUBPROCESS_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/POSIXEnvironment.h" 20| | 21| |#include "llvm/ADT/Optional.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| | 29| |namespace llbuild { 30| | namespace basic { 31| | 32| | // MARK: Quality of Service 33| | 34| | enum class QualityOfService { 35| | /// A default quality of service (i.e. what the system would use without 36| | /// other advisement, generally this would be comparable to what would be 37| | /// done by `make`, `ninja`, etc.) 38| | Normal, 39| | 40| | /// User-initiated, high priority work. 41| | UserInitiated, 42| | 43| | /// Batch work performed on behalf of the user. 44| | Utility, 45| | 46| | /// Background work that is not directly visible to the user. 47| | Background 48| | }; 49| | 50| | QualityOfService getDefaultQualityOfService(); 51| | void setDefaultQualityOfService(QualityOfService level); 52| | 53| | void setCurrentThreadQualityOfService(QualityOfService level); 54| | 55| | 56| | // MARK: Process Info 57| | 58| | /// Handle used to communicate information about a launched process. 59| | struct ProcessHandle { 60| | /// Opaque ID. 61| | uint64_t id; 62| | }; 63| | 64| | struct ProcessInfo { 65| | /// Whether the process can be safely interrupted. 66| | bool canSafelyInterrupt; 67| | }; 68| | 69| | 70| | // MARK: Process Group 71| | 72| | class ProcessGroup { 73| | ProcessGroup(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 74| | void operator=(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 75| | ProcessGroup& operator=(ProcessGroup&&) LLBUILD_DELETED_FUNCTION; 76| | 77| | std::unordered_map processes; 78| | std::condition_variable processesCondition; 79| | bool closed = false; 80| | 81| | public: 82| 0| ProcessGroup() {} 83| | ~ProcessGroup(); 84| | 85| | std::mutex mutex; 86| | 87| 0| void close() { closed = true; } 88| | bool isClosed() const { return closed; } 89| | 90| | void add(std::lock_guard&& lock, llbuild_pid_t pid, 91| 0| ProcessInfo info) { 92| 0| processes.emplace(std::make_pair(pid, info)); 93| 0| } 94| | 95| 0| void remove(llbuild_pid_t pid) { 96| 0| { 97| 0| std::lock_guard lock(mutex); 98| 0| processes.erase(pid); 99| 0| } 100| 0| processesCondition.notify_all(); 101| 0| } 102| | 103| | void signalAll(int signal); 104| | }; 105| | 106| | 107| | // MARK: Process Execution 108| | 109| | /// Status of a process execution. 110| | enum class ProcessStatus { 111| | Succeeded = 0, 112| | Failed, 113| | Cancelled, 114| | Skipped, 115| | }; 116| | 117| | /// Result of a process execution. 118| | struct ProcessResult { 119| | 120| | /// The final status of the command 121| | ProcessStatus status; 122| | 123| | /// Process exit code 124| | int exitCode; 125| | 126| | /// Process identifier (can be -1 for failure reasons) 127| | llbuild_pid_t pid; 128| | 129| | /// User time (in us) 130| | uint64_t utime; 131| | 132| | /// System time (in us) 133| | uint64_t stime; 134| | 135| | /// Max RSS (in bytes) 136| | uint64_t maxrss; 137| | 138| | ProcessResult(ProcessStatus status, int exitCode = -1, 139| | llbuild_pid_t pid = (llbuild_pid_t)-1, uint64_t utime = 0, 140| | uint64_t stime = 0, uint64_t maxrss = 0) 141| | : status(status), exitCode(exitCode), pid(pid), utime(utime), 142| 0| stime(stime), maxrss(maxrss) {} 143| | 144| | static ProcessResult makeFailed(int exitCode = -1) { 145| | return ProcessResult(ProcessStatus::Failed, exitCode); 146| | } 147| | 148| | static ProcessResult makeCancelled(int exitCode = -1) { 149| | return ProcessResult(ProcessStatus::Cancelled, exitCode); 150| | } 151| | }; 152| | 153| | 154| | typedef std::function&&)> ProcessReleaseFn; 155| | typedef std::function ProcessCompletionFn; 156| | 157| | 158| | /// Opaque context passed on to the delegate 159| | struct ProcessContext; 160| | 161| | /// Delegate interface for process execution. 162| | /// 163| | /// All delegate interfaces are invoked synchronously by the subprocess 164| | /// methods (as called by the execution queue, for example) and should defer 165| | /// any long running operations to avoid blocking the queue unnecessarily. 166| | /// 167| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, 168| | /// which will arrive concurrently and without any specified thread. 169| | class ProcessDelegate { 170| | // DO NOT COPY 171| | ProcessDelegate(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 172| | void operator=(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 173| | ProcessDelegate& operator=(ProcessDelegate&& rhs) LLBUILD_DELETED_FUNCTION; 174| | 175| | public: 176| 0| ProcessDelegate() {} 177| | virtual ~ProcessDelegate(); 178| | 179| | /// Called when the external process has started executing. 180| | /// 181| | /// The subprocess code guarantees that any processStarted() call will be 182| | /// paired with exactly one \see processFinished() call. 183| | /// 184| | /// \param ctx - Opaque context passed on to the delegate 185| | /// \param handle - A unique handle used in subsequent delegate calls to 186| | /// identify the process. This handle should only be used to associate 187| | /// different status calls relating to the same process. It is only 188| | /// guaranteed to be unique from when it has been provided here to when it 189| | /// has been provided to the \see processFinished() call. 190| | virtual void processStarted(ProcessContext* ctx, ProcessHandle handle) = 0; 191| | 192| | /// Called to report an error in the management of a command process. 193| | /// 194| | /// \param ctx - Opaque context passed on to the delegate 195| | /// \param handle - The process handle. 196| | /// \param message - The error message. 197| | // 198| | // FIXME: Need to move to more structured error handling. 199| | virtual void processHadError(ProcessContext* ctx, ProcessHandle handle, 200| | const Twine& message) = 0; 201| | 202| | /// Called to report a command processes' (merged) standard output and error. 203| | /// 204| | /// \param ctx - Opaque context passed on to the delegate 205| | /// \param handle - The process handle. 206| | /// \param data - The process output. 207| | virtual void processHadOutput(ProcessContext* ctx, ProcessHandle handle, 208| | StringRef data) = 0; 209| | 210| | /// Called when a command's job has finished executing an external process. 211| | /// 212| | /// \param ctx - Opaque context passed on to the delegate 213| | /// \param handle - The handle used to identify the process. This handle 214| | /// will become invalid as soon as the client returns from this API call. 215| | /// \param result - Whether the process suceeded, failed or was cancelled. 216| | // 217| | // FIXME: Need to include additional information on the status here, e.g., the 218| | // signal status, and the process output (if buffering). 219| | virtual void processFinished(ProcessContext* ctx, ProcessHandle handle, 220| | const ProcessResult& result) = 0; 221| | }; 222| | 223| | 224| | struct ProcessAttributes { 225| | /// If true, whether it is safe to attempt to SIGINT the process to cancel 226| | /// it. If false, the process won't be interrupted during cancellation and 227| | /// will be given a chance to complete (if it fails to complete it will 228| | /// ultimately be sent a SIGKILL). 229| | bool canSafelyInterrupt; 230| | 231| | /// If set, the working directory to change into before spawning (support 232| | /// not guaranteed on all platforms). 233| | StringRef workingDir = {}; 234| | 235| | /// If true, exposes a control file descriptor that may be used to 236| | /// communicate with the build system. 237| | bool controlEnabled = true; 238| | }; 239| | 240| | /// Execute the given command line. 241| | /// 242| | /// This will launch and execute the given command line and wait for it to 243| | /// complete or release its execution lane. 244| | /// 245| | /// \param delegate The process delegate. 246| | /// 247| | /// \param ctx The context object passed to the delegate. 248| | /// 249| | /// \param pgrp The process group in which to track this process. 250| | /// 251| | /// \param handle The handle object passed to the delegate. 252| | /// 253| | /// \param commandLine The command line to execute. 254| | /// 255| | /// \param environment The environment to launch with. 256| | /// 257| | /// \param attributes Additional attributes for the process to be spawned. 258| | /// 259| | /// \param releaseFn Functional called when a process wishes to release its 260| | /// exclusive access to build system resources (namely an execution lane). 261| | /// 262| | /// \param completionFn An optional function that, if supplied, will be run 263| | /// following the completion of the process. This may be run asynchronously 264| | /// from another thread if the executed process asks the system to release 265| | /// its execution lane. Callers should put cleanup and notification work 266| | /// here. 267| | /// 268| | // 269| | // FIXME: This interface will need to get more complicated, and provide the 270| | // command result and facilities for dealing with the output. 271| | void spawnProcess(ProcessDelegate& delegate, 272| | ProcessContext* ctx, 273| | ProcessGroup& pgrp, 274| | ProcessHandle handle, 275| | ArrayRef commandLine, 276| | POSIXEnvironment environment, 277| | ProcessAttributes attributes, 278| | ProcessReleaseFn&& releaseFn, 279| | ProcessCompletionFn&& completionFn); 280| | 281| | /// @} 282| | 283| | } 284| |} 285| | 286| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildDescription.cpp: 1| |//===-- BuildDescription.cpp ----------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildDescription.h" 14| | 15| |using namespace llbuild; 16| |using namespace llbuild::buildsystem; 17| | 18| 0|Node::~Node() {} 19| | 20| 0|Command::~Command() {} 21| | 22| 0|Tool::~Tool() {} 23| | 24| 0|std::unique_ptr Tool::createCustomCommand(const BuildKey& key) { 25| 0| return nullptr; 26| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildFile.cpp: 1| |//===-- BuildFile.cpp -----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildFile.h" 14| | 15| |#include "llbuild/Basic/FileSystem.h" 16| |#include "llbuild/Basic/LLVM.h" 17| |#include "llbuild/BuildSystem/BuildDescription.h" 18| | 19| |#include "llvm/ADT/STLExtras.h" 20| |#include "llvm/Support/MemoryBuffer.h" 21| |#include "llvm/Support/SourceMgr.h" 22| |#include "llvm/Support/YAMLParser.h" 23| | 24| |using namespace llbuild; 25| |using namespace llbuild::buildsystem; 26| | 27| 0|void ConfigureContext::error(const Twine& message) const { 28| 0| delegate.error(filename, at, message); 29| 0|} 30| | 31| 0|BuildFileDelegate::~BuildFileDelegate() {} 32| | 33| |#pragma mark - BuildFile implementation 34| | 35| |namespace { 36| | 37| |#ifndef NDEBUG 38| |static void dumpNode(llvm::yaml::Node* node, unsigned indent=0) 39| | LLVM_ATTRIBUTE_USED; 40| 0|static void dumpNode(llvm::yaml::Node* node, unsigned indent) { 41| 0| switch (node->getType()) { 42| 0| default: { 43| 0| fprintf(stderr, "%*s\n", indent*2, "", node); 44| 0| break; 45| 0| } 46| 0| 47| 0| case llvm::yaml::Node::NK_Null: { 48| 0| fprintf(stderr, "%*s(null)\n", indent*2, ""); 49| 0| break; 50| 0| } 51| 0| 52| 0| case llvm::yaml::Node::NK_Scalar: { 53| 0| llvm::yaml::ScalarNode* scalar = llvm::cast(node); 54| 0| SmallString<256> storage; 55| 0| fprintf(stderr, "%*s(scalar: '%s')\n", indent*2, "", 56| 0| scalar->getValue(storage).str().c_str()); 57| 0| break; 58| 0| } 59| 0| 60| 0| case llvm::yaml::Node::NK_KeyValue: { 61| 0| assert(0 && "unexpected keyvalue node"); 62| 0| break; 63| 0| } 64| 0| 65| 0| case llvm::yaml::Node::NK_Mapping: { 66| 0| llvm::yaml::MappingNode* map = llvm::cast(node); 67| 0| fprintf(stderr, "%*smap:\n", indent*2, ""); 68| 0| for (auto& it: *map) { 69| 0| fprintf(stderr, "%*skey:\n", (indent+1)*2, ""); 70| 0| dumpNode(it.getKey(), indent+2); 71| 0| fprintf(stderr, "%*svalue:\n", (indent+1)*2, ""); 72| 0| dumpNode(it.getValue(), indent+2); 73| 0| } 74| 0| break; 75| 0| } 76| 0| 77| 0| case llvm::yaml::Node::NK_Sequence: { 78| 0| llvm::yaml::SequenceNode* sequence = 79| 0| llvm::cast(node); 80| 0| fprintf(stderr, "%*ssequence:\n", indent*2, ""); 81| 0| for (auto& it: *sequence) { 82| 0| dumpNode(&it, indent+1); 83| 0| } 84| 0| break; 85| 0| } 86| 0| 87| 0| case llvm::yaml::Node::NK_Alias: { 88| 0| fprintf(stderr, "%*s(alias)\n", indent*2, ""); 89| 0| break; 90| 0| } 91| 0| } 92| 0|} 93| |#endif 94| | 95| |class BuildFileImpl { 96| | /// The name of the main input file. 97| | std::string mainFilename; 98| | 99| | /// The delegate the BuildFile was configured with. 100| | BuildFileDelegate& delegate; 101| | 102| | /// The set of all registered tools. 103| | BuildDescription::tool_set tools; 104| | 105| | /// The set of all declared targets. 106| | BuildDescription::target_set targets; 107| | 108| | /// Default target name 109| | std::string defaultTarget; 110| | 111| | /// The set of all declared nodes. 112| | BuildDescription::node_set nodes; 113| | 114| | /// The set of all declared commands. 115| | BuildDescription::command_set commands; 116| | 117| | /// The number of parsing errors. 118| | int numErrors = 0; 119| | 120| | // FIXME: Factor out into a parser helper class. 121| 0| std::string stringFromScalarNode(llvm::yaml::ScalarNode* scalar) { 122| 0| SmallString<256> storage; 123| 0| return scalar->getValue(storage).str(); 124| 0| } 125| | 126| | /// Emit an error. 127| | void error(StringRef filename, llvm::SMRange at, 128| 0| StringRef message) { 129| 0| BuildFileToken atToken{at.Start.getPointer(), 130| 0| unsigned(at.End.getPointer()-at.Start.getPointer())}; 131| 0| delegate.error(mainFilename, atToken, message); 132| 0| ++numErrors; 133| 0| } 134| | 135| 0| void error(StringRef message) { 136| 0| error(mainFilename, {}, message); 137| 0| } 138| | 139| 0| void error(llvm::yaml::Node* node, StringRef message) { 140| 0| error(mainFilename, node->getSourceRange(), message); 141| 0| } 142| | 143| 0| ConfigureContext getContext(llvm::SMRange at) { 144| 0| BuildFileToken atToken{at.Start.getPointer(), 145| 0| unsigned(at.End.getPointer()-at.Start.getPointer())}; 146| 0| return ConfigureContext{ delegate, mainFilename, atToken }; 147| 0| } 148| | 149| 0| ConfigureContext getContext(llvm::yaml::Node *node) { 150| 0| return getContext(node->getSourceRange()); 151| 0| } 152| | 153| | // FIXME: Factor out into a parser helper class. 154| 0| bool nodeIsScalarString(llvm::yaml::Node* node, StringRef name) { 155| 0| if (node->getType() != llvm::yaml::Node::NK_Scalar) 156| 0| return false; 157| 0| 158| 0| return stringFromScalarNode( 159| 0| static_cast(node)) == name; 160| 0| } 161| | 162| 0| Tool* getOrCreateTool(StringRef name, llvm::yaml::Node* forNode) { 163| 0| // First, check the map. 164| 0| auto it = tools.find(name); 165| 0| if (it != tools.end()) 166| 0| return it->second.get(); 167| 0| 168| 0| // Otherwise, ask the delegate to create the tool. 169| 0| auto tool = delegate.lookupTool(name); 170| 0| if (!tool) { 171| 0| error(forNode, "invalid tool type in 'tools' map"); 172| 0| return nullptr; 173| 0| } 174| 0| auto result = tool.get(); 175| 0| tools[name] = std::move(tool); 176| 0| 177| 0| return result; 178| 0| } 179| | 180| 0| Node* getOrCreateNode(StringRef name, bool isImplicit) { 181| 0| // First, check the map. 182| 0| auto it = nodes.find(name); 183| 0| if (it != nodes.end()) 184| 0| return it->second.get(); 185| 0| 186| 0| // Otherwise, ask the delegate to create the node. 187| 0| auto node = delegate.lookupNode(name, isImplicit); 188| 0| assert(node); 189| 0| auto result = node.get(); 190| 0| nodes[name] = std::move(node); 191| 0| 192| 0| return result; 193| 0| } 194| | 195| 0| bool parseRootNode(llvm::yaml::Node* node) { 196| 0| // The root must always be a mapping. 197| 0| if (node->getType() != llvm::yaml::Node::NK_Mapping) { 198| 0| error(node, "unexpected top-level node"); 199| 0| return false; 200| 0| } 201| 0| auto mapping = static_cast(node); 202| 0| 203| 0| // Iterate over each of the sections in the mapping. 204| 0| auto it = mapping->begin(); 205| 0| if (!nodeIsScalarString(it->getKey(), "client")) { 206| 0| error(it->getKey(), "expected initial mapping key 'client'"); 207| 0| return false; 208| 0| } 209| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 210| 0| error(it->getValue(), "unexpected 'client' value (expected map)"); 211| 0| return false; 212| 0| } 213| 0| 214| 0| // Parse the client mapping. 215| 0| if (!parseClientMapping( 216| 0| static_cast(it->getValue()))) { 217| 0| return false; 218| 0| } 219| 0| ++it; 220| 0| 221| 0| // Parse the tools mapping, if present. 222| 0| if (it != mapping->end() && nodeIsScalarString(it->getKey(), "tools")) { 223| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 224| 0| error(it->getValue(), "unexpected 'tools' value (expected map)"); 225| 0| return false; 226| 0| } 227| 0| 228| 0| if (!parseToolsMapping( 229| 0| static_cast(it->getValue()))) { 230| 0| return false; 231| 0| } 232| 0| ++it; 233| 0| } 234| 0| 235| 0| // Parse the targets mapping, if present. 236| 0| if (it != mapping->end() && nodeIsScalarString(it->getKey(), "targets")) { 237| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 238| 0| error(it->getValue(), "unexpected 'targets' value (expected map)"); 239| 0| return false; 240| 0| } 241| 0| 242| 0| if (!parseTargetsMapping( 243| 0| static_cast(it->getValue()))) { 244| 0| return false; 245| 0| } 246| 0| ++it; 247| 0| } 248| 0| 249| 0| // Parse the default target, if present. 250| 0| if (it != mapping->end() && nodeIsScalarString(it->getKey(), "default")) { 251| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 252| 0| error(it->getValue(), "unexpected 'default' target value (expected scalar)"); 253| 0| return false; 254| 0| } 255| 0| 256| 0| if (!parseDefaultTarget( 257| 0| static_cast(it->getValue()))) { 258| 0| return false; 259| 0| } 260| 0| ++it; 261| 0| } 262| 0| 263| 0| // Parse the nodes mapping, if present. 264| 0| if (it != mapping->end() && nodeIsScalarString(it->getKey(), "nodes")) { 265| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 266| 0| error(it->getValue(), "unexpected 'nodes' value (expected map)"); 267| 0| return false; 268| 0| } 269| 0| 270| 0| if (!parseNodesMapping( 271| 0| static_cast(it->getValue()))) { 272| 0| return false; 273| 0| } 274| 0| ++it; 275| 0| } 276| 0| 277| 0| // Parse the commands mapping, if present. 278| 0| if (it != mapping->end() && nodeIsScalarString(it->getKey(), "commands")) { 279| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 280| 0| error(it->getValue(), "unexpected 'commands' value (expected map)"); 281| 0| return false; 282| 0| } 283| 0| 284| 0| if (!parseCommandsMapping( 285| 0| static_cast(it->getValue()))) { 286| 0| return false; 287| 0| } 288| 0| ++it; 289| 0| } 290| 0| 291| 0| // There shouldn't be any trailing sections. 292| 0| if (it != mapping->end()) { 293| 0| error(&*it, "unexpected trailing top-level section"); 294| 0| return false; 295| 0| } 296| 0| 297| 0| return true; 298| 0| } 299| | 300| 0| bool parseClientMapping(llvm::yaml::MappingNode* map) { 301| 0| // Collect all of the keys. 302| 0| std::string name; 303| 0| uint32_t version = 0; 304| 0| property_list_type properties; 305| 0| 306| 0| for (auto& entry: *map) { 307| 0| // All keys and values must be scalar. 308| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 309| 0| error(entry.getKey(), "invalid key type in 'client' map"); 310| 0| return false; 311| 0| } 312| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 313| 0| error(entry.getValue(), "invalid value type in 'client' map"); 314| 0| return false; 315| 0| } 316| 0| 317| 0| std::string key = stringFromScalarNode( 318| 0| static_cast(entry.getKey())); 319| 0| std::string value = stringFromScalarNode( 320| 0| static_cast(entry.getValue())); 321| 0| if (key == "name") { 322| 0| name = value; 323| 0| } else if (key == "version") { 324| 0| if (StringRef(value).getAsInteger(10, version)) { 325| 0| error(entry.getValue(), "invalid version number in 'client' map"); 326| 0| } 327| 0| } else { 328| 0| properties.push_back({ key, value }); 329| 0| } 330| 0| } 331| 0| 332| 0| // Pass to the delegate. 333| 0| if (!delegate.configureClient(getContext(map), name, version, properties)) { 334| 0| error(map, "unable to configure client"); 335| 0| return false; 336| 0| } 337| 0| 338| 0| return true; 339| 0| } 340| | 341| 0| bool parseToolsMapping(llvm::yaml::MappingNode* map) { 342| 0| for (auto& entry: *map) { 343| 0| // Every key must be scalar. 344| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 345| 0| error(entry.getKey(), "invalid key type in 'tools' map"); 346| 0| continue; 347| 0| } 348| 0| // Every value must be a mapping. 349| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 350| 0| error(entry.getValue(), "invalid value type in 'tools' map"); 351| 0| continue; 352| 0| } 353| 0| 354| 0| std::string name = stringFromScalarNode( 355| 0| static_cast(entry.getKey())); 356| 0| llvm::yaml::MappingNode* attrs = static_cast( 357| 0| entry.getValue()); 358| 0| 359| 0| // Get the tool. 360| 0| auto tool = getOrCreateTool(name, entry.getKey()); 361| 0| if (!tool) { 362| 0| return false; 363| 0| } 364| 0| 365| 0| // Configure all of the tool attributes. 366| 0| for (auto& valueEntry: *attrs) { 367| 0| auto key = valueEntry.getKey(); 368| 0| auto value = valueEntry.getValue(); 369| 0| 370| 0| // All keys must be scalar. 371| 0| if (key->getType() != llvm::yaml::Node::NK_Scalar) { 372| 0| error(key, "invalid key type for tool in 'tools' map"); 373| 0| continue; 374| 0| } 375| 0| 376| 0| 377| 0| auto attribute = stringFromScalarNode( 378| 0| static_cast(key)); 379| 0| 380| 0| if (value->getType() == llvm::yaml::Node::NK_Mapping) { 381| 0| std::vector> values; 382| 0| for (auto& entry: *static_cast(value)) { 383| 0| // Every key must be scalar. 384| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 385| 0| error(entry.getKey(), ("invalid key type for '" + attribute + 386| 0| "' in 'tools' map")); 387| 0| continue; 388| 0| } 389| 0| // Every value must be scalar. 390| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 391| 0| error(entry.getKey(), ("invalid value type for '" + attribute + 392| 0| "' in 'tools' map")); 393| 0| continue; 394| 0| } 395| 0| 396| 0| std::string key = stringFromScalarNode( 397| 0| static_cast(entry.getKey())); 398| 0| std::string value = stringFromScalarNode( 399| 0| static_cast(entry.getValue())); 400| 0| values.push_back(std::make_pair(key, value)); 401| 0| } 402| 0| 403| 0| if (!tool->configureAttribute( 404| 0| getContext(key), attribute, 405| 0| std::vector>( 406| 0| values.begin(), values.end()))) { 407| 0| return false; 408| 0| } 409| 0| } else if (value->getType() == llvm::yaml::Node::NK_Sequence) { 410| 0| std::vector values; 411| 0| for (auto& node: *static_cast(value)) { 412| 0| if (node.getType() != llvm::yaml::Node::NK_Scalar) { 413| 0| error(&node, "invalid value type for tool in 'tools' map"); 414| 0| continue; 415| 0| } 416| 0| values.push_back( 417| 0| stringFromScalarNode( 418| 0| static_cast(&node))); 419| 0| } 420| 0| 421| 0| if (!tool->configureAttribute( 422| 0| getContext(key), attribute, 423| 0| std::vector(values.begin(), values.end()))) { 424| 0| return false; 425| 0| } 426| 0| } else { 427| 0| if (value->getType() != llvm::yaml::Node::NK_Scalar) { 428| 0| error(value, "invalid value type for tool in 'tools' map"); 429| 0| continue; 430| 0| } 431| 0| 432| 0| if (!tool->configureAttribute( 433| 0| getContext(key), attribute, 434| 0| stringFromScalarNode( 435| 0| static_cast(value)))) { 436| 0| return false; 437| 0| } 438| 0| } 439| 0| } 440| 0| } 441| 0| 442| 0| return true; 443| 0| } 444| | 445| 0| bool parseTargetsMapping(llvm::yaml::MappingNode* map) { 446| 0| for (auto& entry: *map) { 447| 0| // Every key must be scalar. 448| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 449| 0| error(entry.getKey(), "invalid key type in 'targets' map"); 450| 0| continue; 451| 0| } 452| 0| // Every value must be a sequence. 453| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Sequence) { 454| 0| error(entry.getValue(), "invalid value type in 'targets' map"); 455| 0| continue; 456| 0| } 457| 0| 458| 0| std::string name = stringFromScalarNode( 459| 0| static_cast(entry.getKey())); 460| 0| llvm::yaml::SequenceNode* nodes = static_cast( 461| 0| entry.getValue()); 462| 0| 463| 0| // Create the target. 464| 0| auto target = llvm::make_unique(name); 465| 0| 466| 0| // Add all of the nodes. 467| 0| for (auto& node: *nodes) { 468| 0| // All items must be scalar. 469| 0| if (node.getType() != llvm::yaml::Node::NK_Scalar) { 470| 0| error(&node, "invalid node type in 'targets' map"); 471| 0| continue; 472| 0| } 473| 0| 474| 0| target->getNodes().push_back( 475| 0| getOrCreateNode( 476| 0| stringFromScalarNode( 477| 0| static_cast(&node)), 478| 0| /*isImplicit=*/true)); 479| 0| } 480| 0| 481| 0| // Let the delegate know we loaded a target. 482| 0| delegate.loadedTarget(name, *target); 483| 0| 484| 0| // Add the target to the targets map. 485| 0| targets[name] = std::move(target); 486| 0| } 487| 0| 488| 0| return true; 489| 0| } 490| | 491| 0| bool parseDefaultTarget(llvm::yaml::ScalarNode* entry) { 492| 0| std::string target = stringFromScalarNode(entry); 493| 0| 494| 0| if (targets.find(target) == targets.end()) { 495| 0| error(entry, "invalid default target, a default target should be in targets"); 496| 0| return false; 497| 0| } 498| 0| 499| 0| defaultTarget = target; 500| 0| delegate.loadedDefaultTarget(defaultTarget); 501| 0| 502| 0| return true; 503| 0| } 504| | 505| 0| bool parseNodesMapping(llvm::yaml::MappingNode* map) { 506| 0| for (auto& entry: *map) { 507| 0| // Every key must be scalar. 508| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 509| 0| error(entry.getKey(), "invalid key type in 'nodes' map"); 510| 0| continue; 511| 0| } 512| 0| // Every value must be a mapping. 513| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 514| 0| error(entry.getValue(), "invalid value type in 'nodes' map"); 515| 0| continue; 516| 0| } 517| 0| 518| 0| std::string name = stringFromScalarNode( 519| 0| static_cast(entry.getKey())); 520| 0| llvm::yaml::MappingNode* attrs = static_cast( 521| 0| entry.getValue()); 522| 0| 523| 0| // Get the node. 524| 0| // 525| 0| // FIXME: One downside of doing the lookup here is that the client cannot 526| 0| // ever make a context dependent node that can have configured properties. 527| 0| auto node = getOrCreateNode(name, /*isImplicit=*/false); 528| 0| 529| 0| // Configure all of the tool attributes. 530| 0| for (auto& valueEntry: *attrs) { 531| 0| auto key = valueEntry.getKey(); 532| 0| auto value = valueEntry.getValue(); 533| 0| 534| 0| // All keys must be scalar. 535| 0| if (key->getType() != llvm::yaml::Node::NK_Scalar) { 536| 0| error(key, "invalid key type for node in 'nodes' map"); 537| 0| continue; 538| 0| } 539| 0| 540| 0| auto attribute = stringFromScalarNode( 541| 0| static_cast(key)); 542| 0| 543| 0| if (value->getType() == llvm::yaml::Node::NK_Mapping) { 544| 0| std::vector> values; 545| 0| for (auto& entry: *static_cast(value)) { 546| 0| // Every key must be scalar. 547| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 548| 0| error(entry.getKey(), ("invalid key type for '" + attribute + 549| 0| "' in 'nodes' map")); 550| 0| continue; 551| 0| } 552| 0| // Every value must be scalar. 553| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 554| 0| error(entry.getKey(), ("invalid value type for '" + attribute + 555| 0| "' in 'nodes' map")); 556| 0| continue; 557| 0| } 558| 0| 559| 0| std::string key = stringFromScalarNode( 560| 0| static_cast(entry.getKey())); 561| 0| std::string value = stringFromScalarNode( 562| 0| static_cast(entry.getValue())); 563| 0| values.push_back(std::make_pair(key, value)); 564| 0| } 565| 0| 566| 0| if (!node->configureAttribute( 567| 0| getContext(key), attribute, 568| 0| std::vector>( 569| 0| values.begin(), values.end()))) { 570| 0| return false; 571| 0| } 572| 0| } else if (value->getType() == llvm::yaml::Node::NK_Sequence) { 573| 0| std::vector values; 574| 0| for (auto& node: *static_cast(value)) { 575| 0| if (node.getType() != llvm::yaml::Node::NK_Scalar) { 576| 0| error(&node, "invalid value type for node in 'nodes' map"); 577| 0| continue; 578| 0| } 579| 0| values.push_back( 580| 0| stringFromScalarNode( 581| 0| static_cast(&node))); 582| 0| } 583| 0| 584| 0| if (!node->configureAttribute( 585| 0| getContext(key), attribute, 586| 0| std::vector(values.begin(), values.end()))) { 587| 0| return false; 588| 0| } 589| 0| } else { 590| 0| if (value->getType() != llvm::yaml::Node::NK_Scalar) { 591| 0| error(value, "invalid value type for node in 'nodes' map"); 592| 0| continue; 593| 0| } 594| 0| 595| 0| if (!node->configureAttribute( 596| 0| getContext(key), attribute, 597| 0| stringFromScalarNode( 598| 0| static_cast(value)))) { 599| 0| return false; 600| 0| } 601| 0| } 602| 0| } 603| 0| } 604| 0| 605| 0| return true; 606| 0| } 607| | 608| 0| bool parseCommandsMapping(llvm::yaml::MappingNode* map) { 609| 0| for (auto& entry: *map) { 610| 0| // Every key must be scalar. 611| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 612| 0| error(entry.getKey(), "invalid key type in 'commands' map"); 613| 0| continue; 614| 0| } 615| 0| // Every value must be a mapping. 616| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Mapping) { 617| 0| error(entry.getValue(), "invalid value type in 'commands' map"); 618| 0| continue; 619| 0| } 620| 0| 621| 0| std::string name = stringFromScalarNode( 622| 0| static_cast(entry.getKey())); 623| 0| llvm::yaml::MappingNode* attrs = static_cast( 624| 0| entry.getValue()); 625| 0| 626| 0| // Check that the command is not a duplicate. 627| 0| if (commands.count(name) != 0) { 628| 0| error(entry.getKey(), "duplicate command in 'commands' map"); 629| 0| continue; 630| 0| } 631| 0| 632| 0| // Get the initial attribute, which must be the tool name. 633| 0| auto it = attrs->begin(); 634| 0| if (it == attrs->end()) { 635| 0| error(entry.getKey(), 636| 0| "missing 'tool' key for command in 'command' map"); 637| 0| continue; 638| 0| } 639| 0| if (!nodeIsScalarString(it->getKey(), "tool")) { 640| 0| error(it->getKey(), 641| 0| "expected 'tool' initial key for command in 'commands' map"); 642| 0| // Skip to the end. 643| 0| while (it != attrs->end()) ++it; 644| 0| continue; 645| 0| } 646| 0| if (it->getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 647| 0| error(it->getValue(), 648| 0| "invalid 'tool' value type for command in 'commands' map"); 649| 0| // Skip to the end. 650| 0| while (it != attrs->end()) ++it; 651| 0| continue; 652| 0| } 653| 0| 654| 0| // Lookup the tool for this command. 655| 0| auto tool = getOrCreateTool( 656| 0| stringFromScalarNode( 657| 0| static_cast( 658| 0| it->getValue())), 659| 0| it->getValue()); 660| 0| if (!tool) { 661| 0| return false; 662| 0| } 663| 0| 664| 0| // Create the command. 665| 0| auto command = tool->createCommand(name); 666| 0| assert(command && "tool failed to create a command"); 667| 0| 668| 0| // Parse the remaining command attributes. 669| 0| ++it; 670| 0| for (; it != attrs->end(); ++it) { 671| 0| auto key = it->getKey(); 672| 0| auto value = it->getValue(); 673| 0| 674| 0| // If this is a known key, parse it. 675| 0| if (nodeIsScalarString(key, "inputs")) { 676| 0| if (value->getType() != llvm::yaml::Node::NK_Sequence) { 677| 0| error(value, "invalid value type for 'inputs' command key"); 678| 0| continue; 679| 0| } 680| 0| 681| 0| llvm::yaml::SequenceNode* nodeNames = 682| 0| static_cast(value); 683| 0| 684| 0| std::vector nodes; 685| 0| for (auto& nodeName: *nodeNames) { 686| 0| if (nodeName.getType() != llvm::yaml::Node::NK_Scalar) { 687| 0| error(&nodeName, "invalid node type in 'inputs' command key"); 688| 0| continue; 689| 0| } 690| 0| 691| 0| nodes.push_back( 692| 0| getOrCreateNode( 693| 0| stringFromScalarNode( 694| 0| static_cast(&nodeName)), 695| 0| /*isImplicit=*/true)); 696| 0| } 697| 0| 698| 0| command->configureInputs(getContext(key), nodes); 699| 0| } else if (nodeIsScalarString(key, "outputs")) { 700| 0| if (value->getType() != llvm::yaml::Node::NK_Sequence) { 701| 0| error(value, "invalid value type for 'outputs' command key"); 702| 0| continue; 703| 0| } 704| 0| 705| 0| llvm::yaml::SequenceNode* nodeNames = 706| 0| static_cast(value); 707| 0| 708| 0| std::vector nodes; 709| 0| for (auto& nodeName: *nodeNames) { 710| 0| if (nodeName.getType() != llvm::yaml::Node::NK_Scalar) { 711| 0| error(&nodeName, "invalid node type in 'outputs' command key"); 712| 0| continue; 713| 0| } 714| 0| 715| 0| auto node = getOrCreateNode( 716| 0| stringFromScalarNode( 717| 0| static_cast(&nodeName)), 718| 0| /*isImplicit=*/true); 719| 0| nodes.push_back(node); 720| 0| 721| 0| // Add this command to the node producer list. 722| 0| node->getProducers().push_back(command.get()); 723| 0| } 724| 0| 725| 0| command->configureOutputs(getContext(key), nodes); 726| 0| } else if (nodeIsScalarString(key, "description")) { 727| 0| if (value->getType() != llvm::yaml::Node::NK_Scalar) { 728| 0| error(value, "invalid value type for 'description' command key"); 729| 0| continue; 730| 0| } 731| 0| 732| 0| command->configureDescription( 733| 0| getContext(key), stringFromScalarNode( 734| 0| static_cast(value))); 735| 0| } else { 736| 0| // Otherwise, it should be an attribute assignment. 737| 0| 738| 0| // All keys must be scalar. 739| 0| if (key->getType() != llvm::yaml::Node::NK_Scalar) { 740| 0| error(key, "invalid key type in 'commands' map"); 741| 0| continue; 742| 0| } 743| 0| 744| 0| auto attribute = stringFromScalarNode( 745| 0| static_cast(key)); 746| 0| 747| 0| if (value->getType() == llvm::yaml::Node::NK_Mapping) { 748| 0| std::vector> values; 749| 0| for (auto& entry: *static_cast(value)) { 750| 0| // Every key must be scalar. 751| 0| if (entry.getKey()->getType() != llvm::yaml::Node::NK_Scalar) { 752| 0| error(entry.getKey(), ("invalid key type for '" + attribute + 753| 0| "' in 'commands' map")); 754| 0| continue; 755| 0| } 756| 0| // Every value must be scalar. 757| 0| if (entry.getValue()->getType() != llvm::yaml::Node::NK_Scalar) { 758| 0| error(entry.getKey(), ("invalid value type for '" + attribute + 759| 0| "' in 'commands' map")); 760| 0| continue; 761| 0| } 762| 0| 763| 0| std::string key = stringFromScalarNode( 764| 0| static_cast(entry.getKey())); 765| 0| std::string value = stringFromScalarNode( 766| 0| static_cast(entry.getValue())); 767| 0| values.push_back(std::make_pair(key, value)); 768| 0| } 769| 0| 770| 0| if (!command->configureAttribute( 771| 0| getContext(key), attribute, 772| 0| std::vector>( 773| 0| values.begin(), values.end()))) { 774| 0| return false; 775| 0| } 776| 0| } else if (value->getType() == llvm::yaml::Node::NK_Sequence) { 777| 0| std::vector values; 778| 0| for (auto& node: *static_cast(value)) { 779| 0| if (node.getType() != llvm::yaml::Node::NK_Scalar) { 780| 0| error(&node, "invalid value type for command in 'commands' map"); 781| 0| continue; 782| 0| } 783| 0| values.push_back( 784| 0| stringFromScalarNode( 785| 0| static_cast(&node))); 786| 0| } 787| 0| 788| 0| if (!command->configureAttribute( 789| 0| getContext(key), attribute, 790| 0| std::vector(values.begin(), values.end()))) { 791| 0| return false; 792| 0| } 793| 0| } else { 794| 0| if (value->getType() != llvm::yaml::Node::NK_Scalar) { 795| 0| error(value, "invalid value type for command in 'commands' map"); 796| 0| continue; 797| 0| } 798| 0| 799| 0| if (!command->configureAttribute( 800| 0| getContext(key), attribute, 801| 0| stringFromScalarNode( 802| 0| static_cast(value)))) { 803| 0| return false; 804| 0| } 805| 0| } 806| 0| } 807| 0| } 808| 0| 809| 0| // Let the delegate know we loaded a command. 810| 0| delegate.loadedCommand(name, *command); 811| 0| 812| 0| // Add the command to the commands map. 813| 0| commands[name] = std::move(command); 814| 0| } 815| 0| 816| 0| return true; 817| 0| } 818| | 819| |public: 820| | BuildFileImpl(class BuildFile& buildFile, 821| | StringRef mainFilename, 822| | BuildFileDelegate& delegate) 823| 0| : mainFilename(mainFilename), delegate(delegate) {} 824| | 825| 0| BuildFileDelegate* getDelegate() { 826| 0| return &delegate; 827| 0| } 828| | 829| | /// @name Parse Actions 830| | /// @{ 831| | 832| 0| std::unique_ptr load() { 833| 0| // Create a memory buffer for the input. 834| 0| // 835| 0| // FIXME: Lift the file access into the delegate, like we do for Ninja. 836| 0| llvm::SourceMgr sourceMgr; 837| 0| auto input = delegate.getFileSystem().getFileContents(mainFilename); 838| 0| if (!input) { 839| 0| error("unable to open '" + mainFilename + "'"); 840| 0| return nullptr; 841| 0| } 842| 0| 843| 0| delegate.setFileContentsBeingParsed(input->getBuffer()); 844| 0| 845| 0| // Create a YAML parser. 846| 0| llvm::yaml::Stream stream(input->getMemBufferRef(), sourceMgr); 847| 0| 848| 0| // Read the stream, we only expect a single document. 849| 0| auto it = stream.begin(); 850| 0| if (it == stream.end()) { 851| 0| error("missing document in stream"); 852| 0| return nullptr; 853| 0| } 854| 0| 855| 0| auto& document = *it; 856| 0| auto root = document.getRoot(); 857| 0| if (!root) { 858| 0| error("missing document in stream"); 859| 0| return nullptr; 860| 0| } 861| 0| 862| 0| if (!parseRootNode(root)) { 863| 0| return nullptr; 864| 0| } 865| 0| 866| 0| if (++it != stream.end()) { 867| 0| error(it->getRoot(), "unexpected additional document in stream"); 868| 0| return nullptr; 869| 0| } 870| 0| 871| 0| // Create the actual description from our constructed elements. 872| 0| // 873| 0| // FIXME: This is historical, We should tidy up this class to reflect that 874| 0| // it is now just a builder. 875| 0| auto description = llvm::make_unique(); 876| 0| std::swap(description->getNodes(), nodes); 877| 0| std::swap(description->getTargets(), targets); 878| 0| std::swap(description->getDefaultTarget(), defaultTarget); 879| 0| std::swap(description->getCommands(), commands); 880| 0| std::swap(description->getTools(), tools); 881| 0| return description; 882| 0| } 883| |}; 884| | 885| |} 886| | 887| |#pragma mark - BuildFile 888| | 889| |BuildFile::BuildFile(StringRef mainFilename, 890| | BuildFileDelegate& delegate) 891| | : impl(new BuildFileImpl(*this, mainFilename, delegate)) 892| 0|{ 893| 0|} 894| | 895| 0|BuildFile::~BuildFile() { 896| 0| delete static_cast(impl); 897| 0|} 898| | 899| 0|std::unique_ptr BuildFile::load() { 900| 0| // Create the build description. 901| 0| return static_cast(impl)->load(); 902| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildKey.cpp: 1| |//===-- BuildKey.cpp ------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildKey.h" 14| | 15| |#include "llbuild/Basic/LLVM.h" 16| |#include "llbuild/BuildSystem/BuildDescription.h" 17| | 18| |#include "llvm/Support/raw_ostream.h" 19| | 20| |using namespace llbuild; 21| |using namespace llbuild::buildsystem; 22| | 23| 0|StringRef BuildKey::stringForKind(BuildKey::Kind kind) { 24| 0| switch (kind) { 25| 0|#define CASE(kind) case Kind::kind: return #kind 26| 0| CASE(Command); 27| 0| CASE(CustomTask); 28| 0| CASE(DirectoryContents); 29| 0| CASE(FilteredDirectoryContents); 30| 0| CASE(DirectoryTreeSignature); 31| 0| CASE(DirectoryTreeStructureSignature); 32| 0| CASE(Node); 33| 0| CASE(Stat); 34| 0| CASE(Target); 35| 0| CASE(Unknown); 36| 0|#undef CASE 37| 0| } 38| 0| return ""; 39| 0|} 40| | 41| 0|void BuildKey::dump(raw_ostream& os) const { 42| 0| os << "BuildKey(" << stringForKind(getKind()); 43| 0| switch (getKind()) { 44| 0| case Kind::Command: { 45| 0| os << ", name='" << getCommandName() << "'"; 46| 0| break; 47| 0| } 48| 0| case Kind::CustomTask: { 49| 0| os << ", name='" << getCustomTaskName() << "'"; 50| 0| os << ", dataSize='" << getCustomTaskData().size() << "'"; 51| 0| break; 52| 0| } 53| 0| case Kind::DirectoryContents: 54| 0| case Kind::DirectoryTreeSignature: 55| 0| case Kind::DirectoryTreeStructureSignature: { 56| 0| os << ", path='" << getDirectoryPath() << "'"; 57| 0| break; 58| 0| } 59| 0| case Kind::FilteredDirectoryContents: { 60| 0| os << ", path='" << getFilteredDirectoryPath() << "'"; 61| 0| // FIXME: should probably dump filters here too 62| 0| break; 63| 0| } 64| 0| case Kind::Node: { 65| 0| os << ", name='" << getNodeName() << "'"; 66| 0| break; 67| 0| } 68| 0| case Kind::Stat: { 69| 0| os << ", name='" << getStatName() << "'"; 70| 0| break; 71| 0| } 72| 0| case Kind::Target: { 73| 0| os << ", name='" << getTargetName() << "'"; 74| 0| break; 75| 0| } 76| 0| case Kind::Unknown: { 77| 0| break; 78| 0| } 79| 0| } 80| 0| os << ")"; 81| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildNode.cpp: 1| |//===-- BuildNode.cpp -----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildNode.h" 14| | 15| |#include "llbuild/Basic/FileInfo.h" 16| |#include "llbuild/Basic/FileSystem.h" 17| |#include "llbuild/BuildSystem/BuildFile.h" 18| | 19| |#include "llvm/ADT/ArrayRef.h" 20| |#include "llvm/ADT/Twine.h" 21| | 22| |using namespace llbuild; 23| |using namespace llbuild::basic; 24| |using namespace llbuild::buildsystem; 25| | 26| |bool BuildNode::configureAttribute(const ConfigureContext& ctx, StringRef name, 27| 0| StringRef value) { 28| 0| if (name == "is-directory") { 29| 0| if (value == "true") { 30| 0| directory = true; 31| 0| directoryStructure = virtualNode = false; 32| 0| } else if (value == "false") { 33| 0| directory = false; 34| 0| } else { 35| 0| ctx.error("invalid value: '" + value + "' for attribute '" 36| 0| + name + "'"); 37| 0| return false; 38| 0| } 39| 0| return true; 40| 0| } else if (name == "is-directory-structure") { 41| 0| if (value == "true") { 42| 0| directoryStructure = true; 43| 0| directory = virtualNode = false; 44| 0| } else if (value == "false") { 45| 0| directory = false; 46| 0| } else { 47| 0| ctx.error("invalid value: '" + value + "' for attribute '" 48| 0| + name + "'"); 49| 0| return false; 50| 0| } 51| 0| return true; 52| 0| } else if (name == "is-virtual") { 53| 0| if (value == "true") { 54| 0| virtualNode = true; 55| 0| directory = directoryStructure = false; 56| 0| } else if (value == "false") { 57| 0| virtualNode = false; 58| 0| commandTimestamp = false; 59| 0| } else { 60| 0| ctx.error("invalid value: '" + value + "' for attribute '" 61| 0| + name + "'"); 62| 0| return false; 63| 0| } 64| 0| return true; 65| 0| } else if (name == "is-command-timestamp") { 66| 0| if (value == "true") { 67| 0| commandTimestamp = true; 68| 0| virtualNode = true; 69| 0| directory = directoryStructure = false; 70| 0| } else if (value == "false") { 71| 0| commandTimestamp = false; 72| 0| } else { 73| 0| ctx.error("invalid value: '" + value + "' for attribute '" 74| 0| + name + "'"); 75| 0| return false; 76| 0| } 77| 0| return true; 78| 0| } else if (name == "is-mutated") { 79| 0| if (value == "true") { 80| 0| mutated = true; 81| 0| } else if (value == "false") { 82| 0| mutated = false; 83| 0| } else { 84| 0| ctx.error("invalid value: '" + value + "' for attribute '" 85| 0| + name + "'"); 86| 0| return false; 87| 0| } 88| 0| return true; 89| 0| } else if (name == "content-exclusion-patterns") { 90| 0| exclusionPatterns = basic::StringList(value); 91| 0| return true; 92| 0| } 93| 0| 94| 0| // We don't support any other custom attributes. 95| 0| ctx.error("unexpected attribute: '" + name + "'"); 96| 0| return false; 97| 0|} 98| | 99| |bool BuildNode::configureAttribute(const ConfigureContext& ctx, StringRef name, 100| 0| ArrayRef values) { 101| 0| if (name == "content-exclusion-patterns") { 102| 0| exclusionPatterns = basic::StringList(values); 103| 0| return true; 104| 0| } 105| 0| 106| 0| // We don't support any other custom attributes. 107| 0| ctx.error("unexpected attribute: '" + name + "'"); 108| 0| return false; 109| 0|} 110| | 111| |bool BuildNode::configureAttribute( 112| | const ConfigureContext& ctx, StringRef name, 113| 0| ArrayRef> values) { 114| 0| // We don't support any other custom attributes. 115| 0| ctx.error("unexpected attribute: '" + name + "'"); 116| 0| return false; 117| 0|} 118| | 119| 0|FileInfo BuildNode::getFileInfo(basic::FileSystem& fileSystem) const { 120| 0| assert(!isVirtual()); 121| 0| return fileSystem.getFileInfo(getName()); 122| 0|} 123| | 124| 0|FileInfo BuildNode::getLinkInfo(basic::FileSystem& fileSystem) const { 125| 0| assert(!isVirtual()); 126| 0| return fileSystem.getLinkInfo(getName()); 127| 0|} 128| | 129| | 130| 0|FileInfo StatNode::getFileInfo(basic::FileSystem& fileSystem) const { 131| 0| return fileSystem.getFileInfo(name); 132| 0|} 133| | 134| 0|FileInfo StatNode::getLinkInfo(basic::FileSystem& fileSystem) const { 135| 0| return fileSystem.getLinkInfo(name); 136| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildSystem.cpp: 1| |//===-- BuildSystem.cpp ---------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildSystem.h" 14| |#include "llbuild/BuildSystem/BuildSystemCommandInterface.h" 15| |#include "llbuild/BuildSystem/BuildSystemFrontend.h" 16| | 17| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 18| |#include "llbuild/Basic/ExecutionQueue.h" 19| |#include "llbuild/Basic/FileInfo.h" 20| |#include "llbuild/Basic/FileSystem.h" 21| |#include "llbuild/Basic/Hashing.h" 22| |#include "llbuild/Basic/LLVM.h" 23| |#include "llbuild/Basic/PlatformUtility.h" 24| |#include "llbuild/Basic/ShellUtility.h" 25| |#include "llbuild/BuildSystem/BuildFile.h" 26| |#include "llbuild/BuildSystem/BuildKey.h" 27| |#include "llbuild/BuildSystem/BuildNode.h" 28| |#include "llbuild/BuildSystem/BuildValue.h" 29| |#include "llbuild/BuildSystem/ExternalCommand.h" 30| |#include "llbuild/Core/BuildDB.h" 31| |#include "llbuild/Core/BuildEngine.h" 32| |#include "llbuild/Core/DependencyInfoParser.h" 33| |#include "llbuild/Core/MakefileDepsParser.h" 34| | 35| |#include "llvm/ADT/ArrayRef.h" 36| |#include "llvm/ADT/Hashing.h" 37| |#include "llvm/ADT/STLExtras.h" 38| |#include "llvm/ADT/SmallPtrSet.h" 39| |#include "llvm/ADT/SmallString.h" 40| |#include "llvm/ADT/StringMap.h" 41| |#include "llvm/ADT/StringRef.h" 42| |#include "llvm/Support/ErrorHandling.h" 43| |#include "llvm/Support/FileSystem.h" 44| |#include "llvm/Support/MemoryBuffer.h" 45| |#include "llvm/Support/Path.h" 46| |#include "llvm/Support/raw_ostream.h" 47| | 48| |#include 49| |#include 50| |#include 51| |#include 52| | 53| |#ifdef _WIN32 54| |#include 55| |#else 56| |#include 57| |#include 58| |#include 59| |#endif 60| | 61| |using namespace llbuild; 62| |using namespace llbuild::basic; 63| |using namespace llbuild::core; 64| |using namespace llbuild::buildsystem; 65| | 66| 0|BuildSystemDelegate::~BuildSystemDelegate() {} 67| | 68| 0|BuildSystemCommandInterface::~BuildSystemCommandInterface() {} 69| | 70| |#pragma mark - BuildSystem implementation 71| | 72| |namespace { 73| | 74| |class BuildSystemImpl; 75| | 76| |/// The delegate used to load the build file for use by a build system. 77| |class BuildSystemFileDelegate : public BuildFileDelegate { 78| | BuildSystemImpl& system; 79| | 80| | /// FIXME: It would be nice to have a StringSet. 81| | llvm::StringMap internedStrings; 82| | 83| |public: 84| | BuildSystemFileDelegate(BuildSystemImpl& system) 85| 0| : BuildFileDelegate(), system(system) {} 86| | 87| | BuildSystemDelegate& getSystemDelegate(); 88| | 89| | /// @name Delegate Implementation 90| | /// @{ 91| | 92| 0| virtual StringRef getInternedString(StringRef value) override { 93| 0| auto entry = internedStrings.insert(std::make_pair(value, true)); 94| 0| return entry.first->getKey(); 95| 0| } 96| | 97| | virtual FileSystem& getFileSystem() override; 98| | 99| | virtual void setFileContentsBeingParsed(StringRef buffer) override; 100| | 101| | virtual void error(StringRef filename, 102| | const BuildFileToken& at, 103| | const Twine& message) override; 104| | 105| | virtual bool configureClient(const ConfigureContext&, StringRef name, 106| | uint32_t version, 107| | const property_list_type& properties) override; 108| | 109| | virtual std::unique_ptr lookupTool(StringRef name) override; 110| | 111| | virtual void loadedTarget(StringRef name, 112| | const Target& target) override; 113| | 114| | virtual void loadedDefaultTarget(StringRef target) override; 115| | 116| | virtual void loadedCommand(StringRef name, 117| | const Command& target) override; 118| | 119| | virtual std::unique_ptr lookupNode(StringRef name, 120| | bool isImplicit=false) override; 121| | 122| | /// @} 123| |}; 124| | 125| |/// The delegate used to build a loaded build file. 126| |class BuildSystemEngineDelegate : public BuildEngineDelegate { 127| | BuildSystemImpl& system; 128| | 129| | // FIXME: This is an inefficent map, the string is duplicated. 130| | std::unordered_map> dynamicNodes; 131| | 132| | // FIXME: This is an inefficent map, the string is duplicated. 133| | std::unordered_map> dynamicStatNodes; 134| | 135| | /// The custom tasks which are owned by the build system. 136| | std::vector> customTasks; 137| | 138| | const BuildDescription& getBuildDescription() const; 139| | 140| | virtual Rule lookupRule(const KeyType& keyData) override; 141| | virtual bool shouldResolveCycle(const std::vector& items, 142| | Rule* candidateRule, 143| | Rule::CycleAction action) override; 144| | virtual void cycleDetected(const std::vector& items) override; 145| | virtual void error(const Twine& message) override; 146| | 147| |public: 148| 0| BuildSystemEngineDelegate(BuildSystemImpl& system) : system(system) {} 149| | 150| 0| BuildSystemImpl& getBuildSystem() { 151| 0| return system; 152| 0| } 153| |}; 154| | 155| |class BuildSystemImpl : public BuildSystemCommandInterface { 156| | /// The internal schema version. 157| | /// 158| | /// Version History: 159| | /// * 9: Added filters to Directory* BuildKeys 160| | /// * 8: Added DirectoryTreeStructureSignature to BuildValue 161| | /// * 7: Added StaleFileRemoval to BuildValue 162| | /// * 6: Added DirectoryContents to BuildKey 163| | /// * 5: Switch BuildValue to be BinaryCoding based 164| | /// * 4: Pre-history 165| | static const uint32_t internalSchemaVersion = 9; 166| | 167| | BuildSystem& buildSystem; 168| | 169| | /// The delegate the BuildSystem was configured with. 170| | BuildSystemDelegate& delegate; 171| | 172| | /// The file system used by the build system 173| | std::unique_ptr fileSystem; 174| | 175| | /// The name of the main input file. 176| | std::string mainFilename; 177| | 178| | /// The delegate used for the loading the build file. 179| | BuildSystemFileDelegate fileDelegate; 180| | 181| | /// The build description, once loaded. 182| | std::unique_ptr buildDescription; 183| | 184| | /// The delegate used for building the file contents. 185| | BuildSystemEngineDelegate engineDelegate; 186| | 187| | /// The build engine. 188| | BuildEngine buildEngine; 189| | 190| | /// Mutex for access to execution queue. 191| | std::mutex executionQueueMutex; 192| | 193| | /// The execution queue reference; this is only valid while a build is 194| | /// actually in progress. 195| | std::unique_ptr executionQueue; 196| | 197| | /// Flag indicating if the build has been aborted. 198| | bool buildWasAborted = false; 199| | 200| | /// Flag indicating if the build has been cancelled. 201| | std::atomic isCancelled_{ false }; 202| | 203| | /// @name BuildSystemCommandInterface Implementation 204| | /// @{ 205| | 206| 0| virtual BuildEngine& getBuildEngine() override { 207| 0| return buildEngine; 208| 0| } 209| | 210| 0| virtual ExecutionQueue& getExecutionQueue() override { 211| 0| assert(executionQueue.get()); 212| 0| return *executionQueue; 213| 0| } 214| | 215| | virtual void taskNeedsInput(core::Task* task, const BuildKey& key, 216| 0| uintptr_t inputID) override { 217| 0| return buildEngine.taskNeedsInput(task, key.toData(), inputID); 218| 0| } 219| | 220| 0| virtual void taskMustFollow(core::Task* task, const BuildKey& key) override { 221| 0| return buildEngine.taskMustFollow(task, key.toData()); 222| 0| } 223| | 224| | virtual void taskDiscoveredDependency(core::Task* task, 225| 0| const BuildKey& key) override { 226| 0| return buildEngine.taskDiscoveredDependency(task, key.toData()); 227| 0| } 228| | 229| | virtual void taskIsComplete(core::Task* task, const BuildValue& value, 230| 0| bool forceChange) override { 231| 0| return buildEngine.taskIsComplete(task, value.toData(), forceChange); 232| 0| } 233| | 234| 0| virtual void addJob(QueueJob&& job) override { 235| 0| executionQueue->addJob(std::move(job)); 236| 0| } 237| | 238| | /// @} 239| | 240| |public: 241| | BuildSystemImpl(class BuildSystem& buildSystem, 242| | BuildSystemDelegate& delegate, 243| | std::unique_ptr fileSystem) 244| | : buildSystem(buildSystem), delegate(delegate), 245| | fileSystem(std::move(fileSystem)), 246| | fileDelegate(*this), engineDelegate(*this), buildEngine(engineDelegate), 247| 0| executionQueue() {} 248| | 249| 0| BuildSystem& getBuildSystem() { 250| 0| return buildSystem; 251| 0| } 252| | 253| 0| BuildSystemDelegate& getDelegate() override { 254| 0| return delegate; 255| 0| } 256| | 257| 0| basic::FileSystem& getFileSystem() override { 258| 0| return *fileSystem; 259| 0| } 260| | 261| | // FIXME: We should eliminate this, it isn't well formed when loading 262| | // descriptions not from a file. We currently only use that for unit testing, 263| | // though. 264| 0| StringRef getMainFilename() { 265| 0| return mainFilename; 266| 0| } 267| | 268| 0| BuildSystemCommandInterface& getCommandInterface() { 269| 0| return *this; 270| 0| } 271| | 272| 0| const BuildDescription& getBuildDescription() const { 273| 0| assert(buildDescription); 274| 0| return *buildDescription; 275| 0| } 276| | 277| 0| void error(StringRef filename, const Twine& message) { 278| 0| getDelegate().error(filename, {}, message); 279| 0| } 280| | 281| | void error(StringRef filename, const BuildSystemDelegate::Token& at, 282| 0| const Twine& message) { 283| 0| getDelegate().error(filename, at, message); 284| 0| } 285| | 286| | std::unique_ptr lookupNode(StringRef name, 287| | bool isImplicit); 288| | 289| 0| uint32_t getMergedSchemaVersion() { 290| 0| // FIXME: Find a cleaner strategy for merging the internal schema version 291| 0| // with that from the client. 292| 0| auto clientVersion = delegate.getVersion(); 293| 0| assert(clientVersion <= (1 << 16) && "unsupported client version"); 294| 0| return internalSchemaVersion + (clientVersion << 16); 295| 0| } 296| | 297| 0| void configureFileSystem(bool deviceAgnostic) { 298| 0| if (deviceAgnostic) { 299| 0| std::unique_ptr newFS( 300| 0| new DeviceAgnosticFileSystem(std::move(fileSystem))); 301| 0| fileSystem.swap(newFS); 302| 0| } 303| 0| } 304| | 305| | /// @name Client API 306| | /// @{ 307| | 308| 0| bool loadDescription(StringRef filename) { 309| 0| this->mainFilename = filename; 310| 0| 311| 0| auto description = BuildFile(filename, fileDelegate).load(); 312| 0| if (!description) { 313| 0| error(getMainFilename(), "unable to load build file"); 314| 0| return false; 315| 0| } 316| 0| 317| 0| buildDescription = std::move(description); 318| 0| return true; 319| 0| } 320| | 321| 0| void loadDescription(std::unique_ptr description) { 322| 0| buildDescription = std::move(description); 323| 0| } 324| | 325| 0| bool attachDB(StringRef filename, std::string* error_out) { 326| 0| // FIXME: How do we pass the client schema version here, if we haven't 327| 0| // loaded the file yet. 328| 0| std::unique_ptr db( 329| 0| core::createSQLiteBuildDB(filename, getMergedSchemaVersion(), 330| 0| error_out)); 331| 0| if (!db) 332| 0| return false; 333| 0| 334| 0| return buildEngine.attachDB(std::move(db), error_out); 335| 0| } 336| | 337| 0| bool enableTracing(StringRef filename, std::string* error_out) { 338| 0| return buildEngine.enableTracing(filename, error_out); 339| 0| } 340| | 341| | /// Build the given key, and return the result and an indication of success. 342| | llvm::Optional build(BuildKey key); 343| | 344| | bool build(StringRef target); 345| | 346| 0| void setBuildWasAborted(bool value) { 347| 0| buildWasAborted = value; 348| 0| } 349| | 350| 0| void resetForBuild() { 351| 0| std::lock_guard guard(executionQueueMutex); 352| 0| isCancelled_ = false; 353| 0| } 354| | 355| | /// Cancel the running build. 356| 0| void cancel() { 357| 0| std::lock_guard guard(executionQueueMutex); 358| 0| 359| 0| isCancelled_ = true; 360| 0| // Cancel jobs if we actually have a queue. 361| 0| if (executionQueue.get() != nullptr) 362| 0| getExecutionQueue().cancelAllJobs(); 363| 0| } 364| | 365| | /// Check if the build has been cancelled. 366| 0| bool isCancelled() { 367| 0| return isCancelled_; 368| 0| } 369| | 370| | /// @} 371| |}; 372| | 373| |#pragma mark - BuildSystem engine integration 374| | 375| |#pragma mark - Task implementations 376| | 377| 0|static BuildSystemImpl& getBuildSystem(BuildEngine& engine) { 378| 0| return static_cast( 379| 0| engine.getDelegate())->getBuildSystem(); 380| 0|} 381| | 382| | 383| 0|FileSystem& BuildSystemFileDelegate::getFileSystem() { 384| 0| return system.getFileSystem(); 385| 0|} 386| | 387| | 388| |/// This is the task used to "build" a target, it translates between the request 389| |/// for building a target key and the requests for all of its nodes. 390| |class TargetTask : public Task { 391| | Target& target; 392| | 393| | // Build specific data. 394| | // 395| | // FIXME: We should probably factor this out somewhere else, so we can enforce 396| | // it is never used when initialized incorrectly. 397| | 398| | /// If there are any elements, the command had missing input nodes (this implies 399| | /// ShouldSkip is true). 400| | SmallPtrSet missingInputNodes; 401| | 402| 0| virtual void start(BuildEngine& engine) override { 403| 0| // Request all of the necessary system tasks. 404| 0| unsigned id = 0; 405| 0| for (auto it = target.getNodes().begin(), 406| 0| ie = target.getNodes().end(); it != ie; ++it, ++id) { 407| 0| engine.taskNeedsInput(this, BuildKey::makeNode(*it).toData(), id); 408| 0| } 409| 0| } 410| | 411| | virtual void providePriorValue(BuildEngine&, 412| 0| const ValueType& value) override { 413| 0| // Do nothing. 414| 0| } 415| | 416| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 417| 0| const ValueType& valueData) override { 418| 0| // Do nothing. 419| 0| auto value = BuildValue::fromData(valueData); 420| 0| 421| 0| if (value.isMissingInput()) { 422| 0| missingInputNodes.insert(target.getNodes()[inputID]); 423| 0| } 424| 0| } 425| | 426| 0| virtual void inputsAvailable(BuildEngine& engine) override { 427| 0| // If the build should cancel, do nothing. 428| 0| if (getBuildSystem(engine).isCancelled()) { 429| 0| engine.taskIsComplete(this, BuildValue::makeSkippedCommand().toData()); 430| 0| return; 431| 0| } 432| 0| 433| 0| if (!missingInputNodes.empty()) { 434| 0| std::string inputs; 435| 0| raw_string_ostream inputsStream(inputs); 436| 0| for (Node* missingInputNode : missingInputNodes) { 437| 0| if (missingInputNode != *missingInputNodes.begin()) { 438| 0| inputsStream << ", "; 439| 0| } 440| 0| inputsStream << "'" << missingInputNode->getName() << "'"; 441| 0| } 442| 0| inputsStream.flush(); 443| 0| 444| 0| // FIXME: Design the logging and status output APIs. 445| 0| auto& system = getBuildSystem(engine); 446| 0| system.error(system.getMainFilename(), 447| 0| (Twine("cannot build target '") + target.getName() + 448| 0| "' due to missing inputs: " + inputs)); 449| 0| 450| 0| // Report the command failure. 451| 0| system.getDelegate().hadCommandFailure(); 452| 0| } 453| 0| 454| 0| // Complete the task immediately. 455| 0| engine.taskIsComplete(this, BuildValue::makeTarget().toData()); 456| 0| } 457| | 458| |public: 459| 0| TargetTask(Target& target) : target(target) {} 460| | 461| | static bool isResultValid(BuildEngine& engine, Target& node, 462| 0| const BuildValue& value) { 463| 0| // Always treat target tasks as invalid. 464| 0| return false; 465| 0| } 466| |}; 467| | 468| | 469| |/// This is the task to "build" a file node which represents pure raw input to 470| |/// the system. 471| |class FileInputNodeTask : public Task { 472| | BuildNode& node; 473| | 474| 0| virtual void start(BuildEngine& engine) override { 475| 0| assert(node.getProducers().empty()); 476| 0| } 477| | 478| | virtual void providePriorValue(BuildEngine&, 479| 0| const ValueType& value) override { 480| 0| } 481| | 482| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 483| 0| const ValueType& value) override { 484| 0| } 485| | 486| 0| virtual void inputsAvailable(BuildEngine& engine) override { 487| 0| // FIXME: We should do this work in the background. 488| 0| 489| 0| // Get the information on the file. 490| 0| // 491| 0| // FIXME: This needs to delegate, since we want to have a notion of 492| 0| // different node types. 493| 0| assert(!node.isVirtual()); 494| 0| auto info = node.getFileInfo( 495| 0| getBuildSystem(engine).getFileSystem()); 496| 0| if (info.isMissing()) { 497| 0| engine.taskIsComplete(this, BuildValue::makeMissingInput().toData()); 498| 0| return; 499| 0| } 500| 0| 501| 0| engine.taskIsComplete( 502| 0| this, BuildValue::makeExistingInput(info).toData()); 503| 0| } 504| | 505| |public: 506| 0| FileInputNodeTask(BuildNode& node) : node(node) { 507| 0| assert(!node.isVirtual()); 508| 0| } 509| | 510| | static bool isResultValid(BuildEngine& engine, const BuildNode& node, 511| 0| const BuildValue& value) { 512| 0| // The result is valid if the existence matches the value type and the file 513| 0| // information remains the same. 514| 0| // 515| 0| // FIXME: This is inefficient, we will end up doing the stat twice, once 516| 0| // when we check the value for up to dateness, and once when we "build" the 517| 0| // output. 518| 0| // 519| 0| // We can solve this by caching ourselves but I wonder if it is something 520| 0| // the engine should support more naturally. In practice, this is unlikely 521| 0| // to be very performance critical in practice because this is only 522| 0| // redundant in the case where we have never built the node before (or need 523| 0| // to rebuild it), and thus the additional stat is only one small part of 524| 0| // the work we need to perform. 525| 0| auto info = node.getFileInfo( 526| 0| getBuildSystem(engine).getFileSystem()); 527| 0| if (info.isMissing()) { 528| 0| return value.isMissingInput(); 529| 0| } else { 530| 0| return value.isExistingInput() && value.getOutputInfo() == info; 531| 0| } 532| 0| } 533| |}; 534| | 535| |/// This is the task to "build" a file info node which represents raw stat info 536| |/// of a file system object. 537| |class StatTask : public Task { 538| | StatNode& statnode; 539| | 540| 0| virtual void start(BuildEngine& engine) override { 541| 0| // Create a weak link on any potential producer nodes so that we get up to 542| 0| // date stat information. We always run (see isResultValid) so this should 543| 0| // be safe (unlike directory contents where it may not run). 544| 0| engine.taskMustFollow(this, BuildKey::makeNode(statnode.getName()).toData()); 545| 0| } 546| | 547| | virtual void providePriorValue(BuildEngine&, 548| 0| const ValueType& value) override { 549| 0| } 550| | 551| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 552| 0| const ValueType& value) override { 553| 0| } 554| | 555| 0| virtual void inputsAvailable(BuildEngine& engine) override { 556| 0| // FIXME: We should do this work in the background. 557| 0| 558| 0| // Get the information on the file. 559| 0| auto info = statnode.getFileInfo(getBuildSystem(engine).getFileSystem()); 560| 0| if (info.isMissing()) { 561| 0| engine.taskIsComplete(this, BuildValue::makeMissingInput().toData()); 562| 0| return; 563| 0| } 564| 0| 565| 0| engine.taskIsComplete(this, BuildValue::makeExistingInput(info).toData()); 566| 0| } 567| | 568| |public: 569| 0| StatTask(StatNode& statnode) : statnode(statnode) {} 570| | 571| 0| static bool isResultValid(BuildEngine&, const StatNode&, const BuildValue&) { 572| 0| // Always read the stat information 573| 0| return false; 574| 0| } 575| |}; 576| | 577| |/// This is the task to "build" a directory node. 578| |/// 579| |/// This node effectively just adapts a directory tree signature to a node. The 580| |/// reason why we need it (versus simply making the directory tree signature 581| |/// *be* this, is that we want the directory signature to be able to interface 582| |/// with other build nodes produced by commands). 583| |class DirectoryInputNodeTask : public Task { 584| | BuildNode& node; 585| | 586| | core::ValueType directorySignature; 587| | 588| 0| virtual void start(BuildEngine& engine) override { 589| 0| // Remove any trailing slash from the node name. 590| 0| StringRef path = node.getName(); 591| 0| if (path.endswith("/") && path != "/") { 592| 0| path = path.substr(0, path.size() - 1); 593| 0| } 594| 0| 595| 0| engine.taskNeedsInput( 596| 0| this, BuildKey::makeDirectoryTreeSignature(path, 597| 0| node.contentExclusionPatterns()).toData(), 598| 0| /*inputID=*/0); 599| 0| } 600| | 601| | virtual void providePriorValue(BuildEngine&, 602| 0| const ValueType& value) override { 603| 0| } 604| | 605| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 606| 0| const ValueType& value) override { 607| 0| directorySignature = value; 608| 0| } 609| | 610| 0| virtual void inputsAvailable(BuildEngine& engine) override { 611| 0| // Simply propagate the value. 612| 0| engine.taskIsComplete(this, ValueType(directorySignature)); 613| 0| } 614| | 615| |public: 616| 0| DirectoryInputNodeTask(BuildNode& node) : node(node) { 617| 0| assert(!node.isVirtual()); 618| 0| } 619| |}; 620| | 621| | 622| |/// This is the task to "build" a directory structure node. 623| |/// 624| |/// This node effectively just adapts a directory tree structure signature to a 625| |/// node. The reason why we need it (versus simply making the directory tree 626| |/// signature *be* this, is that we want the directory signature to be able to 627| |/// interface with other build nodes produced by commands). 628| |class DirectoryStructureInputNodeTask : public Task { 629| | BuildNode& node; 630| | 631| | core::ValueType directorySignature; 632| | 633| 0| virtual void start(BuildEngine& engine) override { 634| 0| // Remove any trailing slash from the node name. 635| 0| StringRef path = node.getName(); 636| 0| if (path.endswith("/") && path != "/") { 637| 0| path = path.substr(0, path.size() - 1); 638| 0| } 639| 0| engine.taskNeedsInput( 640| 0| this, BuildKey::makeDirectoryTreeStructureSignature(path).toData(), 641| 0| /*inputID=*/0); 642| 0| } 643| | 644| | virtual void providePriorValue(BuildEngine&, 645| 0| const ValueType& value) override { 646| 0| } 647| | 648| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 649| 0| const ValueType& value) override { 650| 0| directorySignature = value; 651| 0| } 652| | 653| 0| virtual void inputsAvailable(BuildEngine& engine) override { 654| 0| // Simply propagate the value. 655| 0| engine.taskIsComplete(this, ValueType(directorySignature)); 656| 0| } 657| | 658| |public: 659| 0| DirectoryStructureInputNodeTask(BuildNode& node) : node(node) { 660| 0| assert(!node.isVirtual()); 661| 0| } 662| |}; 663| | 664| | 665| |/// This is the task to build a virtual node which isn't connected to any 666| |/// output. 667| |class VirtualInputNodeTask : public Task { 668| 0| virtual void start(BuildEngine& engine) override { 669| 0| } 670| | 671| | virtual void providePriorValue(BuildEngine&, 672| 0| const ValueType& value) override { 673| 0| } 674| | 675| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 676| 0| const ValueType& value) override { 677| 0| } 678| | 679| 0| virtual void inputsAvailable(BuildEngine& engine) override { 680| 0| engine.taskIsComplete( 681| 0| this, BuildValue::makeVirtualInput().toData()); 682| 0| } 683| | 684| |public: 685| 0| VirtualInputNodeTask() {} 686| | 687| | static bool isResultValid(BuildEngine& engine, const BuildNode& node, 688| 0| const BuildValue& value) { 689| 0| // Virtual input nodes are always valid unless the value type is wrong. 690| 0| return value.isVirtualInput(); 691| 0| } 692| |}; 693| | 694| | 695| |/// This is the task to "build" a node which is the product of some command. 696| |/// 697| |/// It is responsible for selecting the appropriate producer command to run to 698| |/// produce the node, and for synchronizing any external state the node depends 699| |/// on. 700| |class ProducedNodeTask : public Task { 701| | Node& node; 702| | BuildValue nodeResult; 703| | Command* producingCommand = nullptr; 704| | 705| | // Build specific data. 706| | // 707| | // FIXME: We should probably factor this out somewhere else, so we can enforce 708| | // it is never used when initialized incorrectly. 709| | 710| | // Whether this is a node we are unable to produce. 711| | bool isInvalid = false; 712| | 713| 0| virtual void start(BuildEngine& engine) override { 714| 0| // Request the producer command. 715| 0| if (node.getProducers().size() == 1) { 716| 0| producingCommand = node.getProducers()[0]; 717| 0| engine.taskNeedsInput(this, BuildKey::makeCommand( 718| 0| producingCommand->getName()).toData(), 719| 0| /*InputID=*/0); 720| 0| return; 721| 0| } 722| 0| 723| 0| // We currently do not support building nodes which have multiple producers. 724| 0| getBuildSystem(engine).getDelegate(). 725| 0| cannotBuildNodeDueToMultipleProducers(&node, node.getProducers()); 726| 0| isInvalid = true; 727| 0| } 728| | 729| | virtual void providePriorValue(BuildEngine&, 730| 0| const ValueType& value) override { 731| 0| } 732| | 733| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 734| 0| const ValueType& valueData) override { 735| 0| auto value = BuildValue::fromData(valueData); 736| 0| 737| 0| // Extract the node result from the command. 738| 0| assert(producingCommand); 739| 0| nodeResult = producingCommand->getResultForOutput(&node, value); 740| 0| } 741| | 742| 0| virtual void inputsAvailable(BuildEngine& engine) override { 743| 0| if (isInvalid) { 744| 0| getBuildSystem(engine).getDelegate().hadCommandFailure(); 745| 0| engine.taskIsComplete(this, BuildValue::makeFailedInput().toData()); 746| 0| return; 747| 0| } 748| 0| 749| 0| assert(!nodeResult.isInvalid()); 750| 0| 751| 0| // Complete the task immediately. 752| 0| engine.taskIsComplete(this, nodeResult.toData()); 753| 0| } 754| | 755| |public: 756| | ProducedNodeTask(Node& node) 757| 0| : node(node), nodeResult(BuildValue::makeInvalid()) {} 758| | 759| | static bool isResultValid(BuildEngine&, Node& node, 760| 0| const BuildValue& value) { 761| 0| // If the result was failure, we always need to rebuild (it may produce an 762| 0| // error). 763| 0| if (value.isFailedInput()) 764| 0| return false; 765| 0| 766| 0| // If the result was previously a missing input, it may have been because 767| 0| // we did not previously know how to produce this node. We do now, so 768| 0| // attempt to build it now. 769| 0| if (value.isMissingInput()) 770| 0| return false; 771| 0| 772| 0| // The produced node result itself doesn't need any synchronization. 773| 0| return true; 774| 0| } 775| |}; 776| | 777| | 778| |/// This task is responsible for computing the lists of files in directories. 779| |class DirectoryContentsTask : public Task { 780| | std::string path; 781| | 782| | /// The value for the input directory. 783| | BuildValue directoryValue; 784| | 785| 0| virtual void start(BuildEngine& engine) override { 786| 0| // Request the base directory node -- this task doesn't actually use the 787| 0| // value, but this connects the task to its producer if present. 788| 0| 789| 0| // FIXME: 790| 0| // 791| 0| //engine.taskMustFollow(this, BuildKey::makeNode(path).toData()); 792| 0| // 793| 0| // The taskMustFollow method expresses the weak dependency we have on 794| 0| // 'path', but only at the task level. What we really want is to say at the 795| 0| // 'isResultValid'/scanning level is 'must scan after'. That way we hold up 796| 0| // this and downstream rules until the 'path' node has been set into its 797| 0| // final state*. 798| 0| // 799| 0| // With the explicit dependency we are establishing with taskNeedsInput, we 800| 0| // will unfortunately mark directory contents as 'needs to be built' under 801| 0| // situations where non-releveant stat info has changed. This causes 802| 0| // unnecessary rebuilds. See rdar://problem/30640904 803| 0| // 804| 0| // * The 'final state' of a directory is also a thorny patch of toxic land 805| 0| // mines. We really want directory contents to weakly depend upon anything 806| 0| // that is currently and/or may be altered within it. i.e. if one rule 807| 0| // creates the directory and another rule writes a file into it, we want to 808| 0| // defer scanning until both of them have been scanned and possibly run. 809| 0| // Having a 'must scan after' would help with the first rule (mkdir), but 810| 0| // not the second, in particular if rules are added in subsequent builds. 811| 0| // Related rdar://problem/30638921 812| 0| // 813| 0| engine.taskNeedsInput( 814| 0| this, BuildKey::makeNode(path).toData(), /*inputID=*/0); 815| 0| } 816| | 817| | virtual void providePriorValue(BuildEngine&, 818| 0| const ValueType& value) override { 819| 0| } 820| | 821| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 822| 0| const ValueType& value) override { 823| 0| if (inputID == 0) { 824| 0| directoryValue = BuildValue::fromData(value); 825| 0| return; 826| 0| } 827| 0| } 828| | 829| 0| virtual void inputsAvailable(BuildEngine& engine) override { 830| 0| // FIXME: We should do this work in the background. 831| 0| 832| 0| if (directoryValue.isMissingInput()) { 833| 0| engine.taskIsComplete(this, BuildValue::makeMissingInput().toData()); 834| 0| return; 835| 0| } 836| 0| 837| 0| if (directoryValue.isFailedInput()) { 838| 0| engine.taskIsComplete(this, BuildValue::makeFailedInput().toData()); 839| 0| return; 840| 0| } 841| 0| 842| 0| std::vector filenames; 843| 0| getContents(path, filenames); 844| 0| 845| 0| // Create the result. 846| 0| engine.taskIsComplete( 847| 0| this, BuildValue::makeDirectoryContents(directoryValue.getOutputInfo(), 848| 0| filenames).toData()); 849| 0| } 850| | 851| | 852| 0| static void getContents(StringRef path, std::vector& filenames) { 853| 0| // Get the list of files in the directory. 854| 0| // FIXME: This is not going through the filesystem object. Indeed the fs 855| 0| // object does not currently support directory listing/iteration, but 856| 0| // probably should so that clients may override it. 857| 0| std::error_code ec; 858| 0| for (auto it = llvm::sys::fs::directory_iterator(path, ec), 859| 0| end = llvm::sys::fs::directory_iterator(); it != end; 860| 0| it = it.increment(ec)) { 861| 0| filenames.push_back(llvm::sys::path::filename(it->path())); 862| 0| } 863| 0| 864| 0| // Order the filenames. 865| 0| std::sort(filenames.begin(), filenames.end(), 866| 0| [](const std::string& a, const std::string& b) { 867| 0| return a < b; 868| 0| }); 869| 0| } 870| | 871| | 872| |public: 873| | DirectoryContentsTask(StringRef path) 874| 0| : path(path), directoryValue(BuildValue::makeInvalid()) {} 875| | 876| | static bool isResultValid(BuildEngine& engine, StringRef path, 877| 0| const BuildValue& value) { 878| 0| // The result is valid if the existence matches the existing value type, and 879| 0| // the file information remains the same. 880| 0| auto info = getBuildSystem(engine).getFileSystem().getFileInfo( 881| 0| path); 882| 0| if (info.isMissing()) { 883| 0| return value.isMissingInput(); 884| 0| } else { 885| 0| if (!value.isDirectoryContents()) 886| 0| return false; 887| 0| 888| 0| // If the type changes rebuild 889| 0| if (info.isDirectory() != value.getOutputInfo().isDirectory()) 890| 0| return false; 891| 0| 892| 0| // For files, it is direct stat info that matters 893| 0| if (!info.isDirectory()) 894| 0| return value.getOutputInfo() == info; 895| 0| 896| 0| // With filters, we list the current filtered contents and then compare 897| 0| // the lists. 898| 0| std::vector cur; 899| 0| getContents(path, cur); 900| 0| auto prev = value.getDirectoryContents(); 901| 0| 902| 0| if (cur.size() != prev.size()) 903| 0| return false; 904| 0| 905| 0| auto cur_it = cur.begin(); 906| 0| auto prev_it = prev.begin(); 907| 0| for (; cur_it != cur.end() && prev_it != prev.end(); cur_it++, prev_it++) { 908| 0| if (*cur_it != *prev_it) { 909| 0| return false; 910| 0| } 911| 0| } 912| 0| 913| 0| return true; 914| 0| } 915| 0| } 916| |}; 917| | 918| | 919| |/// This task is responsible for computing the filtered lists of files in 920| |/// directories. 921| |class FilteredDirectoryContentsTask : public Task { 922| | std::string path; 923| | 924| | /// The exclusion filters used while computing the signature 925| | StringList filters; 926| | 927| | /// The value for the input directory. 928| | BuildValue directoryValue; 929| | 930| 0| virtual void start(BuildEngine& engine) override { 931| 0| // FIXME: 932| 0| // 933| 0| //engine.taskMustFollow(this, BuildKey::makeNode(path).toData()); 934| 0| // 935| 0| // The taskMustFollow method expresses the weak dependency we have on 936| 0| // 'path', but only at the task level. What we really want is to say at the 937| 0| // 'isResultValid'/scanning level is 'must scan after'. That way we hold up 938| 0| // this and downstream rules until the 'path' node has been set into its 939| 0| // final state*. 940| 0| // 941| 0| // Here we depend on the file node so that it can be connected up to 942| 0| // potential producers and the raw stat information, in case something else 943| 0| // has changed the contents of the directory. The value does not encode the 944| 0| // raw stat information, thus will produce the same result if the filtered 945| 0| // contents is otherwise the same. This reduces unnecessary rebuilds. That 946| 0| // said, we are still subject to the 'final state' problem: 947| 0| // 948| 0| // * The 'final state' of a directory is also a thorny patch of toxic land 949| 0| // mines. We really want directory contents to weakly depend upon anything 950| 0| // that is currently and/or may be altered within it. i.e. if one rule 951| 0| // creates the directory and another rule writes a file into it, we want to 952| 0| // defer scanning until both of them have been scanned and possibly run. 953| 0| // Having a 'must scan after' would help with the first rule (mkdir), but 954| 0| // not the second, in particular if rules are added in subsequent builds. 955| 0| // Related rdar://problem/30638921 956| 0| engine.taskNeedsInput( 957| 0| this, BuildKey::makeNode(path).toData(), /*inputID=*/0); 958| 0| engine.taskNeedsInput( 959| 0| this, BuildKey::makeStat(path).toData(), /*inputID=*/1); 960| 0| } 961| | 962| | virtual void providePriorValue(BuildEngine&, 963| 0| const ValueType& value) override { 964| 0| } 965| | 966| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 967| 0| const ValueType& value) override { 968| 0| if (inputID == 1) { 969| 0| directoryValue = BuildValue::fromData(value); 970| 0| return; 971| 0| } 972| 0| } 973| | 974| 0| virtual void inputsAvailable(BuildEngine& engine) override { 975| 0| if (directoryValue.isMissingInput()) { 976| 0| engine.taskIsComplete(this, BuildValue::makeMissingInput().toData()); 977| 0| return; 978| 0| } 979| 0| 980| 0| if (!directoryValue.isExistingInput()) { 981| 0| engine.taskIsComplete(this, BuildValue::makeFailedInput().toData()); 982| 0| return; 983| 0| } 984| 0| 985| 0| auto& info = directoryValue.getOutputInfo(); 986| 0| 987| 0| // Non-directory things are just plain-ol' inputs 988| 0| if (!info.isDirectory()) { 989| 0| engine.taskIsComplete(this, BuildValue::makeExistingInput(info).toData()); 990| 0| return; 991| 0| } 992| 0| 993| 0| // Collect the filtered contents 994| 0| std::vector filenames; 995| 0| getFilteredContents(path, filters, filenames); 996| 0| 997| 0| // Create the result. 998| 0| engine.taskIsComplete( 999| 0| this, BuildValue::makeFilteredDirectoryContents(filenames).toData()); 1000| 0| } 1001| | 1002| | 1003| | static void getFilteredContents(StringRef path, const StringList& filters, 1004| 0| std::vector& filenames) { 1005| 0| auto filterStrings = filters.getValues(); 1006| 0| 1007| 0| // Get the list of files in the directory. 1008| 0| // FIXME: This is not going through the filesystem object. Indeed the fs 1009| 0| // object does not currently support directory listing/iteration, but 1010| 0| // probably should so that clients may override it. 1011| 0| std::error_code ec; 1012| 0| for (auto it = llvm::sys::fs::directory_iterator(path, ec), 1013| 0| end = llvm::sys::fs::directory_iterator(); it != end; 1014| 0| it = it.increment(ec)) { 1015| 0| std::string filename = llvm::sys::path::filename(it->path()); 1016| 0| bool excluded = false; 1017| 0| for (auto pattern : filterStrings) { 1018| 0| if (llbuild::basic::sys::filenameMatch(pattern.data(), 1019| 0| filename.c_str()) == 1020| 0| llbuild::basic::sys::MATCH) { 1021| 0| excluded = true; 1022| 0| break; 1023| 0| } 1024| 0| } 1025| 0| if (!excluded) 1026| 0| filenames.push_back(filename); 1027| 0| } 1028| 0| 1029| 0| // Order the filenames. 1030| 0| std::sort(filenames.begin(), filenames.end(), 1031| 0| [](const std::string& a, const std::string& b) { 1032| 0| return a < b; 1033| 0| }); 1034| 0| } 1035| | 1036| | 1037| |public: 1038| | FilteredDirectoryContentsTask(StringRef path, StringList&& filters) 1039| | : path(path), filters(std::move(filters)) 1040| 0| , directoryValue(BuildValue::makeInvalid()) {} 1041| |}; 1042| | 1043| | 1044| | 1045| |/// This is the task to "build" a directory node which will encapsulate (via a 1046| |/// signature) a (optionally) filtered view of the contents of the directory, 1047| |/// recursively. 1048| |class DirectoryTreeSignatureTask : public Task { 1049| | // The basic algorithm we need to follow: 1050| | // 1051| | // 1. Get the directory contents. 1052| | // 2. Get the subpath directory info. 1053| | // 3. For each node input, if it is a directory, get the input node for it. 1054| | // 1055| | // FIXME: This algorithm currently does a redundant stat for each directory, 1056| | // because we stat it once to find out it is a directory, then again when we 1057| | // gather its contents (to use for validating the directory contents). 1058| | // 1059| | // FIXME: We need to fix the directory list to not get contents for symbolic 1060| | // links. 1061| | 1062| | /// This structure encapsulates the information we need on each child. 1063| | struct SubpathInfo { 1064| | /// The filename; 1065| | std::string filename; 1066| | 1067| | /// The result of requesting the node at this subpath, once available. 1068| | ValueType value; 1069| | 1070| | /// The directory signature, if needed. 1071| | llvm::Optional directorySignatureValue; 1072| | }; 1073| | 1074| | /// The path we are taking the signature of. 1075| | std::string path; 1076| | 1077| | /// The exclusion filters used while computing the signature 1078| | StringList filters; 1079| | 1080| | /// The value for the directory itself. 1081| | ValueType directoryValue; 1082| | 1083| | /// The accumulated list of child input info. 1084| | /// 1085| | /// Once we have the input directory information, we resize this to match the 1086| | /// number of children to avoid dynamically resizing it. 1087| | std::vector childResults; 1088| | 1089| 0| virtual void start(BuildEngine& engine) override { 1090| 0| // Ask for the base directory directory contents. 1091| 0| if (filters.isEmpty()) { 1092| 0| engine.taskNeedsInput( 1093| 0| this, BuildKey::makeDirectoryContents(path).toData(), 1094| 0| /*inputID=*/0); 1095| 0| } else { 1096| 0| engine.taskNeedsInput( 1097| 0| this, BuildKey::makeFilteredDirectoryContents(path, filters).toData(), 1098| 0| /*inputID=*/0); 1099| 0| } 1100| 0| } 1101| | 1102| | virtual void providePriorValue(BuildEngine&, 1103| 0| const ValueType& value) override { 1104| 0| } 1105| | 1106| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 1107| 0| const ValueType& valueData) override { 1108| 0| // The first input is the directory contents. 1109| 0| if (inputID == 0) { 1110| 0| // Record the value for the directory. 1111| 0| directoryValue = valueData; 1112| 0| 1113| 0| // Request the inputs for each subpath. 1114| 0| auto value = BuildValue::fromData(valueData); 1115| 0| if ((filters.isEmpty() && !value.isDirectoryContents()) || 1116| 0| (!filters.isEmpty() && !value.isFilteredDirectoryContents())) { 1117| 0| return; 1118| 0| } 1119| 0| 1120| 0| assert(value.isFilteredDirectoryContents() || value.isDirectoryContents()); 1121| 0| auto filenames = value.getDirectoryContents(); 1122| 0| for (size_t i = 0; i != filenames.size(); ++i) { 1123| 0| SmallString<256> childPath{ path }; 1124| 0| llvm::sys::path::append(childPath, filenames[i]); 1125| 0| childResults.emplace_back(SubpathInfo{ filenames[i], {}, None }); 1126| 0| engine.taskNeedsInput(this, BuildKey::makeNode(childPath).toData(), 1127| 0| /*inputID=*/1 + i); 1128| 0| } 1129| 0| return; 1130| 0| } 1131| 0| 1132| 0| // If the input is a child, add it to the collection and dispatch a 1133| 0| // directory request if needed. 1134| 0| if (inputID >= 1 && inputID < 1 + childResults.size()) { 1135| 0| auto index = inputID - 1; 1136| 0| auto& childResult = childResults[index]; 1137| 0| childResult.value = valueData; 1138| 0| 1139| 0| // If this node is a directory, request its signature recursively. 1140| 0| auto value = BuildValue::fromData(valueData); 1141| 0| if (value.isExistingInput()) { 1142| 0| if (value.getOutputInfo().isDirectory()) { 1143| 0| SmallString<256> childPath{ path }; 1144| 0| llvm::sys::path::append(childPath, childResult.filename); 1145| 0| 1146| 0| engine.taskNeedsInput( 1147| 0| this, BuildKey::makeDirectoryTreeSignature(childPath, 1148| 0| filters).toData(), 1149| 0| /*inputID=*/1 + childResults.size() + index); 1150| 0| } 1151| 0| } 1152| 0| return; 1153| 0| } 1154| 0| 1155| 0| // Otherwise, the input should be a directory signature. 1156| 0| auto index = inputID - 1 - childResults.size(); 1157| 0| assert(index < childResults.size()); 1158| 0| childResults[index].directorySignatureValue = valueData; 1159| 0| } 1160| | 1161| 0| virtual void inputsAvailable(BuildEngine& engine) override { 1162| 0| // Compute the signature across all of the inputs. 1163| 0| using llvm::hash_combine; 1164| 0| llvm::hash_code code = hash_value(path); 1165| 0| 1166| 0| // Add the signature for the actual input path. 1167| 0| code = hash_combine( 1168| 0| code, hash_combine_range(directoryValue.begin(), directoryValue.end())); 1169| 0| 1170| 0| // For now, we represent this task as the aggregation of all the inputs. 1171| 0| for (const auto& info: childResults) { 1172| 0| // We merge the children by simply combining their encoded representation. 1173| 0| code = hash_combine( 1174| 0| code, hash_combine_range(info.value.begin(), info.value.end())); 1175| 0| if (info.directorySignatureValue.hasValue()) { 1176| 0| auto& data = info.directorySignatureValue.getValue(); 1177| 0| code = hash_combine( 1178| 0| code, hash_combine_range(data.begin(), data.end())); 1179| 0| } else { 1180| 0| // Combine a random number to represent nil. 1181| 0| code = hash_combine(code, 0XC183979C3E98722E); 1182| 0| } 1183| 0| } 1184| 0| 1185| 0| // Compute the signature. 1186| 0| engine.taskIsComplete(this, BuildValue::makeDirectoryTreeSignature( 1187| 0| CommandSignature(uint64_t(code))).toData()); 1188| 0| } 1189| | 1190| |public: 1191| | DirectoryTreeSignatureTask(StringRef path, StringList&& filters) 1192| 0| : path(path), filters(std::move(filters)) {} 1193| |}; 1194| | 1195| | 1196| |/// This is the task to "build" a directory structure node which will 1197| |/// encapsulate (via a signature) the structure of the directory, recursively. 1198| |class DirectoryTreeStructureSignatureTask : public Task { 1199| | // The basic algorithm we need to follow: 1200| | // 1201| | // 1. Get the directory contents. 1202| | // 2. Get the subpath directory info. 1203| | // 3. For each node input, if it is a directory, get the input node for it. 1204| | // 1205| | // FIXME: This algorithm currently does a redundant stat for each directory, 1206| | // because we stat it once to find out it is a directory, then again when we 1207| | // gather its contents (to use for validating the directory contents). 1208| | // 1209| | // FIXME: We need to fix the directory list to not get contents for symbolic 1210| | // links. 1211| | 1212| | /// This structure encapsulates the information we need on each child. 1213| | struct SubpathInfo { 1214| | /// The filename; 1215| | std::string filename; 1216| | 1217| | /// The result of requesting the node at this subpath, once available. 1218| | ValueType value; 1219| | 1220| | /// The directory structure signature, if needed. 1221| | llvm::Optional directoryStructureSignatureValue; 1222| | }; 1223| | 1224| | /// The path we are taking the signature of. 1225| | std::string path; 1226| | 1227| | /// The value for the directory itself. 1228| | ValueType directoryValue; 1229| | 1230| | /// The accumulated list of child input info. 1231| | /// 1232| | /// Once we have the input directory information, we resize this to match the 1233| | /// number of children to avoid dynamically resizing it. 1234| | std::vector childResults; 1235| | 1236| 0| virtual void start(BuildEngine& engine) override { 1237| 0| // Ask for the base directory directory contents. 1238| 0| engine.taskNeedsInput( 1239| 0| this, BuildKey::makeDirectoryContents(path).toData(), 1240| 0| /*inputID=*/0); 1241| 0| } 1242| | 1243| | virtual void providePriorValue(BuildEngine&, 1244| 0| const ValueType& value) override { 1245| 0| } 1246| | 1247| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 1248| 0| const ValueType& valueData) override { 1249| 0| // The first input is the directory contents. 1250| 0| if (inputID == 0) { 1251| 0| // Record the value for the directory. 1252| 0| directoryValue = valueData; 1253| 0| 1254| 0| // Request the inputs for each subpath. 1255| 0| auto value = BuildValue::fromData(valueData); 1256| 0| if (value.isMissingInput()) 1257| 0| return; 1258| 0| 1259| 0| assert(value.isDirectoryContents()); 1260| 0| auto filenames = value.getDirectoryContents(); 1261| 0| for (size_t i = 0; i != filenames.size(); ++i) { 1262| 0| SmallString<256> childPath{ path }; 1263| 0| llvm::sys::path::append(childPath, filenames[i]); 1264| 0| childResults.emplace_back(SubpathInfo{ filenames[i], {}, None }); 1265| 0| engine.taskNeedsInput(this, BuildKey::makeNode(childPath).toData(), 1266| 0| /*inputID=*/1 + i); 1267| 0| } 1268| 0| return; 1269| 0| } 1270| 0| 1271| 0| // If the input is a child, add it to the collection and dispatch a 1272| 0| // directory structure request if needed. 1273| 0| if (inputID >= 1 && inputID < 1 + childResults.size()) { 1274| 0| auto index = inputID - 1; 1275| 0| auto& childResult = childResults[index]; 1276| 0| childResult.value = valueData; 1277| 0| 1278| 0| // If this node is a directory, request its signature recursively. 1279| 0| auto value = BuildValue::fromData(valueData); 1280| 0| if (value.isExistingInput()) { 1281| 0| if (value.getOutputInfo().isDirectory()) { 1282| 0| SmallString<256> childPath{ path }; 1283| 0| llvm::sys::path::append(childPath, childResult.filename); 1284| 0| 1285| 0| engine.taskNeedsInput( 1286| 0| this, 1287| 0| BuildKey::makeDirectoryTreeStructureSignature(childPath).toData(), 1288| 0| /*inputID=*/1 + childResults.size() + index); 1289| 0| } 1290| 0| } 1291| 0| return; 1292| 0| } 1293| 0| 1294| 0| // Otherwise, the input should be a directory signature. 1295| 0| auto index = inputID - 1 - childResults.size(); 1296| 0| assert(index < childResults.size()); 1297| 0| childResults[index].directoryStructureSignatureValue = valueData; 1298| 0| } 1299| | 1300| 0| virtual void inputsAvailable(BuildEngine& engine) override { 1301| 0| // Compute the signature across all of the inputs. 1302| 0| using llvm::hash_combine; 1303| 0| llvm::hash_code code = hash_value(path); 1304| 0| 1305| 0| // Only merge the structure information on the directory itself. 1306| 0| { 1307| 0| // We need to merge mode information about the directory itself, in case 1308| 0| // it changes type. 1309| 0| auto value = BuildValue::fromData(directoryValue); 1310| 0| if (value.isDirectoryContents()) { 1311| 0| code = hash_combine(code, value.getOutputInfo().mode); 1312| 0| } else { 1313| 0| code = hash_combine( 1314| 0| code, hash_combine_range(directoryValue.begin(), 1315| 0| directoryValue.end())); 1316| 0| } 1317| 0| } 1318| 0| 1319| 0| // For now, we represent this task as the aggregation of all the inputs. 1320| 0| for (const auto& info: childResults) { 1321| 0| // We only merge the "structural" information on a child; i.e. its 1322| 0| // filename and type. 1323| 0| code = hash_combine(code, info.filename); 1324| 0| auto value = BuildValue::fromData(info.value); 1325| 0| if (value.isExistingInput()) { 1326| 0| code = hash_combine(code, value.getOutputInfo().mode); 1327| 0| } else { 1328| 0| // If this node has been modified to report a non-file value, just merge 1329| 0| // the encoded representation. 1330| 0| code = hash_combine( 1331| 0| code, hash_combine_range(info.value.begin(), info.value.end())); 1332| 0| } 1333| 0| 1334| 0| if (info.directoryStructureSignatureValue.hasValue()) { 1335| 0| auto& data = info.directoryStructureSignatureValue.getValue(); 1336| 0| code = hash_combine( 1337| 0| code, hash_combine_range(data.begin(), data.end())); 1338| 0| } else { 1339| 0| // Combine a random number to represent nil. 1340| 0| code = hash_combine(code, 0XC183979C3E98722E); 1341| 0| } 1342| 0| } 1343| 0| 1344| 0| // Compute the signature. 1345| 0| engine.taskIsComplete(this, BuildValue::makeDirectoryTreeStructureSignature( 1346| 0| CommandSignature(uint64_t(code))).toData()); 1347| 0| } 1348| | 1349| |public: 1350| 0| DirectoryTreeStructureSignatureTask(StringRef path) : path(path) {} 1351| |}; 1352| | 1353| | 1354| |/// This is the task to actually execute a command. 1355| |class CommandTask : public Task { 1356| | Command& command; 1357| | 1358| 0| virtual void start(BuildEngine& engine) override { 1359| 0| // Notify the client the command is preparing to run. 1360| 0| getBuildSystem(engine).getDelegate().commandPreparing(&command); 1361| 0| 1362| 0| command.start(getBuildSystem(engine).getCommandInterface(), this); 1363| 0| } 1364| | 1365| | virtual void providePriorValue(BuildEngine& engine, 1366| 0| const ValueType& valueData) override { 1367| 0| BuildValue value = BuildValue::fromData(valueData); 1368| 0| command.providePriorValue( 1369| 0| getBuildSystem(engine).getCommandInterface(), this, value); 1370| 0| } 1371| | 1372| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 1373| 0| const ValueType& valueData) override { 1374| 0| command.provideValue( 1375| 0| getBuildSystem(engine).getCommandInterface(), this, inputID, 1376| 0| BuildValue::fromData(valueData)); 1377| 0| } 1378| | 1379| 0| virtual void inputsAvailable(BuildEngine& engine) override { 1380| 0| auto& bsci = getBuildSystem(engine).getCommandInterface(); 1381| 0| auto fn = [this, &bsci=bsci](QueueJobContext* context) { 1382| 0| // If the build should cancel, do nothing. 1383| 0| if (getBuildSystem(bsci.getBuildEngine()).isCancelled()) { 1384| 0| bsci.taskIsComplete(this, BuildValue::makeCancelledCommand()); 1385| 0| return; 1386| 0| } 1387| 0| 1388| 0| // Check if the command should be skipped. 1389| 0| if (!bsci.getDelegate().shouldCommandStart(&command)) { 1390| 0| // We need to call commandFinished here because commandPreparing and 1391| 0| // shouldCommandStart guarantee that they're followed by 1392| 0| // commandFinished. 1393| 0| bsci.getDelegate().commandFinished(&command, ProcessStatus::Skipped); 1394| 0| bsci.taskIsComplete(this, BuildValue::makeSkippedCommand()); 1395| 0| return; 1396| 0| } 1397| 0| 1398| 0| // Execute the command, with notifications to the delegate. 1399| 0| command.execute(bsci, this, context, [this, &bsci](BuildValue&& result){ 1400| 0| // Inform the engine of the result. 1401| 0| if (result.isFailedCommand()) { 1402| 0| bsci.getDelegate().hadCommandFailure(); 1403| 0| } 1404| 0| bsci.taskIsComplete(this, std::move(result)); 1405| 0| }); 1406| 0| }; 1407| 0| bsci.addJob({ &command, std::move(fn) }); 1408| 0| } 1409| | 1410| |public: 1411| 0| CommandTask(Command& command) : command(command) {} 1412| | 1413| | static bool isResultValid(BuildEngine& engine, Command& command, 1414| 0| const BuildValue& value) { 1415| 0| // Delegate to the command for further checking. 1416| 0| return command.isResultValid( 1417| 0| getBuildSystem(engine).getBuildSystem(), value); 1418| 0| } 1419| |}; 1420| | 1421| |#pragma mark - BuildSystemEngineDelegate implementation 1422| | 1423| |/// This is a synthesized task used to represent a missing command. 1424| |/// 1425| |/// This command is used in cases where a command has been removed from the 1426| |/// manifest, but can still be found during an incremental rebuild. This command 1427| |/// is used to inject an invalid value thus forcing downstream clients to 1428| |/// rebuild. 1429| |class MissingCommandTask : public Task { 1430| |private: 1431| 0| virtual void start(BuildEngine& engine) override { } 1432| | virtual void providePriorValue(BuildEngine& engine, 1433| 0| const ValueType& valueData) override { } 1434| | 1435| | virtual void provideValue(BuildEngine& engine, uintptr_t inputID, 1436| 0| const ValueType& valueData) override { } 1437| | 1438| 0| virtual void inputsAvailable(BuildEngine& engine) override { 1439| 0| // A missing command always builds to an invalid value, and forces 1440| 0| // downstream clients to be rebuilt (at which point they will presumably see 1441| 0| // the command is no longer used). 1442| 0| return engine.taskIsComplete(this, BuildValue::makeInvalid().toData(), 1443| 0| /*forceChange=*/true); 1444| 0| } 1445| | 1446| |public: 1447| | using Task::Task; 1448| |}; 1449| | 1450| 0|const BuildDescription& BuildSystemEngineDelegate::getBuildDescription() const { 1451| 0| return system.getBuildDescription(); 1452| 0|} 1453| | 1454| |static BuildSystemDelegate::CommandStatusKind 1455| 0|convertStatusKind(core::Rule::StatusKind kind) { 1456| 0| switch (kind) { 1457| 0| case core::Rule::StatusKind::IsScanning: 1458| 0| return BuildSystemDelegate::CommandStatusKind::IsScanning; 1459| 0| case core::Rule::StatusKind::IsUpToDate: 1460| 0| return BuildSystemDelegate::CommandStatusKind::IsUpToDate; 1461| 0| case core::Rule::StatusKind::IsComplete: 1462| 0| return BuildSystemDelegate::CommandStatusKind::IsComplete; 1463| 0| } 1464| 0| assert(0 && "unknown status kind"); 1465| 0| return BuildSystemDelegate::CommandStatusKind::IsScanning; 1466| 0|} 1467| | 1468| 0|Rule BuildSystemEngineDelegate::lookupRule(const KeyType& keyData) { 1469| 0| // Decode the key. 1470| 0| auto key = BuildKey::fromData(keyData); 1471| 0| 1472| 0| switch (key.getKind()) { 1473| 0| case BuildKey::Kind::Unknown: 1474| 0| break; 1475| 0| 1476| 0| case BuildKey::Kind::Command: { 1477| 0| // Find the comand. 1478| 0| auto it = getBuildDescription().getCommands().find(key.getCommandName()); 1479| 0| if (it == getBuildDescription().getCommands().end()) { 1480| 0| // If there is no such command, produce an error task. 1481| 0| return Rule{ 1482| 0| keyData, 1483| 0| /*Action=*/ [](BuildEngine& engine) -> Task* { 1484| 0| return engine.registerTask(new MissingCommandTask()); 1485| 0| }, 1486| 0| /*IsValid=*/ [](BuildEngine&, const Rule& rule, 1487| 0| const ValueType& value) -> bool { 1488| 0| // The cached result for a missing command is never valid. 1489| 0| return false; 1490| 0| } 1491| 0| }; 1492| 0| } 1493| 0| 1494| 0| // Create the rule for the command. 1495| 0| Command* command = it->second.get(); 1496| 0| return Rule{ 1497| 0| keyData, 1498| 0| /*Action=*/ [command](BuildEngine& engine) -> Task* { 1499| 0| return engine.registerTask(new CommandTask(*command)); 1500| 0| }, 1501| 0| /*IsValid=*/ [command](BuildEngine& engine, const Rule& rule, 1502| 0| const ValueType& value) -> bool { 1503| 0| return CommandTask::isResultValid( 1504| 0| engine, *command, BuildValue::fromData(value)); 1505| 0| }, 1506| 0| /*UpdateStatus=*/ [command](BuildEngine& engine, 1507| 0| core::Rule::StatusKind status) { 1508| 0| return ::getBuildSystem(engine).getDelegate().commandStatusChanged( 1509| 0| command, convertStatusKind(status)); 1510| 0| } 1511| 0| }; 1512| 0| } 1513| 0| 1514| 0| case BuildKey::Kind::CustomTask: { 1515| 0| // Search for a tool which knows how to create the given custom task. 1516| 0| // 1517| 0| // FIXME: We should most likely have some kind of registration process so we 1518| 0| // can do an efficient query here, but exactly how this should look isn't 1519| 0| // clear yet. 1520| 0| for (const auto& it: getBuildDescription().getTools()) { 1521| 0| auto result = it.second->createCustomCommand(key); 1522| 0| if (!result) continue; 1523| 0| 1524| 0| // Save the custom command. 1525| 0| customTasks.emplace_back(std::move(result)); 1526| 0| Command *command = customTasks.back().get(); 1527| 0| 1528| 0| return Rule{ 1529| 0| keyData, 1530| 0| /*Action=*/ [command](BuildEngine& engine) -> Task* { 1531| 0| return engine.registerTask(new CommandTask(*command)); 1532| 0| }, 1533| 0| /*IsValid=*/ [command](BuildEngine& engine, const Rule& rule, 1534| 0| const ValueType& value) -> bool { 1535| 0| return CommandTask::isResultValid( 1536| 0| engine, *command, BuildValue::fromData(value)); 1537| 0| } 1538| 0| }; 1539| 0| } 1540| 0| 1541| 0| // We were unable to create an appropriate custom command, produce an error 1542| 0| // task. 1543| 0| return Rule{ 1544| 0| keyData, 1545| 0| /*Action=*/ [](BuildEngine& engine) -> Task* { 1546| 0| return engine.registerTask(new MissingCommandTask()); 1547| 0| }, 1548| 0| /*IsValid=*/ [](BuildEngine&, const Rule& rule, 1549| 0| const ValueType& value) -> bool { 1550| 0| // The cached result for a missing command is never valid. 1551| 0| return false; 1552| 0| } 1553| 0| }; 1554| 0| } 1555| 0| 1556| 0| case BuildKey::Kind::DirectoryContents: { 1557| 0| std::string path = key.getDirectoryPath(); 1558| 0| return Rule{ 1559| 0| keyData, 1560| 0| /*Action=*/ [path](BuildEngine& engine) -> Task* { 1561| 0| return engine.registerTask(new DirectoryContentsTask(path)); 1562| 0| }, 1563| 0| /*IsValid=*/ [path](BuildEngine& engine, const Rule& rule, 1564| 0| const ValueType& value) mutable -> bool { 1565| 0| return DirectoryContentsTask::isResultValid( 1566| 0| engine, path, BuildValue::fromData(value)); 1567| 0| } 1568| 0| }; 1569| 0| } 1570| 0| 1571| 0| case BuildKey::Kind::FilteredDirectoryContents: { 1572| 0| std::string path = key.getFilteredDirectoryPath(); 1573| 0| std::string patterns = key.getContentExclusionPatterns(); 1574| 0| return Rule{ 1575| 0| keyData, 1576| 0| /*Action=*/ [path, patterns](BuildEngine& engine) -> Task* { 1577| 0| BinaryDecoder decoder(patterns); 1578| 0| return engine.registerTask(new FilteredDirectoryContentsTask(path, 1579| 0| StringList(decoder))); 1580| 0| }, 1581| 0| /*IsValid=*/ nullptr 1582| 0| }; 1583| 0| } 1584| 0| 1585| 0| case BuildKey::Kind::DirectoryTreeSignature: { 1586| 0| std::string path = key.getDirectoryTreeSignaturePath(); 1587| 0| std::string filters = key.getContentExclusionPatterns(); 1588| 0| return Rule{ 1589| 0| keyData, 1590| 0| /*Action=*/ [path, filters]( 1591| 0| BuildEngine& engine) mutable -> Task* { 1592| 0| BinaryDecoder decoder(filters); 1593| 0| return engine.registerTask(new DirectoryTreeSignatureTask( 1594| 0| path, StringList(decoder))); 1595| 0| }, 1596| 0| // Directory signatures don't require any validation outside of their 1597| 0| // concrete dependencies. 1598| 0| /*IsValid=*/ nullptr 1599| 0| }; 1600| 0| } 1601| 0| 1602| 0| case BuildKey::Kind::DirectoryTreeStructureSignature: { 1603| 0| std::string path = key.getDirectoryPath(); 1604| 0| return Rule{ 1605| 0| keyData, 1606| 0| /*Action=*/ [path]( 1607| 0| BuildEngine& engine) mutable -> Task* { 1608| 0| return engine.registerTask(new DirectoryTreeStructureSignatureTask(path)); 1609| 0| }, 1610| 0| // Directory signatures don't require any validation outside of their 1611| 0| // concrete dependencies. 1612| 0| /*IsValid=*/ nullptr 1613| 0| }; 1614| 0| } 1615| 0| 1616| 0| case BuildKey::Kind::Node: { 1617| 0| // Find the node. 1618| 0| auto it = getBuildDescription().getNodes().find(key.getNodeName()); 1619| 0| BuildNode* node; 1620| 0| if (it != getBuildDescription().getNodes().end()) { 1621| 0| node = static_cast(it->second.get()); 1622| 0| } else { 1623| 0| auto it = dynamicNodes.find(key.getNodeName()); 1624| 0| if (it != dynamicNodes.end()) { 1625| 0| node = it->second.get(); 1626| 0| } else { 1627| 0| // Create nodes on the fly for any unknown ones. 1628| 0| auto nodeOwner = system.lookupNode( 1629| 0| key.getNodeName(), /*isImplicit=*/true); 1630| 0| node = nodeOwner.get(); 1631| 0| dynamicNodes[key.getNodeName()] = std::move(nodeOwner); 1632| 0| } 1633| 0| } 1634| 0| 1635| 0| // Create the rule used to construct this node. 1636| 0| // 1637| 0| // We could bypass this level and directly return the rule to run the 1638| 0| // command, which would reduce the number of tasks in the system. For now we 1639| 0| // do the uniform thing, but do differentiate between input and command 1640| 0| // nodes. 1641| 0| 1642| 0| // Create an input node if there are no producers. 1643| 0| if (node->getProducers().empty()) { 1644| 0| if (node->isVirtual()) { 1645| 0| return Rule{ 1646| 0| keyData, 1647| 0| /*Action=*/ [](BuildEngine& engine) -> Task* { 1648| 0| return engine.registerTask(new VirtualInputNodeTask()); 1649| 0| }, 1650| 0| /*IsValid=*/ [node](BuildEngine& engine, const Rule& rule, 1651| 0| const ValueType& value) -> bool { 1652| 0| return VirtualInputNodeTask::isResultValid( 1653| 0| engine, *node, BuildValue::fromData(value)); 1654| 0| } 1655| 0| }; 1656| 0| } 1657| 0| 1658| 0| if (node->isDirectory()) { 1659| 0| return Rule{ 1660| 0| keyData, 1661| 0| /*Action=*/ [node](BuildEngine& engine) -> Task* { 1662| 0| return engine.registerTask(new DirectoryInputNodeTask(*node)); 1663| 0| }, 1664| 0| // Directory nodes don't require any validation outside of their 1665| 0| // concrete dependencies. 1666| 0| /*IsValid=*/ nullptr 1667| 0| }; 1668| 0| } 1669| 0| 1670| 0| if (node->isDirectoryStructure()) { 1671| 0| return Rule{ 1672| 0| keyData, 1673| 0| /*Action=*/ [node](BuildEngine& engine) -> Task* { 1674| 0| return engine.registerTask( 1675| 0| new DirectoryStructureInputNodeTask(*node)); 1676| 0| }, 1677| 0| // Directory nodes don't require any validation outside of their 1678| 0| // concrete dependencies. 1679| 0| /*IsValid=*/ nullptr 1680| 0| }; 1681| 0| } 1682| 0| 1683| 0| return Rule{ 1684| 0| keyData, 1685| 0| /*Action=*/ [node](BuildEngine& engine) -> Task* { 1686| 0| return engine.registerTask(new FileInputNodeTask(*node)); 1687| 0| }, 1688| 0| /*IsValid=*/ [node](BuildEngine& engine, const Rule& rule, 1689| 0| const ValueType& value) -> bool { 1690| 0| return FileInputNodeTask::isResultValid( 1691| 0| engine, *node, BuildValue::fromData(value)); 1692| 0| } 1693| 0| }; 1694| 0| } 1695| 0| 1696| 0| // Otherwise, create a task for a produced node. 1697| 0| return Rule{ 1698| 0| keyData, 1699| 0| /*Action=*/ [node](BuildEngine& engine) -> Task* { 1700| 0| return engine.registerTask(new ProducedNodeTask(*node)); 1701| 0| }, 1702| 0| /*IsValid=*/ [node](BuildEngine& engine, const Rule& rule, 1703| 0| const ValueType& value) -> bool { 1704| 0| return ProducedNodeTask::isResultValid( 1705| 0| engine, *node, BuildValue::fromData(value)); 1706| 0| } 1707| 0| }; 1708| 0| } 1709| 0| 1710| 0| case BuildKey::Kind::Stat: { 1711| 0| StatNode* statnode; 1712| 0| auto it = dynamicStatNodes.find(key.getStatName()); 1713| 0| if (it != dynamicStatNodes.end()) { 1714| 0| statnode = it->second.get(); 1715| 0| } else { 1716| 0| // Create nodes on the fly for any unknown ones. 1717| 0| auto statOwner = llvm::make_unique(key.getStatName()); 1718| 0| statnode = statOwner.get(); 1719| 0| dynamicStatNodes[key.getStatName()] = std::move(statOwner); 1720| 0| } 1721| 0| 1722| 0| // Create the rule to construct this target. 1723| 0| return Rule{ 1724| 0| keyData, 1725| 0| /*Action=*/ [statnode](BuildEngine& engine) -> Task* { 1726| 0| return engine.registerTask(new StatTask(*statnode)); 1727| 0| }, 1728| 0| /*IsValid=*/ [statnode](BuildEngine& engine, const Rule& rule, 1729| 0| const ValueType& value) -> bool { 1730| 0| return StatTask::isResultValid( 1731| 0| engine, *statnode, BuildValue::fromData(value)); 1732| 0| } 1733| 0| }; 1734| 0| } 1735| 0| case BuildKey::Kind::Target: { 1736| 0| // Find the target. 1737| 0| auto it = getBuildDescription().getTargets().find(key.getTargetName()); 1738| 0| if (it == getBuildDescription().getTargets().end()) { 1739| 0| // FIXME: Invalid target name, produce an error. 1740| 0| assert(0 && "FIXME: invalid target"); 1741| 0| abort(); 1742| 0| } 1743| 0| 1744| 0| // Create the rule to construct this target. 1745| 0| Target* target = it->second.get(); 1746| 0| return Rule{ 1747| 0| keyData, 1748| 0| /*Action=*/ [target](BuildEngine& engine) -> Task* { 1749| 0| return engine.registerTask(new TargetTask(*target)); 1750| 0| }, 1751| 0| /*IsValid=*/ [target](BuildEngine& engine, const Rule& rule, 1752| 0| const ValueType& value) -> bool { 1753| 0| return TargetTask::isResultValid( 1754| 0| engine, *target, BuildValue::fromData(value)); 1755| 0| } 1756| 0| }; 1757| 0| } 1758| 0| } 1759| 0| 1760| 0| assert(0 && "invalid key type"); 1761| 0| abort(); 1762| 0|} 1763| | 1764| |bool BuildSystemEngineDelegate::shouldResolveCycle(const std::vector& cycle, 1765| | Rule* candidateRule, 1766| 0| Rule::CycleAction action) { 1767| 0| return static_cast(&getBuildSystem().getDelegate())->shouldResolveCycle(cycle, candidateRule, action); 1768| 0|} 1769| | 1770| 0|void BuildSystemEngineDelegate::cycleDetected(const std::vector& cycle) { 1771| 0| // Track that the build has been aborted. 1772| 0| getBuildSystem().setBuildWasAborted(true); 1773| 0| static_cast(&getBuildSystem().getDelegate())->cycleDetected(cycle); 1774| 0|} 1775| | 1776| 0|void BuildSystemEngineDelegate::error(const Twine& message) { 1777| 0| system.error(system.getMainFilename(), message); 1778| 0|} 1779| | 1780| |#pragma mark - BuildSystemImpl implementation 1781| | 1782| |std::unique_ptr 1783| 0|BuildSystemImpl::lookupNode(StringRef name, bool isImplicit) { 1784| 0| bool isDirectory = name.endswith("/"); 1785| 0| bool isVirtual = !name.empty() && name[0] == '<' && name.back() == '>'; 1786| 0| return llvm::make_unique(name, isDirectory, 1787| 0| /*isDirectoryStructure=*/false, 1788| 0| isVirtual, 1789| 0| /*isCommandTimestamp=*/false, 1790| 0| /*isMutable=*/false); 1791| 0|} 1792| | 1793| 0|llvm::Optional BuildSystemImpl::build(BuildKey key) { 1794| 0| 1795| 0| if (basic::sys::raiseOpenFileLimit() != 0) { 1796| 0| error(getMainFilename(), "failed to raise open file limit"); 1797| 0| return None; 1798| 0| } 1799| 0| 1800| 0| // Aquire lock and create execution queue. 1801| 0| { 1802| 0| std::lock_guard guard(executionQueueMutex); 1803| 0| 1804| 0| // If we were cancelled, return. 1805| 0| if (isCancelled()) { 1806| 0| return None; 1807| 0| } 1808| 0| 1809| 0| executionQueue = delegate.createExecutionQueue(); 1810| 0| } 1811| 0| 1812| 0| // Build the target. 1813| 0| buildWasAborted = false; 1814| 0| auto result = getBuildEngine().build(key.toData()); 1815| 0| 1816| 0| // Release the execution queue, impicitly waiting for it to complete. The 1817| 0| // asynchronous nature of the engine callbacks means it is possible for the 1818| 0| // queue to have notified the engine of the last task completion, but still 1819| 0| // have other work to perform (e.g., informing the client of command 1820| 0| // completion). 1821| 0| executionQueue.reset(); 1822| 0| 1823| 0| if (buildWasAborted) 1824| 0| return None; 1825| 0| return BuildValue::fromData(result); 1826| 0|} 1827| | 1828| 0|bool BuildSystemImpl::build(StringRef target) { 1829| 0| // The build description must have been loaded. 1830| 0| if (!buildDescription) { 1831| 0| error(getMainFilename(), "no build description loaded"); 1832| 0| return false; 1833| 0| } 1834| 0| 1835| 0| // If target name is not passed then we try to load the default target name 1836| 0| // from manifest file 1837| 0| if (target.empty()) { 1838| 0| target = getBuildDescription().getDefaultTarget(); 1839| 0| } 1840| 0| 1841| 0| // Validate the target name. 1842| 0| auto &targets = getBuildDescription().getTargets(); 1843| 0| if (targets.find(target) == targets.end()) { 1844| 0| error(getMainFilename(), "No target named '" + target + "' in build description"); 1845| 0| return false; 1846| 0| } 1847| 0| 1848| 0| return build(BuildKey::makeTarget(target)).hasValue(); 1849| 0|} 1850| | 1851| |#pragma mark - PhonyTool implementation 1852| | 1853| |class PhonyCommand : public ExternalCommand { 1854| |public: 1855| | using ExternalCommand::ExternalCommand; 1856| | 1857| 0| virtual bool shouldShowStatus() override { return false; } 1858| | 1859| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 1860| 0| llvm::raw_svector_ostream(result) << getName(); 1861| 0| } 1862| | 1863| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 1864| 0| llvm::raw_svector_ostream(result) << getName(); 1865| 0| } 1866| | 1867| | virtual void executeExternalCommand( 1868| | BuildSystemCommandInterface& bsci, 1869| | Task* task, 1870| | QueueJobContext* context, 1871| 0| llvm::Optional completionFn) override { 1872| 0| // Nothing needs to be done for phony commands. 1873| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 1874| 0| fn(ProcessStatus::Succeeded); 1875| 0| }); 1876| 0| } 1877| | 1878| 0| virtual BuildValue getResultForOutput(Node* node, const BuildValue& value) override { 1879| 0| // If the node is virtual, the output is always a virtual input value, 1880| 0| // regardless of the actual build value. 1881| 0| // 1882| 0| // This is a special case for phony commands, to avoid them incorrectly 1883| 0| // propagating failed/cancelled states onwards to downstream commands when 1884| 0| // they are being used only for ordering purposes. 1885| 0| auto buildNode = static_cast(node); 1886| 0| if (buildNode->isVirtual() && !buildNode->isCommandTimestamp()) { 1887| 0| return BuildValue::makeVirtualInput(); 1888| 0| } 1889| 0| 1890| 0| // Otherwise, delegate to the inherited implementation. 1891| 0| return ExternalCommand::getResultForOutput(node, value); 1892| 0| } 1893| |}; 1894| | 1895| |class PhonyTool : public Tool { 1896| |public: 1897| | using Tool::Tool; 1898| | 1899| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 1900| 0| StringRef value) override { 1901| 0| // No supported configuration attributes. 1902| 0| ctx.error("unexpected attribute: '" + name + "'"); 1903| 0| return false; 1904| 0| } 1905| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 1906| 0| ArrayRef values) override { 1907| 0| // No supported configuration attributes. 1908| 0| ctx.error("unexpected attribute: '" + name + "'"); 1909| 0| return false; 1910| 0| } 1911| | virtual bool configureAttribute( 1912| | const ConfigureContext& ctx, StringRef name, 1913| 0| ArrayRef> values) override { 1914| 0| // No supported attributes. 1915| 0| ctx.error("unexpected attribute: '" + name + "'"); 1916| 0| return false; 1917| 0| } 1918| | 1919| 0| virtual std::unique_ptr createCommand(StringRef name) override { 1920| 0| return llvm::make_unique(name); 1921| 0| } 1922| |}; 1923| | 1924| |#pragma mark - ShellTool implementation 1925| | 1926| |class ShellCommand : public ExternalCommand { 1927| | /// The dependencies style to expect (in the `depsPath`). 1928| | enum class DepsStyle { 1929| | /// No discovered dependencies are in use. 1930| | Unused = 0, 1931| | 1932| | /// "Makefile" style dependencies in the form typically generated by C 1933| | /// compilers, wherein the dependencies of the first target are treated as 1934| | /// dependencies of the command. 1935| | Makefile, 1936| | 1937| | /// Darwin's DependencyInfo format. 1938| | DependencyInfo, 1939| | }; 1940| | 1941| | /// The command line arguments. 1942| | std::vector args; 1943| | 1944| | /// Arbitrary string used to contribute to the task signature. 1945| | std::string signatureData; 1946| | 1947| | /// The environment to use. If empty, the environment will be inherited. 1948| | SmallVector, 1> env; 1949| | 1950| | /// The path to the dependency output file, if used. 1951| | SmallVector depsPaths{}; 1952| | 1953| | /// The style of dependencies used. 1954| | DepsStyle depsStyle = DepsStyle::Unused; 1955| | 1956| | /// Whether to inherit the base environment. 1957| | bool inheritEnv = true; 1958| | 1959| | /// Whether it is safe to interrupt (SIGINT) the tool during cancellation. 1960| | bool canSafelyInterrupt = true; 1961| | 1962| | /// Working directory in which to spawn the external command 1963| | std::string workingDirectory; 1964| | 1965| | /// Whether the control pipe is enabled for this command 1966| | bool controlEnabled = true; 1967| | 1968| | /// The cached signature, once computed -- 0 is used as a sentinel value. 1969| | std::atomic cachedSignature{ }; 1970| | 1971| 0| virtual CommandSignature getSignature() override { 1972| 0| CommandSignature signature = cachedSignature; 1973| 0| if (!signature.isNull()) 1974| 0| return signature; 1975| 0| 1976| 0| auto code = ExternalCommand::getSignature(); 1977| 0| if (!signatureData.empty()) { 1978| 0| code = code.combine(signatureData); 1979| 0| } else { 1980| 0| for (const auto& arg: args) { 1981| 0| code = code.combine(arg); 1982| 0| } 1983| 0| for (const auto& entry: env) { 1984| 0| code = code.combine(entry.first); 1985| 0| code = code.combine(entry.second); 1986| 0| } 1987| 0| for (const auto& path: depsPaths) { 1988| 0| code = code.combine(path); 1989| 0| } 1990| 0| code = code.combine(int(depsStyle)); 1991| 0| code = code.combine(int(inheritEnv)); 1992| 0| code = code.combine(int(canSafelyInterrupt)); 1993| 0| } 1994| 0| signature = code; 1995| 0| if (signature.isNull()) { 1996| 0| signature = CommandSignature(1); 1997| 0| } 1998| 0| cachedSignature = signature; 1999| 0| return signature; 2000| 0| } 2001| | 2002| | bool processDiscoveredDependencies(BuildSystemCommandInterface& bsci, 2003| | Task* task, 2004| 0| QueueJobContext* context) { 2005| 0| // It is an error if the dependencies style is not specified. 2006| 0| // 2007| 0| // FIXME: Diagnose this sooner. 2008| 0| if (depsStyle == DepsStyle::Unused) { 2009| 0| getBuildSystem(bsci.getBuildEngine()).error( 2010| 0| "", "missing required 'deps-style' specifier"); 2011| 0| return false; 2012| 0| } 2013| 0| 2014| 0| for (const auto& depsPath: depsPaths) { 2015| 0| // Read the dependencies file. 2016| 0| auto input = bsci.getFileSystem().getFileContents(depsPath); 2017| 0| if (!input) { 2018| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(this, 2019| 0| "unable to open dependencies file (" + depsPath + ")"); 2020| 0| return false; 2021| 0| } 2022| 0| 2023| 0| switch (depsStyle) { 2024| 0| case DepsStyle::Unused: 2025| 0| assert(0 && "unreachable"); 2026| 0| break; 2027| 0| 2028| 0| case DepsStyle::Makefile: 2029| 0| if (!processMakefileDiscoveredDependencies( 2030| 0| bsci, task, context, depsPath, input.get())) 2031| 0| return false; 2032| 0| continue; 2033| 0| 2034| 0| case DepsStyle::DependencyInfo: 2035| 0| if (!processDependencyInfoDiscoveredDependencies( 2036| 0| bsci, task, context, depsPath, input.get())) 2037| 0| return false; 2038| 0| continue; 2039| 0| } 2040| 0| 2041| 0| llvm::report_fatal_error("unknown dependencies style"); 2042| 0| } 2043| 0| 2044| 0| return true; 2045| 0| } 2046| | 2047| | bool processMakefileDiscoveredDependencies(BuildSystemCommandInterface& bsci, 2048| | Task* task, 2049| | QueueJobContext* context, 2050| | StringRef depsPath, 2051| 0| llvm::MemoryBuffer* input) { 2052| 0| // Parse the output. 2053| 0| // 2054| 0| // We just ignore the rule, and add any dependency that we encounter in the 2055| 0| // file. 2056| 0| struct DepsActions : public core::MakefileDepsParser::ParseActions { 2057| 0| BuildSystemCommandInterface& bsci; 2058| 0| Task* task; 2059| 0| ShellCommand* command; 2060| 0| StringRef depsPath; 2061| 0| unsigned numErrors{0}; 2062| 0| 2063| 0| DepsActions(BuildSystemCommandInterface& bsci, Task* task, 2064| 0| ShellCommand* command, StringRef depsPath) 2065| 0| : bsci(bsci), task(task), command(command), depsPath(depsPath) {} 2066| 0| 2067| 0| virtual void error(const char* message, uint64_t position) override { 2068| 0| std::stringstream msg; 2069| 0| msg << "error reading dependency file '" << depsPath.str() << "': " 2070| 0| << message << " at position " << position; 2071| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError( 2072| 0| command, msg.str()); 2073| 0| ++numErrors; 2074| 0| } 2075| 0| 2076| 0| virtual void actOnRuleDependency(const char* dependency, 2077| 0| uint64_t length, 2078| 0| const StringRef unescapedWord) override { 2079| 0| if (llvm::sys::path::is_absolute(unescapedWord)) { 2080| 0| bsci.taskDiscoveredDependency(task, BuildKey::makeNode(unescapedWord)); 2081| 0| return; 2082| 0| } 2083| 0| 2084| 0| // Generate absolute path 2085| 0| // 2086| 0| // NOTE: This is making the assumption that relative paths coming in a 2087| 0| // dependency file are in relation to the explictly set working 2088| 0| // directory, or the current working directory when it has not been set. 2089| 0| SmallString absPath = StringRef(command->workingDirectory); 2090| 0| llvm::sys::path::append(absPath, unescapedWord); 2091| 0| llvm::sys::fs::make_absolute(absPath); 2092| 0| 2093| 0| bsci.taskDiscoveredDependency(task, BuildKey::makeNode(absPath)); 2094| 0| } 2095| 0| 2096| 0| virtual void actOnRuleStart(const char* name, uint64_t length, 2097| 0| const StringRef unescapedWord) override {} 2098| 0| 2099| 0| virtual void actOnRuleEnd() override {} 2100| 0| }; 2101| 0| 2102| 0| DepsActions actions(bsci, task, this, depsPath); 2103| 0| core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(), 2104| 0| actions).parse(); 2105| 0| return actions.numErrors == 0; 2106| 0| } 2107| | 2108| | bool 2109| | processDependencyInfoDiscoveredDependencies(BuildSystemCommandInterface& bsci, 2110| | Task* task, 2111| | QueueJobContext* context, 2112| | StringRef depsPath, 2113| 0| llvm::MemoryBuffer* input) { 2114| 0| // Parse the output. 2115| 0| // 2116| 0| // We just ignore the rule, and add any dependency that we encounter in the 2117| 0| // file. 2118| 0| struct DepsActions : public core::DependencyInfoParser::ParseActions { 2119| 0| BuildSystemCommandInterface& bsci; 2120| 0| Task* task; 2121| 0| ShellCommand* command; 2122| 0| StringRef depsPath; 2123| 0| unsigned numErrors{0}; 2124| 0| 2125| 0| DepsActions(BuildSystemCommandInterface& bsci, Task* task, 2126| 0| ShellCommand* command, StringRef depsPath) 2127| 0| : bsci(bsci), task(task), command(command), depsPath(depsPath) {} 2128| 0| 2129| 0| virtual void error(const char* message, uint64_t position) override { 2130| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(command, 2131| 0| "error reading dependency file '" + depsPath.str() + 2132| 0| "': " + std::string(message)); 2133| 0| ++numErrors; 2134| 0| } 2135| 0| 2136| 0| // Ignore everything but actual inputs. 2137| 0| virtual void actOnVersion(StringRef) override { } 2138| 0| virtual void actOnMissing(StringRef) override { } 2139| 0| virtual void actOnOutput(StringRef) override { } 2140| 0| 2141| 0| virtual void actOnInput(StringRef name) override { 2142| 0| bsci.taskDiscoveredDependency(task, BuildKey::makeNode(name)); 2143| 0| } 2144| 0| }; 2145| 0| 2146| 0| DepsActions actions(bsci, task, this, depsPath); 2147| 0| core::DependencyInfoParser(input->getBuffer(), actions).parse(); 2148| 0| return actions.numErrors == 0; 2149| 0| } 2150| | 2151| |public: 2152| | using ExternalCommand::ExternalCommand; 2153| | ShellCommand(StringRef name, bool controlEnabled) : ExternalCommand(name), 2154| 0| controlEnabled(controlEnabled) { } 2155| | 2156| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 2157| 0| llvm::raw_svector_ostream(result) << getDescription(); 2158| 0| } 2159| | 2160| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 2161| 0| llvm::raw_svector_ostream os(result); 2162| 0| bool first = true; 2163| 0| for (const auto& arg: args) { 2164| 0| if (!first) os << " "; 2165| 0| first = false; 2166| 0| basic::appendShellEscapedString(os, arg); 2167| 0| } 2168| 0| } 2169| | 2170| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2171| 0| StringRef value) override { 2172| 0| if (name == "args") { 2173| 0| // When provided as a scalar string, we default to executing using the 2174| 0| // shell. 2175| 0| args.clear(); 2176| |#if defined(_WIN32) 2177| | args.push_back(ctx.getDelegate().getInternedString( 2178| | "C:\\windows\\system32\\cmd.exe")); 2179| | args.push_back(ctx.getDelegate().getInternedString("/C")); 2180| |#else 2181| | args.push_back(ctx.getDelegate().getInternedString("/bin/sh")); 2182| 0| args.push_back(ctx.getDelegate().getInternedString("-c")); 2183| 0|#endif 2184| 0| args.push_back(ctx.getDelegate().getInternedString(value)); 2185| 0| } else if (name == "signature") { 2186| 0| signatureData = value; 2187| 0| } else if (name == "deps") { 2188| 0| depsPaths.clear(); 2189| 0| depsPaths.emplace_back(value); 2190| 0| } else if (name == "deps-style") { 2191| 0| if (value == "makefile") { 2192| 0| depsStyle = DepsStyle::Makefile; 2193| 0| } else if (value == "dependency-info") { 2194| 0| depsStyle = DepsStyle::DependencyInfo; 2195| 0| } else { 2196| 0| ctx.error("unknown 'deps-style': '" + value + "'"); 2197| 0| return false; 2198| 0| } 2199| 0| return true; 2200| 0| } else if (name == "can-safely-interrupt") { 2201| 0| if (value != "true" && value != "false") { 2202| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 2203| 0| name + "'"); 2204| 0| return false; 2205| 0| } 2206| 0| canSafelyInterrupt = value == "true"; 2207| 0| } else if (name == "inherit-env") { 2208| 0| if (value != "true" && value != "false") { 2209| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 2210| 0| name + "'"); 2211| 0| return false; 2212| 0| } 2213| 0| inheritEnv = value == "true"; 2214| 0| } else if (name == "working-directory") { 2215| 0| // Ensure the working directory is absolute. This will make sure any 2216| 0| // relative directories are interpreted as relative to the CWD at the time 2217| 0| // the rule is defined. 2218| 0| SmallString wd = value; 2219| 0| llvm::sys::fs::make_absolute(wd); 2220| 0| workingDirectory = StringRef(wd); 2221| 0| } else if (name == "control-enabled") { 2222| 0| if (value != "true" && value != "false") { 2223| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 2224| 0| name + "'"); 2225| 0| return false; 2226| 0| } 2227| 0| controlEnabled = value == "true"; 2228| 0| } else { 2229| 0| return ExternalCommand::configureAttribute(ctx, name, value); 2230| 0| } 2231| 0| 2232| 0| return true; 2233| 0| } 2234| | 2235| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2236| 0| ArrayRef values) override { 2237| 0| if (name == "args") { 2238| 0| // Diagnose missing arguments. 2239| 0| if (values.empty()) { 2240| 0| ctx.error("invalid arguments for command '" + getName() + "'"); 2241| 0| return false; 2242| 0| } 2243| 0| 2244| 0| args.clear(); 2245| 0| args.reserve(values.size()); 2246| 0| for (auto arg: values) { 2247| 0| args.emplace_back(ctx.getDelegate().getInternedString(arg)); 2248| 0| } 2249| 0| } else if (name == "deps") { 2250| 0| depsPaths.clear(); 2251| 0| depsPaths.insert(depsPaths.begin(), values.begin(), values.end()); 2252| 0| } else { 2253| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2254| 0| } 2255| 0| 2256| 0| return true; 2257| 0| } 2258| | 2259| | virtual bool configureAttribute( 2260| | const ConfigureContext& ctx, StringRef name, 2261| 0| ArrayRef> values) override { 2262| 0| if (name == "env") { 2263| 0| env.clear(); 2264| 0| env.reserve(values.size()); 2265| 0| for (const auto& entry: values) { 2266| 0| env.emplace_back( 2267| 0| std::make_pair( 2268| 0| ctx.getDelegate().getInternedString(entry.first), 2269| 0| ctx.getDelegate().getInternedString(entry.second))); 2270| 0| } 2271| 0| } else { 2272| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2273| 0| } 2274| 0| 2275| 0| return true; 2276| 0| } 2277| | 2278| | virtual void executeExternalCommand( 2279| | BuildSystemCommandInterface& bsci, 2280| | Task* task, 2281| | QueueJobContext* context, 2282| 0| llvm::Optional completionFn) override { 2283| 0| 2284| 0| // Execute the command. 2285| 0| bsci.getExecutionQueue().executeProcess( 2286| 0| context, args, env, 2287| 0| /*inheritEnvironment=*/inheritEnv, 2288| 0| {canSafelyInterrupt, workingDirectory, controlEnabled}, 2289| 0| /*completionFn=*/{[this, &bsci, task, completionFn](ProcessResult result) { 2290| 0| if (result.status != ProcessStatus::Succeeded) { 2291| 0| // If the command failed, there is no need to gather dependencies. 2292| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2293| 0| return; 2294| 0| } 2295| 0| 2296| 0| // Collect the discovered dependencies, if used. 2297| 0| if (!depsPaths.empty()) { 2298| 0| // FIXME: Really want this job to go into a high priority fifo queue 2299| 0| // so as to not hold up downstream tasks. 2300| 0| bsci.addJob({ this, [this, &bsci, task, completionFn, result](QueueJobContext* context) { 2301| 0| if (!processDiscoveredDependencies(bsci, task, context)) { 2302| 0| // If we were unable to process the dependencies output, report a 2303| 0| // failure. 2304| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 2305| 0| fn(ProcessStatus::Failed); 2306| 0| }); 2307| 0| return; 2308| 0| } 2309| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2310| 0| }}); 2311| 0| return; 2312| 0| } 2313| 0| 2314| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2315| 0| }}); 2316| 0| } 2317| |}; 2318| | 2319| |class ShellTool : public Tool { 2320| |private: 2321| | bool controlEnabled = true; 2322| | 2323| |public: 2324| | using Tool::Tool; 2325| | 2326| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2327| 0| StringRef value) override { 2328| 0| if (name == "control-enabled") { 2329| 0| if (value != "true" && value != "false") { 2330| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 2331| 0| name + "'"); 2332| 0| return false; 2333| 0| } 2334| 0| controlEnabled = (value == "true"); 2335| 0| } else { 2336| 0| ctx.error("unexpected attribute: '" + name + "'"); 2337| 0| return false; 2338| 0| } 2339| 0| return true; 2340| 0| } 2341| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2342| 0| ArrayRef values) override { 2343| 0| // No supported attributes. 2344| 0| ctx.error("unexpected attribute: '" + name + "'"); 2345| 0| return false; 2346| 0| } 2347| | virtual bool configureAttribute( 2348| | const ConfigureContext& ctx, StringRef name, 2349| 0| ArrayRef> values) override { 2350| 0| // No supported attributes. 2351| 0| ctx.error("unexpected attribute: '" + name + "'"); 2352| 0| return false; 2353| 0| } 2354| | 2355| 0| virtual std::unique_ptr createCommand(StringRef name) override { 2356| 0| return llvm::make_unique(name, controlEnabled); 2357| 0| } 2358| |}; 2359| | 2360| |#pragma mark - ClangTool implementation 2361| | 2362| |class ClangShellCommand : public ExternalCommand { 2363| | /// The compiler command to invoke. 2364| | std::vector args; 2365| | 2366| | /// The path to the dependency output file, if used. 2367| | std::string depsPath; 2368| | 2369| 0| virtual CommandSignature getSignature() override { 2370| 0| return ExternalCommand::getSignature() 2371| 0| .combine(args); 2372| 0| } 2373| | 2374| | bool processDiscoveredDependencies(BuildSystemCommandInterface& bsci, 2375| | Task* task, 2376| 0| QueueJobContext* context) { 2377| 0| // Read the dependencies file. 2378| 0| auto input = bsci.getFileSystem().getFileContents(depsPath); 2379| 0| if (!input) { 2380| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(this, 2381| 0| "unable to open dependencies file (" + depsPath + ")"); 2382| 0| return false; 2383| 0| } 2384| 0| 2385| 0| // Parse the output. 2386| 0| // 2387| 0| // We just ignore the rule, and add any dependency that we encounter in the 2388| 0| // file. 2389| 0| struct DepsActions : public core::MakefileDepsParser::ParseActions { 2390| 0| BuildSystemCommandInterface& bsci; 2391| 0| Task* task; 2392| 0| ClangShellCommand* command; 2393| 0| unsigned numErrors{0}; 2394| 0| 2395| 0| DepsActions(BuildSystemCommandInterface& bsci, Task* task, 2396| 0| ClangShellCommand* command) 2397| 0| : bsci(bsci), task(task), command(command) {} 2398| 0| 2399| 0| virtual void error(const char* message, uint64_t position) override { 2400| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(command, 2401| 0| "error reading dependency file '" + command->depsPath + 2402| 0| "': " + std::string(message)); 2403| 0| ++numErrors; 2404| 0| } 2405| 0| 2406| 0| virtual void actOnRuleDependency(const char* dependency, 2407| 0| uint64_t length, 2408| 0| const StringRef unescapedWord) override { 2409| 0| bsci.taskDiscoveredDependency(task, BuildKey::makeNode(unescapedWord)); 2410| 0| } 2411| 0| 2412| 0| virtual void actOnRuleStart(const char* name, uint64_t length, 2413| 0| const StringRef unescapedWord) override {} 2414| 0| 2415| 0| virtual void actOnRuleEnd() override {} 2416| 0| }; 2417| 0| 2418| 0| DepsActions actions(bsci, task, this); 2419| 0| core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(), 2420| 0| actions).parse(); 2421| 0| return actions.numErrors == 0; 2422| 0| } 2423| | 2424| |public: 2425| | using ExternalCommand::ExternalCommand; 2426| | 2427| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 2428| 0| llvm::raw_svector_ostream(result) << getDescription(); 2429| 0| } 2430| | 2431| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 2432| 0| llvm::raw_svector_ostream os(result); 2433| 0| bool first = true; 2434| 0| for (const auto& arg: args) { 2435| 0| if (!first) os << " "; 2436| 0| first = false; 2437| 0| basic::appendShellEscapedString(os, arg); 2438| 0| } 2439| 0| } 2440| | 2441| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2442| 0| StringRef value) override { 2443| 0| if (name == "args") { 2444| 0| // When provided as a scalar string, we default to executing using the 2445| 0| // shell. 2446| 0| args.clear(); 2447| 0| args.push_back(ctx.getDelegate().getInternedString("/bin/sh")); 2448| 0| args.push_back(ctx.getDelegate().getInternedString("-c")); 2449| 0| args.push_back(ctx.getDelegate().getInternedString(value)); 2450| 0| } else if (name == "deps") { 2451| 0| depsPath = value; 2452| 0| } else { 2453| 0| return ExternalCommand::configureAttribute(ctx, name, value); 2454| 0| } 2455| 0| 2456| 0| return true; 2457| 0| } 2458| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2459| 0| ArrayRef values) override { 2460| 0| if (name == "args") { 2461| 0| args.clear(); 2462| 0| args.reserve(values.size()); 2463| 0| for (auto arg: values) { 2464| 0| args.emplace_back(ctx.getDelegate().getInternedString(arg)); 2465| 0| } 2466| 0| } else { 2467| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2468| 0| } 2469| 0| 2470| 0| return true; 2471| 0| } 2472| | virtual bool configureAttribute( 2473| | const ConfigureContext& ctx, StringRef name, 2474| 0| ArrayRef> values) override { 2475| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2476| 0| } 2477| | 2478| | virtual void executeExternalCommand(BuildSystemCommandInterface& bsci, 2479| | Task* task, 2480| | QueueJobContext* context, 2481| 0| llvm::Optional completionFn) override { 2482| 0| // Execute the command. 2483| 0| bsci.getExecutionQueue().executeProcess(context, args, {}, true, {true}, {[this, &bsci, task, completionFn](ProcessResult result){ 2484| 0| 2485| 0| if (result.status != ProcessStatus::Succeeded) { 2486| 0| // If the command failed, there is no need to gather dependencies. 2487| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2488| 0| return; 2489| 0| } 2490| 0| 2491| 0| // Otherwise, collect the discovered dependencies, if used. 2492| 0| if (!depsPath.empty()) { 2493| 0| // FIXME: Really want this job to go into a high priority fifo queue 2494| 0| // so as to not hold up downstream tasks. 2495| 0| bsci.addJob({ this, [this, &bsci, task, completionFn, result](QueueJobContext* context) { 2496| 0| if (!processDiscoveredDependencies(bsci, task, context)) { 2497| 0| // If we were unable to process the dependencies output, report a 2498| 0| // failure. 2499| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 2500| 0| fn(ProcessStatus::Failed); 2501| 0| }); 2502| 0| return; 2503| 0| } 2504| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2505| 0| }}); 2506| 0| return; 2507| 0| } 2508| 0| 2509| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 2510| 0| }}); 2511| 0| } 2512| |}; 2513| | 2514| |class ClangTool : public Tool { 2515| |public: 2516| | using Tool::Tool; 2517| | 2518| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2519| 0| StringRef value) override { 2520| 0| // No supported attributes. 2521| 0| ctx.error("unexpected attribute: '" + name + "'"); 2522| 0| return false; 2523| 0| } 2524| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2525| 0| ArrayRef values) override { 2526| 0| // No supported attributes. 2527| 0| ctx.error("unexpected attribute: '" + name + "'"); 2528| 0| return false; 2529| 0| } 2530| | virtual bool configureAttribute( 2531| | const ConfigureContext& ctx, StringRef name, 2532| 0| ArrayRef> values) override { 2533| 0| // No supported attributes. 2534| 0| ctx.error("unexpected attribute: '" + name + "'"); 2535| 0| return false; 2536| 0| } 2537| | 2538| 0| virtual std::unique_ptr createCommand(StringRef name) override { 2539| 0| return llvm::make_unique(name); 2540| 0| } 2541| |}; 2542| | 2543| |#pragma mark - SwiftCompilerTool implementation 2544| | 2545| |class SwiftGetVersionCommand : public Command { 2546| | std::string executable; 2547| | 2548| |public: 2549| | SwiftGetVersionCommand(const BuildKey& key) 2550| 0| : Command("swift-get-version"), executable(key.getCustomTaskData()) { 2551| 0| } 2552| | 2553| | // FIXME: Should create a CustomCommand class, to avoid all the boilerplate 2554| | // required implementations. 2555| | 2556| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 2557| 0| llvm::raw_svector_ostream(result) << "Checking Swift Compiler Version"; 2558| 0| } 2559| | 2560| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 2561| 0| llvm::raw_svector_ostream(result) << '"' << executable << '"' 2562| 0| << " --version"; 2563| 0| } 2564| | 2565| | virtual void configureDescription(const ConfigureContext&, 2566| 0| StringRef value) override { } 2567| | virtual void configureInputs(const ConfigureContext&, 2568| 0| const std::vector& value) override { } 2569| | virtual void configureOutputs(const ConfigureContext&, 2570| 0| const std::vector& value) override { } 2571| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2572| 0| StringRef value) override { 2573| 0| // No supported attributes. 2574| 0| ctx.error("unexpected attribute: '" + name + "'"); 2575| 0| return false; 2576| 0| } 2577| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2578| 0| ArrayRef values) override { 2579| 0| // No supported attributes. 2580| 0| ctx.error("unexpected attribute: '" + name + "'"); 2581| 0| return false; 2582| 0| } 2583| | virtual bool configureAttribute( 2584| | const ConfigureContext& ctx, StringRef name, 2585| 0| ArrayRef> values) override { 2586| 0| // No supported attributes. 2587| 0| ctx.error("unexpected attribute: '" + name + "'"); 2588| 0| return false; 2589| 0| } 2590| | virtual BuildValue getResultForOutput(Node* node, 2591| 0| const BuildValue& value) override { 2592| 0| // This method should never be called on a custom command. 2593| 0| llvm_unreachable("unexpected"); 2594| 0| return BuildValue::makeInvalid(); 2595| 0| } 2596| | 2597| 0| virtual bool isResultValid(BuildSystem&, const BuildValue& value) override { 2598| 0| // Always rebuild this task. 2599| 0| return false; 2600| 0| } 2601| | 2602| | virtual void start(BuildSystemCommandInterface& bsci, 2603| 0| core::Task* task) override { } 2604| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 2605| 0| const BuildValue&) override { } 2606| | virtual void provideValue(BuildSystemCommandInterface& bsci, core::Task*, 2607| | uintptr_t inputID, 2608| 0| const BuildValue& value) override { } 2609| | 2610| | virtual void execute(BuildSystemCommandInterface& bsci, 2611| | core::Task* task, 2612| | QueueJobContext* context, 2613| 0| ResultFn resultFn) override { 2614| 0| // Construct the command line used to query the swift compiler version. 2615| 0| // 2616| 0| // FIXME: Need a decent subprocess interface. 2617| 0| SmallString<256> command; 2618| 0| llvm::raw_svector_ostream commandOS(command); 2619| 0| commandOS << basic::shellEscaped(executable); 2620| 0| commandOS << " " << "--version"; 2621| 0| 2622| 0| // Read the result. 2623| 0| FILE *fp = basic::sys::popen(commandOS.str().str().c_str(), "r"); 2624| 0| SmallString<4096> result; 2625| 0| if (fp) { 2626| 0| char buf[4096]; 2627| 0| for (;;) { 2628| 0| ssize_t numRead = fread(buf, 1, sizeof(buf), fp); 2629| 0| if (numRead == 0) { 2630| 0| // FIXME: Error handling. 2631| 0| break; 2632| 0| } 2633| 0| result.append(StringRef(buf, numRead)); 2634| 0| } 2635| 0| basic::sys::pclose(fp); 2636| 0| } 2637| 0| 2638| 0| // For now, we can get away with just encoding this as a successful 2639| 0| // command and relying on the signature to detect changes. 2640| 0| // 2641| 0| // FIXME: We should support BuildValues with arbitrary payloads. 2642| 0| resultFn(BuildValue::makeSuccessfulCommand( 2643| 0| basic::FileInfo{}, CommandSignature(result))); 2644| 0| } 2645| |}; 2646| | 2647| |class SwiftCompilerShellCommand : public ExternalCommand { 2648| | /// The compiler command to invoke. 2649| | std::string executable = "swiftc"; 2650| | 2651| | /// The name of the module. 2652| | std::string moduleName; 2653| | 2654| | /// The path of the output module. 2655| | std::string moduleOutputPath; 2656| | 2657| | /// The list of sources (combined). 2658| | std::vector sourcesList; 2659| | 2660| | /// The list of objects (combined). 2661| | std::vector objectsList; 2662| | 2663| | /// The list of import paths (combined). 2664| | std::vector importPaths; 2665| | 2666| | /// The directory in which to store temporary files. 2667| | std::string tempsPath; 2668| | 2669| | /// Additional arguments, as a string. 2670| | std::vector otherArgs; 2671| | 2672| | /// Whether the sources are part of a library or not. 2673| | bool isLibrary = false; 2674| | 2675| | /// Whether to enable -whole-module-optimization. 2676| | bool enableWholeModuleOptimization = false; 2677| | 2678| | /// Enables multi-threading with the thread count if > 0. 2679| | /// 2680| | /// Note: This is only used when whole module optimization is enabled. 2681| | std::string numThreads = "0"; 2682| | 2683| 0| virtual CommandSignature getSignature() override { 2684| 0| return ExternalCommand::getSignature() 2685| 0| .combine(executable) 2686| 0| .combine(moduleName) 2687| 0| .combine(moduleOutputPath) 2688| 0| .combine(sourcesList) 2689| 0| .combine(objectsList) 2690| 0| .combine(importPaths) 2691| 0| .combine(tempsPath) 2692| 0| .combine(otherArgs) 2693| 0| .combine(isLibrary); 2694| 0| } 2695| | 2696| | /// Get the path to use for the output file map. 2697| 0| void getOutputFileMapPath(SmallVectorImpl& result) const { 2698| 0| llvm::sys::path::append(result, tempsPath, "output-file-map.json"); 2699| 0| } 2700| | 2701| | /// Compute the complete set of command line arguments to invoke swift with. 2702| | void constructCommandLineArgs(StringRef outputFileMapPath, 2703| 0| std::vector& result) const { 2704| 0| result.push_back(executable); 2705| 0| result.push_back("-module-name"); 2706| 0| result.push_back(moduleName); 2707| 0| result.push_back("-incremental"); 2708| 0| result.push_back("-emit-dependencies"); 2709| 0| if (!moduleOutputPath.empty()) { 2710| 0| result.push_back("-emit-module"); 2711| 0| result.push_back("-emit-module-path"); 2712| 0| result.push_back(moduleOutputPath); 2713| 0| } 2714| 0| result.push_back("-output-file-map"); 2715| 0| result.push_back(outputFileMapPath); 2716| 0| if (isLibrary) { 2717| 0| result.push_back("-parse-as-library"); 2718| 0| } 2719| 0| if (enableWholeModuleOptimization) { 2720| 0| result.push_back("-whole-module-optimization"); 2721| 0| result.push_back("-num-threads"); 2722| 0| result.push_back(numThreads); 2723| 0| } 2724| 0| result.push_back("-c"); 2725| 0| for (const auto& source: sourcesList) { 2726| 0| result.push_back(source); 2727| 0| } 2728| 0| for (const auto& import: importPaths) { 2729| 0| result.push_back("-I"); 2730| 0| result.push_back(import); 2731| 0| } 2732| 0| for (const auto& arg: otherArgs) { 2733| 0| result.push_back(arg); 2734| 0| } 2735| 0| } 2736| | 2737| |public: 2738| | using ExternalCommand::ExternalCommand; 2739| | 2740| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 2741| 0| llvm::raw_svector_ostream(result) 2742| 0| << "Compiling Swift Module '" << moduleName 2743| 0| << "' (" << sourcesList.size() << " sources)"; 2744| 0| } 2745| | 2746| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 2747| 0| SmallString<64> outputFileMapPath; 2748| 0| getOutputFileMapPath(outputFileMapPath); 2749| 0| 2750| 0| std::vector commandLine; 2751| 0| constructCommandLineArgs(outputFileMapPath, commandLine); 2752| 0| 2753| 0| llvm::raw_svector_ostream os(result); 2754| 0| bool first = true; 2755| 0| for (const auto& arg: commandLine) { 2756| 0| if (!first) os << " "; 2757| 0| first = false; 2758| 0| // FIXME: This isn't correct, we need utilities for doing shell quoting. 2759| 0| if (arg.find(' ') != StringRef::npos) { 2760| 0| os << '"' << arg << '"'; 2761| 0| } else { 2762| 0| os << arg; 2763| 0| } 2764| 0| } 2765| 0| } 2766| | 2767| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2768| 0| StringRef value) override { 2769| 0| if (name == "executable") { 2770| 0| executable = value; 2771| 0| } else if (name == "module-name") { 2772| 0| moduleName = value; 2773| 0| } else if (name == "module-output-path") { 2774| 0| moduleOutputPath = value; 2775| 0| } else if (name == "sources") { 2776| 0| SmallVector sources; 2777| 0| StringRef(value).split(sources, " ", /*MaxSplit=*/-1, 2778| 0| /*KeepEmpty=*/false); 2779| 0| sourcesList = std::vector(sources.begin(), sources.end()); 2780| 0| } else if (name == "objects") { 2781| 0| SmallVector objects; 2782| 0| StringRef(value).split(objects, " ", /*MaxSplit=*/-1, 2783| 0| /*KeepEmpty=*/false); 2784| 0| objectsList = std::vector(objects.begin(), objects.end()); 2785| 0| } else if (name == "import-paths") { 2786| 0| SmallVector imports; 2787| 0| StringRef(value).split(imports, " ", /*MaxSplit=*/-1, 2788| 0| /*KeepEmpty=*/false); 2789| 0| importPaths = std::vector(imports.begin(), imports.end()); 2790| 0| } else if (name == "temps-path") { 2791| 0| tempsPath = value; 2792| 0| } else if (name == "is-library") { 2793| 0| if (!configureBool(ctx, isLibrary, name, value)) 2794| 0| return false; 2795| 0| } else if (name == "enable-whole-module-optimization") { 2796| 0| if (!configureBool(ctx, enableWholeModuleOptimization, name, value)) 2797| 0| return false; 2798| 0| } else if (name == "num-threads") { 2799| 0| int numThreadsInt = 0; 2800| 0| if (value.getAsInteger(10, numThreadsInt)) { 2801| 0| ctx.error("'" + name + "' should be an int."); 2802| 0| return false; 2803| 0| } 2804| 0| if (numThreadsInt < 0) { 2805| 0| ctx.error("'" + name + "' should be greater than or equal to zero."); 2806| 0| return false; 2807| 0| } 2808| 0| numThreads = value; 2809| 0| } else if (name == "other-args") { 2810| 0| SmallVector args; 2811| 0| StringRef(value).split(args, " ", /*MaxSplit=*/-1, 2812| 0| /*KeepEmpty=*/false); 2813| 0| otherArgs = std::vector(args.begin(), args.end()); 2814| 0| } else { 2815| 0| return ExternalCommand::configureAttribute(ctx, name, value); 2816| 0| } 2817| 0| 2818| 0| return true; 2819| 0| } 2820| | 2821| | // Extracts and stores the bool value of an attribute inside "to" variable. 2822| | // Returns true on success and false on error. 2823| 0| bool configureBool(const ConfigureContext& ctx, bool& to, StringRef name, StringRef value) { 2824| 0| if (value != "true" && value != "false") { 2825| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 2826| 0| name + "'"); 2827| 0| return false; 2828| 0| } 2829| 0| to = value == "true"; 2830| 0| return true; 2831| 0| } 2832| | 2833| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 2834| 0| ArrayRef values) override { 2835| 0| if (name == "sources") { 2836| 0| sourcesList = std::vector(values.begin(), values.end()); 2837| 0| } else if (name == "objects") { 2838| 0| objectsList = std::vector(values.begin(), values.end()); 2839| 0| } else if (name == "import-paths") { 2840| 0| importPaths = std::vector(values.begin(), values.end()); 2841| 0| } else if (name == "other-args") { 2842| 0| otherArgs = std::vector(values.begin(), values.end()); 2843| 0| } else { 2844| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2845| 0| } 2846| 0| 2847| 0| return true; 2848| 0| } 2849| | 2850| | virtual bool configureAttribute( 2851| | const ConfigureContext& ctx, StringRef name, 2852| 0| ArrayRef> values) override { 2853| 0| return ExternalCommand::configureAttribute(ctx, name, values); 2854| 0| } 2855| | 2856| | bool writeOutputFileMap(BuildSystemCommandInterface& bsci, 2857| | StringRef outputFileMapPath, 2858| 0| std::vector& depsFiles_out) const { 2859| 0| // FIXME: We need to properly escape everything we write here. 2860| 0| assert(sourcesList.size() == objectsList.size()); 2861| 0| 2862| 0| SmallString<16> data; 2863| 0| std::error_code ec; 2864| 0| llvm::raw_fd_ostream os(outputFileMapPath, ec, 2865| 0| llvm::sys::fs::OpenFlags::F_Text); 2866| 0| if (ec) { 2867| 0| bsci.getDelegate().commandHadError((Command*)this, 2868| 0| "unable to create output file map: '" + outputFileMapPath.str() + "'"); 2869| 0| return false; 2870| 0| } 2871| 0| 2872| 0| os << "{\n"; 2873| 0| 2874| 0| // Write the master file dependencies entry. 2875| 0| SmallString<16> masterDepsPath; 2876| 0| llvm::sys::path::append(masterDepsPath, tempsPath, "master.swiftdeps"); 2877| 0| os << " \"\": {\n"; 2878| 0| if (enableWholeModuleOptimization) { 2879| 0| SmallString<16> depsPath; 2880| 0| llvm::sys::path::append(depsPath, tempsPath, moduleName + ".d"); 2881| 0| depsFiles_out.push_back(depsPath.str()); 2882| 0| SmallString<16> object; 2883| 0| llvm::sys::path::append(object, tempsPath, moduleName + ".o"); 2884| 0| os << " \"dependencies\": \"" << depsPath << "\",\n"; 2885| 0| os << " \"object\": \"" << object << "\",\n"; 2886| 0| } 2887| 0| os << " \"swift-dependencies\": \"" << masterDepsPath << "\"\n"; 2888| 0| os << " },\n"; 2889| 0| 2890| 0| // Write out the entries for each source file. 2891| 0| for (unsigned i = 0; i != sourcesList.size(); ++i) { 2892| 0| auto source = sourcesList[i]; 2893| 0| auto object = objectsList[i]; 2894| 0| auto objectDir = llvm::sys::path::parent_path(object); 2895| 0| auto sourceStem = llvm::sys::path::stem(source); 2896| 0| SmallString<16> partialModulePath; 2897| 0| llvm::sys::path::append(partialModulePath, objectDir, 2898| 0| sourceStem + "~partial.swiftmodule"); 2899| 0| SmallString<16> swiftDepsPath; 2900| 0| llvm::sys::path::append(swiftDepsPath, objectDir, 2901| 0| sourceStem + ".swiftdeps"); 2902| 0| 2903| 0| os << " \"" << source << "\": {\n"; 2904| 0| if (!enableWholeModuleOptimization) { 2905| 0| SmallString<16> depsPath; 2906| 0| llvm::sys::path::append(depsPath, objectDir, sourceStem + ".d"); 2907| 0| os << " \"dependencies\": \"" << depsPath << "\",\n"; 2908| 0| depsFiles_out.push_back(depsPath.str()); 2909| 0| } 2910| 0| os << " \"object\": \"" << object << "\",\n"; 2911| 0| os << " \"swiftmodule\": \"" << partialModulePath << "\",\n"; 2912| 0| os << " \"swift-dependencies\": \"" << swiftDepsPath << "\"\n"; 2913| 0| os << " }" << ((i + 1) < sourcesList.size() ? "," : "") << "\n"; 2914| 0| } 2915| 0| 2916| 0| os << "}\n"; 2917| 0| 2918| 0| os.close(); 2919| 0| 2920| 0| return true; 2921| 0| } 2922| | 2923| | bool processDiscoveredDependencies(BuildSystemCommandInterface& bsci, 2924| 0| core::Task* task, StringRef depsPath) { 2925| 0| // Read the dependencies file. 2926| 0| auto input = bsci.getFileSystem().getFileContents(depsPath); 2927| 0| if (!input) { 2928| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(this, 2929| 0| "unable to open dependencies file (" + depsPath.str() + ")"); 2930| 0| return false; 2931| 0| } 2932| 0| 2933| 0| // Parse the output. 2934| 0| // 2935| 0| // We just ignore the rule, and add any dependency that we encounter in the 2936| 0| // file. 2937| 0| struct DepsActions : public core::MakefileDepsParser::ParseActions { 2938| 0| BuildSystemCommandInterface& bsci; 2939| 0| core::Task* task; 2940| 0| StringRef depsPath; 2941| 0| Command* command; 2942| 0| unsigned numErrors{0}; 2943| 0| unsigned ruleNumber{0}; 2944| 0| 2945| 0| DepsActions(BuildSystemCommandInterface& bsci, core::Task* task, 2946| 0| StringRef depsPath, Command* command) 2947| 0| : bsci(bsci), task(task), depsPath(depsPath) {} 2948| 0| 2949| 0| virtual void error(const char* message, uint64_t position) override { 2950| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(command, 2951| 0| "error reading dependency file '" + depsPath.str() + 2952| 0| "': " + std::string(message)); 2953| 0| ++numErrors; 2954| 0| } 2955| 0| 2956| 0| virtual void actOnRuleDependency(const char* dependency, 2957| 0| uint64_t length, 2958| 0| const StringRef unescapedWord) override { 2959| 0| // Only process dependencies for the first rule (the output file), the 2960| 0| // rest are identical. 2961| 0| if (ruleNumber == 0) { 2962| 0| bsci.taskDiscoveredDependency( 2963| 0| task, BuildKey::makeNode(unescapedWord)); 2964| 0| } 2965| 0| } 2966| 0| 2967| 0| virtual void actOnRuleStart(const char* name, uint64_t length, 2968| 0| const StringRef unescapedWord) override {} 2969| 0| 2970| 0| virtual void actOnRuleEnd() override { 2971| 0| ++ruleNumber; 2972| 0| } 2973| 0| }; 2974| 0| 2975| 0| DepsActions actions(bsci, task, depsPath, this); 2976| 0| core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(), 2977| 0| actions).parse(); 2978| 0| return actions.numErrors == 0; 2979| 0| } 2980| | 2981| | /// Overridden start to also introduce a dependency on the Swift compiler 2982| | /// version. 2983| | virtual void start(BuildSystemCommandInterface& bsci, 2984| 0| core::Task* task) override { 2985| 0| ExternalCommand::start(bsci, task); 2986| 0| 2987| 0| // The Swift compiler version is also an input. 2988| 0| // 2989| 0| // FIXME: We need to fix the input ID situation, this is not extensible. We 2990| 0| // either have to build a registration of the custom tasks so they can divy 2991| 0| // up the input ID namespace, or we should just use the keys. Probably move 2992| 0| // to just using the keys, unless there is a place where that is really not 2993| 0| // cheap. 2994| 0| auto getVersionKey = BuildKey::makeCustomTask( 2995| 0| "swift-get-version", executable); 2996| 0| bsci.taskNeedsInput(task, getVersionKey, 2997| 0| core::BuildEngine::kMaximumInputID - 1); 2998| 0| } 2999| | 3000| | /// Overridden to access the Swift compiler version. 3001| | virtual void provideValue(BuildSystemCommandInterface& bsci, 3002| | core::Task* task, 3003| | uintptr_t inputID, 3004| 0| const BuildValue& value) override { 3005| 0| // We can ignore the 'swift-get-version' input, it is just used to detect 3006| 0| // that we need to rebuild. 3007| 0| if (inputID == core::BuildEngine::kMaximumInputID - 1) { 3008| 0| return; 3009| 0| } 3010| 0| 3011| 0| ExternalCommand::provideValue(bsci, task, inputID, value); 3012| 0| } 3013| | 3014| | virtual void executeExternalCommand( 3015| | BuildSystemCommandInterface& bsci, 3016| | core::Task* task, 3017| | QueueJobContext* context, 3018| 0| llvm::Optional completionFn) override { 3019| 0| // FIXME: Need to add support for required parameters. 3020| 0| if (sourcesList.empty()) { 3021| 0| bsci.getDelegate().error("", {}, "no configured 'sources'"); 3022| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3023| 0| fn(ProcessStatus::Failed); 3024| 0| }); 3025| 0| return; 3026| 0| } 3027| 0| if (objectsList.empty()) { 3028| 0| bsci.getDelegate().error("", {}, "no configured 'objects'"); 3029| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3030| 0| fn(ProcessStatus::Failed); 3031| 0| }); 3032| 0| return; 3033| 0| } 3034| 0| if (moduleName.empty()) { 3035| 0| bsci.getDelegate().error("", {}, "no configured 'module-name'"); 3036| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3037| 0| fn(ProcessStatus::Failed); 3038| 0| }); 3039| 0| return; 3040| 0| } 3041| 0| if (tempsPath.empty()) { 3042| 0| bsci.getDelegate().error("", {}, "no configured 'temps-path'"); 3043| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3044| 0| fn(ProcessStatus::Failed); 3045| 0| }); 3046| 0| return; 3047| 0| } 3048| 0| 3049| 0| if (sourcesList.size() != objectsList.size()) { 3050| 0| bsci.getDelegate().error( 3051| 0| "", {}, "'sources' and 'objects' are not the same size"); 3052| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3053| 0| fn(ProcessStatus::Failed); 3054| 0| }); 3055| 0| return; 3056| 0| } 3057| 0| 3058| 0| // Ensure the temporary directory exists. 3059| 0| // 3060| 0| // We ignore failures here, and just let things that depend on this fail. 3061| 0| // 3062| 0| // FIXME: This should really be done using an additional implicit input, so 3063| 0| // it only happens once per build. 3064| 0| (void) bsci.getFileSystem().createDirectories(tempsPath); 3065| 0| 3066| 0| SmallString<64> outputFileMapPath; 3067| 0| getOutputFileMapPath(outputFileMapPath); 3068| 0| 3069| 0| // Form the complete command. 3070| 0| std::vector commandLine; 3071| 0| constructCommandLineArgs(outputFileMapPath, commandLine); 3072| 0| 3073| 0| // Write the output file map. 3074| 0| std::vector depsFiles; 3075| 0| if (!writeOutputFileMap(bsci, outputFileMapPath, depsFiles)) { 3076| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3077| 0| fn(ProcessStatus::Failed); 3078| 0| }); 3079| 0| return; 3080| 0| } 3081| 0| 3082| 0| // Execute the command. 3083| 0| auto result = bsci.getExecutionQueue().executeProcess(context, commandLine); 3084| 0| 3085| 0| if (result != ProcessStatus::Succeeded) { 3086| 0| // If the command failed, there is no need to gather dependencies. 3087| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 3088| 0| return; 3089| 0| } 3090| 0| 3091| 0| // Load all of the discovered dependencies. 3092| 0| // FIXME: Really want this job to go into a high priority fifo queue 3093| 0| // so as to not hold up downstream tasks. 3094| 0| bsci.addJob({ this, [this, &bsci, task, completionFn, result, depsFiles](QueueJobContext* context) { 3095| 0| for (const auto& depsPath: depsFiles) { 3096| 0| if (!processDiscoveredDependencies(bsci, task, depsPath)) { 3097| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3098| 0| fn(ProcessStatus::Failed); 3099| 0| }); 3100| 0| return; 3101| 0| } 3102| 0| } 3103| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 3104| 0| }}); 3105| 0| } 3106| |}; 3107| | 3108| |class SwiftCompilerTool : public Tool { 3109| |public: 3110| 0| SwiftCompilerTool(StringRef name) : Tool(name) {} 3111| | 3112| | virtual bool configureAttribute( 3113| 0| const ConfigureContext& ctx, StringRef name, StringRef value) override { 3114| 0| // No supported attributes. 3115| 0| ctx.error("unexpected attribute: '" + name + "'"); 3116| 0| return false; 3117| 0| } 3118| | 3119| | virtual bool configureAttribute( 3120| | const ConfigureContext& ctx, StringRef name, 3121| 0| ArrayRef values) override { 3122| 0| // No supported attributes. 3123| 0| ctx.error("unexpected attribute: '" + name + "'"); 3124| 0| return false; 3125| 0| } 3126| | 3127| | virtual bool configureAttribute( 3128| | const ConfigureContext& ctx, StringRef name, 3129| 0| ArrayRef> values) override { 3130| 0| // No supported attributes. 3131| 0| ctx.error("unexpected attribute: '" + name + "'"); 3132| 0| return false; 3133| 0| } 3134| | 3135| 0| virtual std::unique_ptr createCommand(StringRef name) override { 3136| 0| return llvm::make_unique(name); 3137| 0| } 3138| | 3139| | virtual std::unique_ptr createCustomCommand( 3140| 0| const BuildKey& key) override { 3141| 0| if (key.getCustomTaskName() == "swift-get-version" ) { 3142| 0| return llvm::make_unique(key); 3143| 0| } 3144| 0| 3145| 0| return nullptr; 3146| 0| } 3147| |}; 3148| | 3149| | 3150| |#pragma mark - MkdirTool implementation 3151| | 3152| |class MkdirCommand : public ExternalCommand { 3153| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 3154| 0| llvm::raw_svector_ostream(result) << getDescription(); 3155| 0| } 3156| | 3157| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 3158| 0| llvm::raw_svector_ostream os(result); 3159| 0| os << "mkdir -p "; 3160| 0| // FIXME: This isn't correct, we need utilities for doing shell quoting. 3161| 0| if (StringRef(getOutputs()[0]->getName()).find(' ') != StringRef::npos) { 3162| 0| os << '"' << getOutputs()[0]->getName() << '"'; 3163| 0| } else { 3164| 0| os << getOutputs()[0]->getName(); 3165| 0| } 3166| 0| } 3167| | 3168| | virtual bool isResultValid(BuildSystem& system, 3169| 0| const BuildValue& value) override { 3170| 0| // If the prior value wasn't for a successful command, recompute. 3171| 0| if (!value.isSuccessfulCommand()) 3172| 0| return false; 3173| 0| 3174| 0| // Otherwise, the result is valid if the directory still exists. 3175| 0| auto info = getOutputs()[0]->getFileInfo( 3176| 0| system.getFileSystem()); 3177| 0| if (info.isMissing()) 3178| 0| return false; 3179| 0| 3180| 0| // If the item is not a directory, it needs to be recreated. 3181| 0| if (!info.isDirectory()) 3182| 0| return false; 3183| 0| 3184| 0| // FIXME: We should strictly enforce the integrity of this validity routine 3185| 0| // by ensuring that the build result for this command does not fully encode 3186| 0| // the file info, but rather just encodes its success. As is, we are leaking 3187| 0| // out the details of the file info (like the timestamp), but not rerunning 3188| 0| // when they change. This is by design for this command, but it would still 3189| 0| // be nice to be strict about it. 3190| 0| 3191| 0| return true; 3192| 0| } 3193| | 3194| | virtual void executeExternalCommand( 3195| | BuildSystemCommandInterface& bsci, 3196| | Task* task, 3197| | QueueJobContext* context, 3198| 0| llvm::Optional completionFn) override { 3199| 0| auto output = getOutputs()[0]; 3200| 0| if (!bsci.getFileSystem().createDirectories( 3201| 0| output->getName())) { 3202| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(this, 3203| 0| "unable to create directory '" + output->getName().str() + "'"); 3204| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3205| 0| fn(ProcessStatus::Failed); 3206| 0| }); 3207| 0| return; 3208| 0| } 3209| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3210| 0| fn(ProcessStatus::Succeeded); 3211| 0| }); 3212| 0| } 3213| | 3214| |public: 3215| | using ExternalCommand::ExternalCommand; 3216| |}; 3217| | 3218| |class MkdirTool : public Tool { 3219| |public: 3220| | using Tool::Tool; 3221| | 3222| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3223| 0| StringRef value) override { 3224| 0| // No supported attributes. 3225| 0| ctx.error("unexpected attribute: '" + name + "'"); 3226| 0| return false; 3227| 0| } 3228| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3229| 0| ArrayRef values) override { 3230| 0| // No supported attributes. 3231| 0| ctx.error("unexpected attribute: '" + name + "'"); 3232| 0| return false; 3233| 0| } 3234| | virtual bool configureAttribute( 3235| | const ConfigureContext& ctx, StringRef name, 3236| 0| ArrayRef> values) override { 3237| 0| // No supported attributes. 3238| 0| ctx.error("unexpected attribute: '" + name + "'"); 3239| 0| return false; 3240| 0| } 3241| | 3242| 0| virtual std::unique_ptr createCommand(StringRef name) override { 3243| 0| return llvm::make_unique(name); 3244| 0| } 3245| |}; 3246| | 3247| |#pragma mark - SymlinkTool implementation 3248| | 3249| |class SymlinkCommand : public Command { 3250| | /// The declared output node. 3251| | BuildNode* output = nullptr; 3252| | 3253| | /// The path of the actual symbolic link to create, if different from the 3254| | /// output node. 3255| | std::string linkOutputPath; 3256| | 3257| | /// The command description. 3258| | std::string description; 3259| | 3260| | /// Declared command inputs, used only for ordering purposes. 3261| | std::vector inputs; 3262| | 3263| | /// The contents to write at the output path. 3264| | std::string contents; 3265| | 3266| | /// Get the destination path. 3267| 0| StringRef getActualOutputPath() const { 3268| 0| return linkOutputPath.empty() ? output->getName() : 3269| 0| StringRef(linkOutputPath); 3270| 0| } 3271| | 3272| 0| virtual CommandSignature getSignature() { 3273| 0| CommandSignature code(output->getName()); 3274| 0| code = code.combine(contents); 3275| 0| for (const auto* input: inputs) { 3276| 0| code = code.combine(input->getName()); 3277| 0| } 3278| 0| return code; 3279| 0| } 3280| | 3281| | virtual void configureDescription(const ConfigureContext&, 3282| 0| StringRef value) override { 3283| 0| description = value; 3284| 0| } 3285| | 3286| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 3287| 0| llvm::raw_svector_ostream(result) << description; 3288| 0| } 3289| | 3290| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 3291| 0| llvm::raw_svector_ostream os(result); 3292| 0| os << "ln -sfh "; 3293| 0| StringRef outputPath = getActualOutputPath(); 3294| 0| if (!output || !outputPath.empty()) { 3295| 0| // FIXME: This isn't correct, we need utilities for doing shell quoting. 3296| 0| if (outputPath.find(' ') != StringRef::npos) { 3297| 0| os << '"' << outputPath << '"'; 3298| 0| } else { 3299| 0| os << outputPath; 3300| 0| } 3301| 0| } else { 3302| 0| os << "<<>>"; 3303| 0| } 3304| 0| os << ' '; 3305| 0| // FIXME: This isn't correct, we need utilities for doing shell quoting. 3306| 0| if (StringRef(contents).find(' ') != StringRef::npos) { 3307| 0| os << '"' << contents << '"'; 3308| 0| } else { 3309| 0| os << contents; 3310| 0| } 3311| 0| } 3312| | 3313| | virtual void configureInputs(const ConfigureContext& ctx, 3314| 0| const std::vector& value) override { 3315| 0| inputs.reserve(value.size()); 3316| 0| for (auto* node: value) { 3317| 0| inputs.emplace_back(static_cast(node)); 3318| 0| } 3319| 0| } 3320| | 3321| | virtual void configureOutputs(const ConfigureContext& ctx, 3322| 0| const std::vector& value) override { 3323| 0| if (value.size() == 1) { 3324| 0| output = static_cast(value[0]); 3325| 0| } else if (value.empty()) { 3326| 0| ctx.error("missing declared output"); 3327| 0| } else { 3328| 0| ctx.error("unexpected explicit output: '" + value[1]->getName() + "'"); 3329| 0| } 3330| 0| } 3331| | 3332| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3333| 0| StringRef value) override { 3334| 0| if (name == "contents") { 3335| 0| contents = value; 3336| 0| return true; 3337| 0| } else if (name == "link-output-path") { 3338| 0| linkOutputPath = value; 3339| 0| return true; 3340| 0| } else { 3341| 0| ctx.error("unexpected attribute: '" + name + "'"); 3342| 0| return false; 3343| 0| } 3344| 0| } 3345| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3346| 0| ArrayRef values) override { 3347| 0| // No supported attributes. 3348| 0| ctx.error("unexpected attribute: '" + name + "'"); 3349| 0| return false; 3350| 0| } 3351| | virtual bool configureAttribute( 3352| | const ConfigureContext& ctx, StringRef name, 3353| 0| ArrayRef> values) override { 3354| 0| // No supported attributes. 3355| 0| ctx.error("unexpected attribute: '" + name + "'"); 3356| 0| return false; 3357| 0| } 3358| | 3359| | virtual BuildValue getResultForOutput(Node* node, 3360| 0| const BuildValue& value) override { 3361| 0| // If the value was a failed command, propagate the failure. 3362| 0| if (value.isFailedCommand() || value.isPropagatedFailureCommand() || 3363| 0| value.isCancelledCommand()) 3364| 0| return BuildValue::makeFailedInput(); 3365| 0| if (value.isSkippedCommand()) 3366| 0| return BuildValue::makeSkippedCommand(); 3367| 0| 3368| 0| // Otherwise, we should have a successful command -- return the actual 3369| 0| // result for the output. 3370| 0| assert(value.isSuccessfulCommand()); 3371| 0| 3372| 0| auto info = value.getOutputInfo(); 3373| 0| if (info.isMissing()) 3374| 0| return BuildValue::makeMissingOutput(); 3375| 0| return BuildValue::makeExistingInput(info); 3376| 0| } 3377| | 3378| | virtual bool isResultValid(BuildSystem& system, 3379| 0| const BuildValue& value) override { 3380| 0| // It is an error if this command isn't configured properly. 3381| 0| StringRef outputPath = getActualOutputPath(); 3382| 0| if (!output || outputPath.empty()) 3383| 0| return false; 3384| 0| 3385| 0| // If the prior value wasn't for a successful command, recompute. 3386| 0| if (!value.isSuccessfulCommand()) 3387| 0| return false; 3388| 0| 3389| 0| // If the command's signature has changed since it was built, rebuild. 3390| 0| if (value.getCommandSignature() != getSignature()) 3391| 0| return false; 3392| 0| 3393| 0| // If the prior command doesn't look like one for a link, recompute. 3394| 0| if (value.getNumOutputs() != 1) 3395| 0| return false; 3396| 0| 3397| 0| // Otherwise, assume the result is valid if its link status matches the 3398| 0| // previous one. 3399| 0| auto info = system.getFileSystem().getLinkInfo(outputPath); 3400| 0| if (info.isMissing()) 3401| 0| return false; 3402| 0| 3403| 0| return info == value.getOutputInfo(); 3404| 0| } 3405| | 3406| | virtual void start(BuildSystemCommandInterface& bsci, 3407| 0| core::Task* task) override { 3408| 0| // The command itself takes no inputs, so just treat any declared inputs as 3409| 0| // "must follow" directives. 3410| 0| // 3411| 0| // FIXME: We should make this explicit once we have actual support for must 3412| 0| // follow inputs. 3413| 0| for (auto it = inputs.begin(), ie = inputs.end(); it != ie; ++it) { 3414| 0| bsci.taskMustFollow(task, BuildKey::makeNode(*it)); 3415| 0| } 3416| 0| } 3417| | 3418| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 3419| 0| const BuildValue& value) override { 3420| 0| // Ignored. 3421| 0| } 3422| | 3423| | virtual void provideValue(BuildSystemCommandInterface&, core::Task*, 3424| | uintptr_t inputID, 3425| 0| const BuildValue& value) override { 3426| 0| assert(0 && "unexpected API call"); 3427| 0| } 3428| | 3429| | virtual void execute(BuildSystemCommandInterface& bsci, 3430| | core::Task* task, 3431| | QueueJobContext* context, 3432| 0| ResultFn resultFn) override { 3433| 0| // It is an error if this command isn't configured properly. 3434| 0| StringRef outputPath = getActualOutputPath(); 3435| 0| if (!output || outputPath.empty()) { 3436| 0| resultFn(BuildValue::makeFailedCommand()); 3437| 0| return; 3438| 0| } 3439| 0| 3440| 0| // Create the directory containing the symlink, if necessary. 3441| 0| // 3442| 0| // FIXME: Shared behavior with ExternalCommand. 3443| 0| { 3444| 0| auto parent = llvm::sys::path::parent_path(outputPath); 3445| 0| if (!parent.empty()) { 3446| 0| (void) bsci.getFileSystem().createDirectories(parent); 3447| 0| } 3448| 0| } 3449| 0| 3450| 0| // Create the symbolic link (note that despite the poorly chosen LLVM 3451| 0| // name, this is a symlink). 3452| 0| // 3453| 0| // FIXME: Need to use the filesystem interfaces. 3454| 0| bsci.getDelegate().commandStarted(this); 3455| 0| auto success = true; 3456| 0| if (basic::sys::symlink(contents.c_str(), outputPath.str().c_str())) { 3457| 0| // On failure, we attempt to unlink the file and retry. 3458| 0| basic::sys::unlink(outputPath.str().c_str()); 3459| 0| 3460| 0| if (basic::sys::symlink(contents.c_str(), outputPath.str().c_str())) { 3461| 0| getBuildSystem(bsci.getBuildEngine()).getDelegate().commandHadError(this, 3462| 0| "unable to create symlink at '" + outputPath.str() + "'"); 3463| 0| success = false; 3464| 0| } 3465| 0| } 3466| 0| bsci.getDelegate().commandFinished(this, success ? ProcessStatus::Succeeded : ProcessStatus::Failed); 3467| 0| 3468| 0| // Process the result. 3469| 0| if (!success) { 3470| 0| resultFn(BuildValue::makeFailedCommand()); 3471| 0| return; 3472| 0| } 3473| 0| 3474| 0| // Capture the *link* information of the output. 3475| 0| FileInfo outputInfo = bsci.getFileSystem().getLinkInfo( 3476| 0| outputPath); 3477| 0| 3478| 0| // Complete with a successful result. 3479| 0| resultFn(BuildValue::makeSuccessfulCommand(outputInfo, getSignature())); 3480| 0| } 3481| | 3482| |public: 3483| | using Command::Command; 3484| |}; 3485| | 3486| |class SymlinkTool : public Tool { 3487| |public: 3488| | using Tool::Tool; 3489| | 3490| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3491| 0| StringRef value) override { 3492| 0| // No supported attributes. 3493| 0| ctx.error("unexpected attribute: '" + name + "'"); 3494| 0| return false; 3495| 0| } 3496| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3497| 0| ArrayRef values) override { 3498| 0| // No supported attributes. 3499| 0| ctx.error("unexpected attribute: '" + name + "'"); 3500| 0| return false; 3501| 0| } 3502| | virtual bool configureAttribute( 3503| | const ConfigureContext& ctx, StringRef name, 3504| 0| ArrayRef> values) override { 3505| 0| // No supported attributes. 3506| 0| ctx.error("unexpected attribute: '" + name + "'"); 3507| 0| return false; 3508| 0| } 3509| | 3510| 0| virtual std::unique_ptr createCommand(StringRef name) override { 3511| 0| return llvm::make_unique(name); 3512| 0| } 3513| |}; 3514| | 3515| |#pragma mark - ArchiveTool implementation 3516| | 3517| |class ArchiveShellCommand : public ExternalCommand { 3518| | 3519| | std::string archiveName; 3520| | std::vector archiveInputs; 3521| | 3522| | virtual void executeExternalCommand( 3523| | BuildSystemCommandInterface& bsci, 3524| | Task* task, 3525| | QueueJobContext* context, 3526| 0| llvm::Optional completionFn) override { 3527| 0| // First delete the current archive 3528| 0| // TODO instead insert, update and remove files from the archive 3529| 0| if (llvm::sys::fs::remove(archiveName, /*IgnoreNonExisting*/ true)) { 3530| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 3531| 0| fn(ProcessStatus::Failed); 3532| 0| }); 3533| 0| return; 3534| 0| } 3535| 0| 3536| 0| // Create archive 3537| 0| auto args = getArgs(); 3538| 0| bsci.getExecutionQueue().executeProcess(context, 3539| 0| std::vector(args.begin(), args.end()), 3540| 0| {}, true, {true}, 3541| 0| {[completionFn](ProcessResult result) { 3542| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){fn(result);}); 3543| 0| }}); 3544| 0| } 3545| | 3546| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 3547| 0| if (getDescription().empty()) { 3548| 0| llvm::raw_svector_ostream(result) << "Archiving " + archiveName; 3549| 0| } else { 3550| 0| llvm::raw_svector_ostream(result) << getDescription(); 3551| 0| } 3552| 0| } 3553| | 3554| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 3555| 0| llvm::raw_svector_ostream stream(result); 3556| 0| bool first = true; 3557| 0| for (const auto& arg: getArgs()) { 3558| 0| stream << arg; 3559| 0| if (!first) { 3560| 0| stream << " "; 3561| 0| first = false; 3562| 0| } 3563| 0| } 3564| 0| } 3565| | 3566| | virtual void configureInputs(const ConfigureContext& ctx, 3567| 0| const std::vector& value) override { 3568| 0| ExternalCommand::configureInputs(ctx, value); 3569| 0| 3570| 0| for (const auto& input: getInputs()) { 3571| 0| if (!input->isVirtual()) { 3572| 0| archiveInputs.push_back(input->getName()); 3573| 0| } 3574| 0| } 3575| 0| if (archiveInputs.empty()) { 3576| 0| ctx.error("missing expected input"); 3577| 0| } 3578| 0| } 3579| | 3580| | virtual void configureOutputs(const ConfigureContext& ctx, 3581| 0| const std::vector& value) override { 3582| 0| ExternalCommand::configureOutputs(ctx, value); 3583| 0| 3584| 0| for (const auto& output: getOutputs()) { 3585| 0| if (!output->isVirtual()) { 3586| 0| if (archiveName.empty()) { 3587| 0| archiveName = output->getName(); 3588| 0| } else { 3589| 0| ctx.error("unexpected explicit output: " + output->getName()); 3590| 0| } 3591| 0| } 3592| 0| } 3593| 0| if (archiveName.empty()) { 3594| 0| ctx.error("missing expected output"); 3595| 0| } 3596| 0| } 3597| | 3598| 0| std::vector getArgs() const { 3599| 0| std::vector args; 3600| 0| args.push_back("ar"); 3601| 0| args.push_back("cr"); 3602| 0| args.push_back(archiveName); 3603| 0| args.insert(args.end(), archiveInputs.begin(), archiveInputs.end()); 3604| 0| return args; 3605| 0| } 3606| | 3607| |public: 3608| | using ExternalCommand::ExternalCommand; 3609| |}; 3610| | 3611| |class ArchiveTool : public Tool { 3612| |public: 3613| | using Tool::Tool; 3614| | 3615| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3616| 0| StringRef value) override { 3617| 0| // No supported attributes. 3618| 0| ctx.error("unexpected attribute: '" + name + "'"); 3619| 0| return false; 3620| 0| } 3621| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3622| 0| ArrayRef values) override { 3623| 0| // No supported attributes. 3624| 0| ctx.error("unexpected attribute: '" + name + "'"); 3625| 0| return false; 3626| 0| } 3627| | virtual bool configureAttribute( 3628| | const ConfigureContext& ctx, StringRef name, 3629| 0| ArrayRef> values) override { 3630| 0| // No supported attributes. 3631| 0| ctx.error("unexpected attribute: '" + name + "'"); 3632| 0| return false; 3633| 0| } 3634| | 3635| 0| virtual std::unique_ptr createCommand(StringRef name) override { 3636| 0| return llvm::make_unique(name); 3637| 0| } 3638| |}; 3639| | 3640| |#pragma mark - StaleFileRemovalTool implementation 3641| | 3642| |class StaleFileRemovalCommand : public Command { 3643| | std::string description; 3644| | 3645| | std::vector expectedOutputs; 3646| | mutable std::vector filesToDelete; 3647| | std::vector roots; 3648| | mutable bool computedFilesToDelete = false; 3649| | 3650| | BuildValue priorValue; 3651| | bool hasPriorResult = false; 3652| | 3653| | std::string pathSeparators = llbuild::basic::sys::getPathSeparators(); 3654| | 3655| 0| virtual void configureDescription(const ConfigureContext&, StringRef value) override { 3656| 0| description = value; 3657| 0| } 3658| | 3659| 0| virtual void getShortDescription(SmallVectorImpl &result) const override { 3660| 0| llvm::raw_svector_ostream(result) << (description.empty() ? "Stale file removal" : description); 3661| 0| } 3662| | 3663| 0| virtual void getVerboseDescription(SmallVectorImpl &result) const override { 3664| 0| computeFilesToDelete(); 3665| 0| 3666| 0| getShortDescription(result); 3667| 0| llvm::raw_svector_ostream(result) << ", stale files: ["; 3668| 0| for (auto fileToDelete : filesToDelete) { 3669| 0| llvm::raw_svector_ostream(result) << fileToDelete; 3670| 0| if (fileToDelete != *(--filesToDelete.end())) { 3671| 0| llvm::raw_svector_ostream(result) << ", "; 3672| 0| } 3673| 0| } 3674| 0| llvm::raw_svector_ostream(result) << "], roots: ["; 3675| 0| for (auto root : roots) { 3676| 0| llvm::raw_svector_ostream(result) << root; 3677| 0| if (root != *(--roots.end())) { 3678| 0| llvm::raw_svector_ostream(result) << ", "; 3679| 0| } 3680| 0| } 3681| 0| llvm::raw_svector_ostream(result) << "]"; 3682| 0| } 3683| | 3684| | virtual void configureInputs(const ConfigureContext& ctx, 3685| 0| const std::vector& value) override {} 3686| | 3687| | virtual void configureOutputs(const ConfigureContext& ctx, 3688| 0| const std::vector& value) override {} 3689| | 3690| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3691| 0| StringRef value) override { 3692| 0| // No supported attributes. 3693| 0| ctx.error("unexpected attribute: '" + name + "'"); 3694| 0| return false; 3695| 0| } 3696| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3697| 0| ArrayRef values) override { 3698| 0| if (name == "expectedOutputs") { 3699| 0| expectedOutputs.reserve(values.size()); 3700| 0| for (auto value : values) { 3701| 0| expectedOutputs.emplace_back(value.str()); 3702| 0| } 3703| 0| return true; 3704| 0| } else if (name == "roots") { 3705| 0| roots.reserve(values.size()); 3706| 0| for (auto value : values) { 3707| 0| roots.emplace_back(value.str()); 3708| 0| } 3709| 0| return true; 3710| 0| } 3711| 0| 3712| 0| ctx.error("unexpected attribute: '" + name + "'"); 3713| 0| return false; 3714| 0| } 3715| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3716| 0| ArrayRef> values) override { 3717| 0| // No supported attributes. 3718| 0| ctx.error("unexpected attribute: '" + name + "'"); 3719| 0| return false; 3720| 0| } 3721| | 3722| | virtual BuildValue getResultForOutput(Node* node, 3723| 0| const BuildValue& value) override { 3724| 0| // If the value was a failed command, propagate the failure. 3725| 0| if (value.isFailedCommand() || value.isPropagatedFailureCommand() || 3726| 0| value.isCancelledCommand()) 3727| 0| return BuildValue::makeFailedInput(); 3728| 0| if (value.isSkippedCommand()) 3729| 0| return BuildValue::makeSkippedCommand(); 3730| 0| 3731| 0| // Otherwise, this was successful, return the value as-is. 3732| 0| return BuildValue::fromData(value.toData());; 3733| 0| } 3734| | 3735| | virtual bool isResultValid(BuildSystem& system, 3736| 0| const BuildValue& value) override { 3737| 0| // Always re-run stale file removal. 3738| 0| return false; 3739| 0| } 3740| | 3741| | virtual void start(BuildSystemCommandInterface& bsci, 3742| 0| core::Task* task) override {} 3743| | 3744| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 3745| 0| const BuildValue& value) override { 3746| 0| hasPriorResult = true; 3747| 0| priorValue = BuildValue::fromData(value.toData()); 3748| 0| } 3749| | 3750| | virtual void provideValue(BuildSystemCommandInterface&, core::Task*, 3751| | uintptr_t inputID, 3752| 0| const BuildValue& value) override { 3753| 0| assert(0 && "unexpected API call"); 3754| 0| } 3755| | 3756| 0| void computeFilesToDelete() const { 3757| 0| if (computedFilesToDelete) { 3758| 0| return; 3759| 0| } 3760| 0| 3761| 0| std::vector priorValueList = priorValue.getStaleFileList(); 3762| 0| std::set priorNodes(priorValueList.begin(), priorValueList.end()); 3763| 0| std::set expectedNodes(expectedOutputs.begin(), expectedOutputs.end()); 3764| 0| 3765| 0| std::set_difference(priorNodes.begin(), priorNodes.end(), 3766| 0| expectedNodes.begin(), expectedNodes.end(), 3767| 0| std::back_inserter(filesToDelete)); 3768| 0| 3769| 0| computedFilesToDelete = true; 3770| 0| } 3771| | 3772| | virtual void execute(BuildSystemCommandInterface& bsci, 3773| | core::Task* task, 3774| | QueueJobContext* context, 3775| 0| ResultFn resultFn) override { 3776| 0| // Nothing to do if we do not have a prior result. 3777| 0| if (!hasPriorResult || !priorValue.isStaleFileRemoval()) { 3778| 0| bsci.getDelegate().commandStarted(this); 3779| 0| bsci.getDelegate().commandFinished(this, ProcessStatus::Succeeded); 3780| 0| resultFn(BuildValue::makeStaleFileRemoval(expectedOutputs)); 3781| 0| return; 3782| 0| } 3783| 0| 3784| 0| computeFilesToDelete(); 3785| 0| 3786| 0| bsci.getDelegate().commandStarted(this); 3787| 0| 3788| 0| for (auto fileToDelete : filesToDelete) { 3789| 0| // If no root paths are specified, any path is valid. 3790| 0| bool isLocatedUnderRootPath = roots.size() == 0 ? true : false; 3791| 0| 3792| 0| // If root paths are defined, stale file paths should be absolute. 3793| 0| if (roots.size() > 0 && 3794| 0| pathSeparators.find(fileToDelete[0]) == std::string::npos) { 3795| 0| bsci.getDelegate().commandHadWarning(this, "Stale file '" + fileToDelete + "' has a relative path. This is invalid in combination with the root path attribute.\n"); 3796| 0| continue; 3797| 0| } 3798| 0| 3799| 0| // Check if the file is located under one of the allowed root paths. 3800| 0| for (auto root : roots) { 3801| 0| if (pathIsPrefixedByPath(fileToDelete, root)) { 3802| 0| isLocatedUnderRootPath = true; 3803| 0| } 3804| 0| } 3805| 0| 3806| 0| if (!isLocatedUnderRootPath) { 3807| 0| bsci.getDelegate().commandHadWarning(this, "Stale file '" + fileToDelete + "' is located outside of the allowed root paths.\n"); 3808| 0| continue; 3809| 0| } 3810| 0| 3811| 0| if (getBuildSystem(bsci.getBuildEngine()).getFileSystem().remove(fileToDelete)) { 3812| 0| bsci.getDelegate().commandHadNote(this, "Removed stale file '" + fileToDelete + "'\n"); 3813| 0| } else { 3814| 0| // Do not warn if the file has already been deleted. 3815| 0| if (errno != ENOENT) { 3816| 0| bsci.getDelegate().commandHadWarning(this, "cannot remove stale file '" + fileToDelete + "': " + strerror(errno) + "\n"); 3817| 0| } 3818| 0| } 3819| 0| } 3820| 0| 3821| 0| bsci.getDelegate().commandFinished(this, ProcessStatus::Succeeded); 3822| 0| 3823| 0| // Complete with a successful result. 3824| 0| resultFn(BuildValue::makeStaleFileRemoval(expectedOutputs)); 3825| 0| } 3826| | 3827| |public: 3828| | StaleFileRemovalCommand(const StringRef name) 3829| 0| : Command(name), priorValue(BuildValue::makeInvalid()) {} 3830| |}; 3831| | 3832| |class StaleFileRemovalTool : public Tool { 3833| |public: 3834| | using Tool::Tool; 3835| | 3836| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3837| 0| StringRef value) override { 3838| 0| // No supported attributes. 3839| 0| ctx.error("unexpected attribute: '" + name + "'"); 3840| 0| return false; 3841| 0| } 3842| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 3843| 0| ArrayRef values) override { 3844| 0| // No supported attributes. 3845| 0| ctx.error("unexpected attribute: '" + name + "'"); 3846| 0| return false; 3847| 0| } 3848| | virtual bool configureAttribute( 3849| | const ConfigureContext& ctx, StringRef name, 3850| 0| ArrayRef> values) override { 3851| 0| // No supported attributes. 3852| 0| ctx.error("unexpected attribute: '" + name + "'"); 3853| 0| return false; 3854| 0| } 3855| | 3856| 0| virtual std::unique_ptr createCommand(StringRef name) override { 3857| 0| return llvm::make_unique(name); 3858| 0| } 3859| |}; 3860| | 3861| |#pragma mark - BuildSystemFileDelegate 3862| | 3863| 0|BuildSystemDelegate& BuildSystemFileDelegate::getSystemDelegate() { 3864| 0| return system.getDelegate(); 3865| 0|} 3866| | 3867| 0|void BuildSystemFileDelegate::setFileContentsBeingParsed(StringRef buffer) { 3868| 0| getSystemDelegate().setFileContentsBeingParsed(buffer); 3869| 0|} 3870| | 3871| |void BuildSystemFileDelegate::error(StringRef filename, 3872| | const BuildFileToken& at, 3873| 0| const Twine& message) { 3874| 0| // Delegate to the system delegate. 3875| 0| auto atSystemToken = BuildSystemDelegate::Token{at.start, at.length}; 3876| 0| system.error(filename, atSystemToken, message); 3877| 0|} 3878| | 3879| |bool 3880| |BuildSystemFileDelegate::configureClient(const ConfigureContext& ctx, 3881| | StringRef name, 3882| | uint32_t version, 3883| 0| const property_list_type& properties) { 3884| 0| // The client must match the configured name of the build system. 3885| 0| if (name != getSystemDelegate().getName()) 3886| 0| return false; 3887| 0| 3888| 0| // The client version must match the configured version. 3889| 0| // 3890| 0| // FIXME: We should give the client the opportunity to support a previous 3891| 0| // schema version (auto-upgrade). 3892| 0| if (version != getSystemDelegate().getVersion()) 3893| 0| return false; 3894| 0| 3895| 0| for (auto prop : properties) { 3896| 0| if (prop.first == "file-system") { 3897| 0| if (prop.second == "device-agnostic") { 3898| 0| system.configureFileSystem(true); 3899| 0| } else if (prop.second != "default") { 3900| 0| ctx.error("unsupported client file-system: '" + prop.second + "'"); 3901| 0| return false; 3902| 0| } 3903| 0| } 3904| 0| } 3905| 0| 3906| 0| return true; 3907| 0|} 3908| | 3909| |std::unique_ptr 3910| 0|BuildSystemFileDelegate::lookupTool(StringRef name) { 3911| 0| // First, give the client an opportunity to create the tool. 3912| 0| if (auto tool = getSystemDelegate().lookupTool(name)) { 3913| 0| return tool; 3914| 0| } 3915| 0| 3916| 0| // Otherwise, look for one of the builtin tool definitions. 3917| 0| if (name == "shell") { 3918| 0| return llvm::make_unique(name); 3919| 0| } else if (name == "phony") { 3920| 0| return llvm::make_unique(name); 3921| 0| } else if (name == "clang") { 3922| 0| return llvm::make_unique(name); 3923| 0| } else if (name == "mkdir") { 3924| 0| return llvm::make_unique(name); 3925| 0| } else if (name == "symlink") { 3926| 0| return llvm::make_unique(name); 3927| 0| } else if (name == "archive") { 3928| 0| return llvm::make_unique(name); 3929| 0| } else if (name == "stale-file-removal") { 3930| 0| return llvm::make_unique(name); 3931| 0| } else if (name == "swift-compiler") { 3932| 0| return llvm::make_unique(name); 3933| 0| } 3934| 0| 3935| 0| return nullptr; 3936| 0|} 3937| | 3938| |void BuildSystemFileDelegate::loadedTarget(StringRef name, 3939| 0| const Target& target) { 3940| 0|} 3941| | 3942| 0|void BuildSystemFileDelegate::loadedDefaultTarget(StringRef target) { 3943| 0|} 3944| | 3945| |void BuildSystemFileDelegate::loadedCommand(StringRef name, 3946| 0| const Command& command) { 3947| 0|} 3948| | 3949| |std::unique_ptr 3950| |BuildSystemFileDelegate::lookupNode(StringRef name, 3951| 0| bool isImplicit) { 3952| 0| return system.lookupNode(name, isImplicit); 3953| 0|} 3954| | 3955| |} 3956| | 3957| |#pragma mark - BuildSystem 3958| | 3959| |BuildSystem::BuildSystem(BuildSystemDelegate& delegate, std::unique_ptr fileSystem) 3960| | : impl(new BuildSystemImpl(*this, delegate, std::move(fileSystem))) 3961| 0|{ 3962| 0|} 3963| | 3964| 0|BuildSystem::~BuildSystem() { 3965| 0| delete static_cast(impl); 3966| 0|} 3967| | 3968| 0|BuildSystemDelegate& BuildSystem::getDelegate() { 3969| 0| return static_cast(impl)->getDelegate(); 3970| 0|} 3971| | 3972| 0|basic::FileSystem& BuildSystem::getFileSystem() { 3973| 0| return static_cast(impl)->getFileSystem(); 3974| 0|} 3975| | 3976| 0|bool BuildSystem::loadDescription(StringRef mainFilename) { 3977| 0| return static_cast(impl)->loadDescription(mainFilename); 3978| 0|} 3979| | 3980| |void BuildSystem::loadDescription( 3981| 0| std::unique_ptr description) { 3982| 0| return static_cast(impl)->loadDescription( 3983| 0| std::move(description)); 3984| 0|} 3985| | 3986| |bool BuildSystem::attachDB(StringRef path, 3987| 0| std::string* error_out) { 3988| 0| return static_cast(impl)->attachDB(path, error_out); 3989| 0|} 3990| | 3991| |bool BuildSystem::enableTracing(StringRef path, 3992| 0| std::string* error_out) { 3993| 0| return static_cast(impl)->enableTracing(path, error_out); 3994| 0|} 3995| | 3996| 0|llvm::Optional BuildSystem::build(BuildKey key) { 3997| 0| return static_cast(impl)->build(key); 3998| 0|} 3999| | 4000| 0|bool BuildSystem::build(StringRef name) { 4001| 0| return static_cast(impl)->build(name); 4002| 0|} 4003| | 4004| 0|void BuildSystem::cancel() { 4005| 0| if (impl) { 4006| 0| static_cast(impl)->cancel(); 4007| 0| } 4008| 0|} 4009| | 4010| 0|void BuildSystem::resetForBuild() { 4011| 0| static_cast(impl)->resetForBuild(); 4012| 0|} 4013| | 4014| |// This function checks if the given path is prefixed by another path. 4015| |bool llbuild::buildsystem::pathIsPrefixedByPath(std::string path, 4016| 0| std::string prefixPath) { 4017| 0| std::string pathSeparators = llbuild::basic::sys::getPathSeparators(); 4018| 0| // Note: GCC 4.8 doesn't support the mismatch(first1, last1, first2, last2) 4019| 0| // overload, just mismatch(first1, last1, first2), so we have to handle the 4020| 0| // case where prefixPath is longer than path. 4021| 0| if (prefixPath.length() > path.length()) { 4022| 0| // The only case where the prefix can be longer and still be a valid prefix 4023| 0| // is "/foo/" is a prefix of "/foo" 4024| 0| return prefixPath.substr(0, prefixPath.length() - 1) == path && 4025| 0| pathSeparators.find(prefixPath[prefixPath.length() - 1]) != 4026| 0| std::string::npos; 4027| 0| } 4028| 0| auto res = std::mismatch(prefixPath.begin(), prefixPath.end(), path.begin()); 4029| 0| // Check if `prefixPath` has been exhausted or just a separator remains. 4030| 0| bool isPrefix = res.first == prefixPath.end() || 4031| 0| (pathSeparators.find(*(res.first++)) != std::string::npos); 4032| 0| // Check if `path` has been exhausted or just a separator remains. 4033| 0| return isPrefix && 4034| 0| (res.second == path.end() || 4035| 0| (pathSeparators.find(*(res.second++)) != std::string::npos)); 4036| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildSystemFrontend.cpp: 1| |//===-- BuildSystemFrontend.cpp -------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildSystemFrontend.h" 14| | 15| |#include "llbuild/Basic/ExecutionQueue.h" 16| |#include "llbuild/Basic/FileSystem.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/PlatformUtility.h" 19| |#include "llbuild/BuildSystem/BuildDescription.h" 20| |#include "llbuild/BuildSystem/BuildFile.h" 21| |#include "llbuild/BuildSystem/BuildKey.h" 22| |#include "llbuild/BuildSystem/BuildValue.h" 23| | 24| |#include "llvm/ADT/DenseMap.h" 25| |#include "llvm/ADT/SmallPtrSet.h" 26| |#include "llvm/ADT/SmallString.h" 27| |#include "llvm/Support/Format.h" 28| |#include "llvm/Support/Path.h" 29| |#include "llvm/Support/SourceMgr.h" 30| |#include "llvm/Support/raw_ostream.h" 31| | 32| |#include 33| |#include 34| |#include 35| |#include 36| | 37| |using namespace llbuild; 38| |using namespace llbuild::basic; 39| |using namespace llbuild::buildsystem; 40| | 41| |#pragma mark - BuildSystemInvocation implementation 42| | 43| 0|void BuildSystemInvocation::getUsage(int optionWidth, raw_ostream& os) { 44| 0| const struct Options { 45| 0| llvm::StringRef option, helpText; 46| 0| } options[] = { 47| 0| { "--help", "show this help message and exit" }, 48| 0| { "--version", "show the tool version" }, 49| 0| { "-C , --chdir ", "change directory to PATH before building" }, 50| 0| { "--no-db", "disable use of a build database" }, 51| 0| { "--db ", "enable building against the database at PATH" }, 52| 0| { "-f ", "load the build task file at PATH" }, 53| 0| { "--serial", "do not build in parallel" }, 54| 0| { "--scheduler ", "set scheduler algorithm" }, 55| 0| { "-j,--jobs ", "set how many concurrent jobs (lanes) to run" }, 56| 0| { "-v, --verbose", "show verbose status information" }, 57| 0| { "--trace ", "trace build engine operation to PATH" }, 58| 0| }; 59| 0| 60| 0| for (const auto& entry: options) { 61| 0| os << " " << llvm::format("%-*s", optionWidth, entry.option) << " " 62| 0| << entry.helpText << "\n"; 63| 0| } 64| 0|} 65| | 66| |void BuildSystemInvocation::parse(llvm::ArrayRef args, 67| 0| llvm::SourceMgr& sourceMgr) { 68| 0| auto error = [&](const Twine &message) { 69| 0| sourceMgr.PrintMessage(llvm::SMLoc{}, llvm::SourceMgr::DK_Error, message); 70| 0| hadErrors = true; 71| 0| }; 72| 0| 73| 0| while (!args.empty()) { 74| 0| const auto& option = args.front(); 75| 0| args = args.slice(1); 76| 0| 77| 0| if (option == "-") { 78| 0| for (const auto& arg: args) { 79| 0| positionalArgs.push_back(arg); 80| 0| } 81| 0| break; 82| 0| } 83| 0| 84| 0| if (!option.empty() && option[0] != '-') { 85| 0| positionalArgs.push_back(option); 86| 0| continue; 87| 0| } 88| 0| 89| 0| if (option == "--help") { 90| 0| showUsage = true; 91| 0| break; 92| 0| } else if (option == "--version") { 93| 0| showVersion = true; 94| 0| break; 95| 0| } else if (option == "--no-db") { 96| 0| dbPath = ""; 97| 0| } else if (option == "--db") { 98| 0| if (args.empty()) { 99| 0| error("missing argument to '" + option + "'"); 100| 0| break; 101| 0| } 102| 0| dbPath = args[0]; 103| 0| args = args.slice(1); 104| 0| } else if (option == "-C" || option == "--chdir") { 105| 0| if (args.empty()) { 106| 0| error("missing argument to '" + option + "'"); 107| 0| break; 108| 0| } 109| 0| chdirPath = args[0]; 110| 0| args = args.slice(1); 111| 0| } else if (option == "-f") { 112| 0| if (args.empty()) { 113| 0| error("missing argument to '" + option + "'"); 114| 0| break; 115| 0| } 116| 0| buildFilePath = args[0]; 117| 0| args = args.slice(1); 118| 0| } else if (option == "--serial") { 119| 0| useSerialBuild = true; 120| 0| } else if (option == "--scheduler") { 121| 0| if (args.empty()) { 122| 0| error("missing argument to '" + option + "'"); 123| 0| break; 124| 0| } 125| 0| auto algorithm = args[0]; 126| 0| if (algorithm == "commandNamePriority" || algorithm == "default") { 127| 0| schedulerAlgorithm = SchedulerAlgorithm::NamePriority; 128| 0| } else if (algorithm == "fifo") { 129| 0| schedulerAlgorithm = SchedulerAlgorithm::FIFO; 130| 0| } else { 131| 0| error("unknown scheduler algorithm '" + algorithm + "'"); 132| 0| break; 133| 0| } 134| 0| args = args.slice(1); 135| 0| } else if (option == "-j" || option == "--jobs") { 136| 0| if (args.empty()) { 137| 0| error("missing argument to '" + option + "'"); 138| 0| break; 139| 0| } 140| 0| char *end; 141| 0| schedulerLanes = ::strtol(args[0].c_str(), &end, 10); 142| 0| if (*end != '\0') { 143| 0| error("invalid argument '" + args[0] + "' to '" + option + "'"); 144| 0| } 145| 0| args = args.slice(1); 146| 0| } else if (StringRef(option).startswith("-j")) { 147| 0| char *end; 148| 0| schedulerLanes = ::strtol(&option[2], &end, 10); 149| 0| if (*end != '\0') { 150| 0| error("invalid argument to '-j'"); 151| 0| } 152| 0| } else if (option == "-v" || option == "--verbose") { 153| 0| showVerboseStatus = true; 154| 0| } else if (option == "--trace") { 155| 0| if (args.empty()) { 156| 0| error("missing argument to '" + option + "'"); 157| 0| break; 158| 0| } 159| 0| traceFilePath = args[0]; 160| 0| args = args.slice(1); 161| 0| } else { 162| 0| error("invalid option '" + option + "'"); 163| 0| break; 164| 0| } 165| 0| } 166| 0|} 167| | 168| 0|std::string BuildSystemInvocation::formatDetectedCycle(const std::vector& cycle) { 169| 0| // Compute a description of the cycle path. 170| 0| SmallString<256> message; 171| 0| llvm::raw_svector_ostream os(message); 172| 0| os << "cycle detected while building: "; 173| 0| bool first = true; 174| 0| for (const auto* rule: cycle) { 175| 0| if (!first) 176| 0| os << " -> "; 177| 0| 178| 0| // Convert to a build key. 179| 0| auto key = BuildKey::fromData(rule->key); 180| 0| switch (key.getKind()) { 181| 0| case BuildKey::Kind::Unknown: 182| 0| os << "((unknown))"; 183| 0| break; 184| 0| case BuildKey::Kind::Command: 185| 0| os << "command '" << key.getCommandName() << "'"; 186| 0| break; 187| 0| case BuildKey::Kind::CustomTask: 188| 0| os << "custom task '" << key.getCustomTaskName() << "'"; 189| 0| break; 190| 0| case BuildKey::Kind::DirectoryContents: 191| 0| os << "directory-contents '" << key.getDirectoryPath() << "'"; 192| 0| break; 193| 0| case BuildKey::Kind::FilteredDirectoryContents: 194| 0| os << "filtered-directory-contents '" 195| 0| << key.getFilteredDirectoryPath() << "'"; 196| 0| break; 197| 0| case BuildKey::Kind::DirectoryTreeSignature: 198| 0| os << "directory-tree-signature '" 199| 0| << key.getDirectoryTreeSignaturePath() << "'"; 200| 0| break; 201| 0| case BuildKey::Kind::DirectoryTreeStructureSignature: 202| 0| os << "directory-tree-structure-signature '" 203| 0| << key.getDirectoryPath() << "'"; 204| 0| break; 205| 0| case BuildKey::Kind::Node: 206| 0| os << "node '" << key.getNodeName() << "'"; 207| 0| break; 208| 0| case BuildKey::Kind::Stat: 209| 0| os << "stat '" << key.getStatName() << "'"; 210| 0| break; 211| 0| case BuildKey::Kind::Target: 212| 0| os << "target '" << key.getTargetName() << "'"; 213| 0| break; 214| 0| } 215| 0| first = false; 216| 0| } 217| 0| 218| 0| return os.str().str(); 219| 0|} 220| | 221| |#pragma mark - BuildSystemFrontendDelegate implementation 222| | 223| |namespace { 224| | 225| |struct BuildSystemFrontendDelegateImpl; 226| | 227| |class BuildSystemFrontendExecutionQueueDelegate 228| | : public ExecutionQueueDelegate { 229| | BuildSystemFrontendDelegateImpl &delegateImpl; 230| | 231| | bool showVerboseOutput() const; 232| | 233| | BuildSystem& getSystem() const; 234| | 235| |public: 236| | BuildSystemFrontendExecutionQueueDelegate( 237| | BuildSystemFrontendDelegateImpl& delegateImpl) 238| 0| : delegateImpl(delegateImpl) { } 239| | 240| 0| virtual void queueJobStarted(JobDescriptor* command) override { 241| 0| static_cast(&getSystem().getDelegate())-> 242| 0| commandJobStarted(reinterpret_cast(command)); 243| 0| } 244| | 245| 0| virtual void queueJobFinished(JobDescriptor* command) override { 246| 0| static_cast(&getSystem().getDelegate())-> 247| 0| commandJobFinished(reinterpret_cast(command)); 248| 0| } 249| | 250| | virtual void processStarted(ProcessContext* command, 251| 0| ProcessHandle handle) override { 252| 0| static_cast(&getSystem().getDelegate())-> 253| 0| commandProcessStarted( 254| 0| reinterpret_cast(command), 255| 0| BuildSystemFrontendDelegate::ProcessHandle { handle.id }); 256| 0| } 257| | 258| | virtual void processHadError(ProcessContext* command, ProcessHandle handle, 259| 0| const Twine& message) override { 260| 0| static_cast(&getSystem().getDelegate())-> 261| 0| commandProcessHadError( 262| 0| reinterpret_cast(command), 263| 0| BuildSystemFrontendDelegate::ProcessHandle { handle.id }, 264| 0| message); 265| 0| } 266| | 267| | virtual void processHadOutput(ProcessContext* command, ProcessHandle handle, 268| 0| StringRef data) override { 269| 0| static_cast(&getSystem().getDelegate())-> 270| 0| commandProcessHadOutput( 271| 0| reinterpret_cast(command), 272| 0| BuildSystemFrontendDelegate::ProcessHandle { handle.id }, 273| 0| data); 274| 0| } 275| | 276| | virtual void processFinished(ProcessContext* command, ProcessHandle handle, 277| 0| const ProcessResult& result) override { 278| 0| static_cast(&getSystem().getDelegate())-> 279| 0| commandProcessFinished( 280| 0| reinterpret_cast(command), 281| 0| BuildSystemFrontendDelegate::ProcessHandle { handle.id }, 282| 0| result); 283| 0| } 284| |}; 285| | 286| |struct BuildSystemFrontendDelegateImpl { 287| | 288| | /// The status of delegate. 289| | enum class Status { 290| | Uninitialized = 0, 291| | Initialized, 292| | InitializationFailure, 293| | Cancelled, 294| | }; 295| | 296| | llvm::SourceMgr& sourceMgr; 297| | const BuildSystemInvocation& invocation; 298| | 299| | StringRef bufferBeingParsed; 300| | std::atomic numErrors{0}; 301| | std::atomic numFailedCommands{0}; 302| | 303| | BuildSystemFrontendExecutionQueueDelegate executionQueueDelegate; 304| | 305| | BuildSystemFrontend* frontend = nullptr; 306| | BuildSystem* system = nullptr; 307| | 308| | /// The set of active command output buffers, by process handle. 309| | llvm::DenseMap> processOutputBuffers; 310| | 311| | /// The lock protecting `processOutputBuffers`. 312| | std::mutex processOutputBuffersMutex; 313| | 314| | BuildSystemFrontendDelegateImpl(llvm::SourceMgr& sourceMgr, 315| | const BuildSystemInvocation& invocation) 316| | : sourceMgr(sourceMgr), invocation(invocation), 317| 0| executionQueueDelegate(*this) {} 318| | 319| |private: 320| | /// The status of the delegate. 321| | std::atomic status{Status::Uninitialized}; 322| | 323| |public: 324| | 325| | /// Set the status of delegate to the given value. 326| | /// 327| | /// It is not possible to update the status once status is set to initialization failure. 328| 0| void setStatus(Status newStatus) { 329| 0| // Disallow changing status if there was an initialization failure. 330| 0| if (status == Status::InitializationFailure) { 331| 0| return; 332| 0| } 333| 0| status = newStatus; 334| 0| } 335| | 336| | /// Returns the current status. 337| 0| Status getStatus() { 338| 0| return status; 339| 0| } 340| |}; 341| | 342| 0|bool BuildSystemFrontendExecutionQueueDelegate::showVerboseOutput() const { 343| 0| return delegateImpl.invocation.showVerboseStatus; 344| 0|} 345| | 346| 0|BuildSystem& BuildSystemFrontendExecutionQueueDelegate::getSystem() const { 347| 0| assert(delegateImpl.system); 348| 0| return *delegateImpl.system; 349| 0|} 350| | 351| |} 352| | 353| |BuildSystemFrontendDelegate:: 354| |BuildSystemFrontendDelegate(llvm::SourceMgr& sourceMgr, 355| | const BuildSystemInvocation& invocation, 356| | StringRef name, 357| | uint32_t version) 358| | : BuildSystemDelegate(name, version), 359| | impl(new BuildSystemFrontendDelegateImpl(sourceMgr, invocation)) 360| 0|{ 361| 0| 362| 0|} 363| | 364| 0|BuildSystemFrontendDelegate::~BuildSystemFrontendDelegate() { 365| 0| delete static_cast(this->impl); 366| 0|} 367| | 368| |void 369| 0|BuildSystemFrontendDelegate::setFileContentsBeingParsed(StringRef buffer) { 370| 0| auto impl = static_cast(this->impl); 371| 0| 372| 0| impl->bufferBeingParsed = buffer; 373| 0|} 374| | 375| 0|BuildSystemFrontend& BuildSystemFrontendDelegate::getFrontend() { 376| 0| auto impl = static_cast(this->impl); 377| 0| 378| 0| return *impl->frontend; 379| 0|} 380| | 381| 0|llvm::SourceMgr& BuildSystemFrontendDelegate::getSourceMgr() { 382| 0| auto impl = static_cast(this->impl); 383| 0| 384| 0| return impl->sourceMgr; 385| 0|} 386| | 387| 0|unsigned BuildSystemFrontendDelegate::getNumErrors() { 388| 0| auto impl = static_cast(this->impl); 389| 0| 390| 0| return impl->numErrors; 391| 0|} 392| | 393| 0|unsigned BuildSystemFrontendDelegate::getNumFailedCommands() { 394| 0| auto impl = static_cast(this->impl); 395| 0| 396| 0| return impl->numFailedCommands; 397| 0|} 398| | 399| |void 400| 0|BuildSystemFrontendDelegate::error(const Twine& message) { 401| 0| error("", {}, message.str()); 402| 0|} 403| | 404| |void 405| |BuildSystemFrontendDelegate::error(StringRef filename, 406| | const Token& at, 407| 0| const Twine& message) { 408| 0| auto impl = static_cast(this->impl); 409| 0| 410| 0| ++impl->numErrors; 411| 0| 412| 0| // If we have a file and token, resolve the location and range to one 413| 0| // accessible by the source manager. 414| 0| // 415| 0| // FIXME: We shouldn't need to do this, but should switch llbuild to using 416| 0| // SourceMgr natively. 417| 0| llvm::SMLoc loc{}; 418| 0| llvm::SMRange range{}; 419| 0| if (!filename.empty() && at.start) { 420| 0| // FIXME: We ignore errors here, for now, this will be resolved when we move 421| 0| // to SourceMgr completely. 422| 0| auto buffer = impl->system->getFileSystem().getFileContents(filename); 423| 0| if (buffer) { 424| 0| unsigned offset = at.start - impl->bufferBeingParsed.data(); 425| 0| if (offset + at.length < buffer->getBufferSize()) { 426| 0| range.Start = loc = llvm::SMLoc::getFromPointer( 427| 0| buffer->getBufferStart() + offset); 428| 0| range.End = llvm::SMLoc::getFromPointer( 429| 0| buffer->getBufferStart() + (offset + at.length)); 430| 0| getSourceMgr().AddNewSourceBuffer(std::move(buffer), llvm::SMLoc{}); 431| 0| } 432| 0| } 433| 0| } 434| 0| 435| 0| if (range.Start.isValid()) { 436| 0| getSourceMgr().PrintMessage(loc, llvm::SourceMgr::DK_Error, message, range); 437| 0| } else { 438| 0| getSourceMgr().PrintMessage(loc, llvm::SourceMgr::DK_Error, message); 439| 0| } 440| 0| fflush(stderr); 441| 0|} 442| | 443| |std::unique_ptr 444| 0|BuildSystemFrontendDelegate::createExecutionQueue() { 445| 0| auto impl = static_cast(this->impl); 446| 0| 447| 0| if (impl->invocation.useSerialBuild) { 448| 0| return std::unique_ptr( 449| 0| createLaneBasedExecutionQueue(impl->executionQueueDelegate, 1, 450| 0| impl->invocation.schedulerAlgorithm, 451| 0| impl->invocation.environment)); 452| 0| } 453| 0| 454| 0| // Get the number of CPUs to use. 455| 0| unsigned numLanes = impl->invocation.schedulerLanes; 456| 0| if (numLanes == 0) { 457| 0| unsigned numCPUs = std::thread::hardware_concurrency(); 458| 0| if (numCPUs == 0) { 459| 0| error("", {}, "unable to detect number of CPUs"); 460| 0| numLanes = 1; 461| 0| } else { 462| 0| numLanes = numCPUs; 463| 0| } 464| 0| } 465| 0| 466| 0| return std::unique_ptr( 467| 0| createLaneBasedExecutionQueue(impl->executionQueueDelegate, numLanes, 468| 0| impl->invocation.schedulerAlgorithm, 469| 0| impl->invocation.environment)); 470| 0|} 471| | 472| 0|void BuildSystemFrontendDelegate::cancel() { 473| 0| auto delegateImpl = static_cast(impl); 474| 0| assert(delegateImpl->getStatus() != BuildSystemFrontendDelegateImpl::Status::Uninitialized); 475| 0| 476| 0| // Update the status to cancelled. 477| 0| delegateImpl->setStatus(BuildSystemFrontendDelegateImpl::Status::Cancelled); 478| 0| 479| 0| auto system = delegateImpl->system; 480| 0| if (system) { 481| 0| system->cancel(); 482| 0| } 483| 0|} 484| | 485| 0|void BuildSystemFrontendDelegate::resetForBuild() { 486| 0| auto impl = static_cast(this->impl); 487| 0| 488| 0| impl->numFailedCommands = 0; 489| 0| impl->numErrors = 0; 490| 0| 491| 0| // Update status back to initialized on reset. 492| 0| if (impl->getStatus() == BuildSystemFrontendDelegateImpl::Status::Cancelled) { 493| 0| impl->setStatus(BuildSystemFrontendDelegateImpl::Status::Initialized); 494| 0| } 495| 0| 496| 0| // Reset the build system. 497| 0| auto system = impl->system; 498| 0| if (system) { 499| 0| system->resetForBuild(); 500| 0| } 501| 0|} 502| | 503| 0|void BuildSystemFrontendDelegate::hadCommandFailure() { 504| 0| auto impl = static_cast(this->impl); 505| 0| 506| 0| // Increment the failed command count. 507| 0| ++impl->numFailedCommands; 508| 0|} 509| | 510| |void BuildSystemFrontendDelegate::commandStatusChanged(Command*, 511| 0| CommandStatusKind) { 512| 0|} 513| | 514| 0|void BuildSystemFrontendDelegate::commandPreparing(Command*) { 515| 0|} 516| | 517| 0|bool BuildSystemFrontendDelegate::shouldCommandStart(Command*) { 518| 0| return true; 519| 0|} 520| | 521| 0|void BuildSystemFrontendDelegate::commandStarted(Command* command) { 522| 0| // Don't report status if opted out by the command. 523| 0| if (!command->shouldShowStatus()) { 524| 0| return; 525| 0| } 526| 0| 527| 0| // Log the command. 528| 0| // 529| 0| // FIXME: Design the logging and status output APIs. 530| 0| SmallString<64> description; 531| 0| if (getFrontend().getInvocation().showVerboseStatus) { 532| 0| command->getVerboseDescription(description); 533| 0| } else { 534| 0| command->getShortDescription(description); 535| 0| 536| 0| // If the short description is empty, always show the verbose one. 537| 0| if (description.empty()) { 538| 0| command->getVerboseDescription(description); 539| 0| } 540| 0| } 541| 0| fprintf(stdout, "%s\n", description.c_str()); 542| 0| fflush(stdout); 543| 0|} 544| | 545| 0|void BuildSystemFrontendDelegate::commandHadError(Command* command, StringRef data) { 546| 0| fwrite(data.data(), data.size(), 1, stderr); 547| 0| fflush(stderr); 548| 0|} 549| | 550| 0|void BuildSystemFrontendDelegate::commandHadNote(Command* command, StringRef data) { 551| 0| fwrite(data.data(), data.size(), 1, stdout); 552| 0| fflush(stdout); 553| 0|} 554| | 555| 0|void BuildSystemFrontendDelegate::commandHadWarning(Command* command, StringRef data) { 556| 0| fwrite(data.data(), data.size(), 1, stdout); 557| 0| fflush(stdout); 558| 0|} 559| | 560| 0|void BuildSystemFrontendDelegate::commandFinished(Command*, ProcessStatus) { 561| 0|} 562| | 563| |void BuildSystemFrontendDelegate::commandCannotBuildOutputDueToMissingInputs( 564| 0| Command * command, Node *output, SmallPtrSet inputs) { 565| 0| std::string message; 566| 0| llvm::raw_string_ostream messageStream(message); 567| 0| 568| 0| messageStream << "cannot build '"; 569| 0| messageStream << output->getName().str(); 570| 0| messageStream << "' due to missing inputs: "; 571| 0| 572| 0| for (Node* input : inputs) { 573| 0| if (input != *inputs.begin()) { 574| 0| messageStream << ", "; 575| 0| } 576| 0| messageStream << "'" << input->getName() << "'"; 577| 0| } 578| 0| 579| 0| messageStream.flush(); 580| 0| fwrite(message.data(), message.size(), 1, stderr); 581| 0| fflush(stderr); 582| 0|} 583| | 584| |void BuildSystemFrontendDelegate::cannotBuildNodeDueToMultipleProducers( 585| 0| Node *output, std::vector commands) { 586| 0| std::string message; 587| 0| llvm::raw_string_ostream messageStream(message); 588| 0| 589| 0| messageStream << "unable to build node: '"; 590| 0| messageStream << output->getName(); 591| 0| messageStream << "' (node is produced by multiple commands: '"; 592| 0| 593| 0| for (Command* cmd : commands) { 594| 0| if (cmd != *commands.begin()) { 595| 0| messageStream << ", "; 596| 0| } 597| 0| messageStream << "'" << cmd->getName() << "'"; 598| 0| } 599| 0| 600| 0| messageStream.flush(); 601| 0| fwrite(message.data(), message.size(), 1, stderr); 602| 0| fflush(stderr); 603| 0|} 604| | 605| 0|void BuildSystemFrontendDelegate::commandJobStarted(Command*) { 606| 0|} 607| | 608| 0|void BuildSystemFrontendDelegate::commandJobFinished(Command*) { 609| 0|} 610| | 611| |void BuildSystemFrontendDelegate::commandProcessStarted(Command*, 612| 0| ProcessHandle) { 613| 0|} 614| | 615| |bool BuildSystemFrontendDelegate:: 616| |shouldResolveCycle(const std::vector& items, 617| | core::Rule* candidateRule, 618| 0| core::Rule::CycleAction action) { 619| 0| return false; 620| 0|} 621| | 622| |void BuildSystemFrontendDelegate:: 623| |commandProcessHadError(Command* command, ProcessHandle handle, 624| 0| const Twine& message) { 625| 0| SmallString<256> buffer; 626| 0| auto str = message.toStringRef(buffer); 627| 0| 628| 0| // FIXME: Design the logging and status output APIs. 629| 0| fwrite(str.data(), str.size(), 1, stderr); 630| 0| fputc('\n', stderr); 631| 0| fflush(stderr); 632| 0|} 633| | 634| |void BuildSystemFrontendDelegate:: 635| |commandProcessHadOutput(Command* command, ProcessHandle handle, 636| 0| StringRef data) { 637| 0| auto impl = static_cast(this->impl); 638| 0| std::unique_lock lock(impl->processOutputBuffersMutex); 639| 0| 640| 0| // Append to the output buffer. 641| 0| auto& buffer = impl->processOutputBuffers[handle.id]; 642| 0| buffer.insert(buffer.end(), data.begin(), data.end()); 643| 0|} 644| | 645| |void BuildSystemFrontendDelegate:: 646| |commandProcessFinished(Command*, ProcessHandle handle, 647| 0| const ProcessResult& result) { 648| 0| auto impl = static_cast(this->impl); 649| 0| std::unique_lock lock(impl->processOutputBuffersMutex); 650| 0| 651| 0| // If there was an output buffer, flush it. 652| 0| auto it = impl->processOutputBuffers.find(handle.id); 653| 0| if (it == impl->processOutputBuffers.end()) 654| 0| return; 655| 0| 656| 0| fwrite(it->second.data(), it->second.size(), 1, stdout); 657| 0| fflush(stdout); 658| 0| 659| 0| impl->processOutputBuffers.erase(it); 660| 0|} 661| | 662| |#pragma mark - BuildSystemFrontend implementation 663| | 664| |BuildSystemFrontend:: 665| |BuildSystemFrontend(BuildSystemFrontendDelegate& delegate, 666| | const BuildSystemInvocation& invocation, 667| | std::unique_ptr fileSystem) 668| | : delegate(delegate), invocation(invocation), fileSystem(std::move(fileSystem)) 669| 0|{ 670| 0| auto delegateImpl = 671| 0| static_cast(delegate.impl); 672| 0| 673| 0| delegateImpl->frontend = this; 674| 0|} 675| | 676| 0|bool BuildSystemFrontend::initialize() { 677| 0| if (!invocation.chdirPath.empty()) { 678| 0| if (!sys::chdir(invocation.chdirPath.c_str())) { 679| 0| getDelegate().error(Twine("unable to honor --chdir: ") + strerror(errno)); 680| 0| return false; 681| 0| } 682| 0| } 683| 0| 684| 0| // Create the build system. 685| 0| buildSystem.emplace(delegate, std::move(fileSystem)); 686| 0| 687| 0| // Register the system back pointer. 688| 0| // 689| 0| // FIXME: Eliminate this. 690| 0| auto delegateImpl = 691| 0| static_cast(delegate.impl); 692| 0| delegateImpl->system = buildSystem.getPointer(); 693| 0| 694| 0| // Load the build file. 695| 0| if (!buildSystem->loadDescription(invocation.buildFilePath)) 696| 0| return false; 697| 0| 698| 0| // Enable tracing, if requested. 699| 0| if (!invocation.traceFilePath.empty()) { 700| 0| const auto dir = llvm::sys::path::parent_path(invocation.traceFilePath); 701| 0| if (!buildSystem->getFileSystem().createDirectories(dir)) { 702| 0| getDelegate().error(Twine("unable to create tracing directory: " + dir)); 703| 0| return false; 704| 0| } 705| 0| 706| 0| std::string error; 707| 0| if (!buildSystem->enableTracing(invocation.traceFilePath, &error)) { 708| 0| getDelegate().error(Twine("unable to enable tracing: ") + error); 709| 0| return false; 710| 0| } 711| 0| } 712| 0| 713| 0| // Attach the database. 714| 0| if (!invocation.dbPath.empty()) { 715| 0| // If the database path is relative, always make it relative to the input 716| 0| // file. 717| 0| SmallString<256> tmp; 718| 0| StringRef dbPath = invocation.dbPath; 719| 0| if (llvm::sys::path::is_relative(invocation.dbPath) && 720| 0| dbPath.find("://") == StringRef::npos && !dbPath.startswith(":")) { 721| 0| llvm::sys::path::append( 722| 0| tmp, llvm::sys::path::parent_path(invocation.buildFilePath), 723| 0| invocation.dbPath); 724| 0| dbPath = tmp.str(); 725| 0| } 726| 0| 727| 0| std::string error; 728| 0| if (!buildSystem->attachDB(dbPath, &error)) { 729| 0| getDelegate().error(Twine("unable to attach DB: ") + error); 730| 0| return false; 731| 0| } 732| 0| } 733| 0| 734| 0| return true; 735| 0|} 736| | 737| 0|bool BuildSystemFrontend::setupBuild() { 738| 0| auto delegateImpl = 739| 0| static_cast(delegate.impl); 740| 0| 741| 0| // We expect build to be called in these states only. 742| 0| assert(delegateImpl->getStatus() == BuildSystemFrontendDelegateImpl::Status::Uninitialized 743| 0| || delegateImpl->getStatus() == BuildSystemFrontendDelegateImpl::Status::Initialized); 744| 0| 745| 0| // Set the delegate status to initialized. 746| 0| delegateImpl->setStatus(BuildSystemFrontendDelegateImpl::Status::Initialized); 747| 0| 748| 0| // Initialize the build system, if necessary 749| 0| if (!buildSystem.hasValue()) { 750| 0| if (!initialize()) { 751| 0| // Set status to initialization failure. It is not possible to recover from this state. 752| 0| delegateImpl->setStatus(BuildSystemFrontendDelegateImpl::Status::InitializationFailure); 753| 0| return false; 754| 0| } 755| 0| } 756| 0| 757| 0| // If delegate was told to cancel while we were initializing, abort now. 758| 0| if (delegateImpl->getStatus() == BuildSystemFrontendDelegateImpl::Status::Cancelled) { 759| 0| return false; 760| 0| } 761| 0| 762| 0| return true; 763| 0|} 764| | 765| 0|bool BuildSystemFrontend::buildNode(StringRef nodeToBuild) { 766| 0| if (!setupBuild()) { 767| 0| return false; 768| 0| } 769| 0| 770| 0| auto buildValue = buildSystem->build(BuildKey::makeNode(nodeToBuild)); 771| 0| if (!buildValue.hasValue()) { 772| 0| return false; 773| 0| } 774| 0| 775| 0| if (!buildValue.getValue().isExistingInput()) { 776| 0| if (buildValue.getValue().isMissingInput()) { 777| 0| delegate.error((Twine("missing input '") + nodeToBuild + "' and no rule to build it")); 778| 0| } 779| 0| return false; 780| 0| } 781| 0| 782| 0| return delegate.getNumFailedCommands() == 0 && delegate.getNumErrors() == 0; 783| 0|} 784| | 785| 0|bool BuildSystemFrontend::build(StringRef targetToBuild) { 786| 0| if (!setupBuild()) { 787| 0| return false; 788| 0| } 789| 0| 790| 0| // Build the target; if something unspecified failed about the build, return 791| 0| // an error. 792| 0| if (!buildSystem->build(targetToBuild)) 793| 0| return false; 794| 0| 795| 0| // The build was successful if there were no failed commands or unspecified 796| 0| // errors. 797| 0| // 798| 0| // It is the job of the client to report a summary, if desired. 799| 0| return delegate.getNumFailedCommands() == 0 && delegate.getNumErrors() == 0; 800| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/BuildValue.cpp: 1| |//===-- BuildValue.cpp ----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/BuildValue.h" 14| | 15| |#include "llbuild/Basic/LLVM.h" 16| | 17| |#include "llvm/ADT/Hashing.h" 18| | 19| |#include "llvm/Support/raw_ostream.h" 20| | 21| |using namespace llbuild; 22| |using namespace llbuild::buildsystem; 23| | 24| 0|StringRef BuildValue::stringForKind(BuildValue::Kind kind) { 25| 0| switch (kind) { 26| 0|#define CASE(kind) case Kind::kind: return #kind 27| 0| CASE(Invalid); 28| 0| CASE(VirtualInput); 29| 0| CASE(ExistingInput); 30| 0| CASE(MissingInput); 31| 0| CASE(DirectoryContents); 32| 0| CASE(FilteredDirectoryContents); 33| 0| CASE(DirectoryTreeSignature); 34| 0| CASE(DirectoryTreeStructureSignature); 35| 0| CASE(MissingOutput); 36| 0| CASE(FailedInput); 37| 0| CASE(SuccessfulCommand); 38| 0| CASE(FailedCommand); 39| 0| CASE(PropagatedFailureCommand); 40| 0| CASE(CancelledCommand); 41| 0| CASE(SkippedCommand); 42| 0| CASE(Target); 43| 0| CASE(StaleFileRemoval); 44| 0|#undef CASE 45| 0| } 46| 0| return ""; 47| 0|} 48| | 49| 0|void BuildValue::dump(raw_ostream& os) const { 50| 0| os << "BuildValue(" << stringForKind(kind); 51| 0| if (kindHasCommandSignature()) { 52| 0| os << ", signature=" << commandSignature.value; 53| 0| } 54| 0| if (kindHasOutputInfo()) { 55| 0| os << ", outputInfos=["; 56| 0| for (unsigned i = 0; i != getNumOutputs(); ++i) { 57| 0| auto& info = getNthOutputInfo(i); 58| 0| if (i != 0) os << ", "; 59| 0| if (info.isMissing()) { 60| 0| os << "FileInfo{/*missing*/}"; 61| 0| } else { 62| 0| os << "FileInfo{" 63| 0| << "dev=" << info.device 64| 0| << ", inode=" << info.inode 65| 0| << ", mode=" << info.mode 66| 0| << ", size=" << info.size 67| 0| << ", modTime=(" << info.modTime.seconds 68| 0| << ":" << info.modTime.nanoseconds << "}"; 69| 0| } 70| 0| } 71| 0| os << "]"; 72| 0| } 73| 0| if (kindHasStringList()) { 74| 0| std::vector values = getStringListValues(); 75| 0| os << ", values=["; 76| 0| for (unsigned i = 0; i != values.size(); ++i) { 77| 0| if (i != 0) os << ", "; 78| 0| os << '"'; 79| 0| os.write_escaped(values[i]); 80| 0| os << '"'; 81| 0| } 82| 0| os << "]"; 83| 0| } 84| 0| os << ")"; 85| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/ExternalCommand.cpp: 1| |//===-- ExternalCommand.cpp -----------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/BuildSystem/ExternalCommand.h" 14| | 15| |#include "llbuild/Basic/Hashing.h" 16| |#include "llbuild/Basic/ExecutionQueue.h" 17| |#include "llbuild/Basic/FileSystem.h" 18| |#include "llbuild/BuildSystem/BuildFile.h" 19| |#include "llbuild/BuildSystem/BuildKey.h" 20| |#include "llbuild/BuildSystem/BuildNode.h" 21| |#include "llbuild/BuildSystem/BuildSystemCommandInterface.h" 22| |#include "llbuild/BuildSystem/BuildValue.h" 23| | 24| |#include "llbuild/Basic/FileInfo.h" 25| |#include "llbuild/Basic/LLVM.h" 26| | 27| |#include "llvm/ADT/Hashing.h" 28| |#include "llvm/ADT/Twine.h" 29| |#include "llvm/Support/FileSystem.h" 30| |#include "llvm/Support/Path.h" 31| |#include "llvm/Support/raw_ostream.h" 32| | 33| |using namespace llbuild; 34| |using namespace llbuild::basic; 35| |using namespace llbuild::buildsystem; 36| | 37| 0|CommandSignature ExternalCommand::getSignature() { 38| 0| CommandSignature code(getName()); 39| 0| for (const auto* input: inputs) { 40| 0| code = code.combine(input->getName()); 41| 0| } 42| 0| for (const auto* output: outputs) { 43| 0| code = code.combine(output->getName()); 44| 0| } 45| 0| return code 46| 0| .combine(allowMissingInputs) 47| 0| .combine(allowModifiedOutputs) 48| 0| .combine(alwaysOutOfDate); 49| 0|} 50| | 51| |void ExternalCommand::configureDescription(const ConfigureContext&, 52| 0| StringRef value) { 53| 0| description = value; 54| 0|} 55| | 56| |void ExternalCommand:: 57| |configureInputs(const ConfigureContext&, 58| 0| const std::vector& value) { 59| 0| inputs.reserve(value.size()); 60| 0| for (auto* node: value) { 61| 0| inputs.emplace_back(static_cast(node)); 62| 0| } 63| 0|} 64| | 65| |void ExternalCommand:: 66| 0|configureOutputs(const ConfigureContext&, const std::vector& value) { 67| 0| outputs.reserve(value.size()); 68| 0| for (auto* node: value) { 69| 0| outputs.emplace_back(static_cast(node)); 70| 0| } 71| 0|} 72| | 73| |bool ExternalCommand:: 74| |configureAttribute(const ConfigureContext& ctx, StringRef name, 75| 0| StringRef value) { 76| 0| if (name == "allow-missing-inputs") { 77| 0| if (value != "true" && value != "false") { 78| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 79| 0| name + "'"); 80| 0| return false; 81| 0| } 82| 0| allowMissingInputs = value == "true"; 83| 0| return true; 84| 0| } else if (name == "allow-modified-outputs") { 85| 0| if (value != "true" && value != "false") { 86| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 87| 0| name + "'"); 88| 0| return false; 89| 0| } 90| 0| allowModifiedOutputs = value == "true"; 91| 0| return true; 92| 0| } else if (name == "always-out-of-date") { 93| 0| if (value != "true" && value != "false") { 94| 0| ctx.error("invalid value: '" + value + "' for attribute '" + 95| 0| name + "'"); 96| 0| return false; 97| 0| } 98| 0| alwaysOutOfDate = value == "true"; 99| 0| return true; 100| 0| } else { 101| 0| ctx.error("unexpected attribute: '" + name + "'"); 102| 0| return false; 103| 0| } 104| 0|} 105| |bool ExternalCommand:: 106| |configureAttribute(const ConfigureContext& ctx, StringRef name, 107| 0| ArrayRef values) { 108| 0| ctx.error("unexpected attribute: '" + name + "'"); 109| 0| return false; 110| 0|} 111| |bool ExternalCommand::configureAttribute( 112| | const ConfigureContext& ctx, StringRef name, 113| 0| ArrayRef> values) { 114| 0| ctx.error("unexpected attribute: '" + name + "'"); 115| 0| return false; 116| 0|} 117| | 118| |BuildValue ExternalCommand:: 119| 0|getResultForOutput(Node* node, const BuildValue& value) { 120| 0| // If the value was a failed or cancelled command, propagate the failure. 121| 0| if (value.isFailedCommand() || value.isPropagatedFailureCommand() || 122| 0| value.isCancelledCommand()) 123| 0| return BuildValue::makeFailedInput(); 124| 0| if (value.isSkippedCommand()) 125| 0| return BuildValue::makeSkippedCommand(); 126| 0| 127| 0| // Otherwise, we should have a successful command -- return the actual 128| 0| // result for the output. 129| 0| assert(value.isSuccessfulCommand()); 130| 0| 131| 0| // If the node is virtual, the output is always a virtual input value. 132| 0| // 133| 0| // FIXME: Eliminate this, and make the build value array contain an array of 134| 0| // build values. 135| 0| auto buildNode = static_cast(node); 136| 0| if (buildNode->isVirtual() && !buildNode->isCommandTimestamp()) { 137| 0| return BuildValue::makeVirtualInput(); 138| 0| } 139| 0| 140| 0| // Find the index of the output node. 141| 0| // 142| 0| // FIXME: This is O(N). We don't expect N to be large in practice, but it 143| 0| // could be. 144| 0| auto it = std::find(outputs.begin(), outputs.end(), node); 145| 0| assert(it != outputs.end()); 146| 0| 147| 0| auto idx = it - outputs.begin(); 148| 0| assert(idx < value.getNumOutputs()); 149| 0| 150| 0| auto& info = value.getNthOutputInfo(idx); 151| 0| if (info.isMissing()) 152| 0| return BuildValue::makeMissingOutput(); 153| 0| 154| 0| return BuildValue::makeExistingInput(info); 155| 0|} 156| | 157| |bool ExternalCommand::isResultValid(BuildSystem& system, 158| 0| const BuildValue& value) { 159| 0| // Treat the command as always out-of-date, if requested. 160| 0| if (alwaysOutOfDate) 161| 0| return false; 162| 0| 163| 0| // If the prior value wasn't for a successful command, recompute. 164| 0| if (!value.isSuccessfulCommand()) 165| 0| return false; 166| 0| 167| 0| // If the command's signature has changed since it was built, rebuild. 168| 0| if (value.getCommandSignature() != getSignature()) 169| 0| return false; 170| 0| 171| 0| // Check the timestamps on each of the outputs. 172| 0| for (unsigned i = 0, e = outputs.size(); i != e; ++i) { 173| 0| auto* node = outputs[i]; 174| 0| 175| 0| // Ignore virtual outputs. 176| 0| if (node->isVirtual()) 177| 0| continue; 178| 0| 179| 0| // Rebuild if the output information has changed. 180| 0| // 181| 0| // We intentionally allow missing outputs here, as long as they haven't 182| 0| // changed. This is under the assumption that the commands themselves are 183| 0| // behaving correctly when they exit successfully, and that downstream 184| 0| // commands would diagnose required missing inputs. 185| 0| // 186| 0| // FIXME: CONSISTENCY: One consistency issue in this model currently is that 187| 0| // if the output was missing, then appears, nothing will remove it; that 188| 0| // results in an inconsistent build. What would be nice if we supported 189| 0| // per-edge annotations on whether an output was optional -- in that case we 190| 0| // could enforce and error on the missing output if not annotated, and we 191| 0| // could enable behavior to remove such output files if annotated prior to 192| 0| // running the command. 193| 0| auto info = node->getFileInfo(system.getFileSystem()); 194| 0| 195| 0| // If this output is mutated by the build, we can't rely on equivalence, 196| 0| // only existence. 197| 0| if (node->isMutated()) { 198| 0| if (value.getNthOutputInfo(i).isMissing() != info.isMissing()) 199| 0| return false; 200| 0| continue; 201| 0| } 202| 0| 203| 0| if (value.getNthOutputInfo(i) != info) 204| 0| return false; 205| 0| } 206| 0| 207| 0| // Otherwise, the result is ok. 208| 0| return true; 209| 0|} 210| | 211| |void ExternalCommand::start(BuildSystemCommandInterface& bsci, 212| 0| core::Task* task) { 213| 0| // Initialize the build state. 214| 0| skipValue = llvm::None; 215| 0| missingInputNodes.clear(); 216| 0| 217| 0| // Request all of the inputs. 218| 0| unsigned id = 0; 219| 0| for (auto it = inputs.begin(), ie = inputs.end(); it != ie; ++it, ++id) { 220| 0| bsci.taskNeedsInput(task, BuildKey::makeNode(*it), id); 221| 0| } 222| 0|} 223| | 224| |void ExternalCommand::providePriorValue(BuildSystemCommandInterface&, 225| | core::Task*, 226| 0| const BuildValue& value) { 227| 0| if (value.isSuccessfulCommand()) { 228| 0| hasPriorResult = true; 229| 0| priorResultCommandSignature = value.getCommandSignature(); 230| 0| } 231| 0|} 232| | 233| |void ExternalCommand::provideValue(BuildSystemCommandInterface& bsci, 234| | core::Task*, 235| | uintptr_t inputID, 236| 0| const BuildValue& value) { 237| 0| // Process the input value to see if we should skip this command. 238| 0| 239| 0| // All direct inputs should be individual node values. 240| 0| assert(!value.hasMultipleOutputs()); 241| 0| assert(value.isExistingInput() || value.isMissingInput() || 242| 0| value.isMissingOutput() || value.isFailedInput() || 243| 0| value.isVirtualInput() || value.isSkippedCommand() || 244| 0| value.isDirectoryTreeSignature() || 245| 0| value.isDirectoryTreeStructureSignature() || 246| 0| value.isStaleFileRemoval()); 247| 0| 248| 0| // If the input should cause this command to skip, how should it skip? 249| 0| auto getSkipValueForInput = [&]() -> llvm::Optional { 250| 0| // If the value is an signature, existing, or virtual input, we are always 251| 0| // good. 252| 0| if (value.isDirectoryTreeSignature() || 253| 0| value.isDirectoryTreeStructureSignature() || 254| 0| value.isExistingInput() || 255| 0| value.isVirtualInput() || value.isStaleFileRemoval()) 256| 0| return llvm::None; 257| 0| 258| 0| // We explicitly allow running the command against a missing output, under 259| 0| // the expectation that responsibility for reporting this situation falls to 260| 0| // the command. 261| 0| // 262| 0| // FIXME: Eventually, it might be nice to harden the format so that we know 263| 0| // when an output was actually required versus optional. 264| 0| if (value.isMissingOutput()) 265| 0| return llvm::None; 266| 0| 267| 0| // If the value is a missing input, but those are allowed, it is ok. 268| 0| if (value.isMissingInput()) { 269| 0| if (allowMissingInputs) 270| 0| return llvm::None; 271| 0| else 272| 0| return BuildValue::makePropagatedFailureCommand(); 273| 0| } 274| 0| 275| 0| // Propagate failure. 276| 0| if (value.isFailedInput()) 277| 0| return BuildValue::makePropagatedFailureCommand(); 278| 0| 279| 0| // A skipped dependency doesn't cause this command to skip. 280| 0| if (value.isSkippedCommand()) 281| 0| return llvm::None; 282| 0| 283| 0| llvm_unreachable("unexpected input"); 284| 0| }; 285| 0| 286| 0| // Check if we need to skip the command because of this input. 287| 0| auto skipValueForInput = getSkipValueForInput(); 288| 0| if (skipValueForInput.hasValue()) { 289| 0| skipValue = std::move(skipValueForInput); 290| 0| if (value.isMissingInput()) { 291| 0| missingInputNodes.insert(inputs[inputID]); 292| 0| } 293| 0| } else { 294| 0| // If there is a missing input file (from a successful command), we always 295| 0| // need to run the command. 296| 0| if (value.isMissingOutput()) 297| 0| canUpdateIfNewer = false; 298| 0| } 299| 0|} 300| | 301| 0|bool ExternalCommand::canUpdateIfNewerWithResult(const BuildValue& result) { 302| 0| // Unless `allowModifiedOutputs` is specified, we always need to update if 303| 0| // ran. 304| 0| if (!allowModifiedOutputs) 305| 0| return false; 306| 0| 307| 0| // If it was specified, then we can update if all of our outputs simply exist. 308| 0| for (unsigned i = 0, e = result.getNumOutputs(); i != e; ++i) { 309| 0| const FileInfo& outputInfo = result.getNthOutputInfo(i); 310| 0| 311| 0| // If the output is missing, we need to rebuild. 312| 0| if (outputInfo.isMissing()) 313| 0| return false; 314| 0| } 315| 0| return true; 316| 0|} 317| | 318| |BuildValue 319| 0|ExternalCommand::computeCommandResult(BuildSystemCommandInterface& bsci) { 320| 0| // Capture the file information for each of the output nodes. 321| 0| // 322| 0| // FIXME: We need to delegate to the node here. 323| 0| SmallVector outputInfos; 324| 0| for (auto* node: outputs) { 325| 0| if (node->isCommandTimestamp()) { 326| 0| // FIXME: We currently have to shoehorn the timestamp into a fake file 327| 0| // info, but need to refactor the command result to just store the node 328| 0| // subvalues instead. 329| 0| FileInfo info{}; 330| 0| info.size = bsci.getBuildEngine().getCurrentTimestamp(); 331| 0| outputInfos.push_back(info); 332| 0| } else if (node->isVirtual()) { 333| 0| outputInfos.push_back(FileInfo{}); 334| 0| } else { 335| 0| outputInfos.push_back(node->getFileInfo( 336| 0| bsci.getFileSystem())); 337| 0| } 338| 0| } 339| 0| return BuildValue::makeSuccessfulCommand(outputInfos, getSignature()); 340| 0|} 341| | 342| |void ExternalCommand::execute(BuildSystemCommandInterface& bsci, 343| | core::Task* task, 344| | QueueJobContext* context, 345| 0| ResultFn resultFn) { 346| 0| // If this command should be skipped, do nothing. 347| 0| if (skipValue.hasValue()) { 348| 0| // If this command had a failed input, treat it as having failed. 349| 0| if (!missingInputNodes.empty()) { 350| 0| bsci.getDelegate().commandCannotBuildOutputDueToMissingInputs(this, 351| 0| outputs[0], missingInputNodes); 352| 0| 353| 0| // Report the command failure. 354| 0| bsci.getDelegate().hadCommandFailure(); 355| 0| } 356| 0| 357| 0| resultFn(std::move(skipValue.getValue())); 358| 0| return; 359| 0| } 360| 0| assert(missingInputNodes.empty()); 361| 0| 362| 0| // If it is legal to simply update the command, then see if we can do so. 363| 0| if (canUpdateIfNewer && 364| 0| hasPriorResult && priorResultCommandSignature == getSignature()) { 365| 0| BuildValue result = computeCommandResult(bsci); 366| 0| if (canUpdateIfNewerWithResult(result)) { 367| 0| resultFn(std::move(result)); 368| 0| return; 369| 0| } 370| 0| } 371| 0| 372| 0| // Create the directories for the directories containing file outputs. 373| 0| // 374| 0| // FIXME: Implement a shared cache for this, to reduce the number of 375| 0| // syscalls required to make this happen. 376| 0| for (auto* node: outputs) { 377| 0| if (!node->isVirtual()) { 378| 0| // Attempt to create the directory; we ignore errors here under the 379| 0| // assumption the command will diagnose the situation if necessary. 380| 0| // 381| 0| // FIXME: Need to use the filesystem interfaces. 382| 0| auto parent = llvm::sys::path::parent_path(node->getName()); 383| 0| if (!parent.empty()) { 384| 0| (void) bsci.getFileSystem().createDirectories(parent); 385| 0| } 386| 0| } 387| 0| } 388| 0| 389| 0| // Invoke the external command. 390| 0| bsci.getDelegate().commandStarted(this); 391| 0| executeExternalCommand(bsci, task, context, {[this, &bsci, resultFn](ProcessResult result){ 392| 0| bsci.getDelegate().commandFinished(this, result.status); 393| 0| 394| 0| // Process the result. 395| 0| switch (result.status) { 396| 0| case ProcessStatus::Failed: 397| 0| resultFn(BuildValue::makeFailedCommand()); 398| 0| return; 399| 0| case ProcessStatus::Cancelled: 400| 0| resultFn(BuildValue::makeCancelledCommand()); 401| 0| return; 402| 0| case ProcessStatus::Succeeded: 403| 0| resultFn(computeCommandResult(bsci)); 404| 0| return; 405| 0| case ProcessStatus::Skipped: 406| 0| // It is illegal to get skipped result at this point. 407| 0| break; 408| 0| } 409| 0| llvm::report_fatal_error("unknown result"); 410| 0| }}); 411| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildDescription.h: 1| |//===- BuildDescription.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDDESCRIPTION_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDDESCRIPTION_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/ExecutionQueue.h" 18| |#include "llbuild/Basic/LLVM.h" 19| | 20| |#include "llvm/ADT/SmallString.h" 21| |#include "llvm/ADT/StringMap.h" 22| |#include "llvm/ADT/StringRef.h" 23| | 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| | 30| |namespace llbuild { 31| | 32| |namespace core { 33| | 34| |class Task; 35| | 36| |} 37| | 38| |namespace buildsystem { 39| | 40| |/// The type used to pass parsed properties to the delegate. 41| |typedef std::vector> property_list_type; 42| | 43| |class BuildSystem; 44| |class BuildSystemCommandInterface; 45| |class BuildKey; 46| |class BuildValue; 47| |class Command; 48| |class Node; 49| | 50| |/// Context for information that may be needed for a configuration action. 51| |// 52| |// FIXME: This is currently commingled with the build file loading, even though 53| |// it should ideally be possible to create a build description decoupled 54| |// entirely from the build file representation. 55| |struct ConfigureContext; 56| | 57| |/// Abstract tool definition used by the build file. 58| |class Tool { 59| | // DO NOT COPY 60| | Tool(const Tool&) LLBUILD_DELETED_FUNCTION; 61| | void operator=(const Tool&) LLBUILD_DELETED_FUNCTION; 62| | Tool &operator=(Tool&& rhs) LLBUILD_DELETED_FUNCTION; 63| | 64| | std::string name; 65| | 66| |public: 67| 0| explicit Tool(StringRef name) : name(name) {} 68| | virtual ~Tool(); 69| | 70| 0| StringRef getName() const { return name; } 71| | 72| | /// Called by the build file loader to configure a specified tool property. 73| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 74| | StringRef value) = 0; 75| | /// Called by the build file loader to configure a specified tool property. 76| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 77| | ArrayRef values) = 0; 78| | /// Called by the build file loader to configure a specified node property. 79| | virtual bool configureAttribute( 80| | const ConfigureContext&, StringRef name, 81| | ArrayRef> values) = 0; 82| | 83| | /// Called by the build file loader to create a command which uses this tool. 84| | /// 85| | /// \param name - The name of the command. 86| | virtual std::unique_ptr createCommand(StringRef name) = 0; 87| | 88| | /// Called by the build system to create a custom command with the given name. 89| | /// 90| | /// The tool should return null if it does not understand how to create the 91| | /// a custom command for the given key. 92| | /// 93| | /// \param key - The custom build key to create a command for. 94| | /// \returns The command to use, or null. 95| | virtual std::unique_ptr createCustomCommand(const BuildKey& key); 96| |}; 97| | 98| |/// Each Target declares a name that can be used to reference it, and a list of 99| |/// the top-level nodes which must be built to bring that target up to date. 100| |class Target { 101| | /// The name of the target. 102| | std::string name; 103| | 104| | /// The list of nodes that should be computed to build this target. 105| | std::vector nodes; 106| | 107| |public: 108| 0| explicit Target(std::string name) : name(name) { } 109| | 110| 0| StringRef getName() const { return name; } 111| | 112| 0| std::vector& getNodes() { return nodes; } 113| 0| const std::vector& getNodes() const { return nodes; } 114| |}; 115| | 116| |/// Abstract definition for a Node used by the build file. 117| |class Node { 118| | // DO NOT COPY 119| | Node(const Node&) LLBUILD_DELETED_FUNCTION; 120| | void operator=(const Node&) LLBUILD_DELETED_FUNCTION; 121| | Node &operator=(Node&& rhs) LLBUILD_DELETED_FUNCTION; 122| | 123| | /// The name used to identify the node. 124| | std::string name; 125| | 126| | /// The list of commands which can produce this node. 127| | // 128| | // FIXME: Optimize for single entry list. 129| | std::vector producers; 130| | 131| |public: 132| 0| explicit Node(StringRef name) : name(name) {} 133| | virtual ~Node(); 134| | 135| 0| StringRef getName() const { return name; } 136| | 137| 0| std::vector& getProducers() { return producers; } 138| | 139| 0| const std::vector& getProducers() const { return producers; } 140| | 141| | /// Called by the build file loader to configure a specified node property. 142| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 143| | StringRef value) = 0; 144| | /// Called by the build file loader to configure a specified node property. 145| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 146| | ArrayRef values) = 0; 147| | /// Called by the build file loader to configure a specified node property. 148| | virtual bool configureAttribute( 149| | const ConfigureContext&, StringRef name, 150| | ArrayRef> values) = 0; 151| |}; 152| | 153| |/// Abstract command definition used by the build file. 154| |class Command : public basic::JobDescriptor { 155| | // DO NOT COPY 156| | Command(const Command&) LLBUILD_DELETED_FUNCTION; 157| | void operator=(const Command&) LLBUILD_DELETED_FUNCTION; 158| | Command &operator=(Command&& rhs) LLBUILD_DELETED_FUNCTION; 159| | 160| | std::string name; 161| | 162| |public: 163| 0| explicit Command(StringRef name) : name(name) {} 164| | virtual ~Command(); 165| | 166| 0| StringRef getName() const { return name; } 167| | 168| | /// @name Command Information 169| | /// @{ 170| | // 171| | // FIXME: These probably don't belong here, clients generally can just manage 172| | // the information from their commands directly and our predefined interfaces 173| | // won't necessarily match what they want. However, we use them now to allow 174| | // extracting generic status information from the builtin commands. An 175| | // alternate solution would be to simply expose those command classes directly 176| | // and provide some kind of dynamic dispatching mechanism (llvm::cast<>, for 177| | // example) over commands. 178| | 179| | /// Controls whether the default status reporting shows status for the 180| | /// command. 181| 0| virtual bool shouldShowStatus() { return true; } 182| | 183| 0| virtual StringRef getOrdinalName() const override { return getName(); } 184| | 185| | /// Get a short description of the command, for use in status reporting. 186| | virtual void getShortDescription(SmallVectorImpl &result) const override = 0; 187| | 188| | /// Get a verbose description of the command, for use in status reporting. 189| | virtual void getVerboseDescription(SmallVectorImpl &result) const override = 0; 190| | 191| | /// @} 192| | 193| | /// @name File Loading 194| | /// @{ 195| | 196| | /// Called by the build file loader to set the description. 197| | virtual void configureDescription(const ConfigureContext&, 198| | StringRef description) = 0; 199| | 200| | /// Called by the build file loader to pass the list of input nodes. 201| | virtual void configureInputs(const ConfigureContext&, 202| | const std::vector& inputs) = 0; 203| | 204| | /// Called by the build file loader to pass the list of output nodes. 205| | virtual void configureOutputs(const ConfigureContext&, 206| | const std::vector& outputs) = 0; 207| | 208| | /// Called by the build file loader to configure a specified command property. 209| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 210| | StringRef value) = 0; 211| | /// Called by the build file loader to configure a specified command property. 212| | virtual bool configureAttribute(const ConfigureContext&, StringRef name, 213| | ArrayRef values) = 0; 214| | /// Called by the build file loader to configure a specified command property. 215| | virtual bool configureAttribute( 216| | const ConfigureContext&, StringRef name, 217| | ArrayRef> values) = 0; 218| | 219| | /// @} 220| | 221| | /// @name Node Interfaces 222| | /// 223| | /// @description These are the interfaces which allow the build system to 224| | /// coordinate between the abstract command and node objects. 225| | // 226| | // FIXME: This feels awkward, maybe this isn't the right way to manage 227| | // this. However, we want the system to be able to provide the plumbing 228| | // between pluggable comands and nodes, so it feels like it has to live 229| | // somewhere. 230| | // 231| | /// @{ 232| | 233| | /// Get the appropriate output for a particular node (known to be produced by 234| | /// this command) given the command's result. 235| | virtual BuildValue getResultForOutput(Node* node, 236| | const BuildValue& value) = 0; 237| | 238| | /// @} 239| | 240| | /// @name Command Execution 241| | /// 242| | /// @description These APIs directly mirror the APIs available in the 243| | /// lower-level BuildEngine, but with additional services provided by the 244| | /// BuildSystem. See the BuildEngine documentation for more information. 245| | /// 246| | /// @{ 247| | 248| | virtual bool isResultValid(BuildSystem& system, const BuildValue& value) = 0; 249| | 250| | virtual void start(BuildSystemCommandInterface&, core::Task*) = 0; 251| | 252| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 253| | const BuildValue& value) = 0; 254| | 255| | virtual void provideValue(BuildSystemCommandInterface&, core::Task*, 256| | uintptr_t inputID, const BuildValue& value) = 0; 257| | 258| | 259| | typedef std::function ResultFn; 260| | 261| | /// Execute the command, and return the value. 262| | /// 263| | /// This method will always be executed on the build execution queue. 264| | /// 265| | /// Note that resultFn may be executed asynchronously on a separate thread. 266| | virtual void execute(BuildSystemCommandInterface&, core::Task*, 267| | basic::QueueJobContext* context, ResultFn resultFn) = 0; 268| | 269| | /// @} 270| |}; 271| | 272| | 273| |/// A complete description of a build. 274| |class BuildDescription { 275| |public: 276| | // FIXME: This is an inefficent map, the string is duplicated. 277| | typedef llvm::StringMap> node_set; 278| | 279| | // FIXME: This is an inefficent map, the string is duplicated. 280| | typedef llvm::StringMap> target_set; 281| | 282| | // FIXME: This is an inefficent map, the string is duplicated. 283| | typedef llvm::StringMap> command_set; 284| | 285| | // FIXME: This is an inefficent map, the string is duplicated. 286| | typedef llvm::StringMap> tool_set; 287| | 288| |private: 289| | node_set nodes; 290| | 291| | target_set targets; 292| | 293| | command_set commands; 294| | 295| | tool_set tools; 296| | 297| | /// The default target. 298| | std::string defaultTarget; 299| | 300| |public: 301| | /// @name Accessors 302| | /// @{ 303| | 304| | /// Get the set of declared nodes for the file. 305| 0| node_set& getNodes() { return nodes; } 306| | 307| | /// Get the set of declared nodes for the file. 308| 0| const node_set& getNodes() const { return nodes; } 309| | 310| | /// Get the set of declared targets for the file. 311| 0| target_set& getTargets() { return targets; } 312| | 313| | /// Get the set of declared targets for the file. 314| 0| const target_set& getTargets() const { return targets; } 315| | 316| | /// Get the default target. 317| 0| std::string& getDefaultTarget() { return defaultTarget; } 318| | 319| | /// Get the default target. 320| 0| const std::string& getDefaultTarget() const { return defaultTarget; } 321| | 322| | /// Get the set of declared commands for the file. 323| 0| command_set& getCommands() { return commands; } 324| | 325| | /// Get the set of declared commands for the file. 326| 0| const command_set& getCommands() const { return commands; } 327| | 328| | /// Get the set of all tools used by the file. 329| 0| tool_set& getTools() { return tools; } 330| | 331| | /// Get the set of all tools used by the file. 332| 0| const tool_set& getTools() const { return tools; } 333| | 334| | /// @} 335| | /// @name Construction Helpers. 336| | /// @{ 337| | 338| 0| Node& addNode(std::unique_ptr value) { 339| 0| auto& result = *value.get(); 340| 0| getNodes()[value->getName()] = std::move(value); 341| 0| return result; 342| 0| } 343| | 344| 0| Target& addTarget(std::unique_ptr value) { 345| 0| auto& result = *value.get(); 346| 0| getTargets()[value->getName()] = std::move(value); 347| 0| return result; 348| 0| } 349| | 350| 0| Command& addCommand(std::unique_ptr value) { 351| 0| auto& result = *value.get(); 352| 0| getCommands()[value->getName()] = std::move(value); 353| 0| return result; 354| 0| } 355| | 356| 0| Tool& addTool(std::unique_ptr value) { 357| 0| auto& result = *value.get(); 358| 0| getTools()[value->getName()] = std::move(value); 359| 0| return result; 360| 0| } 361| | 362| | /// @} 363| |}; 364| | 365| |} 366| |} 367| | 368| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildFile.h: 1| |//===- BuildFile.h ----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDFILE_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDFILE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/StringRef.h" 20| | 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llbuild { 28| |namespace basic { 29| | 30| |class FileSystem; 31| | 32| |} 33| | 34| |namespace buildsystem { 35| | 36| |/// The type used to pass parsed properties to the delegate. 37| |typedef std::vector> property_list_type; 38| | 39| |class BuildDescription; 40| |class BuildFileDelegate; 41| |class BuildKey; 42| |class BuildSystem; 43| |class BuildSystemCommandInterface; 44| |class BuildValue; 45| |class Command; 46| |class Node; 47| |class Target; 48| |class Tool; 49| | 50| |/// Minimal token object representing the range where a diagnostic occurred. 51| |struct BuildFileToken { 52| | const char* start; 53| | unsigned length; 54| |}; 55| | 56| |/// Context for information that may be needed for a configuration action. 57| |struct ConfigureContext { 58| | /// The file delegate, to use for error reporting, etc. 59| | BuildFileDelegate& delegate; 60| | 61| | /// The file the configuration request originated from. 62| | StringRef filename; 63| | 64| | /// The token to use in error reporting. 65| | BuildFileToken at; 66| | 67| |public: 68| 0| BuildFileDelegate& getDelegate() const { return delegate; } 69| | 70| | void error(const Twine& message) const; 71| |}; 72| | 73| |class BuildFileDelegate { 74| |public: 75| | virtual ~BuildFileDelegate(); 76| | 77| | /// Get an interned string. 78| | virtual StringRef getInternedString(StringRef value) = 0; 79| | 80| | /// Get the file system to use for access. 81| | virtual basic::FileSystem& getFileSystem() = 0; 82| | 83| | /// Called by the build file loader to register the current file contents. 84| | // 85| | // FIXME: This is a total hack, and should be cleaned up. 86| | virtual void setFileContentsBeingParsed(StringRef buffer) = 0; 87| | 88| | /// Called by the build file loader to report an error. 89| | /// 90| | /// \param filename The file the error occurred in. 91| | /// 92| | /// \param at The token at which the error occurred. The token will be null if 93| | /// no location is associated. 94| | /// 95| | /// \param message The diagnostic message. 96| | virtual void error(StringRef filename, 97| | const BuildFileToken& at, 98| | const Twine& message) = 0; 99| | 100| | /// Called by the build file loader after the 'client' file section has been 101| | /// loaded. 102| | /// 103| | /// \param name The expected client name. 104| | /// \param version The client version specified in the file. 105| | /// \param properties The list of additional properties passed to the client. 106| | /// 107| | /// \returns True on success. 108| | virtual bool configureClient(const ConfigureContext&, StringRef name, 109| | uint32_t version, 110| | const property_list_type& properties) = 0; 111| | 112| | /// Called by the build file loader to get a tool definition. 113| | /// 114| | /// \param name The name of the tool to lookup. 115| | /// \returns The tool to use on success, or otherwise nil. 116| | virtual std::unique_ptr lookupTool(StringRef name) = 0; 117| | 118| | /// Called by the build file loader to inform the client that a target 119| | /// definition has been loaded. 120| | virtual void loadedTarget(StringRef name, const Target& target) = 0; 121| | 122| | /// Called by the build file loader to inform the client that a default 123| | /// target has been loaded. 124| | virtual void loadedDefaultTarget(StringRef target) = 0; 125| | 126| | /// Called by the build file loader to inform the client that a command 127| | /// has been fully loaded. 128| | virtual void loadedCommand(StringRef name, const Command& command) = 0; 129| | 130| | /// Called by the build file loader to get a node. 131| | /// 132| | /// \param name The name of the node to lookup. 133| | /// 134| | /// \param isImplicit Whether the node is an implicit one (created as a side 135| | /// effect of being declared by a command). 136| | virtual std::unique_ptr lookupNode(StringRef name, 137| | bool isImplicit=false) = 0; 138| |}; 139| | 140| |/// The BuildFile class supports the "llbuild"-native build description file 141| |/// format. 142| |class BuildFile { 143| |private: 144| | void *impl; 145| | 146| |public: 147| | /// Create a build file with the given delegate. 148| | /// 149| | /// \arg mainFilename The path of the main build file. 150| | explicit BuildFile(StringRef mainFilename, 151| | BuildFileDelegate& delegate); 152| | ~BuildFile(); 153| | 154| | /// Return the delegate the engine was configured with. 155| | BuildFileDelegate* getDelegate(); 156| | 157| | /// Load the build file from the provided filename. 158| | /// 159| | /// \returns A non-null build description on success. 160| | std::unique_ptr load(); 161| |}; 162| | 163| |} 164| |} 165| | 166| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildKey.h: 1| |//===- BuildKey.h -----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDKEY_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDKEY_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| |#include "llbuild/Basic/Compiler.h" 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/StringList.h" 20| |#include "llbuild/Core/BuildEngine.h" 21| |#include "llbuild/BuildSystem/BuildDescription.h" 22| | 23| |#include "llvm/ADT/StringRef.h" 24| | 25| |namespace llbuild { 26| |namespace buildsystem { 27| | 28| |/// The BuildKey encodes the key space used by the BuildSystem when using the 29| |/// core BuildEngine. 30| |class BuildKey { 31| | using KeyType = core::KeyType; 32| | 33| |public: 34| | enum class Kind { 35| | /// A key used to identify a command. 36| | Command, 37| | 38| | /// A key used to identify a custom task. 39| | CustomTask, 40| | 41| | /// A key used to identify directory contents. 42| | DirectoryContents, 43| | 44| | /// A key used to identify filtered directory contents. 45| | FilteredDirectoryContents, 46| | 47| | /// A key used to identify the signature of a complete directory tree. 48| | DirectoryTreeSignature, 49| | 50| | /// A key used to identify the signature of a complete directory tree 51| | /// structure. 52| | DirectoryTreeStructureSignature, 53| | 54| | /// A key used to identify a node. 55| | Node, 56| | 57| | /// A key used to identify a file system stat info. 58| | Stat, 59| | 60| | /// A key used to identify a target. 61| | Target, 62| | 63| | /// An invalid key kind. 64| | Unknown, 65| | }; 66| | static StringRef stringForKind(Kind); 67| | 68| |private: 69| | /// The actual key data. 70| | KeyType key; 71| | 72| |private: 73| 0| BuildKey(const KeyType& key) : key(key) {} 74| 0| BuildKey(char kindCode, StringRef str) { 75| 0| key.reserve(1 + str.size()); 76| 0| key.push_back(kindCode); 77| 0| key.append(str.begin(), str.end()); 78| 0| } 79| | 80| | template 81| 0| BuildKey(char kindCode, StringRef name, const BinaryEncodable& data) { 82| 0| uint32_t nameSize = name.size(); 83| 0| 84| 0| // FIXME: Perhaps should use this encoder for the key itself? Right now 85| 0| // we're manually building the keys and causing some extra memcpy overhead 86| 0| // here. 87| 0| basic::BinaryEncoder encoder; 88| 0| encoder.write(data); 89| 0| uint32_t dataSize = encoder.contents().size(); 90| 0| 91| 0| key.resize(1 + sizeof(uint32_t) + nameSize + dataSize); 92| 0| uint32_t pos = 0; 93| 0| key[pos] = kindCode; pos += 1; 94| 0| memcpy(&key[pos], &nameSize, sizeof(uint32_t)); 95| 0| pos += sizeof(uint32_t); 96| 0| memcpy(&key[pos], name.data(), nameSize); 97| 0| pos += nameSize; 98| 0| memcpy(&key[pos], encoder.contents().data(), dataSize); 99| 0| pos += dataSize; 100| 0| assert(key.size() == pos); 101| 0| (void)pos; 102| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild11buildsystem8BuildKeyC2IN4llvm9StringRefEEEcS4_RKT_ ------------------ | Unexecuted instantiation: _ZN7llbuild11buildsystem8BuildKeyC2INS_5basic10StringListEEEcN4llvm9StringRefERKT_ ------------------ 103| | 104| |public: 105| | /// @name Construction Functions 106| | /// @{ 107| | 108| | /// Create a key for computing a command result. 109| 0| static BuildKey makeCommand(StringRef name) { 110| 0| return BuildKey('C', name); 111| 0| } 112| | 113| | /// Create a key for computing a custom task (manged by a particular command). 114| 0| static BuildKey makeCustomTask(StringRef name, StringRef taskData) { 115| 0| return BuildKey('X', name, taskData); 116| 0| } 117| | 118| | /// Create a key for computing the contents of a directory. 119| 0| static BuildKey makeDirectoryContents(StringRef path) { 120| 0| return BuildKey('D', path); 121| 0| } 122| | 123| | /// Create a key for computing the filtered contents of a directory. 124| | static BuildKey makeFilteredDirectoryContents(StringRef path, 125| 0| const basic::StringList& filters) { 126| 0| return BuildKey('d', path, filters); 127| 0| } 128| | 129| | /// Create a key for computing the contents of a directory. 130| | static BuildKey makeDirectoryTreeSignature(StringRef path, 131| 0| const basic::StringList& filters) { 132| 0| return BuildKey('S', path, filters); 133| 0| } 134| | 135| | /// Create a key for computing the structure of a directory. 136| 0| static BuildKey makeDirectoryTreeStructureSignature(StringRef path) { 137| 0| return BuildKey('s', path); 138| 0| } 139| | 140| | /// Create a key for computing a node result. 141| 0| static BuildKey makeNode(StringRef path) { 142| 0| return BuildKey('N', path); 143| 0| } 144| | 145| | /// Create a key for computing a node result. 146| 0| static BuildKey makeNode(const Node* node) { 147| 0| return BuildKey('N', node->getName()); 148| 0| } 149| | 150| | /// Create a key for computing a file system stat info result. 151| 0| static BuildKey makeStat(StringRef path) { 152| 0| return BuildKey('I', path); 153| 0| } 154| | 155| | /// Createa a key for computing a target. 156| 0| static BuildKey makeTarget(StringRef name) { 157| 0| return BuildKey('T', name); 158| 0| } 159| | 160| | /// @} 161| | /// @name Accessors 162| | /// @{ 163| | 164| 0| const KeyType& getKeyData() const { return key; } 165| | 166| 0| Kind getKind() const { 167| 0| switch (key[0]) { 168| 0| case 'C': return Kind::Command; 169| 0| case 'D': return Kind::DirectoryContents; 170| 0| case 'd': return Kind::FilteredDirectoryContents; 171| 0| case 'N': return Kind::Node; 172| 0| case 'I': return Kind::Stat; 173| 0| case 'S': return Kind::DirectoryTreeSignature; 174| 0| case 's': return Kind::DirectoryTreeStructureSignature; 175| 0| case 'T': return Kind::Target; 176| 0| case 'X': return Kind::CustomTask; 177| 0| default: 178| 0| return Kind::Unknown; 179| 0| } 180| 0| } 181| | 182| 0| bool isCommand() const { return getKind() == Kind::Command; } 183| 0| bool isCustomTask() const { return getKind() == Kind::CustomTask; } 184| 0| bool isDirectoryContents() const { 185| 0| return getKind() == Kind::DirectoryContents; 186| 0| } 187| 0| bool isFilteredDirectoryContents() const { 188| 0| return getKind() == Kind::FilteredDirectoryContents; 189| 0| } 190| 0| bool isDirectoryTreeSignature() const { 191| 0| return getKind() == Kind::DirectoryTreeSignature; 192| 0| } 193| 0| bool isDirectoryTreeStructureSignature() const { 194| 0| return getKind() == Kind::DirectoryTreeStructureSignature; 195| 0| } 196| 0| bool isNode() const { return getKind() == Kind::Node; } 197| 0| bool isStat() const { return getKind() == Kind::Stat; } 198| 0| bool isTarget() const { return getKind() == Kind::Target; } 199| | 200| 0| StringRef getCommandName() const { 201| 0| assert(isCommand()); 202| 0| return StringRef(key.data()+1, key.size()-1); 203| 0| } 204| | 205| 0| StringRef getCustomTaskName() const { 206| 0| assert(isCustomTask()); 207| 0| uint32_t nameSize; 208| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 209| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 210| 0| } 211| | 212| 0| StringRef getCustomTaskData() const { 213| 0| assert(isCustomTask()); 214| 0| uint32_t nameSize; 215| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 216| 0| uint32_t dataSize = key.size() - 1 - sizeof(uint32_t) - nameSize; 217| 0| return StringRef(&key[1 + sizeof(uint32_t) + nameSize], dataSize); 218| 0| } 219| | 220| 0| StringRef getDirectoryPath() const { 221| 0| assert(isDirectoryContents() || isDirectoryTreeStructureSignature()); 222| 0| return StringRef(key.data()+1, key.size()-1); 223| 0| } 224| | 225| 0| StringRef getDirectoryTreeSignaturePath() const { 226| 0| assert(isDirectoryTreeSignature()); 227| 0| uint32_t nameSize; 228| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 229| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 230| 0| } 231| | 232| 0| StringRef getFilteredDirectoryPath() const { 233| 0| assert(isFilteredDirectoryContents()); 234| 0| uint32_t nameSize; 235| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 236| 0| return StringRef(&key[1 + sizeof(uint32_t)], nameSize); 237| 0| } 238| | 239| 0| StringRef getContentExclusionPatterns() const { 240| 0| assert(isDirectoryTreeSignature() || isFilteredDirectoryContents()); 241| 0| uint32_t nameSize; 242| 0| memcpy(&nameSize, &key[1], sizeof(uint32_t)); 243| 0| uint32_t dataSize = key.size() - 1 - sizeof(uint32_t) - nameSize; 244| 0| return StringRef(&key[1 + sizeof(uint32_t) + nameSize], dataSize); 245| 0| } 246| | 247| 0| StringRef getNodeName() const { 248| 0| assert(isNode()); 249| 0| return StringRef(key.data()+1, key.size()-1); 250| 0| } 251| | 252| 0| StringRef getStatName() const { 253| 0| assert(isStat()); 254| 0| return StringRef(key.data()+1, key.size()-1); 255| 0| } 256| | 257| 0| StringRef getTargetName() const { 258| 0| assert(isTarget()); 259| 0| return StringRef(key.data()+1, key.size()-1); 260| 0| } 261| | 262| | /// @} 263| | 264| | /// @name Conversion to core ValueType. 265| | /// @{ 266| | 267| 0| static BuildKey fromData(const KeyType& key) { 268| 0| auto result = BuildKey(key); 269| 0| assert(result.getKind() != Kind::Unknown && "invalid key"); 270| 0| return result; 271| 0| } 272| | 273| 0| const core::KeyType toData() const { return getKeyData(); } 274| | 275| | /// @} 276| | 277| | /// @name Debug Support 278| | /// @{ 279| | 280| | void dump(raw_ostream& OS) const; 281| | 282| | /// @} 283| |}; 284| | 285| |} 286| |} 287| | 288| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildNode.h: 1| |//===- BuildNode.h ----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDNODE_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDNODE_H 15| | 16| |#include "BuildDescription.h" 17| | 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/StringList.h" 20| |#include "llbuild/BuildSystem/BuildFile.h" 21| | 22| |#include "llvm/ADT/StringRef.h" 23| | 24| |namespace llbuild { 25| |namespace basic { 26| | 27| |struct FileInfo; 28| |class FileSystem; 29| | 30| |} 31| | 32| |namespace buildsystem { 33| | 34| |// FIXME: Figure out how this is going to be organized. 35| |class BuildNode : public Node { 36| | /// Whether or not this node represents a full directory. 37| | // 38| | // FIXME: We need a type enumeration here. 39| | bool directory; 40| | 41| | /// Whether or not this node represents the full directory structure. 42| | // 43| | // FIXME: We need a type enumeration here. 44| | bool directoryStructure; 45| | 46| | /// Whether or not this node is "virtual" (i.e., not a filesystem path). 47| | bool virtualNode; 48| | 49| | /// Whether this node represents a "command timestamp". 50| | /// 51| | /// Such nodes should always also be virtual. 52| | bool commandTimestamp; 53| | 54| | /// Whether this node is mutated by the build. 55| | /// 56| | /// This flag cannot currently be honored to provide a strongly consistent 57| | /// build, but it is used to detect when the file system information on a node 58| | /// cannot be safely used to track *output* file state. 59| | bool mutated; 60| | 61| | /// Exclusion filters for directory listings 62| | /// 63| | /// Items matching these filter strings are not considered as part of the 64| | /// signature for directory and directory structure nodes. 65| | basic::StringList exclusionPatterns; 66| | 67| |public: 68| | explicit BuildNode(StringRef name, bool isDirectory, 69| | bool isDirectoryStructure, bool isVirtual, 70| | bool isCommandTimestamp, bool isMutated) 71| | : Node(name), directory(isDirectory), 72| | directoryStructure(isDirectoryStructure), virtualNode(isVirtual), 73| 0| commandTimestamp(isCommandTimestamp), mutated(isMutated) {} 74| | 75| | /// Check whether this is a "virtual" (non-filesystem related) node. 76| 0| bool isVirtual() const { return virtualNode; } 77| | 78| | /// Check whether this node is intended to represent a directory's contents 79| | /// recursively. 80| 0| bool isDirectory() const { return directory; } 81| | 82| | /// Check whether this node is intended to represent a directory's structure 83| | /// recursively. 84| 0| bool isDirectoryStructure() const { return directoryStructure; } 85| | 86| 0| bool isCommandTimestamp() const { return commandTimestamp; } 87| | 88| 0| bool isMutated() const { return mutated; } 89| | 90| 0| const basic::StringList& contentExclusionPatterns() const { 91| 0| return exclusionPatterns; 92| 0| } 93| | 94| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 95| | StringRef value) override; 96| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 97| | ArrayRef values) override; 98| | virtual bool configureAttribute( 99| | const ConfigureContext& ctx, StringRef name, 100| | ArrayRef> values) override; 101| | 102| | basic::FileInfo getFileInfo(basic::FileSystem&) const; 103| | basic::FileInfo getLinkInfo(basic::FileSystem&) const; 104| |}; 105| | 106| | 107| |class StatNode { 108| | std::string name; 109| | 110| |public: 111| 0| explicit StatNode(StringRef name) : name(name) {} 112| | 113| 0| const std::string& getName() { return name; } 114| | 115| | basic::FileInfo getFileInfo(basic::FileSystem&) const; 116| | basic::FileInfo getLinkInfo(basic::FileSystem&) const; 117| |}; 118| | 119| | 120| |} 121| |} 122| | 123| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildSystem.h: 1| |//===- BuildSystem.h --------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDSYSTEM_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDSYSTEM_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/Subprocess.h" 19| | 20| |#include "llvm/ADT/Optional.h" 21| |#include "llvm/ADT/StringRef.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |namespace llbuild { 29| |namespace basic { 30| | class ExecutionQueue; 31| | class FileSystem; 32| |} 33| | 34| |namespace buildsystem { 35| | 36| |class BuildDescription; 37| |class BuildKey; 38| |class BuildValue; 39| |class Command; 40| |class Node; 41| |class Tool; 42| | 43| |bool pathIsPrefixedByPath(std::string path, std::string prefixPath); 44| | 45| |class BuildSystemDelegate { 46| | // DO NOT COPY 47| | BuildSystemDelegate(const BuildSystemDelegate&) 48| | LLBUILD_DELETED_FUNCTION; 49| | void operator=(const BuildSystemDelegate&) 50| | LLBUILD_DELETED_FUNCTION; 51| | BuildSystemDelegate &operator=(BuildSystemDelegate&& rhs) 52| | LLBUILD_DELETED_FUNCTION; 53| | 54| |public: 55| | /// Command status change event kinds. 56| | /// 57| | /// This must be kept in sync with core::Rule::StatusKind. 58| | enum class CommandStatusKind { 59| | /// Indicates the command is being scanned. 60| | IsScanning = 0, 61| | 62| | /// Indicates the command is up-to-date, and doesn't need to run. 63| | IsUpToDate = 1, 64| | 65| | /// Indicates the command was run, and is now complete. 66| | IsComplete = 2 67| | }; 68| | 69| | /// Minimal token object representing the range where a diagnostic occurred. 70| | struct Token { 71| | const char* start; 72| | unsigned length; 73| | }; 74| | 75| |private: 76| | std::string name; 77| | uint32_t version; 78| | 79| |public: 80| | /// Configure the client properties. 81| | /// 82| | /// \param name An identifier for the client system. 83| | /// 84| | /// \param version A version number to identify the schema the client is 85| | /// using, and changes to the schema version number will result in 86| | /// invalidation of all cached build results. NOTE: Currently, this is limited 87| | /// to a 16-bit number as an implementation detail. 88| | BuildSystemDelegate(StringRef name, uint32_t version) 89| 0| : name(name), version(version) {} 90| | virtual ~BuildSystemDelegate(); 91| | 92| | /// Called by the build system to get the client name. 93| 0| StringRef getName() const { return name; } 94| | 95| | /// Called by the build system to get the current client version. 96| 0| uint32_t getVersion() const { return version; } 97| | 98| | /// Called by the build file loader to register the current file contents. 99| | // 100| | // FIXME: This is a total hack, and should be cleaned up. 101| | virtual void setFileContentsBeingParsed(StringRef buffer) = 0; 102| | 103| | /// Called by the build file loader to report an error. 104| | /// 105| | /// \param filename The file the error occurred in. 106| | /// 107| | /// \param at The token at which the error occurred. The token will be null if 108| | /// no location is associated. 109| | /// 110| | /// \param message The diagnostic message. 111| | virtual void error(StringRef filename, 112| | const Token& at, 113| | const Twine& message) = 0; 114| | 115| | /// Called by the build system to get a tool definition. 116| | /// 117| | /// This method is called to look for all tools, even ones which are built-in 118| | /// to the BuildSystem, in order to give the client an opportunity to override 119| | /// built-in tools. 120| | /// 121| | /// \param name The name of the tool to lookup. 122| | /// \returns The tool to use on success, or otherwise nil. 123| | virtual std::unique_ptr lookupTool(StringRef name) = 0; 124| | 125| | /// Called by the build system to get create the object used to dispatch work. 126| | virtual std::unique_ptr createExecutionQueue() = 0; 127| | 128| | /// Called by the build system to report a command failure. 129| | virtual void hadCommandFailure() = 0; 130| | 131| | /// Called by the build system to report that a declared command's state is 132| | /// changing. 133| | // 134| | // FIXME: This API is now gross, there shouldn't be one generic status changed 135| | // method and three individual other state change methods. 136| | virtual void commandStatusChanged(Command*, CommandStatusKind) = 0; 137| | 138| | /// Called by the build system to report that a declared command is preparing 139| | /// to run. 140| | /// 141| | /// This method is called before the command starts, when the system has 142| | /// identified that it will eventually need to run (after all of its inputs 143| | /// have been satisfied). 144| | /// 145| | /// The system guarantees that all such calls will be paired with a 146| | /// corresponding \see commandFinished() call. 147| | /// 148| | /// The system only makes this callback for commands explicitly declared in 149| | /// the build manifest (i.e., not for any work implicitly spawned by those 150| | /// commands). 151| | virtual void commandPreparing(Command*) = 0; 152| | 153| | /// Called by the build system to allow the delegate to skip a command without 154| | /// implicitly skipping its dependents. 155| | /// 156| | /// WARNING: Clients need to take special care when using this. Skipping 157| | /// commands without considering their dependencies or dependents can easily 158| | /// produce an inconsistent build. 159| | /// 160| | /// This method is called before the command starts, when the system has 161| | /// identified that it will eventually need to run (after all of its inputs 162| | /// have been satisfied). 163| | /// 164| | /// The system guarantees that all such calls will be paired with a 165| | /// corresponding \see commandFinished() call. 166| | virtual bool shouldCommandStart(Command*) = 0; 167| | 168| | /// Called by the build system to report that a declared command has started. 169| | /// 170| | /// The system guarantees that all such calls will be paired with a 171| | /// corresponding \see commandFinished() call. 172| | /// 173| | /// The system only makes this callback for commands explicitly declared in 174| | /// the build manifest (i.e., not for any work implicitly spawned by those 175| | /// commands). 176| | virtual void commandStarted(Command*) = 0; 177| | 178| | /// Called to report an error during the execution of a command. 179| | /// 180| | /// \param data - The error message. 181| | virtual void commandHadError(Command*, StringRef data) = 0; 182| | 183| | /// Called to report a note during the execution of a command. 184| | /// 185| | /// \param data - The note message. 186| | virtual void commandHadNote(Command*, StringRef data) = 0; 187| | 188| | /// Called to report a warning during the execution of a command. 189| | /// 190| | /// \param data - The warning message. 191| | virtual void commandHadWarning(Command*, StringRef data) = 0; 192| | 193| | /// Called by the build system to report a command has completed. 194| | /// 195| | /// \param status - The status of command (e.g. success, failure, etc). 196| | virtual void commandFinished(Command*, basic::ProcessStatus status) = 0; 197| | 198| | /// Called by the build system to report a command could not build due to 199| | /// missing inputs. 200| | virtual void commandCannotBuildOutputDueToMissingInputs(Command*, 201| | Node* output, SmallPtrSet inputs) = 0; 202| | 203| | /// Called by the build system to report a node could not be built 204| | /// because multiple commands are producing it. 205| | virtual void cannotBuildNodeDueToMultipleProducers(Node* output, 206| | std::vector) = 0; 207| |}; 208| | 209| |/// The BuildSystem class is used to perform builds using the native build 210| |/// system. 211| |class BuildSystem { 212| |private: 213| | void *impl; 214| | 215| | // Copying is disabled. 216| | BuildSystem(const BuildSystem&) LLBUILD_DELETED_FUNCTION; 217| | void operator=(const BuildSystem&) LLBUILD_DELETED_FUNCTION; 218| | 219| |public: 220| | /// Create a build system with the given delegate. 221| | BuildSystem(BuildSystemDelegate& delegate, std::unique_ptr fileSystem); 222| | ~BuildSystem(); 223| | 224| | /// Return the delegate the engine was configured with. 225| | BuildSystemDelegate& getDelegate(); 226| | 227| | /// Get the file system to use for access. 228| | basic::FileSystem& getFileSystem(); 229| | 230| | /// @name Client API 231| | /// @{ 232| | 233| | /// Load the build description from a file. 234| | /// 235| | /// \returns True on success. 236| | bool loadDescription(StringRef mainFilename); 237| | 238| | /// Load an explicit build description. from a file. 239| | void loadDescription(std::unique_ptr description); 240| | 241| | /// Attach (or create) the database at the given path. 242| | /// 243| | /// \returns True on success. 244| | bool attachDB(StringRef path, std::string* error_out); 245| | 246| | /// Enable low-level engine tracing into the given output file. 247| | /// 248| | /// \returns True on success. 249| | bool enableTracing(StringRef path, std::string* error_out); 250| | 251| | /// Build the named target. 252| | /// 253| | /// A build description *must* have been loaded before calling this method. 254| | /// 255| | /// \returns True on success, or false if the build was aborted (for example, 256| | /// if a cycle was discovered). 257| | bool build(StringRef target); 258| | 259| | /// Build a specific key directly. 260| | /// 261| | /// A build description *must* have been loaded before calling this method. 262| | /// 263| | /// \returns The result of computing the value, or nil if the build failed. 264| | llvm::Optional build(BuildKey target); 265| | 266| | /// Reset mutable build state before a new build operation. 267| | void resetForBuild(); 268| | 269| | /// Cancel the current build. 270| | void cancel(); 271| | 272| | /// @} 273| |}; 274| | 275| |} 276| |} 277| | 278| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildSystemFrontend.h: 1| |//===- BuildSystemFrontend.h ------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDSYSTEMFRONTEND_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDSYSTEMFRONTEND_H 15| | 16| |#include "llbuild/Basic/ExecutionQueue.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/BuildSystem/BuildSystem.h" 19| |#include "llbuild/BuildSystem/BuildNode.h" 20| |#include "llbuild/Core/BuildEngine.h" 21| | 22| |#include "llvm/ADT/ArrayRef.h" 23| |#include "llvm/ADT/StringRef.h" 24| |#include "llvm/ADT/Optional.h" 25| | 26| |#include 27| |#include 28| |#include 29| | 30| |namespace llvm { 31| | 32| |class SourceMgr; 33| | 34| |} 35| | 36| |namespace llbuild { 37| |namespace basic { 38| | 39| |class FileSystem; 40| | 41| |} 42| | 43| |namespace buildsystem { 44| | 45| |class BuildSystemFrontendDelegate; 46| |class BuildSystemInvocation; 47| |enum class CommandResult; 48| | 49| |/// This provides a standard "frontend" to the build system features, for use in 50| |/// building bespoke build systems that can still take advantage of desirable 51| |/// shared behavior. 52| |/// 53| |/// The frontend glues together various parts of the build system functionality 54| |/// to provide: 55| |/// o Support for common command line options. 56| |/// o Support for parallel, persistent builds. 57| |/// o Support for command line diagnostics and status reporting. 58| |/// 59| |/// NOTE: This class is *NOT* thread safe. 60| |class BuildSystemFrontend { 61| | BuildSystemFrontendDelegate& delegate; 62| | const BuildSystemInvocation& invocation; 63| | std::unique_ptr fileSystem; 64| | llvm::Optional buildSystem; 65| | 66| |private: 67| | 68| | bool setupBuild(); 69| | 70| |public: 71| | BuildSystemFrontend(BuildSystemFrontendDelegate& delegate, 72| | const BuildSystemInvocation& invocation, 73| | std::unique_ptr fileSystem); 74| | 75| | /// @name Accessors 76| | /// @{ 77| | 78| 0| BuildSystemFrontendDelegate& getDelegate() { return delegate; } 79| 0| const BuildSystemFrontendDelegate& getDelegate() const { return delegate; } 80| | 81| 0| const BuildSystemInvocation& getInvocation() { return invocation; } 82| | 83| | /// @} 84| | 85| | /// @name Client API 86| | /// @{ 87| | 88| | /// Initialize the build system. 89| | /// 90| | /// This will load the manifest and apply all of the command line options to 91| | /// construct an appropriate underlying `BuildSystem` for use by subsequent 92| | /// build calls. 93| | /// 94| | /// \returns True on success, or false if there were errors. If initialization 95| | /// fails, the frontend is in an indeterminant state and should not be reused. 96| | bool initialize(); 97| | 98| | /// Build the named target using the specified invocation parameters. 99| | /// 100| | /// \returns True on success, or false if there were errors. 101| | bool build(StringRef targetToBuild); 102| | 103| | /// Build a single node using the specified invocation parameters. 104| | /// 105| | /// \returns True on success, or false if there were errors. 106| | bool buildNode(StringRef nodeToBuild); 107| | 108| | /// @} 109| |}; 110| | 111| |/// The frontend-specific delegate, which provides some shared behaviors. 112| |class BuildSystemFrontendDelegate : public BuildSystemDelegate { 113| | friend class BuildSystemFrontend; 114| | 115| |public: 116| | /// Handle used to communicate information about a launched process. 117| | struct ProcessHandle { 118| | /// Opaque ID. 119| | uintptr_t id; 120| | }; 121| | 122| |private: 123| | void* impl; 124| | 125| | /// Default implementation, cannot be overriden by subclasses. 126| | virtual void setFileContentsBeingParsed(StringRef buffer) override; 127| | 128| |public: 129| | /// Create a frontend delegate. 130| | /// 131| | /// \param sourceMgr The source manager to use for reporting diagnostics. 132| | /// \param invocation The invocation parameters. 133| | /// \param name The name of build system client. 134| | /// \param version The version of the build system client. 135| | BuildSystemFrontendDelegate(llvm::SourceMgr& sourceMgr, 136| | const BuildSystemInvocation& invocation, 137| | StringRef name, 138| | uint32_t version); 139| | virtual ~BuildSystemFrontendDelegate(); 140| | 141| | /// Called by the build system to get a tool definition, must be provided by 142| | /// subclasses. 143| | virtual std::unique_ptr lookupTool(StringRef name) override = 0; 144| | 145| | /// Provides an appropriate execution queue based on the invocation options. 146| | virtual std::unique_ptr createExecutionQueue() override; 147| | 148| | /// Cancels the current build. 149| | virtual void cancel(); 150| | 151| | /// Reset mutable build state before a new build operation. 152| | void resetForBuild(); 153| | 154| | /// Provides a default handler. 155| | /// 156| | /// Subclass should call this method if overridden. 157| | virtual void hadCommandFailure() override; 158| | 159| | /// @name Frontend-specific APIs 160| | /// @{ 161| | 162| | /// Report a non-file specific error message. 163| | void error(const Twine& message); 164| | 165| | /// Provides a default error implementation which will delegate to the 166| | /// provided source manager. 167| | virtual void error(StringRef filename, const Token& at, 168| | const Twine& message) override; 169| | 170| | /// @} 171| | 172| | /// @name Status Reporting APIs 173| | /// 174| | /// The frontend provides default implementations of these methods which 175| | /// report the status to stdout. Clients should override if they wish to 176| | /// direct the status elsewhere. 177| | /// 178| | /// @{ 179| | 180| | /// Called by the build system to report that a declared command's state is 181| | /// changing. 182| | virtual void commandStatusChanged(Command*, CommandStatusKind) override; 183| | 184| | /// Called by the build system to report that a declared command is preparing 185| | /// to run. 186| | /// 187| | /// The system guarantees that all such calls will be paired with a 188| | /// corresponding \see commandFinished() call. 189| | virtual void commandPreparing(Command*) override; 190| | 191| | /// Called by the build system to allow the delegate to skip a command without 192| | /// implicitly skipping its dependents. 193| | /// 194| | /// WARNING: Clients need to take special care when using this. Skipping 195| | /// commands without considering their dependencies or dependents can easily 196| | /// produce an inconsistent build. 197| | /// 198| | /// This method is called before the command starts, when the system has 199| | /// identified that it will eventually need to run (after all of its inputs 200| | /// have been satisfied). 201| | /// 202| | /// The system guarantees that all such calls will be paired with a 203| | /// corresponding \see commandFinished() call. 204| | virtual bool shouldCommandStart(Command*) override; 205| | 206| | /// Called by the build system to report that a declared command has started. 207| | /// 208| | /// The system guarantees that all such calls will be paired with a 209| | /// corresponding \see commandFinished() call. 210| | virtual void commandStarted(Command*) override; 211| | 212| | /// Called to report an error during the execution of a command. 213| | /// 214| | /// \param data - The error message. 215| | virtual void commandHadError(Command*, StringRef data) override; 216| | 217| | /// Called to report a note during the execution of a command. 218| | /// 219| | /// \param data - The note message. 220| | virtual void commandHadNote(Command*, StringRef data) override; 221| | 222| | /// Called to report a warning during the execution of a command. 223| | /// 224| | /// \param data - The warning message. 225| | virtual void commandHadWarning(Command*, StringRef data) override; 226| | 227| | /// Called by the build system to report a command has completed. 228| | /// 229| | /// \param result - The result of command (e.g. success, failure, etc). 230| | virtual void commandFinished(Command*, basic::ProcessStatus result) override; 231| | 232| | /// Called by the build system to report a command could not build due to 233| | /// missing inputs. 234| | virtual void commandCannotBuildOutputDueToMissingInputs(Command*, 235| | Node* output, SmallPtrSet inputs) override; 236| | 237| | /// Called by the build system to report a node could not be built 238| | /// because multiple commands are producing it. 239| | virtual void cannotBuildNodeDueToMultipleProducers(Node* output, 240| | std::vector) override; 241| | 242| | /// Called when a command's job has been started. 243| | /// 244| | /// The system guarantees that any commandStart() call will be paired with 245| | /// exactly one \see commandFinished() call. 246| | // 247| | // FIXME: We may eventually want to allow the individual job to provide some 248| | // additional context here, for complex commands. 249| | // 250| | // FIXME: Design a way to communicate the "lane" here, for use in "super 251| | // console" like UIs. 252| | virtual void commandJobStarted(Command*); 253| | 254| | /// Called when a command's job has been finished. 255| | virtual void commandJobFinished(Command*); 256| | 257| | /// Called when a command's job has started executing an external process. 258| | /// 259| | /// The system guarantees that any commandProcessStarted() call will be paired 260| | /// with exactly one \see commandProcessFinished() call. 261| | /// 262| | /// \param handle - A unique handle used in subsequent delegate calls to 263| | /// identify the process. This handle should only be used to associate 264| | /// different status calls relating to the same process. It is only guaranteed 265| | /// to be unique from when it has been provided here to when it has been 266| | /// provided to the \see commandProcessFinished() call. 267| | virtual void commandProcessStarted(Command*, ProcessHandle handle); 268| | 269| | /// Called to report an error in the management of a command process. 270| | /// 271| | /// \param handle - The process handle. 272| | /// \param message - The error message. 273| | // 274| | // FIXME: Need to move to more structured error handling. 275| | virtual void commandProcessHadError(Command*, ProcessHandle handle, 276| | const Twine& message); 277| | 278| | /// Called to report a command processes' (merged) standard output and error. 279| | /// 280| | /// \param handle - The process handle. 281| | /// \param data - The process output. 282| | virtual void commandProcessHadOutput(Command*, ProcessHandle handle, 283| | StringRef data); 284| | 285| | /// Called when a command's job has finished executing an external process. 286| | /// 287| | /// \param handle - The handle used to identify the process. This handle will 288| | /// become invalid as soon as the client returns from this API call. 289| | /// 290| | /// \param result - Whether the process suceeded, failed or was cancelled. 291| | // 292| | // FIXME: Need to include additional information on the status here, e.g., the 293| | // signal status, and the process output (if buffering). 294| | virtual void commandProcessFinished(Command*, ProcessHandle handle, 295| | const basic::ProcessResult& result); 296| | 297| | /// Called when a cycle is detected by the build engine and it cannot make 298| | /// forward progress. 299| | /// 300| | /// \param items The ordered list of items comprising the cycle, starting from 301| | /// the node which was requested to build and ending with the first node in 302| | /// the cycle (i.e., the node participating in the cycle will appear twice). 303| | virtual void cycleDetected(const std::vector& items) = 0; 304| | 305| | /// Called when a cycle is detected by the build engine to check if it should 306| | /// attempt to resolve the cycle and continue 307| | /// 308| | /// \param items The ordered list of items comprising the cycle, starting from 309| | /// the node which was requested to build and ending with the first node in 310| | /// the cycle (i.e., the node participating in the cycle will appear twice). 311| | /// \param candidateRule The rule the engine will use to attempt to break the 312| | /// cycle. 313| | /// \param action The action the engine will take on the candidateRule. 314| | /// \returns True if the engine should attempt to resolve the cycle, false 315| | /// otherwise. Resolution is attempted by either forcing items to be built, or 316| | /// supplying a previously built result to a node in the cycle. The latter 317| | /// action may yield unexpected results and thus this should be opted into 318| | /// with care. 319| | virtual bool shouldResolveCycle(const std::vector& items, 320| | core::Rule* candidateRule, 321| | core::Rule::CycleAction action); 322| | /// @} 323| | 324| | /// @name Accessors 325| | /// @{ 326| | 327| | BuildSystemFrontend& getFrontend(); 328| | 329| | llvm::SourceMgr& getSourceMgr(); 330| | 331| | /// Get the number of reported errors. 332| | unsigned getNumErrors(); 333| | 334| | /// Get the number of failed commands. 335| | unsigned getNumFailedCommands(); 336| | 337| | /// @} 338| |}; 339| | 340| | 341| |/// This class wraps the common options which are used by the frontend. 342| |class BuildSystemInvocation { 343| |public: 344| | /// Whether the command usage should be printed. 345| | bool showUsage = false; 346| | 347| | /// Whether the command version should be printed. 348| | bool showVersion = false; 349| | 350| | /// Whether to show verbose output. 351| | bool showVerboseStatus = false; 352| | 353| | /// Whether to use a serial build. 354| | bool useSerialBuild = false; 355| | 356| | /// The path of the database file to use, if any. 357| | std::string dbPath = "build.db"; 358| | 359| | /// The path of a directory to change into before anything else, if any. 360| | std::string chdirPath = ""; 361| | 362| | /// The path of the build file to use. 363| | std::string buildFilePath = "build.llbuild"; 364| | 365| | /// The path of the build trace output file to use, if any. 366| | std::string traceFilePath = ""; 367| | 368| | basic::SchedulerAlgorithm schedulerAlgorithm = 369| | basic::SchedulerAlgorithm::NamePriority; 370| | 371| | uint32_t schedulerLanes = 0; 372| | 373| | /// The base environment to use when executing subprocesses. 374| | /// 375| | /// The format is expected to match that of `::main()`, i.e. a null-terminated 376| | /// array of pointers to null terminated C strings. 377| | /// 378| | /// If empty, the environment of the calling process will be used. 379| | const char* const* environment = nullptr; 380| | 381| | /// The positional arguments. 382| | std::vector positionalArgs; 383| | 384| | /// Whether there were any parsing errors. 385| | bool hadErrors = false; 386| | 387| |public: 388| | /// Get the appropriate "usage" text to use for the built in arguments. 389| | static void getUsage(int optionWidth, raw_ostream& os); 390| | 391| | /// Parse the invocation parameters from the given arguments. 392| | /// 393| | /// \param sourceMgr The source manager to use for diagnostics. 394| | void parse(ArrayRef args, llvm::SourceMgr& sourceMgr); 395| | 396| | /// Provides a default string representation for a cycle detected by the build engine. 397| | static std::string formatDetectedCycle(const std::vector& cycle); 398| |}; 399| | 400| |} 401| |} 402| | 403| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/BuildValue.h: 1| |//===- BuildValue.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_BUILDVALUE_H 14| |#define LLBUILD_BUILDSYSTEM_BUILDVALUE_H 15| | 16| |#include "llbuild/Core/BuildEngine.h" 17| |#include "llbuild/Basic/BinaryCoding.h" 18| |#include "llbuild/Basic/Compiler.h" 19| |#include "llbuild/Basic/FileInfo.h" 20| |#include "llbuild/Basic/Hashing.h" 21| |#include "llbuild/Basic/LLVM.h" 22| |#include "llbuild/Basic/StringList.h" 23| | 24| |#include "llvm/ADT/ArrayRef.h" 25| |#include "llvm/ADT/SmallVector.h" 26| |#include "llvm/ADT/StringRef.h" 27| |#include "llvm/Support/raw_ostream.h" 28| | 29| |#include 30| | 31| |namespace llvm { 32| |class raw_ostream; 33| |} 34| | 35| |namespace llbuild { 36| |namespace buildsystem { 37| | 38| |/// The BuildValue encodes the value space used by the BuildSystem when using 39| |/// the core BuildEngine. 40| |class BuildValue { 41| | using FileInfo = basic::FileInfo; 42| | 43| | enum class Kind : uint32_t { 44| | /// An invalid value, for sentinel purposes. 45| | Invalid = 0, 46| | 47| | /// A value produced by a virtual input. 48| | VirtualInput, 49| | 50| | /// A value produced by an existing input file. 51| | ExistingInput, 52| | 53| | /// A value produced by a missing input file. 54| | MissingInput, 55| | 56| | /// The contents of a directory. 57| | DirectoryContents, 58| | 59| | /// The signature of a directories contents. 60| | DirectoryTreeSignature, 61| | 62| | /// The signature of a directories structure. 63| | DirectoryTreeStructureSignature, 64| | 65| | /// A value produced by stale file removal. 66| | StaleFileRemoval, 67| | 68| | /// A value produced by a command which succeeded, but whose output was 69| | /// missing. 70| | MissingOutput, 71| | 72| | /// A value for a produced output whose command failed or was cancelled. 73| | FailedInput, 74| | 75| | /// A value produced by a successful command. 76| | SuccessfulCommand, 77| | 78| | /// A value produced by a failing command. 79| | FailedCommand, 80| | 81| | /// A value produced by a command which was skipped because one of its 82| | /// dependencies failed. 83| | PropagatedFailureCommand, 84| | 85| | /// A value produced by a command which was cancelled. 86| | CancelledCommand, 87| | 88| | /// A value produced by a command which was skipped. 89| | SkippedCommand, 90| | 91| | /// Sentinel value representing the result of "building" a top-level target. 92| | Target, 93| | 94| | /// The filtered contents of a directory. 95| | FilteredDirectoryContents, 96| | 97| | }; 98| | static StringRef stringForKind(Kind); 99| | 100| | friend struct basic::BinaryCodingTraits; 101| | 102| | /// The kind of value. 103| | Kind kind = Kind::Invalid; 104| | 105| | /// The number of attached output infos. 106| | uint32_t numOutputInfos = 0; 107| | 108| | /// The command hash, for successful commands. 109| | basic::CommandSignature commandSignature; 110| | 111| | union { 112| | /// The file info for the rule output, for existing inputs, successful 113| | /// commands with a single output, and directory contents. 114| | FileInfo asOutputInfo; 115| | 116| | /// The file info for successful commands with multiple outputs. 117| | FileInfo* asOutputInfos; 118| | } valueData = { {} }; 119| | 120| | /// String list storage. 121| | // 122| | // FIXME: We are currently paying the cost for carrying this around on every 123| | // value, which is very wasteful. We need to redesign this type to be 124| | // customized to each exact value. 125| | basic::StringList stringValues; 126| | 127| 0| bool kindHasCommandSignature() const { 128| 0| return isSuccessfulCommand() || 129| 0| isDirectoryTreeSignature() || isDirectoryTreeStructureSignature(); 130| 0| } 131| | 132| 0| bool kindHasStringList() const { 133| 0| return isDirectoryContents() || isFilteredDirectoryContents() || isStaleFileRemoval(); 134| 0| } 135| | 136| 0| bool kindHasOutputInfo() const { 137| 0| return isExistingInput() || isSuccessfulCommand() || isDirectoryContents(); 138| 0| } 139| | 140| |private: 141| | // Copying is disabled. 142| | BuildValue(const BuildValue&) LLBUILD_DELETED_FUNCTION; 143| | void operator=(const BuildValue&) LLBUILD_DELETED_FUNCTION; 144| | 145| 0| BuildValue() {} 146| | BuildValue(basic::BinaryDecoder& decoder); 147| | BuildValue(Kind kind, basic::CommandSignature commandSignature = basic::CommandSignature()) 148| 0| : kind(kind), commandSignature(commandSignature) { } 149| | BuildValue(Kind kind, ArrayRef outputInfos, 150| | basic::CommandSignature commandSignature = basic::CommandSignature()) 151| | : kind(kind), numOutputInfos(outputInfos.size()), 152| | commandSignature(commandSignature) 153| 0| { 154| 0| assert(numOutputInfos >= 1); 155| 0| if (numOutputInfos == 1) { 156| 0| valueData.asOutputInfo = outputInfos[0]; 157| 0| } else { 158| 0| valueData.asOutputInfos = new FileInfo[numOutputInfos]; 159| 0| for (uint32_t i = 0; i != numOutputInfos; ++i) { 160| 0| valueData.asOutputInfos[i] = outputInfos[i]; 161| 0| } 162| 0| } 163| 0| } 164| | 165| | /// Create a build value containing directory contents. 166| | BuildValue(Kind kind, FileInfo directoryInfo, ArrayRef values) 167| | : BuildValue(kind, directoryInfo) 168| 0| { 169| 0| assert(kindHasStringList()); 170| 0| 171| 0| stringValues = basic::StringList(values); 172| 0| } ------------------ | Unexecuted instantiation: _ZN7llbuild11buildsystem10BuildValueC1ENS1_4KindENS_5basic8FileInfoEN4llvm8ArrayRefINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEE ------------------ | Unexecuted instantiation: _ZN7llbuild11buildsystem10BuildValueC2ENS1_4KindENS_5basic8FileInfoEN4llvm8ArrayRefINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEE ------------------ 173| | 174| | BuildValue(Kind kind, ArrayRef values) 175| 0| : kind(kind), stringValues(values) { 176| 0| assert(kindHasStringList()); 177| 0| } 178| | 179| 0| std::vector getStringListValues() const { 180| 0| assert(kindHasStringList()); 181| 0| return stringValues.getValues(); 182| 0| } 183| | 184| 0| FileInfo& getNthOutputInfo(unsigned n) { 185| 0| assert(kindHasOutputInfo() && "invalid call for value kind"); 186| 0| assert(n < getNumOutputs()); 187| 0| if (hasMultipleOutputs()) { 188| 0| return valueData.asOutputInfos[n]; 189| 0| } else { 190| 0| assert(n == 0); 191| 0| return valueData.asOutputInfo; 192| 0| } 193| 0| } 194| | 195| |public: 196| | // BuildValues can only be moved, not copied. 197| 0| BuildValue(BuildValue&& rhs) : numOutputInfos(rhs.numOutputInfos) { 198| 0| kind = rhs.kind; 199| 0| numOutputInfos = rhs.numOutputInfos; 200| 0| commandSignature = rhs.commandSignature; 201| 0| if (rhs.hasMultipleOutputs()) { 202| 0| valueData.asOutputInfos = rhs.valueData.asOutputInfos; 203| 0| rhs.valueData.asOutputInfos = nullptr; 204| 0| } else { 205| 0| valueData.asOutputInfo = rhs.valueData.asOutputInfo; 206| 0| } 207| 0| if (rhs.kindHasStringList()) { 208| 0| stringValues = std::move(rhs.stringValues); 209| 0| } 210| 0| } 211| 0| BuildValue& operator=(BuildValue&& rhs) { 212| 0| if (this != &rhs) { 213| 0| // Release our resources. 214| 0| if (hasMultipleOutputs()) 215| 0| delete[] valueData.asOutputInfos; 216| 0| 217| 0| // Move the data. 218| 0| kind = rhs.kind; 219| 0| numOutputInfos = rhs.numOutputInfos; 220| 0| commandSignature = rhs.commandSignature; 221| 0| if (rhs.hasMultipleOutputs()) { 222| 0| valueData.asOutputInfos = rhs.valueData.asOutputInfos; 223| 0| rhs.valueData.asOutputInfos = nullptr; 224| 0| } else { 225| 0| valueData.asOutputInfo = rhs.valueData.asOutputInfo; 226| 0| } 227| 0| if (rhs.kindHasStringList()) { 228| 0| stringValues = std::move(rhs.stringValues); 229| 0| } 230| 0| } 231| 0| return *this; 232| 0| } 233| 0| ~BuildValue() { 234| 0| if (hasMultipleOutputs()) { 235| 0| delete[] valueData.asOutputInfos; 236| 0| } 237| 0| } 238| | 239| | /// @name Construction Functions 240| | /// @{ 241| | 242| 0| static BuildValue makeInvalid() { 243| 0| return BuildValue(Kind::Invalid); 244| 0| } 245| 0| static BuildValue makeVirtualInput() { 246| 0| return BuildValue(Kind::VirtualInput); 247| 0| } 248| 0| static BuildValue makeExistingInput(FileInfo outputInfo) { 249| 0| assert(!outputInfo.isMissing()); 250| 0| return BuildValue(Kind::ExistingInput, outputInfo); 251| 0| } 252| 0| static BuildValue makeMissingInput() { 253| 0| return BuildValue(Kind::MissingInput); 254| 0| } 255| | static BuildValue makeDirectoryContents(FileInfo directoryInfo, 256| 0| ArrayRef values) { 257| 0| return BuildValue(Kind::DirectoryContents, directoryInfo, values); 258| 0| } 259| 0| static BuildValue makeDirectoryTreeSignature(basic::CommandSignature signature) { 260| 0| return BuildValue(Kind::DirectoryTreeSignature, signature); 261| 0| } 262| 0| static BuildValue makeDirectoryTreeStructureSignature(basic::CommandSignature signature) { 263| 0| return BuildValue(Kind::DirectoryTreeStructureSignature, signature); 264| 0| } 265| 0| static BuildValue makeMissingOutput() { 266| 0| return BuildValue(Kind::MissingOutput); 267| 0| } 268| 0| static BuildValue makeFailedInput() { 269| 0| return BuildValue(Kind::FailedInput); 270| 0| } 271| | static BuildValue makeSuccessfulCommand( 272| 0| ArrayRef outputInfos, basic::CommandSignature commandSignature) { 273| 0| return BuildValue(Kind::SuccessfulCommand, outputInfos, commandSignature); 274| 0| } 275| 0| static BuildValue makeFailedCommand() { 276| 0| return BuildValue(Kind::FailedCommand); 277| 0| } 278| 0| static BuildValue makePropagatedFailureCommand() { 279| 0| return BuildValue(Kind::PropagatedFailureCommand); 280| 0| } 281| 0| static BuildValue makeCancelledCommand() { 282| 0| return BuildValue(Kind::CancelledCommand); 283| 0| } 284| 0| static BuildValue makeSkippedCommand() { 285| 0| return BuildValue(Kind::SkippedCommand); 286| 0| } 287| 0| static BuildValue makeTarget() { 288| 0| return BuildValue(Kind::Target); 289| 0| } 290| 0| static BuildValue makeStaleFileRemoval(ArrayRef values) { 291| 0| return BuildValue(Kind::StaleFileRemoval, values); 292| 0| } 293| 0| static BuildValue makeFilteredDirectoryContents(ArrayRef values) { 294| 0| return BuildValue(Kind::FilteredDirectoryContents, values); 295| 0| } 296| | 297| | /// @} 298| | 299| | /// @name Accessors 300| | /// @{ 301| | 302| 0| bool isInvalid() const { return kind == Kind::Invalid; } 303| 0| bool isVirtualInput() const { return kind == Kind::VirtualInput; } 304| 0| bool isExistingInput() const { return kind == Kind::ExistingInput; } 305| 0| bool isMissingInput() const { return kind == Kind::MissingInput; } 306| | 307| 0| bool isDirectoryContents() const { return kind == Kind::DirectoryContents; } 308| 0| bool isDirectoryTreeSignature() const { 309| 0| return kind == Kind::DirectoryTreeSignature; 310| 0| } 311| 0| bool isDirectoryTreeStructureSignature() const { 312| 0| return kind == Kind::DirectoryTreeStructureSignature; 313| 0| } 314| 0| bool isStaleFileRemoval() const { return kind == Kind::StaleFileRemoval; } 315| | 316| 0| bool isMissingOutput() const { return kind == Kind::MissingOutput; } 317| 0| bool isFailedInput() const { return kind == Kind::FailedInput; } 318| 0| bool isSuccessfulCommand() const {return kind == Kind::SuccessfulCommand; } 319| 0| bool isFailedCommand() const { return kind == Kind::FailedCommand; } 320| 0| bool isPropagatedFailureCommand() const { 321| 0| return kind == Kind::PropagatedFailureCommand; 322| 0| } 323| 0| bool isCancelledCommand() const { return kind == Kind::CancelledCommand; } 324| 0| bool isSkippedCommand() const { return kind == Kind::SkippedCommand; } 325| 0| bool isTarget() const { return kind == Kind::Target; } 326| 0| bool isFilteredDirectoryContents() const { 327| 0| return kind == Kind::FilteredDirectoryContents; 328| 0| } 329| | 330| 0| std::vector getDirectoryContents() const { 331| 0| assert((isDirectoryContents() || isFilteredDirectoryContents()) && "invalid call for value kind"); 332| 0| return getStringListValues(); 333| 0| } 334| | 335| 0| std::vector getStaleFileList() const { 336| 0| assert(isStaleFileRemoval() && "invalid call for value kind"); 337| 0| return getStringListValues(); 338| 0| } 339| | 340| 0| basic::CommandSignature getDirectoryTreeSignature() const { 341| 0| assert(isDirectoryTreeSignature() && "invalid call for value kind"); 342| 0| return commandSignature; 343| 0| } 344| | 345| 0| basic::CommandSignature getDirectoryTreeStructureSignature() const { 346| 0| assert(isDirectoryTreeStructureSignature() && 347| 0| "invalid call for value kind"); 348| 0| return commandSignature; 349| 0| } 350| | 351| 0| bool hasMultipleOutputs() const { 352| 0| return numOutputInfos > 1; 353| 0| } 354| | 355| 0| unsigned getNumOutputs() const { 356| 0| assert(kindHasOutputInfo() && "invalid call for value kind"); 357| 0| return numOutputInfos; 358| 0| } 359| | 360| 0| const FileInfo& getOutputInfo() const { 361| 0| assert(kindHasOutputInfo() && "invalid call for value kind"); 362| 0| assert(!hasMultipleOutputs() && 363| 0| "invalid call on result with multiple outputs"); 364| 0| return valueData.asOutputInfo; 365| 0| } 366| | 367| 0| const FileInfo& getNthOutputInfo(unsigned n) const { 368| 0| assert(kindHasOutputInfo() && "invalid call for value kind"); 369| 0| assert(n < getNumOutputs()); 370| 0| if (hasMultipleOutputs()) { 371| 0| return valueData.asOutputInfos[n]; 372| 0| } else { 373| 0| assert(n == 0); 374| 0| return valueData.asOutputInfo; 375| 0| } 376| 0| } 377| | 378| 0| basic::CommandSignature getCommandSignature() const { 379| 0| assert(isSuccessfulCommand() && "invalid call for value kind"); 380| 0| return commandSignature; 381| 0| } 382| | 383| | /// @} 384| | 385| | /// @name Conversion to core ValueType. 386| | /// @{ 387| | 388| 0| static BuildValue fromData(const core::ValueType& value) { 389| 0| basic::BinaryDecoder decoder(StringRef((char*)value.data(), value.size())); 390| 0| return BuildValue(decoder); 391| 0| } 392| | core::ValueType toData() const; 393| | 394| | /// @} 395| | 396| | /// @name Debug Support 397| | /// @{ 398| | 399| | void dump(raw_ostream& OS) const; 400| | 401| | /// @} 402| |}; 403| | 404| |} 405| | 406| |template<> 407| |struct basic::BinaryCodingTraits { 408| | typedef buildsystem::BuildValue::Kind Kind; 409| | 410| 0| static inline void encode(const Kind& value, BinaryEncoder& coder) { 411| 0| uint8_t tmp = uint8_t(value); 412| 0| assert(value == Kind(tmp)); 413| 0| coder.write(tmp); 414| 0| } 415| 0| static inline void decode(Kind& value, BinaryDecoder& coder) { 416| 0| uint8_t tmp; 417| 0| coder.read(tmp); 418| 0| value = Kind(tmp); 419| 0| } 420| |}; 421| | 422| 0|inline buildsystem::BuildValue::BuildValue(basic::BinaryDecoder& coder) { 423| 0| // Handle empty decode requests. 424| 0| if (coder.isEmpty()) { 425| 0| kind = BuildValue::Kind::Invalid; 426| 0| return; 427| 0| } 428| 0| 429| 0| coder.read(kind); 430| 0| if (kindHasCommandSignature()) 431| 0| coder.read(commandSignature); 432| 0| if (kindHasOutputInfo()) { 433| 0| coder.read(numOutputInfos); 434| 0| if (numOutputInfos > 1) { 435| 0| valueData.asOutputInfos = new FileInfo[numOutputInfos]; 436| 0| } 437| 0| for (uint32_t i = 0; i != numOutputInfos; ++i) { 438| 0| coder.read(getNthOutputInfo(i)); 439| 0| } 440| 0| } 441| 0| if (kindHasStringList()) { 442| 0| stringValues = basic::StringList(coder); 443| 0| } 444| 0| coder.finish(); 445| 0|} 446| | 447| 0|inline core::ValueType buildsystem::BuildValue::toData() const { 448| 0| basic::BinaryEncoder coder; 449| 0| coder.write(kind); 450| 0| if (kindHasCommandSignature()) 451| 0| coder.write(commandSignature); 452| 0| if (kindHasOutputInfo()) { 453| 0| coder.write(numOutputInfos); 454| 0| for (uint32_t i = 0; i != numOutputInfos; ++i) { 455| 0| coder.write(getNthOutputInfo(i)); 456| 0| } 457| 0| } 458| 0| if (kindHasStringList()) { 459| 0| stringValues.encode(coder); 460| 0| } 461| 0| return coder.contents(); 462| 0|} 463| | 464| |} 465| | 466| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/BuildSystem/include/llbuild/BuildSystem/ExternalCommand.h: 1| |//===- ExternalCommand.h ----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_EXTERNALCOMMAND_H 14| |#define LLBUILD_BUILDSYSTEM_EXTERNALCOMMAND_H 15| | 16| |#include "llbuild/BuildSystem/BuildDescription.h" 17| |#include "llbuild/BuildSystem/BuildSystem.h" 18| |#include "llbuild/BuildSystem/BuildValue.h" 19| | 20| |#include "llvm/ADT/Optional.h" 21| |#include "llvm/ADT/SmallPtrSet.h" 22| |#include "llvm/ADT/StringRef.h" 23| | 24| |#include 25| |#include 26| | 27| |namespace llbuild { 28| | namespace basic { 29| | class QueueJobContext; 30| | } 31| | namespace core { 32| | class Task; 33| | } 34| | 35| |namespace buildsystem { 36| | 37| |class BuildNode; 38| |class BuildSystem; 39| | 40| |/// This is a base class for defining commands which are run externally to the 41| |/// build system and interact using files. It defines common base behaviors 42| |/// which make sense for all such tools. 43| |class ExternalCommand : public Command { 44| | std::vector inputs; 45| | std::vector outputs; 46| | std::string description; 47| | 48| | /// Whether to allow missing inputs. 49| | bool allowMissingInputs = false; 50| | 51| | /// Whether to allow modified outputs. 52| | // 53| | // FIXME: This is currently useful as a mechanism for defining builds in which 54| | // an output is intentionally modified by another command. However, this isn't 55| | // a very robust mechanism, and we should ultimately move to a model whereby 56| | // we can reconstruct exactly the state of each individual command (by having 57| | // a durable storage for the outputs outside of the file system). 58| | bool allowModifiedOutputs = false; 59| | 60| | /// Whether to treat the command as always being out-of-date. 61| | bool alwaysOutOfDate = false; 62| | 63| | // Build specific data. 64| | // 65| | // FIXME: We should probably factor this out somewhere else, so we can enforce 66| | // it is never used when initialized incorrectly. 67| | 68| | /// The previous build result command signature, if available. 69| | basic::CommandSignature priorResultCommandSignature; 70| | 71| | /// If not None, the command should be skipped with the provided BuildValue. 72| | llvm::Optional skipValue; 73| | 74| | /// If there are any elements, the command had missing input nodes 75| | /// (this implies ShouldSkip is true). 76| | SmallPtrSet missingInputNodes; 77| | 78| | /// If true, the command can legally be updated if the output state allows it. 79| | bool canUpdateIfNewer = true; 80| | 81| | /// Whether a prior result has been found. 82| | bool hasPriorResult = false; 83| | 84| | /// Compute the output result for the command. 85| | BuildValue computeCommandResult(BuildSystemCommandInterface& bsci); 86| | 87| | /// Check if it is legal to only update the result (versus rerunning) 88| | /// because the outputs are newer than all of the inputs. 89| | bool canUpdateIfNewerWithResult(const BuildValue& result); 90| | 91| |protected: 92| 0| const std::vector& getInputs() const { return inputs; } 93| | 94| 0| const std::vector& getOutputs() const { return outputs; } 95| | 96| 0| StringRef getDescription() const { return description; } 97| | 98| | /// This function must be overriden by subclasses for any additional keys. 99| | virtual basic::CommandSignature getSignature(); 100| | 101| | /// Extension point for subclasses, to actually execute the command. 102| | virtual void executeExternalCommand( 103| | BuildSystemCommandInterface& bsci, 104| | core::Task* task, 105| | basic::QueueJobContext* context, 106| | llvm::Optional completionFn = {llvm::None}) = 0; 107| | 108| |public: 109| | using Command::Command; 110| | 111| | virtual void configureDescription(const ConfigureContext&, 112| | StringRef value) override; 113| | 114| | virtual void configureInputs(const ConfigureContext&, 115| | const std::vector& value) override; 116| | 117| | virtual void configureOutputs(const ConfigureContext&, 118| | const std::vector& value) override; 119| | 120| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 121| | StringRef value) override; 122| | virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name, 123| | ArrayRef values) override; 124| | virtual bool configureAttribute( 125| | const ConfigureContext&, StringRef name, 126| | ArrayRef> values) override; 127| | 128| | virtual BuildValue getResultForOutput(Node* node, 129| | const BuildValue& value) override; 130| | 131| | virtual bool isResultValid(BuildSystem&, const BuildValue& value) override; 132| | 133| | virtual void start(BuildSystemCommandInterface& bsci, 134| | core::Task* task) override; 135| | 136| | virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*, 137| | const BuildValue&) override; 138| | 139| | virtual void provideValue(BuildSystemCommandInterface& bsci, core::Task*, 140| | uintptr_t inputID, 141| | const BuildValue& value) override; 142| | 143| | virtual void execute(BuildSystemCommandInterface& bsci, 144| | core::Task* task, 145| | basic::QueueJobContext* context, 146| | ResultFn resultFn) override; 147| |}; 148| | 149| |} 150| |} 151| | 152| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/BuildEngine.h: 1| |//===- BuildEngine.h --------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_BUILDENGINE_H 14| |#define LLBUILD_CORE_BUILDENGINE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/ADT/Twine.h" 20| | 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |namespace llbuild { 29| |namespace core { 30| | 31| |// FIXME: Need to abstract KeyType; 32| |typedef std::string KeyType; 33| |typedef uint64_t KeyID; 34| |typedef std::vector ValueType; 35| | 36| |class BuildDB; 37| |class BuildEngine; 38| | 39| |/// A monotonically increasing timestamp identifying which iteration of a build 40| |/// an event occurred during. 41| |typedef uint64_t Timestamp; 42| | 43| |/// This object contains the result of executing a task to produce the value for 44| |/// a key. 45| |struct Result { 46| | /// The last value that resulted from executing the task. 47| | ValueType value = {}; 48| | 49| | /// The build timestamp during which the result \see Value was computed. 50| | uint64_t computedAt = 0; 51| | 52| | /// The build timestamp at which this result was last checked to be 53| | /// up-to-date. 54| | /// 55| | /// \invariant builtAt >= computedAt 56| | // 57| | // FIXME: Think about this representation more. The problem with storing this 58| | // field here in this fashion is that every build will result in bringing all 59| | // of the \see builtAt fields up to date. That is unfortunate from a 60| | // persistence perspective, where it would be ideal if we didn't touch any 61| | // disk state for null builds. 62| | uint64_t builtAt = 0; 63| | 64| | /// The explicit dependencies required by the generation. 65| | // 66| | // FIXME: At some point, figure out the optimal representation for this field, 67| | // which is likely to be a lot of the resident memory size. 68| | std::vector dependencies; 69| |}; 70| | 71| |/// A task object represents an abstract in-progress computation in the build 72| |/// engine. 73| |/// 74| |/// The task represents not just the primary computation, but also the process 75| |/// of starting the computation and necessary input dependencies. Tasks are 76| |/// expected to be created in response to \see BuildEngine requests to initiate 77| |/// the production of particular result value. 78| |/// 79| |/// The creator may use \see BuildEngine::taskNeedsInput() to specify input 80| |/// dependencies on the Task. The Task itself may also specify additional input 81| |/// dependencies dynamically during the execution of \see Task::start() or \see 82| |/// Task::provideValue(). 83| |/// 84| |/// Once a task has been created and registered, the BuildEngine will invoke 85| |/// \see Task::start() to initiate the computation. The BuildEngine will provide 86| |/// the in progress task with its requested inputs via \see 87| |/// Task::provideValue(). 88| |/// 89| |/// After all inputs requested by the Task have been delivered, the BuildEngine 90| |/// will invoke \see Task::inputsAvailable() to instruct the Task it should 91| |/// complete its computation and provide the output. The Task is responsible for 92| |/// providing the engine with the computed value when ready using \see 93| |/// BuildEngine::taskIsComplete(). 94| |/// 95| |/// A task which has been cancelled may be destroyed without any of the above 96| |/// behaviors having been completed. 97| |class Task { 98| |public: 99| 0| Task() {} 100| | virtual ~Task(); 101| | 102| | /// Executed by the build engine when the task should be started. 103| | virtual void start(BuildEngine&) = 0; 104| | 105| | /// Invoked by the build engine to provide the prior result for the task's 106| | /// output, if present. 107| | /// 108| | /// This callback will always be invoked immediately after the task is 109| | /// started, and prior to its receipt of any other callbacks. 110| 0| virtual void providePriorValue(BuildEngine&, const ValueType& value) {}; 111| | 112| | /// Invoked by the build engine to provide an input value as it becomes 113| | /// available. 114| | /// 115| | /// \param inputID The unique identifier provided to the build engine to 116| | /// represent this input when requested in \see 117| | /// BuildEngine::taskNeedsInput(). 118| | /// 119| | /// \param value The computed value for the given input. 120| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 121| | const ValueType& value) = 0; 122| | 123| | /// Executed by the build engine to indicate that all inputs have been 124| | /// provided, and the task should begin its computation. 125| | /// 126| | /// The task is expected to call \see BuildEngine::taskIsComplete() when it is 127| | /// done with its computation. 128| | /// 129| | /// It is an error for any client to request an additional input for a task 130| | /// after the last requested input has been provided by the build engine. 131| | virtual void inputsAvailable(BuildEngine&) = 0; 132| |}; 133| | 134| |/// A rule represents an individual element of computation that can be performed 135| |/// by the build engine. 136| |/// 137| |/// Each rule is identified by a unique key and the value for that key can be 138| |/// computed to produce a result, and supplies a set of callbacks that are used 139| |/// to implement the rule's behavior. 140| |/// 141| |/// The computation for a rule is done by invocation of its \see Action 142| |/// callback, which is responsible for creating a Task object which will manage 143| |/// the computation. 144| |/// 145| |/// All callbacks for the Rule are always invoked synchronously on the primary 146| |/// BuildEngine thread. 147| |// 148| |// FIXME: The intent of having a callback like Rule structure and a decoupled 149| |// (virtual) Task is that the Rule objects (of which there can be very many) can 150| |// be optimized for being lightweight. We don't currently make much of an 151| |// attempt in this direction with the std::functions, but we should investigate 152| |// if this can be lighter weight -- especially since many clients are likely to 153| |// need little more than a place to stuff a context object and register their 154| |// callbacks. 155| |// 156| |// FIXME: We also need to figure out if a richer concurrency model is needed for 157| |// the callbacks. The current intent is that they should be lightweight and 158| |// Tasks should be used when real concurrency is needed. 159| |class Rule { 160| |public: 161| | enum class StatusKind { 162| | /// Indicates the rule is being scanned. 163| | IsScanning = 0, 164| | 165| | /// Indicates the rule is up-to-date, and doesn't need to run. 166| | IsUpToDate = 1, 167| | 168| | /// Indicates the rule was run, and is now complete. 169| | IsComplete = 2 170| | }; 171| | 172| | enum class CycleAction { 173| | /// Indicates a rule will be forced to build 174| | ForceBuild = 0, 175| | 176| | /// Indicates a rule's prior value will be supplied to a downstream rule 177| | SupplyPriorValue = 1 178| | }; 179| | 180| | /// The key computed by the rule. 181| | KeyType key; 182| | 183| | /// Called to create the task to build the rule, when necessary. 184| | std::function action; 185| | 186| | /// Called to check whether the previously computed value for this rule is 187| | /// still valid. 188| | /// 189| | /// This callback is designed for use in synchronizing values which represent 190| | /// state managed externally to the build engine. For example, a rule which 191| | /// computes something on the file system may use this to verify that the 192| | /// computed output has not changed since it was built. 193| | std::function isResultValid; 195| | 196| | /// Called to indicate a change in the rule status. 197| | std::function updateStatus; 198| |}; 199| | 200| |/// Delegate interface for use with the build engine. 201| |class BuildEngineDelegate { 202| |public: 203| | virtual ~BuildEngineDelegate(); 204| | 205| | /// Get the rule to use for the given Key. 206| | /// 207| | /// The delegate *must* provide a rule for any possible key that can be 208| | /// requested (either by a client, through \see BuildEngine::build(), or via a 209| | /// Task through mechanisms such as \see BuildEngine::taskNeedsInput(). If a 210| | /// requested Key cannot be supplied, the delegate should provide a dummy rule 211| | /// that the client can translate into an error. 212| | virtual Rule lookupRule(const KeyType& key) = 0; 213| | 214| | /// Called when a cycle is detected by the build engine to check if it should 215| | /// attempt to resolve the cycle and continue 216| | /// 217| | /// \param items The ordered list of items comprising the cycle, starting from 218| | /// the node which was requested to build and ending with the first node in 219| | /// the cycle (i.e., the node participating in the cycle will appear twice). 220| | /// \param candidateRule The rule the engine will use to attempt to break the 221| | /// cycle. 222| | /// \param action The action the engine will take on the candidateRule. 223| | /// \returns True if the engine should attempt to resolve the cycle, false 224| | /// otherwise. Resolution is attempted by either forcing items to be built, or 225| | /// supplying a previously built result to a node in the cycle. The latter 226| | /// action may yield unexpected results and thus this should be opted into 227| | /// with care. 228| | virtual bool shouldResolveCycle(const std::vector& items, 229| | Rule* candidateRule, 230| | Rule::CycleAction action); 231| | 232| | /// Called when a cycle is detected by the build engine and it cannot make 233| | /// forward progress. 234| | /// 235| | /// \param items The ordered list of items comprising the cycle, starting from 236| | /// the node which was requested to build and ending with the first node in 237| | /// the cycle (i.e., the node participating in the cycle will appear twice). 238| | virtual void cycleDetected(const std::vector& items) = 0; 239| | 240| | /// Called when a fatal error is encountered by the build engine. 241| | /// 242| | /// \param message The diagnostic message. 243| | virtual void error(const llvm::Twine& message) = 0; 244| | 245| |}; 246| | 247| |/// A build engine supports fast, incremental, persistent, and parallel 248| |/// execution of computational graphs. 249| |/// 250| |/// Computational elements in the graph are modeled by \see Rule objects, which 251| |/// are assocated with a specific \see KeyType, and which can be executed to 252| |/// produce an output \see ValueType for that key. 253| |/// 254| |/// Rule objects are evaluated by first invoking their action to produce a \see 255| |/// Task object which is responsible for the live execution of the 256| |/// computation. The Task object can interact with the BuildEngine to request 257| |/// inputs or to notify the engine of its completion, and receives various 258| |/// callbacks from the engine as the computation progresses. 259| |/// 260| |/// The engine itself executes using a deterministic, serial operation, but it 261| |/// supports parallel computation by allowing the individual Task objects to 262| |/// defer their own computation to signal the BuildEngine of its completion on 263| |/// alternate threads. 264| |/// 265| |/// To support persistence, the engine allows attaching a database (\see 266| |/// attachDB()) which can be used to record the prior results of evaluating Rule 267| |/// instances. 268| |class BuildEngine { 269| | void *impl; 270| | 271| | // Copying is disabled. 272| | BuildEngine(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 273| | void operator=(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 274| | 275| |public: 276| | /// Create a build engine with the given delegate. 277| | explicit BuildEngine(BuildEngineDelegate& delegate); 278| | ~BuildEngine(); 279| | 280| | /// Return the delegate the engine was configured with. 281| | BuildEngineDelegate* getDelegate(); 282| | 283| | /// Get the current build timestamp used by the engine. 284| | /// 285| | /// The timestamp is a monotonically increasing value which is incremented 286| | /// with each requested build. 287| | Timestamp getCurrentTimestamp(); 288| | 289| | /// @name Rule Definition 290| | /// @{ 291| | 292| | /// Add a rule which the engine can use to produce outputs. 293| | void addRule(Rule&& rule); 294| | 295| | /// @} 296| | 297| | /// @name Client API 298| | /// @{ 299| | 300| | /// Build the result for a particular key. 301| | /// 302| | /// \returns The result of computing the key, or the empty value if the key 303| | /// could not be computed; the latter case only happens if a cycle was 304| | /// discovered currently. 305| | const ValueType& build(const KeyType& key); 306| | 307| | /// Cancel the currently running build. 308| | /// 309| | /// The engine guarantees that it will not *start* any task after processing 310| | /// the current engine work loop iteration after it has been cancelled. 311| | /// 312| | /// This method is thread-safe. 313| | /// 314| | /// This method should only be used when a build is actively running. Invoking 315| | /// this method before a build has started will have no effect. 316| | // 317| | // FIXME: This method is hard to use correctly, we should modify build to 318| | // return an explicit object to represent an in-flight build, and then expose 319| | // cancellation on that. 320| | void cancelBuild(); 321| | 322| | /// Attach a database for persisting build state. 323| | /// 324| | /// A database should only be attached immediately after creating the engine, 325| | /// it is an error to attach a database after adding rules or initiating any 326| | /// builds, or to attempt to attach multiple databases. 327| | /// 328| | /// \param error_out [out] Error string if return value is false. 329| | /// \returns false if the build database could not be attached. 330| | bool attachDB(std::unique_ptr database, std::string* error_out); 331| | 332| | /// Enable tracing into the given output file. 333| | /// 334| | /// \returns True on success. 335| | bool enableTracing(const std::string& path, std::string* error_out); 336| | 337| | /// Dump the build state to a file in Graphviz DOT format. 338| | void dumpGraphToFile(const std::string &path); 339| | 340| | /// @} 341| | 342| | /// @name Task Management APIs 343| | /// @{ 344| | 345| | /// Register the given task, in response to a Rule evaluation. 346| | /// 347| | /// The engine tasks ownership of the \arg Task, and it is expected to 348| | /// subsequently be returned as the task to execute for a Rule evaluation. 349| | /// 350| | /// \returns The provided task, for the convenience of the client. 351| | Task* registerTask(Task* task); 352| | 353| | /// The maximum allowed input ID. 354| | static const uintptr_t kMaximumInputID = ~(uintptr_t)0xFF; 355| | 356| | /// Specify the given \arg Task depends upon the result of computing \arg Key. 357| | /// 358| | /// The result, when available, will be provided to the task via \see 359| | /// Task::provideValue(), supplying the provided \arg InputID to allow the 360| | /// task to identify the particular input. 361| | /// 362| | /// NOTE: It is an unchecked error for a task to request the same input value 363| | /// multiple times. 364| | /// 365| | /// \param inputID An arbitrary value that may be provided by the client to 366| | /// use in efficiently associating this input. The range of this parameter is 367| | /// intentionally chosen to allow a pointer to be provided, but note that all 368| | /// input IDs greater than \see kMaximumInputID are reserved for internal use 369| | /// by the engine. 370| | void taskNeedsInput(Task* task, const KeyType& key, uintptr_t inputID); 371| | 372| | /// Specify that the given \arg Task must be built subsequent to the 373| | /// computation of \arg Key. 374| | /// 375| | /// The value of the computation of \arg Key is not available to the task, and 376| | /// the only guarantee the engine provides is that if \arg Key is computed 377| | /// during a build, then \arg Task will not be computed until after it. 378| | void taskMustFollow(Task* task, const KeyType& key); 379| | 380| | /// Inform the engine of an input dependency that was discovered by the task 381| | /// during its execution, a la compiler generated dependency files. 382| | /// 383| | /// This call may only be made after a task has received all of its inputs; 384| | /// inputs discovered prior to that point should simply be requested as normal 385| | /// input dependencies. 386| | /// 387| | /// Such a dependency is not used to provide additional input to the task, 388| | /// rather it is a way for the task to report an additional input which should 389| | /// be considered the next time the rule is evaluated. The expected use case 390| | /// for a discovered dependency is is when a processing task cannot predict 391| | /// all of its inputs prior to being run, but can presume that any unknown 392| | /// inputs already exist. In such cases, the task can go ahead and run and can 393| | /// report the all of the discovered inputs as it executes. Once the task is 394| | /// complete, these inputs will be recorded as being dependencies of the task 395| | /// so that it will be recomputed when any of the inputs change. 396| | /// 397| | /// It is legal to call this method from any thread, but the caller is 398| | /// responsible for ensuring that it is never called concurrently for the same 399| | /// task. 400| | void taskDiscoveredDependency(Task* task, const KeyType& key); 401| | 402| | /// Called by a task to indicate it has completed and to provide its value. 403| | /// 404| | /// It is legal to call this method from any thread. 405| | /// 406| | /// \param value The new value for the task's rule. 407| | /// 408| | /// \param forceChange If true, treat the value as changed and trigger 409| | /// dependents to rebuild, even if the value itself is not different from the 410| | /// prior result. 411| | void taskIsComplete(Task* task, ValueType&& value, bool forceChange = false); 412| | 413| | /// @} 414| |}; 415| | 416| |} 417| |} 418| | 419| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/DependencyInfoParser.h: 1| |//===- DependencyInfoParser.h -----------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_DEPENDENCYINFOPARSER_H 14| |#define LLBUILD_CORE_DEPENDENCYINFOPARSER_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| |namespace core { 24| | 25| |/// Interface for parsing the "dependency info" format used by Darwin tools. 26| |class DependencyInfoParser { 27| |public: 28| | /// Delegate interface for parser behavior. 29| | struct ParseActions { 30| | virtual ~ParseActions(); 31| | 32| | /// Called if an error is encountered in parsing the input. 33| | /// 34| | /// \param message A C-string text message including information on the 35| | /// error. 36| | /// 37| | /// \param position The approximate position of the error in the input 38| | /// buffer. 39| | virtual void error(const char* message, uint64_t position) = 0; 40| | 41| | /// Called when the version information is found. 42| | /// 43| | /// There can only ever be one version info record in the file. 44| | virtual void actOnVersion(StringRef) = 0; 45| | 46| | /// Called when an input is found. 47| | virtual void actOnInput(StringRef) = 0; 48| | 49| | /// Called when an output is found. 50| | virtual void actOnOutput(StringRef) = 0; 51| | 52| | /// Called when a missing file entry is found. 53| | /// 54| | /// These entries indicate a file which was looked for by the tool, but not 55| | /// found, and can be used to track anti-dependencies. 56| | virtual void actOnMissing(StringRef) = 0; 57| | }; 58| | 59| | StringRef data; 60| | ParseActions& actions; 61| | 62| |public: 63| | DependencyInfoParser(StringRef data, ParseActions& actions) 64| 0| : data(data), actions(actions) {} 65| | 66| | void parse(); 67| |}; 68| | 69| |} 70| |} 71| | 72| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/MakefileDepsParser.h: 1| |//===- MakefileDepsParser.h -------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_MAKEFILEDEPSPARSER_H 14| |#define LLBUILD_CORE_MAKEFILEDEPSPARSER_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| |namespace core { 24| | 25| |/// Interface for parsing compiler-style dependencies output, which is a 26| |/// restricted subset of the Makefile syntax. 27| |class MakefileDepsParser { 28| |public: 29| | /// Delegate interface for parser behavior. 30| | struct ParseActions { 31| | virtual ~ParseActions(); 32| | 33| | /// Called if an error is encountered in parsing the input. 34| | /// 35| | /// \param message A C-string text message including information on the 36| | /// error. 37| | /// 38| | /// \param position The approximate position of the error in the input 39| | /// buffer. 40| | virtual void error(const char* message, uint64_t position) = 0; 41| | 42| | /// Called when a new rule is encountered. 43| | /// 44| | /// \param name - A pointer to the rule name string start. 45| | /// 46| | /// \param length - The raw length of the rule name string, including escape 47| | /// sequences. 48| | /// 49| | /// \param unescapedWord - An unescaped version of the name. 50| | virtual void actOnRuleStart(const char* name, uint64_t length, 51| | const StringRef unescapedWord) = 0; 52| | 53| | /// Called when a new dependency is found for the current rule. 54| | /// 55| | /// This is only called between paired calls to \see actOnRuleStart() and 56| | /// \see actOnRuleEnd(). 57| | /// 58| | /// \param dependency - A pointer to the dependency string start. 59| | /// 60| | /// \param length - The raw length of the dependency string, including 61| | /// escape sequences. 62| | /// 63| | /// \param unescapedWord - An unescaped version of the dependency. 64| | virtual void actOnRuleDependency(const char* dependency, uint64_t length, 65| | const StringRef unescapedWord) = 0; 66| | 67| | /// Called when a rule is complete. 68| | virtual void actOnRuleEnd() = 0; 69| | }; 70| | 71| | const char* data; 72| | uint64_t length; 73| | ParseActions& actions; 74| | 75| |public: 76| | MakefileDepsParser(const char* data, uint64_t length, ParseActions& actions) 77| 0| : data(data), length(length), actions(actions) {} 78| | 79| | void parse(); 80| |}; 81| | 82| |} 83| |} 84| | 85| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/ArrayRef.h: 1| |//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_ARRAYREF_H 11| |#define LLVM_ADT_ARRAYREF_H 12| | 13| |#include "llvm/ADT/None.h" 14| |#include "llvm/ADT/SmallVector.h" 15| |#include 16| | 17| |namespace llvm { 18| | 19| | /// ArrayRef - Represent a constant reference to an array (0 or more elements 20| | /// consecutively in memory), i.e. a start pointer and a length. It allows 21| | /// various APIs to take consecutive elements easily and conveniently. 22| | /// 23| | /// This class does not own the underlying data, it is expected to be used in 24| | /// situations where the data resides in some other buffer, whose lifetime 25| | /// extends past that of the ArrayRef. For this reason, it is not in general 26| | /// safe to store an ArrayRef. 27| | /// 28| | /// This is intended to be trivially copyable, so it should be passed by 29| | /// value. 30| | template 31| | class ArrayRef { 32| | public: 33| | typedef const T *iterator; 34| | typedef const T *const_iterator; 35| | typedef size_t size_type; 36| | 37| | typedef std::reverse_iterator reverse_iterator; 38| | 39| | private: 40| | /// The start of the array, in an external buffer. 41| | const T *Data; 42| | 43| | /// The number of elements. 44| | size_type Length; 45| | 46| | public: 47| | /// @name Constructors 48| | /// @{ 49| | 50| | /// Construct an empty ArrayRef. 51| 0| /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} 52| | 53| | /// Construct an empty ArrayRef from None. 54| 0| /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMRangeEEC2ENS_8NoneTypeE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMFixItEEC2ENS_8NoneTypeE ------------------ 55| | 56| | /// Construct an ArrayRef from a single element. 57| | /*implicit*/ ArrayRef(const T &OneElt) 58| 0| : Data(&OneElt), Length(1) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefIN7llbuild5basic8FileInfoEEC2ERKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMRangeEEC2ERKS1_ ------------------ 59| | 60| | /// Construct an ArrayRef from a pointer and length. 61| | /*implicit*/ ArrayRef(const T *data, size_t length) 62| 0| : Data(data), Length(length) {} 63| | 64| | /// Construct an ArrayRef from a range. 65| | ArrayRef(const T *begin, const T *end) 66| | : Data(begin), Length(end - begin) {} 67| | 68| | /// Construct an ArrayRef from a SmallVector. This is templated in order to 69| | /// avoid instantiating SmallVectorTemplateCommon whenever we 70| | /// copy-construct an ArrayRef. 71| | template 72| | /*implicit*/ ArrayRef(const SmallVectorTemplateCommon &Vec) 73| 0| : Data(Vec.data()), Length(Vec.size()) { 74| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEEC2IvEERKNS_25SmallVectorTemplateCommonIS4_T_EE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefIN7llbuild5basic8FileInfoEEC2IvEERKNS_25SmallVectorTemplateCommonIS3_T_EE ------------------ 75| | 76| | /// Construct an ArrayRef from a std::vector. 77| | template 78| | /*implicit*/ ArrayRef(const std::vector &Vec) 79| 0| : Data(Vec.data()), Length(Vec.size()) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEEC2INS1_9allocatorIS4_EEEERKNS1_6vectorIS4_T_EE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_9StringRefEEC2INSt3__19allocatorIS1_EEEERKNS4_6vectorIS1_T_EE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEC2INS5_IS7_EEEERKNS1_6vectorIS7_T_EE ------------------ 80| | 81| | /// Construct an ArrayRef from a C array. 82| | template 83| | /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) 84| | : Data(Arr), Length(N) {} 85| | 86| | /// Construct an ArrayRef from a std::initializer_list. 87| | /*implicit*/ ArrayRef(const std::initializer_list &Vec) 88| | : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), 89| | Length(Vec.size()) {} 90| | 91| | /// Construct an ArrayRef from ArrayRef. This uses SFINAE to 92| | /// ensure that only ArrayRefs of pointers can be converted. 93| | template 94| | ArrayRef(const ArrayRef &A, 95| | typename std::enable_if< 96| | std::is_convertible::value>::type* = 0) 97| | : Data(A.data()), Length(A.size()) {} 98| | 99| | /// @} 100| | /// @name Simple Operations 101| | /// @{ 102| | 103| 0| iterator begin() const { return Data; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE5beginEv ------------------ 104| 0| iterator end() const { return Data + Length; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE3endEv ------------------ 105| | 106| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 107| | reverse_iterator rend() const { return reverse_iterator(begin()); } 108| | 109| | /// empty - Check if the array is empty. 110| 0| bool empty() const { return Length == 0; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE5emptyEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE5emptyEv ------------------ 111| | 112| 0| const T *data() const { return Data; } 113| | 114| | /// size - Get the array size. 115| 0| size_t size() const { return Length; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIN7llbuild5basic8FileInfoEE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE4sizeEv ------------------ 116| | 117| | /// front - Get the first element. 118| 0| const T &front() const { 119| 0| assert(!empty()); 120| 0| return Data[0]; 121| 0| } 122| | 123| | /// back - Get the last element. 124| | const T &back() const { 125| | assert(!empty()); 126| | return Data[Length-1]; 127| | } 128| | 129| | // copy - Allocate copy in Allocator and return ArrayRef to it. 130| | template ArrayRef copy(Allocator &A) { 131| | T *Buff = A.template Allocate(Length); 132| | std::copy(begin(), end(), Buff); 133| | return ArrayRef(Buff, Length); 134| | } 135| | 136| | /// equals - Check for element-wise equality. 137| | bool equals(ArrayRef RHS) const { 138| | if (Length != RHS.Length) 139| | return false; 140| | if (Length == 0) 141| | return true; 142| | return std::equal(begin(), end(), RHS.begin()); 143| | } 144| | 145| | /// slice(n) - Chop off the first N elements of the array. 146| 0| ArrayRef slice(unsigned N) const { 147| 0| assert(N <= size() && "Invalid specifier"); 148| 0| return ArrayRef(data()+N, size()-N); 149| 0| } 150| | 151| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 152| | /// elements in the array. 153| | ArrayRef slice(unsigned N, unsigned M) const { 154| | assert(N+M <= size() && "Invalid specifier"); 155| | return ArrayRef(data()+N, M); 156| | } 157| | 158| | // \brief Drop the last \p N elements of the array. 159| | ArrayRef drop_back(unsigned N = 1) const { 160| | assert(size() >= N && "Dropping more elements than exist"); 161| | return slice(0, size() - N); 162| | } 163| | 164| | /// @} 165| | /// @name Operator Overloads 166| | /// @{ 167| 0| const T &operator[](size_t Index) const { 168| 0| assert(Index < Length && "Invalid index!"); 169| 0| return Data[Index]; 170| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIN7llbuild5basic8FileInfoEEixEm ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEixEm ------------------ 171| | 172| | /// @} 173| | /// @name Expensive Operations 174| | /// @{ 175| | std::vector vec() const { 176| | return std::vector(Data, Data+Length); 177| | } 178| | 179| | /// @} 180| | /// @name Conversion operators 181| | /// @{ 182| | operator std::vector() const { 183| | return std::vector(Data, Data+Length); 184| | } 185| | 186| | /// @} 187| | }; 188| | 189| | /// MutableArrayRef - Represent a mutable reference to an array (0 or more 190| | /// elements consecutively in memory), i.e. a start pointer and a length. It 191| | /// allows various APIs to take and modify consecutive elements easily and 192| | /// conveniently. 193| | /// 194| | /// This class does not own the underlying data, it is expected to be used in 195| | /// situations where the data resides in some other buffer, whose lifetime 196| | /// extends past that of the MutableArrayRef. For this reason, it is not in 197| | /// general safe to store a MutableArrayRef. 198| | /// 199| | /// This is intended to be trivially copyable, so it should be passed by 200| | /// value. 201| | template 202| | class MutableArrayRef : public ArrayRef { 203| | public: 204| | typedef T *iterator; 205| | 206| | typedef std::reverse_iterator reverse_iterator; 207| | 208| | /// Construct an empty MutableArrayRef. 209| | /*implicit*/ MutableArrayRef() : ArrayRef() {} 210| | 211| | /// Construct an empty MutableArrayRef from None. 212| | /*implicit*/ MutableArrayRef(NoneType) : ArrayRef() {} 213| | 214| | /// Construct an MutableArrayRef from a single element. 215| | /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef(OneElt) {} 216| | 217| | /// Construct an MutableArrayRef from a pointer and length. 218| | /*implicit*/ MutableArrayRef(T *data, size_t length) 219| | : ArrayRef(data, length) {} 220| | 221| | /// Construct an MutableArrayRef from a range. 222| | MutableArrayRef(T *begin, T *end) : ArrayRef(begin, end) {} 223| | 224| | /// Construct an MutableArrayRef from a SmallVector. 225| | /*implicit*/ MutableArrayRef(SmallVectorImpl &Vec) 226| | : ArrayRef(Vec) {} 227| | 228| | /// Construct a MutableArrayRef from a std::vector. 229| | /*implicit*/ MutableArrayRef(std::vector &Vec) 230| | : ArrayRef(Vec) {} 231| | 232| | /// Construct an MutableArrayRef from a C array. 233| | template 234| | /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) 235| | : ArrayRef(Arr) {} 236| | 237| | T *data() const { return const_cast(ArrayRef::data()); } 238| | 239| | iterator begin() const { return data(); } 240| | iterator end() const { return data() + this->size(); } 241| | 242| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 243| | reverse_iterator rend() const { return reverse_iterator(begin()); } 244| | 245| | /// front - Get the first element. 246| | T &front() const { 247| | assert(!this->empty()); 248| | return data()[0]; 249| | } 250| | 251| | /// back - Get the last element. 252| | T &back() const { 253| | assert(!this->empty()); 254| | return data()[this->size()-1]; 255| | } 256| | 257| | /// slice(n) - Chop off the first N elements of the array. 258| | MutableArrayRef slice(unsigned N) const { 259| | assert(N <= this->size() && "Invalid specifier"); 260| | return MutableArrayRef(data()+N, this->size()-N); 261| | } 262| | 263| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 264| | /// elements in the array. 265| | MutableArrayRef slice(unsigned N, unsigned M) const { 266| | assert(N+M <= this->size() && "Invalid specifier"); 267| | return MutableArrayRef(data()+N, M); 268| | } 269| | 270| | /// @} 271| | /// @name Operator Overloads 272| | /// @{ 273| | T &operator[](size_t Index) const { 274| | assert(Index < this->size() && "Invalid index!"); 275| | return data()[Index]; 276| | } 277| | }; 278| | 279| | /// @name ArrayRef Convenience constructors 280| | /// @{ 281| | 282| | /// Construct an ArrayRef from a single element. 283| | template 284| | ArrayRef makeArrayRef(const T &OneElt) { 285| | return OneElt; 286| | } 287| | 288| | /// Construct an ArrayRef from a pointer and length. 289| | template 290| | ArrayRef makeArrayRef(const T *data, size_t length) { 291| | return ArrayRef(data, length); 292| | } 293| | 294| | /// Construct an ArrayRef from a range. 295| | template 296| | ArrayRef makeArrayRef(const T *begin, const T *end) { 297| | return ArrayRef(begin, end); 298| | } 299| | 300| | /// Construct an ArrayRef from a SmallVector. 301| | template 302| | ArrayRef makeArrayRef(const SmallVectorImpl &Vec) { 303| | return Vec; 304| | } 305| | 306| | /// Construct an ArrayRef from a SmallVector. 307| | template 308| | ArrayRef makeArrayRef(const SmallVector &Vec) { 309| | return Vec; 310| | } 311| | 312| | /// Construct an ArrayRef from a std::vector. 313| | template 314| | ArrayRef makeArrayRef(const std::vector &Vec) { 315| | return Vec; 316| | } 317| | 318| | /// Construct an ArrayRef from a C array. 319| | template 320| | ArrayRef makeArrayRef(const T (&Arr)[N]) { 321| | return ArrayRef(Arr); 322| | } 323| | 324| | /// @} 325| | /// @name ArrayRef Comparison Operators 326| | /// @{ 327| | 328| | template 329| | inline bool operator==(ArrayRef LHS, ArrayRef RHS) { 330| | return LHS.equals(RHS); 331| | } 332| | 333| | template 334| | inline bool operator!=(ArrayRef LHS, ArrayRef RHS) { 335| | return !(LHS == RHS); 336| | } 337| | 338| | /// @} 339| | 340| | // ArrayRefs can be treated like a POD type. 341| | template struct isPodLike; 342| | template struct isPodLike > { 343| | static const bool value = true; 344| | }; 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/DenseMap.h: 1| |//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the DenseMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_DENSEMAP_H 15| |#define LLVM_ADT_DENSEMAP_H 16| | 17| |#include "llvm/ADT/DenseMapInfo.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/PointerLikeTypeTraits.h" 22| |#include "llvm/Support/type_traits.h" 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| |#include 31| | 32| |namespace llvm { 33| | 34| |namespace detail { 35| |// We extend a pair to allow users to override the bucket type with their own 36| |// implementation without requiring two members. 37| |template 38| |struct DenseMapPair : public std::pair { 39| 0| KeyT &getFirst() { return std::pair::first; } 40| 0| const KeyT &getFirst() const { return std::pair::first; } 41| 0| ValueT &getSecond() { return std::pair::second; } 42| | const ValueT &getSecond() const { return std::pair::second; } 43| |}; 44| |} 45| | 46| |template < 47| | typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, 48| | typename Bucket = detail::DenseMapPair, bool IsConst = false> 49| |class DenseMapIterator; 50| | 51| |template 53| |class DenseMapBase { 54| |public: 55| | typedef unsigned size_type; 56| | typedef KeyT key_type; 57| | typedef ValueT mapped_type; 58| | typedef BucketT value_type; 59| | 60| | typedef DenseMapIterator iterator; 61| | typedef DenseMapIterator 62| | const_iterator; 63| | inline iterator begin() { 64| | // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). 65| | return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); 66| | } 67| 0| inline iterator end() { 68| 0| return iterator(getBucketsEnd(), getBucketsEnd(), true); 69| 0| } 70| | inline const_iterator begin() const { 71| | return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd()); 72| | } 73| | inline const_iterator end() const { 74| | return const_iterator(getBucketsEnd(), getBucketsEnd(), true); 75| | } 76| | 77| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { 78| | return getNumEntries() == 0; 79| | } 80| | unsigned size() const { return getNumEntries(); } 81| | 82| | /// Grow the densemap so that it has at least Size buckets. Does not shrink 83| | void resize(size_type Size) { 84| | if (Size > getNumBuckets()) 85| | grow(Size); 86| | } 87| | 88| | void clear() { 89| | if (getNumEntries() == 0 && getNumTombstones() == 0) return; 90| | 91| | // If the capacity of the array is huge, and the # elements used is small, 92| | // shrink the array. 93| | if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { 94| | shrink_and_clear(); 95| | return; 96| | } 97| | 98| | const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 99| | for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 100| | if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { 101| | if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 102| | P->getSecond().~ValueT(); 103| | decrementNumEntries(); 104| | } 105| | P->getFirst() = EmptyKey; 106| | } 107| | } 108| | assert(getNumEntries() == 0 && "Node count imbalance!"); 109| | setNumTombstones(0); 110| | } 111| | 112| | /// Return 1 if the specified key is in the map, 0 otherwise. 113| | size_type count(const KeyT &Val) const { 114| | const BucketT *TheBucket; 115| | return LookupBucketFor(Val, TheBucket) ? 1 : 0; 116| | } 117| | 118| 0| iterator find(const KeyT &Val) { 119| 0| BucketT *TheBucket; 120| 0| if (LookupBucketFor(Val, TheBucket)) 121| 0| return iterator(TheBucket, getBucketsEnd(), true); 122| 0| return end(); 123| 0| } 124| | const_iterator find(const KeyT &Val) const { 125| | const BucketT *TheBucket; 126| | if (LookupBucketFor(Val, TheBucket)) 127| | return const_iterator(TheBucket, getBucketsEnd(), true); 128| | return end(); 129| | } 130| | 131| | /// Alternate version of find() which allows a different, and possibly 132| | /// less expensive, key type. 133| | /// The DenseMapInfo is responsible for supplying methods 134| | /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key 135| | /// type used. 136| | template 137| | iterator find_as(const LookupKeyT &Val) { 138| | BucketT *TheBucket; 139| | if (LookupBucketFor(Val, TheBucket)) 140| | return iterator(TheBucket, getBucketsEnd(), true); 141| | return end(); 142| | } 143| | template 144| | const_iterator find_as(const LookupKeyT &Val) const { 145| | const BucketT *TheBucket; 146| | if (LookupBucketFor(Val, TheBucket)) 147| | return const_iterator(TheBucket, getBucketsEnd(), true); 148| | return end(); 149| | } 150| | 151| | /// lookup - Return the entry for the specified key, or a default 152| | /// constructed value if no such entry exists. 153| | ValueT lookup(const KeyT &Val) const { 154| | const BucketT *TheBucket; 155| | if (LookupBucketFor(Val, TheBucket)) 156| | return TheBucket->getSecond(); 157| | return ValueT(); 158| | } 159| | 160| | // Inserts key,value pair into the map if the key isn't already in the map. 161| | // If the key is already in the map, it returns false and doesn't update the 162| | // value. 163| | std::pair insert(const std::pair &KV) { 164| | BucketT *TheBucket; 165| | if (LookupBucketFor(KV.first, TheBucket)) 166| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 167| | false); // Already in map. 168| | 169| | // Otherwise, insert the new element. 170| | TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); 171| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 172| | } 173| | 174| | // Inserts key,value pair into the map if the key isn't already in the map. 175| | // If the key is already in the map, it returns false and doesn't update the 176| | // value. 177| | std::pair insert(std::pair &&KV) { 178| | BucketT *TheBucket; 179| | if (LookupBucketFor(KV.first, TheBucket)) 180| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 181| | false); // Already in map. 182| | 183| | // Otherwise, insert the new element. 184| | TheBucket = InsertIntoBucket(std::move(KV.first), 185| | std::move(KV.second), 186| | TheBucket); 187| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 188| | } 189| | 190| | /// insert - Range insertion of pairs. 191| | template 192| | void insert(InputIt I, InputIt E) { 193| | for (; I != E; ++I) 194| | insert(*I); 195| | } 196| | 197| | 198| | bool erase(const KeyT &Val) { 199| | BucketT *TheBucket; 200| | if (!LookupBucketFor(Val, TheBucket)) 201| | return false; // not in map. 202| | 203| | TheBucket->getSecond().~ValueT(); 204| | TheBucket->getFirst() = getTombstoneKey(); 205| | decrementNumEntries(); 206| | incrementNumTombstones(); 207| | return true; 208| | } 209| 0| void erase(iterator I) { 210| 0| BucketT *TheBucket = &*I; 211| 0| TheBucket->getSecond().~ValueT(); 212| 0| TheBucket->getFirst() = getTombstoneKey(); 213| 0| decrementNumEntries(); 214| 0| incrementNumTombstones(); 215| 0| } 216| | 217| 0| value_type& FindAndConstruct(const KeyT &Key) { 218| 0| BucketT *TheBucket; 219| 0| if (LookupBucketFor(Key, TheBucket)) 220| 0| return *TheBucket; 221| 0| 222| 0| return *InsertIntoBucket(Key, ValueT(), TheBucket); 223| 0| } 224| | 225| 0| ValueT &operator[](const KeyT &Key) { 226| 0| return FindAndConstruct(Key).second; 227| 0| } 228| | 229| | value_type& FindAndConstruct(KeyT &&Key) { 230| | BucketT *TheBucket; 231| | if (LookupBucketFor(Key, TheBucket)) 232| | return *TheBucket; 233| | 234| | return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket); 235| | } 236| | 237| | ValueT &operator[](KeyT &&Key) { 238| | return FindAndConstruct(std::move(Key)).second; 239| | } 240| | 241| | /// isPointerIntoBucketsArray - Return true if the specified pointer points 242| | /// somewhere into the DenseMap's array of buckets (i.e. either to a key or 243| | /// value in the DenseMap). 244| | bool isPointerIntoBucketsArray(const void *Ptr) const { 245| | return Ptr >= getBuckets() && Ptr < getBucketsEnd(); 246| | } 247| | 248| | /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets 249| | /// array. In conjunction with the previous method, this can be used to 250| | /// determine whether an insertion caused the DenseMap to reallocate. 251| | const void *getPointerIntoBucketsArray() const { return getBuckets(); } 252| | 253| |protected: 254| 0| DenseMapBase() {} 255| | 256| 0| void destroyAll() { 257| 0| if (getNumBuckets() == 0) // Nothing to do. 258| 0| return; 259| 0| 260| 0| const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 261| 0| for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 262| 0| if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 263| 0| !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) 264| 0| P->getSecond().~ValueT(); 265| 0| P->getFirst().~KeyT(); 266| 0| } 267| 0| 268| 0|#ifndef NDEBUG 269| 0| memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); 270| 0|#endif 271| 0| } 272| | 273| 0| void initEmpty() { 274| 0| setNumEntries(0); 275| 0| setNumTombstones(0); 276| 0| 277| 0| assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && 278| 0| "# initial buckets must be a power of two!"); 279| 0| const KeyT EmptyKey = getEmptyKey(); 280| 0| for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) 281| 0| new (&B->getFirst()) KeyT(EmptyKey); 282| 0| } 283| | 284| 0| void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { 285| 0| initEmpty(); 286| 0| 287| 0| // Insert all the old elements. 288| 0| const KeyT EmptyKey = getEmptyKey(); 289| 0| const KeyT TombstoneKey = getTombstoneKey(); 290| 0| for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { 291| 0| if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && 292| 0| !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { 293| 0| // Insert the key/value into the new table. 294| 0| BucketT *DestBucket; 295| 0| bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); 296| 0| (void)FoundVal; // silence warning. 297| 0| assert(!FoundVal && "Key already in new map?"); 298| 0| DestBucket->getFirst() = std::move(B->getFirst()); 299| 0| new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); 300| 0| incrementNumEntries(); 301| 0| 302| 0| // Free the value. 303| 0| B->getSecond().~ValueT(); 304| 0| } 305| 0| B->getFirst().~KeyT(); 306| 0| } 307| 0| 308| 0|#ifndef NDEBUG 309| 0| if (OldBucketsBegin != OldBucketsEnd) 310| 0| memset((void*)OldBucketsBegin, 0x5a, 311| 0| sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); 312| 0|#endif 313| 0| } 314| | 315| | template 316| | void copyFrom( 317| | const DenseMapBase &other) { 318| | assert(&other != this); 319| | assert(getNumBuckets() == other.getNumBuckets()); 320| | 321| | setNumEntries(other.getNumEntries()); 322| | setNumTombstones(other.getNumTombstones()); 323| | 324| | if (isPodLike::value && isPodLike::value) 325| | memcpy(getBuckets(), other.getBuckets(), 326| | getNumBuckets() * sizeof(BucketT)); 327| | else 328| | for (size_t i = 0; i < getNumBuckets(); ++i) { 329| | new (&getBuckets()[i].getFirst()) 330| | KeyT(other.getBuckets()[i].getFirst()); 331| | if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && 332| | !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) 333| | new (&getBuckets()[i].getSecond()) 334| | ValueT(other.getBuckets()[i].getSecond()); 335| | } 336| | } 337| | 338| | void swap(DenseMapBase& RHS) { 339| | std::swap(getNumEntries(), RHS.getNumEntries()); 340| | std::swap(getNumTombstones(), RHS.getNumTombstones()); 341| | } 342| | 343| 0| static unsigned getHashValue(const KeyT &Val) { 344| 0| return KeyInfoT::getHashValue(Val); 345| 0| } 346| | template 347| | static unsigned getHashValue(const LookupKeyT &Val) { 348| | return KeyInfoT::getHashValue(Val); 349| | } 350| 0| static const KeyT getEmptyKey() { 351| 0| return KeyInfoT::getEmptyKey(); 352| 0| } 353| 0| static const KeyT getTombstoneKey() { 354| 0| return KeyInfoT::getTombstoneKey(); 355| 0| } 356| | 357| |private: 358| 0| unsigned getNumEntries() const { 359| 0| return static_cast(this)->getNumEntries(); 360| 0| } 361| 0| void setNumEntries(unsigned Num) { 362| 0| static_cast(this)->setNumEntries(Num); 363| 0| } 364| 0| void incrementNumEntries() { 365| 0| setNumEntries(getNumEntries() + 1); 366| 0| } 367| 0| void decrementNumEntries() { 368| 0| setNumEntries(getNumEntries() - 1); 369| 0| } 370| 0| unsigned getNumTombstones() const { 371| 0| return static_cast(this)->getNumTombstones(); 372| 0| } 373| 0| void setNumTombstones(unsigned Num) { 374| 0| static_cast(this)->setNumTombstones(Num); 375| 0| } 376| 0| void incrementNumTombstones() { 377| 0| setNumTombstones(getNumTombstones() + 1); 378| 0| } 379| 0| void decrementNumTombstones() { 380| 0| setNumTombstones(getNumTombstones() - 1); 381| 0| } 382| 0| const BucketT *getBuckets() const { 383| 0| return static_cast(this)->getBuckets(); 384| 0| } 385| 0| BucketT *getBuckets() { 386| 0| return static_cast(this)->getBuckets(); 387| 0| } 388| 0| unsigned getNumBuckets() const { 389| 0| return static_cast(this)->getNumBuckets(); 390| 0| } 391| 0| BucketT *getBucketsEnd() { 392| 0| return getBuckets() + getNumBuckets(); 393| 0| } 394| | const BucketT *getBucketsEnd() const { 395| | return getBuckets() + getNumBuckets(); 396| | } 397| | 398| 0| void grow(unsigned AtLeast) { 399| 0| static_cast(this)->grow(AtLeast); 400| 0| } 401| | 402| | void shrink_and_clear() { 403| | static_cast(this)->shrink_and_clear(); 404| | } 405| | 406| | 407| | BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, 408| | BucketT *TheBucket) { 409| | TheBucket = InsertIntoBucketImpl(Key, TheBucket); 410| | 411| | TheBucket->getFirst() = Key; 412| | new (&TheBucket->getSecond()) ValueT(Value); 413| | return TheBucket; 414| | } 415| | 416| | BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, 417| 0| BucketT *TheBucket) { 418| 0| TheBucket = InsertIntoBucketImpl(Key, TheBucket); 419| 0| 420| 0| TheBucket->getFirst() = Key; 421| 0| new (&TheBucket->getSecond()) ValueT(std::move(Value)); 422| 0| return TheBucket; 423| 0| } 424| | 425| | BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { 426| | TheBucket = InsertIntoBucketImpl(Key, TheBucket); 427| | 428| | TheBucket->getFirst() = std::move(Key); 429| | new (&TheBucket->getSecond()) ValueT(std::move(Value)); 430| | return TheBucket; 431| | } 432| | 433| 0| BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { 434| 0| // If the load of the hash table is more than 3/4, or if fewer than 1/8 of 435| 0| // the buckets are empty (meaning that many are filled with tombstones), 436| 0| // grow the table. 437| 0| // 438| 0| // The later case is tricky. For example, if we had one empty bucket with 439| 0| // tons of tombstones, failing lookups (e.g. for insertion) would have to 440| 0| // probe almost the entire table until it found the empty bucket. If the 441| 0| // table completely filled with tombstones, no lookup would ever succeed, 442| 0| // causing infinite loops in lookup. 443| 0| unsigned NewNumEntries = getNumEntries() + 1; 444| 0| unsigned NumBuckets = getNumBuckets(); 445| 0| if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { 446| 0| this->grow(NumBuckets * 2); 447| 0| LookupBucketFor(Key, TheBucket); 448| 0| NumBuckets = getNumBuckets(); 449| 0| } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= 450| 0| NumBuckets/8)) { 451| 0| this->grow(NumBuckets); 452| 0| LookupBucketFor(Key, TheBucket); 453| 0| } 454| 0| assert(TheBucket); 455| 0| 456| 0| // Only update the state after we've grown our bucket space appropriately 457| 0| // so that when growing buckets we have self-consistent entry count. 458| 0| incrementNumEntries(); 459| 0| 460| 0| // If we are writing over a tombstone, remember this. 461| 0| const KeyT EmptyKey = getEmptyKey(); 462| 0| if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) 463| 0| decrementNumTombstones(); 464| 0| 465| 0| return TheBucket; 466| 0| } 467| | 468| | /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in 469| | /// FoundBucket. If the bucket contains the key and a value, this returns 470| | /// true, otherwise it returns a bucket with an empty marker or tombstone and 471| | /// returns false. 472| | template 473| | bool LookupBucketFor(const LookupKeyT &Val, 474| 0| const BucketT *&FoundBucket) const { 475| 0| const BucketT *BucketsPtr = getBuckets(); 476| 0| const unsigned NumBuckets = getNumBuckets(); 477| 0| 478| 0| if (NumBuckets == 0) { 479| 0| FoundBucket = nullptr; 480| 0| return false; 481| 0| } 482| 0| 483| 0| // FoundTombstone - Keep track of whether we find a tombstone while probing. 484| 0| const BucketT *FoundTombstone = nullptr; 485| 0| const KeyT EmptyKey = getEmptyKey(); 486| 0| const KeyT TombstoneKey = getTombstoneKey(); 487| 0| assert(!KeyInfoT::isEqual(Val, EmptyKey) && 488| 0| !KeyInfoT::isEqual(Val, TombstoneKey) && 489| 0| "Empty/Tombstone value shouldn't be inserted into map!"); 490| 0| 491| 0| unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); 492| 0| unsigned ProbeAmt = 1; 493| 0| while (1) { 494| 0| const BucketT *ThisBucket = BucketsPtr + BucketNo; 495| 0| // Found Val's bucket? If so, return it. 496| 0| if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { 497| 0| FoundBucket = ThisBucket; 498| 0| return true; 499| 0| } 500| 0| 501| 0| // If we found an empty bucket, the key doesn't exist in the set. 502| 0| // Insert it and return the default value. 503| 0| if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { 504| 0| // If we've already seen a tombstone while probing, fill it in instead 505| 0| // of the empty bucket we eventually probed to. 506| 0| FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; 507| 0| return false; 508| 0| } 509| 0| 510| 0| // If this is a tombstone, remember it. If Val ends up not in the map, we 511| 0| // prefer to return it than something that would require more probing. 512| 0| if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && 513| 0| !FoundTombstone) 514| 0| FoundTombstone = ThisBucket; // Remember the first tombstone found. 515| 0| 516| 0| // Otherwise, it's a hash collision or a tombstone, continue quadratic 517| 0| // probing. 518| 0| BucketNo += ProbeAmt++; 519| 0| BucketNo &= (NumBuckets-1); 520| 0| } 521| 0| } 522| | 523| | template 524| 0| bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { 525| 0| const BucketT *ConstFoundBucket; 526| 0| bool Result = const_cast(this) 527| 0| ->LookupBucketFor(Val, ConstFoundBucket); 528| 0| FoundBucket = const_cast(ConstFoundBucket); 529| 0| return Result; 530| 0| } 531| | 532| |public: 533| | /// Return the approximate size (in bytes) of the actual map. 534| | /// This is just the raw memory used by DenseMap. 535| | /// If entries are pointers to objects, the size of the referenced objects 536| | /// are not included. 537| | size_t getMemorySize() const { 538| | return getNumBuckets() * sizeof(BucketT); 539| | } 540| |}; 541| | 542| |template , 544| | typename BucketT = detail::DenseMapPair> 545| |class DenseMap : public DenseMapBase, 546| | KeyT, ValueT, KeyInfoT, BucketT> { 547| | // Lift some types from the dependent base class into this class for 548| | // simplicity of referring to them. 549| | typedef DenseMapBase BaseT; 550| | friend class DenseMapBase; 551| | 552| | BucketT *Buckets; 553| | unsigned NumEntries; 554| | unsigned NumTombstones; 555| | unsigned NumBuckets; 556| | 557| |public: 558| 0| explicit DenseMap(unsigned NumInitBuckets = 0) { 559| 0| init(NumInitBuckets); 560| 0| } 561| | 562| | DenseMap(const DenseMap &other) : BaseT() { 563| | init(0); 564| | copyFrom(other); 565| | } 566| | 567| | DenseMap(DenseMap &&other) : BaseT() { 568| | init(0); 569| | swap(other); 570| | } 571| | 572| | template 573| | DenseMap(const InputIt &I, const InputIt &E) { 574| | init(NextPowerOf2(std::distance(I, E))); 575| | this->insert(I, E); 576| | } 577| | 578| 0| ~DenseMap() { 579| 0| this->destroyAll(); 580| 0| operator delete(Buckets); 581| 0| } 582| | 583| | void swap(DenseMap& RHS) { 584| | std::swap(Buckets, RHS.Buckets); 585| | std::swap(NumEntries, RHS.NumEntries); 586| | std::swap(NumTombstones, RHS.NumTombstones); 587| | std::swap(NumBuckets, RHS.NumBuckets); 588| | } 589| | 590| | DenseMap& operator=(const DenseMap& other) { 591| | if (&other != this) 592| | copyFrom(other); 593| | return *this; 594| | } 595| | 596| | DenseMap& operator=(DenseMap &&other) { 597| | this->destroyAll(); 598| | operator delete(Buckets); 599| | init(0); 600| | swap(other); 601| | return *this; 602| | } 603| | 604| | void copyFrom(const DenseMap& other) { 605| | this->destroyAll(); 606| | operator delete(Buckets); 607| | if (allocateBuckets(other.NumBuckets)) { 608| | this->BaseT::copyFrom(other); 609| | } else { 610| | NumEntries = 0; 611| | NumTombstones = 0; 612| | } 613| | } 614| | 615| 0| void init(unsigned InitBuckets) { 616| 0| if (allocateBuckets(InitBuckets)) { 617| 0| this->BaseT::initEmpty(); 618| 0| } else { 619| 0| NumEntries = 0; 620| 0| NumTombstones = 0; 621| 0| } 622| 0| } 623| | 624| 0| void grow(unsigned AtLeast) { 625| 0| unsigned OldNumBuckets = NumBuckets; 626| 0| BucketT *OldBuckets = Buckets; 627| 0| 628| 0| allocateBuckets(std::max(64, static_cast(NextPowerOf2(AtLeast-1)))); 629| 0| assert(Buckets); 630| 0| if (!OldBuckets) { 631| 0| this->BaseT::initEmpty(); 632| 0| return; 633| 0| } 634| 0| 635| 0| this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); 636| 0| 637| 0| // Free the old table. 638| 0| operator delete(OldBuckets); 639| 0| } 640| | 641| | void shrink_and_clear() { 642| | unsigned OldNumEntries = NumEntries; 643| | this->destroyAll(); 644| | 645| | // Reduce the number of buckets. 646| | unsigned NewNumBuckets = 0; 647| | if (OldNumEntries) 648| | NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); 649| | if (NewNumBuckets == NumBuckets) { 650| | this->BaseT::initEmpty(); 651| | return; 652| | } 653| | 654| | operator delete(Buckets); 655| | init(NewNumBuckets); 656| | } 657| | 658| |private: 659| 0| unsigned getNumEntries() const { 660| 0| return NumEntries; 661| 0| } 662| 0| void setNumEntries(unsigned Num) { 663| 0| NumEntries = Num; 664| 0| } 665| | 666| 0| unsigned getNumTombstones() const { 667| 0| return NumTombstones; 668| 0| } 669| 0| void setNumTombstones(unsigned Num) { 670| 0| NumTombstones = Num; 671| 0| } 672| | 673| 0| BucketT *getBuckets() const { 674| 0| return Buckets; 675| 0| } 676| | 677| 0| unsigned getNumBuckets() const { 678| 0| return NumBuckets; 679| 0| } 680| | 681| 0| bool allocateBuckets(unsigned Num) { 682| 0| NumBuckets = Num; 683| 0| if (NumBuckets == 0) { 684| 0| Buckets = nullptr; 685| 0| return false; 686| 0| } 687| 0| 688| 0| Buckets = static_cast(operator new(sizeof(BucketT) * NumBuckets)); 689| 0| return true; 690| 0| } 691| |}; 692| | 693| |template , 695| | typename BucketT = detail::DenseMapPair> 696| |class SmallDenseMap 697| | : public DenseMapBase< 698| | SmallDenseMap, KeyT, 699| | ValueT, KeyInfoT, BucketT> { 700| | // Lift some types from the dependent base class into this class for 701| | // simplicity of referring to them. 702| | typedef DenseMapBase BaseT; 703| | friend class DenseMapBase; 704| | 705| | unsigned Small : 1; 706| | unsigned NumEntries : 31; 707| | unsigned NumTombstones; 708| | 709| | struct LargeRep { 710| | BucketT *Buckets; 711| | unsigned NumBuckets; 712| | }; 713| | 714| | /// A "union" of an inline bucket array and the struct representing 715| | /// a large bucket. This union will be discriminated by the 'Small' bit. 716| | AlignedCharArrayUnion storage; 717| | 718| |public: 719| | explicit SmallDenseMap(unsigned NumInitBuckets = 0) { 720| | init(NumInitBuckets); 721| | } 722| | 723| | SmallDenseMap(const SmallDenseMap &other) : BaseT() { 724| | init(0); 725| | copyFrom(other); 726| | } 727| | 728| | SmallDenseMap(SmallDenseMap &&other) : BaseT() { 729| | init(0); 730| | swap(other); 731| | } 732| | 733| | template 734| | SmallDenseMap(const InputIt &I, const InputIt &E) { 735| | init(NextPowerOf2(std::distance(I, E))); 736| | this->insert(I, E); 737| | } 738| | 739| | ~SmallDenseMap() { 740| | this->destroyAll(); 741| | deallocateBuckets(); 742| | } 743| | 744| | void swap(SmallDenseMap& RHS) { 745| | unsigned TmpNumEntries = RHS.NumEntries; 746| | RHS.NumEntries = NumEntries; 747| | NumEntries = TmpNumEntries; 748| | std::swap(NumTombstones, RHS.NumTombstones); 749| | 750| | const KeyT EmptyKey = this->getEmptyKey(); 751| | const KeyT TombstoneKey = this->getTombstoneKey(); 752| | if (Small && RHS.Small) { 753| | // If we're swapping inline bucket arrays, we have to cope with some of 754| | // the tricky bits of DenseMap's storage system: the buckets are not 755| | // fully initialized. Thus we swap every key, but we may have 756| | // a one-directional move of the value. 757| | for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 758| | BucketT *LHSB = &getInlineBuckets()[i], 759| | *RHSB = &RHS.getInlineBuckets()[i]; 760| | bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && 761| | !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); 762| | bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && 763| | !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); 764| | if (hasLHSValue && hasRHSValue) { 765| | // Swap together if we can... 766| | std::swap(*LHSB, *RHSB); 767| | continue; 768| | } 769| | // Swap separately and handle any assymetry. 770| | std::swap(LHSB->getFirst(), RHSB->getFirst()); 771| | if (hasLHSValue) { 772| | new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); 773| | LHSB->getSecond().~ValueT(); 774| | } else if (hasRHSValue) { 775| | new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); 776| | RHSB->getSecond().~ValueT(); 777| | } 778| | } 779| | return; 780| | } 781| | if (!Small && !RHS.Small) { 782| | std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); 783| | std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); 784| | return; 785| | } 786| | 787| | SmallDenseMap &SmallSide = Small ? *this : RHS; 788| | SmallDenseMap &LargeSide = Small ? RHS : *this; 789| | 790| | // First stash the large side's rep and move the small side across. 791| | LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); 792| | LargeSide.getLargeRep()->~LargeRep(); 793| | LargeSide.Small = true; 794| | // This is similar to the standard move-from-old-buckets, but the bucket 795| | // count hasn't actually rotated in this case. So we have to carefully 796| | // move construct the keys and values into their new locations, but there 797| | // is no need to re-hash things. 798| | for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 799| | BucketT *NewB = &LargeSide.getInlineBuckets()[i], 800| | *OldB = &SmallSide.getInlineBuckets()[i]; 801| | new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); 802| | OldB->getFirst().~KeyT(); 803| | if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && 804| | !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { 805| | new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); 806| | OldB->getSecond().~ValueT(); 807| | } 808| | } 809| | 810| | // The hard part of moving the small buckets across is done, just move 811| | // the TmpRep into its new home. 812| | SmallSide.Small = false; 813| | new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); 814| | } 815| | 816| | SmallDenseMap& operator=(const SmallDenseMap& other) { 817| | if (&other != this) 818| | copyFrom(other); 819| | return *this; 820| | } 821| | 822| | SmallDenseMap& operator=(SmallDenseMap &&other) { 823| | this->destroyAll(); 824| | deallocateBuckets(); 825| | init(0); 826| | swap(other); 827| | return *this; 828| | } 829| | 830| | void copyFrom(const SmallDenseMap& other) { 831| | this->destroyAll(); 832| | deallocateBuckets(); 833| | Small = true; 834| | if (other.getNumBuckets() > InlineBuckets) { 835| | Small = false; 836| | new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); 837| | } 838| | this->BaseT::copyFrom(other); 839| | } 840| | 841| | void init(unsigned InitBuckets) { 842| | Small = true; 843| | if (InitBuckets > InlineBuckets) { 844| | Small = false; 845| | new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); 846| | } 847| | this->BaseT::initEmpty(); 848| | } 849| | 850| | void grow(unsigned AtLeast) { 851| | if (AtLeast >= InlineBuckets) 852| | AtLeast = std::max(64, NextPowerOf2(AtLeast-1)); 853| | 854| | if (Small) { 855| | if (AtLeast < InlineBuckets) 856| | return; // Nothing to do. 857| | 858| | // First move the inline buckets into a temporary storage. 859| | AlignedCharArrayUnion TmpStorage; 860| | BucketT *TmpBegin = reinterpret_cast(TmpStorage.buffer); 861| | BucketT *TmpEnd = TmpBegin; 862| | 863| | // Loop over the buckets, moving non-empty, non-tombstones into the 864| | // temporary storage. Have the loop move the TmpEnd forward as it goes. 865| | const KeyT EmptyKey = this->getEmptyKey(); 866| | const KeyT TombstoneKey = this->getTombstoneKey(); 867| | for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { 868| | if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 869| | !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 870| | assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && 871| | "Too many inline buckets!"); 872| | new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); 873| | new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); 874| | ++TmpEnd; 875| | P->getSecond().~ValueT(); 876| | } 877| | P->getFirst().~KeyT(); 878| | } 879| | 880| | // Now make this map use the large rep, and move all the entries back 881| | // into it. 882| | Small = false; 883| | new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 884| | this->moveFromOldBuckets(TmpBegin, TmpEnd); 885| | return; 886| | } 887| | 888| | LargeRep OldRep = std::move(*getLargeRep()); 889| | getLargeRep()->~LargeRep(); 890| | if (AtLeast <= InlineBuckets) { 891| | Small = true; 892| | } else { 893| | new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 894| | } 895| | 896| | this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); 897| | 898| | // Free the old table. 899| | operator delete(OldRep.Buckets); 900| | } 901| | 902| | void shrink_and_clear() { 903| | unsigned OldSize = this->size(); 904| | this->destroyAll(); 905| | 906| | // Reduce the number of buckets. 907| | unsigned NewNumBuckets = 0; 908| | if (OldSize) { 909| | NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); 910| | if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) 911| | NewNumBuckets = 64; 912| | } 913| | if ((Small && NewNumBuckets <= InlineBuckets) || 914| | (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { 915| | this->BaseT::initEmpty(); 916| | return; 917| | } 918| | 919| | deallocateBuckets(); 920| | init(NewNumBuckets); 921| | } 922| | 923| |private: 924| | unsigned getNumEntries() const { 925| | return NumEntries; 926| | } 927| | void setNumEntries(unsigned Num) { 928| | assert(Num < INT_MAX && "Cannot support more than INT_MAX entries"); 929| | NumEntries = Num; 930| | } 931| | 932| | unsigned getNumTombstones() const { 933| | return NumTombstones; 934| | } 935| | void setNumTombstones(unsigned Num) { 936| | NumTombstones = Num; 937| | } 938| | 939| | const BucketT *getInlineBuckets() const { 940| | assert(Small); 941| | // Note that this cast does not violate aliasing rules as we assert that 942| | // the memory's dynamic type is the small, inline bucket buffer, and the 943| | // 'storage.buffer' static type is 'char *'. 944| | return reinterpret_cast(storage.buffer); 945| | } 946| | BucketT *getInlineBuckets() { 947| | return const_cast( 948| | const_cast(this)->getInlineBuckets()); 949| | } 950| | const LargeRep *getLargeRep() const { 951| | assert(!Small); 952| | // Note, same rule about aliasing as with getInlineBuckets. 953| | return reinterpret_cast(storage.buffer); 954| | } 955| | LargeRep *getLargeRep() { 956| | return const_cast( 957| | const_cast(this)->getLargeRep()); 958| | } 959| | 960| | const BucketT *getBuckets() const { 961| | return Small ? getInlineBuckets() : getLargeRep()->Buckets; 962| | } 963| | BucketT *getBuckets() { 964| | return const_cast( 965| | const_cast(this)->getBuckets()); 966| | } 967| | unsigned getNumBuckets() const { 968| | return Small ? InlineBuckets : getLargeRep()->NumBuckets; 969| | } 970| | 971| | void deallocateBuckets() { 972| | if (Small) 973| | return; 974| | 975| | operator delete(getLargeRep()->Buckets); 976| | getLargeRep()->~LargeRep(); 977| | } 978| | 979| | LargeRep allocateBuckets(unsigned Num) { 980| | assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); 981| | LargeRep Rep = { 982| | static_cast(operator new(sizeof(BucketT) * Num)), Num 983| | }; 984| | return Rep; 985| | } 986| |}; 987| | 988| |template 990| |class DenseMapIterator { 991| | typedef DenseMapIterator ConstIterator; 992| | friend class DenseMapIterator; 993| | 994| |public: 995| | typedef ptrdiff_t difference_type; 996| | typedef typename std::conditional::type 997| | value_type; 998| | typedef value_type *pointer; 999| | typedef value_type &reference; 1000| | typedef std::forward_iterator_tag iterator_category; 1001| |private: 1002| | pointer Ptr, End; 1003| |public: 1004| | DenseMapIterator() : Ptr(nullptr), End(nullptr) {} 1005| | 1006| | DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false) 1007| 0| : Ptr(Pos), End(E) { 1008| 0| if (!NoAdvance) AdvancePastEmptyBuckets(); 1009| 0| } 1010| | 1011| | // Converting ctor from non-const iterators to const iterators. SFINAE'd out 1012| | // for const iterator destinations so it doesn't end up as a user defined copy 1013| | // constructor. 1014| | template ::type> 1016| | DenseMapIterator( 1017| | const DenseMapIterator &I) 1018| 0| : Ptr(I.Ptr), End(I.End) {} 1019| | 1020| 0| reference operator*() const { 1021| 0| return *Ptr; 1022| 0| } 1023| 0| pointer operator->() const { 1024| 0| return Ptr; 1025| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorImNSt3__16vectorIhNS1_9allocatorIhEEEENS_12DenseMapInfoImEENS_6detail12DenseMapPairImS5_EELb1EEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorImNSt3__16vectorIhNS1_9allocatorIhEEEENS_12DenseMapInfoImEENS_6detail12DenseMapPairImS5_EELb0EEptEv ------------------ 1026| | 1027| 0| bool operator==(const ConstIterator &RHS) const { 1028| 0| return Ptr == RHS.operator->(); 1029| 0| } 1030| | bool operator!=(const ConstIterator &RHS) const { 1031| | return Ptr != RHS.operator->(); 1032| | } 1033| | 1034| | inline DenseMapIterator& operator++() { // Preincrement 1035| | ++Ptr; 1036| | AdvancePastEmptyBuckets(); 1037| | return *this; 1038| | } 1039| | DenseMapIterator operator++(int) { // Postincrement 1040| | DenseMapIterator tmp = *this; ++*this; return tmp; 1041| | } 1042| | 1043| |private: 1044| 0| void AdvancePastEmptyBuckets() { 1045| 0| const KeyT Empty = KeyInfoT::getEmptyKey(); 1046| 0| const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 1047| 0| 1048| 0| while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || 1049| 0| KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) 1050| 0| ++Ptr; 1051| 0| } 1052| |}; 1053| | 1054| |template 1055| |static inline size_t 1056| |capacity_in_bytes(const DenseMap &X) { 1057| | return X.getMemorySize(); 1058| |} 1059| | 1060| |} // end namespace llvm 1061| | 1062| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/DenseMapInfo.h: 1| |//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines DenseMapInfo traits for DenseMap. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_DENSEMAPINFO_H 15| |#define LLVM_ADT_DENSEMAPINFO_H 16| | 17| |#include "llvm/Support/PointerLikeTypeTraits.h" 18| |#include "llvm/Support/type_traits.h" 19| | 20| |namespace llvm { 21| | 22| |template 23| |struct DenseMapInfo { 24| | //static inline T getEmptyKey(); 25| | //static inline T getTombstoneKey(); 26| | //static unsigned getHashValue(const T &Val); 27| | //static bool isEqual(const T &LHS, const T &RHS); 28| |}; 29| | 30| |// Provide DenseMapInfo for all pointers. 31| |template 32| |struct DenseMapInfo { 33| | static inline T* getEmptyKey() { 34| | uintptr_t Val = static_cast(-1); 35| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 36| | return reinterpret_cast(Val); 37| | } 38| | static inline T* getTombstoneKey() { 39| | uintptr_t Val = static_cast(-2); 40| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 41| | return reinterpret_cast(Val); 42| | } 43| | static unsigned getHashValue(const T *PtrVal) { 44| | return (unsigned((uintptr_t)PtrVal) >> 4) ^ 45| | (unsigned((uintptr_t)PtrVal) >> 9); 46| | } 47| | static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } 48| |}; 49| | 50| |// Provide DenseMapInfo for chars. 51| |template<> struct DenseMapInfo { 52| 0| static inline char getEmptyKey() { return ~0; } 53| 0| static inline char getTombstoneKey() { return ~0 - 1; } 54| 0| static unsigned getHashValue(const char& Val) { return Val * 37U; } 55| 0| static bool isEqual(const char &LHS, const char &RHS) { 56| 0| return LHS == RHS; 57| 0| } 58| |}; 59| | 60| |// Provide DenseMapInfo for unsigned ints. 61| |template<> struct DenseMapInfo { 62| 0| static inline unsigned getEmptyKey() { return ~0U; } 63| 0| static inline unsigned getTombstoneKey() { return ~0U - 1; } 64| 0| static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } 65| 0| static bool isEqual(const unsigned& LHS, const unsigned& RHS) { 66| 0| return LHS == RHS; 67| 0| } 68| |}; 69| | 70| |// Provide DenseMapInfo for unsigned longs. 71| |template<> struct DenseMapInfo { 72| 0| static inline unsigned long getEmptyKey() { return ~0UL; } 73| 0| static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } 74| 0| static unsigned getHashValue(const unsigned long& Val) { 75| 0| return (unsigned)(Val * 37UL); 76| 0| } 77| 0| static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { 78| 0| return LHS == RHS; 79| 0| } 80| |}; 81| | 82| |// Provide DenseMapInfo for unsigned long longs. 83| |template<> struct DenseMapInfo { 84| | static inline unsigned long long getEmptyKey() { return ~0ULL; } 85| | static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } 86| | static unsigned getHashValue(const unsigned long long& Val) { 87| | return (unsigned)(Val * 37ULL); 88| | } 89| | static bool isEqual(const unsigned long long& LHS, 90| | const unsigned long long& RHS) { 91| | return LHS == RHS; 92| | } 93| |}; 94| | 95| |// Provide DenseMapInfo for ints. 96| |template<> struct DenseMapInfo { 97| 0| static inline int getEmptyKey() { return 0x7fffffff; } 98| 0| static inline int getTombstoneKey() { return -0x7fffffff - 1; } 99| 0| static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } 100| 0| static bool isEqual(const int& LHS, const int& RHS) { 101| 0| return LHS == RHS; 102| 0| } 103| |}; 104| | 105| |// Provide DenseMapInfo for longs. 106| |template<> struct DenseMapInfo { 107| 0| static inline long getEmptyKey() { 108| 0| return (1UL << (sizeof(long) * 8 - 1)) - 1UL; 109| 0| } 110| 0| static inline long getTombstoneKey() { return getEmptyKey() - 1L; } 111| 0| static unsigned getHashValue(const long& Val) { 112| 0| return (unsigned)(Val * 37UL); 113| 0| } 114| 0| static bool isEqual(const long& LHS, const long& RHS) { 115| 0| return LHS == RHS; 116| 0| } 117| |}; 118| | 119| |// Provide DenseMapInfo for long longs. 120| |template<> struct DenseMapInfo { 121| 0| static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } 122| 0| static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } 123| 0| static unsigned getHashValue(const long long& Val) { 124| 0| return (unsigned)(Val * 37ULL); 125| 0| } 126| | static bool isEqual(const long long& LHS, 127| 0| const long long& RHS) { 128| 0| return LHS == RHS; 129| 0| } 130| |}; 131| | 132| |// Provide DenseMapInfo for all pairs whose members have info. 133| |template 134| |struct DenseMapInfo > { 135| | typedef std::pair Pair; 136| | typedef DenseMapInfo FirstInfo; 137| | typedef DenseMapInfo SecondInfo; 138| | 139| | static inline Pair getEmptyKey() { 140| | return std::make_pair(FirstInfo::getEmptyKey(), 141| | SecondInfo::getEmptyKey()); 142| | } 143| | static inline Pair getTombstoneKey() { 144| | return std::make_pair(FirstInfo::getTombstoneKey(), 145| | SecondInfo::getTombstoneKey()); 146| | } 147| | static unsigned getHashValue(const Pair& PairVal) { 148| | uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 149| | | (uint64_t)SecondInfo::getHashValue(PairVal.second); 150| | key += ~(key << 32); 151| | key ^= (key >> 22); 152| | key += ~(key << 13); 153| | key ^= (key >> 8); 154| | key += (key << 3); 155| | key ^= (key >> 15); 156| | key += ~(key << 27); 157| | key ^= (key >> 31); 158| | return (unsigned)key; 159| | } 160| | static bool isEqual(const Pair &LHS, const Pair &RHS) { 161| | return FirstInfo::isEqual(LHS.first, RHS.first) && 162| | SecondInfo::isEqual(LHS.second, RHS.second); 163| | } 164| |}; 165| | 166| |} // end namespace llvm 167| | 168| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Hashing.h: 1| |//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the newly proposed standard C++ interfaces for hashing 11| |// arbitrary data and building hash functions for user-defined types. This 12| |// interface was originally proposed in N3333[1] and is currently under review 13| |// for inclusion in a future TR and/or standard. 14| |// 15| |// The primary interfaces provide are comprised of one type and three functions: 16| |// 17| |// -- 'hash_code' class is an opaque type representing the hash code for some 18| |// data. It is the intended product of hashing, and can be used to implement 19| |// hash tables, checksumming, and other common uses of hashes. It is not an 20| |// integer type (although it can be converted to one) because it is risky 21| |// to assume much about the internals of a hash_code. In particular, each 22| |// execution of the program has a high probability of producing a different 23| |// hash_code for a given input. Thus their values are not stable to save or 24| |// persist, and should only be used during the execution for the 25| |// construction of hashing datastructures. 26| |// 27| |// -- 'hash_value' is a function designed to be overloaded for each 28| |// user-defined type which wishes to be used within a hashing context. It 29| |// should be overloaded within the user-defined type's namespace and found 30| |// via ADL. Overloads for primitive types are provided by this library. 31| |// 32| |// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid 33| |// programmers in easily and intuitively combining a set of data into 34| |// a single hash_code for their object. They should only logically be used 35| |// within the implementation of a 'hash_value' routine or similar context. 36| |// 37| |// Note that 'hash_combine_range' contains very special logic for hashing 38| |// a contiguous array of integers or pointers. This logic is *extremely* fast, 39| |// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were 40| |// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys 41| |// under 32-bytes. 42| |// 43| |//===----------------------------------------------------------------------===// 44| | 45| |#ifndef LLVM_ADT_HASHING_H 46| |#define LLVM_ADT_HASHING_H 47| | 48| |#include "llvm/Support/DataTypes.h" 49| |#include "llvm/Support/Host.h" 50| |#include "llvm/Support/SwapByteOrder.h" 51| |#include "llvm/Support/type_traits.h" 52| |#include 53| |#include 54| |#include 55| |#include 56| |#include 57| | 58| |namespace llvm { 59| | 60| |/// \brief An opaque object representing a hash code. 61| |/// 62| |/// This object represents the result of hashing some entity. It is intended to 63| |/// be used to implement hashtables or other hashing-based data structures. 64| |/// While it wraps and exposes a numeric value, this value should not be 65| |/// trusted to be stable or predictable across processes or executions. 66| |/// 67| |/// In order to obtain the hash_code for an object 'x': 68| |/// \code 69| |/// using llvm::hash_value; 70| |/// llvm::hash_code code = hash_value(x); 71| |/// \endcode 72| |class hash_code { 73| | size_t value; 74| | 75| |public: 76| | /// \brief Default construct a hash_code. 77| | /// Note that this leaves the value uninitialized. 78| 0| hash_code() {} 79| | 80| | /// \brief Form a hash code directly from a numerical value. 81| 0| hash_code(size_t value) : value(value) {} 82| | 83| | /// \brief Convert the hash code to its numerical value for use. 84| 0| /*explicit*/ operator size_t() const { return value; } 85| | 86| 0| friend bool operator==(const hash_code &lhs, const hash_code &rhs) { 87| 0| return lhs.value == rhs.value; 88| 0| } 89| 0| friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { 90| 0| return lhs.value != rhs.value; 91| 0| } 92| | 93| | /// \brief Allow a hash_code to be directly run through hash_value. 94| 0| friend size_t hash_value(const hash_code &code) { return code.value; } 95| |}; 96| | 97| |/// \brief Compute a hash_code for any integer value. 98| |/// 99| |/// Note that this function is intended to compute the same hash_code for 100| |/// a particular value without regard to the pre-promotion type. This is in 101| |/// contrast to hash_combine which may produce different hash_codes for 102| |/// differing argument types even if they would implicit promote to a common 103| |/// type without changing the value. 104| |template 105| |typename std::enable_if::value, hash_code>::type 106| |hash_value(T value); 107| | 108| |/// \brief Compute a hash_code for a pointer's address. 109| |/// 110| |/// N.B.: This hashes the *address*. Not the value and not the type. 111| |template hash_code hash_value(const T *ptr); 112| | 113| |/// \brief Compute a hash_code for a pair of objects. 114| |template 115| |hash_code hash_value(const std::pair &arg); 116| | 117| |/// \brief Compute a hash_code for a standard string. 118| |template 119| |hash_code hash_value(const std::basic_string &arg); 120| | 121| | 122| |/// \brief Override the execution seed with a fixed value. 123| |/// 124| |/// This hashing library uses a per-execution seed designed to change on each 125| |/// run with high probability in order to ensure that the hash codes are not 126| |/// attackable and to ensure that output which is intended to be stable does 127| |/// not rely on the particulars of the hash codes produced. 128| |/// 129| |/// That said, there are use cases where it is important to be able to 130| |/// reproduce *exactly* a specific behavior. To that end, we provide a function 131| |/// which will forcibly set the seed to a fixed value. This must be done at the 132| |/// start of the program, before any hashes are computed. Also, it cannot be 133| |/// undone. This makes it thread-hostile and very hard to use outside of 134| |/// immediately on start of a simple program designed for reproducible 135| |/// behavior. 136| |void set_fixed_execution_hash_seed(size_t fixed_value); 137| | 138| | 139| |// All of the implementation details of actually computing the various hash 140| |// code values are held within this namespace. These routines are included in 141| |// the header file mainly to allow inlining and constant propagation. 142| |namespace hashing { 143| |namespace detail { 144| | 145| 0|inline uint64_t fetch64(const char *p) { 146| 0| uint64_t result; 147| 0| memcpy(&result, p, sizeof(result)); 148| 0| if (sys::IsBigEndianHost) 149| 0| sys::swapByteOrder(result); 150| 0| return result; 151| 0|} 152| | 153| 0|inline uint32_t fetch32(const char *p) { 154| 0| uint32_t result; 155| 0| memcpy(&result, p, sizeof(result)); 156| 0| if (sys::IsBigEndianHost) 157| 0| sys::swapByteOrder(result); 158| 0| return result; 159| 0|} 160| | 161| |/// Some primes between 2^63 and 2^64 for various uses. 162| |static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; 163| |static const uint64_t k1 = 0xb492b66fbe98f273ULL; 164| |static const uint64_t k2 = 0x9ae16a3b2f90404fULL; 165| |static const uint64_t k3 = 0xc949d7c7509e6557ULL; 166| | 167| |/// \brief Bitwise right rotate. 168| |/// Normally this will compile to a single instruction, especially if the 169| |/// shift is a manifest constant. 170| 0|inline uint64_t rotate(uint64_t val, size_t shift) { 171| 0| // Avoid shifting by 64: doing so yields an undefined result. 172| 0| return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); 173| 0|} 174| | 175| 0|inline uint64_t shift_mix(uint64_t val) { 176| 0| return val ^ (val >> 47); 177| 0|} 178| | 179| 0|inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { 180| 0| // Murmur-inspired hashing. 181| 0| const uint64_t kMul = 0x9ddfea08eb382d69ULL; 182| 0| uint64_t a = (low ^ high) * kMul; 183| 0| a ^= (a >> 47); 184| 0| uint64_t b = (high ^ a) * kMul; 185| 0| b ^= (b >> 47); 186| 0| b *= kMul; 187| 0| return b; 188| 0|} 189| | 190| 0|inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { 191| 0| uint8_t a = s[0]; 192| 0| uint8_t b = s[len >> 1]; 193| 0| uint8_t c = s[len - 1]; 194| 0| uint32_t y = static_cast(a) + (static_cast(b) << 8); 195| 0| uint32_t z = len + (static_cast(c) << 2); 196| 0| return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; 197| 0|} 198| | 199| 0|inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { 200| 0| uint64_t a = fetch32(s); 201| 0| return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); 202| 0|} 203| | 204| 0|inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { 205| 0| uint64_t a = fetch64(s); 206| 0| uint64_t b = fetch64(s + len - 8); 207| 0| return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; 208| 0|} 209| | 210| 0|inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { 211| 0| uint64_t a = fetch64(s) * k1; 212| 0| uint64_t b = fetch64(s + 8); 213| 0| uint64_t c = fetch64(s + len - 8) * k2; 214| 0| uint64_t d = fetch64(s + len - 16) * k0; 215| 0| return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, 216| 0| a + rotate(b ^ k3, 20) - c + len + seed); 217| 0|} 218| | 219| 0|inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { 220| 0| uint64_t z = fetch64(s + 24); 221| 0| uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; 222| 0| uint64_t b = rotate(a + z, 52); 223| 0| uint64_t c = rotate(a, 37); 224| 0| a += fetch64(s + 8); 225| 0| c += rotate(a, 7); 226| 0| a += fetch64(s + 16); 227| 0| uint64_t vf = a + z; 228| 0| uint64_t vs = b + rotate(a, 31) + c; 229| 0| a = fetch64(s + 16) + fetch64(s + len - 32); 230| 0| z = fetch64(s + len - 8); 231| 0| b = rotate(a + z, 52); 232| 0| c = rotate(a, 37); 233| 0| a += fetch64(s + len - 24); 234| 0| c += rotate(a, 7); 235| 0| a += fetch64(s + len - 16); 236| 0| uint64_t wf = a + z; 237| 0| uint64_t ws = b + rotate(a, 31) + c; 238| 0| uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); 239| 0| return shift_mix((seed ^ (r * k0)) + vs) * k2; 240| 0|} 241| | 242| 0|inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { 243| 0| if (length >= 4 && length <= 8) 244| 0| return hash_4to8_bytes(s, length, seed); 245| 0| if (length > 8 && length <= 16) 246| 0| return hash_9to16_bytes(s, length, seed); 247| 0| if (length > 16 && length <= 32) 248| 0| return hash_17to32_bytes(s, length, seed); 249| 0| if (length > 32) 250| 0| return hash_33to64_bytes(s, length, seed); 251| 0| if (length != 0) 252| 0| return hash_1to3_bytes(s, length, seed); 253| 0| 254| 0| return k2 ^ seed; 255| 0|} 256| | 257| |/// \brief The intermediate state used during hashing. 258| |/// Currently, the algorithm for computing hash codes is based on CityHash and 259| |/// keeps 56 bytes of arbitrary state. 260| |struct hash_state { 261| | uint64_t h0, h1, h2, h3, h4, h5, h6; 262| | 263| | /// \brief Create a new hash_state structure and initialize it based on the 264| | /// seed and the first 64-byte chunk. 265| | /// This effectively performs the initial mix. 266| 0| static hash_state create(const char *s, uint64_t seed) { 267| 0| hash_state state = { 268| 0| 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), 269| 0| seed * k1, shift_mix(seed), 0 }; 270| 0| state.h6 = hash_16_bytes(state.h4, state.h5); 271| 0| state.mix(s); 272| 0| return state; 273| 0| } 274| | 275| | /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' 276| | /// and 'b', including whatever is already in 'a' and 'b'. 277| 0| static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { 278| 0| a += fetch64(s); 279| 0| uint64_t c = fetch64(s + 24); 280| 0| b = rotate(b + a + c, 21); 281| 0| uint64_t d = a; 282| 0| a += fetch64(s + 8) + fetch64(s + 16); 283| 0| b += rotate(a, 44) + d; 284| 0| a += c; 285| 0| } 286| | 287| | /// \brief Mix in a 64-byte buffer of data. 288| | /// We mix all 64 bytes even when the chunk length is smaller, but we 289| | /// record the actual length. 290| 0| void mix(const char *s) { 291| 0| h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; 292| 0| h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; 293| 0| h0 ^= h6; 294| 0| h1 += h3 + fetch64(s + 40); 295| 0| h2 = rotate(h2 + h5, 33) * k1; 296| 0| h3 = h4 * k1; 297| 0| h4 = h0 + h5; 298| 0| mix_32_bytes(s, h3, h4); 299| 0| h5 = h2 + h6; 300| 0| h6 = h1 + fetch64(s + 16); 301| 0| mix_32_bytes(s + 32, h5, h6); 302| 0| std::swap(h2, h0); 303| 0| } 304| | 305| | /// \brief Compute the final 64-bit hash code value based on the current 306| | /// state and the length of bytes hashed. 307| 0| uint64_t finalize(size_t length) { 308| 0| return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, 309| 0| hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); 310| 0| } 311| |}; 312| | 313| | 314| |/// \brief A global, fixed seed-override variable. 315| |/// 316| |/// This variable can be set using the \see llvm::set_fixed_execution_seed 317| |/// function. See that function for details. Do not, under any circumstances, 318| |/// set or read this variable. 319| |extern size_t fixed_seed_override; 320| | 321| 0|inline size_t get_execution_seed() { 322| 0| // FIXME: This needs to be a per-execution seed. This is just a placeholder 323| 0| // implementation. Switching to a per-execution seed is likely to flush out 324| 0| // instability bugs and so will happen as its own commit. 325| 0| // 326| 0| // However, if there is a fixed seed override set the first time this is 327| 0| // called, return that instead of the per-execution seed. 328| 0| const uint64_t seed_prime = 0xff51afd7ed558ccdULL; 329| 0| static size_t seed = fixed_seed_override ? fixed_seed_override 330| 0| : (size_t)seed_prime; 331| 0| return seed; 332| 0|} 333| | 334| | 335| |/// \brief Trait to indicate whether a type's bits can be hashed directly. 336| |/// 337| |/// A type trait which is true if we want to combine values for hashing by 338| |/// reading the underlying data. It is false if values of this type must 339| |/// first be passed to hash_value, and the resulting hash_codes combined. 340| |// 341| |// FIXME: We want to replace is_integral_or_enum and is_pointer here with 342| |// a predicate which asserts that comparing the underlying storage of two 343| |// values of the type for equality is equivalent to comparing the two values 344| |// for equality. For all the platforms we care about, this holds for integers 345| |// and pointers, but there are platforms where it doesn't and we would like to 346| |// support user-defined types which happen to satisfy this property. 347| |template struct is_hashable_data 348| | : std::integral_constant::value || 349| | std::is_pointer::value) && 350| | 64 % sizeof(T) == 0)> {}; 351| | 352| |// Special case std::pair to detect when both types are viable and when there 353| |// is no alignment-derived padding in the pair. This is a bit of a lie because 354| |// std::pair isn't truly POD, but it's close enough in all reasonable 355| |// implementations for our use case of hashing the underlying data. 356| |template struct is_hashable_data > 357| | : std::integral_constant::value && 358| | is_hashable_data::value && 359| | (sizeof(T) + sizeof(U)) == 360| | sizeof(std::pair))> {}; 361| | 362| |/// \brief Helper to get the hashable data representation for a type. 363| |/// This variant is enabled when the type itself can be used. 364| |template 365| |typename std::enable_if::value, T>::type 366| 0|get_hashable_data(const T &value) { 367| 0| return value; 368| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataIyEENSt3__19enable_ifIXsr16is_hashable_dataIT_EE5valueES5_E4typeERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataIcEENSt3__19enable_ifIXsr16is_hashable_dataIT_EE5valueES5_E4typeERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataIbEENSt3__19enable_ifIXsr16is_hashable_dataIT_EE5valueES5_E4typeERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataIhEENSt3__19enable_ifIXsr16is_hashable_dataIT_EE5valueES5_E4typeERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataImEENSt3__19enable_ifIXsr16is_hashable_dataIT_EE5valueES5_E4typeERKS5_ ------------------ 369| |/// \brief Helper to get the hashable data representation for a type. 370| |/// This variant is enabled when we must first call hash_value and use the 371| |/// result as our data. 372| |template 373| |typename std::enable_if::value, size_t>::type 374| 0|get_hashable_data(const T &value) { 375| 0| using ::llvm::hash_value; 376| 0| return hash_value(value); 377| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEENS3_9enable_ifIXntsr16is_hashable_dataIT_EE5valueEmE4typeERKSB_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataINS_9StringRefEEENSt3__19enable_ifIXntsr16is_hashable_dataIT_EE5valueEmE4typeERKS6_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17get_hashable_dataINS_9hash_codeEEENSt3__19enable_ifIXntsr16is_hashable_dataIT_EE5valueEmE4typeERKS6_ ------------------ 378| | 379| |/// \brief Helper to store data from a value into a buffer and advance the 380| |/// pointer into that buffer. 381| |/// 382| |/// This routine first checks whether there is enough space in the provided 383| |/// buffer, and if not immediately returns false. If there is space, it 384| |/// copies the underlying bytes of value into the buffer, advances the 385| |/// buffer_ptr past the copied bytes, and returns true. 386| |template 387| |bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, 388| 0| size_t offset = 0) { 389| 0| size_t store_size = sizeof(value) - offset; 390| 0| if (buffer_ptr + store_size > buffer_end) 391| 0| return false; 392| 0| const char *value_data = reinterpret_cast(&value); 393| 0| memcpy(buffer_ptr, value_data + offset, store_size); 394| 0| buffer_ptr += store_size; 395| 0| return true; 396| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceIyEEbRPcS3_RKT_m ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceImEEbRPcS3_RKT_m ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceIcEEbRPcS3_RKT_m ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceIbEEbRPcS3_RKT_m ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail17store_and_advanceIhEEbRPcS3_RKT_m ------------------ 397| | 398| |/// \brief Implement the combining of integral values into a hash_code. 399| |/// 400| |/// This overload is selected when the value type of the iterator is 401| |/// integral. Rather than computing a hash_code for each object and then 402| |/// combining them, this (as an optimization) directly combines the integers. 403| |template 404| 0|hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { 405| 0| const size_t seed = get_execution_seed(); 406| 0| char buffer[64], *buffer_ptr = buffer; 407| 0| char *const buffer_end = std::end(buffer); 408| 0| while (first != last && store_and_advance(buffer_ptr, buffer_end, 409| 0| get_hashable_data(*first))) 410| 0| ++first; 411| 0| if (first == last) 412| 0| return hash_short(buffer, buffer_ptr - buffer, seed); 413| 0| assert(buffer_ptr == buffer_end); 414| 0| 415| 0| hash_state state = state.create(buffer, seed); 416| 0| size_t length = 64; 417| 0| while (first != last) { 418| 0| // Fill up the buffer. We don't clear it, which re-mixes the last round 419| 0| // when only a partial 64-byte chunk is left. 420| 0| buffer_ptr = buffer; 421| 0| while (first != last && store_and_advance(buffer_ptr, buffer_end, 422| 0| get_hashable_data(*first))) 423| 0| ++first; 424| 0| 425| 0| // Rotate the buffer if we did a partial fill in order to simulate doing 426| 0| // a mix of the last 64-bytes. That is how the algorithm works when we 427| 0| // have a contiguous byte sequence, and we want to emulate that here. 428| 0| std::rotate(buffer, buffer_ptr, buffer_end); 429| 0| 430| 0| // Mix this chunk into the current state. 431| 0| state.mix(buffer); 432| 0| length += buffer_ptr - buffer; 433| 0| }; 434| 0| 435| 0| return state.finalize(length); 436| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail23hash_combine_range_implINSt3__111__wrap_iterIPKcEEEENS_9hash_codeET_S9_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail23hash_combine_range_implINSt3__111__wrap_iterIPhEEEENS_9hash_codeET_S8_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail23hash_combine_range_implINSt3__111__wrap_iterIPKhEEEENS_9hash_codeET_S9_ ------------------ 437| | 438| |/// \brief Implement the combining of integral values into a hash_code. 439| |/// 440| |/// This overload is selected when the value type of the iterator is integral 441| |/// and when the input iterator is actually a pointer. Rather than computing 442| |/// a hash_code for each object and then combining them, this (as an 443| |/// optimization) directly combines the integers. Also, because the integers 444| |/// are stored in contiguous memory, this routine avoids copying each value 445| |/// and directly reads from the underlying memory. 446| |template 447| |typename std::enable_if::value, hash_code>::type 448| |hash_combine_range_impl(ValueT *first, ValueT *last) { 449| | const size_t seed = get_execution_seed(); 450| | const char *s_begin = reinterpret_cast(first); 451| | const char *s_end = reinterpret_cast(last); 452| | const size_t length = std::distance(s_begin, s_end); 453| | if (length <= 64) 454| | return hash_short(s_begin, length, seed); 455| | 456| | const char *s_aligned_end = s_begin + (length & ~63); 457| | hash_state state = state.create(s_begin, seed); 458| | s_begin += 64; 459| | while (s_begin != s_aligned_end) { 460| | state.mix(s_begin); 461| | s_begin += 64; 462| | } 463| | if (length & 63) 464| | state.mix(s_end - 64); 465| | 466| | return state.finalize(length); 467| |} 468| | 469| |} // namespace detail 470| |} // namespace hashing 471| | 472| | 473| |/// \brief Compute a hash_code for a sequence of values. 474| |/// 475| |/// This hashes a sequence of values. It produces the same hash_code as 476| |/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences 477| |/// and is significantly faster given pointers and types which can be hashed as 478| |/// a sequence of bytes. 479| |template 480| 0|hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { 481| 0| return ::llvm::hashing::detail::hash_combine_range_impl(first, last); 482| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm18hash_combine_rangeINSt3__111__wrap_iterIPKcEEEENS_9hash_codeET_S7_ ------------------ | Unexecuted instantiation: _ZN4llvm18hash_combine_rangeINSt3__111__wrap_iterIPhEEEENS_9hash_codeET_S6_ ------------------ | Unexecuted instantiation: _ZN4llvm18hash_combine_rangeINSt3__111__wrap_iterIPKhEEEENS_9hash_codeET_S7_ ------------------ 483| | 484| | 485| |// Implementation details for hash_combine. 486| |namespace hashing { 487| |namespace detail { 488| | 489| |/// \brief Helper class to manage the recursive combining of hash_combine 490| |/// arguments. 491| |/// 492| |/// This class exists to manage the state and various calls involved in the 493| |/// recursive combining of arguments used in hash_combine. It is particularly 494| |/// useful at minimizing the code in the recursive calls to ease the pain 495| |/// caused by a lack of variadic functions. 496| |struct hash_combine_recursive_helper { 497| | char buffer[64]; 498| | hash_state state; 499| | const size_t seed; 500| | 501| |public: 502| | /// \brief Construct a recursive hash combining helper. 503| | /// 504| | /// This sets up the state for a recursive hash combine, including getting 505| | /// the seed and buffer setup. 506| | hash_combine_recursive_helper() 507| 0| : seed(get_execution_seed()) {} 508| | 509| | /// \brief Combine one chunk of data into the current in-flight hash. 510| | /// 511| | /// This merges one chunk of data into the hash. First it tries to buffer 512| | /// the data. If the buffer is full, it hashes the buffer into its 513| | /// hash_state, empties it, and then merges the new chunk in. This also 514| | /// handles cases where the data straddles the end of the buffer. 515| | template 516| 0| char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { 517| 0| if (!store_and_advance(buffer_ptr, buffer_end, data)) { 518| 0| // Check for skew which prevents the buffer from being packed, and do 519| 0| // a partial store into the buffer to fill it. This is only a concern 520| 0| // with the variadic combine because that formation can have varying 521| 0| // argument types. 522| 0| size_t partial_store_size = buffer_end - buffer_ptr; 523| 0| memcpy(buffer_ptr, &data, partial_store_size); 524| 0| 525| 0| // If the store fails, our buffer is full and ready to hash. We have to 526| 0| // either initialize the hash state (on the first full buffer) or mix 527| 0| // this buffer into the existing hash state. Length tracks the *hashed* 528| 0| // length, not the buffered length. 529| 0| if (length == 0) { 530| 0| state = state.create(buffer, seed); 531| 0| length = 64; 532| 0| } else { 533| 0| // Mix this chunk into the current state and bump length up by 64. 534| 0| state.mix(buffer); 535| 0| length += 64; 536| 0| } 537| 0| // Reset the buffer_ptr to the head of the buffer for the next chunk of 538| 0| // data. 539| 0| buffer_ptr = buffer; 540| 0| 541| 0| // Try again to store into the buffer -- this cannot fail as we only 542| 0| // store types smaller than the buffer. 543| 0| if (!store_and_advance(buffer_ptr, buffer_end, data, 544| 0| partial_store_size)) 545| 0| abort(); 546| 0| } 547| 0| return buffer_ptr; 548| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper12combine_dataIyEEPcRmS4_S4_T_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper12combine_dataImEEPcRmS4_S4_T_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper12combine_dataIbEEPcRmS4_S4_T_ ------------------ 549| | 550| | /// \brief Recursive, variadic combining method. 551| | /// 552| | /// This function recurses through each argument, combining that argument 553| | /// into a single hash. 554| | template 555| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, 556| 0| const T &arg, const Ts &...args) { 557| 0| buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); 558| 0| 559| 0| // Recurse to the next argument. 560| 0| return combine(length, buffer_ptr, buffer_end, args...); 561| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIyJNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEEENS_9hash_codeEmPcSC_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEJEEENS_9hash_codeEmPcSC_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIyJNS_9StringRefEEEENS_9hash_codeEmPcS6_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9StringRefEJEEENS_9hash_codeEmPcS6_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIyJbEEENS_9hash_codeEmPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIbJEEENS_9hash_codeEmPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9hash_codeEJS4_EEES4_mPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9hash_codeEJEEES4_mPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9hash_codeEJmEEES4_mPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineImJEEENS_9hash_codeEmPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9hash_codeEJyEEES4_mPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineIyJEEENS_9hash_codeEmPcS5_RKT_DpRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm7hashing6detail29hash_combine_recursive_helper7combineINS_9hash_codeEJNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEES4_mPcSC_RKT_DpRKT0_ ------------------ 562| | 563| | /// \brief Base case for recursive, variadic combining. 564| | /// 565| | /// The base case when combining arguments recursively is reached when all 566| | /// arguments have been handled. It flushes the remaining buffer and 567| | /// constructs a hash_code. 568| 0| hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { 569| 0| // Check whether the entire set of values fit in the buffer. If so, we'll 570| 0| // use the optimized short hashing routine and skip state entirely. 571| 0| if (length == 0) 572| 0| return hash_short(buffer, buffer_ptr - buffer, seed); 573| 0| 574| 0| // Mix the final buffer, rotating it if we did a partial fill in order to 575| 0| // simulate doing a mix of the last 64-bytes. That is how the algorithm 576| 0| // works when we have a contiguous byte sequence, and we want to emulate 577| 0| // that here. 578| 0| std::rotate(buffer, buffer_ptr, buffer_end); 579| 0| 580| 0| // Mix this chunk into the current state. 581| 0| state.mix(buffer); 582| 0| length += buffer_ptr - buffer; 583| 0| 584| 0| return state.finalize(length); 585| 0| } 586| |}; 587| | 588| |} // namespace detail 589| |} // namespace hashing 590| | 591| |/// \brief Combine values into a single hash_code. 592| |/// 593| |/// This routine accepts a varying number of arguments of any type. It will 594| |/// attempt to combine them into a single hash_code. For user-defined types it 595| |/// attempts to call a \see hash_value overload (via ADL) for the type. For 596| |/// integer and pointer types it directly combines their data into the 597| |/// resulting hash_code. 598| |/// 599| |/// The result is suitable for returning from a user's hash_value 600| |/// *implementation* for their user-defined type. Consumers of a type should 601| |/// *not* call this routine, they should instead call 'hash_value'. 602| 0|template hash_code hash_combine(const Ts &...args) { 603| 0| // Recursively hash each argument using a helper class. 604| 0| ::llvm::hashing::detail::hash_combine_recursive_helper helper; 605| 0| return helper.combine(0, helper.buffer, helper.buffer + 64, args...); 606| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJyNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEENS_9hash_codeEDpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJyNS_9StringRefEEEENS_9hash_codeEDpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJybEEENS_9hash_codeEDpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJNS_9hash_codeES1_EEES1_DpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJNS_9hash_codeEmEEES1_DpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJNS_9hash_codeEyEEES1_DpRKT_ ------------------ | Unexecuted instantiation: _ZN4llvm12hash_combineIJNS_9hash_codeENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEES1_DpRKT_ ------------------ 607| | 608| |// Implementation details for implementations of hash_value overloads provided 609| |// here. 610| |namespace hashing { 611| |namespace detail { 612| | 613| |/// \brief Helper to hash the value of a single integer. 614| |/// 615| |/// Overloads for smaller integer types are not provided to ensure consistent 616| |/// behavior in the presence of integral promotions. Essentially, 617| |/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. 618| 0|inline hash_code hash_integer_value(uint64_t value) { 619| 0| // Similar to hash_4to8_bytes but using a seed instead of length. 620| 0| const uint64_t seed = get_execution_seed(); 621| 0| const char *s = reinterpret_cast(&value); 622| 0| const uint64_t a = fetch32(s); 623| 0| return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); 624| 0|} 625| | 626| |} // namespace detail 627| |} // namespace hashing 628| | 629| |// Declared and documented above, but defined here so that any of the hashing 630| |// infrastructure is available. 631| |template 632| |typename std::enable_if::value, hash_code>::type 633| |hash_value(T value) { 634| | return ::llvm::hashing::detail::hash_integer_value(value); 635| |} 636| | 637| |// Declared and documented above, but defined here so that any of the hashing 638| |// infrastructure is available. 639| |template hash_code hash_value(const T *ptr) { 640| | return ::llvm::hashing::detail::hash_integer_value( 641| | reinterpret_cast(ptr)); 642| |} 643| | 644| |// Declared and documented above, but defined here so that any of the hashing 645| |// infrastructure is available. 646| |template 647| |hash_code hash_value(const std::pair &arg) { 648| | return hash_combine(arg.first, arg.second); 649| |} 650| | 651| |// Declared and documented above, but defined here so that any of the hashing 652| |// infrastructure is available. 653| |template 654| 0|hash_code hash_value(const std::basic_string &arg) { 655| 0| return hash_combine_range(arg.begin(), arg.end()); 656| 0|} 657| | 658| |} // namespace llvm 659| | 660| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/IntrusiveRefCntPtr.h: 1| |//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines IntrusiveRefCntPtr, a template class that 11| |// implements a "smart" pointer for objects that maintain their own 12| |// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 13| |// generic base classes for objects that wish to have their lifetimes 14| |// managed using reference counting. 15| |// 16| |// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 17| |// LLVM-style casting. 18| |// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H 22| |#define LLVM_ADT_INTRUSIVEREFCNTPTR_H 23| | 24| |#include "llvm/Support/Casting.h" 25| |#include "llvm/Support/Compiler.h" 26| |#include 27| |#include 28| | 29| |namespace llvm { 30| | 31| | template 32| | class IntrusiveRefCntPtr; 33| | 34| |//===----------------------------------------------------------------------===// 35| |/// RefCountedBase - A generic base class for objects that wish to 36| |/// have their lifetimes managed using reference counts. Classes 37| |/// subclass RefCountedBase to obtain such functionality, and are 38| |/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 39| |/// which automatically handle the management of reference counts. 40| |/// Objects that subclass RefCountedBase should not be allocated on 41| |/// the stack, as invoking "delete" (which is called when the 42| |/// reference count hits 0) on such objects is an error. 43| |//===----------------------------------------------------------------------===// 44| | template 45| | class RefCountedBase { 46| | mutable unsigned ref_cnt; 47| | 48| | public: 49| 0| RefCountedBase() : ref_cnt(0) {} 50| | RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 51| | 52| 0| void Retain() const { ++ref_cnt; } ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail12DirIterStateEE6RetainEv ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail15RecDirIterStateEE6RetainEv ------------------ 53| 0| void Release() const { 54| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 55| 0| if (--ref_cnt == 0) delete static_cast(this); 56| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail12DirIterStateEE7ReleaseEv ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail15RecDirIterStateEE7ReleaseEv ------------------ 57| | }; 58| | 59| |//===----------------------------------------------------------------------===// 60| |/// RefCountedBaseVPTR - A class that has the same function as 61| |/// RefCountedBase, but with a virtual destructor. Should be used 62| |/// instead of RefCountedBase for classes that already have virtual 63| |/// methods to enforce dynamic allocation via 'new'. Classes that 64| |/// inherit from RefCountedBaseVPTR can't be allocated on stack - 65| |/// attempting to do this will produce a compile error. 66| |//===----------------------------------------------------------------------===// 67| | class RefCountedBaseVPTR { 68| | mutable unsigned ref_cnt; 69| | virtual void anchor(); 70| | 71| | protected: 72| 0| RefCountedBaseVPTR() : ref_cnt(0) {} 73| 0| RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 74| | 75| 0| virtual ~RefCountedBaseVPTR() {} 76| | 77| 0| void Retain() const { ++ref_cnt; } 78| 0| void Release() const { 79| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 80| 0| if (--ref_cnt == 0) delete this; 81| 0| } 82| | 83| | template 84| | friend struct IntrusiveRefCntPtrInfo; 85| | }; 86| | 87| | 88| | template struct IntrusiveRefCntPtrInfo { 89| 0| static void retain(T *obj) { obj->Retain(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE6retainEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE6retainEPS4_ ------------------ 90| 0| static void release(T *obj) { obj->Release(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE7releaseEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE7releaseEPS4_ ------------------ 91| | }; 92| | 93| |/// \brief A thread-safe version of \c llvm::RefCountedBase. 94| |/// 95| |/// A generic base class for objects that wish to have their lifetimes managed 96| |/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to 97| |/// obtain such functionality, and are typically handled with 98| |/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the 99| |/// management of reference counts. 100| |template 101| |class ThreadSafeRefCountedBase { 102| | mutable std::atomic RefCount; 103| | 104| |protected: 105| | ThreadSafeRefCountedBase() : RefCount(0) {} 106| | 107| |public: 108| | void Retain() const { ++RefCount; } 109| | 110| | void Release() const { 111| | int NewRefCount = --RefCount; 112| | assert(NewRefCount >= 0 && "Reference count was already zero."); 113| | if (NewRefCount == 0) 114| | delete static_cast(this); 115| | } 116| |}; 117| | 118| |//===----------------------------------------------------------------------===// 119| |/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 120| |/// that assumes the wrapped object has a reference count associated 121| |/// with it that can be managed via calls to 122| |/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 123| |/// manage reference counts via the RAII idiom: upon creation of 124| |/// smart pointer the reference count of the wrapped object is 125| |/// incremented and upon destruction of the smart pointer the 126| |/// reference count is decremented. This class also safely handles 127| |/// wrapping NULL pointers. 128| |/// 129| |/// Reference counting is implemented via calls to 130| |/// Obj->Retain()/Obj->Release(). Release() is required to destroy 131| |/// the object when the reference count reaches zero. Inheriting from 132| |/// RefCountedBase/RefCountedBaseVPTR takes care of this 133| |/// automatically. 134| |//===----------------------------------------------------------------------===// 135| | template 136| | class IntrusiveRefCntPtr { 137| | T* Obj; 138| | 139| | public: 140| | typedef T element_type; 141| | 142| 0| explicit IntrusiveRefCntPtr() : Obj(nullptr) {} 143| | 144| 0| IntrusiveRefCntPtr(T* obj) : Obj(obj) { 145| 0| retain(); 146| 0| } 147| | 148| 0| IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 149| 0| retain(); 150| 0| } 151| | 152| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 153| | S.Obj = nullptr; 154| | } 155| | 156| | template 157| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.get()) { 158| | S.Obj = 0; 159| | } 160| | 161| | template 162| | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) 163| | : Obj(S.get()) { 164| | retain(); 165| | } 166| | 167| 0| IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 168| 0| swap(S); 169| 0| return *this; 170| 0| } 171| | 172| 0| ~IntrusiveRefCntPtr() { release(); } 173| | 174| 0| T& operator*() const { return *Obj; } 175| | 176| 0| T* operator->() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEEptEv ------------------ 177| | 178| 0| T* get() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE3getEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE3getEv ------------------ 179| | 180| 0| explicit operator bool() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEEcvbEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEEcvbEv ------------------ 181| | 182| 0| void swap(IntrusiveRefCntPtr& other) { 183| 0| T* tmp = other.Obj; 184| 0| other.Obj = Obj; 185| 0| Obj = tmp; 186| 0| } 187| | 188| 0| void reset() { 189| 0| release(); 190| 0| Obj = nullptr; 191| 0| } 192| | 193| | void resetWithoutRelease() { 194| | Obj = 0; 195| | } 196| | 197| | private: 198| 0| void retain() { if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE6retainEv ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE6retainEv ------------------ 199| 0| void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); } ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE7releaseEv ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE7releaseEv ------------------ 200| | 201| | template 202| | friend class IntrusiveRefCntPtr; 203| | }; 204| | 205| | template 206| | inline bool operator==(const IntrusiveRefCntPtr& A, 207| | const IntrusiveRefCntPtr& B) 208| 0| { 209| 0| return A.get() == B.get(); 210| 0| } ------------------ | Unexecuted instantiation: _ZN4llvmeqINS_3sys2fs6detail12DirIterStateES4_EEbRKNS_18IntrusiveRefCntPtrIT_EERKNS5_IT0_EE ------------------ | Unexecuted instantiation: _ZN4llvmeqINS_3sys2fs6detail15RecDirIterStateES4_EEbRKNS_18IntrusiveRefCntPtrIT_EERKNS5_IT0_EE ------------------ 211| | 212| | template 213| | inline bool operator!=(const IntrusiveRefCntPtr& A, 214| | const IntrusiveRefCntPtr& B) 215| | { 216| | return A.get() != B.get(); 217| | } 218| | 219| | template 220| | inline bool operator==(const IntrusiveRefCntPtr& A, 221| | U* B) 222| | { 223| | return A.get() == B; 224| | } 225| | 226| | template 227| | inline bool operator!=(const IntrusiveRefCntPtr& A, 228| | U* B) 229| | { 230| | return A.get() != B; 231| | } 232| | 233| | template 234| | inline bool operator==(T* A, 235| | const IntrusiveRefCntPtr& B) 236| | { 237| | return A == B.get(); 238| | } 239| | 240| | template 241| | inline bool operator!=(T* A, 242| | const IntrusiveRefCntPtr& B) 243| | { 244| | return A != B.get(); 245| | } 246| | 247| | template 248| | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 249| | return !B; 250| | } 251| | 252| | template 253| | bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 254| | return B == A; 255| | } 256| | 257| | template 258| | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 259| | return !(A == B); 260| | } 261| | 262| | template 263| | bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 264| | return !(A == B); 265| | } 266| | 267| |//===----------------------------------------------------------------------===// 268| |// LLVM-style downcasting support for IntrusiveRefCntPtr objects 269| |//===----------------------------------------------------------------------===// 270| | 271| | template struct simplify_type > { 272| | typedef T* SimpleType; 273| | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr& Val) { 274| | return Val.get(); 275| | } 276| | }; 277| | 278| | template struct simplify_type > { 279| | typedef /*const*/ T* SimpleType; 280| | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { 281| | return Val.get(); 282| | } 283| | }; 284| | 285| |} // end namespace llvm 286| | 287| |#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Optional.h: 1| |//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides Optional, a template class modeled in the spirit of 11| |// OCaml's 'opt' variant. The idea is to strongly type whether or not 12| |// a value can be optional. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_ADT_OPTIONAL_H 17| |#define LLVM_ADT_OPTIONAL_H 18| | 19| |#include "llvm/ADT/None.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include "llvm/Support/Compiler.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |template 30| |class Optional { 31| | AlignedCharArrayUnion storage; 32| | bool hasVal; 33| |public: 34| | typedef T value_type; 35| | 36| 0| Optional(NoneType) : hasVal(false) {} ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEC2ENS_8NoneTypeE ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEC2ENS_8NoneTypeE ------------------ 37| 0| explicit Optional() : hasVal(false) {} ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEEC2Ev ------------------ 38| | Optional(const T &y) : hasVal(true) { 39| | new (storage.buffer) T(y); 40| | } 41| 0| Optional(const Optional &O) : hasVal(O.hasVal) { 42| 0| if (hasVal) 43| 0| new (storage.buffer) T(*O); 44| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEC2ERKS8_ ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEC2ERKS6_ ------------------ 45| | 46| 0| Optional(T &&y) : hasVal(true) { 47| 0| new (storage.buffer) T(std::forward(y)); 48| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEC2EOS7_ ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEC2EOS3_ ------------------ 49| 0| Optional(Optional &&O) : hasVal(O) { 50| 0| if (O) { 51| 0| new (storage.buffer) T(std::move(*O)); 52| 0| O.reset(); 53| 0| } 54| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEC2EOS8_ ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEC2EOS6_ ------------------ 55| 0| Optional &operator=(T &&y) { 56| 0| if (hasVal) 57| 0| **this = std::move(y); 58| 0| else { 59| 0| new (storage.buffer) T(std::move(y)); 60| 0| hasVal = true; 61| 0| } 62| 0| return *this; 63| 0| } 64| 0| Optional &operator=(Optional &&O) { 65| 0| if (!O) 66| 0| reset(); 67| 0| else { 68| 0| *this = std::move(*O); 69| 0| O.reset(); 70| 0| } 71| 0| return *this; 72| 0| } 73| | 74| | /// Create a new object by constructing it in place with the given arguments. 75| | template 76| 0| void emplace(ArgTypes &&...Args) { 77| 0| reset(); 78| 0| hasVal = true; 79| 0| new (storage.buffer) T(std::forward(Args)...); 80| 0| } 81| | 82| | static inline Optional create(const T* y) { 83| | return y ? Optional(*y) : Optional(); 84| | } 85| | 86| | // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 87| | // could be made more efficient by passing by value, possibly unifying them 88| | // with the rvalue versions above - but this could place a different set of 89| | // requirements (notably: the existence of a default ctor) when implemented 90| | // in that way. Careful SFINAE to avoid such pitfalls would be required. 91| 0| Optional &operator=(const T &y) { 92| 0| if (hasVal) 93| 0| **this = y; 94| 0| else { 95| 0| new (storage.buffer) T(y); 96| 0| hasVal = true; 97| 0| } 98| 0| return *this; 99| 0| } 100| | 101| | Optional &operator=(const Optional &O) { 102| | if (!O) 103| | reset(); 104| | else 105| | *this = *O; 106| | return *this; 107| | } 108| | 109| 0| void reset() { 110| 0| if (hasVal) { 111| 0| (**this).~T(); 112| 0| hasVal = false; 113| 0| } 114| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE5resetEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE5resetEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEE5resetEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEE5resetEv ------------------ 115| | 116| 0| ~Optional() { 117| 0| reset(); 118| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEED2Ev ------------------ 119| | 120| 0| const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); } ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE10getPointerEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEE10getPointerEv ------------------ 121| 0| T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); } ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE10getPointerEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE10getPointerEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEE10getPointerEv ------------------ | Unexecuted instantiation: _ZN4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEE10getPointerEv ------------------ 122| 0| const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } ------------------ | Unexecuted instantiation: _ZNKR4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE8getValueEv ------------------ | Unexecuted instantiation: _ZNKR4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEE8getValueEv ------------------ 123| 0| T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE8getValueEv ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE8getValueEv ------------------ 124| | 125| 0| explicit operator bool() const { return hasVal; } ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEcvbEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEcvbEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEcvbEv ------------------ 126| 0| bool hasValue() const { return hasVal; } ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEE8hasValueEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEE8hasValueEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalIN7llbuild11buildsystem10BuildValueEE8hasValueEv ------------------ | Unexecuted instantiation: _ZNK4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEE8hasValueEv ------------------ 127| | const T* operator->() const { return getPointer(); } 128| 0| T* operator->() { return getPointer(); } 129| 0| const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } ------------------ | Unexecuted instantiation: _ZNKR4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEdeEv ------------------ | Unexecuted instantiation: _ZNKR4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEdeEv ------------------ 130| 0| T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalIN7llbuild11buildsystem10BuildValueEEdeEv ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalINSt3__18functionIFvN7llbuild5basic13ProcessResultEEEEEdeEv ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalINSt3__16vectorIhNS1_9allocatorIhEEEEEdeEv ------------------ | Unexecuted instantiation: _ZNR4llvm8OptionalIN7llbuild11buildsystem11BuildSystemEEdeEv ------------------ 131| | 132| | template 133| | LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { 134| | return hasValue() ? getValue() : std::forward(value); 135| | } 136| | 137| 0| void unwrapIn(std::function fn) { 138| 0| if (hasValue()) 139| 0| fn(getValue()); 140| 0| } 141| 0| void unwrapIn(std::function fn) const { 142| 0| if (hasValue()) 143| 0| fn(getValue()); 144| 0| } 145| | 146| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 147| | T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 148| | T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 149| | 150| | template 151| | T getValueOr(U &&value) && { 152| | return hasValue() ? std::move(getValue()) : std::forward(value); 153| | } 154| |#endif 155| |}; 156| | 157| |template struct isPodLike; 158| |template struct isPodLike > { 159| | // An Optional is pod-like if T is. 160| | static const bool value = isPodLike::value; 161| |}; 162| | 163| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 164| |/// explicitly compare the underlying values and account for empty \c Optional 165| |/// objects. 166| |/// 167| |/// This routine will never be defined. It returns \c void to help diagnose 168| |/// errors at compile time. 169| |template 170| |void operator==(const Optional &X, const Optional &Y); 171| | 172| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 173| |/// explicitly compare the underlying values and account for empty \c Optional 174| |/// objects. 175| |/// 176| |/// This routine will never be defined. It returns \c void to help diagnose 177| |/// errors at compile time. 178| |template 179| |void operator!=(const Optional &X, const Optional &Y); 180| | 181| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 182| |/// explicitly compare the underlying values and account for empty \c Optional 183| |/// objects. 184| |/// 185| |/// This routine will never be defined. It returns \c void to help diagnose 186| |/// errors at compile time. 187| |template 188| |void operator<(const Optional &X, const Optional &Y); 189| | 190| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 191| |/// explicitly compare the underlying values and account for empty \c Optional 192| |/// objects. 193| |/// 194| |/// This routine will never be defined. It returns \c void to help diagnose 195| |/// errors at compile time. 196| |template 197| |void operator<=(const Optional &X, const Optional &Y); 198| | 199| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 200| |/// explicitly compare the underlying values and account for empty \c Optional 201| |/// objects. 202| |/// 203| |/// This routine will never be defined. It returns \c void to help diagnose 204| |/// errors at compile time. 205| |template 206| |void operator>=(const Optional &X, const Optional &Y); 207| | 208| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 209| |/// explicitly compare the underlying values and account for empty \c Optional 210| |/// objects. 211| |/// 212| |/// This routine will never be defined. It returns \c void to help diagnose 213| |/// errors at compile time. 214| |template 215| |void operator>(const Optional &X, const Optional &Y); 216| | 217| |} // end llvm namespace 218| | 219| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/STLExtras.h: 1| |//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some templates that are useful if you are working with the 11| |// STL at all. 12| |// 13| |// No library is required when using these functions. 14| |// 15| |//===----------------------------------------------------------------------===// 16| | 17| |#ifndef LLVM_ADT_STLEXTRAS_H 18| |#define LLVM_ADT_STLEXTRAS_H 19| | 20| |#include "llvm/Support/Compiler.h" 21| |#include 22| |#include // for std::size_t 23| |#include // for qsort 24| |#include 25| |#include 26| |#include 27| |#include // for std::pair 28| | 29| |namespace llvm { 30| | 31| |//===----------------------------------------------------------------------===// 32| |// Extra additions to 33| |//===----------------------------------------------------------------------===// 34| | 35| |template 36| |struct identity : public std::unary_function { 37| | Ty &operator()(Ty &self) const { 38| | return self; 39| | } 40| | const Ty &operator()(const Ty &self) const { 41| | return self; 42| | } 43| |}; 44| | 45| |template 46| |struct less_ptr : public std::binary_function { 47| | bool operator()(const Ty* left, const Ty* right) const { 48| | return *left < *right; 49| | } 50| |}; 51| | 52| |template 53| |struct greater_ptr : public std::binary_function { 54| | bool operator()(const Ty* left, const Ty* right) const { 55| | return *right < *left; 56| | } 57| |}; 58| | 59| |/// An efficient, type-erasing, non-owning reference to a callable. This is 60| |/// intended for use as the type of a function parameter that is not used 61| |/// after the function in question returns. 62| |/// 63| |/// This class does not own the callable, so it is not in general safe to store 64| |/// a function_ref. 65| |template class function_ref; 66| | 67| |template 68| |class function_ref { 69| | Ret (*callback)(intptr_t callable, Params ...params); 70| | intptr_t callable; 71| | 72| | template 73| | static Ret callback_fn(intptr_t callable, Params ...params) { 74| | return (*reinterpret_cast(callable))( 75| | std::forward(params)...); 76| | } 77| | 78| |public: 79| | template 80| | function_ref(Callable &&callable, 81| | typename std::enable_if< 82| | !std::is_same::type, 83| | function_ref>::value>::type * = nullptr) 84| | : callback(callback_fn::type>), 85| | callable(reinterpret_cast(&callable)) {} 86| | Ret operator()(Params ...params) const { 87| | return callback(callable, std::forward(params)...); 88| | } 89| |}; 90| | 91| |// deleter - Very very very simple method that is used to invoke operator 92| |// delete on something. It is used like this: 93| |// 94| |// for_each(V.begin(), B.end(), deleter); 95| |// 96| |template 97| |inline void deleter(T *Ptr) { 98| | delete Ptr; 99| |} 100| | 101| | 102| | 103| |//===----------------------------------------------------------------------===// 104| |// Extra additions to 105| |//===----------------------------------------------------------------------===// 106| | 107| |// mapped_iterator - This is a simple iterator adapter that causes a function to 108| |// be dereferenced whenever operator* is invoked on the iterator. 109| |// 110| |template 111| |class mapped_iterator { 112| | RootIt current; 113| | UnaryFunc Fn; 114| |public: 115| | typedef typename std::iterator_traits::iterator_category 116| | iterator_category; 117| | typedef typename std::iterator_traits::difference_type 118| | difference_type; 119| | typedef typename UnaryFunc::result_type value_type; 120| | 121| | typedef void pointer; 122| | //typedef typename UnaryFunc::result_type *pointer; 123| | typedef void reference; // Can't modify value returned by fn 124| | 125| | typedef RootIt iterator_type; 126| | 127| | inline const RootIt &getCurrent() const { return current; } 128| | inline const UnaryFunc &getFunc() const { return Fn; } 129| | 130| | inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) 131| | : current(I), Fn(F) {} 132| | 133| | inline value_type operator*() const { // All this work to do this 134| | return Fn(*current); // little change 135| | } 136| | 137| | mapped_iterator &operator++() { 138| | ++current; 139| | return *this; 140| | } 141| | mapped_iterator &operator--() { 142| | --current; 143| | return *this; 144| | } 145| | mapped_iterator operator++(int) { 146| | mapped_iterator __tmp = *this; 147| | ++current; 148| | return __tmp; 149| | } 150| | mapped_iterator operator--(int) { 151| | mapped_iterator __tmp = *this; 152| | --current; 153| | return __tmp; 154| | } 155| | mapped_iterator operator+(difference_type n) const { 156| | return mapped_iterator(current + n, Fn); 157| | } 158| | mapped_iterator &operator+=(difference_type n) { 159| | current += n; 160| | return *this; 161| | } 162| | mapped_iterator operator-(difference_type n) const { 163| | return mapped_iterator(current - n, Fn); 164| | } 165| | mapped_iterator &operator-=(difference_type n) { 166| | current -= n; 167| | return *this; 168| | } 169| | reference operator[](difference_type n) const { return *(*this + n); } 170| | 171| | bool operator!=(const mapped_iterator &X) const { return !operator==(X); } 172| | bool operator==(const mapped_iterator &X) const { 173| | return current == X.current; 174| | } 175| | bool operator<(const mapped_iterator &X) const { return current < X.current; } 176| | 177| | difference_type operator-(const mapped_iterator &X) const { 178| | return current - X.current; 179| | } 180| |}; 181| | 182| |template 183| |inline mapped_iterator 184| |operator+(typename mapped_iterator::difference_type N, 185| | const mapped_iterator &X) { 186| | return mapped_iterator(X.getCurrent() - N, X.getFunc()); 187| |} 188| | 189| | 190| |// map_iterator - Provide a convenient way to create mapped_iterators, just like 191| |// make_pair is useful for creating pairs... 192| |// 193| |template 194| |inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { 195| | return mapped_iterator(I, F); 196| |} 197| | 198| |//===----------------------------------------------------------------------===// 199| |// Extra additions to 200| |//===----------------------------------------------------------------------===// 201| | 202| |/// \brief Function object to check whether the first component of a std::pair 203| |/// compares less than the first component of another std::pair. 204| |struct less_first { 205| | template bool operator()(const T &lhs, const T &rhs) const { 206| | return lhs.first < rhs.first; 207| | } 208| |}; 209| | 210| |/// \brief Function object to check whether the second component of a std::pair 211| |/// compares less than the second component of another std::pair. 212| |struct less_second { 213| | template bool operator()(const T &lhs, const T &rhs) const { 214| | return lhs.second < rhs.second; 215| | } 216| |}; 217| | 218| |// A subset of N3658. More stuff can be added as-needed. 219| | 220| |/// \brief Represents a compile-time sequence of integers. 221| |template struct integer_sequence { 222| | typedef T value_type; 223| | 224| | static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } 225| |}; 226| | 227| |/// \brief Alias for the common case of a sequence of size_ts. 228| |template 229| |struct index_sequence : integer_sequence {}; 230| | 231| |template 232| |struct build_index_impl : build_index_impl {}; 233| |template 234| |struct build_index_impl<0, I...> : index_sequence {}; 235| | 236| |/// \brief Creates a compile-time integer sequence for a parameter pack. 237| |template 238| |struct index_sequence_for : build_index_impl {}; 239| | 240| |//===----------------------------------------------------------------------===// 241| |// Extra additions for arrays 242| |//===----------------------------------------------------------------------===// 243| | 244| |/// Find the length of an array. 245| |template 246| |LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { 247| | return N; 248| |} 249| | 250| |/// Adapt std::less for array_pod_sort. 251| |template 252| |inline int array_pod_sort_comparator(const void *P1, const void *P2) { 253| | if (std::less()(*reinterpret_cast(P1), 254| | *reinterpret_cast(P2))) 255| | return -1; 256| | if (std::less()(*reinterpret_cast(P2), 257| | *reinterpret_cast(P1))) 258| | return 1; 259| | return 0; 260| |} 261| | 262| |/// get_array_pod_sort_comparator - This is an internal helper function used to 263| |/// get type deduction of T right. 264| |template 265| |inline int (*get_array_pod_sort_comparator(const T &)) 266| | (const void*, const void*) { 267| | return array_pod_sort_comparator; 268| |} 269| | 270| | 271| |/// array_pod_sort - This sorts an array with the specified start and end 272| |/// extent. This is just like std::sort, except that it calls qsort instead of 273| |/// using an inlined template. qsort is slightly slower than std::sort, but 274| |/// most sorts are not performance critical in LLVM and std::sort has to be 275| |/// template instantiated for each type, leading to significant measured code 276| |/// bloat. This function should generally be used instead of std::sort where 277| |/// possible. 278| |/// 279| |/// This function assumes that you have simple POD-like types that can be 280| |/// compared with std::less and can be moved with memcpy. If this isn't true, 281| |/// you should use std::sort. 282| |/// 283| |/// NOTE: If qsort_r were portable, we could allow a custom comparator and 284| |/// default to std::less. 285| |template 286| |inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 287| | // Don't inefficiently call qsort with one element or trigger undefined 288| | // behavior with an empty sequence. 289| | auto NElts = End - Start; 290| | if (NElts <= 1) return; 291| | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 292| |} 293| | 294| |template 295| |inline void array_pod_sort( 296| | IteratorTy Start, IteratorTy End, 297| | int (*Compare)( 298| | const typename std::iterator_traits::value_type *, 299| | const typename std::iterator_traits::value_type *)) { 300| | // Don't inefficiently call qsort with one element or trigger undefined 301| | // behavior with an empty sequence. 302| | auto NElts = End - Start; 303| | if (NElts <= 1) return; 304| | qsort(&*Start, NElts, sizeof(*Start), 305| | reinterpret_cast(Compare)); 306| |} 307| | 308| |//===----------------------------------------------------------------------===// 309| |// Extra additions to 310| |//===----------------------------------------------------------------------===// 311| | 312| |/// For a container of pointers, deletes the pointers and then clears the 313| |/// container. 314| |template 315| |void DeleteContainerPointers(Container &C) { 316| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 317| | delete *I; 318| | C.clear(); 319| |} 320| | 321| |/// In a container of pairs (usually a map) whose second element is a pointer, 322| |/// deletes the second elements and then clears the container. 323| |template 324| |void DeleteContainerSeconds(Container &C) { 325| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 326| | delete I->second; 327| | C.clear(); 328| |} 329| | 330| |//===----------------------------------------------------------------------===// 331| |// Extra additions to 332| |//===----------------------------------------------------------------------===// 333| | 334| |// Implement make_unique according to N3656. 335| | 336| |/// \brief Constructs a `new T()` with the given args and returns a 337| |/// `unique_ptr` which owns the object. 338| |/// 339| |/// Example: 340| |/// 341| |/// auto p = make_unique(); 342| |/// auto p = make_unique>(0, 1); 343| |template 344| |typename std::enable_if::value, std::unique_ptr>::type 345| 0|make_unique(Args &&... args) { 346| 0| return std::unique_ptr(new T(std::forward(args)...)); 347| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild11buildsystem6TargetEJRNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEEENS4_9enable_ifIXntsr3std8is_arrayIT_EE5valueENS4_10unique_ptrISD_NS4_14default_deleteISD_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild11buildsystem16BuildDescriptionEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS4_10unique_ptrIS6_NS4_14default_deleteIS6_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_19ShellToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_112ShellCommandEJRNS_9StringRefERbEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS6_10unique_ptrIS8_NS6_14default_deleteIS8_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_19PhonyToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_112PhonyCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_19ClangToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_117ClangShellCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_19MkdirToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_112MkdirCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_111SymlinkToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_114SymlinkCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_111ArchiveToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_119ArchiveShellCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_120StaleFileRemovalToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_123StaleFileRemovalCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_117SwiftCompilerToolEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_125SwiftCompilerShellCommandEJRNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: BuildSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_122SwiftGetVersionCommandEJRKN7llbuild11buildsystem8BuildKeyEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS8_10unique_ptrISA_NS8_14default_deleteISA_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild11buildsystem9BuildNodeEJRNS_9StringRefERbbS6_bbEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS7_10unique_ptrIS9_NS7_14default_deleteIS9_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild11buildsystem8StatNodeEJNS_9StringRefEEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_10unique_ptrIS7_NS5_14default_deleteIS7_EEEEE4typeEDpOT0_ ------------------ 348| | 349| |/// \brief Constructs a `new T[n]` with the given args and returns a 350| |/// `unique_ptr` which owns the object. 351| |/// 352| |/// \param n size of the new array. 353| |/// 354| |/// Example: 355| |/// 356| |/// auto p = make_unique(2); // value-initializes the array with 0's. 357| |template 358| |typename std::enable_if::value && std::extent::value == 0, 359| | std::unique_ptr>::type 360| |make_unique(size_t n) { 361| | return std::unique_ptr(new typename std::remove_extent::type[n]()); 362| |} 363| | 364| |/// This function isn't used and is only here to provide better compile errors. 365| |template 366| |typename std::enable_if::value != 0>::type 367| |make_unique(Args &&...) = delete; 368| | 369| |struct FreeDeleter { 370| 0| void operator()(void* v) { 371| 0| ::free(v); 372| 0| } 373| |}; 374| | 375| |template 376| |struct pair_hash { 377| | size_t operator()(const std::pair &P) const { 378| | return std::hash()(P.first) * 31 + std::hash()(P.second); 379| | } 380| |}; 381| | 382| |/// A functor like C++14's std::less in its absence. 383| |struct less { 384| | template bool operator()(A &&a, B &&b) const { 385| | return std::forward(a) < std::forward(b); 386| | } 387| |}; 388| | 389| |/// A functor like C++14's std::equal in its absence. 390| |struct equal { 391| | template bool operator()(A &&a, B &&b) const { 392| | return std::forward(a) == std::forward(b); 393| | } 394| |}; 395| | 396| |/// Binary functor that adapts to any other binary functor after dereferencing 397| |/// operands. 398| |template struct deref { 399| | T func; 400| | // Could be further improved to cope with non-derivable functors and 401| | // non-binary functors (should be a variadic template member function 402| | // operator()). 403| | template 404| | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { 405| | assert(lhs); 406| | assert(rhs); 407| | return func(*lhs, *rhs); 408| | } 409| |}; 410| | 411| |} // End llvm namespace 412| | 413| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallPtrSet.h: 1| |//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallPtrSet class. See the doxygen comment for 11| |// SmallPtrSetImplBase for more details on the algorithm used. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_ADT_SMALLPTRSET_H 16| |#define LLVM_ADT_SMALLPTRSET_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include "llvm/Support/PointerLikeTypeTraits.h" 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |class SmallPtrSetIteratorImpl; 30| | 31| |/// SmallPtrSetImplBase - This is the common code shared among all the 32| |/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one 33| |/// for small and one for large sets. 34| |/// 35| |/// Small sets use an array of pointers allocated in the SmallPtrSet object, 36| |/// which is treated as a simple array of pointers. When a pointer is added to 37| |/// the set, the array is scanned to see if the element already exists, if not 38| |/// the element is 'pushed back' onto the array. If we run out of space in the 39| |/// array, we grow into the 'large set' case. SmallSet should be used when the 40| |/// sets are often small. In this case, no memory allocation is used, and only 41| |/// light-weight and cache-efficient scanning is used. 42| |/// 43| |/// Large sets use a classic exponentially-probed hash table. Empty buckets are 44| |/// represented with an illegal pointer value (-1) to allow null pointers to be 45| |/// inserted. Tombstones are represented with another illegal pointer value 46| |/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or 47| |/// more. When this happens, the table is doubled in size. 48| |/// 49| |class SmallPtrSetImplBase { 50| | friend class SmallPtrSetIteratorImpl; 51| |protected: 52| | /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. 53| | const void **SmallArray; 54| | /// CurArray - This is the current set of buckets. If equal to SmallArray, 55| | /// then the set is in 'small mode'. 56| | const void **CurArray; 57| | /// CurArraySize - The allocated size of CurArray, always a power of two. 58| | unsigned CurArraySize; 59| | 60| | // If small, this is # elts allocated consecutively 61| | unsigned NumElements; 62| | unsigned NumTombstones; 63| | 64| | // Helpers to copy and move construct a SmallPtrSet. 65| | SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that); 66| | SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize, 67| | SmallPtrSetImplBase &&that); 68| | explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) : 69| 0| SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { 70| 0| assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && 71| 0| "Initial size must be a power of two!"); 72| 0| clear(); 73| 0| } 74| | ~SmallPtrSetImplBase(); 75| | 76| |public: 77| | typedef unsigned size_type; 78| 0| bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } 79| 0| size_type size() const { return NumElements; } 80| | 81| 0| void clear() { 82| 0| // If the capacity of the array is huge, and the # elements used is small, 83| 0| // shrink the array. 84| 0| if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) 85| 0| return shrink_and_clear(); 86| 0| 87| 0| // Fill the array with empty markers. 88| 0| memset(CurArray, -1, CurArraySize*sizeof(void*)); 89| 0| NumElements = 0; 90| 0| NumTombstones = 0; 91| 0| } 92| | 93| |protected: 94| 0| static void *getTombstoneMarker() { return reinterpret_cast(-2); } 95| 0| static void *getEmptyMarker() { 96| 0| // Note that -1 is chosen to make clear() efficiently implementable with 97| 0| // memset and because it's not a valid pointer value. 98| 0| return reinterpret_cast(-1); 99| 0| } 100| | 101| | /// insert_imp - This returns true if the pointer was new to the set, false if 102| | /// it was already in the set. This is hidden from the client so that the 103| | /// derived class can check that the right type of pointer is passed in. 104| | std::pair insert_imp(const void *Ptr); 105| | 106| | /// erase_imp - If the set contains the specified pointer, remove it and 107| | /// return true, otherwise return false. This is hidden from the client so 108| | /// that the derived class can check that the right type of pointer is passed 109| | /// in. 110| | bool erase_imp(const void * Ptr); 111| | 112| 0| bool count_imp(const void * Ptr) const { 113| 0| if (isSmall()) { 114| 0| // Linear search for the item. 115| 0| for (const void *const *APtr = SmallArray, 116| 0| *const *E = SmallArray+NumElements; APtr != E; ++APtr) 117| 0| if (*APtr == Ptr) 118| 0| return true; 119| 0| return false; 120| 0| } 121| 0| 122| 0| // Big set case. 123| 0| return *FindBucketFor(Ptr) == Ptr; 124| 0| } 125| | 126| |private: 127| 0| bool isSmall() const { return CurArray == SmallArray; } 128| | 129| | const void * const *FindBucketFor(const void *Ptr) const; 130| | void shrink_and_clear(); 131| | 132| | /// Grow - Allocate a larger backing store for the buckets and move it over. 133| | void Grow(unsigned NewSize); 134| | 135| | void operator=(const SmallPtrSetImplBase &RHS) = delete; 136| |protected: 137| | /// swap - Swaps the elements of two sets. 138| | /// Note: This method assumes that both sets have the same small size. 139| | void swap(SmallPtrSetImplBase &RHS); 140| | 141| | void CopyFrom(const SmallPtrSetImplBase &RHS); 142| | void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS); 143| |}; 144| | 145| |/// SmallPtrSetIteratorImpl - This is the common base class shared between all 146| |/// instances of SmallPtrSetIterator. 147| |class SmallPtrSetIteratorImpl { 148| |protected: 149| | const void *const *Bucket; 150| | const void *const *End; 151| |public: 152| | explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) 153| 0| : Bucket(BP), End(E) { 154| 0| AdvanceIfNotValid(); 155| 0| } 156| | 157| 0| bool operator==(const SmallPtrSetIteratorImpl &RHS) const { 158| 0| return Bucket == RHS.Bucket; 159| 0| } 160| 0| bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { 161| 0| return Bucket != RHS.Bucket; 162| 0| } 163| | 164| |protected: 165| | /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket 166| | /// that is. This is guaranteed to stop because the end() bucket is marked 167| | /// valid. 168| 0| void AdvanceIfNotValid() { 169| 0| assert(Bucket <= End); 170| 0| while (Bucket != End && 171| 0| (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || 172| 0| *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) 173| 0| ++Bucket; 174| 0| } 175| |}; 176| | 177| |/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. 178| |template 179| |class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { 180| | typedef PointerLikeTypeTraits PtrTraits; 181| | 182| |public: 183| | typedef PtrTy value_type; 184| | typedef PtrTy reference; 185| | typedef PtrTy pointer; 186| | typedef std::ptrdiff_t difference_type; 187| | typedef std::forward_iterator_tag iterator_category; 188| | 189| | explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) 190| 0| : SmallPtrSetIteratorImpl(BP, E) {} 191| | 192| | // Most methods provided by baseclass. 193| | 194| 0| const PtrTy operator*() const { 195| 0| assert(Bucket < End); 196| 0| return PtrTraits::getFromVoidPointer(const_cast(*Bucket)); 197| 0| } 198| | 199| 0| inline SmallPtrSetIterator& operator++() { // Preincrement 200| 0| ++Bucket; 201| 0| AdvanceIfNotValid(); 202| 0| return *this; 203| 0| } 204| | 205| | SmallPtrSetIterator operator++(int) { // Postincrement 206| | SmallPtrSetIterator tmp = *this; ++*this; return tmp; 207| | } 208| |}; 209| | 210| |/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next 211| |/// power of two (which means N itself if N is already a power of two). 212| |template 213| |struct RoundUpToPowerOfTwo; 214| | 215| |/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a 216| |/// helper template used to implement RoundUpToPowerOfTwo. 217| |template 218| |struct RoundUpToPowerOfTwoH { 219| | enum { Val = N }; 220| |}; 221| |template 222| |struct RoundUpToPowerOfTwoH { 223| | enum { 224| | // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets 225| | // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. 226| | Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val 227| | }; 228| |}; 229| | 230| |template 231| |struct RoundUpToPowerOfTwo { 232| | enum { Val = RoundUpToPowerOfTwoH::Val }; 233| |}; 234| | 235| | 236| |/// \brief A templated base class for \c SmallPtrSet which provides the 237| |/// typesafe interface that is common across all small sizes. 238| |/// 239| |/// This is particularly useful for passing around between interface boundaries 240| |/// to avoid encoding a particular small size in the interface boundary. 241| |template 242| |class SmallPtrSetImpl : public SmallPtrSetImplBase { 243| | typedef PointerLikeTypeTraits PtrTraits; 244| | 245| | SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; 246| |protected: 247| | // Constructors that forward to the base. 248| | SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) 249| 0| : SmallPtrSetImplBase(SmallStorage, that) {} 250| | SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, 251| | SmallPtrSetImpl &&that) 252| | : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} 253| | explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) 254| 0| : SmallPtrSetImplBase(SmallStorage, SmallSize) {} 255| | 256| |public: 257| | typedef SmallPtrSetIterator iterator; 258| | typedef SmallPtrSetIterator const_iterator; 259| | 260| | /// Inserts Ptr if and only if there is no element in the container equal to 261| | /// Ptr. The bool component of the returned pair is true if and only if the 262| | /// insertion takes place, and the iterator component of the pair points to 263| | /// the element equal to Ptr. 264| 0| std::pair insert(PtrType Ptr) { 265| 0| auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); 266| 0| return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); 267| 0| } 268| | 269| | /// erase - If the set contains the specified pointer, remove it and return 270| | /// true, otherwise return false. 271| | bool erase(PtrType Ptr) { 272| | return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); 273| | } 274| | 275| | /// count - Return 1 if the specified pointer is in the set, 0 otherwise. 276| | size_type count(PtrType Ptr) const { 277| | return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; 278| | } 279| | 280| | template 281| | void insert(IterT I, IterT E) { 282| | for (; I != E; ++I) 283| | insert(*I); 284| | } 285| | 286| 0| inline iterator begin() const { 287| 0| return iterator(CurArray, CurArray+CurArraySize); 288| 0| } 289| 0| inline iterator end() const { 290| 0| return iterator(CurArray+CurArraySize, CurArray+CurArraySize); 291| 0| } 292| |}; 293| | 294| |/// SmallPtrSet - This class implements a set which is optimized for holding 295| |/// SmallSize or less elements. This internally rounds up SmallSize to the next 296| |/// power of two if it is not already a power of two. See the comments above 297| |/// SmallPtrSetImplBase for details of the algorithm. 298| |template 299| |class SmallPtrSet : public SmallPtrSetImpl { 300| | typedef SmallPtrSetImpl BaseT; 301| | 302| | // Make sure that SmallSize is a power of two, round up if not. 303| | enum { SmallSizePowTwo = RoundUpToPowerOfTwo::Val }; 304| | /// SmallStorage - Fixed size storage used in 'small mode'. 305| | const void *SmallStorage[SmallSizePowTwo]; 306| |public: 307| 0| SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} 308| 0| SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} 309| | SmallPtrSet(SmallPtrSet &&that) 310| | : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} 311| | 312| | template 313| | SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { 314| | this->insert(I, E); 315| | } 316| | 317| | SmallPtrSet & 318| | operator=(const SmallPtrSet &RHS) { 319| | if (&RHS != this) 320| | this->CopyFrom(RHS); 321| | return *this; 322| | } 323| | 324| | SmallPtrSet& 325| | operator=(SmallPtrSet &&RHS) { 326| | if (&RHS != this) 327| | this->MoveFrom(SmallSizePowTwo, std::move(RHS)); 328| | return *this; 329| | } 330| | 331| | /// swap - Swaps the elements of two sets. 332| | void swap(SmallPtrSet &RHS) { 333| | SmallPtrSetImplBase::swap(RHS); 334| | } 335| |}; 336| | 337| |} 338| | 339| |namespace std { 340| | /// Implement std::swap in terms of SmallPtrSet swap. 341| | template 342| | inline void swap(llvm::SmallPtrSet &LHS, llvm::SmallPtrSet &RHS) { 343| | LHS.swap(RHS); 344| | } 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallString.h: 1| |//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallString class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLSTRING_H 15| |#define LLVM_ADT_SMALLSTRING_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |namespace llvm { 21| | 22| |/// SmallString - A SmallString is just a SmallVector with methods and accessors 23| |/// that make it work better as a string (e.g. operator+ etc). 24| |template 25| |class SmallString : public SmallVector { 26| |public: 27| | /// Default ctor - Initialize to empty. 28| 0| SmallString() {} ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj64EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj16EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj4096EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EEC2Ev ------------------ 29| | 30| | /// Initialize from a StringRef. 31| 0| SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj1024EEC2ENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj256EEC2ENS_9StringRefE ------------------ 32| | 33| | /// Initialize with a range. 34| | template 35| | SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} 36| | 37| | // Note that in order to add new overloads for append & assign, we have to 38| | // duplicate the inherited versions so as not to inadvertently hide them. 39| | 40| | /// @} 41| | /// @name String Assignment 42| | /// @{ 43| | 44| | /// Assign from a repeated element. 45| | void assign(size_t NumElts, char Elt) { 46| | this->SmallVectorImpl::assign(NumElts, Elt); 47| | } 48| | 49| | /// Assign from an iterator pair. 50| | template 51| | void assign(in_iter S, in_iter E) { 52| | this->clear(); 53| | SmallVectorImpl::append(S, E); 54| | } 55| | 56| | /// Assign from a StringRef. 57| | void assign(StringRef RHS) { 58| | this->clear(); 59| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 60| | } 61| | 62| | /// Assign from a SmallVector. 63| | void assign(const SmallVectorImpl &RHS) { 64| | this->clear(); 65| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 66| | } 67| | 68| | /// @} 69| | /// @name String Concatenation 70| | /// @{ 71| | 72| | /// Append from an iterator pair. 73| | template 74| 0| void append(in_iter S, in_iter E) { 75| 0| SmallVectorImpl::append(S, E); 76| 0| } 77| | 78| | void append(size_t NumInputs, char Elt) { 79| | SmallVectorImpl::append(NumInputs, Elt); 80| | } 81| | 82| | 83| | /// Append from a StringRef. 84| 0| void append(StringRef RHS) { 85| 0| SmallVectorImpl::append(RHS.begin(), RHS.end()); 86| 0| } 87| | 88| | /// Append from a SmallVector. 89| | void append(const SmallVectorImpl &RHS) { 90| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 91| | } 92| | 93| | /// @} 94| | /// @name String Comparison 95| | /// @{ 96| | 97| | /// Check for string equality. This is more efficient than compare() when 98| | /// the relative ordering of inequal strings isn't needed. 99| | bool equals(StringRef RHS) const { 100| | return str().equals(RHS); 101| | } 102| | 103| | /// Check for string equality, ignoring case. 104| | bool equals_lower(StringRef RHS) const { 105| | return str().equals_lower(RHS); 106| | } 107| | 108| | /// Compare two strings; the result is -1, 0, or 1 if this string is 109| | /// lexicographically less than, equal to, or greater than the \p RHS. 110| | int compare(StringRef RHS) const { 111| | return str().compare(RHS); 112| | } 113| | 114| | /// compare_lower - Compare two strings, ignoring case. 115| | int compare_lower(StringRef RHS) const { 116| | return str().compare_lower(RHS); 117| | } 118| | 119| | /// compare_numeric - Compare two strings, treating sequences of digits as 120| | /// numbers. 121| | int compare_numeric(StringRef RHS) const { 122| | return str().compare_numeric(RHS); 123| | } 124| | 125| | /// @} 126| | /// @name String Predicates 127| | /// @{ 128| | 129| | /// startswith - Check if this string starts with the given \p Prefix. 130| | bool startswith(StringRef Prefix) const { 131| | return str().startswith(Prefix); 132| | } 133| | 134| | /// endswith - Check if this string ends with the given \p Suffix. 135| | bool endswith(StringRef Suffix) const { 136| | return str().endswith(Suffix); 137| | } 138| | 139| | /// @} 140| | /// @name String Searching 141| | /// @{ 142| | 143| | /// find - Search for the first character \p C in the string. 144| | /// 145| | /// \return - The index of the first occurrence of \p C, or npos if not 146| | /// found. 147| | size_t find(char C, size_t From = 0) const { 148| | return str().find(C, From); 149| | } 150| | 151| | /// Search for the first string \p Str in the string. 152| | /// 153| | /// \returns The index of the first occurrence of \p Str, or npos if not 154| | /// found. 155| | size_t find(StringRef Str, size_t From = 0) const { 156| | return str().find(Str, From); 157| | } 158| | 159| | /// Search for the last character \p C in the string. 160| | /// 161| | /// \returns The index of the last occurrence of \p C, or npos if not 162| | /// found. 163| | size_t rfind(char C, size_t From = StringRef::npos) const { 164| | return str().rfind(C, From); 165| | } 166| | 167| | /// Search for the last string \p Str in the string. 168| | /// 169| | /// \returns The index of the last occurrence of \p Str, or npos if not 170| | /// found. 171| | size_t rfind(StringRef Str) const { 172| | return str().rfind(Str); 173| | } 174| | 175| | /// Find the first character in the string that is \p C, or npos if not 176| | /// found. Same as find. 177| | size_t find_first_of(char C, size_t From = 0) const { 178| | return str().find_first_of(C, From); 179| | } 180| | 181| | /// Find the first character in the string that is in \p Chars, or npos if 182| | /// not found. 183| | /// 184| | /// Complexity: O(size() + Chars.size()) 185| | size_t find_first_of(StringRef Chars, size_t From = 0) const { 186| | return str().find_first_of(Chars, From); 187| | } 188| | 189| | /// Find the first character in the string that is not \p C or npos if not 190| | /// found. 191| | size_t find_first_not_of(char C, size_t From = 0) const { 192| | return str().find_first_not_of(C, From); 193| | } 194| | 195| | /// Find the first character in the string that is not in the string 196| | /// \p Chars, or npos if not found. 197| | /// 198| | /// Complexity: O(size() + Chars.size()) 199| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const { 200| | return str().find_first_not_of(Chars, From); 201| | } 202| | 203| | /// Find the last character in the string that is \p C, or npos if not 204| | /// found. 205| | size_t find_last_of(char C, size_t From = StringRef::npos) const { 206| | return str().find_last_of(C, From); 207| | } 208| | 209| | /// Find the last character in the string that is in \p C, or npos if not 210| | /// found. 211| | /// 212| | /// Complexity: O(size() + Chars.size()) 213| | size_t find_last_of( 214| | StringRef Chars, size_t From = StringRef::npos) const { 215| | return str().find_last_of(Chars, From); 216| | } 217| | 218| | /// @} 219| | /// @name Helpful Algorithms 220| | /// @{ 221| | 222| | /// Return the number of occurrences of \p C in the string. 223| | size_t count(char C) const { 224| | return str().count(C); 225| | } 226| | 227| | /// Return the number of non-overlapped occurrences of \p Str in the 228| | /// string. 229| | size_t count(StringRef Str) const { 230| | return str().count(Str); 231| | } 232| | 233| | /// @} 234| | /// @name Substring Operations 235| | /// @{ 236| | 237| | /// Return a reference to the substring from [Start, Start + N). 238| | /// 239| | /// \param Start The index of the starting character in the substring; if 240| | /// the index is npos or greater than the length of the string then the 241| | /// empty substring will be returned. 242| | /// 243| | /// \param N The number of characters to included in the substring. If \p N 244| | /// exceeds the number of characters remaining in the string, the string 245| | /// suffix (starting with \p Start) will be returned. 246| | StringRef substr(size_t Start, size_t N = StringRef::npos) const { 247| | return str().substr(Start, N); 248| | } 249| | 250| | /// Return a reference to the substring from [Start, End). 251| | /// 252| | /// \param Start The index of the starting character in the substring; if 253| | /// the index is npos or greater than the length of the string then the 254| | /// empty substring will be returned. 255| | /// 256| | /// \param End The index following the last character to include in the 257| | /// substring. If this is npos, or less than \p Start, or exceeds the 258| | /// number of characters remaining in the string, the string suffix 259| | /// (starting with \p Start) will be returned. 260| | StringRef slice(size_t Start, size_t End) const { 261| | return str().slice(Start, End); 262| | } 263| | 264| | // Extra methods. 265| | 266| | /// Explicit conversion to StringRef. 267| 0| StringRef str() const { return StringRef(this->begin(), this->size()); } ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj256EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj1024EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj64EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj16EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj4096EE3strEv ------------------ 268| | 269| | // TODO: Make this const, if it's safe... 270| 0| const char* c_str() { 271| 0| this->push_back(0); 272| 0| this->pop_back(); 273| 0| return this->data(); 274| 0| } 275| | 276| | /// Implicit conversion to StringRef. 277| 0| operator StringRef() const { return str(); } ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj1024EEcvNS_9StringRefEEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj64EEcvNS_9StringRefEEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj4096EEcvNS_9StringRefEEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj256EEcvNS_9StringRefEEv ------------------ 278| | 279| | // Extra operators. 280| | const SmallString &operator=(StringRef RHS) { 281| | this->clear(); 282| | return *this += RHS; 283| | } 284| | 285| | SmallString &operator+=(StringRef RHS) { 286| | this->append(RHS.begin(), RHS.end()); 287| | return *this; 288| | } 289| | SmallString &operator+=(char C) { 290| | this->push_back(C); 291| | return *this; 292| | } 293| |}; 294| | 295| |} 296| | 297| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallVector.h: 1| |//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLVECTOR_H 15| |#define LLVM_ADT_SMALLVECTOR_H 16| | 17| |#include "llvm/ADT/iterator_range.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/type_traits.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |namespace llvm { 32| | 33| |/// This is all the non-templated stuff common to all SmallVectors. 34| |class SmallVectorBase { 35| |protected: 36| | void *BeginX, *EndX, *CapacityX; 37| | 38| |protected: 39| | SmallVectorBase(void *FirstEl, size_t Size) 40| 0| : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} 41| | 42| | /// This is an implementation of the grow() method which only works 43| | /// on POD-like data types and is out of line to reduce code duplication. 44| | void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); 45| | 46| |public: 47| | /// This returns size()*sizeof(T). 48| | size_t size_in_bytes() const { 49| | return size_t((char*)EndX - (char*)BeginX); 50| | } 51| | 52| | /// capacity_in_bytes - This returns capacity()*sizeof(T). 53| | size_t capacity_in_bytes() const { 54| | return size_t((char*)CapacityX - (char*)BeginX); 55| | } 56| | 57| 0| bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } 58| |}; 59| | 60| |template struct SmallVectorStorage; 61| | 62| |/// This is the part of SmallVectorTemplateBase which does not depend on whether 63| |/// the type T is a POD. The extra dummy template argument is used by ArrayRef 64| |/// to avoid unnecessarily requiring T to be complete. 65| |template 66| |class SmallVectorTemplateCommon : public SmallVectorBase { 67| |private: 68| | template friend struct SmallVectorStorage; 69| | 70| | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 71| | // don't want it to be automatically run, so we need to represent the space as 72| | // something else. Use an array of char of sufficient alignment. 73| | typedef llvm::AlignedCharArrayUnion U; 74| | U FirstEl; 75| | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 76| | 77| |protected: 78| 0| SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvEC2Em ------------------ 79| | 80| 0| void grow_pod(size_t MinSizeInBytes, size_t TSize) { 81| 0| SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); 82| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE8grow_podEmm ------------------ 83| | 84| | /// Return true if this is a smallvector which has not had dynamic 85| | /// memory allocated for it. 86| 0| bool isSmall() const { 87| 0| return BeginX == static_cast(&FirstEl); 88| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPvvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE7isSmallEv ------------------ 89| | 90| | /// Put this vector in a state of being small. 91| 0| void resetToSmall() { 92| 0| BeginX = EndX = CapacityX = &FirstEl; 93| 0| } 94| | 95| 0| void setEnd(T *P) { this->EndX = P; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE6setEndEPc ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE6setEndEPh ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE6setEndEPS1_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE6setEndEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE6setEndEPS1_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE6setEndEPS7_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE6setEndEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE6setEndEPS3_ ------------------ 96| |public: 97| | typedef size_t size_type; 98| | typedef ptrdiff_t difference_type; 99| | typedef T value_type; 100| | typedef T *iterator; 101| | typedef const T *const_iterator; 102| | 103| | typedef std::reverse_iterator const_reverse_iterator; 104| | typedef std::reverse_iterator reverse_iterator; 105| | 106| | typedef T &reference; 107| | typedef const T &const_reference; 108| | typedef T *pointer; 109| | typedef const T *const_pointer; 110| | 111| | // forward iterator creation methods. 112| 0| iterator begin() { return (iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE5beginEv ------------------ 113| 0| const_iterator begin() const { return (const_iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE5beginEv ------------------ 114| 0| iterator end() { return (iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE3endEv ------------------ 115| 0| const_iterator end() const { return (const_iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE3endEv ------------------ 116| |protected: 117| 0| iterator capacity_ptr() { return (iterator)this->CapacityX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE12capacity_ptrEv ------------------ 118| 0| const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE12capacity_ptrEv ------------------ 119| |public: 120| | 121| | // reverse iterator creation methods. 122| | reverse_iterator rbegin() { return reverse_iterator(end()); } 123| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 124| | reverse_iterator rend() { return reverse_iterator(begin()); } 125| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 126| | 127| 0| size_type size() const { return end()-begin(); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE4sizeEv ------------------ 128| | size_type max_size() const { return size_type(-1) / sizeof(T); } 129| | 130| | /// Return the total number of elements in the currently allocated buffer. 131| 0| size_t capacity() const { return capacity_ptr() - begin(); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE8capacityEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE8capacityEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE8capacityEv ------------------ 132| | 133| | /// Return a pointer to the vector's buffer, even if empty(). 134| 0| pointer data() { return pointer(begin()); } 135| | /// Return a pointer to the vector's buffer, even if empty(). 136| 0| const_pointer data() const { return const_pointer(begin()); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE4dataEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairINS_9StringRefES3_EEvE4dataEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIN7llbuild5basic8FileInfoEvE4dataEv ------------------ 137| | 138| | reference operator[](size_type idx) { 139| | assert(idx < size()); 140| | return begin()[idx]; 141| | } 142| | const_reference operator[](size_type idx) const { 143| | assert(idx < size()); 144| | return begin()[idx]; 145| | } 146| | 147| | reference front() { 148| | assert(!empty()); 149| | return begin()[0]; 150| | } 151| | const_reference front() const { 152| | assert(!empty()); 153| | return begin()[0]; 154| | } 155| | 156| | reference back() { 157| | assert(!empty()); 158| | return end()[-1]; 159| | } 160| | const_reference back() const { 161| | assert(!empty()); 162| | return end()[-1]; 163| | } 164| |}; 165| | 166| |/// SmallVectorTemplateBase - This is where we put method 167| |/// implementations that are designed to work with non-POD-like T's. 168| |template 169| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 170| |protected: 171| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 172| | 173| 0| static void destroy_range(T *S, T *E) { 174| 0| while (S != E) { 175| 0| --E; 176| 0| E->~T(); 177| 0| } 178| 0| } 179| | 180| | /// Use move-assignment to move the range [I, E) onto the 181| | /// objects starting with "Dest". This is just 's 182| | /// std::move, but not all stdlibs actually provide that. 183| | template 184| | static It2 move(It1 I, It1 E, It2 Dest) { 185| | for (; I != E; ++I, ++Dest) 186| | *Dest = ::std::move(*I); 187| | return Dest; 188| | } 189| | 190| | /// Use move-assignment to move the range 191| | /// [I, E) onto the objects ending at "Dest", moving objects 192| | /// in reverse order. This is just 's 193| | /// std::move_backward, but not all stdlibs actually provide that. 194| | template 195| 0| static It2 move_backward(It1 I, It1 E, It2 Dest) { 196| 0| while (I != E) 197| 0| *--Dest = ::std::move(*--E); 198| 0| return Dest; 199| 0| } 200| | 201| | /// Move the range [I, E) into the uninitialized memory starting with "Dest", 202| | /// constructing elements as needed. 203| | template 204| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 205| 0| for (; I != E; ++I, ++Dest) 206| 0| ::new ((void*) &*Dest) T(::std::move(*I)); 207| 0| } 208| | 209| | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", 210| | /// constructing elements as needed. 211| | template 212| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 213| 0| std::uninitialized_copy(I, E, Dest); 214| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEELb0EE18uninitialized_copyINS1_13move_iteratorIPS7_EESB_EEvT_SD_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEELb0EE18uninitialized_copyIPKNS_9StringRefEPS7_EEvT_SE_T0_ ------------------ 215| | 216| | /// Grow the allocated memory (without initializing new elements), doubling 217| | /// the size of the allocated memory. Guarantees space for at least one more 218| | /// element, or MinSize more elements if specified. 219| | void grow(size_t MinSize = 0); 220| | 221| |public: 222| 0| void push_back(const T &Elt) { 223| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 224| 0| this->grow(); 225| 0| ::new ((void*) this->end()) T(Elt); 226| 0| this->setEnd(this->end()+1); 227| 0| } 228| | 229| | void push_back(T &&Elt) { 230| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 231| | this->grow(); 232| | ::new ((void*) this->end()) T(::std::move(Elt)); 233| | this->setEnd(this->end()+1); 234| | } 235| | 236| | void pop_back() { 237| | this->setEnd(this->end()-1); 238| | this->end()->~T(); 239| | } 240| |}; 241| | 242| |// Define this out-of-line to dissuade the C++ compiler from inlining it. 243| |template 244| 0|void SmallVectorTemplateBase::grow(size_t MinSize) { 245| 0| size_t CurCapacity = this->capacity(); 246| 0| size_t CurSize = this->size(); 247| 0| // Always grow, even from zero. 248| 0| size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); 249| 0| if (NewCapacity < MinSize) 250| 0| NewCapacity = MinSize; 251| 0| T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); 252| 0| 253| 0| // Move the elements over. 254| 0| this->uninitialized_move(this->begin(), this->end(), NewElts); 255| 0| 256| 0| // Destroy the original elements. 257| 0| destroy_range(this->begin(), this->end()); 258| 0| 259| 0| // If this wasn't grown from the inline copy, deallocate the old space. 260| 0| if (!this->isSmall()) 261| 0| free(this->begin()); 262| 0| 263| 0| this->setEnd(NewElts+CurSize); 264| 0| this->BeginX = NewElts; 265| 0| this->CapacityX = this->begin()+NewCapacity; 266| 0|} 267| | 268| | 269| |/// SmallVectorTemplateBase - This is where we put method 270| |/// implementations that are designed to work with POD-like T's. 271| |template 272| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 273| |protected: 274| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairINS_9StringRefES3_EELb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIN7llbuild5basic8FileInfoELb1EEC2Em ------------------ 275| | 276| | // No need to do a destroy loop for POD's. 277| 0| static void destroy_range(T *, T *) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE13destroy_rangeEPcS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EE13destroy_rangeEPS4_S6_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE13destroy_rangeEPS1_S3_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE13destroy_rangeEPhS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairINS_9StringRefES3_EELb1EE13destroy_rangeEPS4_S6_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EE13destroy_rangeEPS1_S3_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIN7llbuild5basic8FileInfoELb1EE13destroy_rangeEPS3_S5_ ------------------ 278| | 279| | /// Use move-assignment to move the range [I, E) onto the 280| | /// objects starting with "Dest". For PODs, this is just memcpy. 281| | template 282| 0| static It2 move(It1 I, It1 E, It2 Dest) { 283| 0| return ::std::copy(I, E, Dest); 284| 0| } 285| | 286| | /// Use move-assignment to move the range [I, E) onto the objects ending at 287| | /// "Dest", moving objects in reverse order. 288| | template 289| 0| static It2 move_backward(It1 I, It1 E, It2 Dest) { 290| 0| return ::std::copy_backward(I, E, Dest); 291| 0| } 292| | 293| | /// Move the range [I, E) onto the uninitialized memory 294| | /// starting with "Dest", constructing elements into it as needed. 295| | template 296| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 297| 0| // Just do a copy. 298| 0| uninitialized_copy(I, E, Dest); 299| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_moveIPhS3_EEvT_S4_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_moveIPcS3_EEvT_S4_T0_ ------------------ 300| | 301| | /// Copy the range [I, E) onto the uninitialized memory 302| | /// starting with "Dest", constructing elements into it as needed. 303| | template 304| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 305| 0| // Arbitrary iterator types; just use the basic implementation. 306| 0| std::uninitialized_copy(I, E, Dest); 307| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyINSt3__113move_iteratorIPhEES5_EEvT_S7_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIPKcPhEEvT_S6_T0_ ------------------ 308| | 309| | /// Copy the range [I, E) onto the uninitialized memory 310| | /// starting with "Dest", constructing elements into it as needed. 311| | template 312| | static void uninitialized_copy( 313| | T1 *I, T1 *E, T2 *Dest, 314| | typename std::enable_if::type, 315| 0| T2>::value>::type * = nullptr) { 316| 0| // Use memcpy for PODs iterated by pointers (which includes SmallVector 317| 0| // iterators): std::uninitialized_copy optimizes to memmove, but we can 318| 0| // use memcpy here. 319| 0| memcpy(Dest, I, (E-I)*sizeof(T)); 320| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIKccEEvPT_S5_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS8_12remove_constIS4_E4typeES6_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIhhEEvPT_S4_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS7_12remove_constIS3_E4typeES5_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIccEEvPT_S4_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS7_12remove_constIS3_E4typeES5_EE5valueEvE4typeE ------------------ 321| | 322| | /// Double the size of the allocated memory, guaranteeing space for at 323| | /// least one more element or MinSize if specified. 324| 0| void grow(size_t MinSize = 0) { 325| 0| this->grow_pod(MinSize*sizeof(T), sizeof(T)); 326| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairINS_9StringRefES3_EELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIN7llbuild5basic8FileInfoELb1EE4growEm ------------------ 327| |public: 328| 0| void push_back(const T &Elt) { 329| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 330| 0| this->grow(); 331| 0| memcpy(this->end(), &Elt, sizeof(T)); 332| 0| this->setEnd(this->end()+1); 333| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE9push_backERKc ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE9push_backERKh ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIN7llbuild5basic8FileInfoELb1EE9push_backERKS3_ ------------------ 334| | 335| 0| void pop_back() { 336| 0| this->setEnd(this->end()-1); 337| 0| } 338| |}; 339| | 340| | 341| |/// This class consists of common code factored out of the SmallVector class to 342| |/// reduce code duplication based on the SmallVector 'N' template parameter. 343| |template 344| |class SmallVectorImpl : public SmallVectorTemplateBase::value> { 345| | typedef SmallVectorTemplateBase::value > SuperClass; 346| | 347| | SmallVectorImpl(const SmallVectorImpl&) = delete; 348| |public: 349| | typedef typename SuperClass::iterator iterator; 350| | typedef typename SuperClass::size_type size_type; 351| | 352| |protected: 353| | // Default ctor - Initialize to empty. 354| | explicit SmallVectorImpl(unsigned N) 355| 0| : SmallVectorTemplateBase::value>(N*sizeof(T)) { 356| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairINS_9StringRefES3_EEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_9StringRefEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIN7llbuild5basic8FileInfoEEC2Ej ------------------ 357| | 358| |public: 359| 0| ~SmallVectorImpl() { 360| 0| // Destroy the constructed elements in the vector. 361| 0| this->destroy_range(this->begin(), this->end()); 362| 0| 363| 0| // If this wasn't grown from the inline copy, deallocate the old space. 364| 0| if (!this->isSmall()) 365| 0| free(this->begin()); 366| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIPvmEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIPvED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairINS_9StringRefES3_EEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_9StringRefEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIN7llbuild5basic8FileInfoEED2Ev ------------------ 367| | 368| | 369| 0| void clear() { 370| 0| this->destroy_range(this->begin(), this->end()); 371| 0| this->EndX = this->BeginX; 372| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE5clearEv ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairINS_9StringRefES3_EEE5clearEv ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE5clearEv ------------------ 373| | 374| | void resize(size_type N) { 375| | if (N < this->size()) { 376| | this->destroy_range(this->begin()+N, this->end()); 377| | this->setEnd(this->begin()+N); 378| | } else if (N > this->size()) { 379| | if (this->capacity() < N) 380| | this->grow(N); 381| | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) 382| | new (&*I) T(); 383| | this->setEnd(this->begin()+N); 384| | } 385| | } 386| | 387| | void resize(size_type N, const T &NV) { 388| | if (N < this->size()) { 389| | this->destroy_range(this->begin()+N, this->end()); 390| | this->setEnd(this->begin()+N); 391| | } else if (N > this->size()) { 392| | if (this->capacity() < N) 393| | this->grow(N); 394| | std::uninitialized_fill(this->end(), this->begin()+N, NV); 395| | this->setEnd(this->begin()+N); 396| | } 397| | } 398| | 399| 0| void reserve(size_type N) { 400| 0| if (this->capacity() < N) 401| 0| this->grow(N); 402| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhE7reserveEm ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE7reserveEm ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairINS_9StringRefES3_EEE7reserveEm ------------------ 403| | 404| | T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { 405| | T Result = ::std::move(this->back()); 406| | this->pop_back(); 407| | return Result; 408| | } 409| | 410| | void swap(SmallVectorImpl &RHS); 411| | 412| | /// Add the specified range to the end of the SmallVector. 413| | template 414| 0| void append(in_iter in_start, in_iter in_end) { 415| 0| size_type NumInputs = std::distance(in_start, in_end); 416| 0| // Grow allocated space if needed. 417| 0| if (NumInputs > size_type(this->capacity_ptr()-this->end())) 418| 0| this->grow(this->size()+NumInputs); 419| 0| 420| 0| // Copy the new elements over. 421| 0| this->uninitialized_copy(in_start, in_end, this->end()); 422| 0| this->setEnd(this->end() + NumInputs); 423| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6appendIPKcEEvT_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhE6appendIPKcEEvT_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhE6appendINSt3__113move_iteratorIPhEEEEvT_S7_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE6appendIPKNS_9StringRefEEEvT_SD_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE6appendINS1_13move_iteratorIPS7_EEEEvT_SD_ ------------------ 424| | 425| | /// Add the specified range to the end of the SmallVector. 426| | void append(size_type NumInputs, const T &Elt) { 427| | // Grow allocated space if needed. 428| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 429| | this->grow(this->size()+NumInputs); 430| | 431| | // Copy the new elements over. 432| | std::uninitialized_fill_n(this->end(), NumInputs, Elt); 433| | this->setEnd(this->end() + NumInputs); 434| | } 435| | 436| | void append(std::initializer_list IL) { 437| | append(IL.begin(), IL.end()); 438| | } 439| | 440| | void assign(size_type NumElts, const T &Elt) { 441| | clear(); 442| | if (this->capacity() < NumElts) 443| | this->grow(NumElts); 444| | this->setEnd(this->begin()+NumElts); 445| | std::uninitialized_fill(this->begin(), this->end(), Elt); 446| | } 447| | 448| | void assign(std::initializer_list IL) { 449| | clear(); 450| | append(IL); 451| | } 452| | 453| | iterator erase(iterator I) { 454| | assert(I >= this->begin() && "Iterator to erase is out of bounds."); 455| | assert(I < this->end() && "Erasing at past-the-end iterator."); 456| | 457| | iterator N = I; 458| | // Shift all elts down one. 459| | this->move(I+1, this->end(), I); 460| | // Drop the last elt. 461| | this->pop_back(); 462| | return(N); 463| | } 464| | 465| | iterator erase(iterator S, iterator E) { 466| | assert(S >= this->begin() && "Range to erase is out of bounds."); 467| | assert(S <= E && "Trying to erase invalid range."); 468| | assert(E <= this->end() && "Trying to erase past the end."); 469| | 470| | iterator N = S; 471| | // Shift all elts down. 472| | iterator I = this->move(E, this->end(), S); 473| | // Drop the last elts. 474| | this->destroy_range(I, this->end()); 475| | this->setEnd(I); 476| | return(N); 477| | } 478| | 479| | iterator insert(iterator I, T &&Elt) { 480| | if (I == this->end()) { // Important special case for empty vector. 481| | this->push_back(::std::move(Elt)); 482| | return this->end()-1; 483| | } 484| | 485| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 486| | assert(I <= this->end() && "Inserting past the end of the vector."); 487| | 488| | if (this->EndX >= this->CapacityX) { 489| | size_t EltNo = I-this->begin(); 490| | this->grow(); 491| | I = this->begin()+EltNo; 492| | } 493| | 494| | ::new ((void*) this->end()) T(::std::move(this->back())); 495| | // Push everything else over. 496| | this->move_backward(I, this->end()-1, this->end()); 497| | this->setEnd(this->end()+1); 498| | 499| | // If we just moved the element we're inserting, be sure to update 500| | // the reference. 501| | T *EltPtr = &Elt; 502| | if (I <= EltPtr && EltPtr < this->EndX) 503| | ++EltPtr; 504| | 505| | *I = ::std::move(*EltPtr); 506| | return I; 507| | } 508| | 509| | iterator insert(iterator I, const T &Elt) { 510| | if (I == this->end()) { // Important special case for empty vector. 511| | this->push_back(Elt); 512| | return this->end()-1; 513| | } 514| | 515| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 516| | assert(I <= this->end() && "Inserting past the end of the vector."); 517| | 518| | if (this->EndX >= this->CapacityX) { 519| | size_t EltNo = I-this->begin(); 520| | this->grow(); 521| | I = this->begin()+EltNo; 522| | } 523| | ::new ((void*) this->end()) T(std::move(this->back())); 524| | // Push everything else over. 525| | this->move_backward(I, this->end()-1, this->end()); 526| | this->setEnd(this->end()+1); 527| | 528| | // If we just moved the element we're inserting, be sure to update 529| | // the reference. 530| | const T *EltPtr = &Elt; 531| | if (I <= EltPtr && EltPtr < this->EndX) 532| | ++EltPtr; 533| | 534| | *I = *EltPtr; 535| | return I; 536| | } 537| | 538| | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 539| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 540| | size_t InsertElt = I - this->begin(); 541| | 542| | if (I == this->end()) { // Important special case for empty vector. 543| | append(NumToInsert, Elt); 544| | return this->begin()+InsertElt; 545| | } 546| | 547| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 548| | assert(I <= this->end() && "Inserting past the end of the vector."); 549| | 550| | // Ensure there is enough space. 551| | reserve(this->size() + NumToInsert); 552| | 553| | // Uninvalidate the iterator. 554| | I = this->begin()+InsertElt; 555| | 556| | // If there are more elements between the insertion point and the end of the 557| | // range than there are being inserted, we can use a simple approach to 558| | // insertion. Since we already reserved space, we know that this won't 559| | // reallocate the vector. 560| | if (size_t(this->end()-I) >= NumToInsert) { 561| | T *OldEnd = this->end(); 562| | append(std::move_iterator(this->end() - NumToInsert), 563| | std::move_iterator(this->end())); 564| | 565| | // Copy the existing elements that get replaced. 566| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 567| | 568| | std::fill_n(I, NumToInsert, Elt); 569| | return I; 570| | } 571| | 572| | // Otherwise, we're inserting more elements than exist already, and we're 573| | // not inserting at the end. 574| | 575| | // Move over the elements that we're about to overwrite. 576| | T *OldEnd = this->end(); 577| | this->setEnd(this->end() + NumToInsert); 578| | size_t NumOverwritten = OldEnd-I; 579| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 580| | 581| | // Replace the overwritten part. 582| | std::fill_n(I, NumOverwritten, Elt); 583| | 584| | // Insert the non-overwritten middle part. 585| | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 586| | return I; 587| | } 588| | 589| | template 590| 0| iterator insert(iterator I, ItTy From, ItTy To) { 591| 0| // Convert iterator to elt# to avoid invalidating iterator when we reserve() 592| 0| size_t InsertElt = I - this->begin(); 593| 0| 594| 0| if (I == this->end()) { // Important special case for empty vector. 595| 0| append(From, To); 596| 0| return this->begin()+InsertElt; 597| 0| } 598| 0| 599| 0| assert(I >= this->begin() && "Insertion iterator is out of bounds."); 600| 0| assert(I <= this->end() && "Inserting past the end of the vector."); 601| 0| 602| 0| size_t NumToInsert = std::distance(From, To); 603| 0| 604| 0| // Ensure there is enough space. 605| 0| reserve(this->size() + NumToInsert); 606| 0| 607| 0| // Uninvalidate the iterator. 608| 0| I = this->begin()+InsertElt; 609| 0| 610| 0| // If there are more elements between the insertion point and the end of the 611| 0| // range than there are being inserted, we can use a simple approach to 612| 0| // insertion. Since we already reserved space, we know that this won't 613| 0| // reallocate the vector. 614| 0| if (size_t(this->end()-I) >= NumToInsert) { 615| 0| T *OldEnd = this->end(); 616| 0| append(std::move_iterator(this->end() - NumToInsert), 617| 0| std::move_iterator(this->end())); 618| 0| 619| 0| // Copy the existing elements that get replaced. 620| 0| this->move_backward(I, OldEnd-NumToInsert, OldEnd); 621| 0| 622| 0| std::copy(From, To, I); 623| 0| return I; 624| 0| } 625| 0| 626| 0| // Otherwise, we're inserting more elements than exist already, and we're 627| 0| // not inserting at the end. 628| 0| 629| 0| // Move over the elements that we're about to overwrite. 630| 0| T *OldEnd = this->end(); 631| 0| this->setEnd(this->end() + NumToInsert); 632| 0| size_t NumOverwritten = OldEnd-I; 633| 0| this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 634| 0| 635| 0| // Replace the overwritten part. 636| 0| for (T *J = I; NumOverwritten > 0; --NumOverwritten) { 637| 0| *J = *From; 638| 0| ++J; ++From; 639| 0| } 640| 0| 641| 0| // Insert the non-overwritten middle part. 642| 0| this->uninitialized_copy(From, To, OldEnd); 643| 0| return I; 644| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhE6insertIPKcEEPhS5_T_S6_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE6insertIPKNS_9StringRefEEEPS7_SD_T_SE_ ------------------ 645| | 646| | void insert(iterator I, std::initializer_list IL) { 647| | insert(I, IL.begin(), IL.end()); 648| | } 649| | 650| 0| template void emplace_back(ArgTypes &&... Args) { 651| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 652| 0| this->grow(); 653| 0| ::new ((void *)this->end()) T(std::forward(Args)...); 654| 0| this->setEnd(this->end() + 1); 655| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE12emplace_backIJRNS_9StringRefEEEEvDpOT_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairINS_9StringRefES3_EEE12emplace_backIJS4_EEEvDpOT_ ------------------ 656| | 657| | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 658| | 659| | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); 660| | 661| | bool operator==(const SmallVectorImpl &RHS) const { 662| | if (this->size() != RHS.size()) return false; 663| | return std::equal(this->begin(), this->end(), RHS.begin()); 664| | } 665| | bool operator!=(const SmallVectorImpl &RHS) const { 666| | return !(*this == RHS); 667| | } 668| | 669| | bool operator<(const SmallVectorImpl &RHS) const { 670| | return std::lexicographical_compare(this->begin(), this->end(), 671| | RHS.begin(), RHS.end()); 672| | } 673| | 674| | /// Set the array size to \p N, which the current array must have enough 675| | /// capacity for. 676| | /// 677| | /// This does not construct or destroy any elements in the vector. 678| | /// 679| | /// Clients can use this in conjunction with capacity() to write past the end 680| | /// of the buffer when they know that more elements are available, and only 681| | /// update the size later. This avoids the cost of value initializing elements 682| | /// which will only be overwritten. 683| | void set_size(size_type N) { 684| | assert(N <= this->capacity()); 685| | this->setEnd(this->begin() + N); 686| | } 687| |}; 688| | 689| | 690| |template 691| |void SmallVectorImpl::swap(SmallVectorImpl &RHS) { 692| | if (this == &RHS) return; 693| | 694| | // We can only avoid copying elements if neither vector is small. 695| | if (!this->isSmall() && !RHS.isSmall()) { 696| | std::swap(this->BeginX, RHS.BeginX); 697| | std::swap(this->EndX, RHS.EndX); 698| | std::swap(this->CapacityX, RHS.CapacityX); 699| | return; 700| | } 701| | if (RHS.size() > this->capacity()) 702| | this->grow(RHS.size()); 703| | if (this->size() > RHS.capacity()) 704| | RHS.grow(this->size()); 705| | 706| | // Swap the shared elements. 707| | size_t NumShared = this->size(); 708| | if (NumShared > RHS.size()) NumShared = RHS.size(); 709| | for (size_type i = 0; i != NumShared; ++i) 710| | std::swap((*this)[i], RHS[i]); 711| | 712| | // Copy over the extra elts. 713| | if (this->size() > RHS.size()) { 714| | size_t EltDiff = this->size() - RHS.size(); 715| | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 716| | RHS.setEnd(RHS.end()+EltDiff); 717| | this->destroy_range(this->begin()+NumShared, this->end()); 718| | this->setEnd(this->begin()+NumShared); 719| | } else if (RHS.size() > this->size()) { 720| | size_t EltDiff = RHS.size() - this->size(); 721| | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 722| | this->setEnd(this->end() + EltDiff); 723| | this->destroy_range(RHS.begin()+NumShared, RHS.end()); 724| | RHS.setEnd(RHS.begin()+NumShared); 725| | } 726| |} 727| | 728| |template 729| |SmallVectorImpl &SmallVectorImpl:: 730| | operator=(const SmallVectorImpl &RHS) { 731| | // Avoid self-assignment. 732| | if (this == &RHS) return *this; 733| | 734| | // If we already have sufficient space, assign the common elements, then 735| | // destroy any excess. 736| | size_t RHSSize = RHS.size(); 737| | size_t CurSize = this->size(); 738| | if (CurSize >= RHSSize) { 739| | // Assign common elements. 740| | iterator NewEnd; 741| | if (RHSSize) 742| | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 743| | else 744| | NewEnd = this->begin(); 745| | 746| | // Destroy excess elements. 747| | this->destroy_range(NewEnd, this->end()); 748| | 749| | // Trim. 750| | this->setEnd(NewEnd); 751| | return *this; 752| | } 753| | 754| | // If we have to grow to have enough elements, destroy the current elements. 755| | // This allows us to avoid copying them during the grow. 756| | // FIXME: don't do this if they're efficiently moveable. 757| | if (this->capacity() < RHSSize) { 758| | // Destroy current elements. 759| | this->destroy_range(this->begin(), this->end()); 760| | this->setEnd(this->begin()); 761| | CurSize = 0; 762| | this->grow(RHSSize); 763| | } else if (CurSize) { 764| | // Otherwise, use assignment for the already-constructed elements. 765| | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 766| | } 767| | 768| | // Copy construct the new elements in place. 769| | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 770| | this->begin()+CurSize); 771| | 772| | // Set end. 773| | this->setEnd(this->begin()+RHSSize); 774| | return *this; 775| |} 776| | 777| |template 778| 0|SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { 779| 0| // Avoid self-assignment. 780| 0| if (this == &RHS) return *this; 781| 0| 782| 0| // If the RHS isn't small, clear this vector and then steal its buffer. 783| 0| if (!RHS.isSmall()) { 784| 0| this->destroy_range(this->begin(), this->end()); 785| 0| if (!this->isSmall()) free(this->begin()); 786| 0| this->BeginX = RHS.BeginX; 787| 0| this->EndX = RHS.EndX; 788| 0| this->CapacityX = RHS.CapacityX; 789| 0| RHS.resetToSmall(); 790| 0| return *this; 791| 0| } 792| 0| 793| 0| // If we already have sufficient space, assign the common elements, then 794| 0| // destroy any excess. 795| 0| size_t RHSSize = RHS.size(); 796| 0| size_t CurSize = this->size(); 797| 0| if (CurSize >= RHSSize) { 798| 0| // Assign common elements. 799| 0| iterator NewEnd = this->begin(); 800| 0| if (RHSSize) 801| 0| NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); 802| 0| 803| 0| // Destroy excess elements and trim the bounds. 804| 0| this->destroy_range(NewEnd, this->end()); 805| 0| this->setEnd(NewEnd); 806| 0| 807| 0| // Clear the RHS. 808| 0| RHS.clear(); 809| 0| 810| 0| return *this; 811| 0| } 812| 0| 813| 0| // If we have to grow to have enough elements, destroy the current elements. 814| 0| // This allows us to avoid copying them during the grow. 815| 0| // FIXME: this may not actually make any sense if we can efficiently move 816| 0| // elements. 817| 0| if (this->capacity() < RHSSize) { 818| 0| // Destroy current elements. 819| 0| this->destroy_range(this->begin(), this->end()); 820| 0| this->setEnd(this->begin()); 821| 0| CurSize = 0; 822| 0| this->grow(RHSSize); 823| 0| } else if (CurSize) { 824| 0| // Otherwise, use assignment for the already-constructed elements. 825| 0| this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); 826| 0| } 827| 0| 828| 0| // Move-construct the new elements in place. 829| 0| this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), 830| 0| this->begin()+CurSize); 831| 0| 832| 0| // Set end. 833| 0| this->setEnd(this->begin()+RHSSize); 834| 0| 835| 0| RHS.clear(); 836| 0| return *this; 837| 0|} 838| | 839| |/// Storage for the SmallVector elements which aren't contained in 840| |/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' 841| |/// element is in the base class. This is specialized for the N=1 and N=0 cases 842| |/// to avoid allocating unnecessary storage. 843| |template 844| |struct SmallVectorStorage { 845| | typename SmallVectorTemplateCommon::U InlineElts[N - 1]; 846| |}; 847| |template struct SmallVectorStorage {}; 848| |template struct SmallVectorStorage {}; 849| | 850| |/// This is a 'vector' (really, a variable-sized array), optimized 851| |/// for the case when the array is small. It contains some number of elements 852| |/// in-place, which allows it to avoid heap allocation when the actual number of 853| |/// elements is below that threshold. This allows normal "small" cases to be 854| |/// fast without losing generality for large inputs. 855| |/// 856| |/// Note that this does not attempt to be exception safe. 857| |/// 858| |template 859| |class SmallVector : public SmallVectorImpl { 860| | /// Inline space for elements which aren't stored in the base class. 861| | SmallVectorStorage Storage; 862| |public: 863| 0| SmallVector() : SmallVectorImpl(N) { 864| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINSt3__14pairINS_9StringRefES3_EELj1EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEELj1EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIhLj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj64EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_9StringRefELj32EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj16EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj4096EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj128EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIN7llbuild5basic8FileInfoELj8EEC2Ev ------------------ 865| | 866| | explicit SmallVector(size_t Size, const T &Value = T()) 867| | : SmallVectorImpl(N) { 868| | this->assign(Size, Value); 869| | } 870| | 871| | template 872| 0| SmallVector(ItTy S, ItTy E) : SmallVectorImpl(N) { 873| 0| this->append(S, E); 874| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj1024EEC2IPKcEET_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj256EEC2IPKcEET_S5_ ------------------ 875| | 876| | template 877| | explicit SmallVector(const llvm::iterator_range R) 878| | : SmallVectorImpl(N) { 879| | this->append(R.begin(), R.end()); 880| | } 881| | 882| | SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { 883| | this->assign(IL); 884| | } 885| | 886| | SmallVector(const SmallVector &RHS) : SmallVectorImpl(N) { 887| | if (!RHS.empty()) 888| | SmallVectorImpl::operator=(RHS); 889| | } 890| | 891| | const SmallVector &operator=(const SmallVector &RHS) { 892| | SmallVectorImpl::operator=(RHS); 893| | return *this; 894| | } 895| | 896| | SmallVector(SmallVector &&RHS) : SmallVectorImpl(N) { 897| | if (!RHS.empty()) 898| | SmallVectorImpl::operator=(::std::move(RHS)); 899| | } 900| | 901| | const SmallVector &operator=(SmallVector &&RHS) { 902| | SmallVectorImpl::operator=(::std::move(RHS)); 903| | return *this; 904| | } 905| | 906| | SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { 907| | if (!RHS.empty()) 908| | SmallVectorImpl::operator=(::std::move(RHS)); 909| | } 910| | 911| | const SmallVector &operator=(SmallVectorImpl &&RHS) { 912| | SmallVectorImpl::operator=(::std::move(RHS)); 913| | return *this; 914| | } 915| | 916| | const SmallVector &operator=(std::initializer_list IL) { 917| | this->assign(IL); 918| | return *this; 919| | } 920| |}; 921| | 922| |template 923| |static inline size_t capacity_in_bytes(const SmallVector &X) { 924| | return X.capacity_in_bytes(); 925| |} 926| | 927| |} // End llvm namespace 928| | 929| |namespace std { 930| | /// Implement std::swap in terms of SmallVector swap. 931| | template 932| | inline void 933| | swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { 934| | LHS.swap(RHS); 935| | } 936| | 937| | /// Implement std::swap in terms of SmallVector swap. 938| | template 939| | inline void 940| | swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { 941| | LHS.swap(RHS); 942| | } 943| |} 944| | 945| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringMap.h: 1| |//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGMAP_H 15| |#define LLVM_ADT_STRINGMAP_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/Allocator.h" 19| |#include 20| |#include 21| | 22| |namespace llvm { 23| | template 24| | class StringMapConstIterator; 25| | template 26| | class StringMapIterator; 27| | template 28| | class StringMapEntry; 29| | 30| |/// StringMapEntryBase - Shared base class of StringMapEntry instances. 31| |class StringMapEntryBase { 32| | unsigned StrLen; 33| |public: 34| 0| explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 35| | 36| 0| unsigned getKeyLength() const { return StrLen; } 37| |}; 38| | 39| |/// StringMapImpl - This is the base class of StringMap that is shared among 40| |/// all of its instantiations. 41| |class StringMapImpl { 42| |protected: 43| | // Array of NumBuckets pointers to entries, null pointers are holes. 44| | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 45| | // by an array of the actual hash values as unsigned integers. 46| | StringMapEntryBase **TheTable; 47| | unsigned NumBuckets; 48| | unsigned NumItems; 49| | unsigned NumTombstones; 50| | unsigned ItemSize; 51| |protected: 52| | explicit StringMapImpl(unsigned itemSize) 53| | : TheTable(nullptr), 54| | // Initialize the map with zero buckets to allocation. 55| 0| NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 56| | StringMapImpl(StringMapImpl &&RHS) 57| | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 58| | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 59| 0| ItemSize(RHS.ItemSize) { 60| 0| RHS.TheTable = nullptr; 61| 0| RHS.NumBuckets = 0; 62| 0| RHS.NumItems = 0; 63| 0| RHS.NumTombstones = 0; 64| 0| } 65| | 66| | StringMapImpl(unsigned InitSize, unsigned ItemSize); 67| | unsigned RehashTable(unsigned BucketNo = 0); 68| | 69| | /// LookupBucketFor - Look up the bucket that the specified string should end 70| | /// up in. If it already exists as a key in the map, the Item pointer for the 71| | /// specified bucket will be non-null. Otherwise, it will be null. In either 72| | /// case, the FullHashValue field of the bucket will be set to the hash value 73| | /// of the string. 74| | unsigned LookupBucketFor(StringRef Key); 75| | 76| | /// FindKey - Look up the bucket that contains the specified key. If it exists 77| | /// in the map, return the bucket number of the key. Otherwise return -1. 78| | /// This does not modify the map. 79| | int FindKey(StringRef Key) const; 80| | 81| | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 82| | /// delete it. This aborts if the value isn't in the table. 83| | void RemoveKey(StringMapEntryBase *V); 84| | 85| | /// RemoveKey - Remove the StringMapEntry for the specified key from the 86| | /// table, returning it. If the key is not in the table, this returns null. 87| | StringMapEntryBase *RemoveKey(StringRef Key); 88| |private: 89| | void init(unsigned Size); 90| |public: 91| 0| static StringMapEntryBase *getTombstoneVal() { 92| 0| return (StringMapEntryBase*)-1; 93| 0| } 94| | 95| 0| unsigned getNumBuckets() const { return NumBuckets; } 96| 0| unsigned getNumItems() const { return NumItems; } 97| | 98| 0| bool empty() const { return NumItems == 0; } 99| 0| unsigned size() const { return NumItems; } 100| | 101| 0| void swap(StringMapImpl &Other) { 102| 0| std::swap(TheTable, Other.TheTable); 103| 0| std::swap(NumBuckets, Other.NumBuckets); 104| 0| std::swap(NumItems, Other.NumItems); 105| 0| std::swap(NumTombstones, Other.NumTombstones); 106| 0| } 107| |}; 108| | 109| |/// StringMapEntry - This is used to represent one value that is inserted into 110| |/// a StringMap. It contains the Value itself and the key: the string length 111| |/// and data. 112| |template 113| |class StringMapEntry : public StringMapEntryBase { 114| | StringMapEntry(StringMapEntry &E) = delete; 115| |public: 116| | ValueTy second; 117| | 118| | explicit StringMapEntry(unsigned strLen) 119| | : StringMapEntryBase(strLen), second() {} 120| | template 121| | StringMapEntry(unsigned strLen, InitTy &&V) 122| 0| : StringMapEntryBase(strLen), second(std::forward(V)) {} ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEEC2IS8_EEjOT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEC2IS8_EEjOT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEC2IS8_EEjOT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEC2IS8_EEjOT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryIbEC2IbEEjOT_ ------------------ 123| | 124| 0| StringRef getKey() const { 125| 0| return StringRef(getKeyData(), getKeyLength()); 126| 0| } 127| | 128| | const ValueTy &getValue() const { return second; } 129| | ValueTy &getValue() { return second; } 130| | 131| | void setValue(const ValueTy &V) { second = V; } 132| | 133| | /// getKeyData - Return the start of the string data that is the key for this 134| | /// value. The string data is always stored immediately after the 135| | /// StringMapEntry object. 136| 0| const char *getKeyData() const {return reinterpret_cast(this+1);} ------------------ | Unexecuted instantiation: _ZNK4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEE10getKeyDataEv ------------------ | Unexecuted instantiation: _ZNK4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEE10getKeyDataEv ------------------ | Unexecuted instantiation: _ZNK4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEE10getKeyDataEv ------------------ | Unexecuted instantiation: _ZNK4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEE10getKeyDataEv ------------------ | Unexecuted instantiation: _ZNK4llvm14StringMapEntryIbE10getKeyDataEv ------------------ 137| | 138| | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 139| | 140| | /// Create - Create a StringMapEntry for the specified key and default 141| | /// construct the value. 142| | template 143| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 144| 0| InitType &&InitVal) { 145| 0| unsigned KeyLength = Key.size(); 146| 0| 147| 0| // Allocate a new item with space for the string at the end and a null 148| 0| // terminator. 149| 0| unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ 150| 0| KeyLength+1; 151| 0| unsigned Alignment = alignOf(); 152| 0| 153| 0| StringMapEntry *NewItem = 154| 0| static_cast(Allocator.Allocate(AllocSize,Alignment)); 155| 0| 156| 0| // Default construct the value. 157| 0| new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); 158| 0| 159| 0| // Copy the string information. 160| 0| char *StrBuffer = const_cast(NewItem->getKeyData()); 161| 0| memcpy(StrBuffer, Key.data(), KeyLength); 162| 0| StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 163| 0| return NewItem; 164| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEE6CreateINS_15MallocAllocatorES8_EEPS9_NS_9StringRefERT_OT0_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEE6CreateINS_15MallocAllocatorES8_EEPS9_NS_9StringRefERT_OT0_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEE6CreateINS_15MallocAllocatorES8_EEPS9_NS_9StringRefERT_OT0_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEE6CreateINS_15MallocAllocatorES8_EEPS9_NS_9StringRefERT_OT0_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryIbE6CreateINS_15MallocAllocatorEbEEPS1_NS_9StringRefERT_OT0_ ------------------ 165| | 166| | template 167| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 168| | return Create(Key, Allocator, ValueTy()); 169| | } 170| | 171| | /// Create - Create a StringMapEntry with normal malloc/free. 172| | template 173| | static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { 174| | MallocAllocator A; 175| | return Create(Key, A, std::forward(InitVal)); 176| | } 177| | 178| | static StringMapEntry *Create(StringRef Key) { 179| | return Create(Key, ValueTy()); 180| | } 181| | 182| | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 183| | /// into a StringMapEntry, return the StringMapEntry itself. 184| | static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 185| | char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); 186| | return *reinterpret_cast(Ptr); 187| | } 188| | 189| | /// Destroy - Destroy this StringMapEntry, releasing memory back to the 190| | /// specified allocator. 191| | template 192| 0| void Destroy(AllocatorTy &Allocator) { 193| 0| // Free memory referenced by the item. 194| 0| unsigned AllocSize = 195| 0| static_cast(sizeof(StringMapEntry)) + getKeyLength() + 1; 196| 0| this->~StringMapEntry(); 197| 0| Allocator.Deallocate(static_cast(this), AllocSize); 198| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEE7DestroyINS_15MallocAllocatorEEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEE7DestroyINS_15MallocAllocatorEEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEE7DestroyINS_15MallocAllocatorEEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEE7DestroyINS_15MallocAllocatorEEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm14StringMapEntryIbE7DestroyINS_15MallocAllocatorEEEvRT_ ------------------ 199| | 200| | /// Destroy this object, releasing memory back to the malloc allocator. 201| | void Destroy() { 202| | MallocAllocator A; 203| | Destroy(A); 204| | } 205| |}; 206| | 207| | 208| |/// StringMap - This is an unconventional map that is specialized for handling 209| |/// keys that are "strings", which are basically ranges of bytes. This does some 210| |/// funky memory allocation and hashing things to make it extremely efficient, 211| |/// storing the string data *after* the value in the map. 212| |template 213| |class StringMap : public StringMapImpl { 214| | AllocatorTy Allocator; 215| |public: 216| | typedef StringMapEntry MapEntryTy; 217| | 218| 0| StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapIbNS_15MallocAllocatorEEC2Ev ------------------ 219| | explicit StringMap(unsigned InitialSize) 220| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} 221| | 222| | explicit StringMap(AllocatorTy A) 223| | : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} 224| | 225| | StringMap(unsigned InitialSize, AllocatorTy A) 226| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), 227| | Allocator(A) {} 228| | 229| | StringMap(StringMap &&RHS) 230| 0| : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2EOSA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2EOSA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2EOSA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEC2EOSA_ ------------------ 231| | 232| 0| StringMap &operator=(StringMap RHS) { 233| 0| StringMapImpl::swap(RHS); 234| 0| std::swap(Allocator, RHS.Allocator); 235| 0| return *this; 236| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEaSESA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEaSESA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEaSESA_ ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEaSESA_ ------------------ 237| | 238| | // FIXME: Implement copy operations if/when they're needed. 239| | 240| | AllocatorTy &getAllocator() { return Allocator; } 241| | const AllocatorTy &getAllocator() const { return Allocator; } 242| | 243| | typedef const char* key_type; 244| | typedef ValueTy mapped_type; 245| | typedef StringMapEntry value_type; 246| | typedef size_t size_type; 247| | 248| | typedef StringMapConstIterator const_iterator; 249| | typedef StringMapIterator iterator; 250| | 251| | iterator begin() { 252| | return iterator(TheTable, NumBuckets == 0); 253| | } 254| 0| iterator end() { 255| 0| return iterator(TheTable+NumBuckets, true); 256| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ 257| 0| const_iterator begin() const { 258| 0| return const_iterator(TheTable, NumBuckets == 0); 259| 0| } 260| 0| const_iterator end() const { 261| 0| return const_iterator(TheTable+NumBuckets, true); 262| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE3endEv ------------------ 263| | 264| 0| iterator find(StringRef Key) { 265| 0| int Bucket = FindKey(Key); 266| 0| if (Bucket == -1) return end(); 267| 0| return iterator(TheTable+Bucket, true); 268| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ 269| | 270| 0| const_iterator find(StringRef Key) const { 271| 0| int Bucket = FindKey(Key); 272| 0| if (Bucket == -1) return end(); 273| 0| return const_iterator(TheTable+Bucket, true); 274| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ | Unexecuted instantiation: _ZNK4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE4findENS_9StringRefE ------------------ 275| | 276| | /// lookup - Return the entry for the specified key, or a default 277| | /// constructed value if no such entry exists. 278| | ValueTy lookup(StringRef Key) const { 279| | const_iterator it = find(Key); 280| | if (it != end()) 281| | return it->second; 282| | return ValueTy(); 283| | } 284| | 285| 0| ValueTy &operator[](StringRef Key) { 286| 0| return insert(std::make_pair(Key, ValueTy())).first->second; 287| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEixENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEixENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEixENS_9StringRefE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEEixENS_9StringRefE ------------------ 288| | 289| | /// count - Return 1 if the element is in the map, 0 otherwise. 290| 0| size_type count(StringRef Key) const { 291| 0| return find(Key) == end() ? 0 : 1; 292| 0| } 293| | 294| | /// insert - Insert the specified key/value pair into the map. If the key 295| | /// already exists in the map, return false and ignore the request, otherwise 296| | /// insert it and return true. 297| | bool insert(MapEntryTy *KeyValue) { 298| | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 299| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 300| | if (Bucket && Bucket != getTombstoneVal()) 301| | return false; // Already exists in map. 302| | 303| | if (Bucket == getTombstoneVal()) 304| | --NumTombstones; 305| | Bucket = KeyValue; 306| | ++NumItems; 307| | assert(NumItems + NumTombstones <= NumBuckets); 308| | 309| | RehashTable(); 310| | return true; 311| | } 312| | 313| | /// insert - Inserts the specified key/value pair into the map if the key 314| | /// isn't already in the map. The bool component of the returned pair is true 315| | /// if and only if the insertion takes place, and the iterator component of 316| | /// the pair points to the element with key equivalent to the key of the pair. 317| 0| std::pair insert(std::pair KV) { 318| 0| unsigned BucketNo = LookupBucketFor(KV.first); 319| 0| StringMapEntryBase *&Bucket = TheTable[BucketNo]; 320| 0| if (Bucket && Bucket != getTombstoneVal()) 321| 0| return std::make_pair(iterator(TheTable + BucketNo, false), 322| 0| false); // Already exists in map. 323| 0| 324| 0| if (Bucket == getTombstoneVal()) 325| 0| --NumTombstones; 326| 0| Bucket = 327| 0| MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 328| 0| ++NumItems; 329| 0| assert(NumItems + NumTombstones <= NumBuckets); 330| 0| 331| 0| BucketNo = RehashTable(BucketNo); 332| 0| return std::make_pair(iterator(TheTable + BucketNo, false), true); 333| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE6insertENS1_4pairINS_9StringRefES8_EE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE6insertENS1_4pairINS_9StringRefES8_EE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE6insertENS1_4pairINS_9StringRefES8_EE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEE6insertENS1_4pairINS_9StringRefES8_EE ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapIbNS_15MallocAllocatorEE6insertENSt3__14pairINS_9StringRefEbEE ------------------ 334| | 335| | // clear - Empties out the StringMap 336| | void clear() { 337| | if (empty()) return; 338| | 339| | // Zap all values, resetting the keys back to non-present (not tombstone), 340| | // which is safe because we're removing all elements. 341| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 342| | StringMapEntryBase *&Bucket = TheTable[I]; 343| | if (Bucket && Bucket != getTombstoneVal()) { 344| | static_cast(Bucket)->Destroy(Allocator); 345| | } 346| | Bucket = nullptr; 347| | } 348| | 349| | NumItems = 0; 350| | NumTombstones = 0; 351| | } 352| | 353| | /// remove - Remove the specified key/value pair from the map, but do not 354| | /// erase it. This aborts if the key is not in the map. 355| | void remove(MapEntryTy *KeyValue) { 356| | RemoveKey(KeyValue); 357| | } 358| | 359| | void erase(iterator I) { 360| | MapEntryTy &V = *I; 361| | remove(&V); 362| | V.Destroy(Allocator); 363| | } 364| | 365| | bool erase(StringRef Key) { 366| | iterator I = find(Key); 367| | if (I == end()) return false; 368| | erase(I); 369| | return true; 370| | } 371| | 372| 0| ~StringMap() { 373| 0| // Delete all the elements in the map, but don't reset the elements 374| 0| // to default values. This is a copy of clear(), but avoids unnecessary 375| 0| // work not required in the destructor. 376| 0| if (!empty()) { 377| 0| for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 378| 0| StringMapEntryBase *Bucket = TheTable[I]; 379| 0| if (Bucket && Bucket != getTombstoneVal()) { 380| 0| static_cast(Bucket)->Destroy(Allocator); 381| 0| } 382| 0| } 383| 0| } 384| 0| free(TheTable); 385| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEENS_15MallocAllocatorEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm9StringMapIbNS_15MallocAllocatorEED2Ev ------------------ 386| |}; 387| | 388| | 389| |template 390| |class StringMapConstIterator { 391| |protected: 392| | StringMapEntryBase **Ptr; 393| |public: 394| | typedef StringMapEntry value_type; 395| | 396| | StringMapConstIterator() : Ptr(nullptr) { } 397| | 398| | explicit StringMapConstIterator(StringMapEntryBase **Bucket, 399| | bool NoAdvance = false) 400| 0| : Ptr(Bucket) { 401| 0| if (!NoAdvance) AdvancePastEmptyBuckets(); 402| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorIbEC2EPPNS_18StringMapEntryBaseEb ------------------ 403| | 404| 0| const value_type &operator*() const { 405| 0| return *static_cast*>(*Ptr); 406| 0| } 407| 0| const value_type *operator->() const { 408| 0| return static_cast*>(*Ptr); 409| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEptEv ------------------ 410| | 411| 0| bool operator==(const StringMapConstIterator &RHS) const { 412| 0| return Ptr == RHS.Ptr; 413| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEeqERKS9_ ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEeqERKS9_ ------------------ 414| 0| bool operator!=(const StringMapConstIterator &RHS) const { 415| 0| return Ptr != RHS.Ptr; 416| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEEneERKS9_ ------------------ | Unexecuted instantiation: _ZNK4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEneERKS9_ ------------------ 417| | 418| 0| inline StringMapConstIterator& operator++() { // Preincrement 419| 0| ++Ptr; 420| 0| AdvancePastEmptyBuckets(); 421| 0| return *this; 422| 0| } 423| | StringMapConstIterator operator++(int) { // Postincrement 424| | StringMapConstIterator tmp = *this; ++*this; return tmp; 425| | } 426| | 427| |private: 428| 0| void AdvancePastEmptyBuckets() { 429| 0| while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 430| 0| ++Ptr; 431| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEE23AdvancePastEmptyBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEE23AdvancePastEmptyBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEE23AdvancePastEmptyBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEE23AdvancePastEmptyBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm22StringMapConstIteratorIbE23AdvancePastEmptyBucketsEv ------------------ 432| |}; 433| | 434| |template 435| |class StringMapIterator : public StringMapConstIterator { 436| |public: 437| | StringMapIterator() {} 438| | explicit StringMapIterator(StringMapEntryBase **Bucket, 439| | bool NoAdvance = false) 440| 0| : StringMapConstIterator(Bucket, NoAdvance) { 441| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEC2EPPNS_18StringMapEntryBaseEb ------------------ | Unexecuted instantiation: _ZN4llvm17StringMapIteratorIbEC2EPPNS_18StringMapEntryBaseEb ------------------ 442| | StringMapEntry &operator*() const { 443| | return *static_cast*>(*this->Ptr); 444| | } 445| 0| StringMapEntry *operator->() const { 446| 0| return static_cast*>(*this->Ptr); 447| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm17StringMapIteratorINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS1_14default_deleteIS5_EEEEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm17StringMapIteratorIbEptEv ------------------ 448| |}; 449| | 450| |} 451| | 452| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringRef.h: 1| |//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_STRINGREF_H 11| |#define LLVM_ADT_STRINGREF_H 12| | 13| |#include 14| |#include 15| |#include 16| |#include 17| |#include 18| |#include 19| | 20| |namespace llvm { 21| | template 22| | class SmallVectorImpl; 23| | class hash_code; 24| | class StringRef; 25| | 26| | /// Helper functions for StringRef::getAsInteger. 27| | bool getAsUnsignedInteger(StringRef Str, unsigned Radix, 28| | unsigned long long &Result); 29| | 30| | bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); 31| | 32| | /// StringRef - Represent a constant reference to a string, i.e. a character 33| | /// array and a length, which need not be null terminated. 34| | /// 35| | /// This class does not own the string data, it is expected to be used in 36| | /// situations where the character data resides in some other buffer, whose 37| | /// lifetime extends past that of the StringRef. For this reason, it is not in 38| | /// general safe to store a StringRef. 39| | class StringRef { 40| | public: 41| | typedef const char *iterator; 42| | typedef const char *const_iterator; 43| | static const size_t npos = ~size_t(0); 44| | typedef size_t size_type; 45| | 46| | private: 47| | /// The start of the string, in an external buffer. 48| | const char *Data; 49| | 50| | /// The length of the string. 51| | size_t Length; 52| | 53| | // Workaround memcmp issue with null pointers (undefined behavior) 54| | // by providing a specialized version 55| 0| static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { 56| 0| if (Length == 0) { return 0; } 57| 0| return ::memcmp(Lhs,Rhs,Length); 58| 0| } 59| | 60| | public: 61| | /// @name Constructors 62| | /// @{ 63| | 64| | /// Construct an empty string ref. 65| 0| /*implicit*/ StringRef() : Data(nullptr), Length(0) {} 66| | 67| | /// Construct a string ref from a cstring. 68| | /*implicit*/ StringRef(const char *Str) 69| 0| : Data(Str) { 70| 0| assert(Str && "StringRef cannot be built from a NULL argument"); 71| 0| Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior 72| 0| } 73| | 74| | /// Construct a string ref from a pointer and length. 75| | /*implicit*/ StringRef(const char *data, size_t length) 76| 0| : Data(data), Length(length) { 77| 0| assert((data || length == 0) && 78| 0| "StringRef cannot be built from a NULL argument with non-null length"); 79| 0| } 80| | 81| | /// Construct a string ref from an std::string. 82| | /*implicit*/ StringRef(const std::string &Str) 83| 0| : Data(Str.data()), Length(Str.length()) {} 84| | 85| | /// @} 86| | /// @name Iterators 87| | /// @{ 88| | 89| 0| iterator begin() const { return Data; } 90| | 91| 0| iterator end() const { return Data + Length; } 92| | 93| 0| const unsigned char *bytes_begin() const { 94| 0| return reinterpret_cast(begin()); 95| 0| } 96| 0| const unsigned char *bytes_end() const { 97| 0| return reinterpret_cast(end()); 98| 0| } 99| | 100| | /// @} 101| | /// @name String Operations 102| | /// @{ 103| | 104| | /// data - Get a pointer to the start of the string (which may not be null 105| | /// terminated). 106| 0| const char *data() const { return Data; } 107| | 108| | /// empty - Check if the string is empty. 109| 0| bool empty() const { return Length == 0; } 110| | 111| | /// size - Get the string size. 112| 0| size_t size() const { return Length; } 113| | 114| | /// front - Get the first character in the string. 115| | char front() const { 116| | assert(!empty()); 117| | return Data[0]; 118| | } 119| | 120| | /// back - Get the last character in the string. 121| 0| char back() const { 122| 0| assert(!empty()); 123| 0| return Data[Length-1]; 124| 0| } 125| | 126| | // copy - Allocate copy in Allocator and return StringRef to it. 127| | template StringRef copy(Allocator &A) const { 128| | char *S = A.template Allocate(Length); 129| | std::copy(begin(), end(), S); 130| | return StringRef(S, Length); 131| | } 132| | 133| | /// equals - Check for string equality, this is more efficient than 134| | /// compare() when the relative ordering of inequal strings isn't needed. 135| 0| bool equals(StringRef RHS) const { 136| 0| return (Length == RHS.Length && 137| 0| compareMemory(Data, RHS.Data, RHS.Length) == 0); 138| 0| } 139| | 140| | /// equals_lower - Check for string equality, ignoring case. 141| | bool equals_lower(StringRef RHS) const { 142| | return Length == RHS.Length && compare_lower(RHS) == 0; 143| | } 144| | 145| | /// compare - Compare two strings; the result is -1, 0, or 1 if this string 146| | /// is lexicographically less than, equal to, or greater than the \p RHS. 147| | int compare(StringRef RHS) const { 148| | // Check the prefix for a mismatch. 149| | if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) 150| | return Res < 0 ? -1 : 1; 151| | 152| | // Otherwise the prefixes match, so we only need to check the lengths. 153| | if (Length == RHS.Length) 154| | return 0; 155| | return Length < RHS.Length ? -1 : 1; 156| | } 157| | 158| | /// compare_lower - Compare two strings, ignoring case. 159| | int compare_lower(StringRef RHS) const; 160| | 161| | /// compare_numeric - Compare two strings, treating sequences of digits as 162| | /// numbers. 163| | int compare_numeric(StringRef RHS) const; 164| | 165| | /// \brief Determine the edit distance between this string and another 166| | /// string. 167| | /// 168| | /// \param Other the string to compare this string against. 169| | /// 170| | /// \param AllowReplacements whether to allow character 171| | /// replacements (change one character into another) as a single 172| | /// operation, rather than as two operations (an insertion and a 173| | /// removal). 174| | /// 175| | /// \param MaxEditDistance If non-zero, the maximum edit distance that 176| | /// this routine is allowed to compute. If the edit distance will exceed 177| | /// that maximum, returns \c MaxEditDistance+1. 178| | /// 179| | /// \returns the minimum number of character insertions, removals, 180| | /// or (if \p AllowReplacements is \c true) replacements needed to 181| | /// transform one of the given strings into the other. If zero, 182| | /// the strings are identical. 183| | unsigned edit_distance(StringRef Other, bool AllowReplacements = true, 184| | unsigned MaxEditDistance = 0) const; 185| | 186| | /// str - Get the contents as an std::string. 187| 0| std::string str() const { 188| 0| if (!Data) return std::string(); 189| 0| return std::string(Data, Length); 190| 0| } 191| | 192| | /// @} 193| | /// @name Operator Overloads 194| | /// @{ 195| | 196| 0| char operator[](size_t Index) const { 197| 0| assert(Index < Length && "Invalid index!"); 198| 0| return Data[Index]; 199| 0| } 200| | 201| | /// @} 202| | /// @name Type Conversions 203| | /// @{ 204| | 205| 0| operator std::string() const { 206| 0| return str(); 207| 0| } 208| | 209| | /// @} 210| | /// @name String Predicates 211| | /// @{ 212| | 213| | /// Check if this string starts with the given \p Prefix. 214| 0| bool startswith(StringRef Prefix) const { 215| 0| return Length >= Prefix.Length && 216| 0| compareMemory(Data, Prefix.Data, Prefix.Length) == 0; 217| 0| } 218| | 219| | /// Check if this string starts with the given \p Prefix, ignoring case. 220| | bool startswith_lower(StringRef Prefix) const; 221| | 222| | /// Check if this string ends with the given \p Suffix. 223| 0| bool endswith(StringRef Suffix) const { 224| 0| return Length >= Suffix.Length && 225| 0| compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 226| 0| } 227| | 228| | /// Check if this string ends with the given \p Suffix, ignoring case. 229| | bool endswith_lower(StringRef Suffix) const; 230| | 231| | /// @} 232| | /// @name String Searching 233| | /// @{ 234| | 235| | /// Search for the first character \p C in the string. 236| | /// 237| | /// \returns The index of the first occurrence of \p C, or npos if not 238| | /// found. 239| 0| size_t find(char C, size_t From = 0) const { 240| 0| for (size_t i = std::min(From, Length), e = Length; i != e; ++i) 241| 0| if (Data[i] == C) 242| 0| return i; 243| 0| return npos; 244| 0| } 245| | 246| | /// Search for the first string \p Str in the string. 247| | /// 248| | /// \returns The index of the first occurrence of \p Str, or npos if not 249| | /// found. 250| | size_t find(StringRef Str, size_t From = 0) const; 251| | 252| | /// Search for the last character \p C in the string. 253| | /// 254| | /// \returns The index of the last occurrence of \p C, or npos if not 255| | /// found. 256| | size_t rfind(char C, size_t From = npos) const { 257| | From = std::min(From, Length); 258| | size_t i = From; 259| | while (i != 0) { 260| | --i; 261| | if (Data[i] == C) 262| | return i; 263| | } 264| | return npos; 265| | } 266| | 267| | /// Search for the last string \p Str in the string. 268| | /// 269| | /// \returns The index of the last occurrence of \p Str, or npos if not 270| | /// found. 271| | size_t rfind(StringRef Str) const; 272| | 273| | /// Find the first character in the string that is \p C, or npos if not 274| | /// found. Same as find. 275| | size_t find_first_of(char C, size_t From = 0) const { 276| | return find(C, From); 277| | } 278| | 279| | /// Find the first character in the string that is in \p Chars, or npos if 280| | /// not found. 281| | /// 282| | /// Complexity: O(size() + Chars.size()) 283| | size_t find_first_of(StringRef Chars, size_t From = 0) const; 284| | 285| | /// Find the first character in the string that is not \p C or npos if not 286| | /// found. 287| | size_t find_first_not_of(char C, size_t From = 0) const; 288| | 289| | /// Find the first character in the string that is not in the string 290| | /// \p Chars, or npos if not found. 291| | /// 292| | /// Complexity: O(size() + Chars.size()) 293| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const; 294| | 295| | /// Find the last character in the string that is \p C, or npos if not 296| | /// found. 297| | size_t find_last_of(char C, size_t From = npos) const { 298| | return rfind(C, From); 299| | } 300| | 301| | /// Find the last character in the string that is in \p C, or npos if not 302| | /// found. 303| | /// 304| | /// Complexity: O(size() + Chars.size()) 305| | size_t find_last_of(StringRef Chars, size_t From = npos) const; 306| | 307| | /// Find the last character in the string that is not \p C, or npos if not 308| | /// found. 309| | size_t find_last_not_of(char C, size_t From = npos) const; 310| | 311| | /// Find the last character in the string that is not in \p Chars, or 312| | /// npos if not found. 313| | /// 314| | /// Complexity: O(size() + Chars.size()) 315| | size_t find_last_not_of(StringRef Chars, size_t From = npos) const; 316| | 317| | /// @} 318| | /// @name Helpful Algorithms 319| | /// @{ 320| | 321| | /// Return the number of occurrences of \p C in the string. 322| 0| size_t count(char C) const { 323| 0| size_t Count = 0; 324| 0| for (size_t i = 0, e = Length; i != e; ++i) 325| 0| if (Data[i] == C) 326| 0| ++Count; 327| 0| return Count; 328| 0| } 329| | 330| | /// Return the number of non-overlapped occurrences of \p Str in 331| | /// the string. 332| | size_t count(StringRef Str) const; 333| | 334| | /// Parse the current string as an integer of the specified radix. If 335| | /// \p Radix is specified as zero, this does radix autosensing using 336| | /// extended C rules: 0 is octal, 0x is hex, 0b is binary. 337| | /// 338| | /// If the string is invalid or if only a subset of the string is valid, 339| | /// this returns true to signify the error. The string is considered 340| | /// erroneous if empty or if it overflows T. 341| | template 342| | typename std::enable_if::is_signed, bool>::type 343| 0| getAsInteger(unsigned Radix, T &Result) const { 344| 0| long long LLVal; 345| 0| if (getAsSignedInteger(*this, Radix, LLVal) || 346| 0| static_cast(LLVal) != LLVal) 347| 0| return true; 348| 0| Result = LLVal; 349| 0| return false; 350| 0| } 351| | 352| | template 353| | typename std::enable_if::is_signed, bool>::type 354| 0| getAsInteger(unsigned Radix, T &Result) const { 355| 0| unsigned long long ULLVal; 356| 0| // The additional cast to unsigned long long is required to avoid the 357| 0| // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type 358| 0| // 'unsigned __int64' when instantiating getAsInteger with T = bool. 359| 0| if (getAsUnsignedInteger(*this, Radix, ULLVal) || 360| 0| static_cast(static_cast(ULLVal)) != ULLVal) 361| 0| return true; 362| 0| Result = ULLVal; 363| 0| return false; 364| 0| } 365| | 366| | /// @} 367| | /// @name String Operations 368| | /// @{ 369| | 370| | // Convert the given ASCII string to lowercase. 371| | std::string lower() const; 372| | 373| | /// Convert the given ASCII string to uppercase. 374| | std::string upper() const; 375| | 376| | /// @} 377| | /// @name Substring Operations 378| | /// @{ 379| | 380| | /// Return a reference to the substring from [Start, Start + N). 381| | /// 382| | /// \param Start The index of the starting character in the substring; if 383| | /// the index is npos or greater than the length of the string then the 384| | /// empty substring will be returned. 385| | /// 386| | /// \param N The number of characters to included in the substring. If N 387| | /// exceeds the number of characters remaining in the string, the string 388| | /// suffix (starting with \p Start) will be returned. 389| 0| StringRef substr(size_t Start, size_t N = npos) const { 390| 0| Start = std::min(Start, Length); 391| 0| return StringRef(Data + Start, std::min(N, Length - Start)); 392| 0| } 393| | 394| | /// Return a StringRef equal to 'this' but with the first \p N elements 395| | /// dropped. 396| | StringRef drop_front(size_t N = 1) const { 397| | assert(size() >= N && "Dropping more elements than exist"); 398| | return substr(N); 399| | } 400| | 401| | /// Return a StringRef equal to 'this' but with the last \p N elements 402| | /// dropped. 403| | StringRef drop_back(size_t N = 1) const { 404| | assert(size() >= N && "Dropping more elements than exist"); 405| | return substr(0, size()-N); 406| | } 407| | 408| | /// Return a reference to the substring from [Start, End). 409| | /// 410| | /// \param Start The index of the starting character in the substring; if 411| | /// the index is npos or greater than the length of the string then the 412| | /// empty substring will be returned. 413| | /// 414| | /// \param End The index following the last character to include in the 415| | /// substring. If this is npos, or less than \p Start, or exceeds the 416| | /// number of characters remaining in the string, the string suffix 417| | /// (starting with \p Start) will be returned. 418| | StringRef slice(size_t Start, size_t End) const { 419| | Start = std::min(Start, Length); 420| | End = std::min(std::max(Start, End), Length); 421| | return StringRef(Data + Start, End - Start); 422| | } 423| | 424| | /// Split into two substrings around the first occurrence of a separator 425| | /// character. 426| | /// 427| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 428| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 429| | /// maximal. If \p Separator is not in the string, then the result is a 430| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 431| | /// 432| | /// \param Separator The character to split on. 433| | /// \returns The split substrings. 434| | std::pair split(char Separator) const { 435| | size_t Idx = find(Separator); 436| | if (Idx == npos) 437| | return std::make_pair(*this, StringRef()); 438| | return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 439| | } 440| | 441| | /// Split into two substrings around the first occurrence of a separator 442| | /// string. 443| | /// 444| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 445| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 446| | /// maximal. If \p Separator is not in the string, then the result is a 447| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 448| | /// 449| | /// \param Separator - The string to split on. 450| | /// \return - The split substrings. 451| | std::pair split(StringRef Separator) const { 452| | size_t Idx = find(Separator); 453| | if (Idx == npos) 454| | return std::make_pair(*this, StringRef()); 455| | return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); 456| | } 457| | 458| | /// Split into substrings around the occurrences of a separator string. 459| | /// 460| | /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most 461| | /// \p MaxSplit splits are done and consequently <= \p MaxSplit 462| | /// elements are added to A. 463| | /// If \p KeepEmpty is false, empty strings are not added to \p A. They 464| | /// still count when considering \p MaxSplit 465| | /// An useful invariant is that 466| | /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true 467| | /// 468| | /// \param A - Where to put the substrings. 469| | /// \param Separator - The string to split on. 470| | /// \param MaxSplit - The maximum number of times the string is split. 471| | /// \param KeepEmpty - True if empty substring should be added. 472| | void split(SmallVectorImpl &A, 473| | StringRef Separator, int MaxSplit = -1, 474| | bool KeepEmpty = true) const; 475| | 476| | /// Split into two substrings around the last occurrence of a separator 477| | /// character. 478| | /// 479| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 480| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 481| | /// minimal. If \p Separator is not in the string, then the result is a 482| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 483| | /// 484| | /// \param Separator - The character to split on. 485| | /// \return - The split substrings. 486| 0| std::pair rsplit(char Separator) const { 487| 0| size_t Idx = rfind(Separator); 488| 0| if (Idx == npos) 489| 0| return std::make_pair(*this, StringRef()); 490| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 491| 0| } 492| | 493| | /// Return string with consecutive characters in \p Chars starting from 494| | /// the left removed. 495| | StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { 496| | return drop_front(std::min(Length, find_first_not_of(Chars))); 497| | } 498| | 499| | /// Return string with consecutive characters in \p Chars starting from 500| | /// the right removed. 501| | StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { 502| | return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); 503| | } 504| | 505| | /// Return string with consecutive characters in \p Chars starting from 506| | /// the left and right removed. 507| 0| StringRef trim(StringRef Chars = " \t\n\v\f\r") const { 508| 0| return ltrim(Chars).rtrim(Chars); 509| 0| } 510| | 511| | /// @} 512| | }; 513| | 514| | /// @name StringRef Comparison Operators 515| | /// @{ 516| | 517| 0| inline bool operator==(StringRef LHS, StringRef RHS) { 518| 0| return LHS.equals(RHS); 519| 0| } 520| | 521| 0| inline bool operator!=(StringRef LHS, StringRef RHS) { 522| 0| return !(LHS == RHS); 523| 0| } 524| | 525| | inline bool operator<(StringRef LHS, StringRef RHS) { 526| | return LHS.compare(RHS) == -1; 527| | } 528| | 529| 0| inline bool operator<=(StringRef LHS, StringRef RHS) { 530| 0| return LHS.compare(RHS) != 1; 531| 0| } 532| | 533| 0| inline bool operator>(StringRef LHS, StringRef RHS) { 534| 0| return LHS.compare(RHS) == 1; 535| 0| } 536| | 537| 0| inline bool operator>=(StringRef LHS, StringRef RHS) { 538| 0| return LHS.compare(RHS) != -1; 539| 0| } 540| | 541| | inline std::string &operator+=(std::string &buffer, StringRef string) { 542| | return buffer.append(string.data(), string.size()); 543| | } 544| | 545| | /// @} 546| | 547| | /// \brief Compute a hash_code for a StringRef. 548| | hash_code hash_value(StringRef S); 549| | 550| | // StringRefs can be treated like a POD type. 551| | template struct isPodLike; 552| | template <> struct isPodLike { static const bool value = true; }; 553| |} 554| | 555| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Twine.h: 1| |//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_TWINE_H 11| |#define LLVM_ADT_TWINE_H 12| | 13| |#include "llvm/ADT/StringRef.h" 14| |#include "llvm/Support/DataTypes.h" 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include 17| |#include 18| | 19| |namespace llvm { 20| | template 21| | class SmallVectorImpl; 22| | class StringRef; 23| | class raw_ostream; 24| | 25| | /// Twine - A lightweight data structure for efficiently representing the 26| | /// concatenation of temporary values as strings. 27| | /// 28| | /// A Twine is a kind of rope, it represents a concatenated string using a 29| | /// binary-tree, where the string is the preorder of the nodes. Since the 30| | /// Twine can be efficiently rendered into a buffer when its result is used, 31| | /// it avoids the cost of generating temporary values for intermediate string 32| | /// results -- particularly in cases when the Twine result is never 33| | /// required. By explicitly tracking the type of leaf nodes, we can also avoid 34| | /// the creation of temporary strings for conversions operations (such as 35| | /// appending an integer to a string). 36| | /// 37| | /// A Twine is not intended for use directly and should not be stored, its 38| | /// implementation relies on the ability to store pointers to temporary stack 39| | /// objects which may be deallocated at the end of a statement. Twines should 40| | /// only be used accepted as const references in arguments, when an API wishes 41| | /// to accept possibly-concatenated strings. 42| | /// 43| | /// Twines support a special 'null' value, which always concatenates to form 44| | /// itself, and renders as an empty string. This can be returned from APIs to 45| | /// effectively nullify any concatenations performed on the result. 46| | /// 47| | /// \b Implementation 48| | /// 49| | /// Given the nature of a Twine, it is not possible for the Twine's 50| | /// concatenation method to construct interior nodes; the result must be 51| | /// represented inside the returned value. For this reason a Twine object 52| | /// actually holds two values, the left- and right-hand sides of a 53| | /// concatenation. We also have nullary Twine objects, which are effectively 54| | /// sentinel values that represent empty strings. 55| | /// 56| | /// Thus, a Twine can effectively have zero, one, or two children. The \see 57| | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 58| | /// testing the number of children. 59| | /// 60| | /// We maintain a number of invariants on Twine objects (FIXME: Why): 61| | /// - Nullary twines are always represented with their Kind on the left-hand 62| | /// side, and the Empty kind on the right-hand side. 63| | /// - Unary twines are always represented with the value on the left-hand 64| | /// side, and the Empty kind on the right-hand side. 65| | /// - If a Twine has another Twine as a child, that child should always be 66| | /// binary (otherwise it could have been folded into the parent). 67| | /// 68| | /// These invariants are check by \see isValid(). 69| | /// 70| | /// \b Efficiency Considerations 71| | /// 72| | /// The Twine is designed to yield efficient and small code for common 73| | /// situations. For this reason, the concat() method is inlined so that 74| | /// concatenations of leaf nodes can be optimized into stores directly into a 75| | /// single stack allocated object. 76| | /// 77| | /// In practice, not all compilers can be trusted to optimize concat() fully, 78| | /// so we provide two additional methods (and accompanying operator+ 79| | /// overloads) to guarantee that particularly important cases (cstring plus 80| | /// StringRef) codegen as desired. 81| | class Twine { 82| | /// NodeKind - Represent the type of an argument. 83| | enum NodeKind : unsigned char { 84| | /// An empty string; the result of concatenating anything with it is also 85| | /// empty. 86| | NullKind, 87| | 88| | /// The empty string. 89| | EmptyKind, 90| | 91| | /// A pointer to a Twine instance. 92| | TwineKind, 93| | 94| | /// A pointer to a C string instance. 95| | CStringKind, 96| | 97| | /// A pointer to an std::string instance. 98| | StdStringKind, 99| | 100| | /// A pointer to a StringRef instance. 101| | StringRefKind, 102| | 103| | /// A char value reinterpreted as a pointer, to render as a character. 104| | CharKind, 105| | 106| | /// An unsigned int value reinterpreted as a pointer, to render as an 107| | /// unsigned decimal integer. 108| | DecUIKind, 109| | 110| | /// An int value reinterpreted as a pointer, to render as a signed 111| | /// decimal integer. 112| | DecIKind, 113| | 114| | /// A pointer to an unsigned long value, to render as an unsigned decimal 115| | /// integer. 116| | DecULKind, 117| | 118| | /// A pointer to a long value, to render as a signed decimal integer. 119| | DecLKind, 120| | 121| | /// A pointer to an unsigned long long value, to render as an unsigned 122| | /// decimal integer. 123| | DecULLKind, 124| | 125| | /// A pointer to a long long value, to render as a signed decimal integer. 126| | DecLLKind, 127| | 128| | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 129| | /// integer. 130| | UHexKind 131| | }; 132| | 133| | union Child 134| | { 135| | const Twine *twine; 136| | const char *cString; 137| | const std::string *stdString; 138| | const StringRef *stringRef; 139| | char character; 140| | unsigned int decUI; 141| | int decI; 142| | const unsigned long *decUL; 143| | const long *decL; 144| | const unsigned long long *decULL; 145| | const long long *decLL; 146| | const uint64_t *uHex; 147| | }; 148| | 149| | private: 150| | /// LHS - The prefix in the concatenation, which may be uninitialized for 151| | /// Null or Empty kinds. 152| | Child LHS; 153| | /// RHS - The suffix in the concatenation, which may be uninitialized for 154| | /// Null or Empty kinds. 155| | Child RHS; 156| | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 157| | NodeKind LHSKind; 158| | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). 159| | NodeKind RHSKind; 160| | 161| | private: 162| | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 163| | explicit Twine(NodeKind Kind) 164| 0| : LHSKind(Kind), RHSKind(EmptyKind) { 165| 0| assert(isNullary() && "Invalid kind!"); 166| 0| } 167| | 168| | /// Construct a binary twine. 169| | explicit Twine(const Twine &LHS, const Twine &RHS) 170| 0| : LHSKind(TwineKind), RHSKind(TwineKind) { 171| 0| this->LHS.twine = &LHS; 172| 0| this->RHS.twine = &RHS; 173| 0| assert(isValid() && "Invalid twine!"); 174| 0| } 175| | 176| | /// Construct a twine from explicit values. 177| | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) 178| 0| : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { 179| 0| assert(isValid() && "Invalid twine!"); 180| 0| } 181| | 182| | /// Since the intended use of twines is as temporary objects, assignments 183| | /// when concatenating might cause undefined behavior or stack corruptions 184| | Twine &operator=(const Twine &Other) = delete; 185| | 186| | /// isNull - Check for the null twine. 187| 0| bool isNull() const { 188| 0| return getLHSKind() == NullKind; 189| 0| } 190| | 191| | /// isEmpty - Check for the empty twine. 192| 0| bool isEmpty() const { 193| 0| return getLHSKind() == EmptyKind; 194| 0| } 195| | 196| | /// isNullary - Check if this is a nullary twine (null or empty). 197| 0| bool isNullary() const { 198| 0| return isNull() || isEmpty(); 199| 0| } 200| | 201| | /// isUnary - Check if this is a unary twine. 202| 0| bool isUnary() const { 203| 0| return getRHSKind() == EmptyKind && !isNullary(); 204| 0| } 205| | 206| | /// isBinary - Check if this is a binary twine. 207| 0| bool isBinary() const { 208| 0| return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 209| 0| } 210| | 211| | /// isValid - Check if this is a valid twine (satisfying the invariants on 212| | /// order and number of arguments). 213| 0| bool isValid() const { 214| 0| // Nullary twines always have Empty on the RHS. 215| 0| if (isNullary() && getRHSKind() != EmptyKind) 216| 0| return false; 217| 0| 218| 0| // Null should never appear on the RHS. 219| 0| if (getRHSKind() == NullKind) 220| 0| return false; 221| 0| 222| 0| // The RHS cannot be non-empty if the LHS is empty. 223| 0| if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 224| 0| return false; 225| 0| 226| 0| // A twine child should always be binary. 227| 0| if (getLHSKind() == TwineKind && 228| 0| !LHS.twine->isBinary()) 229| 0| return false; 230| 0| if (getRHSKind() == TwineKind && 231| 0| !RHS.twine->isBinary()) 232| 0| return false; 233| 0| 234| 0| return true; 235| 0| } 236| | 237| | /// getLHSKind - Get the NodeKind of the left-hand side. 238| 0| NodeKind getLHSKind() const { return LHSKind; } 239| | 240| | /// getRHSKind - Get the NodeKind of the right-hand side. 241| 0| NodeKind getRHSKind() const { return RHSKind; } 242| | 243| | /// printOneChild - Print one child from a twine. 244| | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; 245| | 246| | /// printOneChildRepr - Print the representation of one child from a twine. 247| | void printOneChildRepr(raw_ostream &OS, Child Ptr, 248| | NodeKind Kind) const; 249| | 250| | public: 251| | /// @name Constructors 252| | /// @{ 253| | 254| | /// Construct from an empty string. 255| 0| /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 256| 0| assert(isValid() && "Invalid twine!"); 257| 0| } 258| | 259| | Twine(const Twine &) = default; 260| | 261| | /// Construct from a C string. 262| | /// 263| | /// We take care here to optimize "" into the empty twine -- this will be 264| | /// optimized out for string constants. This allows Twine arguments have 265| | /// default "" values, without introducing unnecessary string constants. 266| | /*implicit*/ Twine(const char *Str) 267| 0| : RHSKind(EmptyKind) { 268| 0| if (Str[0] != '\0') { 269| 0| LHS.cString = Str; 270| 0| LHSKind = CStringKind; 271| 0| } else 272| 0| LHSKind = EmptyKind; 273| 0| 274| 0| assert(isValid() && "Invalid twine!"); 275| 0| } 276| | 277| | /// Construct from an std::string. 278| | /*implicit*/ Twine(const std::string &Str) 279| 0| : LHSKind(StdStringKind), RHSKind(EmptyKind) { 280| 0| LHS.stdString = &Str; 281| 0| assert(isValid() && "Invalid twine!"); 282| 0| } 283| | 284| | /// Construct from a StringRef. 285| | /*implicit*/ Twine(const StringRef &Str) 286| 0| : LHSKind(StringRefKind), RHSKind(EmptyKind) { 287| 0| LHS.stringRef = &Str; 288| 0| assert(isValid() && "Invalid twine!"); 289| 0| } 290| | 291| | /// Construct from a char. 292| | explicit Twine(char Val) 293| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 294| 0| LHS.character = Val; 295| 0| } 296| | 297| | /// Construct from a signed char. 298| | explicit Twine(signed char Val) 299| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 300| 0| LHS.character = static_cast(Val); 301| 0| } 302| | 303| | /// Construct from an unsigned char. 304| | explicit Twine(unsigned char Val) 305| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 306| 0| LHS.character = static_cast(Val); 307| 0| } 308| | 309| | /// Construct a twine to print \p Val as an unsigned decimal integer. 310| | explicit Twine(unsigned Val) 311| 0| : LHSKind(DecUIKind), RHSKind(EmptyKind) { 312| 0| LHS.decUI = Val; 313| 0| } 314| | 315| | /// Construct a twine to print \p Val as a signed decimal integer. 316| | explicit Twine(int Val) 317| 0| : LHSKind(DecIKind), RHSKind(EmptyKind) { 318| 0| LHS.decI = Val; 319| 0| } 320| | 321| | /// Construct a twine to print \p Val as an unsigned decimal integer. 322| | explicit Twine(const unsigned long &Val) 323| 0| : LHSKind(DecULKind), RHSKind(EmptyKind) { 324| 0| LHS.decUL = &Val; 325| 0| } 326| | 327| | /// Construct a twine to print \p Val as a signed decimal integer. 328| | explicit Twine(const long &Val) 329| 0| : LHSKind(DecLKind), RHSKind(EmptyKind) { 330| 0| LHS.decL = &Val; 331| 0| } 332| | 333| | /// Construct a twine to print \p Val as an unsigned decimal integer. 334| | explicit Twine(const unsigned long long &Val) 335| 0| : LHSKind(DecULLKind), RHSKind(EmptyKind) { 336| 0| LHS.decULL = &Val; 337| 0| } 338| | 339| | /// Construct a twine to print \p Val as a signed decimal integer. 340| | explicit Twine(const long long &Val) 341| 0| : LHSKind(DecLLKind), RHSKind(EmptyKind) { 342| 0| LHS.decLL = &Val; 343| 0| } 344| | 345| | // FIXME: Unfortunately, to make sure this is as efficient as possible we 346| | // need extra binary constructors from particular types. We can't rely on 347| | // the compiler to be smart enough to fold operator+()/concat() down to the 348| | // right thing. Yet. 349| | 350| | /// Construct as the concatenation of a C string and a StringRef. 351| | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) 352| 0| : LHSKind(CStringKind), RHSKind(StringRefKind) { 353| 0| this->LHS.cString = LHS; 354| 0| this->RHS.stringRef = &RHS; 355| 0| assert(isValid() && "Invalid twine!"); 356| 0| } 357| | 358| | /// Construct as the concatenation of a StringRef and a C string. 359| | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) 360| 0| : LHSKind(StringRefKind), RHSKind(CStringKind) { 361| 0| this->LHS.stringRef = &LHS; 362| 0| this->RHS.cString = RHS; 363| 0| assert(isValid() && "Invalid twine!"); 364| 0| } 365| | 366| | /// Create a 'null' string, which is an empty string that always 367| | /// concatenates to form another empty string. 368| 0| static Twine createNull() { 369| 0| return Twine(NullKind); 370| 0| } 371| | 372| | /// @} 373| | /// @name Numeric Conversions 374| | /// @{ 375| | 376| | // Construct a twine to print \p Val as an unsigned hexadecimal integer. 377| | static Twine utohexstr(const uint64_t &Val) { 378| | Child LHS, RHS; 379| | LHS.uHex = &Val; 380| | RHS.twine = nullptr; 381| | return Twine(LHS, UHexKind, RHS, EmptyKind); 382| | } 383| | 384| | /// @} 385| | /// @name Predicate Operations 386| | /// @{ 387| | 388| | /// isTriviallyEmpty - Check if this twine is trivially empty; a false 389| | /// return value does not necessarily mean the twine is empty. 390| | bool isTriviallyEmpty() const { 391| | return isNullary(); 392| | } 393| | 394| | /// isSingleStringRef - Return true if this twine can be dynamically 395| | /// accessed as a single StringRef value with getSingleStringRef(). 396| | bool isSingleStringRef() const { 397| | if (getRHSKind() != EmptyKind) return false; 398| | 399| | switch (getLHSKind()) { 400| | case EmptyKind: 401| | case CStringKind: 402| | case StdStringKind: 403| | case StringRefKind: 404| | return true; 405| | default: 406| | return false; 407| | } 408| | } 409| | 410| | /// @} 411| | /// @name String Operations 412| | /// @{ 413| | 414| | Twine concat(const Twine &Suffix) const; 415| | 416| | /// @} 417| | /// @name Output & Conversion. 418| | /// @{ 419| | 420| | /// str - Return the twine contents as a std::string. 421| | std::string str() const; 422| | 423| | /// toVector - Write the concatenated string into the given SmallString or 424| | /// SmallVector. 425| | void toVector(SmallVectorImpl &Out) const; 426| | 427| | /// getSingleStringRef - This returns the twine as a single StringRef. This 428| | /// method is only valid if isSingleStringRef() is true. 429| | StringRef getSingleStringRef() const { 430| | assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); 431| | switch (getLHSKind()) { 432| | default: llvm_unreachable("Out of sync with isSingleStringRef"); 433| | case EmptyKind: return StringRef(); 434| | case CStringKind: return StringRef(LHS.cString); 435| | case StdStringKind: return StringRef(*LHS.stdString); 436| | case StringRefKind: return *LHS.stringRef; 437| | } 438| | } 439| | 440| | /// toStringRef - This returns the twine as a single StringRef if it can be 441| | /// represented as such. Otherwise the twine is written into the given 442| | /// SmallVector and a StringRef to the SmallVector's data is returned. 443| | StringRef toStringRef(SmallVectorImpl &Out) const; 444| | 445| | /// toNullTerminatedStringRef - This returns the twine as a single null 446| | /// terminated StringRef if it can be represented as such. Otherwise the 447| | /// twine is written into the given SmallVector and a StringRef to the 448| | /// SmallVector's data is returned. 449| | /// 450| | /// The returned StringRef's size does not include the null terminator. 451| | StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; 452| | 453| | /// Write the concatenated string represented by this twine to the 454| | /// stream \p OS. 455| | void print(raw_ostream &OS) const; 456| | 457| | /// Dump the concatenated string represented by this twine to stderr. 458| | void dump() const; 459| | 460| | /// Write the representation of this twine to the stream \p OS. 461| | void printRepr(raw_ostream &OS) const; 462| | 463| | /// Dump the representation of this twine to stderr. 464| | void dumpRepr() const; 465| | 466| | /// @} 467| | }; 468| | 469| | /// @name Twine Inline Implementations 470| | /// @{ 471| | 472| 0| inline Twine Twine::concat(const Twine &Suffix) const { 473| 0| // Concatenation with null is null. 474| 0| if (isNull() || Suffix.isNull()) 475| 0| return Twine(NullKind); 476| 0| 477| 0| // Concatenation with empty yields the other side. 478| 0| if (isEmpty()) 479| 0| return Suffix; 480| 0| if (Suffix.isEmpty()) 481| 0| return *this; 482| 0| 483| 0| // Otherwise we need to create a new node, taking care to fold in unary 484| 0| // twines. 485| 0| Child NewLHS, NewRHS; 486| 0| NewLHS.twine = this; 487| 0| NewRHS.twine = &Suffix; 488| 0| NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 489| 0| if (isUnary()) { 490| 0| NewLHS = LHS; 491| 0| NewLHSKind = getLHSKind(); 492| 0| } 493| 0| if (Suffix.isUnary()) { 494| 0| NewRHS = Suffix.LHS; 495| 0| NewRHSKind = Suffix.getLHSKind(); 496| 0| } 497| 0| 498| 0| return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 499| 0| } 500| | 501| 0| inline Twine operator+(const Twine &LHS, const Twine &RHS) { 502| 0| return LHS.concat(RHS); 503| 0| } 504| | 505| | /// Additional overload to guarantee simplified codegen; this is equivalent to 506| | /// concat(). 507| | 508| 0| inline Twine operator+(const char *LHS, const StringRef &RHS) { 509| 0| return Twine(LHS, RHS); 510| 0| } 511| | 512| | /// Additional overload to guarantee simplified codegen; this is equivalent to 513| | /// concat(). 514| | 515| 0| inline Twine operator+(const StringRef &LHS, const char *RHS) { 516| 0| return Twine(LHS, RHS); 517| 0| } 518| | 519| | inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 520| | RHS.print(OS); 521| | return OS; 522| | } 523| | 524| | /// @} 525| |} 526| | 527| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/AlignOf.h: 1| |//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the AlignOf function that computes alignments for 11| |// arbitrary types. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ALIGNOF_H 16| |#define LLVM_SUPPORT_ALIGNOF_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include 20| | 21| |namespace llvm { 22| |template 23| |struct AlignmentCalcImpl { 24| | char x; 25| | T t; 26| |private: 27| | AlignmentCalcImpl() {} // Never instantiate. 28| |}; 29| | 30| |/// AlignOf - A templated class that contains an enum value representing 31| |/// the alignment of the template argument. For example, 32| |/// AlignOf::Alignment represents the alignment of type "int". The 33| |/// alignment calculated is the minimum alignment, and not necessarily 34| |/// the "desired" alignment returned by GCC's __alignof__ (for example). Note 35| |/// that because the alignment is an enum value, it can be used as a 36| |/// compile-time constant (e.g., for template instantiation). 37| |template 38| |struct AlignOf { 39| | enum { Alignment = 40| | static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; 41| | 42| | enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; 43| | enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; 44| | enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; 45| | enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; 46| | 47| | enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; 48| | enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; 49| | enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; 50| | enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; 51| |}; 52| | 53| |/// alignOf - A templated function that returns the minimum alignment of 54| |/// of a type. This provides no extra functionality beyond the AlignOf 55| |/// class besides some cosmetic cleanliness. Example usage: 56| |/// alignOf() returns the alignment of an int. 57| |template 58| 0|inline unsigned alignOf() { return AlignOf::Alignment; } ------------------ | Unexecuted instantiation: _ZN4llvm7alignOfINS_14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4NodeENS2_14default_deleteIS6_EEEEEEEEjv ------------------ | Unexecuted instantiation: _ZN4llvm7alignOfINS_14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem6TargetENS2_14default_deleteIS6_EEEEEEEEjv ------------------ | Unexecuted instantiation: _ZN4llvm7alignOfINS_14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem7CommandENS2_14default_deleteIS6_EEEEEEEEjv ------------------ | Unexecuted instantiation: _ZN4llvm7alignOfINS_14StringMapEntryINSt3__110unique_ptrIN7llbuild11buildsystem4ToolENS2_14default_deleteIS6_EEEEEEEEjv ------------------ | Unexecuted instantiation: _ZN4llvm7alignOfINS_14StringMapEntryIbEEEEjv ------------------ 59| | 60| |/// \struct AlignedCharArray 61| |/// \brief Helper for building an aligned character array type. 62| |/// 63| |/// This template is used to explicitly build up a collection of aligned 64| |/// character array types. We have to build these up using a macro and explicit 65| |/// specialization to cope with old versions of MSVC and GCC where only an 66| |/// integer literal can be used to specify an alignment constraint. Once built 67| |/// up here, we can then begin to indirect between these using normal C++ 68| |/// template parameters. 69| | 70| |// MSVC requires special handling here. 71| |#ifndef _MSC_VER 72| | 73| |#if __has_feature(cxx_alignas) 74| |template 75| |struct AlignedCharArray { 76| | alignas(Alignment) char buffer[Size]; 77| |}; 78| | 79| |#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) 80| |/// \brief Create a type with an aligned char buffer. 81| |template 82| |struct AlignedCharArray; 83| | 84| |#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 85| | template \ 86| | struct AlignedCharArray { \ 87| | __attribute__((aligned(x))) char buffer[Size]; \ 88| | }; 89| | 90| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) 91| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) 92| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) 93| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) 94| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 95| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 96| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 97| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 98| | 99| |#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 100| | 101| |#else 102| |# error No supported align as directive. 103| |#endif 104| | 105| |#else // _MSC_VER 106| | 107| |/// \brief Create a type with an aligned char buffer. 108| |template 109| |struct AlignedCharArray; 110| | 111| |// We provide special variations of this template for the most common 112| |// alignments because __declspec(align(...)) doesn't actually work when it is 113| |// a member of a by-value function argument in MSVC, even if the alignment 114| |// request is something reasonably like 8-byte or 16-byte. Note that we can't 115| |// even include the declspec with the union that forces the alignment because 116| |// MSVC warns on the existence of the declspec despite the union member forcing 117| |// proper alignment. 118| | 119| |template 120| |struct AlignedCharArray<1, Size> { 121| | union { 122| | char aligned; 123| | char buffer[Size]; 124| | }; 125| |}; 126| | 127| |template 128| |struct AlignedCharArray<2, Size> { 129| | union { 130| | short aligned; 131| | char buffer[Size]; 132| | }; 133| |}; 134| | 135| |template 136| |struct AlignedCharArray<4, Size> { 137| | union { 138| | int aligned; 139| | char buffer[Size]; 140| | }; 141| |}; 142| | 143| |template 144| |struct AlignedCharArray<8, Size> { 145| | union { 146| | double aligned; 147| | char buffer[Size]; 148| | }; 149| |}; 150| | 151| | 152| |// The rest of these are provided with a __declspec(align(...)) and we simply 153| |// can't pass them by-value as function arguments on MSVC. 154| | 155| |#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 156| | template \ 157| | struct AlignedCharArray { \ 158| | __declspec(align(x)) char buffer[Size]; \ 159| | }; 160| | 161| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 162| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 163| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 164| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 165| | 166| |#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 167| | 168| |#endif // _MSC_VER 169| | 170| |namespace detail { 171| |template 175| |class AlignerImpl { 176| | T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; 177| | 178| | AlignerImpl(); // Never defined or instantiated. 179| |}; 180| | 181| |template 185| |union SizerImpl { 186| | char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], 187| | arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], 188| | arr9[sizeof(T9)], arr10[sizeof(T10)]; 189| |}; 190| |} // end namespace detail 191| | 192| |/// \brief This union template exposes a suitably aligned and sized character 193| |/// array member which can hold elements of any of up to four types. 194| |/// 195| |/// These types may be arrays, structs, or any other types. The goal is to 196| |/// expose a char array buffer member which can be used as suitable storage for 197| |/// a placement new of any of these types. Support for more than seven types can 198| |/// be added at the cost of more boiler plate. 199| |template 203| |struct AlignedCharArrayUnion : llvm::AlignedCharArray< 204| | AlignOf >::Alignment, 206| | sizeof(detail::SizerImpl)> { 208| |}; 209| |} // end namespace llvm 210| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Allocator.h: 1| |//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// \file 10| |/// 11| |/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both 12| |/// of these conform to an LLVM "Allocator" concept which consists of an 13| |/// Allocate method accepting a size and alignment, and a Deallocate accepting 14| |/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of 15| |/// Allocate and Deallocate for setting size and alignment based on the final 16| |/// type. These overloads are typically provided by a base class template \c 17| |/// AllocatorBase. 18| |/// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_SUPPORT_ALLOCATOR_H 22| |#define LLVM_SUPPORT_ALLOCATOR_H 23| | 24| |#include "llvm/ADT/SmallVector.h" 25| |#include "llvm/Support/AlignOf.h" 26| |#include "llvm/Support/DataTypes.h" 27| |#include "llvm/Support/MathExtras.h" 28| |#include "llvm/Support/Memory.h" 29| |#include 30| |#include 31| |#include 32| |#include 33| | 34| |namespace llvm { 35| | 36| |/// \brief CRTP base class providing obvious overloads for the core \c 37| |/// Allocate() methods of LLVM-style allocators. 38| |/// 39| |/// This base class both documents the full public interface exposed by all 40| |/// LLVM-style allocators, and redirects all of the overloads to a single core 41| |/// set of methods which the derived class must define. 42| |template class AllocatorBase { 43| |public: 44| | /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method 45| | /// must be implemented by \c DerivedT. 46| | void *Allocate(size_t Size, size_t Alignment) { 47| |#ifdef __clang__ 48| | static_assert(static_cast( 49| | &AllocatorBase::Allocate) != 50| | static_cast( 51| | &DerivedT::Allocate), 52| | "Class derives from AllocatorBase without implementing the " 53| | "core Allocate(size_t, size_t) overload!"); 54| |#endif 55| | return static_cast(this)->Allocate(Size, Alignment); 56| | } 57| | 58| | /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this 59| | /// allocator. 60| | void Deallocate(const void *Ptr, size_t Size) { 61| |#ifdef __clang__ 62| | static_assert(static_cast( 63| | &AllocatorBase::Deallocate) != 64| | static_cast( 65| | &DerivedT::Deallocate), 66| | "Class derives from AllocatorBase without implementing the " 67| | "core Deallocate(void *) overload!"); 68| |#endif 69| | return static_cast(this)->Deallocate(Ptr, Size); 70| | } 71| | 72| | // The rest of these methods are helpers that redirect to one of the above 73| | // core methods. 74| | 75| | /// \brief Allocate space for a sequence of objects without constructing them. 76| | template T *Allocate(size_t Num = 1) { 77| | return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); 78| | } 79| | 80| | /// \brief Deallocate space for a sequence of objects without constructing them. 81| | template 82| | typename std::enable_if< 83| | !std::is_same::type, void>::value, void>::type 84| | Deallocate(T *Ptr, size_t Num = 1) { 85| | Deallocate(static_cast(Ptr), Num * sizeof(T)); 86| | } 87| |}; 88| | 89| |class MallocAllocator : public AllocatorBase { 90| |public: 91| 0| void Reset() {} 92| | 93| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, 94| 0| size_t /*Alignment*/) { 95| 0| return malloc(Size); 96| 0| } 97| | 98| | // Pull in base class overloads. 99| | using AllocatorBase::Allocate; 100| | 101| 0| void Deallocate(const void *Ptr, size_t /*Size*/) { 102| 0| free(const_cast(Ptr)); 103| 0| } 104| | 105| | // Pull in base class overloads. 106| | using AllocatorBase::Deallocate; 107| | 108| 0| void PrintStats() const {} 109| |}; 110| | 111| |namespace detail { 112| | 113| |// We call out to an external function to actually print the message as the 114| |// printing code uses Allocator.h in its implementation. 115| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 116| | size_t TotalMemory); 117| |} // End namespace detail. 118| | 119| |/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. 120| |/// 121| |/// This isn't strictly a bump-pointer allocator as it uses backing slabs of 122| |/// memory rather than relying on a boundless contiguous heap. However, it has 123| |/// bump-pointer semantics in that it is a monotonically growing pool of memory 124| |/// where every allocation is found by merely allocating the next N bytes in 125| |/// the slab, or the next N bytes in the next slab. 126| |/// 127| |/// Note that this also has a threshold for forcing allocations above a certain 128| |/// size into their own slab. 129| |/// 130| |/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator 131| |/// object, which wraps malloc, to allocate memory, but it can be changed to 132| |/// use a custom allocator. 133| |template 135| |class BumpPtrAllocatorImpl 136| | : public AllocatorBase< 137| | BumpPtrAllocatorImpl> { 138| |public: 139| | static_assert(SizeThreshold <= SlabSize, 140| | "The SizeThreshold must be at most the SlabSize to ensure " 141| | "that objects larger than a slab go into their own memory " 142| | "allocation."); 143| | 144| | BumpPtrAllocatorImpl() 145| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} 146| | template 147| | BumpPtrAllocatorImpl(T &&Allocator) 148| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), 149| | Allocator(std::forward(Allocator)) {} 150| | 151| | // Manually implement a move constructor as we must clear the old allocators 152| | // slabs as a matter of correctness. 153| | BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) 154| | : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), 155| | CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), 156| | BytesAllocated(Old.BytesAllocated), 157| | Allocator(std::move(Old.Allocator)) { 158| | Old.CurPtr = Old.End = nullptr; 159| | Old.BytesAllocated = 0; 160| | Old.Slabs.clear(); 161| | Old.CustomSizedSlabs.clear(); 162| | } 163| | 164| 0| ~BumpPtrAllocatorImpl() { 165| 0| DeallocateSlabs(Slabs.begin(), Slabs.end()); 166| 0| DeallocateCustomSizedSlabs(); 167| 0| } 168| | 169| | BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { 170| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 171| | DeallocateCustomSizedSlabs(); 172| | 173| | CurPtr = RHS.CurPtr; 174| | End = RHS.End; 175| | BytesAllocated = RHS.BytesAllocated; 176| | Slabs = std::move(RHS.Slabs); 177| | CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); 178| | Allocator = std::move(RHS.Allocator); 179| | 180| | RHS.CurPtr = RHS.End = nullptr; 181| | RHS.BytesAllocated = 0; 182| | RHS.Slabs.clear(); 183| | RHS.CustomSizedSlabs.clear(); 184| | return *this; 185| | } 186| | 187| | /// \brief Deallocate all but the current slab and reset the current pointer 188| | /// to the beginning of it, freeing all memory allocated so far. 189| | void Reset() { 190| | if (Slabs.empty()) 191| | return; 192| | 193| | // Reset the state. 194| | BytesAllocated = 0; 195| | CurPtr = (char *)Slabs.front(); 196| | End = CurPtr + SlabSize; 197| | 198| | // Deallocate all but the first slab, and all custome sized slabs. 199| | DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); 200| | Slabs.erase(std::next(Slabs.begin()), Slabs.end()); 201| | DeallocateCustomSizedSlabs(); 202| | CustomSizedSlabs.clear(); 203| | } 204| | 205| | /// \brief Allocate space at the specified alignment. 206| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { 207| | assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); 208| | 209| | // Keep track of how many bytes we've allocated. 210| | BytesAllocated += Size; 211| | 212| | size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); 213| | assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); 214| | 215| | // Check if we have enough space. 216| | if (Adjustment + Size <= size_t(End - CurPtr)) { 217| | char *AlignedPtr = CurPtr + Adjustment; 218| | CurPtr = AlignedPtr + Size; 219| | // Update the allocation point of this memory block in MemorySanitizer. 220| | // Without this, MemorySanitizer messages for values originated from here 221| | // will point to the allocation of the entire slab. 222| | __msan_allocated_memory(AlignedPtr, Size); 223| | return AlignedPtr; 224| | } 225| | 226| | // If Size is really big, allocate a separate slab for it. 227| | size_t PaddedSize = Size + Alignment - 1; 228| | if (PaddedSize > SizeThreshold) { 229| | void *NewSlab = Allocator.Allocate(PaddedSize, 0); 230| | CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); 231| | 232| | uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); 233| | assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); 234| | char *AlignedPtr = (char*)AlignedAddr; 235| | __msan_allocated_memory(AlignedPtr, Size); 236| | return AlignedPtr; 237| | } 238| | 239| | // Otherwise, start a new slab and try again. 240| | StartNewSlab(); 241| | uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); 242| | assert(AlignedAddr + Size <= (uintptr_t)End && 243| | "Unable to allocate memory!"); 244| | char *AlignedPtr = (char*)AlignedAddr; 245| | CurPtr = AlignedPtr + Size; 246| | __msan_allocated_memory(AlignedPtr, Size); 247| | return AlignedPtr; 248| | } 249| | 250| | // Pull in base class overloads. 251| | using AllocatorBase::Allocate; 252| | 253| 0| void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} 254| | 255| | // Pull in base class overloads. 256| | using AllocatorBase::Deallocate; 257| | 258| | size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } 259| | 260| | size_t getTotalMemory() const { 261| | size_t TotalMemory = 0; 262| | for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) 263| | TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); 264| | for (auto &PtrAndSize : CustomSizedSlabs) 265| | TotalMemory += PtrAndSize.second; 266| | return TotalMemory; 267| | } 268| | 269| | void PrintStats() const { 270| | detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, 271| | getTotalMemory()); 272| | } 273| | 274| |private: 275| | /// \brief The current pointer into the current slab. 276| | /// 277| | /// This points to the next free byte in the slab. 278| | char *CurPtr; 279| | 280| | /// \brief The end of the current slab. 281| | char *End; 282| | 283| | /// \brief The slabs allocated so far. 284| | SmallVector Slabs; 285| | 286| | /// \brief Custom-sized slabs allocated for too-large allocation requests. 287| | SmallVector, 0> CustomSizedSlabs; 288| | 289| | /// \brief How many bytes we've allocated. 290| | /// 291| | /// Used so that we can compute how much space was wasted. 292| | size_t BytesAllocated; 293| | 294| | /// \brief The allocator instance we use to get slabs of memory. 295| | AllocatorT Allocator; 296| | 297| 0| static size_t computeSlabSize(unsigned SlabIdx) { 298| 0| // Scale the actual allocated slab size based on the number of slabs 299| 0| // allocated. Every 128 slabs allocated, we double the allocated size to 300| 0| // reduce allocation frequency, but saturate at multiplying the slab size by 301| 0| // 2^30. 302| 0| return SlabSize * ((size_t)1 << std::min(30, SlabIdx / 128)); 303| 0| } 304| | 305| | /// \brief Allocate a new slab and move the bump pointers over into the new 306| | /// slab, modifying CurPtr and End. 307| 0| void StartNewSlab() { 308| 0| size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); 309| 0| 310| 0| void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); 311| 0| Slabs.push_back(NewSlab); 312| 0| CurPtr = (char *)(NewSlab); 313| 0| End = ((char *)NewSlab) + AllocatedSlabSize; 314| 0| } 315| | 316| | /// \brief Deallocate a sequence of slabs. 317| | void DeallocateSlabs(SmallVectorImpl::iterator I, 318| 0| SmallVectorImpl::iterator E) { 319| 0| for (; I != E; ++I) { 320| 0| size_t AllocatedSlabSize = 321| 0| computeSlabSize(std::distance(Slabs.begin(), I)); 322| 0|#ifndef NDEBUG 323| 0| // Poison the memory so stale pointers crash sooner. Note we must 324| 0| // preserve the Size and NextPtr fields at the beginning. 325| 0| if (AllocatedSlabSize != 0) { 326| 0| sys::Memory::setRangeWritable(*I, AllocatedSlabSize); 327| 0| memset(*I, 0xCD, AllocatedSlabSize); 328| 0| } 329| 0|#endif 330| 0| Allocator.Deallocate(*I, AllocatedSlabSize); 331| 0| } 332| 0| } 333| | 334| | /// \brief Deallocate all memory for custom sized slabs. 335| 0| void DeallocateCustomSizedSlabs() { 336| 0| for (auto &PtrAndSize : CustomSizedSlabs) { 337| 0| void *Ptr = PtrAndSize.first; 338| 0| size_t Size = PtrAndSize.second; 339| 0|#ifndef NDEBUG 340| 0| // Poison the memory so stale pointers crash sooner. Note we must 341| 0| // preserve the Size and NextPtr fields at the beginning. 342| 0| sys::Memory::setRangeWritable(Ptr, Size); 343| 0| memset(Ptr, 0xCD, Size); 344| 0|#endif 345| 0| Allocator.Deallocate(Ptr, Size); 346| 0| } 347| 0| } 348| | 349| | template friend class SpecificBumpPtrAllocator; 350| |}; 351| | 352| |/// \brief The standard BumpPtrAllocator which just uses the default template 353| |/// paramaters. 354| |typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 355| | 356| |/// \brief A BumpPtrAllocator that allows only elements of a specific type to be 357| |/// allocated. 358| |/// 359| |/// This allows calling the destructor in DestroyAll() and when the allocator is 360| |/// destroyed. 361| |template class SpecificBumpPtrAllocator { 362| | BumpPtrAllocator Allocator; 363| | 364| |public: 365| | SpecificBumpPtrAllocator() : Allocator() {} 366| | SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) 367| | : Allocator(std::move(Old.Allocator)) {} 368| | ~SpecificBumpPtrAllocator() { DestroyAll(); } 369| | 370| | SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { 371| | Allocator = std::move(RHS.Allocator); 372| | return *this; 373| | } 374| | 375| | /// Call the destructor of each allocated object and deallocate all but the 376| | /// current slab and reset the current pointer to the beginning of it, freeing 377| | /// all memory allocated so far. 378| | void DestroyAll() { 379| | auto DestroyElements = [](char *Begin, char *End) { 380| | assert(Begin == (char*)alignAddr(Begin, alignOf())); 381| | for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) 382| | reinterpret_cast(Ptr)->~T(); 383| | }; 384| | 385| | for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; 386| | ++I) { 387| | size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( 388| | std::distance(Allocator.Slabs.begin(), I)); 389| | char *Begin = (char*)alignAddr(*I, alignOf()); 390| | char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr 391| | : (char *)*I + AllocatedSlabSize; 392| | 393| | DestroyElements(Begin, End); 394| | } 395| | 396| | for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { 397| | void *Ptr = PtrAndSize.first; 398| | size_t Size = PtrAndSize.second; 399| | DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); 400| | } 401| | 402| | Allocator.Reset(); 403| | } 404| | 405| | /// \brief Allocate space for an array of objects without constructing them. 406| | T *Allocate(size_t num = 1) { return Allocator.Allocate(num); } 407| |}; 408| | 409| |} // end namespace llvm 410| | 411| |template 412| |void *operator new(size_t Size, 413| | llvm::BumpPtrAllocatorImpl &Allocator) { 415| | struct S { 416| | char c; 417| | union { 418| | double D; 419| | long double LD; 420| | long long L; 421| | void *P; 422| | } x; 423| | }; 424| | return Allocator.Allocate( 425| | Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); 426| |} 427| | 428| |template 429| |void operator delete( 430| | void *, llvm::BumpPtrAllocatorImpl &) { 431| |} 432| | 433| |#endif // LLVM_SUPPORT_ALLOCATOR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/CBindingWrapping.h: 1| |//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the wrapping macros for the C interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H 15| |#define LLVM_SUPPORT_CBINDINGWRAPPING_H 16| | 17| |#include "llvm/Support/Casting.h" 18| | 19| |#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 20| 0| inline ty *unwrap(ref P) { \ 21| 0| return reinterpret_cast(P); \ 22| 0| } \ 23| | \ 24| 0| inline ref wrap(const ty *P) { \ 25| 0| return reinterpret_cast(const_cast(P)); \ 26| 0| } 27| | 28| |#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ 29| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 30| | \ 31| | template \ 32| | inline T *unwrap(ref P) { \ 33| | return cast(unwrap(P)); \ 34| | } 35| | 36| |#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ 37| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 38| | \ 39| | template \ 40| | inline T *unwrap(ref P) { \ 41| | T *Q = (T*)unwrap(P); \ 42| | assert(Q && "Invalid cast!"); \ 43| | return Q; \ 44| | } 45| | 46| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Casting.h: 1| |//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the isa(), cast(), dyn_cast(), cast_or_null(), 11| |// and dyn_cast_or_null() templates. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_CASTING_H 16| |#define LLVM_SUPPORT_CASTING_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/type_traits.h" 20| |#include 21| | 22| |namespace llvm { 23| | 24| |//===----------------------------------------------------------------------===// 25| |// isa Support Templates 26| |//===----------------------------------------------------------------------===// 27| | 28| |// Define a template that can be specialized by smart pointers to reflect the 29| |// fact that they are automatically dereferenced, and are not involved with the 30| |// template selection process... the default implementation is a noop. 31| |// 32| |template struct simplify_type { 33| | typedef From SimpleType; // The real type this represents... 34| | 35| | // An accessor to get the real value... 36| 0| static SimpleType &getSimplifiedValue(From &Val) { return Val; } 37| |}; 38| | 39| |template struct simplify_type { 40| | typedef typename simplify_type::SimpleType NonConstSimpleType; 41| | typedef typename add_const_past_pointer::type 42| | SimpleType; 43| | typedef typename add_lvalue_reference_if_not_pointer::type 44| | RetType; 45| 0| static RetType getSimplifiedValue(const From& Val) { 46| 0| return simplify_type::getSimplifiedValue(const_cast(Val)); 47| 0| } 48| |}; 49| | 50| |// The core of the implementation of isa is here; To and From should be 51| |// the names of classes. This template can be specialized to customize the 52| |// implementation of isa<> without rewriting it from scratch. 53| |template 54| |struct isa_impl { 55| 0| static inline bool doit(const From &Val) { 56| 0| return To::classof(&Val); 57| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8isa_implINS_4yaml10ScalarNodeENS1_4NodeEvE4doitERKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm8isa_implINS_4yaml11MappingNodeENS1_4NodeEvE4doitERKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm8isa_implINS_4yaml12SequenceNodeENS1_4NodeEvE4doitERKS3_ ------------------ 58| |}; 59| | 60| |/// \brief Always allow upcasts, and perform no dynamic check for them. 61| |template 62| |struct isa_impl< 63| | To, From, typename std::enable_if::value>::type> { 64| | static inline bool doit(const From &) { return true; } 65| |}; 66| | 67| |template struct isa_impl_cl { 68| | static inline bool doit(const From &Val) { 69| | return isa_impl::doit(Val); 70| | } 71| |}; 72| | 73| |template struct isa_impl_cl { 74| | static inline bool doit(const From &Val) { 75| | return isa_impl::doit(Val); 76| | } 77| |}; 78| | 79| |template struct isa_impl_cl { 80| | static inline bool doit(const From *Val) { 81| | assert(Val && "isa<> used on a null pointer"); 82| | return isa_impl::doit(*Val); 83| | } 84| |}; 85| | 86| |template struct isa_impl_cl { 87| | static inline bool doit(const From *Val) { 88| | assert(Val && "isa<> used on a null pointer"); 89| | return isa_impl::doit(*Val); 90| | } 91| |}; 92| | 93| |template struct isa_impl_cl { 94| 0| static inline bool doit(const From *Val) { 95| 0| assert(Val && "isa<> used on a null pointer"); 96| 0| return isa_impl::doit(*Val); 97| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11isa_impl_clINS_4yaml10ScalarNodeEPKNS1_4NodeEE4doitES5_ ------------------ | Unexecuted instantiation: _ZN4llvm11isa_impl_clINS_4yaml11MappingNodeEPKNS1_4NodeEE4doitES5_ ------------------ | Unexecuted instantiation: _ZN4llvm11isa_impl_clINS_4yaml12SequenceNodeEPKNS1_4NodeEE4doitES5_ ------------------ 98| |}; 99| | 100| |template struct isa_impl_cl { 101| | static inline bool doit(const From *Val) { 102| | assert(Val && "isa<> used on a null pointer"); 103| | return isa_impl::doit(*Val); 104| | } 105| |}; 106| | 107| |template 108| |struct isa_impl_wrap { 109| | // When From != SimplifiedType, we can simplify the type some more by using 110| | // the simplify_type template. 111| 0| static bool doit(const From &Val) { 112| 0| return isa_impl_wrap::SimpleType>::doit( 114| 0| simplify_type::getSimplifiedValue(Val)); 115| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml10ScalarNodeEKPNS1_4NodeEPKS3_E4doitERS5_ ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml11MappingNodeEKPNS1_4NodeEPKS3_E4doitERS5_ ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml12SequenceNodeEKPNS1_4NodeEPKS3_E4doitERS5_ ------------------ 116| |}; 117| | 118| |template 119| |struct isa_impl_wrap { 120| | // When From == SimpleType, we are as simple as we are going to get. 121| 0| static bool doit(const FromTy &Val) { 122| 0| return isa_impl_cl::doit(Val); 123| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml10ScalarNodeEPKNS1_4NodeES5_E4doitERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml11MappingNodeEPKNS1_4NodeES5_E4doitERKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm13isa_impl_wrapINS_4yaml12SequenceNodeEPKNS1_4NodeES5_E4doitERKS5_ ------------------ 124| |}; 125| | 126| |// isa - Return true if the parameter to the template is an instance of the 127| |// template type argument. Used like this: 128| |// 129| |// if (isa(myVal)) { ... } 130| |// 131| |template 132| 0|LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) { 133| 0| return isa_impl_wrap::SimpleType>::doit(Val); 135| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm3isaINS_4yaml10ScalarNodeEPNS1_4NodeEEEbRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm3isaINS_4yaml11MappingNodeEPNS1_4NodeEEEbRKT0_ ------------------ | Unexecuted instantiation: _ZN4llvm3isaINS_4yaml12SequenceNodeEPNS1_4NodeEEEbRKT0_ ------------------ 136| | 137| |//===----------------------------------------------------------------------===// 138| |// cast Support Templates 139| |//===----------------------------------------------------------------------===// 140| | 141| |template struct cast_retty; 142| | 143| | 144| |// Calculate what type the 'cast' function should return, based on a requested 145| |// type of To and a source type of From. 146| |template struct cast_retty_impl { 147| | typedef To& ret_type; // Normal case, return Ty& 148| |}; 149| |template struct cast_retty_impl { 150| | typedef const To &ret_type; // Normal case, return Ty& 151| |}; 152| | 153| |template struct cast_retty_impl { 154| | typedef To* ret_type; // Pointer arg case, return Ty* 155| |}; 156| | 157| |template struct cast_retty_impl { 158| | typedef const To* ret_type; // Constant pointer arg case, return const Ty* 159| |}; 160| | 161| |template struct cast_retty_impl { 162| | typedef const To* ret_type; // Constant pointer arg case, return const Ty* 163| |}; 164| | 165| | 166| |template 167| |struct cast_retty_wrap { 168| | // When the simplified type and the from type are not the same, use the type 169| | // simplifier to reduce the type, then reuse cast_retty_impl to get the 170| | // resultant type. 171| | typedef typename cast_retty::ret_type ret_type; 172| |}; 173| | 174| |template 175| |struct cast_retty_wrap { 176| | // When the simplified type is equal to the from type, use it directly. 177| | typedef typename cast_retty_impl::ret_type ret_type; 178| |}; 179| | 180| |template 181| |struct cast_retty { 182| | typedef typename cast_retty_wrap::SimpleType>::ret_type ret_type; 184| |}; 185| | 186| |// Ensure the non-simple values are converted using the simplify_type template 187| |// that may be specialized by smart pointers... 188| |// 189| |template struct cast_convert_val { 190| | // This is not a simple type, use the template to simplify it... 191| | static typename cast_retty::ret_type doit(From &Val) { 192| | return cast_convert_val::SimpleType>::doit( 194| | simplify_type::getSimplifiedValue(Val)); 195| | } 196| |}; 197| | 198| |template struct cast_convert_val { 199| | // This _is_ a simple type, just cast it. 200| 0| static typename cast_retty::ret_type doit(const FromTy &Val) { 201| 0| typename cast_retty::ret_type Res2 202| 0| = (typename cast_retty::ret_type)const_cast(Val); 203| 0| return Res2; 204| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm16cast_convert_valINS_4yaml10ScalarNodeEPNS1_4NodeES4_E4doitERKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm16cast_convert_valINS_4yaml11MappingNodeEPNS1_4NodeES4_E4doitERKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm16cast_convert_valINS_4yaml12SequenceNodeEPNS1_4NodeES4_E4doitERKS4_ ------------------ 205| |}; 206| | 207| |template struct is_simple_type { 208| | static const bool value = 209| | std::is_same::SimpleType>::value; 210| |}; 211| | 212| |// cast - Return the argument parameter cast to the specified type. This 213| |// casting operator asserts that the type is correct, so it does not return null 214| |// on failure. It does not allow a null argument (use cast_or_null for that). 215| |// It is typically used like this: 216| |// 217| |// cast(myVal)->getParent() 218| |// 219| |template 220| |inline typename std::enable_if::value, 221| | typename cast_retty::ret_type>::type 222| |cast(const Y &Val) { 223| | assert(isa(Val) && "cast() argument of incompatible type!"); 224| | return cast_convert_val< 225| | X, const Y, typename simplify_type::SimpleType>::doit(Val); 226| |} 227| | 228| |template 229| |inline typename cast_retty::ret_type cast(Y &Val) { 230| | assert(isa(Val) && "cast() argument of incompatible type!"); 231| | return cast_convert_val::SimpleType>::doit(Val); 233| |} 234| | 235| |template 236| 0|inline typename cast_retty::ret_type cast(Y *Val) { 237| 0| assert(isa(Val) && "cast() argument of incompatible type!"); 238| 0| return cast_convert_val::SimpleType>::doit(Val); 240| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm4castINS_4yaml10ScalarNodeENS1_4NodeEEENS_10cast_rettyIT_PT0_E8ret_typeES7_ ------------------ | Unexecuted instantiation: _ZN4llvm4castINS_4yaml11MappingNodeENS1_4NodeEEENS_10cast_rettyIT_PT0_E8ret_typeES7_ ------------------ | Unexecuted instantiation: _ZN4llvm4castINS_4yaml12SequenceNodeENS1_4NodeEEENS_10cast_rettyIT_PT0_E8ret_typeES7_ ------------------ 241| | 242| |// cast_or_null - Functionally identical to cast, except that a null value is 243| |// accepted. 244| |// 245| |template 246| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 247| | !is_simple_type::value, typename cast_retty::ret_type>::type 248| |cast_or_null(const Y &Val) { 249| | if (!Val) 250| | return nullptr; 251| | assert(isa(Val) && "cast_or_null() argument of incompatible type!"); 252| | return cast(Val); 253| |} 254| | 255| |template 256| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 257| | !is_simple_type::value, typename cast_retty::ret_type>::type 258| |cast_or_null(Y &Val) { 259| | if (!Val) 260| | return nullptr; 261| | assert(isa(Val) && "cast_or_null() argument of incompatible type!"); 262| | return cast(Val); 263| |} 264| | 265| |template 266| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type 267| |cast_or_null(Y *Val) { 268| | if (!Val) return nullptr; 269| | assert(isa(Val) && "cast_or_null() argument of incompatible type!"); 270| | return cast(Val); 271| |} 272| | 273| | 274| |// dyn_cast - Return the argument parameter cast to the specified type. This 275| |// casting operator returns null if the argument is of the wrong type, so it can 276| |// be used to test for a type as well as cast if successful. This should be 277| |// used in the context of an if statement like this: 278| |// 279| |// if (const Instruction *I = dyn_cast(myVal)) { ... } 280| |// 281| | 282| |template 283| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 284| | !is_simple_type::value, typename cast_retty::ret_type>::type 285| |dyn_cast(const Y &Val) { 286| | return isa(Val) ? cast(Val) : nullptr; 287| |} 288| | 289| |template 290| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type 291| |dyn_cast(Y &Val) { 292| | return isa(Val) ? cast(Val) : nullptr; 293| |} 294| | 295| |template 296| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type 297| |dyn_cast(Y *Val) { 298| | return isa(Val) ? cast(Val) : nullptr; 299| |} 300| | 301| |// dyn_cast_or_null - Functionally identical to dyn_cast, except that a null 302| |// value is accepted. 303| |// 304| |template 305| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 306| | !is_simple_type::value, typename cast_retty::ret_type>::type 307| |dyn_cast_or_null(const Y &Val) { 308| | return (Val && isa(Val)) ? cast(Val) : nullptr; 309| |} 310| | 311| |template 312| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 313| | !is_simple_type::value, typename cast_retty::ret_type>::type 314| |dyn_cast_or_null(Y &Val) { 315| | return (Val && isa(Val)) ? cast(Val) : nullptr; 316| |} 317| | 318| |template 319| |LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type 320| |dyn_cast_or_null(Y *Val) { 321| | return (Val && isa(Val)) ? cast(Val) : nullptr; 322| |} 323| | 324| |} // End llvm namespace 325| | 326| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Compiler.h: 1| |//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines several macros, based on the current compiler. This allows 11| |// use of compiler-specific features in a way that remains portable. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_COMPILER_H 16| |#define LLVM_SUPPORT_COMPILER_H 17| | 18| |#include "llvm/Config/llvm-config.h" 19| | 20| |#ifndef __has_feature 21| |# define __has_feature(x) 0 22| |#endif 23| | 24| |#ifndef __has_extension 25| |# define __has_extension(x) 0 26| |#endif 27| | 28| |#ifndef __has_attribute 29| |# define __has_attribute(x) 0 30| |#endif 31| | 32| |#ifndef __has_builtin 33| |# define __has_builtin(x) 0 34| |#endif 35| | 36| |/// \macro LLVM_GNUC_PREREQ 37| |/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't 38| |/// available. 39| |#ifndef LLVM_GNUC_PREREQ 40| |# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 42| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43| | ((maj) << 20) + ((min) << 10) + (patch)) 44| |# elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 46| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47| |# else 48| |# define LLVM_GNUC_PREREQ(maj, min, patch) 0 49| |# endif 50| |#endif 51| | 52| |/// \macro LLVM_MSC_PREREQ 53| |/// \brief Is the compiler MSVC of at least the specified version? 54| |/// The common \param version values to check for are: 55| |/// * 1800: Microsoft Visual Studio 2013 / 12.0 56| |/// * 1900: Microsoft Visual Studio 2015 / 14.0 57| |#ifdef _MSC_VER 58| |#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) 59| | 60| |// We require at least MSVC 2013. 61| |#if !LLVM_MSC_PREREQ(1800) 62| |#error LLVM requires at least MSVC 2013. 63| |#endif 64| | 65| |#else 66| |#define LLVM_MSC_PREREQ(version) 0 67| |#endif 68| | 69| |#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) 70| |#define LLVM_NOEXCEPT noexcept 71| |#else 72| |#define LLVM_NOEXCEPT 73| |#endif 74| | 75| |/// \brief Does the compiler support r-value reference *this? 76| |/// 77| |/// Sadly, this is separate from just r-value reference support because GCC 78| |/// implemented this later than everything else. 79| |#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) 80| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 81| |#else 82| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 83| |#endif 84| | 85| |/// Expands to '&' if r-value references are supported. 86| |/// 87| |/// This can be used to provide l-value/r-value overrides of member functions. 88| |/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS 89| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 90| |#define LLVM_LVALUE_FUNCTION & 91| |#else 92| |#define LLVM_LVALUE_FUNCTION 93| |#endif 94| | 95| |#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) 96| |# define LLVM_CONSTEXPR constexpr 97| |#else 98| |# define LLVM_CONSTEXPR 99| |#endif 100| | 101| |/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked 102| |/// into a shared library, then the class should be private to the library and 103| |/// not accessible from outside it. Can also be used to mark variables and 104| |/// functions, making them private to any shared library they are linked into. 105| |/// On PE/COFF targets, library visibility is the default, so this isn't needed. 106| |#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 107| | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) 108| |#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) 109| |#else 110| |#define LLVM_LIBRARY_VISIBILITY 111| |#endif 112| | 113| |#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) 114| |#define LLVM_END_WITH_NULL __attribute__((sentinel)) 115| |#else 116| |#define LLVM_END_WITH_NULL 117| |#endif 118| | 119| |#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) 120| |#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) 121| |#else 122| |#define LLVM_ATTRIBUTE_USED 123| |#endif 124| | 125| |#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) 126| |#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) 127| |#else 128| |#define LLVM_ATTRIBUTE_UNUSED_RESULT 129| |#endif 130| | 131| |// Some compilers warn about unused functions. When a function is sometimes 132| |// used or not depending on build settings (e.g. a function only called from 133| |// within "assert"), this attribute can be used to suppress such warnings. 134| |// 135| |// However, it shouldn't be used for unused *variables*, as those have a much 136| |// more portable solution: 137| |// (void)unused_var_name; 138| |// Prefer cast-to-void wherever it is sufficient. 139| |#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) 140| |#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) 141| |#else 142| |#define LLVM_ATTRIBUTE_UNUSED 143| |#endif 144| | 145| |// FIXME: Provide this for PE/COFF targets. 146| |#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 147| | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) 148| |#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) 149| |#else 150| |#define LLVM_ATTRIBUTE_WEAK 151| |#endif 152| | 153| |// Prior to clang 3.2, clang did not accept any spelling of 154| |// __has_attribute(const), so assume it is supported. 155| |#if defined(__clang__) || defined(__GNUC__) 156| |// aka 'CONST' but following LLVM Conventions. 157| |#define LLVM_READNONE __attribute__((__const__)) 158| |#else 159| |#define LLVM_READNONE 160| |#endif 161| | 162| |#if __has_attribute(pure) || defined(__GNUC__) 163| |// aka 'PURE' but following LLVM Conventions. 164| |#define LLVM_READONLY __attribute__((__pure__)) 165| |#else 166| |#define LLVM_READONLY 167| |#endif 168| | 169| |#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) 170| 0|#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) 171| 0|#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) 172| |#else 173| |#define LLVM_LIKELY(EXPR) (EXPR) 174| |#define LLVM_UNLIKELY(EXPR) (EXPR) 175| |#endif 176| | 177| |// C++ doesn't support 'extern template' of template specializations. GCC does, 178| |// but requires __extension__ before it. In the header, use this: 179| |// EXTERN_TEMPLATE_INSTANTIATION(class foo); 180| |// in the .cpp file, use this: 181| |// TEMPLATE_INSTANTIATION(class foo); 182| |#ifdef __GNUC__ 183| |#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X 184| |#define TEMPLATE_INSTANTIATION(X) template X 185| |#else 186| |#define EXTERN_TEMPLATE_INSTANTIATION(X) 187| |#define TEMPLATE_INSTANTIATION(X) 188| |#endif 189| | 190| |/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, 191| |/// mark a method "not for inlining". 192| |#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) 193| |#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) 194| |#elif defined(_MSC_VER) 195| |#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) 196| |#else 197| |#define LLVM_ATTRIBUTE_NOINLINE 198| |#endif 199| | 200| |/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do 201| |/// so, mark a method "always inline" because it is performance sensitive. GCC 202| |/// 3.4 supported this but is buggy in various cases and produces unimplemented 203| |/// errors, just use it in GCC 4.0 and later. 204| |#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) 205| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) 206| |#elif defined(_MSC_VER) 207| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline 208| |#else 209| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE 210| |#endif 211| | 212| |#ifdef __GNUC__ 213| |#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) 214| |#elif defined(_MSC_VER) 215| |#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) 216| |#else 217| |#define LLVM_ATTRIBUTE_NORETURN 218| |#endif 219| | 220| |#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) 221| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 222| |#else 223| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL 224| |#endif 225| | 226| |/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress 227| |/// pedantic diagnostics. 228| |#ifdef __GNUC__ 229| |#define LLVM_EXTENSION __extension__ 230| |#else 231| |#define LLVM_EXTENSION 232| |#endif 233| | 234| |// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") 235| |#if __has_feature(attribute_deprecated_with_message) 236| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 237| | decl __attribute__((deprecated(message))) 238| |#elif defined(__GNUC__) 239| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 240| | decl __attribute__((deprecated)) 241| |#elif defined(_MSC_VER) 242| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 243| | __declspec(deprecated(message)) decl 244| |#else 245| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 246| | decl 247| |#endif 248| | 249| |/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands 250| |/// to an expression which states that it is undefined behavior for the 251| |/// compiler to reach this point. Otherwise is not defined. 252| |#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) 253| |# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() 254| |#elif defined(_MSC_VER) 255| |# define LLVM_BUILTIN_UNREACHABLE __assume(false) 256| |#endif 257| | 258| |/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression 259| |/// which causes the program to exit abnormally. 260| |#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) 261| |# define LLVM_BUILTIN_TRAP __builtin_trap() 262| |#elif defined(_MSC_VER) 263| |// The __debugbreak intrinsic is supported by MSVC, does not require forward 264| |// declarations involving platform-specific typedefs (unlike RaiseException), 265| |// results in a call to vectored exception handlers, and encodes to a short 266| |// instruction that still causes the trapping behavior we want. 267| |# define LLVM_BUILTIN_TRAP __debugbreak() 268| |#else 269| |# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 270| |#endif 271| | 272| |/// \macro LLVM_ASSUME_ALIGNED 273| |/// \brief Returns a pointer with an assumed alignment. 274| |#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) 275| |# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) 276| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 277| |// As of today, clang does not support __builtin_assume_aligned. 278| |# define LLVM_ASSUME_ALIGNED(p, a) \ 279| | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) 280| |#else 281| |# define LLVM_ASSUME_ALIGNED(p, a) (p) 282| |#endif 283| | 284| |/// \macro LLVM_FUNCTION_NAME 285| |/// \brief Expands to __func__ on compilers which support it. Otherwise, 286| |/// expands to a compiler-dependent replacement. 287| |#if defined(_MSC_VER) 288| |# define LLVM_FUNCTION_NAME __FUNCTION__ 289| |#else 290| |# define LLVM_FUNCTION_NAME __func__ 291| |#endif 292| | 293| |/// \macro LLVM_MEMORY_SANITIZER_BUILD 294| |/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. 295| |#if __has_feature(memory_sanitizer) 296| |# define LLVM_MEMORY_SANITIZER_BUILD 1 297| |# include 298| |#else 299| |# define LLVM_MEMORY_SANITIZER_BUILD 0 300| |# define __msan_allocated_memory(p, size) 301| |# define __msan_unpoison(p, size) 302| |#endif 303| | 304| |/// \macro LLVM_ADDRESS_SANITIZER_BUILD 305| |/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. 306| |#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 307| |# define LLVM_ADDRESS_SANITIZER_BUILD 1 308| |#else 309| |# define LLVM_ADDRESS_SANITIZER_BUILD 0 310| |#endif 311| | 312| |/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST 313| |/// \brief Is unaligned memory access fast on the host machine. 314| |/// 315| |/// Don't specialize on alignment for platforms where unaligned memory accesses 316| |/// generates the same code as aligned memory accesses for common types. 317| |#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ 318| | defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ 319| | defined(_X86_) || defined(__i386) || defined(__i386__) 320| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 321| |#else 322| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 323| |#endif 324| | 325| |/// \brief Mark debug helper function definitions like dump() that should not be 326| |/// stripped from debug builds. 327| |// FIXME: Move this to a private config.h as it's not usable in public headers. 328| |#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED 330| |#else 331| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE 332| |#endif 333| | 334| |/// \macro LLVM_THREAD_LOCAL 335| |/// \brief A thread-local storage specifier which can be used with globals, 336| |/// extern globals, and static globals. 337| |/// 338| |/// This is essentially an extremely restricted analog to C++11's thread_local 339| |/// support, and uses that when available. However, it falls back on 340| |/// platform-specific or vendor-provided extensions when necessary. These 341| |/// extensions don't support many of the C++11 thread_local's features. You 342| |/// should only use this for PODs that you can statically initialize to 343| |/// some constant value. In almost all circumstances this is most appropriate 344| |/// for use with a pointer, integer, or small aggregation of pointers and 345| |/// integers. 346| |#if LLVM_ENABLE_THREADS 347| |#if __has_feature(cxx_thread_local) 348| |#define LLVM_THREAD_LOCAL thread_local 349| |#elif defined(_MSC_VER) 350| |// MSVC supports this with a __declspec. 351| |#define LLVM_THREAD_LOCAL __declspec(thread) 352| |#else 353| |// Clang, GCC, and other compatible compilers used __thread prior to C++11 and 354| |// we only need the restricted functionality that provides. 355| |#define LLVM_THREAD_LOCAL __thread 356| |#endif 357| |#else // !LLVM_ENABLE_THREADS 358| |// If threading is disabled entirely, this compiles to nothing and you get 359| |// a normal global variable. 360| |#define LLVM_THREAD_LOCAL 361| |#endif 362| | 363| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorHandling.h: 1| |//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ERRORHANDLING_H 16| |#define LLVM_SUPPORT_ERRORHANDLING_H 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include 21| | 22| |namespace llvm { 23| | class Twine; 24| | 25| | /// An error handler callback. 26| | typedef void (*fatal_error_handler_t)(void *user_data, 27| | const std::string& reason, 28| | bool gen_crash_diag); 29| | 30| | /// install_fatal_error_handler - Installs a new error handler to be used 31| | /// whenever a serious (non-recoverable) error is encountered by LLVM. 32| | /// 33| | /// If no error handler is installed the default is to print the error message 34| | /// to stderr, and call exit(1). If an error handler is installed then it is 35| | /// the handler's responsibility to log the message, it will no longer be 36| | /// printed to stderr. If the error handler returns, then exit(1) will be 37| | /// called. 38| | /// 39| | /// It is dangerous to naively use an error handler which throws an exception. 40| | /// Even though some applications desire to gracefully recover from arbitrary 41| | /// faults, blindly throwing exceptions through unfamiliar code isn't a way to 42| | /// achieve this. 43| | /// 44| | /// \param user_data - An argument which will be passed to the install error 45| | /// handler. 46| | void install_fatal_error_handler(fatal_error_handler_t handler, 47| | void *user_data = nullptr); 48| | 49| | /// Restores default error handling behaviour. 50| | void remove_fatal_error_handler(); 51| | 52| | /// ScopedFatalErrorHandler - This is a simple helper class which just 53| | /// calls install_fatal_error_handler in its constructor and 54| | /// remove_fatal_error_handler in its destructor. 55| | struct ScopedFatalErrorHandler { 56| | explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, 57| 0| void *user_data = nullptr) { 58| 0| install_fatal_error_handler(handler, user_data); 59| 0| } 60| | 61| 0| ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } 62| | }; 63| | 64| | /// Reports a serious error, calling any installed error handler. These 65| | /// functions are intended to be used for error conditions which are outside 66| | /// the control of the compiler (I/O errors, invalid user input, etc.) 67| | /// 68| | /// If no error handler is installed the default is to print the message to 69| | /// standard error, followed by a newline. 70| | /// After the error handler is called this function will call exit(1), it 71| | /// does not return. 72| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, 73| | bool gen_crash_diag = true); 74| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, 75| | bool gen_crash_diag = true); 76| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, 77| | bool gen_crash_diag = true); 78| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, 79| | bool gen_crash_diag = true); 80| | 81| | /// This function calls abort(), and prints the optional message to stderr. 82| | /// Use the llvm_unreachable macro (that adds location info), instead of 83| | /// calling this function directly. 84| | LLVM_ATTRIBUTE_NORETURN void 85| | llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, 86| | unsigned line=0); 87| |} 88| | 89| |/// Marks that the current location is not supposed to be reachable. 90| |/// In !NDEBUG builds, prints the message and location info to stderr. 91| |/// In NDEBUG builds, becomes an optimizer hint that the current location 92| |/// is not supposed to be reachable. On compilers that don't support 93| |/// such hints, prints a reduced message instead. 94| |/// 95| |/// Use this instead of assert(0). It conveys intent more clearly and 96| |/// allows compilers to omit some unnecessary code. 97| |#ifndef NDEBUG 98| |#define llvm_unreachable(msg) \ 99| 0| ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) 100| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 101| |#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE 102| |#else 103| |#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() 104| |#endif 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/FileSystem.h: 1| |//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::fs namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |// All functions return an error_code and their actual work via the last out 15| |// argument. The out argument is defined if and only if errc::success is 16| |// returned. A function may return any error code in the generic or system 17| |// category. However, they shall be equivalent to any error conditions listed 18| |// in each functions respective documentation if the condition applies. [ note: 19| |// this does not guarantee that error_code will be in the set of explicitly 20| |// listed codes, but it does guarantee that if any of the explicitly listed 21| |// errors occur, the correct error_code will be used ]. All functions may 22| |// return errc::not_enough_memory if there is not enough memory to complete the 23| |// operation. 24| |// 25| |//===----------------------------------------------------------------------===// 26| | 27| |#ifndef LLVM_SUPPORT_FILESYSTEM_H 28| |#define LLVM_SUPPORT_FILESYSTEM_H 29| | 30| |#include "llvm/ADT/IntrusiveRefCntPtr.h" 31| |#include "llvm/ADT/SmallString.h" 32| |#include "llvm/ADT/Twine.h" 33| |#include "llvm/Support/DataTypes.h" 34| |#include "llvm/Support/ErrorHandling.h" 35| |#include "llvm/Support/TimeValue.h" 36| |#include 37| |#include 38| |#include 39| |#include 40| |#include 41| |#include 42| |#include 43| | 44| |#ifdef HAVE_SYS_STAT_H 45| |#include 46| |#endif 47| | 48| |namespace llvm { 49| |namespace sys { 50| |namespace fs { 51| | 52| |/// An enumeration for the file system's view of the type. 53| |enum class file_type { 54| | status_error, 55| | file_not_found, 56| | regular_file, 57| | directory_file, 58| | symlink_file, 59| | block_file, 60| | character_file, 61| | fifo_file, 62| | socket_file, 63| | type_unknown 64| |}; 65| | 66| |/// space_info - Self explanatory. 67| |struct space_info { 68| | uint64_t capacity; 69| | uint64_t free; 70| | uint64_t available; 71| |}; 72| | 73| |enum perms { 74| | no_perms = 0, 75| | owner_read = 0400, 76| | owner_write = 0200, 77| | owner_exe = 0100, 78| | owner_all = owner_read | owner_write | owner_exe, 79| | group_read = 040, 80| | group_write = 020, 81| | group_exe = 010, 82| | group_all = group_read | group_write | group_exe, 83| | others_read = 04, 84| | others_write = 02, 85| | others_exe = 01, 86| | others_all = others_read | others_write | others_exe, 87| | all_read = owner_read | group_read | others_read, 88| | all_write = owner_write | group_write | others_write, 89| | all_exe = owner_exe | group_exe | others_exe, 90| | all_all = owner_all | group_all | others_all, 91| | set_uid_on_exe = 04000, 92| | set_gid_on_exe = 02000, 93| | sticky_bit = 01000, 94| | perms_not_known = 0xFFFF 95| |}; 96| | 97| |// Helper functions so that you can use & and | to manipulate perms bits: 98| |inline perms operator|(perms l , perms r) { 99| | return static_cast( 100| | static_cast(l) | static_cast(r)); 101| |} 102| 0|inline perms operator&(perms l , perms r) { 103| 0| return static_cast( 104| 0| static_cast(l) & static_cast(r)); 105| 0|} 106| 0|inline perms &operator|=(perms &l, perms r) { 107| 0| l = l | r; 108| 0| return l; 109| 0|} 110| 0|inline perms &operator&=(perms &l, perms r) { 111| 0| l = l & r; 112| 0| return l; 113| 0|} 114| 0|inline perms operator~(perms x) { 115| 0| return static_cast(~static_cast(x)); 116| 0|} 117| | 118| |class UniqueID { 119| | uint64_t Device; 120| | uint64_t File; 121| | 122| |public: 123| 0| UniqueID() {} 124| 0| UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 125| | bool operator==(const UniqueID &Other) const { 126| | return Device == Other.Device && File == Other.File; 127| | } 128| 0| bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 129| 0| bool operator<(const UniqueID &Other) const { 130| 0| return std::tie(Device, File) < std::tie(Other.Device, Other.File); 131| 0| } 132| 0| uint64_t getDevice() const { return Device; } 133| 0| uint64_t getFile() const { return File; } 134| |}; 135| | 136| |/// file_status - Represents the result of a call to stat and friends. It has 137| |/// a platform-specific member to store the result. 138| |class file_status 139| |{ 140| | #if defined(LLVM_ON_UNIX) 141| | dev_t fs_st_dev; 142| | ino_t fs_st_ino; 143| | time_t fs_st_mtime; 144| | uid_t fs_st_uid; 145| | gid_t fs_st_gid; 146| | off_t fs_st_size; 147| | #elif defined (LLVM_ON_WIN32) 148| | uint32_t LastWriteTimeHigh; 149| | uint32_t LastWriteTimeLow; 150| | uint32_t VolumeSerialNumber; 151| | uint32_t FileSizeHigh; 152| | uint32_t FileSizeLow; 153| | uint32_t FileIndexHigh; 154| | uint32_t FileIndexLow; 155| | #endif 156| | friend bool equivalent(file_status A, file_status B); 157| | file_type Type; 158| | perms Perms; 159| |public: 160| | #if defined(LLVM_ON_UNIX) 161| | file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 162| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), 163| 0| Type(file_type::status_error), Perms(perms_not_known) {} 164| | 165| | file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 166| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), 167| 0| Perms(perms_not_known) {} 168| | 169| | file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, 170| | uid_t UID, gid_t GID, off_t Size) 171| | : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), 172| 0| fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} 173| | #elif defined(LLVM_ON_WIN32) 174| | file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), 175| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 176| | FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), 177| | Perms(perms_not_known) {} 178| | 179| | file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), 180| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 181| | FileIndexHigh(0), FileIndexLow(0), Type(Type), 182| | Perms(perms_not_known) {} 183| | 184| | file_status(file_type Type, uint32_t LastWriteTimeHigh, 185| | uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, 186| | uint32_t FileSizeHigh, uint32_t FileSizeLow, 187| | uint32_t FileIndexHigh, uint32_t FileIndexLow) 188| | : LastWriteTimeHigh(LastWriteTimeHigh), 189| | LastWriteTimeLow(LastWriteTimeLow), 190| | VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), 191| | FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), 192| | FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} 193| | #endif 194| | 195| | // getters 196| | file_type type() const { return Type; } 197| 0| perms permissions() const { return Perms; } 198| | TimeValue getLastModificationTime() const; 199| | UniqueID getUniqueID() const; 200| | 201| | #if defined(LLVM_ON_UNIX) 202| 0| uint32_t getUser() const { return fs_st_uid; } 203| 0| uint32_t getGroup() const { return fs_st_gid; } 204| | uint64_t getSize() const { return fs_st_size; } 205| | #elif defined (LLVM_ON_WIN32) 206| | uint32_t getUser() const { 207| | return 9999; // Not applicable to Windows, so... 208| | } 209| | uint32_t getGroup() const { 210| | return 9999; // Not applicable to Windows, so... 211| | } 212| | uint64_t getSize() const { 213| | return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 214| | } 215| | #endif 216| | 217| | // setters 218| 0| void type(file_type v) { Type = v; } 219| 0| void permissions(perms p) { Perms = p; } 220| |}; 221| | 222| |/// file_magic - An "enum class" enumeration of file types based on magic (the first 223| |/// N bytes of the file). 224| |struct file_magic { 225| | enum Impl { 226| | unknown = 0, ///< Unrecognized file 227| | bitcode, ///< Bitcode file 228| | archive, ///< ar style archive file 229| | elf, ///< ELF Unknown type 230| | elf_relocatable, ///< ELF Relocatable object file 231| | elf_executable, ///< ELF Executable image 232| | elf_shared_object, ///< ELF dynamically linked shared lib 233| | elf_core, ///< ELF core image 234| | macho_object, ///< Mach-O Object file 235| | macho_executable, ///< Mach-O Executable 236| | macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 237| | macho_core, ///< Mach-O Core File 238| | macho_preload_executable, ///< Mach-O Preloaded Executable 239| | macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 240| | macho_dynamic_linker, ///< The Mach-O dynamic linker 241| | macho_bundle, ///< Mach-O Bundle file 242| | macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 243| | macho_dsym_companion, ///< Mach-O dSYM companion file 244| | macho_kext_bundle, ///< Mach-O kext bundle file 245| | macho_universal_binary, ///< Mach-O universal binary 246| | coff_object, ///< COFF object file 247| | coff_import_library, ///< COFF import library 248| | pecoff_executable, ///< PECOFF executable file 249| | windows_resource ///< Windows compiled resource file (.rc) 250| | }; 251| | 252| 0| bool is_object() const { 253| 0| return V == unknown ? false : true; 254| 0| } 255| | 256| 0| file_magic() : V(unknown) {} 257| 0| file_magic(Impl V) : V(V) {} 258| 0| operator Impl() const { return V; } 259| | 260| |private: 261| | Impl V; 262| |}; 263| | 264| |/// @} 265| |/// @name Physical Operators 266| |/// @{ 267| | 268| |/// @brief Make \a path an absolute path. 269| |/// 270| |/// Makes \a path absolute using the current directory if it is not already. An 271| |/// empty \a path will result in the current directory. 272| |/// 273| |/// /absolute/path => /absolute/path 274| |/// relative/../path => /relative/../path 275| |/// 276| |/// @param path A path that is modified to be an absolute path. 277| |/// @returns errc::success if \a path has been made absolute, otherwise a 278| |/// platform-specific error_code. 279| |std::error_code make_absolute(SmallVectorImpl &path); 280| | 281| |/// @brief Create all the non-existent directories in path. 282| |/// 283| |/// @param path Directories to create. 284| |/// @returns errc::success if is_directory(path), otherwise a platform 285| |/// specific error_code. If IgnoreExisting is false, also returns 286| |/// error if the directory already existed. 287| |std::error_code create_directories(const Twine &path, 288| | bool IgnoreExisting = true); 289| | 290| |/// @brief Create the directory in path. 291| |/// 292| |/// @param path Directory to create. 293| |/// @returns errc::success if is_directory(path), otherwise a platform 294| |/// specific error_code. If IgnoreExisting is false, also returns 295| |/// error if the directory already existed. 296| |std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); 297| | 298| |/// @brief Create a link from \a from to \a to. 299| |/// 300| |/// The link may be a soft or a hard link, depending on the platform. The caller 301| |/// may not assume which one. Currently on windows it creates a hard link since 302| |/// soft links require extra privileges. On unix, it creates a soft link since 303| |/// hard links don't work on SMB file systems. 304| |/// 305| |/// @param to The path to hard link to. 306| |/// @param from The path to hard link from. This is created. 307| |/// @returns errc::success if the link was created, otherwise a platform 308| |/// specific error_code. 309| |std::error_code create_link(const Twine &to, const Twine &from); 310| | 311| |/// @brief Get the current path. 312| |/// 313| |/// @param result Holds the current path on return. 314| |/// @returns errc::success if the current path has been stored in result, 315| |/// otherwise a platform-specific error_code. 316| |std::error_code current_path(SmallVectorImpl &result); 317| | 318| |/// @brief Remove path. Equivalent to POSIX remove(). 319| |/// 320| |/// @param path Input path. 321| |/// @returns errc::success if path has been removed or didn't exist, otherwise a 322| |/// platform-specific error code. If IgnoreNonExisting is false, also 323| |/// returns error if the file didn't exist. 324| |std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 325| | 326| |/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 327| |/// 328| |/// @param from The path to rename from. 329| |/// @param to The path to rename to. This is created. 330| |std::error_code rename(const Twine &from, const Twine &to); 331| | 332| |/// @brief Copy the contents of \a From to \a To. 333| |/// 334| |/// @param From The path to copy from. 335| |/// @param To The path to copy to. This is created. 336| |std::error_code copy_file(const Twine &From, const Twine &To); 337| | 338| |/// @brief Resize path to size. File is resized as if by POSIX truncate(). 339| |/// 340| |/// @param FD Input file descriptor. 341| |/// @param Size Size to resize to. 342| |/// @returns errc::success if \a path has been resized to \a size, otherwise a 343| |/// platform-specific error_code. 344| |std::error_code resize_file(int FD, uint64_t Size); 345| | 346| |/// @} 347| |/// @name Physical Observers 348| |/// @{ 349| | 350| |/// @brief Does file exist? 351| |/// 352| |/// @param status A file_status previously returned from stat. 353| |/// @returns True if the file represented by status exists, false if it does 354| |/// not. 355| |bool exists(file_status status); 356| | 357| |enum class AccessMode { Exist, Write, Execute }; 358| | 359| |/// @brief Can the file be accessed? 360| |/// 361| |/// @param Path Input path. 362| |/// @returns errc::success if the path can be accessed, otherwise a 363| |/// platform-specific error_code. 364| |std::error_code access(const Twine &Path, AccessMode Mode); 365| | 366| |/// @brief Does file exist? 367| |/// 368| |/// @param Path Input path. 369| |/// @returns True if it exists, false otherwise. 370| |inline bool exists(const Twine &Path) { 371| | return !access(Path, AccessMode::Exist); 372| |} 373| | 374| |/// @brief Can we execute this file? 375| |/// 376| |/// @param Path Input path. 377| |/// @returns True if we can execute it, false otherwise. 378| |inline bool can_execute(const Twine &Path) { 379| | return !access(Path, AccessMode::Execute); 380| |} 381| | 382| |/// @brief Can we write this file? 383| |/// 384| |/// @param Path Input path. 385| |/// @returns True if we can write to it, false otherwise. 386| 0|inline bool can_write(const Twine &Path) { 387| 0| return !access(Path, AccessMode::Write); 388| 0|} 389| | 390| |/// @brief Do file_status's represent the same thing? 391| |/// 392| |/// @param A Input file_status. 393| |/// @param B Input file_status. 394| |/// 395| |/// assert(status_known(A) || status_known(B)); 396| |/// 397| |/// @returns True if A and B both represent the same file system entity, false 398| |/// otherwise. 399| |bool equivalent(file_status A, file_status B); 400| | 401| |/// @brief Do paths represent the same thing? 402| |/// 403| |/// assert(status_known(A) || status_known(B)); 404| |/// 405| |/// @param A Input path A. 406| |/// @param B Input path B. 407| |/// @param result Set to true if stat(A) and stat(B) have the same device and 408| |/// inode (or equivalent). 409| |/// @returns errc::success if result has been successfully set, otherwise a 410| |/// platform-specific error_code. 411| |std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 412| | 413| |/// @brief Simpler version of equivalent for clients that don't need to 414| |/// differentiate between an error and false. 415| 0|inline bool equivalent(const Twine &A, const Twine &B) { 416| 0| bool result; 417| 0| return !equivalent(A, B, result) && result; 418| 0|} 419| | 420| |/// @brief Does status represent a directory? 421| |/// 422| |/// @param status A file_status previously returned from status. 423| |/// @returns status.type() == file_type::directory_file. 424| |bool is_directory(file_status status); 425| | 426| |/// @brief Is path a directory? 427| |/// 428| |/// @param path Input path. 429| |/// @param result Set to true if \a path is a directory, false if it is not. 430| |/// Undefined otherwise. 431| |/// @returns errc::success if result has been successfully set, otherwise a 432| |/// platform-specific error_code. 433| |std::error_code is_directory(const Twine &path, bool &result); 434| | 435| |/// @brief Simpler version of is_directory for clients that don't need to 436| |/// differentiate between an error and false. 437| 0|inline bool is_directory(const Twine &Path) { 438| 0| bool Result; 439| 0| return !is_directory(Path, Result) && Result; 440| 0|} 441| | 442| |/// @brief Does status represent a regular file? 443| |/// 444| |/// @param status A file_status previously returned from status. 445| |/// @returns status_known(status) && status.type() == file_type::regular_file. 446| |bool is_regular_file(file_status status); 447| | 448| |/// @brief Is path a regular file? 449| |/// 450| |/// @param path Input path. 451| |/// @param result Set to true if \a path is a regular file, false if it is not. 452| |/// Undefined otherwise. 453| |/// @returns errc::success if result has been successfully set, otherwise a 454| |/// platform-specific error_code. 455| |std::error_code is_regular_file(const Twine &path, bool &result); 456| | 457| |/// @brief Simpler version of is_regular_file for clients that don't need to 458| |/// differentiate between an error and false. 459| 0|inline bool is_regular_file(const Twine &Path) { 460| 0| bool Result; 461| 0| if (is_regular_file(Path, Result)) 462| 0| return false; 463| 0| return Result; 464| 0|} 465| | 466| |/// @brief Does this status represent something that exists but is not a 467| |/// directory, regular file, or symlink? 468| |/// 469| |/// @param status A file_status previously returned from status. 470| |/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 471| |bool is_other(file_status status); 472| | 473| |/// @brief Is path something that exists but is not a directory, 474| |/// regular file, or symlink? 475| |/// 476| |/// @param path Input path. 477| |/// @param result Set to true if \a path exists, but is not a directory, regular 478| |/// file, or a symlink, false if it does not. Undefined otherwise. 479| |/// @returns errc::success if result has been successfully set, otherwise a 480| |/// platform-specific error_code. 481| |std::error_code is_other(const Twine &path, bool &result); 482| | 483| |/// @brief Get file status as if by POSIX stat(). 484| |/// 485| |/// @param path Input path. 486| |/// @param result Set to the file status. 487| |/// @returns errc::success if result has been successfully set, otherwise a 488| |/// platform-specific error_code. 489| |std::error_code status(const Twine &path, file_status &result); 490| | 491| |/// @brief A version for when a file descriptor is already available. 492| |std::error_code status(int FD, file_status &Result); 493| | 494| |/// @brief Get file size. 495| |/// 496| |/// @param Path Input path. 497| |/// @param Result Set to the size of the file in \a Path. 498| |/// @returns errc::success if result has been successfully set, otherwise a 499| |/// platform-specific error_code. 500| 0|inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 501| 0| file_status Status; 502| 0| std::error_code EC = status(Path, Status); 503| 0| if (EC) 504| 0| return EC; 505| 0| Result = Status.getSize(); 506| 0| return std::error_code(); 507| 0|} 508| | 509| |/// @brief Set the file modification and access time. 510| |/// 511| |/// @returns errc::success if the file times were successfully set, otherwise a 512| |/// platform-specific error_code or errc::function_not_supported on 513| |/// platforms where the functionality isn't available. 514| |std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); 515| | 516| |/// @brief Is status available? 517| |/// 518| |/// @param s Input file status. 519| |/// @returns True if status() != status_error. 520| |bool status_known(file_status s); 521| | 522| |/// @brief Is status available? 523| |/// 524| |/// @param path Input path. 525| |/// @param result Set to true if status() != status_error. 526| |/// @returns errc::success if result has been successfully set, otherwise a 527| |/// platform-specific error_code. 528| |std::error_code status_known(const Twine &path, bool &result); 529| | 530| |/// @brief Create a uniquely named file. 531| |/// 532| |/// Generates a unique path suitable for a temporary file and then opens it as a 533| |/// file. The name is based on \a model with '%' replaced by a random char in 534| |/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 535| |/// directory will be prepended. 536| |/// 537| |/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 538| |/// 539| |/// This is an atomic operation. Either the file is created and opened, or the 540| |/// file system is left untouched. 541| |/// 542| |/// The intendend use is for files that are to be kept, possibly after 543| |/// renaming them. For example, when running 'clang -c foo.o', the file can 544| |/// be first created as foo-abc123.o and then renamed. 545| |/// 546| |/// @param Model Name to base unique path off of. 547| |/// @param ResultFD Set to the opened file's file descriptor. 548| |/// @param ResultPath Set to the opened file's absolute path. 549| |/// @returns errc::success if Result{FD,Path} have been successfully set, 550| |/// otherwise a platform-specific error_code. 551| |std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 552| | SmallVectorImpl &ResultPath, 553| | unsigned Mode = all_read | all_write); 554| | 555| |/// @brief Simpler version for clients that don't want an open file. 556| |std::error_code createUniqueFile(const Twine &Model, 557| | SmallVectorImpl &ResultPath); 558| | 559| |/// @brief Create a file in the system temporary directory. 560| |/// 561| |/// The filename is of the form prefix-random_chars.suffix. Since the directory 562| |/// is not know to the caller, Prefix and Suffix cannot have path separators. 563| |/// The files are created with mode 0600. 564| |/// 565| |/// This should be used for things like a temporary .s that is removed after 566| |/// running the assembler. 567| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 568| | int &ResultFD, 569| | SmallVectorImpl &ResultPath); 570| | 571| |/// @brief Simpler version for clients that don't want an open file. 572| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 573| | SmallVectorImpl &ResultPath); 574| | 575| |std::error_code createUniqueDirectory(const Twine &Prefix, 576| | SmallVectorImpl &ResultPath); 577| | 578| |enum OpenFlags : unsigned { 579| | F_None = 0, 580| | 581| | /// F_Excl - When opening a file, this flag makes raw_fd_ostream 582| | /// report an error if the file already exists. 583| | F_Excl = 1, 584| | 585| | /// F_Append - When opening a file, if it already exists append to the 586| | /// existing file instead of returning an error. This may not be specified 587| | /// with F_Excl. 588| | F_Append = 2, 589| | 590| | /// The file should be opened in text mode on platforms that make this 591| | /// distinction. 592| | F_Text = 4, 593| | 594| | /// Open the file for read and write. 595| | F_RW = 8 596| |}; 597| | 598| |inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 599| | return OpenFlags(unsigned(A) | unsigned(B)); 600| |} 601| | 602| 0|inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 603| 0| A = A | B; 604| 0| return A; 605| 0|} 606| | 607| |std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 608| | OpenFlags Flags, unsigned Mode = 0666); 609| | 610| |std::error_code openFileForRead(const Twine &Name, int &ResultFD); 611| | 612| |/// @brief Identify the type of a binary file based on how magical it is. 613| |file_magic identify_magic(StringRef magic); 614| | 615| |/// @brief Get and identify \a path's type based on its content. 616| |/// 617| |/// @param path Input path. 618| |/// @param result Set to the type of file, or file_magic::unknown. 619| |/// @returns errc::success if result has been successfully set, otherwise a 620| |/// platform-specific error_code. 621| |std::error_code identify_magic(const Twine &path, file_magic &result); 622| | 623| |std::error_code getUniqueID(const Twine Path, UniqueID &Result); 624| | 625| |/// This class represents a memory mapped file. It is based on 626| |/// boost::iostreams::mapped_file. 627| |class mapped_file_region { 628| | mapped_file_region() = delete; 629| | mapped_file_region(mapped_file_region&) = delete; 630| | mapped_file_region &operator =(mapped_file_region&) = delete; 631| | 632| |public: 633| | enum mapmode { 634| | readonly, ///< May only access map via const_data as read only. 635| | readwrite, ///< May access map via data and modify it. Written to path. 636| | priv ///< May modify via data, but changes are lost on destruction. 637| | }; 638| | 639| |private: 640| | /// Platform-specific mapping state. 641| | uint64_t Size; 642| | void *Mapping; 643| | 644| | std::error_code init(int FD, uint64_t Offset, mapmode Mode); 645| | 646| |public: 647| | /// \param fd An open file descriptor to map. mapped_file_region takes 648| | /// ownership if closefd is true. It must have been opended in the correct 649| | /// mode. 650| | mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, 651| | std::error_code &ec); 652| | 653| | ~mapped_file_region(); 654| | 655| | uint64_t size() const; 656| | char *data() const; 657| | 658| | /// Get a const view of the data. Modifying this memory has undefined 659| | /// behavior. 660| | const char *const_data() const; 661| | 662| | /// \returns The minimum alignment offset must be. 663| | static int alignment(); 664| |}; 665| | 666| |/// Return the path to the main executable, given the value of argv[0] from 667| |/// program startup and the address of main itself. In extremis, this function 668| |/// may fail and return an empty path. 669| |std::string getMainExecutable(const char *argv0, void *MainExecAddr); 670| | 671| |/// @} 672| |/// @name Iterators 673| |/// @{ 674| | 675| |/// directory_entry - A single entry in a directory. Caches the status either 676| |/// from the result of the iteration syscall, or the first time status is 677| |/// called. 678| |class directory_entry { 679| | std::string Path; 680| | mutable file_status Status; 681| | 682| |public: 683| | explicit directory_entry(const Twine &path, file_status st = file_status()) 684| | : Path(path.str()) 685| 0| , Status(st) {} 686| | 687| 0| directory_entry() {} 688| | 689| 0| void assign(const Twine &path, file_status st = file_status()) { 690| 0| Path = path.str(); 691| 0| Status = st; 692| 0| } 693| | 694| | void replace_filename(const Twine &filename, file_status st = file_status()); 695| | 696| 0| const std::string &path() const { return Path; } 697| | std::error_code status(file_status &result) const; 698| | 699| 0| bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 700| 0| bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 701| | bool operator< (const directory_entry& rhs) const; 702| | bool operator<=(const directory_entry& rhs) const; 703| | bool operator> (const directory_entry& rhs) const; 704| | bool operator>=(const directory_entry& rhs) const; 705| |}; 706| | 707| |namespace detail { 708| | struct DirIterState; 709| | 710| | std::error_code directory_iterator_construct(DirIterState &, StringRef); 711| | std::error_code directory_iterator_increment(DirIterState &); 712| | std::error_code directory_iterator_destruct(DirIterState &); 713| | 714| | /// DirIterState - Keeps state for the directory_iterator. It is reference 715| | /// counted in order to preserve InputIterator semantics on copy. 716| | struct DirIterState : public RefCountedBase { 717| | DirIterState() 718| 0| : IterationHandle(0) {} 719| | 720| 0| ~DirIterState() { 721| 0| directory_iterator_destruct(*this); 722| 0| } 723| | 724| | intptr_t IterationHandle; 725| | directory_entry CurrentEntry; 726| | }; 727| |} 728| | 729| |/// directory_iterator - Iterates through the entries in path. There is no 730| |/// operator++ because we need an error_code. If it's really needed we can make 731| |/// it call report_fatal_error on error. 732| |class directory_iterator { 733| | IntrusiveRefCntPtr State; 734| | 735| |public: 736| 0| explicit directory_iterator(const Twine &path, std::error_code &ec) { 737| 0| State = new detail::DirIterState; 738| 0| SmallString<128> path_storage; 739| 0| ec = detail::directory_iterator_construct(*State, 740| 0| path.toStringRef(path_storage)); 741| 0| } 742| | 743| 0| explicit directory_iterator(const directory_entry &de, std::error_code &ec) { 744| 0| State = new detail::DirIterState; 745| 0| ec = detail::directory_iterator_construct(*State, de.path()); 746| 0| } 747| | 748| | /// Construct end iterator. 749| 0| directory_iterator() : State(nullptr) {} 750| | 751| | // No operator++ because we need error_code. 752| 0| directory_iterator &increment(std::error_code &ec) { 753| 0| ec = directory_iterator_increment(*State); 754| 0| return *this; 755| 0| } 756| | 757| 0| const directory_entry &operator*() const { return State->CurrentEntry; } 758| 0| const directory_entry *operator->() const { return &State->CurrentEntry; } 759| | 760| 0| bool operator==(const directory_iterator &RHS) const { 761| 0| if (State == RHS.State) 762| 0| return true; 763| 0| if (!RHS.State) 764| 0| return State->CurrentEntry == directory_entry(); 765| 0| if (!State) 766| 0| return RHS.State->CurrentEntry == directory_entry(); 767| 0| return State->CurrentEntry == RHS.State->CurrentEntry; 768| 0| } 769| | 770| 0| bool operator!=(const directory_iterator &RHS) const { 771| 0| return !(*this == RHS); 772| 0| } 773| | // Other members as required by 774| | // C++ Std, 24.1.1 Input iterators [input.iterators] 775| |}; 776| | 777| |namespace detail { 778| | /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 779| | /// reference counted in order to preserve InputIterator semantics on copy. 780| | struct RecDirIterState : public RefCountedBase { 781| | RecDirIterState() 782| | : Level(0) 783| 0| , HasNoPushRequest(false) {} 784| | 785| | std::stack > Stack; 786| | uint16_t Level; 787| | bool HasNoPushRequest; 788| | }; 789| |} 790| | 791| |/// recursive_directory_iterator - Same as directory_iterator except for it 792| |/// recurses down into child directories. 793| |class recursive_directory_iterator { 794| | IntrusiveRefCntPtr State; 795| | 796| |public: 797| 0| recursive_directory_iterator() {} 798| | explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) 799| 0| : State(new detail::RecDirIterState) { 800| 0| State->Stack.push(directory_iterator(path, ec)); 801| 0| if (State->Stack.top() == directory_iterator()) 802| 0| State.reset(); 803| 0| } 804| | // No operator++ because we need error_code. 805| 0| recursive_directory_iterator &increment(std::error_code &ec) { 806| 0| const directory_iterator end_itr; 807| 0| 808| 0| if (State->HasNoPushRequest) 809| 0| State->HasNoPushRequest = false; 810| 0| else { 811| 0| file_status st; 812| 0| if ((ec = State->Stack.top()->status(st))) return *this; 813| 0| if (is_directory(st)) { 814| 0| State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 815| 0| if (ec) return *this; 816| 0| if (State->Stack.top() != end_itr) { 817| 0| ++State->Level; 818| 0| return *this; 819| 0| } 820| 0| State->Stack.pop(); 821| 0| } 822| 0| } 823| 0| 824| 0| while (!State->Stack.empty() 825| 0| && State->Stack.top().increment(ec) == end_itr) { 826| 0| State->Stack.pop(); 827| 0| --State->Level; 828| 0| } 829| 0| 830| 0| // Check if we are done. If so, create an end iterator. 831| 0| if (State->Stack.empty()) 832| 0| State.reset(); 833| 0| 834| 0| return *this; 835| 0| } 836| | 837| 0| const directory_entry &operator*() const { return *State->Stack.top(); } 838| 0| const directory_entry *operator->() const { return &*State->Stack.top(); } 839| | 840| | // observers 841| | /// Gets the current level. Starting path is at level 0. 842| 0| int level() const { return State->Level; } 843| | 844| | /// Returns true if no_push has been called for this directory_entry. 845| 0| bool no_push_request() const { return State->HasNoPushRequest; } 846| | 847| | // modifiers 848| | /// Goes up one level if Level > 0. 849| 0| void pop() { 850| 0| assert(State && "Cannot pop an end iterator!"); 851| 0| assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 852| 0| 853| 0| const directory_iterator end_itr; 854| 0| std::error_code ec; 855| 0| do { 856| 0| if (ec) 857| 0| report_fatal_error("Error incrementing directory iterator."); 858| 0| State->Stack.pop(); 859| 0| --State->Level; 860| 0| } while (!State->Stack.empty() 861| 0| && State->Stack.top().increment(ec) == end_itr); 862| 0| 863| 0| // Check if we are done. If so, create an end iterator. 864| 0| if (State->Stack.empty()) 865| 0| State.reset(); 866| 0| } 867| | 868| | /// Does not go down into the current directory_entry. 869| 0| void no_push() { State->HasNoPushRequest = true; } 870| | 871| 0| bool operator==(const recursive_directory_iterator &RHS) const { 872| 0| return State == RHS.State; 873| 0| } 874| | 875| 0| bool operator!=(const recursive_directory_iterator &RHS) const { 876| 0| return !(*this == RHS); 877| 0| } 878| | // Other members as required by 879| | // C++ Std, 24.1.1 Input iterators [input.iterators] 880| |}; 881| | 882| |/// @} 883| | 884| |} // end namespace fs 885| |} // end namespace sys 886| |} // end namespace llvm 887| | 888| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Format.h: 1| |//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the format() function, which can be used with other 11| |// LLVM subsystems to provide printf-style formatting. This gives all the power 12| |// and risk of printf. This can be used like this (with raw_ostreams as an 13| |// example): 14| |// 15| |// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; 16| |// 17| |// Or if you prefer: 18| |// 19| |// OS << format("mynumber: %4.5f\n", 1234.412); 20| |// 21| |//===----------------------------------------------------------------------===// 22| | 23| |#ifndef LLVM_SUPPORT_FORMAT_H 24| |#define LLVM_SUPPORT_FORMAT_H 25| | 26| |#include "llvm/ADT/STLExtras.h" 27| |#include "llvm/ADT/StringRef.h" 28| |#include "llvm/Support/DataTypes.h" 29| |#include 30| |#include 31| |#include 32| | 33| |namespace llvm { 34| | 35| |/// This is a helper class used for handling formatted output. It is the 36| |/// abstract base class of a templated derived class. 37| |class format_object_base { 38| |protected: 39| | const char *Fmt; 40| | ~format_object_base() = default; // Disallow polymorphic deletion. 41| | format_object_base(const format_object_base &) = default; 42| | virtual void home(); // Out of line virtual method. 43| | 44| | /// Call snprintf() for this object, on the given buffer and size. 45| | virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; 46| | 47| |public: 48| 0| format_object_base(const char *fmt) : Fmt(fmt) {} 49| | 50| | /// Format the object into the specified buffer. On success, this returns 51| | /// the length of the formatted string. If the buffer is too small, this 52| | /// returns a length to retry with, which will be larger than BufferSize. 53| | unsigned print(char *Buffer, unsigned BufferSize) const { 54| | assert(BufferSize && "Invalid buffer size!"); 55| | 56| | // Print the string, leaving room for the terminating null. 57| | int N = snprint(Buffer, BufferSize); 58| | 59| | // VC++ and old GlibC return negative on overflow, just double the size. 60| | if (N < 0) 61| | return BufferSize * 2; 62| | 63| | // Other implementations yield number of bytes needed, not including the 64| | // final '\0'. 65| | if (unsigned(N) >= BufferSize) 66| | return N + 1; 67| | 68| | // Otherwise N is the length of output (not including the final '\0'). 69| | return N; 70| | } 71| |}; 72| | 73| |/// These are templated helper classes used by the format function that 74| |/// capture the object to be formated and the format string. When actually 75| |/// printed, this synthesizes the string into a temporary buffer provided and 76| |/// returns whether or not it is big enough. 77| | 78| |template 79| |class format_object final : public format_object_base { 80| | std::tuple Vals; 81| | 82| | template 83| | int snprint_tuple(char *Buffer, unsigned BufferSize, 84| 0| index_sequence) const { 85| |#ifdef _MSC_VER 86| | return _snprintf(Buffer, BufferSize, Fmt, std::get(Vals)...); 87| |#else 88| | return snprintf(Buffer, BufferSize, Fmt, std::get(Vals)...); 89| 0|#endif 90| 0| } 91| | 92| |public: 93| | format_object(const char *fmt, const Ts &... vals) 94| 0| : format_object_base(fmt), Vals(vals...) {} 95| | 96| 0| int snprint(char *Buffer, unsigned BufferSize) const override { 97| 0| return snprint_tuple(Buffer, BufferSize, index_sequence_for()); 98| 0| } 99| |}; 100| | 101| |/// These are helper functions used to produce formatted output. They use 102| |/// template type deduction to construct the appropriate instance of the 103| |/// format_object class to simplify their construction. 104| |/// 105| |/// This is typically used like: 106| |/// \code 107| |/// OS << format("%0.4f", myfloat) << '\n'; 108| |/// \endcode 109| | 110| |template 111| 0|inline format_object format(const char *Fmt, const Ts &... Vals) { 112| 0| return format_object(Fmt, Vals...); 113| 0|} 114| | 115| |/// This is a helper class used for left_justify() and right_justify(). 116| |class FormattedString { 117| | StringRef Str; 118| | unsigned Width; 119| | bool RightJustify; 120| | friend class raw_ostream; 121| |public: 122| | FormattedString(StringRef S, unsigned W, bool R) 123| 0| : Str(S), Width(W), RightJustify(R) { } 124| |}; 125| | 126| |/// left_justify - append spaces after string so total output is 127| |/// \p Width characters. If \p Str is larger that \p Width, full string 128| |/// is written with no padding. 129| 0|inline FormattedString left_justify(StringRef Str, unsigned Width) { 130| 0| return FormattedString(Str, Width, false); 131| 0|} 132| | 133| |/// right_justify - add spaces before string so total output is 134| |/// \p Width characters. If \p Str is larger that \p Width, full string 135| |/// is written with no padding. 136| 0|inline FormattedString right_justify(StringRef Str, unsigned Width) { 137| 0| return FormattedString(Str, Width, true); 138| 0|} 139| | 140| |/// This is a helper class used for format_hex() and format_decimal(). 141| |class FormattedNumber { 142| | uint64_t HexValue; 143| | int64_t DecValue; 144| | unsigned Width; 145| | bool Hex; 146| | bool Upper; 147| | bool HexPrefix; 148| | friend class raw_ostream; 149| |public: 150| | FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, 151| | bool Prefix) 152| | : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), 153| 0| HexPrefix(Prefix) {} 154| |}; 155| | 156| |/// format_hex - Output \p N as a fixed width hexadecimal. If number will not 157| |/// fit in width, full number is still printed. Examples: 158| |/// OS << format_hex(255, 4) => 0xff 159| |/// OS << format_hex(255, 4, true) => 0xFF 160| |/// OS << format_hex(255, 6) => 0x00ff 161| |/// OS << format_hex(255, 2) => 0xff 162| |inline FormattedNumber format_hex(uint64_t N, unsigned Width, 163| 0| bool Upper = false) { 164| 0| assert(Width <= 18 && "hex width must be <= 18"); 165| 0| return FormattedNumber(N, 0, Width, true, Upper, true); 166| 0|} 167| | 168| |/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not 169| |/// prepend '0x' to the outputted string. If number will not fit in width, 170| |/// full number is still printed. Examples: 171| |/// OS << format_hex_no_prefix(255, 4) => ff 172| |/// OS << format_hex_no_prefix(255, 4, true) => FF 173| |/// OS << format_hex_no_prefix(255, 6) => 00ff 174| |/// OS << format_hex_no_prefix(255, 2) => ff 175| |inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, 176| 0| bool Upper = false) { 177| 0| assert(Width <= 18 && "hex width must be <= 18"); 178| 0| return FormattedNumber(N, 0, Width, true, Upper, false); 179| 0|} 180| | 181| |/// format_decimal - Output \p N as a right justified, fixed-width decimal. If 182| |/// number will not fit in width, full number is still printed. Examples: 183| |/// OS << format_decimal(0, 5) => " 0" 184| |/// OS << format_decimal(255, 5) => " 255" 185| |/// OS << format_decimal(-1, 3) => " -1" 186| |/// OS << format_decimal(12345, 3) => "12345" 187| 0|inline FormattedNumber format_decimal(int64_t N, unsigned Width) { 188| 0| return FormattedNumber(0, N, Width, false, false, false); 189| 0|} 190| | 191| | 192| |} // end namespace llvm 193| | 194| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MathExtras.h: 1| |//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful for math stuff. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MATHEXTRAS_H 15| |#define LLVM_SUPPORT_MATHEXTRAS_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/SwapByteOrder.h" 19| |#include 20| |#include 21| |#include 22| | 23| |#ifdef _MSC_VER 24| |#include 25| |#endif 26| | 27| |namespace llvm { 28| |/// \brief The behavior an operation has on an input of 0. 29| |enum ZeroBehavior { 30| | /// \brief The returned value is undefined. 31| | ZB_Undefined, 32| | /// \brief The returned value is numeric_limits::max() 33| | ZB_Max, 34| | /// \brief The returned value is numeric_limits::digits 35| | ZB_Width 36| |}; 37| | 38| |namespace detail { 39| |template struct TrailingZerosCounter { 40| | static std::size_t count(T Val, ZeroBehavior) { 41| | if (!Val) 42| | return std::numeric_limits::digits; 43| | if (Val & 0x1) 44| | return 0; 45| | 46| | // Bisection method. 47| | std::size_t ZeroBits = 0; 48| | T Shift = std::numeric_limits::digits >> 1; 49| | T Mask = std::numeric_limits::max() >> Shift; 50| | while (Shift) { 51| | if ((Val & Mask) == 0) { 52| | Val >>= Shift; 53| | ZeroBits |= Shift; 54| | } 55| | Shift >>= 1; 56| | Mask >>= Shift; 57| | } 58| | return ZeroBits; 59| | } 60| |}; 61| | 62| |#if __GNUC__ >= 4 || _MSC_VER 63| |template struct TrailingZerosCounter { 64| | static std::size_t count(T Val, ZeroBehavior ZB) { 65| | if (ZB != ZB_Undefined && Val == 0) 66| | return 32; 67| | 68| |#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) 69| | return __builtin_ctz(Val); 70| |#elif _MSC_VER 71| | unsigned long Index; 72| | _BitScanForward(&Index, Val); 73| | return Index; 74| |#endif 75| | } 76| |}; 77| | 78| |#if !defined(_MSC_VER) || defined(_M_X64) 79| |template struct TrailingZerosCounter { 80| | static std::size_t count(T Val, ZeroBehavior ZB) { 81| | if (ZB != ZB_Undefined && Val == 0) 82| | return 64; 83| | 84| |#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) 85| | return __builtin_ctzll(Val); 86| |#elif _MSC_VER 87| | unsigned long Index; 88| | _BitScanForward64(&Index, Val); 89| | return Index; 90| |#endif 91| | } 92| |}; 93| |#endif 94| |#endif 95| |} // namespace detail 96| | 97| |/// \brief Count number of 0's from the least significant bit to the most 98| |/// stopping at the first 1. 99| |/// 100| |/// Only unsigned integral types are allowed. 101| |/// 102| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 103| |/// valid arguments. 104| |template 105| |std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 106| | static_assert(std::numeric_limits::is_integer && 107| | !std::numeric_limits::is_signed, 108| | "Only unsigned integral types are allowed."); 109| | return detail::TrailingZerosCounter::count(Val, ZB); 110| |} 111| | 112| |namespace detail { 113| |template struct LeadingZerosCounter { 114| | static std::size_t count(T Val, ZeroBehavior) { 115| | if (!Val) 116| | return std::numeric_limits::digits; 117| | 118| | // Bisection method. 119| | std::size_t ZeroBits = 0; 120| | for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) { 121| | T Tmp = Val >> Shift; 122| | if (Tmp) 123| | Val = Tmp; 124| | else 125| | ZeroBits |= Shift; 126| | } 127| | return ZeroBits; 128| | } 129| |}; 130| | 131| |#if __GNUC__ >= 4 || _MSC_VER 132| |template struct LeadingZerosCounter { 133| | static std::size_t count(T Val, ZeroBehavior ZB) { 134| | if (ZB != ZB_Undefined && Val == 0) 135| | return 32; 136| | 137| |#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) 138| | return __builtin_clz(Val); 139| |#elif _MSC_VER 140| | unsigned long Index; 141| | _BitScanReverse(&Index, Val); 142| | return Index ^ 31; 143| |#endif 144| | } 145| |}; 146| | 147| |#if !defined(_MSC_VER) || defined(_M_X64) 148| |template struct LeadingZerosCounter { 149| | static std::size_t count(T Val, ZeroBehavior ZB) { 150| | if (ZB != ZB_Undefined && Val == 0) 151| | return 64; 152| | 153| |#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) 154| | return __builtin_clzll(Val); 155| |#elif _MSC_VER 156| | unsigned long Index; 157| | _BitScanReverse64(&Index, Val); 158| | return Index ^ 63; 159| |#endif 160| | } 161| |}; 162| |#endif 163| |#endif 164| |} // namespace detail 165| | 166| |/// \brief Count number of 0's from the most significant bit to the least 167| |/// stopping at the first 1. 168| |/// 169| |/// Only unsigned integral types are allowed. 170| |/// 171| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 172| |/// valid arguments. 173| |template 174| |std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 175| | static_assert(std::numeric_limits::is_integer && 176| | !std::numeric_limits::is_signed, 177| | "Only unsigned integral types are allowed."); 178| | return detail::LeadingZerosCounter::count(Val, ZB); 179| |} 180| | 181| |/// \brief Get the index of the first set bit starting from the least 182| |/// significant bit. 183| |/// 184| |/// Only unsigned integral types are allowed. 185| |/// 186| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 187| |/// valid arguments. 188| |template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { 189| | if (ZB == ZB_Max && Val == 0) 190| | return std::numeric_limits::max(); 191| | 192| | return countTrailingZeros(Val, ZB_Undefined); 193| |} 194| | 195| |/// \brief Get the index of the last set bit starting from the least 196| |/// significant bit. 197| |/// 198| |/// Only unsigned integral types are allowed. 199| |/// 200| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 201| |/// valid arguments. 202| |template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { 203| | if (ZB == ZB_Max && Val == 0) 204| | return std::numeric_limits::max(); 205| | 206| | // Use ^ instead of - because both gcc and llvm can remove the associated ^ 207| | // in the __builtin_clz intrinsic on x86. 208| | return countLeadingZeros(Val, ZB_Undefined) ^ 209| | (std::numeric_limits::digits - 1); 210| |} 211| | 212| |/// \brief Macro compressed bit reversal table for 256 bits. 213| |/// 214| |/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable 215| |static const unsigned char BitReverseTable256[256] = { 216| |#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 217| |#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) 218| |#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) 219| | R6(0), R6(2), R6(1), R6(3) 220| |#undef R2 221| |#undef R4 222| |#undef R6 223| |}; 224| | 225| |/// \brief Reverse the bits in \p Val. 226| |template 227| |T reverseBits(T Val) { 228| | unsigned char in[sizeof(Val)]; 229| | unsigned char out[sizeof(Val)]; 230| | std::memcpy(in, &Val, sizeof(Val)); 231| | for (unsigned i = 0; i < sizeof(Val); ++i) 232| | out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; 233| | std::memcpy(&Val, out, sizeof(Val)); 234| | return Val; 235| |} 236| | 237| |// NOTE: The following support functions use the _32/_64 extensions instead of 238| |// type overloading so that signed and unsigned integers can be used without 239| |// ambiguity. 240| | 241| |/// Hi_32 - This function returns the high 32 bits of a 64 bit value. 242| 0|inline uint32_t Hi_32(uint64_t Value) { 243| 0| return static_cast(Value >> 32); 244| 0|} 245| | 246| |/// Lo_32 - This function returns the low 32 bits of a 64 bit value. 247| 0|inline uint32_t Lo_32(uint64_t Value) { 248| 0| return static_cast(Value); 249| 0|} 250| | 251| |/// Make_64 - This functions makes a 64-bit integer from a high / low pair of 252| |/// 32-bit integers. 253| 0|inline uint64_t Make_64(uint32_t High, uint32_t Low) { 254| 0| return ((uint64_t)High << 32) | (uint64_t)Low; 255| 0|} 256| | 257| |/// isInt - Checks if an integer fits into the given bit width. 258| |template 259| |inline bool isInt(int64_t x) { 260| | return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 261| |} 262| |// Template specializations to get better code for common cases. 263| |template<> 264| 0|inline bool isInt<8>(int64_t x) { 265| 0| return static_cast(x) == x; 266| 0|} 267| |template<> 268| 0|inline bool isInt<16>(int64_t x) { 269| 0| return static_cast(x) == x; 270| 0|} 271| |template<> 272| 0|inline bool isInt<32>(int64_t x) { 273| 0| return static_cast(x) == x; 274| 0|} 275| | 276| |/// isShiftedInt - Checks if a signed integer is an N bit number shifted 277| |/// left by S. 278| |template 279| |inline bool isShiftedInt(int64_t x) { 280| | return isInt(x) && (x % (1< 285| |inline bool isUInt(uint64_t x) { 286| | return N >= 64 || x < (UINT64_C(1)<<(N)); 287| |} 288| |// Template specializations to get better code for common cases. 289| |template<> 290| 0|inline bool isUInt<8>(uint64_t x) { 291| 0| return static_cast(x) == x; 292| 0|} 293| |template<> 294| 0|inline bool isUInt<16>(uint64_t x) { 295| 0| return static_cast(x) == x; 296| 0|} 297| |template<> 298| 0|inline bool isUInt<32>(uint64_t x) { 299| 0| return static_cast(x) == x; 300| 0|} 301| | 302| |/// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted 303| |/// left by S. 304| |template 305| |inline bool isShiftedUInt(uint64_t x) { 306| | return isUInt(x) && (x % (1<> (64 - N))); 313| 0|} 314| | 315| |/// isIntN - Checks if an signed integer fits into the given (dynamic) 316| |/// bit width. 317| 0|inline bool isIntN(unsigned N, int64_t x) { 318| 0| return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 319| 0|} 320| | 321| |/// isMask_32 - This function returns true if the argument is a sequence of ones 322| |/// starting at the least significant bit with the remainder zero (32 bit 323| |/// version). Ex. isMask_32(0x0000FFFFU) == true. 324| 0|inline bool isMask_32(uint32_t Value) { 325| 0| return Value && ((Value + 1) & Value) == 0; 326| 0|} 327| | 328| |/// isMask_64 - This function returns true if the argument is a sequence of ones 329| |/// starting at the least significant bit with the remainder zero (64 bit 330| |/// version). 331| 0|inline bool isMask_64(uint64_t Value) { 332| 0| return Value && ((Value + 1) & Value) == 0; 333| 0|} 334| | 335| |/// isShiftedMask_32 - This function returns true if the argument contains a 336| |/// sequence of ones with the remainder zero (32 bit version.) 337| |/// Ex. isShiftedMask_32(0x0000FF00U) == true. 338| 0|inline bool isShiftedMask_32(uint32_t Value) { 339| 0| return isMask_32((Value - 1) | Value); 340| 0|} 341| | 342| |/// isShiftedMask_64 - This function returns true if the argument contains a 343| |/// sequence of ones with the remainder zero (64 bit version.) 344| 0|inline bool isShiftedMask_64(uint64_t Value) { 345| 0| return isMask_64((Value - 1) | Value); 346| 0|} 347| | 348| |/// isPowerOf2_32 - This function returns true if the argument is a power of 349| |/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) 350| 0|inline bool isPowerOf2_32(uint32_t Value) { 351| 0| return Value && !(Value & (Value - 1)); 352| 0|} 353| | 354| |/// isPowerOf2_64 - This function returns true if the argument is a power of two 355| |/// > 0 (64 bit edition.) 356| |inline bool isPowerOf2_64(uint64_t Value) { 357| | return Value && !(Value & (Value - int64_t(1L))); 358| |} 359| | 360| |/// ByteSwap_16 - This function returns a byte-swapped representation of the 361| |/// 16-bit argument, Value. 362| 0|inline uint16_t ByteSwap_16(uint16_t Value) { 363| 0| return sys::SwapByteOrder_16(Value); 364| 0|} 365| | 366| |/// ByteSwap_32 - This function returns a byte-swapped representation of the 367| |/// 32-bit argument, Value. 368| 0|inline uint32_t ByteSwap_32(uint32_t Value) { 369| 0| return sys::SwapByteOrder_32(Value); 370| 0|} 371| | 372| |/// ByteSwap_64 - This function returns a byte-swapped representation of the 373| |/// 64-bit argument, Value. 374| 0|inline uint64_t ByteSwap_64(uint64_t Value) { 375| 0| return sys::SwapByteOrder_64(Value); 376| 0|} 377| | 378| |/// \brief Count the number of ones from the most significant bit to the first 379| |/// zero bit. 380| |/// 381| |/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. 382| |/// Only unsigned integral types are allowed. 383| |/// 384| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 385| |/// ZB_Undefined are valid arguments. 386| |template 387| |std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 388| | static_assert(std::numeric_limits::is_integer && 389| | !std::numeric_limits::is_signed, 390| | "Only unsigned integral types are allowed."); 391| | return countLeadingZeros(~Value, ZB); 392| |} 393| | 394| |/// \brief Count the number of ones from the least significant bit to the first 395| |/// zero bit. 396| |/// 397| |/// Ex. countTrailingOnes(0x00FF00FF) == 8. 398| |/// Only unsigned integral types are allowed. 399| |/// 400| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 401| |/// ZB_Undefined are valid arguments. 402| |template 403| |std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 404| | static_assert(std::numeric_limits::is_integer && 405| | !std::numeric_limits::is_signed, 406| | "Only unsigned integral types are allowed."); 407| | return countTrailingZeros(~Value, ZB); 408| |} 409| | 410| |namespace detail { 411| |template struct PopulationCounter { 412| | static unsigned count(T Value) { 413| | // Generic version, forward to 32 bits. 414| | static_assert(SizeOfT <= 4, "Not implemented!"); 415| |#if __GNUC__ >= 4 416| | return __builtin_popcount(Value); 417| |#else 418| | uint32_t v = Value; 419| | v = v - ((v >> 1) & 0x55555555); 420| | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 421| | return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 422| |#endif 423| | } 424| |}; 425| | 426| |template struct PopulationCounter { 427| | static unsigned count(T Value) { 428| |#if __GNUC__ >= 4 429| | return __builtin_popcountll(Value); 430| |#else 431| | uint64_t v = Value; 432| | v = v - ((v >> 1) & 0x5555555555555555ULL); 433| | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 434| | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 435| | return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); 436| |#endif 437| | } 438| |}; 439| |} // namespace detail 440| | 441| |/// \brief Count the number of set bits in a value. 442| |/// Ex. countPopulation(0xF000F000) = 8 443| |/// Returns 0 if the word is zero. 444| |template 445| |inline unsigned countPopulation(T Value) { 446| | static_assert(std::numeric_limits::is_integer && 447| | !std::numeric_limits::is_signed, 448| | "Only unsigned integral types are allowed."); 449| | return detail::PopulationCounter::count(Value); 450| |} 451| | 452| |/// Log2_32 - This function returns the floor log base 2 of the specified value, 453| |/// -1 if the value is zero. (32 bit edition.) 454| |/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 455| 0|inline unsigned Log2_32(uint32_t Value) { 456| 0| return 31 - countLeadingZeros(Value); 457| 0|} 458| | 459| |/// Log2_64 - This function returns the floor log base 2 of the specified value, 460| |/// -1 if the value is zero. (64 bit edition.) 461| 0|inline unsigned Log2_64(uint64_t Value) { 462| 0| return 63 - countLeadingZeros(Value); 463| 0|} 464| | 465| |/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified 466| |/// value, 32 if the value is zero. (32 bit edition). 467| |/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 468| |inline unsigned Log2_32_Ceil(uint32_t Value) { 469| | return 32 - countLeadingZeros(Value - 1); 470| |} 471| | 472| |/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified 473| |/// value, 64 if the value is zero. (64 bit edition.) 474| 0|inline unsigned Log2_64_Ceil(uint64_t Value) { 475| 0| return 64 - countLeadingZeros(Value - 1); 476| 0|} 477| | 478| |/// GreatestCommonDivisor64 - Return the greatest common divisor of the two 479| |/// values using Euclid's algorithm. 480| 0|inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { 481| 0| while (B) { 482| 0| uint64_t T = B; 483| 0| B = A % B; 484| 0| A = T; 485| 0| } 486| 0| return A; 487| 0|} 488| | 489| |/// BitsToDouble - This function takes a 64-bit integer and returns the bit 490| |/// equivalent double. 491| 0|inline double BitsToDouble(uint64_t Bits) { 492| 0| union { 493| 0| uint64_t L; 494| 0| double D; 495| 0| } T; 496| 0| T.L = Bits; 497| 0| return T.D; 498| 0|} 499| | 500| |/// BitsToFloat - This function takes a 32-bit integer and returns the bit 501| |/// equivalent float. 502| 0|inline float BitsToFloat(uint32_t Bits) { 503| 0| union { 504| 0| uint32_t I; 505| 0| float F; 506| 0| } T; 507| 0| T.I = Bits; 508| 0| return T.F; 509| 0|} 510| | 511| |/// DoubleToBits - This function takes a double and returns the bit 512| |/// equivalent 64-bit integer. Note that copying doubles around 513| |/// changes the bits of NaNs on some hosts, notably x86, so this 514| |/// routine cannot be used if these bits are needed. 515| 0|inline uint64_t DoubleToBits(double Double) { 516| 0| union { 517| 0| uint64_t L; 518| 0| double D; 519| 0| } T; 520| 0| T.D = Double; 521| 0| return T.L; 522| 0|} 523| | 524| |/// FloatToBits - This function takes a float and returns the bit 525| |/// equivalent 32-bit integer. Note that copying floats around 526| |/// changes the bits of NaNs on some hosts, notably x86, so this 527| |/// routine cannot be used if these bits are needed. 528| 0|inline uint32_t FloatToBits(float Float) { 529| 0| union { 530| 0| uint32_t I; 531| 0| float F; 532| 0| } T; 533| 0| T.F = Float; 534| 0| return T.I; 535| 0|} 536| | 537| |/// MinAlign - A and B are either alignments or offsets. Return the minimum 538| |/// alignment that may be assumed after adding the two together. 539| 0|inline uint64_t MinAlign(uint64_t A, uint64_t B) { 540| 0| // The largest power of 2 that divides both A and B. 541| 0| // 542| 0| // Replace "-Value" by "1+~Value" in the following commented code to avoid 543| 0| // MSVC warning C4146 544| 0| // return (A | B) & -(A | B); 545| 0| return (A | B) & (1 + ~(A | B)); 546| 0|} 547| | 548| |/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. 549| |/// 550| |/// Alignment should be a power of two. This method rounds up, so 551| |/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. 552| |inline uintptr_t alignAddr(void *Addr, size_t Alignment) { 553| | assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && 554| | "Alignment is not a power of two!"); 555| | 556| | assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); 557| | 558| | return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); 559| |} 560| | 561| |/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment 562| |/// bytes, rounding up. 563| |inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { 564| | return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; 565| |} 566| | 567| |/// NextPowerOf2 - Returns the next power of two (in 64-bits) 568| |/// that is strictly greater than A. Returns zero on overflow. 569| 0|inline uint64_t NextPowerOf2(uint64_t A) { 570| 0| A |= (A >> 1); 571| 0| A |= (A >> 2); 572| 0| A |= (A >> 4); 573| 0| A |= (A >> 8); 574| 0| A |= (A >> 16); 575| 0| A |= (A >> 32); 576| 0| return A + 1; 577| 0|} 578| | 579| |/// Returns the power of two which is less than or equal to the given value. 580| |/// Essentially, it is a floor operation across the domain of powers of two. 581| 0|inline uint64_t PowerOf2Floor(uint64_t A) { 582| 0| if (!A) return 0; 583| 0| return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); 584| 0|} 585| | 586| |/// Returns the next integer (mod 2**64) that is greater than or equal to 587| |/// \p Value and is a multiple of \p Align. \p Align must be non-zero. 588| |/// 589| |/// Examples: 590| |/// \code 591| |/// RoundUpToAlignment(5, 8) = 8 592| |/// RoundUpToAlignment(17, 8) = 24 593| |/// RoundUpToAlignment(~0LL, 8) = 0 594| |/// RoundUpToAlignment(321, 255) = 510 595| |/// \endcode 596| |inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { 597| | return (Value + Align - 1) / Align * Align; 598| |} 599| | 600| |/// Returns the offset to the next integer (mod 2**64) that is greater than 601| |/// or equal to \p Value and is a multiple of \p Align. \p Align must be 602| |/// non-zero. 603| 0|inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { 604| 0| return RoundUpToAlignment(Value, Align) - Value; 605| 0|} 606| | 607| |/// SignExtend32 - Sign extend B-bit number x to 32-bit int. 608| |/// Usage int32_t r = SignExtend32<5>(x); 609| |template inline int32_t SignExtend32(uint32_t x) { 610| | return int32_t(x << (32 - B)) >> (32 - B); 611| |} 612| | 613| |/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. 614| |/// Requires 0 < B <= 32. 615| 0|inline int32_t SignExtend32(uint32_t X, unsigned B) { 616| 0| return int32_t(X << (32 - B)) >> (32 - B); 617| 0|} 618| | 619| |/// SignExtend64 - Sign extend B-bit number x to 64-bit int. 620| |/// Usage int64_t r = SignExtend64<5>(x); 621| |template inline int64_t SignExtend64(uint64_t x) { 622| | return int64_t(x << (64 - B)) >> (64 - B); 623| |} 624| | 625| |/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. 626| |/// Requires 0 < B <= 64. 627| 0|inline int64_t SignExtend64(uint64_t X, unsigned B) { 628| 0| return int64_t(X << (64 - B)) >> (64 - B); 629| 0|} 630| | 631| |extern const float huge_valf; 632| |} // End llvm namespace 633| | 634| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Memory.h: 1| |//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Memory class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORY_H 15| |#define LLVM_SUPPORT_MEMORY_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| | /// This class encapsulates the notion of a memory block which has an address 25| | /// and a size. It is used by the Memory class (a friend) as the result of 26| | /// various memory allocation operations. 27| | /// @see Memory 28| | /// @brief Memory block abstraction. 29| | class MemoryBlock { 30| | public: 31| 0| MemoryBlock() : Address(nullptr), Size(0) { } 32| 0| MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } 33| | void *base() const { return Address; } 34| | size_t size() const { return Size; } 35| | private: 36| | void *Address; ///< Address of first byte of memory area 37| | size_t Size; ///< Size, in bytes of the memory area 38| | friend class Memory; 39| | }; 40| | 41| | /// This class provides various memory handling functions that manipulate 42| | /// MemoryBlock instances. 43| | /// @since 1.4 44| | /// @brief An abstraction for memory operations. 45| | class Memory { 46| | public: 47| | enum ProtectionFlags { 48| | MF_READ = 0x1000000, 49| | MF_WRITE = 0x2000000, 50| | MF_EXEC = 0x4000000 51| | }; 52| | 53| | /// This method allocates a block of memory that is suitable for loading 54| | /// dynamically generated code (e.g. JIT). An attempt to allocate 55| | /// \p NumBytes bytes of virtual memory is made. 56| | /// \p NearBlock may point to an existing allocation in which case 57| | /// an attempt is made to allocate more memory near the existing block. 58| | /// The actual allocated address is not guaranteed to be near the requested 59| | /// address. 60| | /// \p Flags is used to set the initial protection flags for the block 61| | /// of the memory. 62| | /// \p EC [out] returns an object describing any error that occurs. 63| | /// 64| | /// This method may allocate more than the number of bytes requested. The 65| | /// actual number of bytes allocated is indicated in the returned 66| | /// MemoryBlock. 67| | /// 68| | /// The start of the allocated block must be aligned with the 69| | /// system allocation granularity (64K on Windows, page size on Linux). 70| | /// If the address following \p NearBlock is not so aligned, it will be 71| | /// rounded up to the next allocation granularity boundary. 72| | /// 73| | /// \r a non-null MemoryBlock if the function was successful, 74| | /// otherwise a null MemoryBlock is with \p EC describing the error. 75| | /// 76| | /// @brief Allocate mapped memory. 77| | static MemoryBlock allocateMappedMemory(size_t NumBytes, 78| | const MemoryBlock *const NearBlock, 79| | unsigned Flags, 80| | std::error_code &EC); 81| | 82| | /// This method releases a block of memory that was allocated with the 83| | /// allocateMappedMemory method. It should not be used to release any 84| | /// memory block allocated any other way. 85| | /// \p Block describes the memory to be released. 86| | /// 87| | /// \r error_success if the function was successful, or an error_code 88| | /// describing the failure if an error occurred. 89| | /// 90| | /// @brief Release mapped memory. 91| | static std::error_code releaseMappedMemory(MemoryBlock &Block); 92| | 93| | /// This method sets the protection flags for a block of memory to the 94| | /// state specified by /p Flags. The behavior is not specified if the 95| | /// memory was not allocated using the allocateMappedMemory method. 96| | /// \p Block describes the memory block to be protected. 97| | /// \p Flags specifies the new protection state to be assigned to the block. 98| | /// \p ErrMsg [out] returns a string describing any error that occurred. 99| | /// 100| | /// If \p Flags is MF_WRITE, the actual behavior varies 101| | /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the 102| | /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 103| | /// 104| | /// \r error_success if the function was successful, or an error_code 105| | /// describing the failure if an error occurred. 106| | /// 107| | /// @brief Set memory protection state. 108| | static std::error_code protectMappedMemory(const MemoryBlock &Block, 109| | unsigned Flags); 110| | 111| | /// This method allocates a block of Read/Write/Execute memory that is 112| | /// suitable for executing dynamically generated code (e.g. JIT). An 113| | /// attempt to allocate \p NumBytes bytes of virtual memory is made. 114| | /// \p NearBlock may point to an existing allocation in which case 115| | /// an attempt is made to allocate more memory near the existing block. 116| | /// 117| | /// On success, this returns a non-null memory block, otherwise it returns 118| | /// a null memory block and fills in *ErrMsg. 119| | /// 120| | /// @brief Allocate Read/Write/Execute memory. 121| | static MemoryBlock AllocateRWX(size_t NumBytes, 122| | const MemoryBlock *NearBlock, 123| | std::string *ErrMsg = nullptr); 124| | 125| | /// This method releases a block of Read/Write/Execute memory that was 126| | /// allocated with the AllocateRWX method. It should not be used to 127| | /// release any memory block allocated any other way. 128| | /// 129| | /// On success, this returns false, otherwise it returns true and fills 130| | /// in *ErrMsg. 131| | /// @brief Release Read/Write/Execute memory. 132| | static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); 133| | 134| | 135| | /// InvalidateInstructionCache - Before the JIT can run a block of code 136| | /// that has been emitted it must invalidate the instruction cache on some 137| | /// platforms. 138| | static void InvalidateInstructionCache(const void *Addr, size_t Len); 139| | 140| | /// setExecutable - Before the JIT can run a block of code, it has to be 141| | /// given read and executable privilege. Return true if it is already r-x 142| | /// or the system is able to change its previlege. 143| | static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); 144| | 145| | /// setWritable - When adding to a block of code, the JIT may need 146| | /// to mark a block of code as RW since the protections are on page 147| | /// boundaries, and the JIT internal allocations are not page aligned. 148| | static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); 149| | 150| | /// setRangeExecutable - Mark the page containing a range of addresses 151| | /// as executable. 152| | static bool setRangeExecutable(const void *Addr, size_t Size); 153| | 154| | /// setRangeWritable - Mark the page containing a range of addresses 155| | /// as writable. 156| | static bool setRangeWritable(const void *Addr, size_t Size); 157| | }; 158| |} 159| |} 160| | 161| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MemoryBuffer.h: 1| |//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the MemoryBuffer interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORYBUFFER_H 15| |#define LLVM_SUPPORT_MEMORYBUFFER_H 16| | 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/Support/CBindingWrapping.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include "llvm/Support/ErrorOr.h" 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |class MemoryBufferRef; 27| | 28| |/// This interface provides simple read-only access to a block of memory, and 29| |/// provides simple methods for reading files and standard input into a memory 30| |/// buffer. In addition to basic access to the characters in the file, this 31| |/// interface guarantees you can read one character past the end of the file, 32| |/// and that this character will read as '\0'. 33| |/// 34| |/// The '\0' guarantee is needed to support an optimization -- it's intended to 35| |/// be more efficient for clients which are reading all the data to stop 36| |/// reading when they encounter a '\0' than to continually check the file 37| |/// position to see if it has reached the end of the file. 38| |class MemoryBuffer { 39| | const char *BufferStart; // Start of the buffer. 40| | const char *BufferEnd; // End of the buffer. 41| | 42| | MemoryBuffer(const MemoryBuffer &) = delete; 43| | MemoryBuffer &operator=(const MemoryBuffer &) = delete; 44| |protected: 45| 0| MemoryBuffer() {} 46| | void init(const char *BufStart, const char *BufEnd, 47| | bool RequiresNullTerminator); 48| |public: 49| | virtual ~MemoryBuffer(); 50| | 51| 0| const char *getBufferStart() const { return BufferStart; } 52| | const char *getBufferEnd() const { return BufferEnd; } 53| 0| size_t getBufferSize() const { return BufferEnd-BufferStart; } 54| | 55| 0| StringRef getBuffer() const { 56| 0| return StringRef(BufferStart, getBufferSize()); 57| 0| } 58| | 59| | /// Return an identifier for this buffer, typically the filename it was read 60| | /// from. 61| | virtual const char *getBufferIdentifier() const { 62| | return "Unknown buffer"; 63| | } 64| | 65| | /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer 66| | /// if successful, otherwise returning null. If FileSize is specified, this 67| | /// means that the client knows that the file exists and that it has the 68| | /// specified size. 69| | /// 70| | /// \param IsVolatileSize Set to true to indicate that the file size may be 71| | /// changing, e.g. when libclang tries to parse while the user is 72| | /// editing/updating the file. 73| | static ErrorOr> 74| | getFile(const Twine &Filename, int64_t FileSize = -1, 75| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 76| | 77| | /// Given an already-open file descriptor, map some slice of it into a 78| | /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. 79| | /// Since this is in the middle of a file, the buffer is not null terminated. 80| | static ErrorOr> 81| | getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, 82| | int64_t Offset); 83| | 84| | /// Given an already-open file descriptor, read the file and return a 85| | /// MemoryBuffer. 86| | /// 87| | /// \param IsVolatileSize Set to true to indicate that the file size may be 88| | /// changing, e.g. when libclang tries to parse while the user is 89| | /// editing/updating the file. 90| | static ErrorOr> 91| | getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, 92| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 93| | 94| | /// Open the specified memory range as a MemoryBuffer. Note that InputData 95| | /// must be null terminated if RequiresNullTerminator is true. 96| | static std::unique_ptr 97| | getMemBuffer(StringRef InputData, StringRef BufferName = "", 98| | bool RequiresNullTerminator = true); 99| | 100| | static std::unique_ptr 101| | getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); 102| | 103| | /// Open the specified memory range as a MemoryBuffer, copying the contents 104| | /// and taking ownership of it. InputData does not have to be null terminated. 105| | static std::unique_ptr 106| | getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); 107| | 108| | /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note 109| | /// that the caller need not initialize the memory allocated by this method. 110| | /// The memory is owned by the MemoryBuffer object. 111| | static std::unique_ptr 112| | getNewMemBuffer(size_t Size, StringRef BufferName = ""); 113| | 114| | /// Allocate a new MemoryBuffer of the specified size that is not initialized. 115| | /// Note that the caller should initialize the memory allocated by this 116| | /// method. The memory is owned by the MemoryBuffer object. 117| | static std::unique_ptr 118| | getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); 119| | 120| | /// Read all of stdin into a file buffer, and return it. 121| | static ErrorOr> getSTDIN(); 122| | 123| | /// Open the specified file as a MemoryBuffer, or open stdin if the Filename 124| | /// is "-". 125| | static ErrorOr> 126| | getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1); 127| | 128| | /// Map a subrange of the the specified file as a MemoryBuffer. 129| | static ErrorOr> 130| | getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); 131| | 132| | //===--------------------------------------------------------------------===// 133| | // Provided for performance analysis. 134| | //===--------------------------------------------------------------------===// 135| | 136| | /// The kind of memory backing used to support the MemoryBuffer. 137| | enum BufferKind { 138| | MemoryBuffer_Malloc, 139| | MemoryBuffer_MMap 140| | }; 141| | 142| | /// Return information on the memory mechanism used to support the 143| | /// MemoryBuffer. 144| | virtual BufferKind getBufferKind() const = 0; 145| | 146| | MemoryBufferRef getMemBufferRef() const; 147| |}; 148| | 149| |class MemoryBufferRef { 150| | StringRef Buffer; 151| | StringRef Identifier; 152| | 153| |public: 154| 0| MemoryBufferRef() {} 155| | MemoryBufferRef(StringRef Buffer, StringRef Identifier) 156| 0| : Buffer(Buffer), Identifier(Identifier) {} 157| | 158| | StringRef getBuffer() const { return Buffer; } 159| | 160| | StringRef getBufferIdentifier() const { return Identifier; } 161| | 162| | const char *getBufferStart() const { return Buffer.begin(); } 163| | const char *getBufferEnd() const { return Buffer.end(); } 164| 0| size_t getBufferSize() const { return Buffer.size(); } 165| |}; 166| | 167| |// Create wrappers for C Binding types (see CBindingWrapping.h). 168| |typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; 169| |DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) 170| | 171| |} // end namespace llvm 172| | 173| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Path.h: 1| |//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::path namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_PATH_H 17| |#define LLVM_SUPPORT_PATH_H 18| | 19| |#include "llvm/ADT/SmallString.h" 20| |#include "llvm/ADT/Twine.h" 21| |#include "llvm/Support/DataTypes.h" 22| |#include 23| | 24| |namespace llvm { 25| |namespace sys { 26| |namespace path { 27| | 28| |/// @name Lexical Component Iterator 29| |/// @{ 30| | 31| |/// @brief Path iterator. 32| |/// 33| |/// This is an input iterator that iterates over the individual components in 34| |/// \a path. The traversal order is as follows: 35| |/// * The root-name element, if present. 36| |/// * The root-directory element, if present. 37| |/// * Each successive filename element, if present. 38| |/// * Dot, if one or more trailing non-root slash characters are present. 39| |/// Traversing backwards is possible with \a reverse_iterator 40| |/// 41| |/// Iteration examples. Each component is separated by ',': 42| |/// @code 43| |/// / => / 44| |/// /foo => /,foo 45| |/// foo/ => foo,. 46| |/// /foo/bar => /,foo,bar 47| |/// ../ => ..,. 48| |/// C:\foo\bar => C:,/,foo,bar 49| |/// @endcode 50| |class const_iterator 51| | : public std::iterator { 52| | StringRef Path; ///< The entire path. 53| | StringRef Component; ///< The current component. Not necessarily in Path. 54| | size_t Position; ///< The iterators current position within Path. 55| | 56| | // An end iterator has Position = Path.size() + 1. 57| | friend const_iterator begin(StringRef path); 58| | friend const_iterator end(StringRef path); 59| | 60| |public: 61| | reference operator*() const { return Component; } 62| | pointer operator->() const { return &Component; } 63| | const_iterator &operator++(); // preincrement 64| | const_iterator &operator++(int); // postincrement 65| | bool operator==(const const_iterator &RHS) const; 66| | bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); } 67| | 68| | /// @brief Difference in bytes between this and RHS. 69| | ptrdiff_t operator-(const const_iterator &RHS) const; 70| |}; 71| | 72| |/// @brief Reverse path iterator. 73| |/// 74| |/// This is an input iterator that iterates over the individual components in 75| |/// \a path in reverse order. The traversal order is exactly reversed from that 76| |/// of \a const_iterator 77| |class reverse_iterator 78| | : public std::iterator { 79| | StringRef Path; ///< The entire path. 80| | StringRef Component; ///< The current component. Not necessarily in Path. 81| | size_t Position; ///< The iterators current position within Path. 82| | 83| | friend reverse_iterator rbegin(StringRef path); 84| | friend reverse_iterator rend(StringRef path); 85| | 86| |public: 87| | reference operator*() const { return Component; } 88| 0| pointer operator->() const { return &Component; } 89| | reverse_iterator &operator++(); // preincrement 90| | reverse_iterator &operator++(int); // postincrement 91| | bool operator==(const reverse_iterator &RHS) const; 92| 0| bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } 93| |}; 94| | 95| |/// @brief Get begin iterator over \a path. 96| |/// @param path Input path. 97| |/// @returns Iterator initialized with the first component of \a path. 98| |const_iterator begin(StringRef path); 99| | 100| |/// @brief Get end iterator over \a path. 101| |/// @param path Input path. 102| |/// @returns Iterator initialized to the end of \a path. 103| |const_iterator end(StringRef path); 104| | 105| |/// @brief Get reverse begin iterator over \a path. 106| |/// @param path Input path. 107| |/// @returns Iterator initialized with the first reverse component of \a path. 108| |reverse_iterator rbegin(StringRef path); 109| | 110| |/// @brief Get reverse end iterator over \a path. 111| |/// @param path Input path. 112| |/// @returns Iterator initialized to the reverse end of \a path. 113| |reverse_iterator rend(StringRef path); 114| | 115| |/// @} 116| |/// @name Lexical Modifiers 117| |/// @{ 118| | 119| |/// @brief Remove the last component from \a path unless it is the root dir. 120| |/// 121| |/// @code 122| |/// directory/filename.cpp => directory/ 123| |/// directory/ => directory 124| |/// filename.cpp => 125| |/// / => / 126| |/// @endcode 127| |/// 128| |/// @param path A path that is modified to not have a file component. 129| |void remove_filename(SmallVectorImpl &path); 130| | 131| |/// @brief Replace the file extension of \a path with \a extension. 132| |/// 133| |/// @code 134| |/// ./filename.cpp => ./filename.extension 135| |/// ./filename => ./filename.extension 136| |/// ./ => ./.extension 137| |/// @endcode 138| |/// 139| |/// @param path A path that has its extension replaced with \a extension. 140| |/// @param extension The extension to be added. It may be empty. It may also 141| |/// optionally start with a '.', if it does not, one will be 142| |/// prepended. 143| |void replace_extension(SmallVectorImpl &path, const Twine &extension); 144| | 145| |/// @brief Append to path. 146| |/// 147| |/// @code 148| |/// /foo + bar/f => /foo/bar/f 149| |/// /foo/ + bar/f => /foo/bar/f 150| |/// foo + bar/f => foo/bar/f 151| |/// @endcode 152| |/// 153| |/// @param path Set to \a path + \a component. 154| |/// @param a The component to be appended to \a path. 155| |void append(SmallVectorImpl &path, const Twine &a, 156| | const Twine &b = "", 157| | const Twine &c = "", 158| | const Twine &d = ""); 159| | 160| |/// @brief Append to path. 161| |/// 162| |/// @code 163| |/// /foo + [bar,f] => /foo/bar/f 164| |/// /foo/ + [bar,f] => /foo/bar/f 165| |/// foo + [bar,f] => foo/bar/f 166| |/// @endcode 167| |/// 168| |/// @param path Set to \a path + [\a begin, \a end). 169| |/// @param begin Start of components to append. 170| |/// @param end One past the end of components to append. 171| |void append(SmallVectorImpl &path, 172| | const_iterator begin, const_iterator end); 173| | 174| |/// @} 175| |/// @name Transforms (or some other better name) 176| |/// @{ 177| | 178| |/// Convert path to the native form. This is used to give paths to users and 179| |/// operating system calls in the platform's normal way. For example, on Windows 180| |/// all '/' are converted to '\'. 181| |/// 182| |/// @param path A path that is transformed to native format. 183| |/// @param result Holds the result of the transformation. 184| |void native(const Twine &path, SmallVectorImpl &result); 185| | 186| |/// Convert path to the native form in place. This is used to give paths to 187| |/// users and operating system calls in the platform's normal way. For example, 188| |/// on Windows all '/' are converted to '\'. 189| |/// 190| |/// @param path A path that is transformed to native format. 191| |void native(SmallVectorImpl &path); 192| | 193| |/// @} 194| |/// @name Lexical Observers 195| |/// @{ 196| | 197| |/// @brief Get root name. 198| |/// 199| |/// @code 200| |/// //net/hello => //net 201| |/// c:/hello => c: (on Windows, on other platforms nothing) 202| |/// /hello => 203| |/// @endcode 204| |/// 205| |/// @param path Input path. 206| |/// @result The root name of \a path if it has one, otherwise "". 207| |StringRef root_name(StringRef path); 208| | 209| |/// @brief Get root directory. 210| |/// 211| |/// @code 212| |/// /goo/hello => / 213| |/// c:/hello => / 214| |/// d/file.txt => 215| |/// @endcode 216| |/// 217| |/// @param path Input path. 218| |/// @result The root directory of \a path if it has one, otherwise 219| |/// "". 220| |StringRef root_directory(StringRef path); 221| | 222| |/// @brief Get root path. 223| |/// 224| |/// Equivalent to root_name + root_directory. 225| |/// 226| |/// @param path Input path. 227| |/// @result The root path of \a path if it has one, otherwise "". 228| |StringRef root_path(StringRef path); 229| | 230| |/// @brief Get relative path. 231| |/// 232| |/// @code 233| |/// C:\hello\world => hello\world 234| |/// foo/bar => foo/bar 235| |/// /foo/bar => foo/bar 236| |/// @endcode 237| |/// 238| |/// @param path Input path. 239| |/// @result The path starting after root_path if one exists, otherwise "". 240| |StringRef relative_path(StringRef path); 241| | 242| |/// @brief Get parent path. 243| |/// 244| |/// @code 245| |/// / => 246| |/// /foo => / 247| |/// foo/../bar => foo/.. 248| |/// @endcode 249| |/// 250| |/// @param path Input path. 251| |/// @result The parent path of \a path if one exists, otherwise "". 252| |StringRef parent_path(StringRef path); 253| | 254| |/// @brief Get filename. 255| |/// 256| |/// @code 257| |/// /foo.txt => foo.txt 258| |/// . => . 259| |/// .. => .. 260| |/// / => / 261| |/// @endcode 262| |/// 263| |/// @param path Input path. 264| |/// @result The filename part of \a path. This is defined as the last component 265| |/// of \a path. 266| |StringRef filename(StringRef path); 267| | 268| |/// @brief Get stem. 269| |/// 270| |/// If filename contains a dot but not solely one or two dots, result is the 271| |/// substring of filename ending at (but not including) the last dot. Otherwise 272| |/// it is filename. 273| |/// 274| |/// @code 275| |/// /foo/bar.txt => bar 276| |/// /foo/bar => bar 277| |/// /foo/.txt => 278| |/// /foo/. => . 279| |/// /foo/.. => .. 280| |/// @endcode 281| |/// 282| |/// @param path Input path. 283| |/// @result The stem of \a path. 284| |StringRef stem(StringRef path); 285| | 286| |/// @brief Get extension. 287| |/// 288| |/// If filename contains a dot but not solely one or two dots, result is the 289| |/// substring of filename starting at (and including) the last dot, and ending 290| |/// at the end of \a path. Otherwise "". 291| |/// 292| |/// @code 293| |/// /foo/bar.txt => .txt 294| |/// /foo/bar => 295| |/// /foo/.txt => .txt 296| |/// @endcode 297| |/// 298| |/// @param path Input path. 299| |/// @result The extension of \a path. 300| |StringRef extension(StringRef path); 301| | 302| |/// @brief Check whether the given char is a path separator on the host OS. 303| |/// 304| |/// @param value a character 305| |/// @result true if \a value is a path separator character on the host OS 306| |bool is_separator(char value); 307| | 308| |/// @brief Return the preferred separator for this platform. 309| |/// 310| |/// @result StringRef of the preferred separator, null-terminated. 311| |StringRef get_separator(); 312| | 313| |/// @brief Get the typical temporary directory for the system, e.g., 314| |/// "/var/tmp" or "C:/TEMP" 315| |/// 316| |/// @param erasedOnReboot Whether to favor a path that is erased on reboot 317| |/// rather than one that potentially persists longer. This parameter will be 318| |/// ignored if the user or system has set the typical environment variable 319| |/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. 320| |/// 321| |/// @param result Holds the resulting path name. 322| |void system_temp_directory(bool erasedOnReboot, SmallVectorImpl &result); 323| | 324| |/// @brief Get the user's home directory. 325| |/// 326| |/// @param result Holds the resulting path name. 327| |/// @result True if a home directory is set, false otherwise. 328| |bool home_directory(SmallVectorImpl &result); 329| | 330| |/// @brief Has root name? 331| |/// 332| |/// root_name != "" 333| |/// 334| |/// @param path Input path. 335| |/// @result True if the path has a root name, false otherwise. 336| |bool has_root_name(const Twine &path); 337| | 338| |/// @brief Has root directory? 339| |/// 340| |/// root_directory != "" 341| |/// 342| |/// @param path Input path. 343| |/// @result True if the path has a root directory, false otherwise. 344| |bool has_root_directory(const Twine &path); 345| | 346| |/// @brief Has root path? 347| |/// 348| |/// root_path != "" 349| |/// 350| |/// @param path Input path. 351| |/// @result True if the path has a root path, false otherwise. 352| |bool has_root_path(const Twine &path); 353| | 354| |/// @brief Has relative path? 355| |/// 356| |/// relative_path != "" 357| |/// 358| |/// @param path Input path. 359| |/// @result True if the path has a relative path, false otherwise. 360| |bool has_relative_path(const Twine &path); 361| | 362| |/// @brief Has parent path? 363| |/// 364| |/// parent_path != "" 365| |/// 366| |/// @param path Input path. 367| |/// @result True if the path has a parent path, false otherwise. 368| |bool has_parent_path(const Twine &path); 369| | 370| |/// @brief Has filename? 371| |/// 372| |/// filename != "" 373| |/// 374| |/// @param path Input path. 375| |/// @result True if the path has a filename, false otherwise. 376| |bool has_filename(const Twine &path); 377| | 378| |/// @brief Has stem? 379| |/// 380| |/// stem != "" 381| |/// 382| |/// @param path Input path. 383| |/// @result True if the path has a stem, false otherwise. 384| |bool has_stem(const Twine &path); 385| | 386| |/// @brief Has extension? 387| |/// 388| |/// extension != "" 389| |/// 390| |/// @param path Input path. 391| |/// @result True if the path has a extension, false otherwise. 392| |bool has_extension(const Twine &path); 393| | 394| |/// @brief Is path absolute? 395| |/// 396| |/// @param path Input path. 397| |/// @result True if the path is absolute, false if it is not. 398| |bool is_absolute(const Twine &path); 399| | 400| |/// @brief Is path relative? 401| |/// 402| |/// @param path Input path. 403| |/// @result True if the path is relative, false if it is not. 404| |bool is_relative(const Twine &path); 405| | 406| |} // end namespace path 407| |} // end namespace sys 408| |} // end namespace llvm 409| | 410| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/PointerLikeTypeTraits.h: 1| |//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the PointerLikeTypeTraits class. This allows data 11| |// structures to reason about pointers and other things that are pointer sized. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 16| |#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 17| | 18| |#include "llvm/Support/DataTypes.h" 19| | 20| |namespace llvm { 21| | 22| |/// PointerLikeTypeTraits - This is a traits object that is used to handle 23| |/// pointer types and things that are just wrappers for pointers as a uniform 24| |/// entity. 25| |template 26| |class PointerLikeTypeTraits { 27| | // getAsVoidPointer 28| | // getFromVoidPointer 29| | // getNumLowBitsAvailable 30| |}; 31| | 32| |// Provide PointerLikeTypeTraits for non-cvr pointers. 33| |template 34| |class PointerLikeTypeTraits { 35| |public: 36| 0| static inline void *getAsVoidPointer(T* P) { return P; } 37| 0| static inline T *getFromVoidPointer(void *P) { 38| 0| return static_cast(P); 39| 0| } 40| | 41| | /// Note, we assume here that malloc returns objects at least 4-byte aligned. 42| | /// However, this may be wrong, or pointers may be from something other than 43| | /// malloc. In this case, you should specialize this template to reduce this. 44| | /// 45| | /// All clients should use assertions to do a run-time check to ensure that 46| | /// this is actually true. 47| | enum { NumLowBitsAvailable = 2 }; 48| |}; 49| | 50| |// Provide PointerLikeTypeTraits for const pointers. 51| |template 52| |class PointerLikeTypeTraits { 53| | typedef PointerLikeTypeTraits NonConst; 54| | 55| |public: 56| | static inline const void *getAsVoidPointer(const T* P) { 57| | return NonConst::getAsVoidPointer(const_cast(P)); 58| | } 59| | static inline const T *getFromVoidPointer(const void *P) { 60| | return NonConst::getFromVoidPointer(const_cast(P)); 61| | } 62| | enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; 63| |}; 64| | 65| |// Provide PointerLikeTypeTraits for uintptr_t. 66| |template<> 67| |class PointerLikeTypeTraits { 68| |public: 69| 0| static inline void *getAsVoidPointer(uintptr_t P) { 70| 0| return reinterpret_cast(P); 71| 0| } 72| 0| static inline uintptr_t getFromVoidPointer(void *P) { 73| 0| return reinterpret_cast(P); 74| 0| } 75| | // No bits are available! 76| | enum { NumLowBitsAvailable = 0 }; 77| |}; 78| | 79| |} // end namespace llvm 80| | 81| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SMLoc.h: 1| |//===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMLoc class. This class encapsulates a location in 11| |// source code for use in diagnostics. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SMLOC_H 16| |#define LLVM_SUPPORT_SMLOC_H 17| | 18| |#include 19| | 20| |namespace llvm { 21| | 22| |/// Represents a location in source code. 23| |class SMLoc { 24| | const char *Ptr; 25| |public: 26| 0| SMLoc() : Ptr(nullptr) {} 27| | 28| 0| bool isValid() const { return Ptr != nullptr; } 29| | 30| | bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } 31| | bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } 32| | 33| 0| const char *getPointer() const { return Ptr; } 34| | 35| 0| static SMLoc getFromPointer(const char *Ptr) { 36| 0| SMLoc L; 37| 0| L.Ptr = Ptr; 38| 0| return L; 39| 0| } 40| |}; 41| | 42| |/// Represents a range in source code. 43| |/// 44| |/// SMRange is implemented using a half-open range, as is the convention in C++. 45| |/// In the string "abc", the range (1,3] represents the substring "bc", and the 46| |/// range (2,2] represents an empty range between the characters "b" and "c". 47| |class SMRange { 48| |public: 49| | SMLoc Start, End; 50| | 51| 0| SMRange() {} 52| | SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { 53| | assert(Start.isValid() == End.isValid() && 54| | "Start and end should either both be valid or both be invalid!"); 55| | } 56| | 57| | bool isValid() const { return Start.isValid(); } 58| |}; 59| | 60| |} // end namespace llvm 61| | 62| |#endif 63| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SourceMgr.h: 1| |//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMDiagnostic and SourceMgr classes. This 11| |// provides a simple substrate for diagnostics, #include handling, and other low 12| |// level things for simple parsers. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_SOURCEMGR_H 17| |#define LLVM_SUPPORT_SOURCEMGR_H 18| | 19| |#include "llvm/ADT/ArrayRef.h" 20| |#include "llvm/ADT/StringRef.h" 21| |#include "llvm/ADT/Twine.h" 22| |#include "llvm/Support/MemoryBuffer.h" 23| |#include "llvm/Support/SMLoc.h" 24| |#include 25| | 26| |namespace llvm { 27| | class SourceMgr; 28| | class SMDiagnostic; 29| | class SMFixIt; 30| | class Twine; 31| | class raw_ostream; 32| | 33| |/// This owns the files read by a parser, handles include stacks, 34| |/// and handles diagnostic wrangling. 35| |class SourceMgr { 36| |public: 37| | enum DiagKind { 38| | DK_Error, 39| | DK_Warning, 40| | DK_Note 41| | }; 42| | 43| | /// Clients that want to handle their own diagnostics in a custom way can 44| | /// register a function pointer+context as a diagnostic handler. 45| | /// It gets called each time PrintMessage is invoked. 46| | typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); 47| |private: 48| | struct SrcBuffer { 49| | /// The memory buffer for the file. 50| | std::unique_ptr Buffer; 51| | 52| | /// This is the location of the parent include, or null if at the top level. 53| | SMLoc IncludeLoc; 54| | 55| 0| SrcBuffer() {} 56| | 57| | SrcBuffer(SrcBuffer &&O) 58| 0| : Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {} 59| | }; 60| | 61| | /// This is all of the buffers that we are reading from. 62| | std::vector Buffers; 63| | 64| | // This is the list of directories we should search for include files in. 65| | std::vector IncludeDirectories; 66| | 67| | /// This is a cache for line number queries, its implementation is really 68| | /// private to SourceMgr.cpp. 69| | mutable void *LineNoCache; 70| | 71| | DiagHandlerTy DiagHandler; 72| | void *DiagContext; 73| | 74| | bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } 75| | 76| | SourceMgr(const SourceMgr&) = delete; 77| | void operator=(const SourceMgr&) = delete; 78| |public: 79| | SourceMgr() 80| 0| : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} 81| | ~SourceMgr(); 82| | 83| 0| void setIncludeDirs(const std::vector &Dirs) { 84| 0| IncludeDirectories = Dirs; 85| 0| } 86| | 87| | /// Specify a diagnostic handler to be invoked every time PrintMessage is 88| | /// called. \p Ctx is passed into the handler when it is invoked. 89| 0| void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { 90| 0| DiagHandler = DH; 91| 0| DiagContext = Ctx; 92| 0| } 93| | 94| 0| DiagHandlerTy getDiagHandler() const { return DiagHandler; } 95| 0| void *getDiagContext() const { return DiagContext; } 96| | 97| | const SrcBuffer &getBufferInfo(unsigned i) const { 98| | assert(isValidBufferID(i)); 99| | return Buffers[i - 1]; 100| | } 101| | 102| | const MemoryBuffer *getMemoryBuffer(unsigned i) const { 103| | assert(isValidBufferID(i)); 104| | return Buffers[i - 1].Buffer.get(); 105| | } 106| | 107| 0| unsigned getNumBuffers() const { 108| 0| return Buffers.size(); 109| 0| } 110| | 111| 0| unsigned getMainFileID() const { 112| 0| assert(getNumBuffers()); 113| 0| return 1; 114| 0| } 115| | 116| 0| SMLoc getParentIncludeLoc(unsigned i) const { 117| 0| assert(isValidBufferID(i)); 118| 0| return Buffers[i - 1].IncludeLoc; 119| 0| } 120| | 121| | /// Add a new source buffer to this source manager. This takes ownership of 122| | /// the memory buffer. 123| | unsigned AddNewSourceBuffer(std::unique_ptr F, 124| 0| SMLoc IncludeLoc) { 125| 0| SrcBuffer NB; 126| 0| NB.Buffer = std::move(F); 127| 0| NB.IncludeLoc = IncludeLoc; 128| 0| Buffers.push_back(std::move(NB)); 129| 0| return Buffers.size(); 130| 0| } 131| | 132| | /// Search for a file with the specified name in the current directory or in 133| | /// one of the IncludeDirs. 134| | /// 135| | /// If no file is found, this returns 0, otherwise it returns the buffer ID 136| | /// of the stacked file. The full path to the included file can be found in 137| | /// \p IncludedFile. 138| | unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, 139| | std::string &IncludedFile); 140| | 141| | /// Return the ID of the buffer containing the specified location. 142| | /// 143| | /// 0 is returned if the buffer is not found. 144| | unsigned FindBufferContainingLoc(SMLoc Loc) const; 145| | 146| | /// Find the line number for the specified location in the specified file. 147| | /// This is not a fast method. 148| | unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { 149| | return getLineAndColumn(Loc, BufferID).first; 150| | } 151| | 152| | /// Find the line and column number for the specified location in the 153| | /// specified file. This is not a fast method. 154| | std::pair getLineAndColumn(SMLoc Loc, 155| | unsigned BufferID = 0) const; 156| | 157| | /// Emit a message about the specified location with the specified string. 158| | /// 159| | /// \param ShowColors Display colored messages if output is a terminal and 160| | /// the default error handler is used. 161| | void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, 162| | const Twine &Msg, 163| | ArrayRef Ranges = None, 164| | ArrayRef FixIts = None, 165| | bool ShowColors = true) const; 166| | 167| | /// Emits a diagnostic to llvm::errs(). 168| | void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 169| | ArrayRef Ranges = None, 170| | ArrayRef FixIts = None, 171| | bool ShowColors = true) const; 172| | 173| | /// Emits a manually-constructed diagnostic to the given output stream. 174| | /// 175| | /// \param ShowColors Display colored messages if output is a terminal and 176| | /// the default error handler is used. 177| | void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, 178| | bool ShowColors = true) const; 179| | 180| | /// Return an SMDiagnostic at the specified location with the specified 181| | /// string. 182| | /// 183| | /// \param Msg If non-null, the kind of message (e.g., "error") which is 184| | /// prefixed to the message. 185| | SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 186| | ArrayRef Ranges = None, 187| | ArrayRef FixIts = None) const; 188| | 189| | /// Prints the names of included files and the line of the file they were 190| | /// included from. A diagnostic handler can use this before printing its 191| | /// custom formatted message. 192| | /// 193| | /// \param IncludeLoc The location of the include. 194| | /// \param OS the raw_ostream to print on. 195| | void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; 196| |}; 197| | 198| | 199| |/// Represents a single fixit, a replacement of one range of text with another. 200| |class SMFixIt { 201| | SMRange Range; 202| | 203| | std::string Text; 204| | 205| |public: 206| | // FIXME: Twine.str() is not very efficient. 207| | SMFixIt(SMLoc Loc, const Twine &Insertion) 208| 0| : Range(Loc, Loc), Text(Insertion.str()) { 209| 0| assert(Loc.isValid()); 210| 0| } 211| | 212| | // FIXME: Twine.str() is not very efficient. 213| | SMFixIt(SMRange R, const Twine &Replacement) 214| 0| : Range(R), Text(Replacement.str()) { 215| 0| assert(R.isValid()); 216| 0| } 217| | 218| | StringRef getText() const { return Text; } 219| | SMRange getRange() const { return Range; } 220| | 221| | bool operator<(const SMFixIt &Other) const { 222| | if (Range.Start.getPointer() != Other.Range.Start.getPointer()) 223| | return Range.Start.getPointer() < Other.Range.Start.getPointer(); 224| | if (Range.End.getPointer() != Other.Range.End.getPointer()) 225| | return Range.End.getPointer() < Other.Range.End.getPointer(); 226| | return Text < Other.Text; 227| | } 228| |}; 229| | 230| | 231| |/// Instances of this class encapsulate one diagnostic report, allowing 232| |/// printing to a raw_ostream as a caret diagnostic. 233| |class SMDiagnostic { 234| | const SourceMgr *SM; 235| | SMLoc Loc; 236| | std::string Filename; 237| | int LineNo, ColumnNo; 238| | SourceMgr::DiagKind Kind; 239| | std::string Message, LineContents; 240| | std::vector > Ranges; 241| | SmallVector FixIts; 242| | 243| |public: 244| | // Null diagnostic. 245| | SMDiagnostic() 246| 0| : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} 247| | // Diagnostic with no location (e.g. file not found, command line arg error). 248| | SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) 249| | : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), 250| 0| Message(Msg) {} 251| | 252| | // Diagnostic with a location. 253| | SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 254| | int Line, int Col, SourceMgr::DiagKind Kind, 255| | StringRef Msg, StringRef LineStr, 256| | ArrayRef > Ranges, 257| | ArrayRef FixIts = None); 258| | 259| 0| const SourceMgr *getSourceMgr() const { return SM; } 260| | SMLoc getLoc() const { return Loc; } 261| | StringRef getFilename() const { return Filename; } 262| | int getLineNo() const { return LineNo; } 263| | int getColumnNo() const { return ColumnNo; } 264| | SourceMgr::DiagKind getKind() const { return Kind; } 265| | StringRef getMessage() const { return Message; } 266| 0| StringRef getLineContents() const { return LineContents; } 267| 0| ArrayRef > getRanges() const { 268| 0| return Ranges; 269| 0| } 270| | 271| 0| void addFixIt(const SMFixIt &Hint) { 272| 0| FixIts.push_back(Hint); 273| 0| } 274| | 275| 0| ArrayRef getFixIts() const { 276| 0| return FixIts; 277| 0| } 278| | 279| | void print(const char *ProgName, raw_ostream &S, 280| | bool ShowColors = true) const; 281| |}; 282| | 283| |} // end llvm namespace 284| | 285| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SwapByteOrder.h: 1| |//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic and optimized functions to swap the byte order of 11| |// an integral type. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H 16| |#define LLVM_SUPPORT_SWAPBYTEORDER_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| |namespace sys { 25| | 26| |/// SwapByteOrder_16 - This function returns a byte-swapped representation of 27| |/// the 16-bit argument. 28| |inline uint16_t SwapByteOrder_16(uint16_t value) { 29| |#if defined(_MSC_VER) && !defined(_DEBUG) 30| | // The DLL version of the runtime lacks these functions (bug!?), but in a 31| | // release build they're replaced with BSWAP instructions anyway. 32| | return _byteswap_ushort(value); 33| |#else 34| | uint16_t Hi = value << 8; 35| | uint16_t Lo = value >> 8; 36| | return Hi | Lo; 37| |#endif 38| |} 39| | 40| |/// SwapByteOrder_32 - This function returns a byte-swapped representation of 41| |/// the 32-bit argument. 42| 0|inline uint32_t SwapByteOrder_32(uint32_t value) { 43| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 44| 0| return __builtin_bswap32(value); 45| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 46| 0| return _byteswap_ulong(value); 47| 0|#else 48| 0| uint32_t Byte0 = value & 0x000000FF; 49| 0| uint32_t Byte1 = value & 0x0000FF00; 50| 0| uint32_t Byte2 = value & 0x00FF0000; 51| 0| uint32_t Byte3 = value & 0xFF000000; 52| 0| return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 53| 0|#endif 54| 0|} 55| | 56| |/// SwapByteOrder_64 - This function returns a byte-swapped representation of 57| |/// the 64-bit argument. 58| 0|inline uint64_t SwapByteOrder_64(uint64_t value) { 59| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 60| 0| return __builtin_bswap64(value); 61| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 62| 0| return _byteswap_uint64(value); 63| 0|#else 64| 0| uint64_t Hi = SwapByteOrder_32(uint32_t(value)); 65| 0| uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); 66| 0| return (Hi << 32) | Lo; 67| 0|#endif 68| 0|} 69| | 70| 0|inline unsigned char getSwappedBytes(unsigned char C) { return C; } 71| 0|inline signed char getSwappedBytes(signed char C) { return C; } 72| 0|inline char getSwappedBytes(char C) { return C; } 73| | 74| 0|inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } 75| 0|inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } 76| | 77| 0|inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } 78| 0|inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } 79| | 80| |#if __LONG_MAX__ == __INT_MAX__ 81| |inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } 82| |inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } 83| |#elif __LONG_MAX__ == __LONG_LONG_MAX__ 84| 0|inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } 85| 0|inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } 86| |#else 87| |#error "Unknown long size!" 88| |#endif 89| | 90| 0|inline unsigned long long getSwappedBytes(unsigned long long C) { 91| 0| return SwapByteOrder_64(C); 92| 0|} 93| 0|inline signed long long getSwappedBytes(signed long long C) { 94| 0| return SwapByteOrder_64(C); 95| 0|} 96| | 97| 0|inline float getSwappedBytes(float C) { 98| 0| union { 99| 0| uint32_t i; 100| 0| float f; 101| 0| } in, out; 102| 0| in.f = C; 103| 0| out.i = SwapByteOrder_32(in.i); 104| 0| return out.f; 105| 0|} 106| | 107| 0|inline float getSwappedBytes(double C) { 108| 0| union { 109| 0| uint64_t i; 110| 0| double d; 111| 0| } in, out; 112| 0| in.d = C; 113| 0| out.i = SwapByteOrder_64(in.i); 114| 0| return out.d; 115| 0|} 116| | 117| |template 118| 0|inline void swapByteOrder(T &Value) { 119| 0| Value = getSwappedBytes(Value); 120| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIyEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIjEEvRT_ ------------------ 121| | 122| |} // end namespace sys 123| |} // end namespace llvm 124| | 125| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/TimeValue.h: 1| |//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This header file declares the operating system TimeValue concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_TIMEVALUE_H 15| |#define LLVM_SUPPORT_TIMEVALUE_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| | 20| |namespace llvm { 21| |namespace sys { 22| | /// This class is used where a precise fixed point in time is required. The 23| | /// range of TimeValue spans many hundreds of billions of years both past and 24| | /// present. The precision of TimeValue is to the nanosecond. However, the 25| | /// actual precision of its values will be determined by the resolution of 26| | /// the system clock. The TimeValue class is used in conjunction with several 27| | /// other lib/System interfaces to specify the time at which a call should 28| | /// timeout, etc. 29| | /// @since 1.4 30| | /// @brief Provides an abstraction for a fixed point in time. 31| | class TimeValue { 32| | 33| | /// @name Constants 34| | /// @{ 35| | public: 36| | 37| | /// A constant TimeValue representing the smallest time 38| | /// value permissible by the class. MinTime is some point 39| | /// in the distant past, about 300 billion years BCE. 40| | /// @brief The smallest possible time value. 41| | static TimeValue MinTime() { 42| | return TimeValue ( INT64_MIN,0 ); 43| | } 44| | 45| | /// A constant TimeValue representing the largest time 46| | /// value permissible by the class. MaxTime is some point 47| | /// in the distant future, about 300 billion years AD. 48| | /// @brief The largest possible time value. 49| 0| static TimeValue MaxTime() { 50| 0| return TimeValue ( INT64_MAX,0 ); 51| 0| } 52| | 53| | /// A constant TimeValue representing the base time, 54| | /// or zero time of 00:00:00 (midnight) January 1st, 2000. 55| | /// @brief 00:00:00 Jan 1, 2000 UTC. 56| 0| static TimeValue ZeroTime() { 57| 0| return TimeValue ( 0,0 ); 58| 0| } 59| | 60| | /// A constant TimeValue for the Posix base time which is 61| | /// 00:00:00 (midnight) January 1st, 1970. 62| | /// @brief 00:00:00 Jan 1, 1970 UTC. 63| 0| static TimeValue PosixZeroTime() { 64| 0| return TimeValue ( PosixZeroTimeSeconds,0 ); 65| 0| } 66| | 67| | /// A constant TimeValue for the Win32 base time which is 68| | /// 00:00:00 (midnight) January 1st, 1601. 69| | /// @brief 00:00:00 Jan 1, 1601 UTC. 70| 0| static TimeValue Win32ZeroTime() { 71| 0| return TimeValue ( Win32ZeroTimeSeconds,0 ); 72| 0| } 73| | 74| | /// @} 75| | /// @name Types 76| | /// @{ 77| | public: 78| | typedef int64_t SecondsType; ///< Type used for representing seconds. 79| | typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. 80| | 81| | enum TimeConversions { 82| | NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion 83| | MICROSECONDS_PER_SECOND = 1000000, ///< One Million 84| | MILLISECONDS_PER_SECOND = 1000, ///< One Thousand 85| | NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand 86| | NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million 87| | NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) 88| | }; 89| | 90| | /// @} 91| | /// @name Constructors 92| | /// @{ 93| | public: 94| | /// \brief Default construct a time value, initializing to ZeroTime. 95| 0| TimeValue() : seconds_(0), nanos_(0) {} 96| | 97| | /// Caller provides the exact value in seconds and nanoseconds. The 98| | /// \p nanos argument defaults to zero for convenience. 99| | /// @brief Explicit constructor 100| | explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) 101| | : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } 102| | 103| | /// Caller provides the exact value as a double in seconds with the 104| | /// fractional part representing nanoseconds. 105| | /// @brief Double Constructor. 106| | explicit TimeValue( double new_time ) 107| 0| : seconds_( 0 ) , nanos_ ( 0 ) { 108| 0| SecondsType integer_part = static_cast( new_time ); 109| 0| seconds_ = integer_part; 110| 0| nanos_ = static_cast( (new_time - 111| 0| static_cast(integer_part)) * NANOSECONDS_PER_SECOND ); 112| 0| this->normalize(); 113| 0| } 114| | 115| | /// This is a static constructor that returns a TimeValue that represents 116| | /// the current time. 117| | /// @brief Creates a TimeValue with the current time (UTC). 118| | static TimeValue now(); 119| | 120| | /// @} 121| | /// @name Operators 122| | /// @{ 123| | public: 124| | /// Add \p that to \p this. 125| | /// @returns this 126| | /// @brief Incrementing assignment operator. 127| 0| TimeValue& operator += (const TimeValue& that ) { 128| 0| this->seconds_ += that.seconds_ ; 129| 0| this->nanos_ += that.nanos_ ; 130| 0| this->normalize(); 131| 0| return *this; 132| 0| } 133| | 134| | /// Subtract \p that from \p this. 135| | /// @returns this 136| | /// @brief Decrementing assignment operator. 137| 0| TimeValue& operator -= (const TimeValue &that ) { 138| 0| this->seconds_ -= that.seconds_ ; 139| 0| this->nanos_ -= that.nanos_ ; 140| 0| this->normalize(); 141| 0| return *this; 142| 0| } 143| | 144| | /// Determine if \p this is less than \p that. 145| | /// @returns True iff *this < that. 146| | /// @brief True if this < that. 147| 0| int operator < (const TimeValue &that) const { return that > *this; } 148| | 149| | /// Determine if \p this is greather than \p that. 150| | /// @returns True iff *this > that. 151| | /// @brief True if this > that. 152| 0| int operator > (const TimeValue &that) const { 153| 0| if ( this->seconds_ > that.seconds_ ) { 154| 0| return 1; 155| 0| } else if ( this->seconds_ == that.seconds_ ) { 156| 0| if ( this->nanos_ > that.nanos_ ) return 1; 157| 0| } 158| 0| return 0; 159| 0| } 160| | 161| | /// Determine if \p this is less than or equal to \p that. 162| | /// @returns True iff *this <= that. 163| | /// @brief True if this <= that. 164| 0| int operator <= (const TimeValue &that) const { return that >= *this; } 165| | 166| | /// Determine if \p this is greater than or equal to \p that. 167| | /// @returns True iff *this >= that. 168| 0| int operator >= (const TimeValue &that) const { 169| 0| if ( this->seconds_ > that.seconds_ ) { 170| 0| return 1; 171| 0| } else if ( this->seconds_ == that.seconds_ ) { 172| 0| if ( this->nanos_ >= that.nanos_ ) return 1; 173| 0| } 174| 0| return 0; 175| 0| } 176| | 177| | /// Determines if two TimeValue objects represent the same moment in time. 178| | /// @returns True iff *this == that. 179| 0| int operator == (const TimeValue &that) const { 180| 0| return (this->seconds_ == that.seconds_) && 181| 0| (this->nanos_ == that.nanos_); 182| 0| } 183| | 184| | /// Determines if two TimeValue objects represent times that are not the 185| | /// same. 186| | /// @returns True iff *this != that. 187| 0| int operator != (const TimeValue &that) const { return !(*this == that); } 188| | 189| | /// Adds two TimeValue objects together. 190| | /// @returns The sum of the two operands as a new TimeValue 191| | /// @brief Addition operator. 192| | friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); 193| | 194| | /// Subtracts two TimeValue objects. 195| | /// @returns The difference of the two operands as a new TimeValue 196| | /// @brief Subtraction operator. 197| | friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); 198| | 199| | /// @} 200| | /// @name Accessors 201| | /// @{ 202| | public: 203| | 204| | /// Returns only the seconds component of the TimeValue. The nanoseconds 205| | /// portion is ignored. No rounding is performed. 206| | /// @brief Retrieve the seconds component 207| 0| SecondsType seconds() const { return seconds_; } 208| | 209| | /// Returns only the nanoseconds component of the TimeValue. The seconds 210| | /// portion is ignored. 211| | /// @brief Retrieve the nanoseconds component. 212| | NanoSecondsType nanoseconds() const { return nanos_; } 213| | 214| | /// Returns only the fractional portion of the TimeValue rounded down to the 215| | /// nearest microsecond (divide by one thousand). 216| | /// @brief Retrieve the fractional part as microseconds; 217| 0| uint32_t microseconds() const { 218| 0| return nanos_ / NANOSECONDS_PER_MICROSECOND; 219| 0| } 220| | 221| | /// Returns only the fractional portion of the TimeValue rounded down to the 222| | /// nearest millisecond (divide by one million). 223| | /// @brief Retrieve the fractional part as milliseconds; 224| 0| uint32_t milliseconds() const { 225| 0| return nanos_ / NANOSECONDS_PER_MILLISECOND; 226| 0| } 227| | 228| | /// Returns the TimeValue as a number of microseconds. Note that the value 229| | /// returned can overflow because the range of a uint64_t is smaller than 230| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 231| | /// systems and is therefore provided. 232| | /// @brief Convert to a number of microseconds (can overflow) 233| 0| uint64_t usec() const { 234| 0| return seconds_ * MICROSECONDS_PER_SECOND + 235| 0| ( nanos_ / NANOSECONDS_PER_MICROSECOND ); 236| 0| } 237| | 238| | /// Returns the TimeValue as a number of milliseconds. Note that the value 239| | /// returned can overflow because the range of a uint64_t is smaller than 240| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 241| | /// systems and is therefore provided. 242| | /// @brief Convert to a number of milliseconds (can overflow) 243| 0| uint64_t msec() const { 244| 0| return seconds_ * MILLISECONDS_PER_SECOND + 245| 0| ( nanos_ / NANOSECONDS_PER_MILLISECOND ); 246| 0| } 247| | 248| | /// Converts the TimeValue into the corresponding number of seconds 249| | /// since the epoch (00:00:00 Jan 1,1970). 250| | uint64_t toEpochTime() const { 251| | return seconds_ - PosixZeroTimeSeconds; 252| | } 253| | 254| | /// Converts the TimeValue into the corresponding number of "ticks" for 255| | /// Win32 platforms, correcting for the difference in Win32 zero time. 256| | /// @brief Convert to Win32's FILETIME 257| | /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) 258| 0| uint64_t toWin32Time() const { 259| 0| uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); 260| 0| result += nanos_ / NANOSECONDS_PER_WIN32_TICK; 261| 0| return result; 262| 0| } 263| | 264| | /// Provides the seconds and nanoseconds as results in its arguments after 265| | /// correction for the Posix zero time. 266| | /// @brief Convert to timespec time (ala POSIX.1b) 267| 0| void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { 268| 0| seconds = seconds_ - PosixZeroTimeSeconds; 269| 0| nanos = nanos_; 270| 0| } 271| | 272| | /// Provides conversion of the TimeValue into a readable time & date. 273| | /// @returns std::string containing the readable time value 274| | /// @brief Convert time to a string. 275| | std::string str() const; 276| | 277| | /// @} 278| | /// @name Mutators 279| | /// @{ 280| | public: 281| | /// The seconds component of the TimeValue is set to \p sec without 282| | /// modifying the nanoseconds part. This is useful for whole second 283| | /// arithmetic. 284| | /// @brief Set the seconds component. 285| 0| void seconds (SecondsType sec ) { 286| 0| this->seconds_ = sec; 287| 0| this->normalize(); 288| 0| } 289| | 290| | /// The nanoseconds component of the TimeValue is set to \p nanos without 291| | /// modifying the seconds part. This is useful for basic computations 292| | /// involving just the nanoseconds portion. Note that the TimeValue will be 293| | /// normalized after this call so that the fractional (nanoseconds) portion 294| | /// will have the smallest equivalent value. 295| | /// @brief Set the nanoseconds component using a number of nanoseconds. 296| 0| void nanoseconds ( NanoSecondsType nanos ) { 297| 0| this->nanos_ = nanos; 298| 0| this->normalize(); 299| 0| } 300| | 301| | /// The seconds component remains unchanged. 302| | /// @brief Set the nanoseconds component using a number of microseconds. 303| 0| void microseconds ( int32_t micros ) { 304| 0| this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; 305| 0| this->normalize(); 306| 0| } 307| | 308| | /// The seconds component remains unchanged. 309| | /// @brief Set the nanoseconds component using a number of milliseconds. 310| 0| void milliseconds ( int32_t millis ) { 311| 0| this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; 312| 0| this->normalize(); 313| 0| } 314| | 315| | /// @brief Converts from microsecond format to TimeValue format 316| 0| void usec( int64_t microseconds ) { 317| 0| this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; 318| 0| this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * 319| 0| NANOSECONDS_PER_MICROSECOND; 320| 0| this->normalize(); 321| 0| } 322| | 323| | /// @brief Converts from millisecond format to TimeValue format 324| 0| void msec( int64_t milliseconds ) { 325| 0| this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; 326| 0| this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * 327| 0| NANOSECONDS_PER_MILLISECOND; 328| 0| this->normalize(); 329| 0| } 330| | 331| | /// Converts the \p seconds argument from PosixTime to the corresponding 332| | /// TimeValue and assigns that value to \p this. 333| | /// @brief Convert seconds form PosixTime to TimeValue 334| 0| void fromEpochTime( SecondsType seconds ) { 335| 0| seconds_ = seconds + PosixZeroTimeSeconds; 336| 0| nanos_ = 0; 337| 0| this->normalize(); 338| 0| } 339| | 340| | /// Converts the \p win32Time argument from Windows FILETIME to the 341| | /// corresponding TimeValue and assigns that value to \p this. 342| | /// @brief Convert seconds form Windows FILETIME to TimeValue 343| 0| void fromWin32Time( uint64_t win32Time ) { 344| 0| this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; 345| 0| this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; 346| 0| } 347| | 348| | /// @} 349| | /// @name Implementation 350| | /// @{ 351| | private: 352| | /// This causes the values to be represented so that the fractional 353| | /// part is minimized, possibly incrementing the seconds part. 354| | /// @brief Normalize to canonical form. 355| | void normalize(); 356| | 357| | /// @} 358| | /// @name Data 359| | /// @{ 360| | private: 361| | /// Store the values as a . 362| | SecondsType seconds_;///< Stores the seconds part of the TimeVal 363| | NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal 364| | 365| | static const SecondsType PosixZeroTimeSeconds; 366| | static const SecondsType Win32ZeroTimeSeconds; 367| | /// @} 368| | 369| | }; 370| | 371| 0|inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { 372| 0| TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); 373| 0| sum.normalize (); 374| 0| return sum; 375| 0|} 376| | 377| |inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { 378| | TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); 379| | difference.normalize (); 380| | return difference; 381| |} 382| | 383| |} 384| |} 385| | 386| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/YAMLParser.h: 1| |//===--- YAMLParser.h - Simple YAML parser --------------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This is a YAML 1.2 parser. 11| |// 12| |// See http://www.yaml.org/spec/1.2/spec.html for the full standard. 13| |// 14| |// This currently does not implement the following: 15| |// * Multi-line literal folding. 16| |// * Tag resolution. 17| |// * UTF-16. 18| |// * BOMs anywhere other than the first Unicode scalar value in the file. 19| |// 20| |// The most important class here is Stream. This represents a YAML stream with 21| |// 0, 1, or many documents. 22| |// 23| |// SourceMgr sm; 24| |// StringRef input = getInput(); 25| |// yaml::Stream stream(input, sm); 26| |// 27| |// for (yaml::document_iterator di = stream.begin(), de = stream.end(); 28| |// di != de; ++di) { 29| |// yaml::Node *n = di->getRoot(); 30| |// if (n) { 31| |// // Do something with n... 32| |// } else 33| |// break; 34| |// } 35| |// 36| |//===----------------------------------------------------------------------===// 37| | 38| |#ifndef LLVM_SUPPORT_YAMLPARSER_H 39| |#define LLVM_SUPPORT_YAMLPARSER_H 40| | 41| |#include "llvm/ADT/SmallString.h" 42| |#include "llvm/ADT/StringRef.h" 43| |#include "llvm/Support/Allocator.h" 44| |#include "llvm/Support/MemoryBuffer.h" 45| |#include "llvm/Support/SMLoc.h" 46| |#include 47| |#include 48| |#include 49| | 50| |namespace llvm { 51| |class SourceMgr; 52| |class raw_ostream; 53| |class Twine; 54| | 55| |namespace yaml { 56| | 57| |class document_iterator; 58| |class Document; 59| |class Node; 60| |class Scanner; 61| |struct Token; 62| | 63| |/// \brief Dump all the tokens in this stream to OS. 64| |/// \returns true if there was an error, false otherwise. 65| |bool dumpTokens(StringRef Input, raw_ostream &); 66| | 67| |/// \brief Scans all tokens in input without outputting anything. This is used 68| |/// for benchmarking the tokenizer. 69| |/// \returns true if there was an error, false otherwise. 70| |bool scanTokens(StringRef Input); 71| | 72| |/// \brief Escape \a Input for a double quoted scalar. 73| |std::string escape(StringRef Input); 74| | 75| |/// \brief This class represents a YAML stream potentially containing multiple 76| |/// documents. 77| |class Stream { 78| |public: 79| | /// \brief This keeps a reference to the string referenced by \p Input. 80| | Stream(StringRef Input, SourceMgr &); 81| | 82| | Stream(MemoryBufferRef InputBuffer, SourceMgr &); 83| | ~Stream(); 84| | 85| | document_iterator begin(); 86| | document_iterator end(); 87| | void skip(); 88| | bool failed(); 89| 0| bool validate() { 90| 0| skip(); 91| 0| return !failed(); 92| 0| } 93| | 94| | void printError(Node *N, const Twine &Msg); 95| | 96| |private: 97| | std::unique_ptr scanner; 98| | std::unique_ptr CurrentDoc; 99| | 100| | friend class Document; 101| |}; 102| | 103| |/// \brief Abstract base class for all Nodes. 104| |class Node { 105| | virtual void anchor(); 106| | 107| |public: 108| | enum NodeKind { 109| | NK_Null, 110| | NK_Scalar, 111| | NK_KeyValue, 112| | NK_Mapping, 113| | NK_Sequence, 114| | NK_Alias 115| | }; 116| | 117| | Node(unsigned int Type, std::unique_ptr &, StringRef Anchor, 118| | StringRef Tag); 119| | 120| | /// \brief Get the value of the anchor attached to this node. If it does not 121| | /// have one, getAnchor().size() will be 0. 122| 0| StringRef getAnchor() const { return Anchor; } 123| | 124| | /// \brief Get the tag as it was written in the document. This does not 125| | /// perform tag resolution. 126| | StringRef getRawTag() const { return Tag; } 127| | 128| | /// \brief Get the verbatium tag for a given Node. This performs tag resoluton 129| | /// and substitution. 130| | std::string getVerbatimTag() const; 131| | 132| 0| SMRange getSourceRange() const { return SourceRange; } 133| 0| void setSourceRange(SMRange SR) { SourceRange = SR; } 134| | 135| | // These functions forward to Document and Scanner. 136| | Token &peekNext(); 137| | Token getNext(); 138| | Node *parseBlockNode(); 139| | BumpPtrAllocator &getAllocator(); 140| | void setError(const Twine &Message, Token &Location) const; 141| | bool failed() const; 142| | 143| 0| virtual void skip() {} 144| | 145| 0| unsigned int getType() const { return TypeID; } 146| | 147| | void *operator new(size_t Size, BumpPtrAllocator &Alloc, 148| | size_t Alignment = 16) throw() { 149| | return Alloc.Allocate(Size, Alignment); 150| | } 151| | 152| 0| void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { 153| 0| Alloc.Deallocate(Ptr, Size); 154| 0| } 155| | 156| |protected: 157| | std::unique_ptr &Doc; 158| | SMRange SourceRange; 159| | 160| 0| void operator delete(void *) throw() {} 161| | 162| 0| virtual ~Node() {} 163| | 164| |private: 165| | unsigned int TypeID; 166| | StringRef Anchor; 167| | /// \brief The tag as typed in the document. 168| | StringRef Tag; 169| |}; 170| | 171| |/// \brief A null value. 172| |/// 173| |/// Example: 174| |/// !!null null 175| |class NullNode : public Node { 176| | void anchor() override; 177| | 178| |public: 179| | NullNode(std::unique_ptr &D) 180| 0| : Node(NK_Null, D, StringRef(), StringRef()) {} 181| | 182| 0| static inline bool classof(const Node *N) { return N->getType() == NK_Null; } 183| |}; 184| | 185| |/// \brief A scalar node is an opaque datum that can be presented as a 186| |/// series of zero or more Unicode scalar values. 187| |/// 188| |/// Example: 189| |/// Adena 190| |class ScalarNode : public Node { 191| | void anchor() override; 192| | 193| |public: 194| | ScalarNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 195| | StringRef Val) 196| 0| : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { 197| 0| SMLoc Start = SMLoc::getFromPointer(Val.begin()); 198| 0| SMLoc End = SMLoc::getFromPointer(Val.end()); 199| 0| SourceRange = SMRange(Start, End); 200| 0| } 201| | 202| | // Return Value without any escaping or folding or other fun YAML stuff. This 203| | // is the exact bytes that are contained in the file (after conversion to 204| | // utf8). 205| 0| StringRef getRawValue() const { return Value; } 206| | 207| | /// \brief Gets the value of this node as a StringRef. 208| | /// 209| | /// \param Storage is used to store the content of the returned StringRef iff 210| | /// it requires any modification from how it appeared in the source. 211| | /// This happens with escaped characters and multi-line literals. 212| | StringRef getValue(SmallVectorImpl &Storage) const; 213| | 214| 0| static inline bool classof(const Node *N) { 215| 0| return N->getType() == NK_Scalar; 216| 0| } 217| | 218| |private: 219| | StringRef Value; 220| | 221| | StringRef unescapeDoubleQuoted(StringRef UnquotedValue, 222| | StringRef::size_type Start, 223| | SmallVectorImpl &Storage) const; 224| |}; 225| | 226| |/// \brief A key and value pair. While not technically a Node under the YAML 227| |/// representation graph, it is easier to treat them this way. 228| |/// 229| |/// TODO: Consider making this not a child of Node. 230| |/// 231| |/// Example: 232| |/// Section: .text 233| |class KeyValueNode : public Node { 234| | void anchor() override; 235| | 236| |public: 237| | KeyValueNode(std::unique_ptr &D) 238| | : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), 239| 0| Value(nullptr) {} 240| | 241| | /// \brief Parse and return the key. 242| | /// 243| | /// This may be called multiple times. 244| | /// 245| | /// \returns The key, or nullptr if failed() == true. 246| | Node *getKey(); 247| | 248| | /// \brief Parse and return the value. 249| | /// 250| | /// This may be called multiple times. 251| | /// 252| | /// \returns The value, or nullptr if failed() == true. 253| | Node *getValue(); 254| | 255| 0| void skip() override { 256| 0| getKey()->skip(); 257| 0| getValue()->skip(); 258| 0| } 259| | 260| 0| static inline bool classof(const Node *N) { 261| 0| return N->getType() == NK_KeyValue; 262| 0| } 263| | 264| |private: 265| | Node *Key; 266| | Node *Value; 267| |}; 268| | 269| |/// \brief This is an iterator abstraction over YAML collections shared by both 270| |/// sequences and maps. 271| |/// 272| |/// BaseT must have a ValueT* member named CurrentEntry and a member function 273| |/// increment() which must set CurrentEntry to 0 to create an end iterator. 274| |template 275| |class basic_collection_iterator 276| | : public std::iterator { 277| |public: 278| 0| basic_collection_iterator() : Base(nullptr) {} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEC2Ev ------------------ 279| 0| basic_collection_iterator(BaseT *B) : Base(B) {} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEC2EPS2_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEC2EPS2_ ------------------ 280| | 281| 0| ValueT *operator->() const { 282| 0| assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 283| 0| return Base->CurrentEntry; 284| 0| } 285| | 286| 0| ValueT &operator*() const { 287| 0| assert(Base && Base->CurrentEntry && 288| 0| "Attempted to dereference end iterator!"); 289| 0| return *Base->CurrentEntry; 290| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEdeEv ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEdeEv ------------------ 291| | 292| | explicit operator ValueT *() const { 293| | assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 294| | return Base->CurrentEntry; 295| | } 296| | 297| 0| bool operator==(const basic_collection_iterator &Other) const { 298| 0| if (Base != Other.Base) 299| 0| return false; 300| 0| return !Base || Base->CurrentEntry == Other.Base->CurrentEntry; 301| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEeqERKS4_ ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEeqERKS4_ ------------------ 302| 0| bool operator!=(const basic_collection_iterator &Other) { 303| 0| return !(*this == Other); 304| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEneERKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEneERKS4_ ------------------ 305| | 306| 0| basic_collection_iterator &operator++() { 307| 0| assert(Base && "Attempted to advance iterator past end!"); 308| 0| Base->increment(); 309| 0| // Create an end iterator. 310| 0| if (!Base->CurrentEntry) 311| 0| Base = nullptr; 312| 0| return *this; 313| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEppEv ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEppEv ------------------ 314| | 315| |private: 316| | BaseT *Base; 317| |}; 318| | 319| |// The following two templates are used for both MappingNode and Sequence Node. 320| |template 321| 0|typename CollectionType::iterator begin(CollectionType &C) { 322| 0| assert(C.IsAtBeginning && "You may only iterate over a collection once!"); 323| 0| C.IsAtBeginning = false; 324| 0| typename CollectionType::iterator ret(&C); 325| 0| ++ret; 326| 0| return ret; 327| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml5beginINS0_11MappingNodeEEENT_8iteratorERS3_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml5beginINS0_12SequenceNodeEEENT_8iteratorERS3_ ------------------ 328| | 329| |template void skip(CollectionType &C) { 330| | // TODO: support skipping from the middle of a parsed collection ;/ 331| | assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); 332| | if (C.IsAtBeginning) 333| | for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; 334| | ++i) 335| | i->skip(); 336| |} 337| | 338| |/// \brief Represents a YAML map created from either a block map for a flow map. 339| |/// 340| |/// This parses the YAML stream as increment() is called. 341| |/// 342| |/// Example: 343| |/// Name: _main 344| |/// Scope: Global 345| |class MappingNode : public Node { 346| | void anchor() override; 347| | 348| |public: 349| | enum MappingType { 350| | MT_Block, 351| | MT_Flow, 352| | MT_Inline ///< An inline mapping node is used for "[key: value]". 353| | }; 354| | 355| | MappingNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 356| | MappingType MT) 357| | : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), 358| 0| IsAtEnd(false), CurrentEntry(nullptr) {} 359| | 360| | friend class basic_collection_iterator; 361| | typedef basic_collection_iterator iterator; 362| | template friend typename T::iterator yaml::begin(T &); 363| | template friend void yaml::skip(T &); 364| | 365| 0| iterator begin() { return yaml::begin(*this); } 366| | 367| 0| iterator end() { return iterator(); } 368| | 369| 0| void skip() override { yaml::skip(*this); } 370| | 371| 0| static inline bool classof(const Node *N) { 372| 0| return N->getType() == NK_Mapping; 373| 0| } 374| | 375| |private: 376| | MappingType Type; 377| | bool IsAtBeginning; 378| | bool IsAtEnd; 379| | KeyValueNode *CurrentEntry; 380| | 381| | void increment(); 382| |}; 383| | 384| |/// \brief Represents a YAML sequence created from either a block sequence for a 385| |/// flow sequence. 386| |/// 387| |/// This parses the YAML stream as increment() is called. 388| |/// 389| |/// Example: 390| |/// - Hello 391| |/// - World 392| |class SequenceNode : public Node { 393| | void anchor() override; 394| | 395| |public: 396| | enum SequenceType { 397| | ST_Block, 398| | ST_Flow, 399| | // Use for: 400| | // 401| | // key: 402| | // - val1 403| | // - val2 404| | // 405| | // As a BlockMappingEntry and BlockEnd are not created in this case. 406| | ST_Indentless 407| | }; 408| | 409| | SequenceNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 410| | SequenceType ST) 411| | : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), 412| | IsAtEnd(false), 413| | WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. 414| 0| CurrentEntry(nullptr) {} 415| | 416| | friend class basic_collection_iterator; 417| | typedef basic_collection_iterator iterator; 418| | template friend typename T::iterator yaml::begin(T &); 419| | template friend void yaml::skip(T &); 420| | 421| | void increment(); 422| | 423| 0| iterator begin() { return yaml::begin(*this); } 424| | 425| 0| iterator end() { return iterator(); } 426| | 427| 0| void skip() override { yaml::skip(*this); } 428| | 429| 0| static inline bool classof(const Node *N) { 430| 0| return N->getType() == NK_Sequence; 431| 0| } 432| | 433| |private: 434| | SequenceType SeqType; 435| | bool IsAtBeginning; 436| | bool IsAtEnd; 437| | bool WasPreviousTokenFlowEntry; 438| | Node *CurrentEntry; 439| |}; 440| | 441| |/// \brief Represents an alias to a Node with an anchor. 442| |/// 443| |/// Example: 444| |/// *AnchorName 445| |class AliasNode : public Node { 446| | void anchor() override; 447| | 448| |public: 449| | AliasNode(std::unique_ptr &D, StringRef Val) 450| 0| : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} 451| | 452| 0| StringRef getName() const { return Name; } 453| | Node *getTarget(); 454| | 455| 0| static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } 456| | 457| |private: 458| | StringRef Name; 459| |}; 460| | 461| |/// \brief A YAML Stream is a sequence of Documents. A document contains a root 462| |/// node. 463| |class Document { 464| |public: 465| | /// \brief Root for parsing a node. Returns a single node. 466| | Node *parseBlockNode(); 467| | 468| | Document(Stream &ParentStream); 469| | 470| | /// \brief Finish parsing the current document and return true if there are 471| | /// more. Return false otherwise. 472| | bool skip(); 473| | 474| | /// \brief Parse and return the root level node. 475| 0| Node *getRoot() { 476| 0| if (Root) 477| 0| return Root; 478| 0| return Root = parseBlockNode(); 479| 0| } 480| | 481| | const std::map &getTagMap() const { return TagMap; } 482| | 483| |private: 484| | friend class Node; 485| | friend class document_iterator; 486| | 487| | /// \brief Stream to read tokens from. 488| | Stream &stream; 489| | 490| | /// \brief Used to allocate nodes to. All are destroyed without calling their 491| | /// destructor when the document is destroyed. 492| | BumpPtrAllocator NodeAllocator; 493| | 494| | /// \brief The root node. Used to support skipping a partially parsed 495| | /// document. 496| | Node *Root; 497| | 498| | /// \brief Maps tag prefixes to their expansion. 499| | std::map TagMap; 500| | 501| | Token &peekNext(); 502| | Token getNext(); 503| | void setError(const Twine &Message, Token &Location) const; 504| | bool failed() const; 505| | 506| | /// \brief Parse %BLAH directives and return true if any were encountered. 507| | bool parseDirectives(); 508| | 509| | /// \brief Parse %YAML 510| | void parseYAMLDirective(); 511| | 512| | /// \brief Parse %TAG 513| | void parseTAGDirective(); 514| | 515| | /// \brief Consume the next token and error if it is not \a TK. 516| | bool expectToken(int TK); 517| |}; 518| | 519| |/// \brief Iterator abstraction for Documents over a Stream. 520| |class document_iterator { 521| |public: 522| 0| document_iterator() : Doc(nullptr) {} 523| 0| document_iterator(std::unique_ptr &D) : Doc(&D) {} 524| | 525| 0| bool operator==(const document_iterator &Other) { 526| 0| if (isAtEnd() || Other.isAtEnd()) 527| 0| return isAtEnd() && Other.isAtEnd(); 528| 0| 529| 0| return Doc == Other.Doc; 530| 0| } 531| 0| bool operator!=(const document_iterator &Other) { return !(*this == Other); } 532| | 533| 0| document_iterator operator++() { 534| 0| assert(Doc && "incrementing iterator past the end."); 535| 0| if (!(*Doc)->skip()) { 536| 0| Doc->reset(nullptr); 537| 0| } else { 538| 0| Stream &S = (*Doc)->stream; 539| 0| Doc->reset(new Document(S)); 540| 0| } 541| 0| return *this; 542| 0| } 543| | 544| 0| Document &operator*() { return *Doc->get(); } 545| | 546| 0| std::unique_ptr &operator->() { return *Doc; } 547| | 548| |private: 549| 0| bool isAtEnd() const { return !Doc || !*Doc; } 550| | 551| | std::unique_ptr *Doc; 552| |}; 553| | 554| |} // End namespace yaml. 555| | 556| |} // End namespace llvm. 557| | 558| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/raw_ostream.h: 1| |//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the raw_ostream class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_RAW_OSTREAM_H 15| |#define LLVM_SUPPORT_RAW_OSTREAM_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include 22| | 23| |namespace llvm { 24| | class format_object_base; 25| | class FormattedString; 26| | class FormattedNumber; 27| | template 28| | class SmallVectorImpl; 29| | 30| | namespace sys { 31| | namespace fs { 32| | enum OpenFlags : unsigned; 33| | } 34| | } 35| | 36| |/// raw_ostream - This class implements an extremely fast bulk output stream 37| |/// that can *only* output to a stream. It does not support seeking, reopening, 38| |/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs 39| |/// a chunk at a time. 40| |class raw_ostream { 41| |private: 42| | void operator=(const raw_ostream &) = delete; 43| | raw_ostream(const raw_ostream &) = delete; 44| | 45| | /// The buffer is handled in such a way that the buffer is 46| | /// uninitialized, unbuffered, or out of space when OutBufCur >= 47| | /// OutBufEnd. Thus a single comparison suffices to determine if we 48| | /// need to take the slow path to write a single character. 49| | /// 50| | /// The buffer is in one of three states: 51| | /// 1. Unbuffered (BufferMode == Unbuffered) 52| | /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). 53| | /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && 54| | /// OutBufEnd - OutBufStart >= 1). 55| | /// 56| | /// If buffered, then the raw_ostream owns the buffer if (BufferMode == 57| | /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is 58| | /// managed by the subclass. 59| | /// 60| | /// If a subclass installs an external buffer using SetBuffer then it can wait 61| | /// for a \see write_impl() call to handle the data which has been put into 62| | /// this buffer. 63| | char *OutBufStart, *OutBufEnd, *OutBufCur; 64| | 65| | enum BufferKind { 66| | Unbuffered = 0, 67| | InternalBuffer, 68| | ExternalBuffer 69| | } BufferMode; 70| | 71| |public: 72| | // color order matches ANSI escape sequence, don't change 73| | enum Colors { 74| | BLACK=0, 75| | RED, 76| | GREEN, 77| | YELLOW, 78| | BLUE, 79| | MAGENTA, 80| | CYAN, 81| | WHITE, 82| | SAVEDCOLOR 83| | }; 84| | 85| | explicit raw_ostream(bool unbuffered=false) 86| 0| : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { 87| 0| // Start out ready to flush. 88| 0| OutBufStart = OutBufEnd = OutBufCur = nullptr; 89| 0| } 90| | 91| | virtual ~raw_ostream(); 92| | 93| | /// tell - Return the current offset with the file. 94| | uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } 95| | 96| | //===--------------------------------------------------------------------===// 97| | // Configuration Interface 98| | //===--------------------------------------------------------------------===// 99| | 100| | /// SetBuffered - Set the stream to be buffered, with an automatically 101| | /// determined buffer size. 102| | void SetBuffered(); 103| | 104| | /// SetBufferSize - Set the stream to be buffered, using the 105| | /// specified buffer size. 106| 0| void SetBufferSize(size_t Size) { 107| 0| flush(); 108| 0| SetBufferAndMode(new char[Size], Size, InternalBuffer); 109| 0| } 110| | 111| 0| size_t GetBufferSize() const { 112| 0| // If we're supposed to be buffered but haven't actually gotten around 113| 0| // to allocating the buffer yet, return the value that would be used. 114| 0| if (BufferMode != Unbuffered && OutBufStart == nullptr) 115| 0| return preferred_buffer_size(); 116| 0| 117| 0| // Otherwise just return the size of the allocated buffer. 118| 0| return OutBufEnd - OutBufStart; 119| 0| } 120| | 121| | /// SetUnbuffered - Set the stream to be unbuffered. When 122| | /// unbuffered, the stream will flush after every write. This routine 123| | /// will also flush the buffer immediately when the stream is being 124| | /// set to unbuffered. 125| 0| void SetUnbuffered() { 126| 0| flush(); 127| 0| SetBufferAndMode(nullptr, 0, Unbuffered); 128| 0| } 129| | 130| | size_t GetNumBytesInBuffer() const { 131| | return OutBufCur - OutBufStart; 132| | } 133| | 134| | //===--------------------------------------------------------------------===// 135| | // Data Output Interface 136| | //===--------------------------------------------------------------------===// 137| | 138| 0| void flush() { 139| 0| if (OutBufCur != OutBufStart) 140| 0| flush_nonempty(); 141| 0| } 142| | 143| 0| raw_ostream &operator<<(char C) { 144| 0| if (OutBufCur >= OutBufEnd) 145| 0| return write(C); 146| 0| *OutBufCur++ = C; 147| 0| return *this; 148| 0| } 149| | 150| | raw_ostream &operator<<(unsigned char C) { 151| | if (OutBufCur >= OutBufEnd) 152| | return write(C); 153| | *OutBufCur++ = C; 154| | return *this; 155| | } 156| | 157| 0| raw_ostream &operator<<(signed char C) { 158| 0| if (OutBufCur >= OutBufEnd) 159| 0| return write(C); 160| 0| *OutBufCur++ = C; 161| 0| return *this; 162| 0| } 163| | 164| 0| raw_ostream &operator<<(StringRef Str) { 165| 0| // Inline fast path, particularly for strings with a known length. 166| 0| size_t Size = Str.size(); 167| 0| 168| 0| // Make sure we can use the fast path. 169| 0| if (Size > (size_t)(OutBufEnd - OutBufCur)) 170| 0| return write(Str.data(), Size); 171| 0| 172| 0| memcpy(OutBufCur, Str.data(), Size); 173| 0| OutBufCur += Size; 174| 0| return *this; 175| 0| } 176| | 177| 0| raw_ostream &operator<<(const char *Str) { 178| 0| // Inline fast path, particularly for constant strings where a sufficiently 179| 0| // smart compiler will simplify strlen. 180| 0| 181| 0| return this->operator<<(StringRef(Str)); 182| 0| } 183| | 184| 0| raw_ostream &operator<<(const std::string &Str) { 185| 0| // Avoid the fast path, it would only increase code size for a marginal win. 186| 0| return write(Str.data(), Str.length()); 187| 0| } 188| | 189| 0| raw_ostream &operator<<(const llvm::SmallVectorImpl &Str) { 190| 0| return write(Str.data(), Str.size()); 191| 0| } 192| | 193| | raw_ostream &operator<<(unsigned long N); 194| | raw_ostream &operator<<(long N); 195| | raw_ostream &operator<<(unsigned long long N); 196| | raw_ostream &operator<<(long long N); 197| | raw_ostream &operator<<(const void *P); 198| | raw_ostream &operator<<(unsigned int N) { 199| | return this->operator<<(static_cast(N)); 200| | } 201| | 202| | raw_ostream &operator<<(int N) { 203| | return this->operator<<(static_cast(N)); 204| | } 205| | 206| | raw_ostream &operator<<(double N); 207| | 208| | /// write_hex - Output \p N in hexadecimal, without any prefix or padding. 209| | raw_ostream &write_hex(unsigned long long N); 210| | 211| | /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and 212| | /// anything that doesn't satisfy std::isprint into an escape sequence. 213| | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); 214| | 215| | raw_ostream &write(unsigned char C); 216| | raw_ostream &write(const char *Ptr, size_t Size); 217| | 218| | // Formatted output, see the format() function in Support/Format.h. 219| | raw_ostream &operator<<(const format_object_base &Fmt); 220| | 221| | // Formatted output, see the leftJustify() function in Support/Format.h. 222| | raw_ostream &operator<<(const FormattedString &); 223| | 224| | // Formatted output, see the formatHex() function in Support/Format.h. 225| | raw_ostream &operator<<(const FormattedNumber &); 226| | 227| | /// indent - Insert 'NumSpaces' spaces. 228| | raw_ostream &indent(unsigned NumSpaces); 229| | 230| | 231| | /// Changes the foreground color of text that will be output from this point 232| | /// forward. 233| | /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to 234| | /// change only the bold attribute, and keep colors untouched 235| | /// @param Bold bold/brighter text, default false 236| | /// @param BG if true change the background, default: change foreground 237| | /// @returns itself so it can be used within << invocations 238| | virtual raw_ostream &changeColor(enum Colors Color, 239| | bool Bold = false, 240| | bool BG = false) { 241| | (void)Color; 242| | (void)Bold; 243| | (void)BG; 244| | return *this; 245| | } 246| | 247| | /// Resets the colors to terminal defaults. Call this when you are done 248| | /// outputting colored text, or before program exit. 249| | virtual raw_ostream &resetColor() { return *this; } 250| | 251| | /// Reverses the forground and background colors. 252| | virtual raw_ostream &reverseColor() { return *this; } 253| | 254| | /// This function determines if this stream is connected to a "tty" or 255| | /// "console" window. That is, the output would be displayed to the user 256| | /// rather than being put on a pipe or stored in a file. 257| | virtual bool is_displayed() const { return false; } 258| | 259| | /// This function determines if this stream is displayed and supports colors. 260| | virtual bool has_colors() const { return is_displayed(); } 261| | 262| | //===--------------------------------------------------------------------===// 263| | // Subclass Interface 264| | //===--------------------------------------------------------------------===// 265| | 266| |private: 267| | /// write_impl - The is the piece of the class that is implemented 268| | /// by subclasses. This writes the \p Size bytes starting at 269| | /// \p Ptr to the underlying stream. 270| | /// 271| | /// This function is guaranteed to only be called at a point at which it is 272| | /// safe for the subclass to install a new buffer via SetBuffer. 273| | /// 274| | /// \param Ptr The start of the data to be written. For buffered streams this 275| | /// is guaranteed to be the start of the buffer. 276| | /// 277| | /// \param Size The number of bytes to be written. 278| | /// 279| | /// \invariant { Size > 0 } 280| | virtual void write_impl(const char *Ptr, size_t Size) = 0; 281| | 282| | // An out of line virtual method to provide a home for the class vtable. 283| | virtual void handle(); 284| | 285| | /// current_pos - Return the current position within the stream, not 286| | /// counting the bytes currently in the buffer. 287| | virtual uint64_t current_pos() const = 0; 288| | 289| |protected: 290| | /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is 291| | /// intended for use only by subclasses which can arrange for the output to go 292| | /// directly into the desired output buffer, instead of being copied on each 293| | /// flush. 294| 0| void SetBuffer(char *BufferStart, size_t Size) { 295| 0| SetBufferAndMode(BufferStart, Size, ExternalBuffer); 296| 0| } 297| | 298| | /// preferred_buffer_size - Return an efficient buffer size for the 299| | /// underlying output mechanism. 300| | virtual size_t preferred_buffer_size() const; 301| | 302| | /// getBufferStart - Return the beginning of the current stream buffer, or 0 303| | /// if the stream is unbuffered. 304| 0| const char *getBufferStart() const { return OutBufStart; } 305| | 306| | //===--------------------------------------------------------------------===// 307| | // Private Interface 308| | //===--------------------------------------------------------------------===// 309| |private: 310| | /// SetBufferAndMode - Install the given buffer and mode. 311| | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); 312| | 313| | /// flush_nonempty - Flush the current buffer, which is known to be 314| | /// non-empty. This outputs the currently buffered data and resets 315| | /// the buffer to empty. 316| | void flush_nonempty(); 317| | 318| | /// copy_to_buffer - Copy data into the buffer. Size must not be 319| | /// greater than the number of unused bytes in the buffer. 320| | void copy_to_buffer(const char *Ptr, size_t Size); 321| |}; 322| | 323| |//===----------------------------------------------------------------------===// 324| |// File Output Streams 325| |//===----------------------------------------------------------------------===// 326| | 327| |/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. 328| |/// 329| |class raw_fd_ostream : public raw_ostream { 330| | int FD; 331| | bool ShouldClose; 332| | 333| | /// Error This flag is true if an error of any kind has been detected. 334| | /// 335| | bool Error; 336| | 337| | /// Controls whether the stream should attempt to use atomic writes, when 338| | /// possible. 339| | bool UseAtomicWrites; 340| | 341| | uint64_t pos; 342| | 343| | /// write_impl - See raw_ostream::write_impl. 344| | void write_impl(const char *Ptr, size_t Size) override; 345| | 346| | /// current_pos - Return the current position within the stream, not 347| | /// counting the bytes currently in the buffer. 348| | uint64_t current_pos() const override { return pos; } 349| | 350| | /// preferred_buffer_size - Determine an efficient buffer size. 351| | size_t preferred_buffer_size() const override; 352| | 353| | /// error_detected - Set the flag indicating that an output error has 354| | /// been encountered. 355| 0| void error_detected() { Error = true; } 356| | 357| |public: 358| | /// Open the specified file for writing. If an error occurs, information 359| | /// about the error is put into EC, and the stream should be immediately 360| | /// destroyed; 361| | /// \p Flags allows optional flags to control how the file will be opened. 362| | /// 363| | /// As a special case, if Filename is "-", then the stream will use 364| | /// STDOUT_FILENO instead of opening a file. Note that it will still consider 365| | /// itself to own the file descriptor. In particular, it will close the 366| | /// file descriptor when it is done (this is necessary to detect 367| | /// output errors). 368| | raw_fd_ostream(StringRef Filename, std::error_code &EC, 369| | sys::fs::OpenFlags Flags); 370| | 371| | /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 372| | /// ShouldClose is true, this closes the file when the stream is destroyed. 373| | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); 374| | 375| | ~raw_fd_ostream(); 376| | 377| | /// close - Manually flush the stream and close the file. 378| | /// Note that this does not call fsync. 379| | void close(); 380| | 381| | /// seek - Flushes the stream and repositions the underlying file descriptor 382| | /// position to the offset specified from the beginning of the file. 383| | uint64_t seek(uint64_t off); 384| | 385| | /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for 386| | /// individual output routines where possible. 387| | /// 388| | /// Note that because raw_ostream's are typically buffered, this flag is only 389| | /// sensible when used on unbuffered streams which will flush their output 390| | /// immediately. 391| 0| void SetUseAtomicWrites(bool Value) { 392| 0| UseAtomicWrites = Value; 393| 0| } 394| | 395| | raw_ostream &changeColor(enum Colors colors, bool bold=false, 396| | bool bg=false) override; 397| | raw_ostream &resetColor() override; 398| | 399| | raw_ostream &reverseColor() override; 400| | 401| | bool is_displayed() const override; 402| | 403| | bool has_colors() const override; 404| | 405| | /// has_error - Return the value of the flag in this raw_fd_ostream indicating 406| | /// whether an output error has been encountered. 407| | /// This doesn't implicitly flush any pending output. Also, it doesn't 408| | /// guarantee to detect all errors unless the stream has been closed. 409| | bool has_error() const { 410| | return Error; 411| | } 412| | 413| | /// clear_error - Set the flag read by has_error() to false. If the error 414| | /// flag is set at the time when this raw_ostream's destructor is called, 415| | /// report_fatal_error is called to report the error. Use clear_error() 416| | /// after handling the error to avoid this behavior. 417| | /// 418| | /// "Errors should never pass silently. 419| | /// Unless explicitly silenced." 420| | /// - from The Zen of Python, by Tim Peters 421| | /// 422| 0| void clear_error() { 423| 0| Error = false; 424| 0| } 425| |}; 426| | 427| |/// outs() - This returns a reference to a raw_ostream for standard output. 428| |/// Use it like: outs() << "foo" << "bar"; 429| |raw_ostream &outs(); 430| | 431| |/// errs() - This returns a reference to a raw_ostream for standard error. 432| |/// Use it like: errs() << "foo" << "bar"; 433| |raw_ostream &errs(); 434| | 435| |/// nulls() - This returns a reference to a raw_ostream which simply discards 436| |/// output. 437| |raw_ostream &nulls(); 438| | 439| |//===----------------------------------------------------------------------===// 440| |// Output Stream Adaptors 441| |//===----------------------------------------------------------------------===// 442| | 443| |/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a 444| |/// simple adaptor class. This class does not encounter output errors. 445| |class raw_string_ostream : public raw_ostream { 446| | std::string &OS; 447| | 448| | /// write_impl - See raw_ostream::write_impl. 449| | void write_impl(const char *Ptr, size_t Size) override; 450| | 451| | /// current_pos - Return the current position within the stream, not 452| | /// counting the bytes currently in the buffer. 453| | uint64_t current_pos() const override { return OS.size(); } 454| |public: 455| 0| explicit raw_string_ostream(std::string &O) : OS(O) {} 456| | ~raw_string_ostream(); 457| | 458| | /// str - Flushes the stream contents to the target string and returns 459| | /// the string's reference. 460| 0| std::string& str() { 461| 0| flush(); 462| 0| return OS; 463| 0| } 464| |}; 465| | 466| |/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or 467| |/// SmallString. This is a simple adaptor class. This class does not 468| |/// encounter output errors. 469| |class raw_svector_ostream : public raw_ostream { 470| | SmallVectorImpl &OS; 471| | 472| | /// write_impl - See raw_ostream::write_impl. 473| | void write_impl(const char *Ptr, size_t Size) override; 474| | 475| | /// current_pos - Return the current position within the stream, not 476| | /// counting the bytes currently in the buffer. 477| | uint64_t current_pos() const override; 478| |public: 479| | /// Construct a new raw_svector_ostream. 480| | /// 481| | /// \param O The vector to write to; this should generally have at least 128 482| | /// bytes free to avoid any extraneous memory overhead. 483| | explicit raw_svector_ostream(SmallVectorImpl &O); 484| | ~raw_svector_ostream(); 485| | 486| | /// resync - This is called when the SmallVector we're appending to is changed 487| | /// outside of the raw_svector_ostream's control. It is only safe to do this 488| | /// if the raw_svector_ostream has previously been flushed. 489| | void resync(); 490| | 491| | /// str - Flushes the stream contents to the target vector and return a 492| | /// StringRef for the vector contents. 493| | StringRef str(); 494| |}; 495| | 496| |/// raw_null_ostream - A raw_ostream that discards all output. 497| |class raw_null_ostream : public raw_ostream { 498| | /// write_impl - See raw_ostream::write_impl. 499| | void write_impl(const char *Ptr, size_t size) override; 500| | 501| | /// current_pos - Return the current position within the stream, not 502| | /// counting the bytes currently in the buffer. 503| | uint64_t current_pos() const override; 504| | 505| |public: 506| 0| explicit raw_null_ostream() {} 507| | ~raw_null_ostream(); 508| |}; 509| | 510| |} // end llvm namespace 511| | 512| |#endif <<<<<< EOF # path=PackageLoading.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/Diagnostics.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import PackageModel 14| | 15| |public enum PackageBuilderDiagnostics { 16| | 17| | /// A target in a package contains no sources. 18| | public struct NoSources: DiagnosticData { 19| | public static let id = DiagnosticID( 20| | type: NoSources.self, 21| | name: "org.swift.diags.pkg-builder.nosources", 22| | defaultBehavior: .warning, 23| 0| description: { 24| 0| $0 <<< "target" <<< { "'\($0.target)'" } 25| 0| $0 <<< "in package" <<< { "'\($0.package)'" } 26| 0| $0 <<< "contains no valid source files" 27| 0| } 28| | ) 29| | 30| | /// The name of the package. 31| | public let package: String 32| | 33| | /// The name of the target which has no sources. 34| | public let target: String 35| | } 36| | 37| | /// C language test target on linux is not supported. 38| | public struct UnsupportedCTarget: DiagnosticData { 39| | public static let id = DiagnosticID( 40| | type: UnsupportedCTarget.self, 41| | name: "org.swift.diags.pkg-builder.nosources", 42| | defaultBehavior: .warning, 43| 0| description: { 44| 0| $0 <<< "ignoring target" <<< { "'\($0.target)'" } 45| 0| $0 <<< "in package" <<< { "'\($0.package)';" } 46| 0| $0 <<< "C language in tests is not yet supported" 47| 0| } 48| | ) 49| | 50| | /// The name of the package. 51| | public let package: String 52| | 53| | /// The name of the target which has no sources. 54| | public let target: String 55| | } 56| | 57| | public struct DuplicateProduct: DiagnosticData { 58| | public static let id = DiagnosticID( 59| | type: DuplicateProduct.self, 60| | name: "org.swift.diags.pkg-builder.dup-product", 61| | defaultBehavior: .warning, 62| 0| description: { 63| 0| $0 <<< "Ignoring duplicate product" <<< { "'\($0.product.name)'" } 64| 0| $0 <<< .substitution({ 65| 0| let `self` = $0 as! DuplicateProduct 66| 0| switch self.product.type { 67| 0| case .library(.automatic): 68| 0| return "" 69| 0| case .executable, .test: fallthrough 70| 0| case .library(.dynamic), .library(.static): 71| 0| return "(\(self.product.type))" 72| 0| } 73| 0| }, preference: .default) 74| 0| } 75| | ) 76| | 77| | public let product: Product 78| | } 79| | 80| | public struct DuplicateTargetDependencyDiagnostic: DiagnosticData { 81| | public static let id = DiagnosticID( 82| | type: DuplicateTargetDependencyDiagnostic.self, 83| | name: "org.swift.diags.pkg-builder.dup-target-dependency", 84| | defaultBehavior: .warning, 85| | description: { 86| 0| $0 <<< "invalid duplicate target dependency declaration" <<< { "'\($0.dependency)'" } 87| 0| <<< "in target" <<< { "'\($0.target)'" } 88| | }) 89| | 90| | public let dependency: String 91| | public let target: String 92| | } 93| | 94| | struct SystemPackageDeprecatedDiagnostic: DiagnosticData { 95| | static let id = DiagnosticID( 96| | type: SystemPackageDeprecatedDiagnostic.self, 97| | name: "org.swift.diags.pkg-builder.sys-pkg-deprecated", 98| | defaultBehavior: .warning, 99| 0| description: { 100| 0| $0 <<< "system packages are deprecated;" 101| 0| $0 <<< "use system library targets instead" 102| 0| } 103| | ) 104| | } 105| | 106| | struct SystemPackageDeclaresTargetsDiagnostic: DiagnosticData { 107| | static let id = DiagnosticID( 108| | type: SystemPackageDeclaresTargetsDiagnostic.self, 109| | name: "org.swift.diags.pkg-builder.sys-pkg-decl-targets", 110| | defaultBehavior: .warning, 111| | description: { 112| 0| $0 <<< "Ignoring declared target(s)" <<< { "'\($0.targets.joined(separator: ", "))'" } <<< "in the system package" 113| | } 114| | ) 115| | 116| | let targets: [String] 117| | } 118| | 119| | struct SystemPackageProductValidationDiagnostic: DiagnosticData { 120| | static let id = DiagnosticID( 121| | type: SystemPackageProductValidationDiagnostic.self, 122| | name: "org.swift.diags.pkg-builder.sys-pkg-product-validation", 123| | description: { 124| 0| $0 <<< "system library product" <<< { $0.product } <<< "shouldn't have a type and contain only one target" 125| | } 126| | ) 127| | 128| | let product: String 129| | } 130| | 131| | struct InvalidExecutableProductDecl: DiagnosticData { 132| | static let id = DiagnosticID( 133| | type: InvalidExecutableProductDecl.self, 134| | name: "org.swift.diags.pkg-builder.invalid-exec-product", 135| | description: { 136| 0| $0 <<< "executable product" <<< { "'" + $0.product + "'" } <<< "should have exactly one executable target" 137| | } 138| | ) 139| | 140| | let product: String 141| | } 142| | 143| | struct ZeroLibraryProducts: DiagnosticData { 144| | static let id = DiagnosticID( 145| | type: ZeroLibraryProducts.self, 146| | name: "org.swift.diags.pkg-builder.\(ZeroLibraryProducts.self)", 147| | description: { 148| | $0 <<< "unable to synthesize a REPL product as there are no library targets in the package" 149| | } 150| | ) 151| | } 152| | 153| | struct BorkenSymlinkDiagnostic: DiagnosticData { 154| | static let id = DiagnosticID( 155| | type: BorkenSymlinkDiagnostic.self, 156| | name: "org.swift.diags.pkg-builder.borken-symlink", 157| | defaultBehavior: .warning, 158| | description: { 159| 0| $0 <<< "ignoring broken symlink" <<< { $0.path } 160| | } 161| | ) 162| | 163| | let path: String 164| | } 165| |} 166| | 167| |public struct ManifestLoadingDiagnostic: DiagnosticData { 168| | public static let id = DiagnosticID( 169| | type: ManifestLoadingDiagnostic.self, 170| | name: "org.swift.diags.pkg-loading.manifest-output", 171| | defaultBehavior: .warning, 172| | description: { 173| 0| $0 <<< { $0.output } 174| | } 175| | ) 176| | 177| | public let output: String 178| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/ManifestBuilder.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import PackageModel 12| | 13| |struct ManifestBuilder { 14| | var name: String! 15| | var platforms: [PlatformDescription] = [] 16| | var targets: [TargetDescription] = [] 17| | var pkgConfig: String? 18| | var swiftLanguageVersions: [SwiftLanguageVersion]? 19| | var dependencies: [PackageDependencyDescription] = [] 20| | var providers: [SystemPackageProviderDescription]? 21| | var errors: [String] = [] 22| | var products: [ProductDescription] = [] 23| | var cxxLanguageStandard: String? 24| | var cLanguageStandard: String? 25| | 26| | let manifestVersion: ManifestVersion 27| | let baseURL: String 28| | let fs: FileSystem 29| | 30| 0| init(manifestVersion: ManifestVersion, baseURL: String, fileSystem: FileSystem) { 31| 0| self.manifestVersion = manifestVersion 32| 0| self.baseURL = baseURL 33| 0| self.fs = fileSystem 34| 0| } 35| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/ManifestLoader.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import SPMUtility 14| |import SPMLLBuild 15| |import struct POSIX.FileInfo 16| |import class Foundation.ProcessInfo 17| |public typealias FileSystem = Basic.FileSystem 18| | 19| |public enum ManifestParseError: Swift.Error { 20| | /// The manifest contains invalid format. 21| | case invalidManifestFormat(String) 22| | 23| | /// The manifest was successfully loaded by swift interpreter but there were runtime issues. 24| | case runtimeManifestErrors([String]) 25| | 26| | case duplicateDependencyDecl([[PackageDependencyDescription]]) 27| | 28| | case unsupportedAPI(api: String, supportedVersions: [ManifestVersion]) 29| |} 30| | 31| |/// Resources required for manifest loading. 32| |/// 33| |/// These requirements are abstracted out to make it easier to add support for 34| |/// using the package manager with alternate toolchains in the future. 35| |public protocol ManifestResourceProvider { 36| | /// The path of the swift compiler. 37| | var swiftCompiler: AbsolutePath { get } 38| | 39| | /// The path of the library resources. 40| | var libDir: AbsolutePath { get } 41| | 42| | /// The path to SDK root. 43| | /// 44| | /// If provided, it will be passed to the swift interpreter. 45| | var sdkRoot: AbsolutePath? { get } 46| |} 47| | 48| |/// Default implemention for the resource provider. 49| |public extension ManifestResourceProvider { 50| | 51| 0| var sdkRoot: AbsolutePath? { 52| 0| return nil 53| 0| } 54| |} 55| | 56| |extension ToolsVersion { 57| | /// Returns the manifest version for this tools version. 58| 0| public var manifestVersion: ManifestVersion { 59| 0| // FIXME: This works for now but we may want to do something better here 60| 0| // if we're going to have a lot of manifest versions. We can make 61| 0| // ManifestVersion a proper version type and then automatically 62| 0| // determine the best version from the available versions. 63| 0| // 64| 0| // At this point, we expect the tools version to be greater than the minimum required. 65| 0| assert(self >= .minimumRequired, "unexpected tools version \(self)") 66| 0| 67| 0| switch major { 68| 0| case 4: 69| 0| // If the tools version is less than 4.2, return manifest version 4. 70| 0| if minor < 2 { 71| 0| return .v4 72| 0| } 73| 0| 74| 0| // Otherwise, return 4.2 75| 0| return .v4_2 76| 0| 77| 0| default: 78| 0| // For rest, return the latest manifest version. 79| 0| return .v5 80| 0| } 81| 0| } 82| |} 83| | 84| |/// Protocol for the manifest loader interface. 85| |public protocol ManifestLoaderProtocol { 86| | /// Load the manifest for the package at `path`. 87| | /// 88| | /// - Parameters: 89| | /// - path: The root path of the package. 90| | /// - baseURL: The URL the manifest was loaded from. 91| | /// - version: The version the manifest is from, if known. 92| | /// - manifestVersion: The version of manifest to load. 93| | /// - fileSystem: If given, the file system to load from (otherwise load from the local file system). 94| | func load( 95| | packagePath path: AbsolutePath, 96| | baseURL: String, 97| | version: Version?, 98| | manifestVersion: ManifestVersion, 99| | fileSystem: FileSystem?, 100| | diagnostics: DiagnosticsEngine? 101| | ) throws -> Manifest 102| |} 103| | 104| |extension ManifestLoaderProtocol { 105| | /// Load the manifest for the package at `path`. 106| | /// 107| | /// - Parameters: 108| | /// - path: The root path of the package. 109| | /// - baseURL: The URL the manifest was loaded from. 110| | /// - version: The version the manifest is from, if known. 111| | /// - fileSystem: The file system to load from. 112| | public func load( 113| | package path: AbsolutePath, 114| | baseURL: String, 115| | version: Version? = nil, 116| | manifestVersion: ManifestVersion, 117| | fileSystem: FileSystem? = nil, 118| | diagnostics: DiagnosticsEngine? = nil 119| 0| ) throws -> Manifest { 120| 0| return try load( 121| 0| packagePath: path, 122| 0| baseURL: baseURL, 123| 0| version: version, 124| 0| manifestVersion: manifestVersion, 125| 0| fileSystem: fileSystem, 126| 0| diagnostics: diagnostics 127| 0| ) 128| 0| } 129| |} 130| | 131| |public protocol ManifestLoaderDelegate { 132| | func willLoad(manifest: AbsolutePath) 133| | func willParse(manifest: AbsolutePath) 134| |} 135| | 136| |/// Utility class for loading manifest files. 137| |/// 138| |/// This class is responsible for reading the manifest data and produce a 139| |/// properly formed `PackageModel.Manifest` object. It currently does so by 140| |/// interpreting the manifest source using Swift -- that produces a JSON 141| |/// serialized form of the manifest (as implemented by `PackageDescription`'s 142| |/// `atexit()` handler) which is then deserialized and loaded. 143| |public final class ManifestLoader: ManifestLoaderProtocol { 144| | 145| | let resources: ManifestResourceProvider 146| | let isManifestSandboxEnabled: Bool 147| 0| var isManifestCachingEnabled: Bool { 148| 0| return cacheDir != nil 149| 0| } 150| | let cacheDir: AbsolutePath! 151| | let delegate: ManifestLoaderDelegate? 152| | 153| | public init( 154| | manifestResources: ManifestResourceProvider, 155| | isManifestSandboxEnabled: Bool = true, 156| | cacheDir: AbsolutePath? = nil, 157| | delegate: ManifestLoaderDelegate? = nil 158| 0| ) { 159| 0| self.resources = manifestResources 160| 0| self.isManifestSandboxEnabled = isManifestSandboxEnabled 161| 0| self.delegate = delegate 162| 0| self.cacheDir = cacheDir 163| 0| } 164| | 165| | @available(*, deprecated) 166| | public convenience init( 167| | resources: ManifestResourceProvider, 168| | isManifestSandboxEnabled: Bool = true 169| 0| ) { 170| 0| self.init( 171| 0| manifestResources: resources, 172| 0| isManifestSandboxEnabled: isManifestSandboxEnabled 173| 0| ) 174| 0| } 175| | 176| | public func load( 177| | packagePath path: AbsolutePath, 178| | baseURL: String, 179| | version: Version?, 180| | manifestVersion: ManifestVersion, 181| | fileSystem: FileSystem? = nil, 182| | diagnostics: DiagnosticsEngine? = nil 183| 0| ) throws -> Manifest { 184| 0| return try loadFile( 185| 0| path: Manifest.path(atPackagePath: path, fileSystem: fileSystem ?? localFileSystem), 186| 0| baseURL: baseURL, 187| 0| version: version, 188| 0| manifestVersion: manifestVersion, 189| 0| fileSystem: fileSystem, 190| 0| diagnostics: diagnostics 191| 0| ) 192| 0| } 193| | 194| | /// Create a manifest by loading a specific manifest file from the given `path`. 195| | /// 196| | /// - Parameters: 197| | /// - path: The path to the manifest file (or a package root). 198| | /// - baseURL: The URL the manifest was loaded from. 199| | /// - version: The version the manifest is from, if known. 200| | /// - fileSystem: If given, the file system to load from (otherwise load from the local file system). 201| | func loadFile( 202| | path inputPath: AbsolutePath, 203| | baseURL: String, 204| | version: Version?, 205| | manifestVersion: ManifestVersion, 206| | fileSystem: FileSystem? = nil, 207| | diagnostics: DiagnosticsEngine? = nil 208| 0| ) throws -> Manifest { 209| 0| 210| 0| // Inform the delegate. 211| 0| self.delegate?.willLoad(manifest: inputPath) 212| 0| 213| 0| // Validate that the file exists. 214| 0| guard (fileSystem ?? localFileSystem).isFile(inputPath) else { 215| 0| throw PackageModel.Package.Error.noManifest( 216| 0| baseURL: baseURL, version: version?.description) 217| 0| } 218| 0| 219| 0| // Get the JSON string for the manifest. 220| 0| let jsonString: String 221| 0| do { 222| 0| jsonString = try loadJSONString( 223| 0| path: inputPath, manifestVersion: manifestVersion, 224| 0| fs: fileSystem, diagnostics: diagnostics) 225| 0| } catch let error as StringError { 226| 0| throw ManifestParseError.invalidManifestFormat(error.description) 227| 0| } 228| 0| 229| 0| // Load the manifest from JSON. 230| 0| let json = try JSON(string: jsonString) 231| 0| var manifestBuilder = ManifestBuilder( 232| 0| manifestVersion: manifestVersion, 233| 0| baseURL: baseURL, 234| 0| fileSystem: fileSystem ?? localFileSystem 235| 0| ) 236| 0| try manifestBuilder.build(v4: json) 237| 0| 238| 0| // Throw if we encountered any runtime errors. 239| 0| guard manifestBuilder.errors.isEmpty else { 240| 0| throw ManifestParseError.runtimeManifestErrors(manifestBuilder.errors) 241| 0| } 242| 0| 243| 0| let manifest = Manifest( 244| 0| name: manifestBuilder.name, 245| 0| platforms: manifestBuilder.platforms, 246| 0| path: inputPath, 247| 0| url: baseURL, 248| 0| version: version, 249| 0| manifestVersion: manifestVersion, 250| 0| pkgConfig: manifestBuilder.pkgConfig, 251| 0| providers: manifestBuilder.providers, 252| 0| cLanguageStandard: manifestBuilder.cLanguageStandard, 253| 0| cxxLanguageStandard: manifestBuilder.cxxLanguageStandard, 254| 0| swiftLanguageVersions: manifestBuilder.swiftLanguageVersions, 255| 0| dependencies: manifestBuilder.dependencies, 256| 0| products: manifestBuilder.products, 257| 0| targets: manifestBuilder.targets 258| 0| ) 259| 0| 260| 0| try validate(manifest) 261| 0| 262| 0| return manifest 263| 0| } 264| | 265| | /// Validate the provided manifest. 266| 0| private func validate(_ manifest: Manifest) throws { 267| 0| let duplicateDecls = manifest.dependencies.map({ KeyedPair($0, key: PackageReference.computeIdentity(packageURL: $0.url)) }).spm_findDuplicateElements() 268| 0| if !duplicateDecls.isEmpty { 269| 0| throw ManifestParseError.duplicateDependencyDecl(duplicateDecls.map({ $0.map({ $0.item }) })) 270| 0| } 271| 0| } 272| | 273| | /// Load the JSON string for the given manifest. 274| | func loadJSONString( 275| | path inputPath: AbsolutePath, 276| | manifestVersion: ManifestVersion, 277| | fs: FileSystem? = nil, 278| | diagnostics: DiagnosticsEngine? = nil 279| 0| ) throws -> String { 280| 0| // If we were given a filesystem, load via a temporary file. 281| 0| if let fs = fs { 282| 0| let contents = try fs.readFileContents(inputPath) 283| 0| let tmpFile = try TemporaryFile(suffix: ".swift") 284| 0| try localFileSystem.writeFileContents(tmpFile.path, bytes: contents) 285| 0| return try parse(path: tmpFile.path, manifestVersion: manifestVersion, diagnostics: diagnostics) 286| 0| } 287| 0| 288| 0| // Load directly if manifest caching is not enabled. 289| 0| if !self.isManifestCachingEnabled { 290| 0| return try parse(path: inputPath, manifestVersion: manifestVersion, diagnostics: diagnostics) 291| 0| } 292| 0| 293| 0| // Otherwise load via llbuild. 294| 0| let key = ManifestLoadRule.RuleKey( 295| 0| path: inputPath, manifestVersion: manifestVersion) 296| 0| let value = try getEngine().build(key: key) 297| 0| 298| 0| return try value.dematerialize() 299| 0| } 300| | 301| | /// Parse the manifest at the given path to JSON. 302| | func parse( 303| | path manifestPath: AbsolutePath, 304| | manifestVersion: ManifestVersion, 305| | diagnostics: DiagnosticsEngine? = nil 306| 0| ) throws -> String { 307| 0| self.delegate?.willParse(manifest: manifestPath) 308| 0| 309| 0| // The compiler has special meaning for files with extensions like .ll, .bc etc. 310| 0| // Assert that we only try to load files with extension .swift to avoid unexpected loading behavior. 311| 0| assert(manifestPath.extension == "swift", 312| 0| "Manifest files must contain .swift suffix in their name, given: \(manifestPath).") 313| 0| 314| 0| // For now, we load the manifest by having Swift interpret it directly. 315| 0| // Eventually, we should have two loading processes, one that loads only 316| 0| // the declarative package specification using the Swift compiler directly 317| 0| // and validates it. 318| 0| 319| 0| // Compute the path to runtime we need to load. 320| 0| let runtimePath = self.runtimePath(for: manifestVersion).pathString 321| 0| let interpreterFlags = self.interpreterFlags(for: manifestVersion) 322| 0| 323| 0| var cmd = [String]() 324| 0| #if os(macOS) 325| 0| // If enabled, use sandbox-exec on macOS. This provides some safety against 326| 0| // arbitrary code execution when parsing manifest files. We only allow 327| 0| // the permissions which are absolutely necessary for manifest parsing. 328| 0| if isManifestSandboxEnabled { 329| 0| cmd += ["sandbox-exec", "-p", sandboxProfile()] 330| 0| } 331| 0| #endif 332| 0| cmd += [resources.swiftCompiler.pathString] 333| 0| cmd += ["--driver-mode=swift"] 334| 0| cmd += bootstrapArgs() 335| 0| cmd += verbosity.ccArgs 336| 0| cmd += ["-L", runtimePath, "-lPackageDescription"] 337| 0| cmd += interpreterFlags 338| 0| cmd += [manifestPath.pathString] 339| 0| 340| 0| // Create and open a temporary file to write json to. 341| 0| let file = try TemporaryFile() 342| 0| // Pass the fd in arguments. 343| 0| cmd += ["-fileno", "\(file.fileHandle.fileDescriptor)"] 344| 0| 345| 0| // Run the command. 346| 0| let result = try Process.popen(arguments: cmd) 347| 0| let output = try (result.utf8Output() + result.utf8stderrOutput()).spm_chuzzle() 348| 0| 349| 0| // Throw an error if there was a non-zero exit or emit the output 350| 0| // produced by the process. A process output will usually mean there 351| 0| // was a warning emitted by the Swift compiler. 352| 0| if result.exitStatus != .terminated(code: 0) { 353| 0| throw StringError(output ?? "") 354| 0| } else if let output = output { 355| 0| diagnostics?.emit(data: ManifestLoadingDiagnostic(output: output)) 356| 0| } 357| 0| 358| 0| guard let json = try localFileSystem.readFileContents(file.path).validDescription else { 359| 0| throw StringError("the manifest has invalid encoding") 360| 0| } 361| 0| 362| 0| return json 363| 0| } 364| | 365| | /// Returns the extra manifest args required during SwiftPM's own bootstrap. 366| 0| private func bootstrapArgs() -> [String] { 367| 0| #if !os(Linux) 368| 0| return [] 369| 0| #else 370| 0| // The Linux bots require extra arguments in order to locate the corelibs. 371| 0| // We can potentially drop this by installing some stable linux toolchain 372| 0| // after Swift gets ABI and module stability. 373| 0| // 374| 0| // Compute if SwiftPM is bootstrapping. 375| 0| let env = ProcessInfo.processInfo.environment 376| 0| guard env.keys.contains("SWIFTPM_BOOTSTRAP") else { return [] } 377| 0| guard let buildPathStr = env["SWIFTPM_BUILD_DIR"], let buildPath = try? AbsolutePath(validating: buildPathStr) else { 378| 0| return [] 379| 0| } 380| 0| 381| 0| // Construct the required search paths relative to the build directory. 382| 0| let libdir = buildPath.appending(RelativePath(".bootstrap/lib/swift/linux")) 383| 0| let incdir = libdir.appending(component: "x86_64") 384| 0| let dispatchIncdir = incdir.appending(component: "dispatch") 385| 0| 386| 0| return [ 387| 0| "-I\(incdir)", 388| 0| "-I\(dispatchIncdir)", 389| 0| "-L\(libdir)", 390| 0| "-Xcc", "-F\(incdir)", 391| 0| ] 392| 0| #endif 393| 0| } 394| | 395| | /// Returns path to the sdk, if possible. 396| 0| private func sdkRoot() -> AbsolutePath? { 397| 0| if let sdkRoot = _sdkRoot { 398| 0| return sdkRoot 399| 0| } 400| 0| 401| 0| // Find SDKROOT on macOS using xcrun. 402| 0| #if os(macOS) 403| 0| let foundPath = try? Process.checkNonZeroExit( 404| 0| args: "xcrun", "--sdk", "macosx", "--show-sdk-path") 405| 0| guard let sdkRoot = foundPath?.spm_chomp(), !sdkRoot.isEmpty else { 406| 0| return nil 407| 0| } 408| 0| _sdkRoot = AbsolutePath(sdkRoot) 409| 0| #endif 410| 0| 411| 0| return _sdkRoot 412| 0| } 413| | // Cache storage for computed sdk path. 414| | private var _sdkRoot: AbsolutePath? = nil 415| | 416| | /// Returns the interpreter flags for a manifest. 417| | public func interpreterFlags( 418| | for manifestVersion: ManifestVersion 419| 0| ) -> [String] { 420| 0| var cmd = [String]() 421| 0| let runtimePath = self.runtimePath(for: manifestVersion) 422| 0| cmd += ["-swift-version", manifestVersion.swiftLanguageVersion.rawValue] 423| 0| cmd += ["-I", runtimePath.pathString] 424| 0| #if os(macOS) 425| 0| cmd += ["-target", "x86_64-apple-macosx10.10"] 426| 0| #endif 427| 0| if let sdkRoot = resources.sdkRoot ?? self.sdkRoot() { 428| 0| cmd += ["-sdk", sdkRoot.pathString] 429| 0| } 430| 0| return cmd 431| 0| } 432| | 433| | /// Returns the runtime path given the manifest version and path to libDir. 434| 0| private func runtimePath(for version: ManifestVersion) -> AbsolutePath { 435| 0| return resources.libDir.appending(version.runtimeSubpath) 436| 0| } 437| | 438| | /// Returns the build engine. 439| 0| private func getEngine() throws -> LLBuildEngine { 440| 0| if let engine = _engine { 441| 0| return engine 442| 0| } 443| 0| 444| 0| let cacheDelegate = ManifestCacheDelegate() 445| 0| let engine = LLBuildEngine(delegate: cacheDelegate) 446| 0| cacheDelegate.loader = self 447| 0| 448| 0| if isManifestCachingEnabled { 449| 0| try localFileSystem.createDirectory(cacheDir, recursive: true) 450| 0| try engine.attachDB(path: cacheDir.appending(component: "manifest.db").pathString) 451| 0| } 452| 0| _engine = engine 453| 0| return engine 454| 0| } 455| | private var _engine: LLBuildEngine? 456| |} 457| | 458| |/// Returns the sandbox profile to be used when parsing manifest on macOS. 459| 0|private func sandboxProfile() -> String { 460| 0| let stream = BufferedOutputByteStream() 461| 0| stream <<< "(version 1)" <<< "\n" 462| 0| // Deny everything by default. 463| 0| stream <<< "(deny default)" <<< "\n" 464| 0| // Import the system sandbox profile. 465| 0| stream <<< "(import \"system.sb\")" <<< "\n" 466| 0| // Allow reading all files. 467| 0| stream <<< "(allow file-read*)" <<< "\n" 468| 0| // These are required by the Swift compiler. 469| 0| stream <<< "(allow process*)" <<< "\n" 470| 0| stream <<< "(allow sysctl*)" <<< "\n" 471| 0| // Allow writing in temporary locations. 472| 0| stream <<< "(allow file-write*" <<< "\n" 473| 0| for directory in Platform.darwinCacheDirectories() { 474| 0| stream <<< " (regex #\"^\(directory.pathString)/org\\.llvm\\.clang.*\")" <<< "\n" 475| 0| } 476| 0| stream <<< ")" <<< "\n" 477| 0| return stream.bytes.description 478| 0|} 479| | 480| |// FIXME: We should probably just remove this and make all Manifest errors Codable. 481| |/// Represents a string error. 482| |struct StringError: Equatable, Codable, CustomStringConvertible, Error { 483| | 484| | /// The description of the error. 485| | public let description: String 486| | 487| | /// Create an instance of StringError. 488| 0| public init(_ description: String) { 489| 0| self.description = description 490| 0| } 491| |} 492| | 493| |extension Result where ErrorType == StringError { 494| | /// Create an instance of Result. 495| | /// 496| | /// Errors will be encoded as StringError using their description. 497| 0| init(string body: () throws -> Value) { 498| 0| do { 499| 0| self = .success(try body()) 500| 0| } catch let error as StringError { 501| 0| self = .failure(error) 502| 0| } catch { 503| 0| self = .failure(StringError(String(describing: error))) 504| 0| } 505| 0| } 506| |} 507| | 508| |// MARK:- Caching support. 509| | 510| |extension Result: LLBuildValue where Value: Codable, ErrorType: Codable {} 511| | 512| |final class ManifestCacheDelegate: LLBuildEngineDelegate { 513| | 514| | weak var loader: ManifestLoader! 515| | 516| 0| func lookupRule(rule: String, key: Key) -> Rule { 517| 0| switch rule { 518| 0| case ManifestLoadRule.ruleName: 519| 0| return ManifestLoadRule(key, loader: loader) 520| 0| case FileInfoRule.ruleName: 521| 0| return FileInfoRule(key) 522| 0| case SwiftPMVersionRule.ruleName: 523| 0| return SwiftPMVersionRule() 524| 0| case ProcessEnvRule.ruleName: 525| 0| return ProcessEnvRule() 526| 0| default: 527| 0| fatalError("Unknown rule \(rule)") 528| 0| } 529| 0| } 530| |} 531| | 532| |/// A rule to load a package manifest. 533| |/// 534| |/// The rule can currently only load manifests which are physically present on 535| |/// the local file system. The rule will re-run if the manifest is modified. 536| |final class ManifestLoadRule: LLBuildRule { 537| | 538| | struct RuleKey: LLBuildKey { 539| | typealias BuildValue = RuleValue 540| | typealias BuildRule = ManifestLoadRule 541| | 542| | let path: AbsolutePath 543| | let manifestVersion: ManifestVersion 544| | } 545| | 546| | typealias RuleValue = Result 547| | 548| 0| override class var ruleName: String { return "\(ManifestLoadRule.self)" } 549| | 550| | private let key: RuleKey 551| | private weak var loader: ManifestLoader! 552| | 553| 0| init(_ key: Key, loader: ManifestLoader) { 554| 0| self.key = RuleKey(key) 555| 0| self.loader = loader 556| 0| super.init() 557| 0| } 558| | 559| 0| override func start(_ engine: LLTaskBuildEngine) { 560| 0| // FIXME: Ideally, we should expose an API in the manifest file to track individual 561| 0| // environment variables instead of blindly invalidating when *anything* changes. 562| 0| engine.taskNeedsInput(ProcessEnvRule.RuleKey(), inputID: 1) 563| 0| 564| 0| engine.taskNeedsInput(SwiftPMVersionRule.RuleKey(), inputID: 2) 565| 0| engine.taskNeedsInput(FileInfoRule.RuleKey(path: key.path), inputID: 3) 566| 0| } 567| | 568| 0| override func inputsAvailable(_ engine: LLTaskBuildEngine) { 569| 0| let value = RuleValue(string: { 570| 0| try loader.parse(path: key.path, manifestVersion: key.manifestVersion) 571| 0| }) 572| 0| engine.taskIsComplete(value) 573| 0| } 574| |} 575| | 576| |// FIXME: Find a proper place for this rule. 577| |/// A rule to compute the current process environment. 578| |/// 579| |/// This rule will always run. 580| |final class ProcessEnvRule: LLBuildRule { 581| | 582| | struct RuleKey: LLBuildKey { 583| | typealias BuildValue = RuleValue 584| | typealias BuildRule = ProcessEnvRule 585| | } 586| | 587| | struct RuleValue: LLBuildValue, Equatable { 588| | let env: [String: String] 589| | } 590| | 591| 0| override class var ruleName: String { return "\(ProcessEnvRule.self)" } 592| | 593| 0| override func isResultValid(_ priorValue: Value) -> Bool { 594| 0| // Always rebuild this rule. 595| 0| return false 596| 0| } 597| | 598| 0| override func inputsAvailable(_ engine: LLTaskBuildEngine) { 599| 0| let env = ProcessInfo.processInfo.environment 600| 0| engine.taskIsComplete(RuleValue(env: env)) 601| 0| } 602| |} 603| | 604| |// FIXME: Find a proper place for this rule. 605| |/// A rule to get file info of a file on disk. 606| |final class FileInfoRule: LLBuildRule { 607| | 608| | struct RuleKey: LLBuildKey { 609| | typealias BuildValue = RuleValue 610| | typealias BuildRule = FileInfoRule 611| | 612| | let path: AbsolutePath 613| | } 614| | 615| | typealias RuleValue = Result 616| | 617| 0| override class var ruleName: String { return "\(FileInfoRule.self)" } 618| | 619| | private let key: RuleKey 620| | 621| 0| init(_ key: Key) { 622| 0| self.key = RuleKey(key) 623| 0| super.init() 624| 0| } 625| | 626| 0| override func isResultValid(_ priorValue: Value) -> Bool { 627| 0| let priorValue = RuleValue(priorValue) 628| 0| 629| 0| // Always rebuild if we had a failure. 630| 0| if case .failure = priorValue { 631| 0| return false 632| 0| } 633| 0| return getFileInfo(key.path) == priorValue 634| 0| } 635| | 636| 0| override func inputsAvailable(_ engine: LLTaskBuildEngine) { 637| 0| engine.taskIsComplete(getFileInfo(key.path)) 638| 0| } 639| | 640| 0| private func getFileInfo(_ path: AbsolutePath) -> RuleValue { 641| 0| return RuleValue(string: { 642| 0| try localFileSystem.getFileInfo(key.path) 643| 0| }) 644| 0| } 645| |} 646| | 647| |// FIXME: Find a proper place for this rule. 648| |/// A rule to compute the current version of the pacakge manager. 649| |/// 650| |/// This rule will always run. 651| |final class SwiftPMVersionRule: LLBuildRule { 652| | 653| | struct RuleKey: LLBuildKey { 654| | typealias BuildValue = RuleValue 655| | typealias BuildRule = SwiftPMVersionRule 656| | } 657| | 658| | struct RuleValue: LLBuildValue, Equatable { 659| | let version: String 660| | } 661| | 662| 0| override class var ruleName: String { return "\(SwiftPMVersionRule.self)" } 663| | 664| 0| override func isResultValid(_ priorValue: Value) -> Bool { 665| 0| // Always rebuild this rule. 666| 0| return false 667| 0| } 668| | 669| 0| override func inputsAvailable(_ engine: LLTaskBuildEngine) { 670| 0| // FIXME: We need to include git hash in the version 671| 0| // string to make this rule more correct. 672| 0| let version = Versioning.currentVersion.displayString 673| 0| engine.taskIsComplete(RuleValue(version: version)) 674| 0| } 675| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/ModuleMapGenerator.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import PackageModel 13| | 14| |public let moduleMapFilename = "module.modulemap" 15| | 16| |/// A protocol for targets which might have a modulemap. 17| |protocol ModuleMapProtocol { 18| | var moduleMapPath: AbsolutePath { get } 19| | 20| | var moduleMapDirectory: AbsolutePath { get } 21| |} 22| | 23| |extension SystemLibraryTarget: ModuleMapProtocol { 24| 0| var moduleMapDirectory: AbsolutePath { 25| 0| return path 26| 0| } 27| | 28| 0| public var moduleMapPath: AbsolutePath { 29| 0| return moduleMapDirectory.appending(component: moduleMapFilename) 30| 0| } 31| |} 32| | 33| |extension ClangTarget: ModuleMapProtocol { 34| 0| var moduleMapDirectory: AbsolutePath { 35| 0| return includeDir 36| 0| } 37| | 38| 0| public var moduleMapPath: AbsolutePath { 39| 0| return moduleMapDirectory.appending(component: moduleMapFilename) 40| 0| } 41| |} 42| | 43| |/// A modulemap generator for clang targets. 44| |/// 45| |/// Modulemap is generated under the following rules provided it is not already present in include directory: 46| |/// 47| |/// * "include/foo/foo.h" exists and `foo` is the only directory under include directory. 48| |/// Generates: `umbrella header "/path/to/include/foo/foo.h"` 49| |/// * "include/foo.h" exists and include contains no other directory. 50| |/// Generates: `umbrella header "/path/to/include/foo.h"` 51| |/// * Otherwise in all other cases. 52| |/// Generates: `umbrella "path/to/include"` 53| |public struct ModuleMapGenerator { 54| | 55| | /// The clang target to operate on. 56| | private let target: ClangTarget 57| | 58| | /// The file system to be used. 59| | private var fileSystem: FileSystem 60| | 61| | /// Stream on which warnings will be emitted. 62| | private let warningStream: OutputByteStream 63| | 64| | public init( 65| | for target: ClangTarget, 66| | fileSystem: FileSystem = localFileSystem, 67| | warningStream: OutputByteStream = stdoutStream 68| 0| ) { 69| 0| self.target = target 70| 0| self.fileSystem = fileSystem 71| 0| self.warningStream = warningStream 72| 0| } 73| | 74| | public enum ModuleMapError: Swift.Error { 75| | case unsupportedIncludeLayoutForModule(String, UnsupportedIncludeLayoutType) 76| | 77| | public enum UnsupportedIncludeLayoutType { 78| | case umbrellaHeaderWithAdditionalNonEmptyDirectories(AbsolutePath, [AbsolutePath]) 79| | case umbrellaHeaderWithAdditionalDirectoriesInIncludeDirectory(AbsolutePath, [AbsolutePath]) 80| | case umbrellaHeaderWithAdditionalFilesInIncludeDirectory(AbsolutePath, [AbsolutePath]) 81| | } 82| | } 83| | 84| | /// Create the synthesized modulemap, if necessary. 85| | /// Note: modulemap is not generated for test targets. 86| 0| public mutating func generateModuleMap(inDir wd: AbsolutePath) throws { 87| 0| assert(target.type == .library) 88| 0| 89| 0| // Return if modulemap is already present. 90| 0| guard !fileSystem.isFile(target.moduleMapPath) else { 91| 0| return 92| 0| } 93| 0| 94| 0| let includeDir = target.includeDir 95| 0| // Warn and return if no include directory. 96| 0| guard fileSystem.isDirectory(includeDir) else { 97| 0| warningStream <<< ("warning: no include directory found for target '\(target.name)'; " + 98| 0| "libraries cannot be imported without public headers") 99| 0| warningStream.flush() 100| 0| return 101| 0| } 102| 0| 103| 0| let walked = try fileSystem.getDirectoryContents(includeDir).map({ includeDir.appending(component: $0) }) 104| 0| 105| 0| let files = walked.filter({ fileSystem.isFile($0) && $0.suffix == ".h" }) 106| 0| let dirs = walked.filter({ fileSystem.isDirectory($0) }) 107| 0| 108| 0| let umbrellaHeaderFlat = includeDir.appending(component: target.c99name + ".h") 109| 0| if fileSystem.isFile(umbrellaHeaderFlat) { 110| 0| guard dirs.isEmpty else { 111| 0| throw ModuleMapError.unsupportedIncludeLayoutForModule( 112| 0| target.name, 113| 0| .umbrellaHeaderWithAdditionalNonEmptyDirectories(umbrellaHeaderFlat, dirs)) 114| 0| } 115| 0| try createModuleMap(inDir: wd, type: .header(umbrellaHeaderFlat)) 116| 0| return 117| 0| } 118| 0| diagnoseInvalidUmbrellaHeader(includeDir) 119| 0| 120| 0| let umbrellaHeader = includeDir.appending(components: target.c99name, target.c99name + ".h") 121| 0| if fileSystem.isFile(umbrellaHeader) { 122| 0| guard dirs.count == 1 else { 123| 0| throw ModuleMapError.unsupportedIncludeLayoutForModule( 124| 0| target.name, 125| 0| .umbrellaHeaderWithAdditionalDirectoriesInIncludeDirectory(umbrellaHeader, dirs)) 126| 0| } 127| 0| guard files.isEmpty else { 128| 0| throw ModuleMapError.unsupportedIncludeLayoutForModule( 129| 0| target.name, 130| 0| .umbrellaHeaderWithAdditionalFilesInIncludeDirectory(umbrellaHeader, files)) 131| 0| } 132| 0| try createModuleMap(inDir: wd, type: .header(umbrellaHeader)) 133| 0| return 134| 0| } 135| 0| diagnoseInvalidUmbrellaHeader(includeDir.appending(component: target.c99name)) 136| 0| 137| 0| try createModuleMap(inDir: wd, type: .directory(includeDir)) 138| 0| } 139| | 140| | /// Warn user if in case target name and c99name are different and there is a 141| | /// `name.h` umbrella header. 142| 0| private func diagnoseInvalidUmbrellaHeader(_ path: AbsolutePath) { 143| 0| let umbrellaHeader = path.appending(component: target.c99name + ".h") 144| 0| let invalidUmbrellaHeader = path.appending(component: target.name + ".h") 145| 0| if target.c99name != target.name && fileSystem.isFile(invalidUmbrellaHeader) { 146| 0| warningStream <<< "warning: \(invalidUmbrellaHeader.pathString) should be renamed to " 147| 0| warningStream <<< "\(umbrellaHeader.pathString) to be used as an umbrella header" 148| 0| warningStream.flush() 149| 0| } 150| 0| } 151| | 152| | private enum UmbrellaType { 153| | case header(AbsolutePath) 154| | case directory(AbsolutePath) 155| | } 156| | 157| 0| private mutating func createModuleMap(inDir wd: AbsolutePath, type: UmbrellaType) throws { 158| 0| let stream = BufferedOutputByteStream() 159| 0| stream <<< "module \(target.c99name) {\n" 160| 0| switch type { 161| 0| case .header(let header): 162| 0| stream <<< " umbrella header \"\(header.pathString)\"\n" 163| 0| case .directory(let path): 164| 0| stream <<< " umbrella \"\(path.pathString)\"\n" 165| 0| } 166| 0| stream <<< " export *\n" 167| 0| stream <<< "}\n" 168| 0| 169| 0| // FIXME: This doesn't belong here. 170| 0| try fileSystem.createDirectory(wd, recursive: true) 171| 0| 172| 0| let file = wd.appending(component: moduleMapFilename) 173| 0| 174| 0| // If the file exists with the identical contents, we don't need to rewrite it. 175| 0| // Otherwise, compiler will recompile even if nothing else has changed. 176| 0| if let contents = try? localFileSystem.readFileContents(file), contents == stream.bytes { 177| 0| return 178| 0| } 179| 0| try fileSystem.writeFileContents(file, bytes: stream.bytes) 180| 0| } 181| |} 182| | 183| |extension ModuleMapGenerator.ModuleMapError: CustomStringConvertible { 184| 0| public var description: String { 185| 0| switch self { 186| 0| case .unsupportedIncludeLayoutForModule(let (name, problem)): 187| 0| return "target '\(name)' failed modulemap generation; \(problem)" 188| 0| } 189| 0| } 190| |} 191| | 192| |extension ModuleMapGenerator.ModuleMapError.UnsupportedIncludeLayoutType: CustomStringConvertible { 193| 0| public var description: String { 194| 0| switch self { 195| 0| case .umbrellaHeaderWithAdditionalNonEmptyDirectories(let (umbrella, dirs)): 196| 0| return "umbrella header defined at '\(umbrella.pathString)', but directories exist: " + 197| 0| dirs.map({ $0.pathString }).sorted().joined(separator: ", ") + 198| 0| "; consider removing them" 199| 0| case .umbrellaHeaderWithAdditionalDirectoriesInIncludeDirectory(let (umbrella, dirs)): 200| 0| return "umbrella header defined at '\(umbrella.pathString)', but more than one directories exist: " + 201| 0| dirs.map({ $0.pathString }).sorted().joined(separator: ", ") + 202| 0| "; consider reducing them to one" 203| 0| case .umbrellaHeaderWithAdditionalFilesInIncludeDirectory(let (umbrella, files)): 204| 0| return "umbrella header defined at '\(umbrella.pathString)', but files exist:" + 205| 0| files.map({ $0.pathString }).sorted().joined(separator: ", ") + 206| 0| "; consider removing them" 207| 0| } 208| 0| } 209| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/PackageBuilder.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import SPMUtility 14| | 15| |/// An error in the structure or layout of a package. 16| |public enum ModuleError: Swift.Error { 17| | 18| | /// Describes a way in which a package layout is invalid. 19| | public enum InvalidLayoutType { 20| | case multipleSourceRoots([String]) 21| | case modulemapInSources(String) 22| | } 23| | 24| | /// Indicates two targets with the same name and their corresponding packages. 25| | case duplicateModule(String, [String]) 26| | 27| | /// One or more referenced targets could not be found. 28| | case modulesNotFound([String]) 29| | 30| | /// Invalid custom path. 31| | case invalidCustomPath(target: String, path: String) 32| | 33| | /// Package layout is invalid. 34| | case invalidLayout(InvalidLayoutType) 35| | 36| | /// The manifest has invalid configuration wrt type of the target. 37| | case invalidManifestConfig(String, String) 38| | 39| | /// The target dependency declaration has cycle in it. 40| | case cycleDetected((path: [String], cycle: [String])) 41| | 42| | /// The public headers directory is at an invalid path. 43| | case invalidPublicHeadersDirectory(String) 44| | 45| | /// The sources of a target are overlapping with another target. 46| | case overlappingSources(target: String, sources: [AbsolutePath]) 47| | 48| | /// We found multiple LinuxMain.swift files. 49| | case multipleLinuxMainFound(package: String, linuxMainFiles: [AbsolutePath]) 50| | 51| | /// The tools version in use is not compatible with target's sources. 52| | case incompatibleToolsVersions(package: String, required: [SwiftLanguageVersion], current: ToolsVersion) 53| | 54| | /// The target path is outside the package. 55| | case targetOutsidePackage(package: String, target: String) 56| | 57| | /// Unsupported target path 58| | case unsupportedTargetPath(String) 59| | 60| | /// Invalid header search path. 61| | case invalidHeaderSearchPath(String) 62| |} 63| | 64| |extension ModuleError: CustomStringConvertible { 65| 0| public var description: String { 66| 0| switch self { 67| 0| case .duplicateModule(let name, let packages): 68| 0| let packages = packages.joined(separator: ", ") 69| 0| return "multiple targets named '\(name)' in: \(packages)" 70| 0| case .modulesNotFound(let targets): 71| 0| let targets = targets.joined(separator: ", ") 72| 0| return "could not find source files for target(s): \(targets); use the 'path' property in the Swift 4 manifest to set a custom target path" 73| 0| case .invalidLayout(let type): 74| 0| return "package has unsupported layout; \(type)" 75| 0| case .invalidManifestConfig(let package, let message): 76| 0| return "configuration of package '\(package)' is invalid; \(message)" 77| 0| case .cycleDetected(let cycle): 78| 0| return "cyclic dependency declaration found: " + 79| 0| (cycle.path + cycle.cycle).joined(separator: " -> ") + 80| 0| " -> " + cycle.cycle[0] 81| 0| case .invalidPublicHeadersDirectory(let name): 82| 0| return "public headers directory path for '\(name)' is invalid or not contained in the target" 83| 0| case .overlappingSources(let target, let sources): 84| 0| return "target '\(target)' has sources overlapping sources: " + 85| 0| sources.map({ $0.pathString }).joined(separator: ", ") 86| 0| case .multipleLinuxMainFound(let package, let linuxMainFiles): 87| 0| return "package '\(package)' has multiple linux main files: " + 88| 0| linuxMainFiles.map({ $0.pathString }).sorted().joined(separator: ", ") 89| 0| case .incompatibleToolsVersions(let package, let required, let current): 90| 0| if required.isEmpty { 91| 0| return "package '\(package)' supported Swift language versions is empty" 92| 0| } 93| 0| return "package '\(package)' requires minimum Swift language version \(required[0]) which is not supported by the current tools version (\(current))" 94| 0| case .targetOutsidePackage(let package, let target): 95| 0| return "target '\(target)' in package '\(package)' is outside the package root" 96| 0| case .unsupportedTargetPath(let targetPath): 97| 0| return "target path '\(targetPath)' is not supported; it should be relative to package root" 98| 0| case .invalidCustomPath(let target, let path): 99| 0| return "invalid custom path '\(path)' for target '\(target)'" 100| 0| case .invalidHeaderSearchPath(let path): 101| 0| return "invalid header search path '\(path)'; header search path should not be outside the package root" 102| 0| } 103| 0| } 104| |} 105| | 106| |extension ModuleError.InvalidLayoutType: CustomStringConvertible { 107| 0| public var description: String { 108| 0| switch self { 109| 0| case .multipleSourceRoots(let paths): 110| 0| return "multiple source roots found: " + paths.sorted().joined(separator: ", ") 111| 0| case .modulemapInSources(let path): 112| 0| return "modulemap '\(path)' should be inside the 'include' directory" 113| 0| } 114| 0| } 115| |} 116| | 117| |extension Target { 118| | 119| | /// An error in the organization or configuration of an individual target. 120| | enum Error: Swift.Error { 121| | 122| | /// The target's name is invalid. 123| | case invalidName(path: String, problem: ModuleNameProblem) 124| | enum ModuleNameProblem { 125| | /// Empty target name. 126| | case emptyName 127| | } 128| | 129| | /// The target contains an invalid mix of languages (e.g. both Swift and C). 130| | case mixedSources(String) 131| | 132| | /// The manifest contains duplicate targets. 133| | case duplicateTargets([String]) 134| | } 135| |} 136| | 137| |extension Target.Error: CustomStringConvertible { 138| 0| var description: String { 139| 0| switch self { 140| 0| case .invalidName(let path, let problem): 141| 0| return "invalid target name at '\(path)'; \(problem)" 142| 0| case .mixedSources(let path): 143| 0| return "target at '\(path)' contains mixed language source files; feature not supported" 144| 0| case .duplicateTargets(let targets): 145| 0| return "duplicate targets found: " + targets.joined(separator: ", ") 146| 0| } 147| 0| } 148| |} 149| | 150| |extension Target.Error.ModuleNameProblem: CustomStringConvertible { 151| 0| var description: String { 152| 0| switch self { 153| 0| case .emptyName: 154| 0| return "target names can not be empty" 155| 0| } 156| 0| } 157| |} 158| | 159| |extension Product { 160| | /// An error in a product definition. 161| | enum Error: Swift.Error { 162| | case noModules(String) 163| | case moduleNotFound(product: String, target: String) 164| | } 165| |} 166| | 167| |extension Product.Error: CustomStringConvertible { 168| 0| var description: String { 169| 0| switch self { 170| 0| case .noModules(let product): 171| 0| return "product '\(product)' doesn't reference any targets" 172| 0| case .moduleNotFound(let product, let target): 173| 0| return "target '\(target)' referenced in product '\(product)' could not be found" 174| 0| } 175| 0| } 176| |} 177| | 178| |/// Helper for constructing a package following the convention system. 179| |/// 180| |/// The 'builder' here refers to the builder pattern and not any build system 181| |/// related function. 182| |public final class PackageBuilder { 183| | /// The manifest for the package being constructed. 184| | private let manifest: Manifest 185| | 186| | /// The path of the package. 187| | private let packagePath: AbsolutePath 188| | 189| | /// The filesystem package builder will run on. 190| | private let fileSystem: FileSystem 191| | 192| | /// The diagnostics engine. 193| | private let diagnostics: DiagnosticsEngine 194| | 195| | /// True if this is the root package. 196| | private let isRootPackage: Bool 197| | 198| | /// Create multiple test products. 199| | /// 200| | /// If set to true, one test product will be created for each test target. 201| | private let shouldCreateMultipleTestProducts: Bool 202| | 203| | /// Create the special REPL product for this package. 204| | private let createREPLProduct: Bool 205| | 206| | /// Create a builder for the given manifest and package `path`. 207| | /// 208| | /// - Parameters: 209| | /// - manifest: The manifest of this package. 210| | /// - path: The root path of the package. 211| | /// - fileSystem: The file system on which the builder should be run. 212| | /// - diagnostics: The diagnostics engine. 213| | /// - isRootPackage: If this is a root package. 214| | /// - createMultipleTestProducts: If enabled, create one test product for 215| | /// each test target. 216| | public init( 217| | manifest: Manifest, 218| | path: AbsolutePath, 219| | fileSystem: FileSystem = localFileSystem, 220| | diagnostics: DiagnosticsEngine, 221| | isRootPackage: Bool, 222| | shouldCreateMultipleTestProducts: Bool = false, 223| | createREPLProduct: Bool = false 224| 0| ) { 225| 0| self.isRootPackage = isRootPackage 226| 0| self.manifest = manifest 227| 0| self.packagePath = path 228| 0| self.fileSystem = fileSystem 229| 0| self.diagnostics = diagnostics 230| 0| self.shouldCreateMultipleTestProducts = shouldCreateMultipleTestProducts 231| 0| self.createREPLProduct = createREPLProduct 232| 0| } 233| | 234| | /// Build a new package following the conventions. 235| 0| public func construct() throws -> Package { 236| 0| let targets = try constructTargets() 237| 0| let products = try constructProducts(targets) 238| 0| // Find the special directory for targets. 239| 0| let targetSpecialDirs = findTargetSpecialDirs(targets) 240| 0| 241| 0| return Package( 242| 0| manifest: manifest, 243| 0| path: packagePath, 244| 0| targets: targets, 245| 0| products: products, 246| 0| targetSearchPath: packagePath.appending(component: targetSpecialDirs.targetDir), 247| 0| testTargetSearchPath: packagePath.appending(component: targetSpecialDirs.testTargetDir) 248| 0| ) 249| 0| } 250| | 251| 0| private func diagnosticLocation() -> DiagnosticLocation { 252| 0| return PackageLocation.Local(name: manifest.name, packagePath: packagePath) 253| 0| } 254| | 255| | /// Computes the special directory where targets are present or should be placed in future. 256| 0| private func findTargetSpecialDirs(_ targets: [Target]) -> (targetDir: String, testTargetDir: String) { 257| 0| let predefinedDirs = findPredefinedTargetDirectory() 258| 0| 259| 0| // Select the preferred tests directory. 260| 0| var testTargetDir = PackageBuilder.predefinedTestDirectories[0] 261| 0| 262| 0| // If found predefined test directory is not same as preferred test directory, 263| 0| // check if any of the test target is actually inside the predefined test directory. 264| 0| if predefinedDirs.testTargetDir != testTargetDir { 265| 0| let expectedTestsDir = packagePath.appending(component: predefinedDirs.testTargetDir) 266| 0| for target in targets where target.type == .test { 267| 0| // If yes, use the predefined test directory as preferred test directory. 268| 0| if expectedTestsDir == target.sources.root.parentDirectory { 269| 0| testTargetDir = predefinedDirs.testTargetDir 270| 0| break 271| 0| } 272| 0| } 273| 0| } 274| 0| 275| 0| return (predefinedDirs.targetDir, testTargetDir) 276| 0| } 277| | 278| | // MARK: Utility Predicates 279| | 280| 0| private func isValidSource(_ path: AbsolutePath) -> Bool { 281| 0| // Ignore files which don't match the expected extensions. 282| 0| guard let ext = path.extension, SupportedLanguageExtension.validExtensions(manifestVersion: self.manifest.manifestVersion).contains(ext) else { 283| 0| return false 284| 0| } 285| 0| 286| 0| let basename = path.basename 287| 0| 288| 0| // Ignore dotfiles. 289| 0| if basename.hasPrefix(".") { return false } 290| 0| 291| 0| // Ignore linux main. 292| 0| if basename == SwiftTarget.linuxMainBasename { return false } 293| 0| 294| 0| // Ignore paths which are not valid files. 295| 0| if !fileSystem.isFile(path) { 296| 0| 297| 0| // Diagnose broken symlinks. 298| 0| if fileSystem.isSymlink(path) { 299| 0| diagnostics.emit( 300| 0| data: PackageBuilderDiagnostics.BorkenSymlinkDiagnostic(path: path.pathString), 301| 0| location: diagnosticLocation() 302| 0| ) 303| 0| } 304| 0| 305| 0| return false 306| 0| } 307| 0| 308| 0| // Ignore manifest files. 309| 0| if path.parentDirectory == packagePath { 310| 0| if basename == Manifest.filename { return false } 311| 0| 312| 0| // Ignore version-specific manifest files. 313| 0| if basename.hasPrefix(Manifest.basename + "@") && basename.hasSuffix(".swift") { 314| 0| return false 315| 0| } 316| 0| } 317| 0| 318| 0| // Otherwise, we have a valid source file. 319| 0| return true 320| 0| } 321| | 322| 0| private func shouldConsiderDirectory(_ path: AbsolutePath) -> Bool { 323| 0| let base = path.basename.lowercased() 324| 0| if base == "tests" { return false } 325| 0| if base == "include" { return false } 326| 0| if base.hasSuffix(".xcodeproj") { return false } 327| 0| if base.hasSuffix(".playground") { return false } 328| 0| if base.hasPrefix(".") { return false } // eg .git 329| 0| if path == packagesDirectory { return false } 330| 0| if !fileSystem.isDirectory(path) { return false } 331| 0| return true 332| 0| } 333| | 334| 0| private var packagesDirectory: AbsolutePath { 335| 0| return packagePath.appending(component: "Packages") 336| 0| } 337| | 338| | /// Returns path to all the items in a directory. 339| | // FIXME: This is generic functionality, and should move to FileSystem. 340| 0| func directoryContents(_ path: AbsolutePath) throws -> [AbsolutePath] { 341| 0| return try fileSystem.getDirectoryContents(path).map({ path.appending(component: $0) }) 342| 0| } 343| | 344| | /// Private function that creates and returns a list of targets defined by a package. 345| 0| private func constructTargets() throws -> [Target] { 346| 0| 347| 0| // Ensure no dupicate target definitions are found. 348| 0| let duplicateTargetNames: [String] = manifest.targets.map({ $0.name 349| 0| }).spm_findDuplicates() 350| 0| 351| 0| if !duplicateTargetNames.isEmpty { 352| 0| throw Target.Error.duplicateTargets(duplicateTargetNames) 353| 0| } 354| 0| 355| 0| // Check for a modulemap file, which indicates a system target. 356| 0| let moduleMapPath = packagePath.appending(component: moduleMapFilename) 357| 0| if fileSystem.isFile(moduleMapPath) { 358| 0| 359| 0| // Warn about any declared targets. 360| 0| let targets = manifest.targets 361| 0| if !targets.isEmpty { 362| 0| diagnostics.emit( 363| 0| data: PackageBuilderDiagnostics.SystemPackageDeclaresTargetsDiagnostic(targets: targets.map({ $0.name })), 364| 0| location: diagnosticLocation() 365| 0| ) 366| 0| } 367| 0| 368| 0| // Emit deprecation notice. 369| 0| switch manifest.manifestVersion { 370| 0| case .v4: break 371| 0| case .v4_2, .v5: 372| 0| diagnostics.emit( 373| 0| data: PackageBuilderDiagnostics.SystemPackageDeprecatedDiagnostic(), 374| 0| location: diagnosticLocation() 375| 0| ) 376| 0| } 377| 0| 378| 0| // Package contains a modulemap at the top level, so we assuming 379| 0| // it's a system library target. 380| 0| return [ 381| 0| SystemLibraryTarget( 382| 0| name: manifest.name, 383| 0| platforms: self.platforms(), 384| 0| path: packagePath, isImplicit: true, 385| 0| pkgConfig: manifest.pkgConfig, 386| 0| providers: manifest.providers) 387| 0| ] 388| 0| } 389| 0| 390| 0| // At this point the target can't be a system target, make sure manifest doesn't contain 391| 0| // system target specific configuration. 392| 0| guard manifest.pkgConfig == nil else { 393| 0| throw ModuleError.invalidManifestConfig( 394| 0| manifest.name, "the 'pkgConfig' property can only be used with a System Module Package") 395| 0| } 396| 0| 397| 0| guard manifest.providers == nil else { 398| 0| throw ModuleError.invalidManifestConfig( 399| 0| manifest.name, "the 'providers' property can only be used with a System Module Package") 400| 0| } 401| 0| 402| 0| return try constructV4Targets() 403| 0| } 404| | 405| | /// Predefined source directories, in order of preference. 406| | public static let predefinedSourceDirectories = ["Sources", "Source", "src", "srcs"] 407| | 408| | /// Predefined test directories, in order of preference. 409| | public static let predefinedTestDirectories = ["Tests", "Sources", "Source", "src", "srcs"] 410| | 411| | /// Finds the predefined directories for regular and test targets. 412| 0| private func findPredefinedTargetDirectory() -> (targetDir: String, testTargetDir: String) { 413| 0| let targetDir = PackageBuilder.predefinedSourceDirectories.first(where: { 414| 0| fileSystem.isDirectory(packagePath.appending(component: $0)) 415| 0| }) ?? PackageBuilder.predefinedSourceDirectories[0] 416| 0| 417| 0| let testTargetDir = PackageBuilder.predefinedTestDirectories.first(where: { 418| 0| fileSystem.isDirectory(packagePath.appending(component: $0)) 419| 0| }) ?? PackageBuilder.predefinedTestDirectories[0] 420| 0| 421| 0| return (targetDir, testTargetDir) 422| 0| } 423| | 424| | /// Construct targets according to PackageDescription 4 conventions. 425| 0| fileprivate func constructV4Targets() throws -> [Target] { 426| 0| // Select the correct predefined directory list. 427| 0| let predefinedDirs = findPredefinedTargetDirectory() 428| 0| 429| 0| /// Returns the path of the given target. 430| 0| func findPath(for target: TargetDescription) throws -> AbsolutePath { 431| 0| // If there is a custom path defined, use that. 432| 0| if let subpath = target.path { 433| 0| if subpath == "" || subpath == "." { 434| 0| return packagePath 435| 0| } 436| 0| 437| 0| // Make sure target is not refenced by absolute path 438| 0| guard let relativeSubPath = try? RelativePath(validating: subpath) else { 439| 0| throw ModuleError.unsupportedTargetPath(subpath) 440| 0| } 441| 0| 442| 0| let path = packagePath.appending(relativeSubPath) 443| 0| // Make sure the target is inside the package root. 444| 0| guard path.contains(packagePath) else { 445| 0| throw ModuleError.targetOutsidePackage(package: manifest.name, target: target.name) 446| 0| } 447| 0| if fileSystem.isDirectory(path) { 448| 0| return path 449| 0| } 450| 0| throw ModuleError.invalidCustomPath(target: target.name, path: subpath) 451| 0| } 452| 0| 453| 0| // Check if target is present in the predefined directory. 454| 0| let predefinedDir = target.isTest ? predefinedDirs.testTargetDir : predefinedDirs.targetDir 455| 0| let path = packagePath.appending(components: predefinedDir, target.name) 456| 0| if fileSystem.isDirectory(path) { 457| 0| return path 458| 0| } 459| 0| throw ModuleError.modulesNotFound([target.name]) 460| 0| } 461| 0| 462| 0| // Create potential targets. 463| 0| let potentialTargets: [PotentialModule] 464| 0| potentialTargets = try manifest.targets.map({ target in 465| 0| let path = try findPath(for: target) 466| 0| return PotentialModule(name: target.name, path: path, type: target.type) 467| 0| }) 468| 0| return try createModules(potentialTargets) 469| 0| } 470| | 471| | // Create targets from the provided potential targets. 472| 0| private func createModules(_ potentialModules: [PotentialModule]) throws -> [Target] { 473| 0| // Find if manifest references a target which isn't present on disk. 474| 0| let allReferencedModules = manifest.allReferencedModules() 475| 0| let potentialModulesName = Set(potentialModules.map({ $0.name })) 476| 0| let missingModules = allReferencedModules.subtracting(potentialModulesName).intersection(allReferencedModules) 477| 0| guard missingModules.isEmpty else { 478| 0| throw ModuleError.modulesNotFound(missingModules.map({ $0 })) 479| 0| } 480| 0| 481| 0| let targetItems = manifest.targets.map({ ($0.name, $0 as TargetDescription) }) 482| 0| let targetMap = Dictionary(items: targetItems) 483| 0| let potentialModuleMap = Dictionary(items: potentialModules.map({ ($0.name, $0) })) 484| 0| let successors: (PotentialModule) -> [PotentialModule] = { 485| 0| // No reference of this target in manifest, i.e. it has no dependencies. 486| 0| guard let target = targetMap[$0.name] else { return [] } 487| 0| return target.dependencies.compactMap({ 488| 0| switch $0 { 489| 0| case .target(let name): 490| 0| // Since we already checked above that all referenced targets 491| 0| // has to present, we always expect this target to be present in 492| 0| // potentialModules dictionary. 493| 0| return potentialModuleMap[name]! 494| 0| case .product: 495| 0| return nil 496| 0| case .byName(let name): 497| 0| // By name dependency may or may not be a target dependency. 498| 0| return potentialModuleMap[name] 499| 0| } 500| 0| }) 501| 0| } 502| 0| // Look for any cycle in the dependencies. 503| 0| if let cycle = findCycle(potentialModules.sorted(by: { $0.name < $1.name }), successors: successors) { 504| 0| throw ModuleError.cycleDetected((cycle.path.map({ $0.name }), cycle.cycle.map({ $0.name }))) 505| 0| } 506| 0| // There was no cycle so we sort the targets topologically. 507| 0| let potentialModules = try! topologicalSort(potentialModules, successors: successors) 508| 0| 509| 0| // The created targets mapped to their name. 510| 0| var targets = [String: Target]() 511| 0| // If a direcotry is empty, we don't create a target object for them. 512| 0| var emptyModules = Set() 513| 0| 514| 0| // Start iterating the potential targets. 515| 0| for potentialModule in potentialModules.lazy.reversed() { 516| 0| // Validate the target name. This function will throw an error if it detects a problem. 517| 0| try validateModuleName(potentialModule.path, potentialModule.name, isTest: potentialModule.isTest) 518| 0| // Get the intra-package dependencies of this target. 519| 0| let deps: [Target] = targetMap[potentialModule.name].map({ 520| 0| $0.dependencies.compactMap({ 521| 0| switch $0 { 522| 0| case .target(let name): 523| 0| // We don't create an object for targets which have no sources. 524| 0| if emptyModules.contains(name) { return nil } 525| 0| return targets[name]! 526| 0| 527| 0| case .byName(let name): 528| 0| // We don't create an object for targets which have no sources. 529| 0| if emptyModules.contains(name) { return nil } 530| 0| return targets[name] 531| 0| 532| 0| case .product: return nil 533| 0| } 534| 0| }) 535| 0| }) ?? [] 536| 0| 537| 0| // Get the target from the manifest. 538| 0| let manifestTarget = targetMap[potentialModule.name] 539| 0| 540| 0| // Figure out the product dependencies. 541| 0| let productDeps: [(String, String?)] 542| 0| productDeps = manifestTarget?.dependencies.compactMap({ 543| 0| switch $0 { 544| 0| case .target: 545| 0| return nil 546| 0| case .byName(let name): 547| 0| // If this dependency was not found locally, it is a product dependency. 548| 0| return potentialModuleMap[name] == nil ? (name, nil) : nil 549| 0| case .product(let name, let package): 550| 0| return (name, package) 551| 0| } 552| 0| }) ?? [] 553| 0| 554| 0| // Create the target. 555| 0| let target = try createTarget( 556| 0| potentialModule: potentialModule, 557| 0| manifestTarget: manifestTarget, 558| 0| moduleDependencies: deps, 559| 0| productDeps: productDeps) 560| 0| // Add the created target to the map or print no sources warning. 561| 0| if let createdTarget = target { 562| 0| targets[createdTarget.name] = createdTarget 563| 0| } else { 564| 0| emptyModules.insert(potentialModule.name) 565| 0| diagnostics.emit(data: PackageBuilderDiagnostics.NoSources(package: manifest.name, target: potentialModule.name)) 566| 0| } 567| 0| } 568| 0| return targets.values.map({ $0 }) 569| 0| } 570| | 571| | /// Private function that checks whether a target name is valid. This method doesn't return anything, but rather, 572| | /// if there's a problem, it throws an error describing what the problem is. 573| 0| private func validateModuleName(_ path: AbsolutePath, _ name: String, isTest: Bool) throws { 574| 0| if name.isEmpty { 575| 0| throw Target.Error.invalidName( 576| 0| path: path.relative(to: packagePath).pathString, 577| 0| problem: .emptyName) 578| 0| } 579| 0| } 580| | 581| | /// Private function that constructs a single Target object for the potential target. 582| | private func createTarget( 583| | potentialModule: PotentialModule, 584| | manifestTarget: TargetDescription?, 585| | moduleDependencies: [Target], 586| | productDeps: [(name: String, package: String?)] 587| 0| ) throws -> Target? { 588| 0| 589| 0| // Create system library target. 590| 0| if potentialModule.type == .system { 591| 0| let moduleMapPath = potentialModule.path.appending(component: moduleMapFilename) 592| 0| guard fileSystem.isFile(moduleMapPath) else { 593| 0| return nil 594| 0| } 595| 0| 596| 0| return SystemLibraryTarget( 597| 0| name: potentialModule.name, 598| 0| platforms: self.platforms(), 599| 0| path: potentialModule.path, isImplicit: false, 600| 0| pkgConfig: manifestTarget?.pkgConfig, 601| 0| providers: manifestTarget?.providers 602| 0| ) 603| 0| } 604| 0| 605| 0| // Check for duplicate target dependencies by name 606| 0| let combinedDependencyNames = moduleDependencies.map { $0.name } + productDeps.map { $0.0 } 607| 0| combinedDependencyNames.spm_findDuplicates().forEach { 608| 0| diagnostics.emit(data: PackageBuilderDiagnostics.DuplicateTargetDependencyDiagnostic(dependency: $0, target: potentialModule.name)) 609| 0| } 610| 0| 611| 0| // Compute the path to public headers directory. 612| 0| let publicHeaderComponent = manifestTarget?.publicHeadersPath ?? ClangTarget.defaultPublicHeadersComponent 613| 0| let publicHeadersPath = potentialModule.path.appending(RelativePath(publicHeaderComponent)) 614| 0| guard publicHeadersPath.contains(potentialModule.path) else { 615| 0| throw ModuleError.invalidPublicHeadersDirectory(potentialModule.name) 616| 0| } 617| 0| 618| 0| // Compute the excluded paths in the target. 619| 0| let targetExcludedPaths: Set 620| 0| if let excludedSubPaths = manifestTarget?.exclude { 621| 0| let excludedPaths = excludedSubPaths.map({ potentialModule.path.appending(RelativePath($0)) }) 622| 0| targetExcludedPaths = Set(excludedPaths) 623| 0| } else { 624| 0| targetExcludedPaths = [] 625| 0| } 626| 0| 627| 0| // Contains the set of sources for this target. 628| 0| var walked = Set() 629| 0| 630| 0| // Contains the paths we need to recursively iterate. 631| 0| var pathsToWalk = [AbsolutePath]() 632| 0| 633| 0| // If there are sources defined in the target use that. 634| 0| if let definedSources = manifestTarget?.sources { 635| 0| for definedSource in definedSources { 636| 0| let definedSourcePath = potentialModule.path.appending(RelativePath(definedSource)) 637| 0| if fileSystem.isDirectory(definedSourcePath) { 638| 0| // If this is a directory, add it to the list of paths to walk. 639| 0| pathsToWalk.append(definedSourcePath) 640| 0| } else if fileSystem.isFile(definedSourcePath) { 641| 0| // Otherwise, this is a sourcefile. 642| 0| walked.insert(definedSourcePath) 643| 0| } else { 644| 0| // FIXME: Should we emit warning about this declared thing or silently ignore? 645| 0| } 646| 0| } 647| 0| } else { 648| 0| // Use the top level target path as the path to be walked. 649| 0| pathsToWalk.append(potentialModule.path) 650| 0| } 651| 0| 652| 0| // Walk each path and form our set of possible source files. 653| 0| for pathToWalk in pathsToWalk { 654| 0| let contents = try walk(pathToWalk, fileSystem: fileSystem, recursing: { path in 655| 0| // Exclude the public header directory. 656| 0| if path == publicHeadersPath { return false } 657| 0| 658| 0| // Exclude if it in the excluded paths of the target. 659| 0| if targetExcludedPaths.contains(path) { return false } 660| 0| 661| 0| // Exclude the directories that should never be walked. 662| 0| let base = path.basename 663| 0| if base.hasSuffix(".xcodeproj") || base.hasSuffix(".playground") || base.hasPrefix(".") { 664| 0| return false 665| 0| } 666| 0| 667| 0| return true 668| 0| }).map({$0}) 669| 0| walked.formUnion(contents) 670| 0| } 671| 0| 672| 0| // Make sure there is no modulemap mixed with the sources. 673| 0| if let path = walked.first(where: { $0.basename == moduleMapFilename }) { 674| 0| throw ModuleError.invalidLayout(.modulemapInSources(path.pathString)) 675| 0| } 676| 0| // Select any source files for the C-based languages and for Swift. 677| 0| let sources = walked.filter(isValidSource).filter({ !targetExcludedPaths.contains($0) }) 678| 0| let clangSources = sources.filter({ SupportedLanguageExtension.clangTargetExtensions(manifestVersion: self.manifest.manifestVersion).contains($0.extension!)}) 679| 0| let swiftSources = sources.filter({ SupportedLanguageExtension.swiftExtensions.contains($0.extension!) }) 680| 0| assert(sources.count == clangSources.count + swiftSources.count) 681| 0| 682| 0| // Create the build setting assignment table for this target. 683| 0| let buildSettings = try self.buildSettings(for: manifestTarget, targetRoot: potentialModule.path) 684| 0| 685| 0| // Create and return the right kind of target depending on what kind of sources we found. 686| 0| if clangSources.isEmpty { 687| 0| guard !swiftSources.isEmpty else { return nil } 688| 0| let swiftSources = Array(swiftSources) 689| 0| try validateSourcesOverlapping(forTarget: potentialModule.name, sources: swiftSources) 690| 0| // No C sources, so we expect to have Swift sources, and we create a Swift target. 691| 0| return SwiftTarget( 692| 0| name: potentialModule.name, 693| 0| platforms: self.platforms(), 694| 0| isTest: potentialModule.isTest, 695| 0| sources: Sources(paths: swiftSources, root: potentialModule.path), 696| 0| dependencies: moduleDependencies, 697| 0| productDependencies: productDeps, 698| 0| swiftVersion: try swiftVersion(), 699| 0| buildSettings: buildSettings 700| 0| ) 701| 0| } else { 702| 0| // No Swift sources, so we expect to have C sources, and we create a C target. 703| 0| guard swiftSources.isEmpty else { throw Target.Error.mixedSources(potentialModule.path.pathString) } 704| 0| let cSources = Array(clangSources) 705| 0| try validateSourcesOverlapping(forTarget: potentialModule.name, sources: cSources) 706| 0| 707| 0| let sources = Sources(paths: cSources, root: potentialModule.path) 708| 0| 709| 0| return ClangTarget( 710| 0| name: potentialModule.name, 711| 0| platforms: self.platforms(), 712| 0| cLanguageStandard: manifest.cLanguageStandard, 713| 0| cxxLanguageStandard: manifest.cxxLanguageStandard, 714| 0| includeDir: publicHeadersPath, 715| 0| isTest: potentialModule.isTest, 716| 0| sources: sources, 717| 0| dependencies: moduleDependencies, 718| 0| productDependencies: productDeps, 719| 0| buildSettings: buildSettings 720| 0| ) 721| 0| } 722| 0| } 723| | 724| | /// Creates build setting assignment table for the given target. 725| 0| func buildSettings(for target: TargetDescription?, targetRoot: AbsolutePath) throws -> BuildSettings.AssignmentTable { 726| 0| var table = BuildSettings.AssignmentTable() 727| 0| guard let target = target else { return table } 728| 0| 729| 0| // Process each setting. 730| 0| for setting in target.settings { 731| 0| let decl: BuildSettings.Declaration 732| 0| 733| 0| // Compute appropriate declaration for the setting. 734| 0| switch setting.name { 735| 0| case .headerSearchPath: 736| 0| 737| 0| switch setting.tool { 738| 0| case .c, .cxx: 739| 0| decl = .HEADER_SEARCH_PATHS 740| 0| case .swift, .linker: 741| 0| fatalError("unexpected tool for setting type \(setting)") 742| 0| } 743| 0| 744| 0| // Ensure that the search path is contained within the package. 745| 0| let subpath = try RelativePath(validating: setting.value[0]) 746| 0| guard targetRoot.appending(subpath).contains(packagePath) else { 747| 0| throw ModuleError.invalidHeaderSearchPath(subpath.pathString) 748| 0| } 749| 0| 750| 0| case .define: 751| 0| switch setting.tool { 752| 0| case .c, .cxx: 753| 0| decl = .GCC_PREPROCESSOR_DEFINITIONS 754| 0| case .swift: 755| 0| decl = .SWIFT_ACTIVE_COMPILATION_CONDITIONS 756| 0| case .linker: 757| 0| fatalError("unexpected tool for setting type \(setting)") 758| 0| } 759| 0| 760| 0| case .linkedLibrary: 761| 0| switch setting.tool { 762| 0| case .c, .cxx, .swift: 763| 0| fatalError("unexpected tool for setting type \(setting)") 764| 0| case .linker: 765| 0| decl = .LINK_LIBRARIES 766| 0| } 767| 0| 768| 0| case .linkedFramework: 769| 0| switch setting.tool { 770| 0| case .c, .cxx, .swift: 771| 0| fatalError("unexpected tool for setting type \(setting)") 772| 0| case .linker: 773| 0| decl = .LINK_FRAMEWORKS 774| 0| } 775| 0| 776| 0| case .unsafeFlags: 777| 0| switch setting.tool { 778| 0| case .c: 779| 0| decl = .OTHER_CFLAGS 780| 0| case .cxx: 781| 0| decl = .OTHER_CPLUSPLUSFLAGS 782| 0| case .swift: 783| 0| decl = .OTHER_SWIFT_FLAGS 784| 0| case .linker: 785| 0| decl = .OTHER_LDFLAGS 786| 0| } 787| 0| } 788| 0| 789| 0| // Create an assignment for this setting. 790| 0| var assignment = BuildSettings.Assignment() 791| 0| assignment.value = setting.value 792| 0| 793| 0| if let config = setting.condition?.config.map({ BuildConfiguration(rawValue: $0)! }) { 794| 0| let condition = BuildSettings.ConfigurationCondition(config) 795| 0| assignment.conditions.append(condition) 796| 0| } 797| 0| 798| 0| if let platforms = setting.condition?.platformNames.map({ platformRegistry.platformByName[$0]! }), !platforms.isEmpty { 799| 0| var condition = BuildSettings.PlatformsCondition() 800| 0| condition.platforms = platforms 801| 0| assignment.conditions.append(condition) 802| 0| } 803| 0| 804| 0| // Finally, add the assignment to the assignment table. 805| 0| table.add(assignment, for: decl) 806| 0| } 807| 0| 808| 0| return table 809| 0| } 810| | 811| | /// Returns the list of platforms supported by the manifest. 812| 0| func platforms() -> [SupportedPlatform] { 813| 0| if let platforms = _platforms { 814| 0| return platforms 815| 0| } 816| 0| 817| 0| var supportedPlatforms: [SupportedPlatform] = [] 818| 0| 819| 0| /// Add each declared platform to the supported platforms list. 820| 0| for platform in manifest.platforms { 821| 0| 822| 0| let supportedPlatform = SupportedPlatform( 823| 0| platform: platformRegistry.platformByName[platform.platformName]!, 824| 0| version: PlatformVersion(platform.version) 825| 0| ) 826| 0| 827| 0| supportedPlatforms.append(supportedPlatform) 828| 0| } 829| 0| 830| 0| // Find the undeclared platforms. 831| 0| let remainingPlatforms = Set(platformRegistry.platformByName.keys).subtracting(supportedPlatforms.map({ $0.platform.name })) 832| 0| 833| 0| /// Start synthesizing for each undeclared platform. 834| 0| for platformName in remainingPlatforms { 835| 0| let platform = platformRegistry.platformByName[platformName]! 836| 0| 837| 0| let supportedPlatform = SupportedPlatform( 838| 0| platform: platform, 839| 0| version: platform.oldestSupportedVersion 840| 0| ) 841| 0| 842| 0| supportedPlatforms.append(supportedPlatform) 843| 0| } 844| 0| 845| 0| _platforms = supportedPlatforms 846| 0| return _platforms! 847| 0| } 848| | private var _platforms: [SupportedPlatform]? = nil 849| | 850| | /// The platform registry instance. 851| 0| private var platformRegistry: PlatformRegistry { 852| 0| return PlatformRegistry.default 853| 0| } 854| | 855| | /// Computes the swift version to use for this manifest. 856| 0| private func swiftVersion() throws -> SwiftLanguageVersion { 857| 0| if let swiftVersion = _swiftVersion { 858| 0| return swiftVersion 859| 0| } 860| 0| 861| 0| let computedSwiftVersion: SwiftLanguageVersion 862| 0| 863| 0| // Figure out the swift version from declared list in the manifest. 864| 0| if let swiftLanguageVersions = manifest.swiftLanguageVersions { 865| 0| guard let swiftVersion = swiftLanguageVersions.sorted(by: >).first(where: { $0 <= ToolsVersion.currentToolsVersion }) else { 866| 0| throw ModuleError.incompatibleToolsVersions( 867| 0| package: manifest.name, required: swiftLanguageVersions, current: .currentToolsVersion) 868| 0| } 869| 0| computedSwiftVersion = swiftVersion 870| 0| } else { 871| 0| // Otherwise, use the version depending on the manifest version. 872| 0| computedSwiftVersion = manifest.manifestVersion.swiftLanguageVersion 873| 0| } 874| 0| _swiftVersion = computedSwiftVersion 875| 0| return computedSwiftVersion 876| 0| } 877| | private var _swiftVersion: SwiftLanguageVersion? = nil 878| | 879| | /// The set of the sources computed so far. 880| | private var allSources = Set() 881| | 882| | /// Validates that the sources of a target are not already present in another target. 883| 0| private func validateSourcesOverlapping(forTarget target: String, sources: [AbsolutePath]) throws { 884| 0| // Compute the sources which overlap with already computed targets. 885| 0| var overlappingSources = [AbsolutePath]() 886| 0| for source in sources { 887| 0| if !allSources.insert(source).inserted { 888| 0| overlappingSources.append(source) 889| 0| } 890| 0| } 891| 0| 892| 0| // Throw if we found any overlapping sources. 893| 0| if !overlappingSources.isEmpty { 894| 0| throw ModuleError.overlappingSources(target: target, sources: overlappingSources) 895| 0| } 896| 0| } 897| | 898| | /// Find the linux main file for the package. 899| 0| private func findLinuxMain(in testTargets: [Target]) throws -> AbsolutePath? { 900| 0| var linuxMainFiles = Set() 901| 0| var pathsSearched = Set() 902| 0| 903| 0| // Look for linux main file adjacent to each test target root, iterating upto package root. 904| 0| for target in testTargets { 905| 0| 906| 0| // Form the initial search path. 907| 0| // 908| 0| // If the target root's parent directory is inside the package, start 909| 0| // search there. Otherwise, we start search from the target root. 910| 0| var searchPath = target.sources.root.parentDirectory 911| 0| if !searchPath.contains(packagePath) { 912| 0| searchPath = target.sources.root 913| 0| } 914| 0| 915| 0| while true { 916| 0| assert(searchPath.contains(packagePath), "search path \(searchPath) is outside the package \(packagePath)") 917| 0| // If we have already searched this path, skip. 918| 0| if !pathsSearched.contains(searchPath) { 919| 0| let linuxMain = searchPath.appending(component: SwiftTarget.linuxMainBasename) 920| 0| if fileSystem.isFile(linuxMain) { 921| 0| linuxMainFiles.insert(linuxMain) 922| 0| } 923| 0| pathsSearched.insert(searchPath) 924| 0| } 925| 0| // Break if we reached all the way to package root. 926| 0| if searchPath == packagePath { break } 927| 0| // Go one level up. 928| 0| searchPath = searchPath.parentDirectory 929| 0| } 930| 0| } 931| 0| 932| 0| // It is an error if there are multiple linux main files. 933| 0| if linuxMainFiles.count > 1 { 934| 0| throw ModuleError.multipleLinuxMainFound( 935| 0| package: manifest.name, linuxMainFiles: linuxMainFiles.map({ $0 })) 936| 0| } 937| 0| return linuxMainFiles.first 938| 0| } 939| | 940| | /// Collects the products defined by a package. 941| 0| private func constructProducts(_ targets: [Target]) throws -> [Product] { 942| 0| var products = OrderedSet>() 943| 0| 944| 0| /// Helper method to append to products array. 945| 0| func append(_ product: Product) { 946| 0| let inserted = products.append(KeyedPair(product, key: product.name)) 947| 0| if !inserted { 948| 0| diagnostics.emit( 949| 0| data: PackageBuilderDiagnostics.DuplicateProduct(product: product), 950| 0| location: diagnosticLocation() 951| 0| ) 952| 0| } 953| 0| } 954| 0| 955| 0| // Collect all test targets. 956| 0| let testModules = targets.filter({ target in 957| 0| guard target.type == .test else { return false } 958| 0| #if os(Linux) 959| 0| // FIXME: Ignore C language test targets on linux for now. 960| 0| if target is ClangTarget { 961| 0| diagnostics.emit(data: PackageBuilderDiagnostics.UnsupportedCTarget( 962| 0| package: manifest.name, target: target.name)) 963| 0| return false 964| 0| } 965| 0| #endif 966| 0| return true 967| 0| }) 968| 0| 969| 0| // If enabled, create one test product for each test target. 970| 0| if shouldCreateMultipleTestProducts { 971| 0| for testTarget in testModules { 972| 0| let product = Product(name: testTarget.name, type: .test, targets: [testTarget]) 973| 0| append(product) 974| 0| } 975| 0| } else if !testModules.isEmpty { 976| 0| // Otherwise we only need to create one test product for all of the 977| 0| // test targets. 978| 0| // 979| 0| // Add suffix 'PackageTests' to test product name so the target name 980| 0| // of linux executable don't collide with main package, if present. 981| 0| let productName = manifest.name + "PackageTests" 982| 0| let linuxMain = try findLinuxMain(in: testModules) 983| 0| 984| 0| let product = Product( 985| 0| name: productName, type: .test, targets: testModules, linuxMain: linuxMain) 986| 0| append(product) 987| 0| } 988| 0| 989| 0| // Map containing targets mapped to their names. 990| 0| let modulesMap = Dictionary(items: targets.map({ ($0.name, $0) })) 991| 0| 992| 0| /// Helper method to get targets from target names. 993| 0| func modulesFrom(targetNames names: [String], product: String) throws -> [Target] { 994| 0| // Ensure the target names are non-empty. 995| 0| guard !names.isEmpty else { throw Product.Error.noModules(product) } 996| 0| // Get targets from target names. 997| 0| let productModules: [Target] = try names.map({ targetName in 998| 0| // Ensure we have this target. 999| 0| guard let target = modulesMap[targetName] else { 1000| 0| throw Product.Error.moduleNotFound(product: product, target: targetName) 1001| 0| } 1002| 0| return target 1003| 0| }) 1004| 0| return productModules 1005| 0| } 1006| 0| 1007| 0| // Only create implicit executables for root packages. 1008| 0| if isRootPackage { 1009| 0| // Compute the list of targets which are being used in an 1010| 0| // executable product so we don't create implicit executables 1011| 0| // for them. 1012| 0| let executableProductTargets = manifest.products.flatMap({ product -> [String] in 1013| 0| switch product.type { 1014| 0| case .library, .test: 1015| 0| return [] 1016| 0| case .executable: 1017| 0| return product.targets 1018| 0| } 1019| 0| }) 1020| 0| 1021| 0| let declaredProductsTargets = Set(executableProductTargets) 1022| 0| for target in targets where target.type == .executable { 1023| 0| // If this target already has an executable product, skip 1024| 0| // generating a product for it. 1025| 0| if declaredProductsTargets.contains(target.name) { 1026| 0| continue 1027| 0| } 1028| 0| let product = Product(name: target.name, type: .executable, targets: [target]) 1029| 0| append(product) 1030| 0| } 1031| 0| } 1032| 0| 1033| 0| for product in manifest.products { 1034| 0| let targets = try modulesFrom(targetNames: product.targets, product: product.name) 1035| 0| // Peform special validations if this product is exporting 1036| 0| // a system library target. 1037| 0| if targets.contains(where: { $0 is SystemLibraryTarget }) { 1038| 0| if product.type != .library(.automatic) || targets.count != 1 { 1039| 0| diagnostics.emit( 1040| 0| data: PackageBuilderDiagnostics.SystemPackageProductValidationDiagnostic(product: product.name), 1041| 0| location: diagnosticLocation() 1042| 0| ) 1043| 0| continue 1044| 0| } 1045| 0| } 1046| 0| 1047| 0| // Do some validation for executable products. 1048| 0| switch product.type { 1049| 0| case .library, .test: 1050| 0| break 1051| 0| case .executable: 1052| 0| let executableTargets = targets.filter({ $0.type == .executable }) 1053| 0| if executableTargets.count != 1 { 1054| 0| diagnostics.emit( 1055| 0| data: PackageBuilderDiagnostics.InvalidExecutableProductDecl(product: product.name), 1056| 0| location: diagnosticLocation() 1057| 0| ) 1058| 0| continue 1059| 0| } 1060| 0| } 1061| 0| 1062| 0| append(Product(name: product.name, type: product.type, targets: targets)) 1063| 0| } 1064| 0| 1065| 0| // Create a special REPL product that contains all the library targets. 1066| 0| if createREPLProduct { 1067| 0| let libraryTargets = targets.filter({ $0.type == .library }) 1068| 0| if libraryTargets.isEmpty { 1069| 0| diagnostics.emit( 1070| 0| data: PackageBuilderDiagnostics.ZeroLibraryProducts(), 1071| 0| location: diagnosticLocation() 1072| 0| ) 1073| 0| } else { 1074| 0| let replProduct = Product( 1075| 0| name: manifest.name + Product.replProductSuffix, 1076| 0| type: .library(.dynamic), 1077| 0| targets: libraryTargets 1078| 0| ) 1079| 0| append(replProduct) 1080| 0| } 1081| 0| } 1082| 0| 1083| 0| return products.map({ $0.item }) 1084| 0| } 1085| | 1086| |} 1087| | 1088| |/// We create this structure after scanning the filesystem for potential targets. 1089| |private struct PotentialModule: Hashable { 1090| | 1091| | /// Name of the target. 1092| | let name: String 1093| | 1094| | /// The path of the target. 1095| | let path: AbsolutePath 1096| | 1097| | /// If this should be a test target. 1098| 0| var isTest: Bool { 1099| 0| return type == .test 1100| 0| } 1101| | 1102| | /// The target type. 1103| | let type: TargetDescription.TargetType 1104| | 1105| | /// The base prefix for the test target, used to associate with the target it tests. 1106| 0| public var basename: String { 1107| 0| guard isTest else { 1108| 0| fatalError("\(Swift.type(of: self)) should be a test target to access basename.") 1109| 0| } 1110| 0| precondition(name.hasSuffix(Target.testModuleNameSuffix)) 1111| 0| let endIndex = name.index(name.endIndex, offsetBy: -Target.testModuleNameSuffix.count) 1112| 0| return String(name[name.startIndex.. Set { 1119| 0| let names = targets.flatMap({ target in 1120| 0| [target.name] + target.dependencies.compactMap({ 1121| 0| switch $0 { 1122| 0| case .target(let name): 1123| 0| return name 1124| 0| case .byName, .product: 1125| 0| return nil 1126| 0| } 1127| 0| }) 1128| 0| }) 1129| 0| return Set(names) 1130| 0| } 1131| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/PackageDescription4Loader.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import PackageModel 14| | 15| |extension ManifestBuilder { 16| 0| mutating func build(v4 json: JSON) throws { 17| 0| let package = try json.getJSON("package") 18| 0| self.name = try package.get(String.self, forKey: "name") 19| 0| self.pkgConfig = package.get("pkgConfig") 20| 0| self.platforms = try parsePlatforms(package) 21| 0| self.swiftLanguageVersions = try parseSwiftLanguageVersion(package) 22| 0| self.products = try package.getArray("products").map(ProductDescription.init(v4:)) 23| 0| self.providers = try? package.getArray("providers").map(SystemPackageProviderDescription.init(v4:)) 24| 0| self.targets = try package.getArray("targets").map(parseTarget(json:)) 25| 0| self.dependencies = try package 26| 0| .getArray("dependencies") 27| 0| .map({ try PackageDependencyDescription(v4: $0, baseURL: self.baseURL, fileSystem: self.fs) }) 28| 0| 29| 0| self.cxxLanguageStandard = package.get("cxxLanguageStandard") 30| 0| self.cLanguageStandard = package.get("cLanguageStandard") 31| 0| 32| 0| self.errors = try json.get("errors") 33| 0| } 34| | 35| 0| func parseSwiftLanguageVersion(_ package: JSON) throws -> [SwiftLanguageVersion]? { 36| 0| guard let versionJSON = try? package.getArray("swiftLanguageVersions") else { 37| 0| return nil 38| 0| } 39| 0| 40| 0| /// Parse the versioned value. 41| 0| let versionedValues = try versionJSON.map({ try VersionedValue(json: $0) }) 42| 0| 43| 0| return try versionedValues.map { versionedValue in 44| 0| // Validate that this versioned value is supported by the current 45| 0| // manifest version. 46| 0| try versionedValue.validate(for: self.manifestVersion) 47| 0| 48| 0| return try SwiftLanguageVersion(string: String(json: versionedValue.value))! 49| 0| } 50| 0| } 51| | 52| 0| func parsePlatforms(_ package: JSON) throws -> [PlatformDescription] { 53| 0| guard let platformsJSON = try? package.getJSON("platforms") else { 54| 0| return [] 55| 0| } 56| 0| 57| 0| /// Ensure that platforms API is used in the right manifest version. 58| 0| let versionedPlatforms = try VersionedValue(json: platformsJSON) 59| 0| try versionedPlatforms.validate(for: self.manifestVersion) 60| 0| 61| 0| // Get the declared platform list. 62| 0| let declaredPlatforms = try versionedPlatforms.value.getArray() 63| 0| 64| 0| // Empty list is not supported. 65| 0| if declaredPlatforms.isEmpty { 66| 0| throw ManifestParseError.runtimeManifestErrors(["supported platforms can't be empty"]) 67| 0| } 68| 0| 69| 0| // Start parsing platforms. 70| 0| var platforms: [PlatformDescription] = [] 71| 0| 72| 0| for platformJSON in declaredPlatforms { 73| 0| // Parse the version and validate that it can be used in the current 74| 0| // manifest version. 75| 0| let versionJSON = try platformJSON.getJSON("version") 76| 0| let versionedVersion = try VersionedValue(json: versionJSON) 77| 0| try versionedVersion.validate(for: self.manifestVersion) 78| 0| 79| 0| // Get the actual value of the version. 80| 0| let version = try String(json: versionedVersion.value) 81| 0| 82| 0| // Get the platform name. 83| 0| let platformName: String = try platformJSON.getJSON("platform").get("name") 84| 0| 85| 0| let description = PlatformDescription(name: platformName, version: version) 86| 0| 87| 0| // Check for duplicates. 88| 0| if platforms.map({ $0.platformName }).contains(platformName) { 89| 0| // FIXME: We need to emit the API name and not the internal platform name. 90| 0| throw ManifestParseError.runtimeManifestErrors(["found multiple declaration for the platform: \(platformName)"]) 91| 0| } 92| 0| 93| 0| platforms.append(description) 94| 0| } 95| 0| 96| 0| return platforms 97| 0| } 98| | 99| 0| private func parseTarget(json: JSON) throws -> TargetDescription { 100| 0| let providers = try? json 101| 0| .getArray("providers") 102| 0| .map(SystemPackageProviderDescription.init(v4:)) 103| 0| 104| 0| let dependencies = try json 105| 0| .getArray("dependencies") 106| 0| .map(TargetDescription.Dependency.init(v4:)) 107| 0| 108| 0| return TargetDescription( 109| 0| name: try json.get("name"), 110| 0| dependencies: dependencies, 111| 0| path: json.get("path"), 112| 0| exclude: try json.get("exclude"), 113| 0| sources: try? json.get("sources"), 114| 0| publicHeadersPath: json.get("publicHeadersPath"), 115| 0| type: try .init(v4: json.get("type")), 116| 0| pkgConfig: json.get("pkgConfig"), 117| 0| providers: providers, 118| 0| settings: try parseBuildSettings(json) 119| 0| ) 120| 0| } 121| | 122| 0| func parseBuildSettings(_ json: JSON) throws -> [TargetBuildSettingDescription.Setting] { 123| 0| var settings: [TargetBuildSettingDescription.Setting] = [] 124| 0| for tool in TargetBuildSettingDescription.Tool.allCases { 125| 0| let key = tool.rawValue + "Settings" 126| 0| if let settingsJSON = try? json.getJSON(key) { 127| 0| settings += try parseBuildSettings(settingsJSON, tool: tool) 128| 0| } 129| 0| } 130| 0| return settings 131| 0| } 132| | 133| 0| func parseBuildSettings(_ json: JSON, tool: TargetBuildSettingDescription.Tool) throws -> [TargetBuildSettingDescription.Setting] { 134| 0| let versionedValue = try VersionedValue(json: json) 135| 0| try versionedValue.validate(for: self.manifestVersion) 136| 0| 137| 0| let declaredSettings = try versionedValue.value.getArray() 138| 0| if declaredSettings.isEmpty { 139| 0| throw ManifestParseError.runtimeManifestErrors(["empty list not supported"]) 140| 0| } 141| 0| 142| 0| return try declaredSettings.map({ 143| 0| try parseBuildSetting($0, tool: tool) 144| 0| }) 145| 0| } 146| | 147| 0| func parseBuildSetting(_ json: JSON, tool: TargetBuildSettingDescription.Tool) throws -> TargetBuildSettingDescription.Setting { 148| 0| let json = try json.getJSON("data") 149| 0| let name = try TargetBuildSettingDescription.SettingName(rawValue: json.get("name"))! 150| 0| 151| 0| var condition: TargetBuildSettingDescription.Condition? 152| 0| if let conditionJSON = try? json.getJSON("condition") { 153| 0| condition = try parseCondition(conditionJSON) 154| 0| } 155| 0| 156| 0| return .init( 157| 0| tool: tool, name: name, 158| 0| value: try json.get("value"), 159| 0| condition: condition 160| 0| ) 161| 0| } 162| | 163| 0| func parseCondition(_ json: JSON) throws -> TargetBuildSettingDescription.Condition { 164| 0| let platformNames: [String]? = try? json.getArray("platforms").map({ try $0.get("name") }) 165| 0| return .init( 166| 0| platformNames: platformNames ?? [], 167| 0| config: try? json.get("config").get("config") 168| 0| ) 169| 0| } 170| |} 171| | 172| |struct VersionedValue: JSONMappable { 173| | let supportedVersions: [ManifestVersion] 174| | let value: JSON 175| | let api: String 176| | 177| 0| init(json: JSON) throws { 178| 0| self.api = try json.get(String.self, forKey: "api") 179| 0| self.value = try json.getJSON("value") 180| 0| 181| 0| let supportedVersionsJSON = try json.get([String].self, forKey: "supportedVersions") 182| 0| self.supportedVersions = supportedVersionsJSON.map({ ManifestVersion(rawValue: $0)! }) 183| 0| } 184| | 185| 0| func validate(for manifestVersion: ManifestVersion) throws { 186| 0| if !supportedVersions.contains(manifestVersion) { 187| 0| throw ManifestParseError.unsupportedAPI( 188| 0| api: api, 189| 0| supportedVersions: supportedVersions 190| 0| ) 191| 0| } 192| 0| } 193| |} 194| | 195| |extension SystemPackageProviderDescription { 196| 0| fileprivate init(v4 json: JSON) throws { 197| 0| let name = try json.get(String.self, forKey: "name") 198| 0| let value = try json.get([String].self, forKey: "values") 199| 0| switch name { 200| 0| case "brew": 201| 0| self = .brew(value) 202| 0| case "apt": 203| 0| self = .apt(value) 204| 0| default: 205| 0| fatalError() 206| 0| } 207| 0| } 208| |} 209| | 210| |extension PackageModel.ProductType { 211| 0| fileprivate init(v4 json: JSON) throws { 212| 0| let productType = try json.get(String.self, forKey: "product_type") 213| 0| 214| 0| switch productType { 215| 0| case "executable": 216| 0| self = .executable 217| 0| 218| 0| case "library": 219| 0| let libraryType: ProductType.LibraryType 220| 0| 221| 0| let libraryTypeString: String? = json.get("type") 222| 0| switch libraryTypeString { 223| 0| case "static"?: 224| 0| libraryType = .static 225| 0| case "dynamic"?: 226| 0| libraryType = .dynamic 227| 0| case nil: 228| 0| libraryType = .automatic 229| 0| default: 230| 0| fatalError() 231| 0| } 232| 0| 233| 0| self = .library(libraryType) 234| 0| 235| 0| default: 236| 0| fatalError("unexpected product type: \(json)") 237| 0| } 238| 0| } 239| |} 240| | 241| |extension ProductDescription { 242| 0| fileprivate init(v4 json: JSON) throws { 243| 0| try self.init( 244| 0| name: json.get("name"), 245| 0| type: .init(v4: json), 246| 0| targets: json.get("targets") 247| 0| ) 248| 0| } 249| |} 250| | 251| |extension PackageDependencyDescription.Requirement { 252| 0| fileprivate init(v4 json: JSON) throws { 253| 0| let type = try json.get(String.self, forKey: "type") 254| 0| switch type { 255| 0| case "branch": 256| 0| self = try .branch(json.get("identifier")) 257| 0| 258| 0| case "revision": 259| 0| self = try .revision(json.get("identifier")) 260| 0| 261| 0| case "range": 262| 0| let lowerBound = try json.get(String.self, forKey: "lowerBound") 263| 0| let upperBound = try json.get(String.self, forKey: "upperBound") 264| 0| self = .range(Version(string: lowerBound)! ..< Version(string: upperBound)!) 265| 0| 266| 0| case "exact": 267| 0| let identifier = try json.get(String.self, forKey: "identifier") 268| 0| self = .exact(Version(string: identifier)!) 269| 0| 270| 0| case "localPackage": 271| 0| self = .localPackage 272| 0| 273| 0| default: 274| 0| fatalError() 275| 0| } 276| 0| } 277| |} 278| | 279| |extension PackageDependencyDescription { 280| 0| fileprivate init(v4 json: JSON, baseURL: String, fileSystem: FileSystem) throws { 281| 0| let isBaseURLRemote = URL.scheme(baseURL) != nil 282| 0| 283| 0| func fixURL(_ url: String) -> String { 284| 0| // If base URL is remote (http/ssh), we can't do any "fixing". 285| 0| if isBaseURLRemote { 286| 0| return url 287| 0| } 288| 0| 289| 0| // If the dependency URL starts with '~/', try to expand it. 290| 0| if url.hasPrefix("~/") { 291| 0| return fileSystem.homeDirectory.appending(RelativePath(String(url.dropFirst(2)))).pathString 292| 0| } 293| 0| 294| 0| // If the dependency URL is not remote, try to "fix" it. 295| 0| if URL.scheme(url) == nil { 296| 0| // If the URL has no scheme, we treat it as a path (either absolute or relative to the base URL). 297| 0| return AbsolutePath(url, relativeTo: AbsolutePath(baseURL)).pathString 298| 0| } 299| 0| 300| 0| return url 301| 0| } 302| 0| 303| 0| try self.init( 304| 0| url: fixURL(json.get("url")), 305| 0| requirement: .init(v4: json.get("requirement")) 306| 0| ) 307| 0| } 308| |} 309| | 310| |extension TargetDescription.TargetType { 311| 0| fileprivate init(v4 string: String) throws { 312| 0| switch string { 313| 0| case "regular": 314| 0| self = .regular 315| 0| case "test": 316| 0| self = .test 317| 0| case "system": 318| 0| self = .system 319| 0| default: 320| 0| fatalError() 321| 0| } 322| 0| } 323| |} 324| | 325| |extension TargetDescription.Dependency { 326| 0| fileprivate init(v4 json: JSON) throws { 327| 0| let type = try json.get(String.self, forKey: "type") 328| 0| 329| 0| switch type { 330| 0| case "target": 331| 0| self = try .target(name: json.get("name")) 332| 0| 333| 0| case "product": 334| 0| let name = try json.get(String.self, forKey: "name") 335| 0| self = .product(name: name, package: json.get("package")) 336| 0| 337| 0| case "byname": 338| 0| self = try .byName(name: json.get("name")) 339| 0| 340| 0| default: 341| 0| fatalError() 342| 0| } 343| 0| } 344| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/Target+PkgConfig.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import SPMUtility 14| | 15| |/// Wrapper struct containing result of a pkgConfig query. 16| |public struct PkgConfigResult { 17| | 18| | /// The name of the pkgConfig file. 19| | public let pkgConfigName: String 20| | 21| | /// The cFlags from pkgConfig. 22| | public let cFlags: [String] 23| | 24| | /// The library flags from pkgConfig. 25| | public let libs: [String] 26| | 27| | /// Available provider, if any. 28| | public let provider: SystemPackageProviderDescription? 29| | 30| | /// Any error encountered during operation. 31| | public let error: Swift.Error? 32| | 33| | /// If the pc file was not found. 34| 0| public var couldNotFindConfigFile: Bool { 35| 0| switch error { 36| 0| case PkgConfigError.couldNotFindConfigFile?: return true 37| 0| default: return false 38| 0| } 39| 0| } 40| | 41| | /// Create a result. 42| | fileprivate init( 43| | pkgConfigName: String, 44| | cFlags: [String] = [], 45| | libs: [String] = [], 46| | error: Swift.Error? = nil, 47| | provider: SystemPackageProviderDescription? = nil 48| 0| ) { 49| 0| self.cFlags = cFlags 50| 0| self.libs = libs 51| 0| self.error = error 52| 0| self.provider = provider 53| 0| self.pkgConfigName = pkgConfigName 54| 0| } 55| |} 56| | 57| |/// Get pkgConfig result for a system library target. 58| 0|public func pkgConfigArgs(for target: SystemLibraryTarget, diagnostics: DiagnosticsEngine, fileSystem: FileSystem = localFileSystem, brewPrefix: AbsolutePath? = nil) -> PkgConfigResult? { 59| 0| // If there is no pkg config name defined, we're done. 60| 0| guard let pkgConfigName = target.pkgConfig else { return nil } 61| 0| 62| 0| // Compute additional search paths for the provider, if any. 63| 0| let provider = target.providers?.first { $0.isAvailable } 64| 0| let additionalSearchPaths = provider?.pkgConfigSearchPath(brewPrefixOverride: brewPrefix) ?? [] 65| 0| 66| 0| // Get the pkg config flags. 67| 0| do { 68| 0| let pkgConfig = try PkgConfig( 69| 0| name: pkgConfigName, 70| 0| additionalSearchPaths: additionalSearchPaths, 71| 0| diagnostics: diagnostics, 72| 0| fileSystem: fileSystem, 73| 0| brewPrefix: brewPrefix) 74| 0| 75| 0| // Run the whitelist checker. 76| 0| let filtered = whitelist(pcFile: pkgConfigName, flags: (pkgConfig.cFlags, pkgConfig.libs)) 77| 0| 78| 0| // Remove any default flags which compiler adds automatically. 79| 0| let (cFlags, libs) = removeDefaultFlags(cFlags: filtered.cFlags, libs: filtered.libs) 80| 0| 81| 0| // Set the error if there are any unallowed flags. 82| 0| var error: Swift.Error? 83| 0| if !filtered.unallowed.isEmpty { 84| 0| error = PkgConfigError.nonWhitelistedFlags(filtered.unallowed.joined(separator: ", ")) 85| 0| } 86| 0| 87| 0| return PkgConfigResult( 88| 0| pkgConfigName: pkgConfigName, 89| 0| cFlags: cFlags, 90| 0| libs: libs, 91| 0| error: error, 92| 0| provider: provider 93| 0| ) 94| 0| } catch { 95| 0| return PkgConfigResult(pkgConfigName: pkgConfigName, error: error, provider: provider) 96| 0| } 97| 0|} 98| | 99| |extension SystemPackageProviderDescription { 100| 0| public var installText: String { 101| 0| switch self { 102| 0| case .brew(let packages): 103| 0| return " brew install \(packages.joined(separator: " "))\n" 104| 0| case .apt(let packages): 105| 0| return " apt-get install \(packages.joined(separator: " "))\n" 106| 0| } 107| 0| } 108| | 109| | /// Check if the provider is available for the current platform. 110| 0| var isAvailable: Bool { 111| 0| guard let platform = Platform.currentPlatform else { return false } 112| 0| switch self { 113| 0| case .brew: 114| 0| if case .darwin = platform { 115| 0| return true 116| 0| } 117| 0| case .apt: 118| 0| if case .linux(.debian) = platform { 119| 0| return true 120| 0| } 121| 0| } 122| 0| return false 123| 0| } 124| | 125| 0| func pkgConfigSearchPath(brewPrefixOverride: AbsolutePath?) -> [AbsolutePath] { 126| 0| switch self { 127| 0| case .brew(let packages): 128| 0| let brewPrefix: String 129| 0| if let brewPrefixOverride = brewPrefixOverride { 130| 0| brewPrefix = brewPrefixOverride.pathString 131| 0| } else { 132| 0| // Homebrew can have multiple versions of the same package. The 133| 0| // user can choose another version than the latest by running 134| 0| // ``brew switch NAME VERSION``, so we shouldn't assume to link 135| 0| // to the latest version. Instead use the version as symlinked 136| 0| // in /usr/local/opt/(NAME)/lib/pkgconfig. 137| 0| struct Static { 138| 0| static let value = { try? Process.checkNonZeroExit(args: "brew", "--prefix").spm_chomp() }() 139| 0| } 140| 0| if let value = Static.value { 141| 0| brewPrefix = value 142| 0| } else { 143| 0| return [] 144| 0| } 145| 0| } 146| 0| return packages.map({ AbsolutePath(brewPrefix).appending(components: "opt", $0, "lib", "pkgconfig") }) 147| 0| case .apt: 148| 0| return [] 149| 0| } 150| 0| } 151| | 152| | // FIXME: Get rid of this method once we move on to new Build code. 153| 0| static func providerForCurrentPlatform(providers: [SystemPackageProviderDescription]) -> SystemPackageProviderDescription? { 154| 0| return providers.first(where: { $0.isAvailable }) 155| 0| } 156| |} 157| | 158| |/// Filters the flags with allowed arguments so unexpected arguments are not passed to 159| |/// compiler/linker. List of allowed flags: 160| |/// cFlags: -I, -F 161| |/// libs: -L, -l, -F, -framework, -w 162| |func whitelist( 163| | pcFile: String, 164| | flags: (cFlags: [String], libs: [String]) 165| 0|) -> (cFlags: [String], libs: [String], unallowed: [String]) { 166| 0| // Returns a tuple with the array of allowed flag and the array of unallowed flags. 167| 0| func filter(flags: [String], filters: [String]) -> (allowed: [String], unallowed: [String]) { 168| 0| var allowed = [String]() 169| 0| var unallowed = [String]() 170| 0| var it = flags.makeIterator() 171| 0| while let flag = it.next() { 172| 0| guard let filter = filters.filter({ flag.hasPrefix($0) }).first else { 173| 0| unallowed += [flag] 174| 0| continue 175| 0| } 176| 0| 177| 0| // Warning suppression flag has no arguments and is not suffixed. 178| 0| guard !flag.hasPrefix("-w") || flag == "-w" else { 179| 0| unallowed += [flag] 180| 0| continue 181| 0| } 182| 0| 183| 0| // If the flag and its value are separated, skip next flag. 184| 0| if flag == filter && flag != "-w" { 185| 0| guard it.next() != nil else { 186| 0| fatalError("Expected associated value") 187| 0| } 188| 0| } 189| 0| allowed += [flag] 190| 0| } 191| 0| return (allowed, unallowed) 192| 0| } 193| 0| 194| 0| let filteredCFlags = filter(flags: flags.cFlags, filters: ["-I", "-F"]) 195| 0| let filteredLibs = filter(flags: flags.libs, filters: ["-L", "-l", "-F", "-framework", "-w"]) 196| 0| 197| 0| return (filteredCFlags.allowed, filteredLibs.allowed, filteredCFlags.unallowed + filteredLibs.unallowed) 198| 0|} 199| | 200| |/// Remove the default flags which are already added by the compiler. 201| |/// 202| |/// This behavior is similar to pkg-config cli tool and helps avoid conflicts between 203| |/// sdk and default search paths in macOS. 204| 0|func removeDefaultFlags(cFlags: [String], libs: [String]) -> ([String], [String]) { 205| 0| /// removes a flag from given array of flags. 206| 0| func remove(flag: (String, String), from flags: [String]) -> [String] { 207| 0| var result = [String]() 208| 0| var it = flags.makeIterator() 209| 0| while let curr = it.next() { 210| 0| switch curr { 211| 0| case flag.0: 212| 0| // Check for style. 213| 0| guard let val = it.next() else { 214| 0| fatalError("Expected associated value") 215| 0| } 216| 0| // If we found a match, don't add these flags and just skip. 217| 0| if val == flag.1 { continue } 218| 0| // Otherwise add both the flags. 219| 0| result.append(curr) 220| 0| result.append(val) 221| 0| 222| 0| case flag.0 + flag.1: 223| 0| // Check for style. 224| 0| continue 225| 0| 226| 0| default: 227| 0| // Otherwise just append this flag. 228| 0| result.append(curr) 229| 0| } 230| 0| } 231| 0| return result 232| 0| } 233| 0| return (remove(flag: ("-I", "/usr/include"), from: cFlags), remove(flag: ("-L", "/usr/lib"), from: libs)) 234| 0|} 235| | 236| |public struct PkgConfigDiagnosticLocation: DiagnosticLocation { 237| | public let pcFile: String 238| | public let target: String 239| | 240| 0| public init(pcFile: String, target: String) { 241| 0| self.pcFile = pcFile 242| 0| self.target = target 243| 0| } 244| | 245| 0| public var localizedDescription: String { 246| 0| return "'\(target)' \(pcFile).pc" 247| 0| } 248| |} 249| | 250| |public struct PkgConfigGenericDiagnostic: DiagnosticData { 251| | public static let id = DiagnosticID( 252| | type: PkgConfigGenericDiagnostic.self, 253| | name: "org.swift.diags.pkg-config-generic", 254| | defaultBehavior: .warning, 255| | description: { 256| 0| $0 <<< { $0.error } 257| | } 258| | ) 259| | 260| | public let error: String 261| | 262| 0| public init(error: String) { 263| 0| self.error = error 264| 0| } 265| |} 266| | 267| |public struct PkgConfigHintDiagnostic: DiagnosticData { 268| | public static let id = DiagnosticID( 269| | type: PkgConfigHintDiagnostic.self, 270| | name: "org.swift.diags.pkg-config-hint", 271| | defaultBehavior: .warning, 272| 0| description: { 273| 0| $0 <<< "you may be able to install" <<< { $0.pkgConfigName } <<< "using your system-packager:\n" 274| 0| $0 <<< { $0.installText } 275| 0| } 276| | ) 277| | 278| | public let pkgConfigName: String 279| | public let installText: String 280| | 281| 0| public init(pkgConfigName: String, installText: String) { 282| 0| self.pkgConfigName = pkgConfigName 283| 0| self.installText = installText 284| 0| } 285| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/PackageLoading/ToolsVersionLoader.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import SPMUtility 14| |import Foundation 15| | 16| |/// Protocol for the manifest loader interface. 17| |public protocol ToolsVersionLoaderProtocol { 18| | 19| | /// Load the tools version at the give package path. 20| | /// 21| | /// - Parameters: 22| | /// - path: The path to the package. 23| | /// - fileSystem: The file system to use to read the file which contains tools version. 24| | /// - Returns: The tools version. 25| | /// - Throws: ToolsVersion.Error 26| | func load(at path: AbsolutePath, fileSystem: FileSystem) throws -> ToolsVersion 27| |} 28| | 29| |extension Manifest { 30| | /// Returns the manifest at the given package path. 31| | /// 32| | /// Version specific manifest is chosen if present, otherwise path to regular 33| | /// manfiest is returned. 34| | public static func path( 35| | atPackagePath packagePath: AbsolutePath, 36| | currentToolsVersion: ToolsVersion = .currentToolsVersion, 37| | fileSystem: FileSystem 38| 0| ) throws -> AbsolutePath { 39| 0| // Look for a version-specific manifest. 40| 0| for versionSpecificKey in Versioning.currentVersionSpecificKeys { 41| 0| let versionSpecificPath = packagePath.appending(component: Manifest.basename + versionSpecificKey + ".swift") 42| 0| if fileSystem.isFile(versionSpecificPath) { 43| 0| return versionSpecificPath 44| 0| } 45| 0| } 46| 0| 47| 0| // Otherwise, check if there is a version-specific manifest that has 48| 0| // a higher tools version than the main Package.swift file. 49| 0| let contents = try fileSystem.getDirectoryContents(packagePath) 50| 0| let regex = try! RegEx(pattern: "^Package@swift-(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?.swift$") 51| 0| 52| 0| // Collect all version-specific manifests at the given package path. 53| 0| let versionSpecificManifests = Dictionary(items: contents.compactMap{ file -> (ToolsVersion, String)? in 54| 0| let parsedVersion = regex.matchGroups(in: file) 55| 0| guard parsedVersion.count == 1, parsedVersion[0].count == 3 else { 56| 0| return nil 57| 0| } 58| 0| 59| 0| let major = Int(parsedVersion[0][0])! 60| 0| let minor = parsedVersion[0][1].isEmpty ? 0 : Int(parsedVersion[0][1])! 61| 0| let patch = parsedVersion[0][2].isEmpty ? 0 : Int(parsedVersion[0][2])! 62| 0| 63| 0| return (ToolsVersion(version: Version(major, minor, patch)), file) 64| 0| }) 65| 0| 66| 0| let regularManifest = packagePath.appending(component: filename) 67| 0| let toolsVersionLoader = ToolsVersionLoader() 68| 0| 69| 0| // Find the version-specific manifest that statisfies the current tools version. 70| 0| if let versionSpecificCandidate = versionSpecificManifests.keys.sorted(by: >).first(where: { $0 <= currentToolsVersion }) { 71| 0| let versionSpecificManifest = packagePath.appending(component: versionSpecificManifests[versionSpecificCandidate]!) 72| 0| 73| 0| // Compare the tools version of this manifest with the regular 74| 0| // manifest and use the version-specific manifest if it has 75| 0| // a greater tools version. 76| 0| let versionSpecificManifestToolsVersion = try toolsVersionLoader.load(file: versionSpecificManifest, fileSystem: fileSystem) 77| 0| let regularManifestToolsVersion = try toolsVersionLoader.load(file: regularManifest, fileSystem: fileSystem) 78| 0| if versionSpecificManifestToolsVersion > regularManifestToolsVersion { 79| 0| return versionSpecificManifest 80| 0| } 81| 0| } 82| 0| 83| 0| return regularManifest 84| 0| } 85| |} 86| | 87| |public class ToolsVersionLoader: ToolsVersionLoaderProtocol { 88| | 89| | let currentToolsVersion: ToolsVersion 90| | 91| 0| public init(currentToolsVersion: ToolsVersion = .currentToolsVersion) { 92| 0| self.currentToolsVersion = currentToolsVersion 93| 0| } 94| | 95| | public enum Error: Swift.Error, CustomStringConvertible { 96| | case malformed(specifier: String, file: AbsolutePath) 97| | 98| 0| public var description: String { 99| 0| switch self { 100| 0| case .malformed(let versionSpecifier, let file): 101| 0| return "the version specifier '\(versionSpecifier)' in '\(file)' is not valid" 102| 0| } 103| 0| } 104| | } 105| | 106| 0| public func load(at path: AbsolutePath, fileSystem: FileSystem) throws -> ToolsVersion { 107| 0| // The file which contains the tools version. 108| 0| let file = try Manifest.path(atPackagePath: path, currentToolsVersion: currentToolsVersion, fileSystem: fileSystem) 109| 0| guard fileSystem.isFile(file) else { 110| 0| // FIXME: We should return an error from here but Workspace tests rely on this in order to work. 111| 0| // This doesn't really cause issues (yet) in practice though. 112| 0| return ToolsVersion.currentToolsVersion 113| 0| } 114| 0| return try load(file: file, fileSystem: fileSystem) 115| 0| } 116| | 117| 0| fileprivate func load(file: AbsolutePath, fileSystem: FileSystem) throws -> ToolsVersion { 118| 0| // FIXME: We don't need the entire file, just the first line. 119| 0| let contents = try fileSystem.readFileContents(file) 120| 0| 121| 0| // Get the version specifier string from tools version file. 122| 0| guard let versionSpecifier = ToolsVersionLoader.split(contents).versionSpecifier else { 123| 0| // Try to diagnose if there is a misspelling of the swift-tools-version comment. 124| 0| let splitted = contents.contents.split( 125| 0| separator: UInt8(ascii: "\n"), 126| 0| maxSplits: 1, 127| 0| omittingEmptySubsequences: false) 128| 0| let misspellings = ["swift-tool", "tool-version"] 129| 0| if let firstLine = ByteString(splitted[0]).validDescription, 130| 0| misspellings.first(where: firstLine.lowercased().contains) != nil { 131| 0| throw Error.malformed(specifier: firstLine, file: file) 132| 0| } 133| 0| // Otherwise assume the default to be v3. 134| 0| return .v3 135| 0| } 136| 0| 137| 0| // Ensure we can construct the version from the specifier. 138| 0| guard let version = ToolsVersion(string: versionSpecifier) else { 139| 0| throw Error.malformed(specifier: versionSpecifier, file: file) 140| 0| } 141| 0| return version 142| 0| } 143| | 144| | /// Splits the bytes to the version specifier (if present) and rest of the contents. 145| 0| public static func split(_ bytes: ByteString) -> (versionSpecifier: String?, rest: [UInt8]) { 146| 0| let splitted = bytes.contents.split( 147| 0| separator: UInt8(ascii: "\n"), 148| 0| maxSplits: 1, 149| 0| omittingEmptySubsequences: false) 150| 0| // Try to match our regex and see if a valid specifier line. 151| 0| guard let firstLine = ByteString(splitted[0]).validDescription, 152| 0| let match = ToolsVersionLoader.regex.firstMatch( 153| 0| in: firstLine, options: [], range: NSRange(location: 0, length: firstLine.count)), 154| 0| match.numberOfRanges >= 2 else { 155| 0| return (nil, bytes.contents) 156| 0| } 157| 0| let versionSpecifier = NSString(string: firstLine).substring(with: match.range(at: 1)) 158| 0| // FIXME: We can probably optimize here and return array slice. 159| 0| return (versionSpecifier, splitted.count == 1 ? [] : Array(splitted[1])) 160| 0| } 161| | 162| | // The regex to match swift tools version specification: 163| | // * It should start with `//` followed by any amount of whitespace. 164| | // * Following that it should contain the case insensitive string `swift-tools-version:`. 165| | // * The text between the above string and `;` or string end becomes the tools version specifier. 166| | static let regex = try! NSRegularExpression( 167| | pattern: "^// swift-tools-version:(.*?)(?:;.*|$)", 168| | options: [.caseInsensitive]) 169| |} <<<<<< EOF # path=llbuildBasic.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/ExecutionQueue.cpp: 1| |//===-- ExecutionQueue.cpp ------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/ExecutionQueue.h" 14| | 15| |#include "llvm/ADT/ArrayRef.h" 16| |#include "llvm/ADT/SmallString.h" 17| |#include "llvm/ADT/StringRef.h" 18| | 19| |#include 20| |#include 21| | 22| |using namespace llbuild; 23| |using namespace llbuild::basic; 24| | 25| | 26| 0|JobDescriptor::~JobDescriptor() { 27| 0|} 28| | 29| 0|QueueJobContext::~QueueJobContext() { 30| 0|} 31| | 32| |ExecutionQueue::ExecutionQueue(ExecutionQueueDelegate& delegate) 33| | : delegate(delegate) 34| 0|{ 35| 0|} 36| | 37| 0|ExecutionQueue::~ExecutionQueue() { 38| 0|} 39| | 40| |ProcessStatus ExecutionQueue::executeProcess(QueueJobContext* context, 41| 0| ArrayRef commandLine) { 42| 0| // Promises are move constructible only, thus cannot be put into std::function 43| 0| // objects that themselves get copied around. So we must create a shared_ptr 44| 0| // here to allow it to go along with the labmda. 45| 0| std::shared_ptr> p{new std::promise}; 46| 0| auto result = p->get_future(); 47| 0| executeProcess(context, commandLine, {}, true, {true}, 48| 0| {[p](ProcessResult result) mutable { 49| 0| p->set_value(result.status); 50| 0| }}); 51| 0| return result.get(); 52| 0|} 53| | 54| |bool ExecutionQueue::executeShellCommand(QueueJobContext* context, 55| 0| StringRef command) { 56| 0| SmallString<1024> commandStorage(command); 57| 0| std::vector commandLine( 58| |#if defined(_WIN32) 59| | {"C:\\windows\\system32\\cmd.exe", "/C", commandStorage.c_str()}); 60| |#else 61| | {"/bin/sh", "-c", commandStorage.c_str()}); 62| 0|#endif 63| 0| return executeProcess(context, commandLine) == ProcessStatus::Succeeded; 64| 0|} 65| | 66| 0|ExecutionQueueDelegate::~ExecutionQueueDelegate() { 67| 0|} 68| | 69| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/FileInfo.cpp: 1| |//===-- FileInfo.cpp ------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/FileInfo.h" 14| | 15| |#include "llbuild/Basic/Stat.h" 16| | 17| |#include 18| |#include 19| | 20| |using namespace llbuild; 21| |using namespace llbuild::basic; 22| | 23| 0|bool FileInfo::isDirectory() const { 24| 0| return (mode & S_IFDIR) != 0; 25| 0|} 26| | 27| |/// Get the information to represent the state of the given node in the file 28| |/// system. 29| |/// 30| |/// \param info_out [out] On success, the important path information. 31| |/// \returns True if information on the path was found. 32| 0|FileInfo FileInfo::getInfoForPath(const std::string& path, bool asLink) { 33| 0| FileInfo result; 34| 0| 35| 0| sys::StatStruct buf; 36| 0| auto statResult = 37| 0| asLink ? sys::lstat(path.c_str(), &buf) : sys::stat(path.c_str(), &buf); 38| 0| if (statResult != 0) { 39| 0| memset(&result, 0, sizeof(result)); 40| 0| assert(result.isMissing()); 41| 0| return result; 42| 0| } 43| 0| 44| 0| result.device = buf.st_dev; 45| 0| result.inode = buf.st_ino; 46| 0| result.mode = buf.st_mode; 47| 0| result.size = buf.st_size; 48| 0|#if defined(__APPLE__) 49| 0| auto seconds = buf.st_mtimespec.tv_sec; 50| 0| auto nanoseconds = buf.st_mtimespec.tv_nsec; 51| |#elif defined(_WIN32) 52| | auto seconds = buf.st_mtime; 53| | auto nanoseconds = 0; 54| |#else 55| | auto seconds = buf.st_mtim.tv_sec; 56| | auto nanoseconds = buf.st_mtim.tv_nsec; 57| |#endif 58| | result.modTime.seconds = seconds; 59| 0| result.modTime.nanoseconds = nanoseconds; 60| 0| 61| 0| // Enforce we never accidentally create our sentinel missing file value. 62| 0| if (result.isMissing()) { 63| 0| result.modTime.nanoseconds = 1; 64| 0| assert(!result.isMissing()); 65| 0| } 66| 0| 67| 0| return result; 68| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/FileSystem.cpp: 1| |//===-- FileSystem.cpp ----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/FileSystem.h" 14| |#include "llbuild/Basic/PlatformUtility.h" 15| |#include "llbuild/Basic/Stat.h" 16| | 17| |#include "llvm/ADT/STLExtras.h" 18| |#include "llvm/Support/FileSystem.h" 19| |#include "llvm/Support/Path.h" 20| |#include "llvm/Support/MemoryBuffer.h" 21| | 22| |#include 23| |#include 24| | 25| |// Cribbed from llvm, where it's been since removed. 26| |namespace { 27| | using namespace std; 28| | using namespace llvm; 29| | using namespace llvm::sys::fs; 30| | 31| | static std::error_code fillStatus(int StatRet, const llbuild::basic::sys::StatStruct &Status, 32| 0| file_status &Result) { 33| 0| if (StatRet != 0) { 34| 0| std::error_code ec(errno, std::generic_category()); 35| 0| if (ec == errc::no_such_file_or_directory) 36| 0| Result = file_status(file_type::file_not_found); 37| 0| else 38| 0| Result = file_status(file_type::status_error); 39| 0| return ec; 40| 0| } 41| 0| 42| 0| file_type Type = file_type::type_unknown; 43| 0| 44| 0| if (S_ISDIR(Status.st_mode)) 45| 0| Type = file_type::directory_file; 46| 0| else if (S_ISREG(Status.st_mode)) 47| 0| Type = file_type::regular_file; 48| 0| else if (S_ISBLK(Status.st_mode)) 49| 0| Type = file_type::block_file; 50| 0| else if (S_ISCHR(Status.st_mode)) 51| 0| Type = file_type::character_file; 52| 0| else if (S_ISFIFO(Status.st_mode)) 53| 0| Type = file_type::fifo_file; 54| 0| else if (S_ISSOCK(Status.st_mode)) 55| 0| Type = file_type::socket_file; 56| 0| else if (S_ISLNK(Status.st_mode)) 57| 0| Type = file_type::symlink_file; 58| 0| 59| |#if defined(_WIN32) 60| | Result = file_status(Type); 61| |#else 62| | perms Perms = static_cast(Status.st_mode); 63| 0| Result = 64| 0| file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime, 65| 0| Status.st_uid, Status.st_gid, Status.st_size); 66| 0|#endif 67| 0| 68| 0| return std::error_code(); 69| 0| } 70| | 71| 0| std::error_code link_status(const Twine &Path, file_status &Result) { 72| 0| SmallString<128> PathStorage; 73| 0| StringRef P = Path.toNullTerminatedStringRef(PathStorage); 74| 0| 75| 0| llbuild::basic::sys::StatStruct Status; 76| 0| int StatRet = llbuild::basic::sys::lstat(P.begin(), &Status); 77| 0| return fillStatus(StatRet, Status, Result); 78| 0| } 79| | 80| 0| error_code _remove_all_r(StringRef path, file_type ft, uint32_t &count) { 81| 0| if (ft == file_type::directory_file) { 82| 0| error_code ec; 83| 0| directory_iterator i(path, ec); 84| 0| if (ec) 85| 0| return ec; 86| 0| 87| 0| for (directory_iterator e; i != e; i.increment(ec)) { 88| 0| if (ec) 89| 0| return ec; 90| 0| 91| 0| file_status st; 92| 0| 93| 0| if (error_code ec = link_status(i->path(), st)) 94| 0| return ec; 95| 0| 96| 0| if (error_code ec = _remove_all_r(i->path(), st.type(), count)) 97| 0| return ec; 98| 0| } 99| 0| 100| 0| if (error_code ec = remove(path, false)) 101| 0| return ec; 102| 0| 103| 0| ++count; // Include the directory itself in the items removed. 104| 0| } else { 105| 0| if (error_code ec = remove(path, false)) 106| 0| return ec; 107| 0| 108| 0| ++count; 109| 0| } 110| 0| 111| 0| return error_code(); 112| 0| } 113| |} 114| | 115| |using namespace llbuild; 116| |using namespace llbuild::basic; 117| | 118| 0|FileSystem::~FileSystem() {} 119| | 120| 0|bool FileSystem::createDirectories(const std::string& path) { 121| 0| // Attempt to create the final directory first, to optimize for the common 122| 0| // case where we don't need to recurse. 123| 0| if (createDirectory(path)) 124| 0| return true; 125| 0| 126| 0| // If that failed, attempt to create the parent. 127| 0| StringRef parent = llvm::sys::path::parent_path(path); 128| 0| if (parent.empty()) 129| 0| return false; 130| 0| return createDirectories(parent) && createDirectory(path); 131| 0|} 132| | 133| | 134| |std::unique_ptr 135| 0|DeviceAgnosticFileSystem::getFileContents(const std::string& path) { 136| 0| return impl->getFileContents(path); 137| 0|} 138| |namespace { 139| | 140| |class LocalFileSystem : public FileSystem { 141| |public: 142| 0| LocalFileSystem() {} 143| | 144| | virtual bool 145| 0| createDirectory(const std::string& path) override { 146| 0| if (!llbuild::basic::sys::mkdir(path.c_str())) { 147| 0| if (errno != EEXIST) { 148| 0| return false; 149| 0| } 150| 0| } 151| 0| return true; 152| 0| } 153| | 154| | virtual std::unique_ptr 155| 0| getFileContents(const std::string& path) override { 156| 0| auto result = llvm::MemoryBuffer::getFile(path); 157| 0| if (result.getError()) { 158| 0| return nullptr; 159| 0| } 160| 0| return std::unique_ptr(result->release()); 161| 0| } 162| | 163| 0| bool rm_tree(const char* path) { 164| 0| uint32_t count = 0; 165| 0| return !_remove_all_r(path, file_type::directory_file, count); 166| 0| } 167| | 168| 0| virtual bool remove(const std::string& path) override { 169| 0| // Assume `path` is a regular file. 170| 0| if (llbuild::basic::sys::unlink(path.c_str()) == 0) { 171| 0| return true; 172| 0| } 173| 0| 174| |#if defined(_WIN32) 175| | // Windows sets EACCES if the file is a directory 176| | if (errno != EACCES) { 177| | return false; 178| | } 179| |#else 180| | // Error can't be that `path` is actually a directory (on Linux `EISDIR` will be returned since 2.1.132). 181| 0| if (errno != EPERM && errno != EISDIR) { 182| 0| return false; 183| 0| } 184| 0|#endif 185| 0| 186| 0| // Check if `path` is a directory. 187| 0| llbuild::basic::sys::StatStruct statbuf; 188| 0| if (llbuild::basic::sys::lstat(path.c_str(), &statbuf) != 0) { 189| 0| return false; 190| 0| } 191| 0| 192| 0| if (S_ISDIR(statbuf.st_mode)) { 193| 0| if (llbuild::basic::sys::rmdir(path.c_str()) == 0) { 194| 0| return true; 195| 0| } else { 196| 0| return rm_tree(path.c_str()); 197| 0| } 198| 0| } 199| 0| 200| 0| return false; 201| 0| } 202| | 203| 0| virtual FileInfo getFileInfo(const std::string& path) override { 204| 0| return FileInfo::getInfoForPath(path); 205| 0| } 206| | 207| 0| virtual FileInfo getLinkInfo(const std::string& path) override { 208| 0| return FileInfo::getInfoForPath(path, /*isLink:*/ true); 209| 0| } 210| |}; 211| | 212| |} 213| | 214| 0|std::unique_ptr basic::createLocalFileSystem() { 215| 0| return llvm::make_unique(); 216| 0|} 217| | 218| |std::unique_ptr 219| 0|basic::DeviceAgnosticFileSystem::from(std::unique_ptr fs) { 220| 0| return llvm::make_unique(std::move(fs)); 221| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/Hashing.cpp: 1| |//===-- Hashing.cpp -------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/Hashing.h" 14| | 15| |#include "llbuild/Basic/LLVM.h" 16| | 17| |#include "llvm/ADT/Hashing.h" 18| | 19| |namespace llbuild { 20| |namespace basic { 21| | 22| 0|uint64_t hashString(StringRef value) { 23| 0| return hash_value(value); 24| 0|} 25| | 26| |} 27| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/LaneBasedExecutionQueue.cpp: 1| |//===-- LaneBasedExecutionQueue.cpp ---------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014-2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/ExecutionQueue.h" 14| | 15| |#include "llbuild/Basic/Tracing.h" 16| | 17| |#include "llvm/ADT/ArrayRef.h" 18| |#include "llvm/ADT/SmallString.h" 19| |#include "llvm/ADT/StringRef.h" 20| |#include "llvm/ADT/STLExtras.h" 21| |#include "llvm/ADT/Twine.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| | 30| |#include 31| | 32| |#ifdef __APPLE__ 33| |#include 34| |#endif 35| | 36| |using namespace llbuild; 37| |using namespace llbuild::basic; 38| | 39| |struct QueueJobLess { 40| | bool operator()(const llbuild::basic::QueueJob &__x, 41| 0| const llbuild::basic::QueueJob &__y) const { 42| 0| return __x.getDescriptor()->getOrdinalName() < 43| 0| __y.getDescriptor()->getOrdinalName(); 44| 0| } 45| |}; 46| | 47| |namespace { 48| | 49| |struct LaneBasedExecutionQueueJobContext : public QueueJobContext { 50| | uint64_t jobID; 51| | uint64_t laneNumber; 52| | 53| | QueueJob& job; 54| | 55| | LaneBasedExecutionQueueJobContext( 56| | uint64_t jobID, uint64_t laneNumber, QueueJob& job) 57| 0| : jobID(jobID), laneNumber(laneNumber), job(job) {} 58| | 59| 0| unsigned laneID() const override { return laneNumber; } 60| |}; 61| | 62| | 63| |class Scheduler { 64| |public: 65| 0| virtual ~Scheduler() { } 66| | 67| | virtual void addJob(QueueJob job) = 0; 68| | virtual QueueJob getNextJob() = 0; 69| | virtual bool empty() const = 0; 70| | virtual uint64_t size() const = 0; 71| | 72| | static std::unique_ptr make(SchedulerAlgorithm alg); 73| |}; 74| | 75| |/// Build execution queue. 76| |// 77| |// FIXME: Consider trying to share this with the Ninja implementation. 78| |class LaneBasedExecutionQueue : public ExecutionQueue { 79| | /// (Random) build identifier 80| | uint32_t buildID; 81| | 82| | /// The number of lanes the queue was configured with. 83| | unsigned numLanes; 84| | 85| | /// A thread for each lane. 86| | std::vector> lanes; 87| | 88| | /// The ready queue of jobs to execute. 89| | std::unique_ptr readyJobs; 90| | std::mutex readyJobsMutex; 91| | std::condition_variable readyJobsCondition; 92| | bool cancelled { false }; 93| | bool shutdown { false }; 94| | 95| | ProcessGroup spawnedProcesses; 96| | 97| | /// Management of cancellation and SIGKILL escalation 98| | std::mutex killAfterTimeoutThreadMutex; 99| | std::unique_ptr killAfterTimeoutThread = nullptr; 100| | std::condition_variable queueCompleteCondition; 101| | std::mutex queueCompleteMutex; 102| | bool queueComplete { false }; 103| | 104| | /// Background (lane released) task management 105| | unsigned backgroundTaskMax = 0; 106| | std::atomic backgroundTaskCount{0}; 107| | 108| | 109| | /// The base environment. 110| | const char* const* environment; 111| | 112| 0| void executeLane(uint32_t buildID, uint32_t laneNumber) { 113| 0| // Set the thread name, if available. 114| 0|#if defined(__APPLE__) 115| 0| pthread_setname_np( 116| 0| (llvm::Twine("org.swift.llbuild Lane-") + 117| 0| llvm::Twine(laneNumber)).str().c_str()); 118| |#elif defined(__linux__) 119| | pthread_setname_np( 120| | pthread_self(), 121| | (llvm::Twine("org.swift.llbuild Lane-") + 122| | llvm::Twine(laneNumber)).str().c_str()); 123| |#endif 124| | 125| 0| // Set the QoS class, if available. 126| 0| setCurrentThreadQualityOfService(getDefaultQualityOfService()); 127| 0| 128| 0| // Lane ID, used in creating reasonably unique task IDs, stores the buildID 129| 0| // in the top 32 bits. The laneID is stored in bits 16:31, and the job 130| 0| // count is placed in the lower order 16 bits. These are not strictly 131| 0| // guaranteed to be unique, but should be close enough for common use cases. 132| 0| uint32_t jobCount = 0; 133| 0| uint64_t laneID = (((uint64_t)buildID & 0xFFFF) << 32) + (((uint64_t)laneNumber & 0xFFFF) << 16); 134| 0| 135| 0| // Execute items from the queue until shutdown. 136| 0| while (true) { 137| 0| // Take a job from the ready queue. 138| 0| QueueJob job{}; 139| 0| uint64_t readyJobsCount; 140| 0| { 141| 0| std::unique_lock lock(readyJobsMutex); 142| 0| 143| 0| // While the queue is empty, wait for an item. 144| 0| while (!shutdown && readyJobs->empty()) { 145| 0| readyJobsCondition.wait(lock); 146| 0| } 147| 0| if (shutdown && readyJobs->empty()) 148| 0| return; 149| 0| 150| 0| // Take an item according to the chosen policy. 151| 0| job = readyJobs->getNextJob(); 152| 0| readyJobsCount = readyJobs->size(); 153| 0| } 154| 0| 155| 0| // If we got an empty job, the queue is shutting down. 156| 0| if (!job.getDescriptor()) 157| 0| break; 158| 0| 159| 0| // Process the job. 160| 0| jobCount++; 161| 0| uint64_t jobID = laneID + jobCount; 162| 0| LaneBasedExecutionQueueJobContext context{ jobID, laneNumber, job }; 163| 0| { 164| 0| TracingExecutionQueueDepth(readyJobsCount); 165| 0| 166| 0| llvm::SmallString<64> description; 167| 0| job.getDescriptor()->getShortDescription(description); 168| 0| TracingExecutionQueueJob t(context.laneNumber, description.str()); 169| 0| 170| 0| getDelegate().queueJobStarted(job.getDescriptor()); 171| 0| job.execute(reinterpret_cast(&context)); 172| 0| getDelegate().queueJobFinished(job.getDescriptor()); 173| 0| } 174| 0| } 175| 0| } 176| | 177| 0| void killAfterTimeout() { 178| 0| std::unique_lock lock(queueCompleteMutex); 179| 0| 180| 0| if (!queueComplete) { 181| 0| // Shorten timeout if in testing context 182| 0| if (getenv("LLBUILD_TEST") != nullptr) { 183| 0| queueCompleteCondition.wait_for(lock, std::chrono::milliseconds(1000)); 184| 0| } else { 185| 0| queueCompleteCondition.wait_for(lock, std::chrono::seconds(10)); 186| 0| } 187| 0| 188| |#if _WIN32 189| | spawnedProcesses.signalAll(SIGTERM); 190| |#else 191| | spawnedProcesses.signalAll(SIGKILL); 192| 0|#endif 193| 0| } 194| 0| } 195| | 196| |public: 197| | LaneBasedExecutionQueue(ExecutionQueueDelegate& delegate, 198| | unsigned numLanes, SchedulerAlgorithm alg, 199| | const char* const* environment) 200| | : ExecutionQueue(delegate), buildID(std::random_device()()), numLanes(numLanes), 201| | readyJobs(Scheduler::make(alg)), environment(environment) 202| 0| { 203| 0| backgroundTaskMax = numLanes * 16; 204| 0| for (unsigned i = 0; i != numLanes; ++i) { 205| 0| lanes.push_back(std::unique_ptr( 206| 0| new std::thread( 207| 0| &LaneBasedExecutionQueue::executeLane, this, buildID, i))); 208| 0| } 209| 0| } 210| | 211| 0| virtual ~LaneBasedExecutionQueue() { 212| 0| // Shut down the lanes. 213| 0| { 214| 0| std::unique_lock lock(readyJobsMutex); 215| 0| shutdown = true; 216| 0| readyJobsCondition.notify_all(); 217| 0| } 218| 0| 219| 0| for (unsigned i = 0; i != numLanes; ++i) { 220| 0| lanes[i]->join(); 221| 0| } 222| 0| 223| 0| { 224| 0| std::lock_guard guard(killAfterTimeoutThreadMutex); 225| 0| if (killAfterTimeoutThread) { 226| 0| { 227| 0| std::unique_lock lock(queueCompleteMutex); 228| 0| queueComplete = true; 229| 0| queueCompleteCondition.notify_all(); 230| 0| } 231| 0| killAfterTimeoutThread->join(); 232| 0| } 233| 0| } 234| 0| } 235| | 236| 0| virtual void addJob(QueueJob job) override { 237| 0| uint64_t readyJobsCount; 238| 0| { 239| 0| std::lock_guard guard(readyJobsMutex); 240| 0| readyJobs->addJob(job); 241| 0| readyJobsCondition.notify_one(); 242| 0| readyJobsCount = readyJobs->size(); 243| 0| } 244| 0| TracingExecutionQueueDepth(readyJobsCount); 245| 0| } 246| | 247| 0| virtual void cancelAllJobs() override { 248| 0| { 249| 0| std::lock_guard lock(readyJobsMutex); 250| 0| std::lock_guard guard(spawnedProcesses.mutex); 251| 0| if (cancelled) return; 252| 0| cancelled = true; 253| 0| spawnedProcesses.close(); 254| 0| readyJobsCondition.notify_all(); 255| 0| } 256| 0| 257| 0| spawnedProcesses.signalAll(SIGINT); 258| 0| { 259| 0| std::lock_guard guard(killAfterTimeoutThreadMutex); 260| 0| killAfterTimeoutThread = llvm::make_unique( 261| 0| &LaneBasedExecutionQueue::killAfterTimeout, this); 262| 0| } 263| 0| } 264| | 265| | virtual void executeProcess( 266| | QueueJobContext* opaqueContext, 267| | ArrayRef commandLine, 268| | ArrayRef> environment, 269| | bool inheritEnvironment, 270| | ProcessAttributes attributes, 271| 0| llvm::Optional completionFn) override { 272| 0| 273| 0| LaneBasedExecutionQueueJobContext& context = 274| 0| *reinterpret_cast(opaqueContext); 275| 0| 276| 0| llvm::SmallString<64> description; 277| 0| context.job.getDescriptor()->getShortDescription(description); 278| 0| TracingExecutionQueueSubprocessStart(context.laneNumber, description.str()); 279| 0| 280| 0| { 281| 0| std::unique_lock lock(readyJobsMutex); 282| 0| // Do not execute new processes anymore after cancellation. 283| 0| if (cancelled) { 284| 0| completionFn.unwrapIn([](ProcessCompletionFn fn){ 285| 0| fn(ProcessResult::makeCancelled()); 286| 0| }); 287| 0| return; 288| 0| } 289| 0| } 290| 0| 291| 0| // Form the complete environment. 292| 0| // 293| 0| // NOTE: We construct the environment in order of precedence, so 294| 0| // overridden keys should be defined first. 295| 0| POSIXEnvironment posixEnv; 296| 0| 297| 0| // Export lane ID to subprocesses. 298| 0| posixEnv.setIfMissing("LLBUILD_BUILD_ID", Twine(buildID).str()); 299| 0| posixEnv.setIfMissing("LLBUILD_LANE_ID", Twine(context.laneNumber).str()); 300| 0| 301| 0| // Add the requested environment. 302| 0| for (const auto& entry: environment) { 303| 0| posixEnv.setIfMissing(entry.first, entry.second); 304| 0| } 305| 0| 306| 0| // Inherit the base environment, if desired. 307| 0| // 308| 0| // FIXME: This involves a lot of redundant allocation, currently. We could 309| 0| // cache this for the common case of a directly inherited environment. 310| 0| if (inheritEnvironment) { 311| 0| for (const char* const* p = this->environment; *p != nullptr; ++p) { 312| 0| auto pair = StringRef(*p).split('='); 313| 0| posixEnv.setIfMissing(pair.first, pair.second); 314| 0| } 315| 0| } 316| 0| 317| 0| // Assign a process handle, which just needs to be unique for as long as we 318| 0| // are communicating with the delegate. 319| 0| ProcessHandle handle; 320| 0| handle.id = context.jobID; 321| 0| 322| 0| ProcessReleaseFn releaseFn = [this](std::function&& processWait) { 323| 0| bool releaseAllowed = false; 324| 0| // This check is not guaranteed to prevent more than backgroundTaskMax 325| 0| // tasks from releasing. We could race between the check and increment and 326| 0| // thus have a few extra. However, for our purposes, this should be fine. 327| 0| // The cap is primarly intended to prevent runaway explosions of tasks. 328| 0| if (backgroundTaskCount < backgroundTaskMax) { 329| 0| backgroundTaskCount++; 330| 0| releaseAllowed = true; 331| 0| } 332| 0| if (releaseAllowed) { 333| 0| // Launch the process wait on a detached thread 334| 0| std::thread([this, processWait=std::move(processWait)]() mutable { 335| 0| processWait(); 336| 0| backgroundTaskCount--; 337| 0| }).detach(); 338| 0| } else { 339| 0| // not allowed to release, call wait directly 340| 0| processWait(); 341| 0| } 342| 0| }; 343| 0| 344| 0| ProcessCompletionFn laneCompletionFn{ 345| 0| [completionFn, lane=context.laneNumber](ProcessResult result) mutable { 346| 0| TracingExecutionQueueSubprocessResult(lane, result.pid, result.utime, 347| 0| result.stime, result.maxrss); 348| 0| completionFn.unwrapIn([result](ProcessCompletionFn fn){ 349| 0| fn(result); 350| 0| }); 351| 0| } 352| 0| }; 353| 0| 354| 0| spawnProcess( 355| 0| getDelegate(), 356| 0| reinterpret_cast(context.job.getDescriptor()), 357| 0| spawnedProcesses, 358| 0| handle, 359| 0| commandLine, 360| 0| posixEnv, 361| 0| attributes, 362| 0| std::move(releaseFn), 363| 0| std::move(laneCompletionFn) 364| 0| ); 365| 0| } 366| |}; 367| | 368| |class PriorityQueueScheduler : public Scheduler { 369| |private: 370| | std::priority_queue, QueueJobLess> jobs; 371| | 372| |public: 373| 0| void addJob(QueueJob job) override { 374| 0| jobs.push(job); 375| 0| } 376| | 377| 0| QueueJob getNextJob() override { 378| 0| QueueJob job = jobs.top(); 379| 0| jobs.pop(); 380| 0| return job; 381| 0| } 382| | 383| 0| bool empty() const override { 384| 0| return jobs.empty(); 385| 0| } 386| | 387| 0| uint64_t size() const override { 388| 0| return jobs.size(); 389| 0| } 390| |}; 391| | 392| |class FifoScheduler : public Scheduler { 393| |private: 394| | std::deque jobs; 395| | 396| |public: 397| 0| void addJob(QueueJob job) override { 398| 0| jobs.push_back(job); 399| 0| } 400| | 401| 0| QueueJob getNextJob() override { 402| 0| QueueJob job = jobs.front(); 403| 0| jobs.pop_front(); 404| 0| return job; 405| 0| } 406| | 407| 0| bool empty() const override { 408| 0| return jobs.empty(); 409| 0| } 410| | 411| 0| uint64_t size() const override { 412| 0| return jobs.size(); 413| 0| } 414| |}; 415| | 416| 0|std::unique_ptr Scheduler::make(SchedulerAlgorithm alg) { 417| 0| switch (alg) { 418| 0| case SchedulerAlgorithm::NamePriority: 419| 0| return std::unique_ptr(new PriorityQueueScheduler); 420| 0| case SchedulerAlgorithm::FIFO: 421| 0| return std::unique_ptr(new FifoScheduler); 422| 0| default: 423| 0| assert(0 && "unknown scheduler algorithm"); 424| 0| return std::unique_ptr(nullptr); 425| 0| } 426| 0|} 427| | 428| |} // anonymous namespace 429| | 430| |#if !defined(_WIN32) 431| |extern "C" { 432| | extern char **environ; 433| |} 434| |#endif 435| | 436| |ExecutionQueue* llbuild::basic::createLaneBasedExecutionQueue( 437| | ExecutionQueueDelegate& delegate, int numLanes, SchedulerAlgorithm alg, 438| | const char* const* environment 439| 0|) { 440| 0| if (!environment) { 441| 0| environment = const_cast(environ); 442| 0| } 443| 0| return new LaneBasedExecutionQueue(delegate, numLanes, alg, environment); 444| 0|} 445| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/PlatformUtility.cpp: 1| |//===- Support/PlatformUtility.cpp - Platform Specific Utilities ----------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#include "llbuild/Basic/PlatformUtility.h" 11| |#include "llbuild/Basic/Stat.h" 12| |#include "llvm/ADT/SmallVector.h" 13| |#include "llvm/Support/ConvertUTF.h" 14| |#include "llvm/Support/Path.h" 15| | 16| |#if defined(_WIN32) 17| |#include "LeanWindows.h" 18| |#include 19| |#include 20| |#include 21| |#include 22| |#else 23| |#include 24| |#include 25| |#endif 26| |#include 27| | 28| |using namespace llbuild; 29| |using namespace llbuild::basic; 30| | 31| 0|bool sys::chdir(const char *fileName) { 32| |#if defined(_WIN32) 33| | llvm::SmallVector wFileName; 34| | llvm::convertUTF8ToUTF16String(fileName, wFileName); 35| | return SetCurrentDirectoryW((LPCWSTR)wFileName.data()); 36| |#else 37| | return ::chdir(fileName) == 0; 38| 0|#endif 39| 0|} 40| | 41| 0|int sys::close(int fileHandle) { 42| |#if defined(_WIN32) 43| | return ::_close(fileHandle); 44| |#else 45| | return ::close(fileHandle); 46| 0|#endif 47| 0|} 48| | 49| |#if defined(_WIN32) 50| |time_t filetimeToTime_t(FILETIME ft) { 51| | long long ltime = ft.dwLowDateTime | ((long long)ft.dwHighDateTime << 32); 52| | return (time_t)((ltime - 116444736000000000) / 10000000); 53| |} 54| |#endif 55| | 56| 0|int sys::lstat(const char *fileName, sys::StatStruct *buf) { 57| |#if defined(_WIN32) 58| | llvm::SmallVector wfilename; 59| | llvm::convertUTF8ToUTF16String(fileName, wfilename); 60| | HANDLE h = CreateFileW( 61| | /*lpFileName=*/(LPCWSTR)wfilename.data(), 62| | /*dwDesiredAccess=*/0, 63| | /*dwShareMode=*/FILE_SHARE_READ, 64| | /*lpSecurityAttributes=*/NULL, 65| | /*dwCreationDisposition=*/OPEN_EXISTING, 66| | /*dwFlagsAndAttributes=*/FILE_FLAG_OPEN_REPARSE_POINT | 67| | FILE_FLAG_BACKUP_SEMANTICS, 68| | /*hTemplateFile=*/NULL); 69| | if (h == INVALID_HANDLE_VALUE) { 70| | int err = GetLastError(); 71| | if (err == ERROR_FILE_NOT_FOUND) { 72| | errno = ENOENT; 73| | } 74| | return -1; 75| | } 76| | BY_HANDLE_FILE_INFORMATION info; 77| | GetFileInformationByHandle(h, &info); 78| | // Group id is always 0 on Windows 79| | buf->st_gid = 0; 80| | buf->st_atime = filetimeToTime_t(info.ftLastAccessTime); 81| | buf->st_ctime = filetimeToTime_t(info.ftCreationTime); 82| | buf->st_dev = info.dwVolumeSerialNumber; 83| | // inodes have meaning on FAT/HPFS/NTFS 84| | buf->st_ino = 0; 85| | buf->st_rdev = info.dwVolumeSerialNumber; 86| | buf->st_mode = 87| | // On a symlink to a directory, Windows sets both the REPARSE_POINT and 88| | // DIRECTORY attributes. Since Windows doesn't provide S_IFLNK and we 89| | // want unix style "symlinks to directories are not directories 90| | // themselves, we say symlinks are regular files 91| | (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) 92| | ? _S_IFREG 93| | : (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR 94| | : _S_IFREG; 95| | buf->st_mode |= (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) 96| | ? _S_IREAD 97| | : _S_IREAD | _S_IWRITE; 98| | llvm::StringRef extension = 99| | llvm::sys::path::extension(llvm::StringRef(fileName)); 100| | if (extension == ".exe" || extension == ".cmd" || extension == ".bat" || 101| | extension == ".com") { 102| | buf->st_mode |= _S_IEXEC; 103| | } 104| | buf->st_mtime = filetimeToTime_t(info.ftLastWriteTime); 105| | buf->st_nlink = info.nNumberOfLinks; 106| | buf->st_size = ((long long)info.nFileSizeHigh << 32) | info.nFileSizeLow; 107| | // Uid is always 0 on Windows systems 108| | buf->st_uid = 0; 109| | CloseHandle(h); 110| | return 0; 111| |#else 112| | return ::lstat(fileName, buf); 113| 0|#endif 114| 0|} 115| | 116| 0|bool sys::mkdir(const char* fileName) { 117| |#if defined(_WIN32) 118| | return _mkdir(fileName) == 0; 119| |#else 120| | return ::mkdir(fileName, S_IRWXU | S_IRWXG | S_IRWXO) == 0; 121| 0|#endif 122| 0|} 123| | 124| 0|int sys::pclose(FILE *stream) { 125| |#if defined(_WIN32) 126| | return ::_pclose(stream); 127| |#else 128| | return ::pclose(stream); 129| 0|#endif 130| 0|} 131| | 132| 0|int sys::pipe(int ptHandles[2]) { 133| |#if defined(_WIN32) 134| | return ::_pipe(ptHandles, 0, 0); 135| |#else 136| | return ::pipe(ptHandles); 137| 0|#endif 138| 0|} 139| | 140| 0|FILE *sys::popen(const char *command, const char *mode) { 141| |#if defined(_WIN32) 142| | return ::_popen(command, mode); 143| |#else 144| | return ::popen(command, mode); 145| 0|#endif 146| 0|} 147| | 148| |int sys::read(int fileHandle, void *destinationBuffer, 149| 0| unsigned int maxCharCount) { 150| |#if defined(_WIN32) 151| | return ::_read(fileHandle, destinationBuffer, maxCharCount); 152| |#else 153| | return ::read(fileHandle, destinationBuffer, maxCharCount); 154| 0|#endif 155| 0|} 156| | 157| 0|int sys::rmdir(const char *path) { 158| |#if defined(_WIN32) 159| | return ::_rmdir(path); 160| |#else 161| | return ::rmdir(path); 162| 0|#endif 163| 0|} 164| | 165| 0|int sys::stat(const char *fileName, StatStruct *buf) { 166| |#if defined(_WIN32) 167| | return ::_stat(fileName, buf); 168| |#else 169| | return ::stat(fileName, buf); 170| 0|#endif 171| 0|} 172| | 173| |// Create a symlink named linkPath which contains the string pointsTo 174| 0|int sys::symlink(const char *pointsTo, const char *linkPath) { 175| |#if defined(_WIN32) 176| | llvm::SmallVector wPointsTo; 177| | llvm::convertUTF8ToUTF16String(pointsTo, wPointsTo); 178| | llvm::SmallVector wLinkPath; 179| | llvm::convertUTF8ToUTF16String(linkPath, wLinkPath); 180| | DWORD attributes = GetFileAttributesW((LPCWSTR)wPointsTo.data()); 181| | DWORD directoryFlag = (attributes != INVALID_FILE_ATTRIBUTES && 182| | attributes & FILE_ATTRIBUTE_DIRECTORY) 183| | ? SYMBOLIC_LINK_FLAG_DIRECTORY 184| | : 0; 185| | // Note that CreateSymbolicLinkW takes its arguments in reverse order 186| | // compared to symlink/_symlink 187| | return !::CreateSymbolicLinkW( 188| | (LPCWSTR)wLinkPath.data(), (LPCWSTR)wPointsTo.data(), 189| | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | directoryFlag); 190| |#else 191| | return ::symlink(pointsTo, linkPath); 192| 0|#endif 193| 0|} 194| | 195| 0|int sys::unlink(const char *fileName) { 196| |#if defined(_WIN32) 197| | return ::_unlink(fileName); 198| |#else 199| | return ::unlink(fileName); 200| 0|#endif 201| 0|} 202| | 203| |int sys::write(int fileHandle, void *destinationBuffer, 204| 0| unsigned int maxCharCount) { 205| |#if defined(_WIN32) 206| | return ::_write(fileHandle, destinationBuffer, maxCharCount); 207| |#else 208| | return ::write(fileHandle, destinationBuffer, maxCharCount); 209| 0|#endif 210| 0|} 211| | 212| |// Raise the open file limit, returns 0 on success, -1 on failure 213| 0|int sys::raiseOpenFileLimit(llbuild_rlim_t limit) { 214| |#if defined(_WIN32) 215| | int curLimit = _getmaxstdio(); 216| | if (curLimit >= limit) { 217| | return 0; 218| | } 219| | // 2048 is the hard upper limit on Windows 220| | return _setmaxstdio(std::min(limit, 2048)) == -1 ? -1 : 0; 221| |#else 222| | int ret = 0; 223| 0| 224| 0| struct rlimit rl; 225| 0| ret = getrlimit(RLIMIT_NOFILE, &rl); 226| 0| if (ret != 0) { 227| 0| return ret; 228| 0| } 229| 0| 230| 0| if (rl.rlim_cur >= limit) { 231| 0| return 0; 232| 0| } 233| 0| 234| 0| rl.rlim_cur = std::min(limit, rl.rlim_max); 235| 0| 236| 0| return setrlimit(RLIMIT_NOFILE, &rl); 237| 0|#endif 238| 0|} 239| | 240| |sys::MATCH_RESULT sys::filenameMatch(const std::string& pattern, 241| 0| const std::string& filename) { 242| |#if defined(_WIN32) 243| | llvm::SmallVector wpattern; 244| | llvm::SmallVector wfilename; 245| | 246| | llvm::convertUTF8ToUTF16String(pattern, wpattern); 247| | llvm::convertUTF8ToUTF16String(filename, wfilename); 248| | 249| | bool result = 250| | PathMatchSpecW((LPCWSTR)wfilename.data(), (LPCWSTR)wpattern.data()); 251| | return result ? sys::MATCH : sys::NO_MATCH; 252| |#else 253| | int result = fnmatch(pattern.c_str(), filename.c_str(), 0); 254| 0| return result == 0 ? sys::MATCH 255| 0| : result == FNM_NOMATCH ? sys::NO_MATCH : sys::MATCH_ERROR; 256| 0|#endif 257| 0|} 258| | 259| 0|void sys::sleep(int seconds) { 260| |#if defined(_WIN32) 261| | // Uses milliseconds 262| | Sleep(seconds * 1000); 263| |#else 264| | ::sleep(seconds); 265| 0|#endif 266| 0|} 267| | 268| 0|std::string sys::strerror(int error) { 269| |#if defined(_WIN32) 270| | LPWSTR errBuff; 271| | int count = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | 272| | FORMAT_MESSAGE_ALLOCATE_BUFFER | 273| | FORMAT_MESSAGE_IGNORE_INSERTS, 274| | nullptr, error, 0, (LPWSTR)&errBuff, 0, nullptr); 275| | llvm::ArrayRef wRef(errBuff, errBuff + count); 276| | llvm::ArrayRef uRef(reinterpret_cast(wRef.begin()), 277| | reinterpret_cast(wRef.end())); 278| | std::string utf8Err; 279| | llvm::convertUTF16ToUTF8String(llvm::ArrayRef(uRef), utf8Err); 280| | LocalFree(errBuff); 281| | return utf8Err; 282| |#else 283| | return ::strerror(error); 284| 0|#endif 285| 0|} 286| | 287| 0|char *sys::strsep(char **stringp, const char *delim) { 288| |#if defined(_WIN32) 289| | // If *stringp is NULL, the strsep() function returns NULL and does nothing 290| | // else. 291| | if (*stringp == NULL) { 292| | return NULL; 293| | } 294| | char *begin = *stringp; 295| | char *end = *stringp; 296| | do { 297| | // Otherwise, this function finds the first token in the string *stringp, 298| | // that is delimited by one of the bytes in the string delim. 299| | for (int i = 0; delim[i] != '\0'; i++) { 300| | if (*end == delim[i]) { 301| | // This token is terminated by overwriting the delimiter with a null 302| | // byte ('\0'), and *stringp is updated to point past the token. 303| | *end = '\0'; 304| | *stringp = end + 1; 305| | return begin; 306| | } 307| | } 308| | } while (*(++end)); 309| | // In case no delimiter was found, the token is taken to be the entire string 310| | // *stringp, and *stringp is made NULL. 311| | *stringp = NULL; 312| | return begin; 313| |#else 314| | return ::strsep(stringp, delim); 315| 0|#endif 316| 0|} 317| | 318| 0|std::string sys::makeTmpDir() { 319| |#if defined(_WIN32) 320| | char path[MAX_PATH]; 321| | tmpnam_s(path, MAX_PATH); 322| | llvm::SmallVector wPath; 323| | llvm::convertUTF8ToUTF16String(path, wPath); 324| | CreateDirectoryW((LPCWSTR)wPath.data(), NULL); 325| | return std::string(path); 326| |#else 327| | char tmpDirPathBuf[] = "/tmp/fileXXXXXX"; 328| 0| return std::string(mkdtemp(tmpDirPathBuf)); 329| 0|#endif 330| 0|} 331| | 332| 0|std::string sys::getPathSeparators() { 333| |#if defined(_WIN32) 334| | return "/\\"; 335| |#else 336| | return "/"; 337| 0|#endif 338| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/SerialQueue.cpp: 1| |//===-- SerialQueue.cpp ---------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/SerialQueue.h" 14| | 15| |#include "llvm/ADT/STLExtras.h" 16| | 17| |#include 18| |#include 19| |#include 20| |#include 21| |#include 22| | 23| |using namespace llbuild; 24| |using namespace llbuild::basic; 25| | 26| |namespace { 27| | 28| |/// A basic serial queue. 29| |/// 30| |/// This implementation has been optimized for simplicity over performance. 31| |// 32| |// FIXME: Optimize. 33| |class SerialQueueImpl { 34| | /// The thread executing the operations. 35| | std::unique_ptr operationsThread; 36| | 37| | /// The queue of operations. 38| | std::deque> operations; 39| | 40| | /// The mutex protecting access to the queue. 41| | std::mutex operationsMutex; 42| | 43| | /// Condition variable used to signal when operations are available. 44| | std::condition_variable readyOperationsCondition; 45| | 46| | /// Thread function to execute operations. 47| 0| void run() { 48| 0| while (true) { 49| 0| // Get the next operation from the queue. 50| 0| std::function fn; 51| 0| { 52| 0| std::unique_lock lock(operationsMutex); 53| 0| 54| 0| // While the queue is empty, wait for an item. 55| 0| while (operations.empty()) { 56| 0| readyOperationsCondition.wait(lock); 57| 0| } 58| 0| 59| 0| fn = operations.front(); 60| 0| operations.pop_front(); 61| 0| } 62| 0| 63| 0| // If we got a nil function, the queue is shutting down. 64| 0| if (!fn) 65| 0| break; 66| 0| 67| 0| // Execute the operation. 68| 0| fn(); 69| 0| } 70| 0| } 71| | 72| 0| void addOperation(std::function&& fn) { 73| 0| std::lock_guard guard(operationsMutex); 74| 0| operations.push_back(fn); 75| 0| readyOperationsCondition.notify_one(); 76| 0| } 77| | 78| |public: 79| 0| SerialQueueImpl() { 80| 0| // Ensure the queue is fully initialized before creating the worker thread. 81| 0| operationsThread = llvm::make_unique( 82| 0| &SerialQueueImpl::run, this); 83| 0| } 84| | 85| 0| ~SerialQueueImpl() { 86| 0| // Signal the worker to shut down. 87| 0| addOperation({}); 88| 0| 89| 0| // Wait for the worker to complete. 90| 0| operationsThread->join(); 91| 0| } 92| | 93| 0| void sync(std::function fn) { 94| 0| assert(fn); 95| 0| 96| 0| // Add an operation which will execute the function and signal its 97| 0| // completion. 98| 0| std::condition_variable cv{}; 99| 0| std::mutex isCompleteMutex{}; 100| 0| bool isComplete = false; 101| 0| addOperation([&]() { 102| 0| fn(); 103| 0| { 104| 0| std::unique_lock lock(isCompleteMutex); 105| 0| isComplete = true; 106| 0| cv.notify_one(); 107| 0| } 108| 0| }); 109| 0| 110| 0| // Wait for the operation to complete. 111| 0| std::unique_lock lock(isCompleteMutex); 112| 0| while (!isComplete) { 113| 0| cv.wait(lock); 114| 0| } 115| 0| } 116| | 117| 0| void async(std::function fn) { 118| 0| assert(fn); 119| 0| 120| 0| // Add the operation. 121| 0| addOperation(std::move(fn)); 122| 0| } 123| |}; 124| | 125| |} 126| | 127| |SerialQueue::SerialQueue() 128| | : impl(new SerialQueueImpl()) 129| 0|{ 130| 0|} 131| | 132| 0|SerialQueue::~SerialQueue() { 133| 0| delete static_cast(impl); 134| 0|} 135| | 136| 0|void SerialQueue::sync(std::function fn) { 137| 0| static_cast(impl)->sync(fn); 138| 0|} 139| | 140| 0|void SerialQueue::async(std::function fn) { 141| 0| static_cast(impl)->async(fn); 142| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/ShellUtility.cpp: 1| |//===-- ShellUtility.cpp --------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/ShellUtility.h" 14| |#include "llvm/ADT/SmallString.h" 15| | 16| |namespace llbuild { 17| |namespace basic { 18| | 19| 0|void appendShellEscapedString(llvm::raw_ostream& os, StringRef string) { 20| 0| 21| 0| static const std::string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_/:@#%+=.,"; 22| 0| auto pos = string.find_first_not_of(whitelist); 23| 0| 24| 0| // We don't need any escaping just append the string and return. 25| 0| if (pos == std::string::npos) { 26| 0| os << string; 27| 0| return; 28| 0| } 29| 0| 30| 0| // We only need to escape the single quote, if it isn't present we can 31| 0| // escape using single quotes. 32| 0| auto singleQuotePos = string.find_first_of("'", pos); 33| 0| if (singleQuotePos == std::string::npos) { 34| 0| os << "'"; 35| 0| os << string; 36| 0| os << "'"; 37| 0| return; 38| 0| } 39| 0| 40| 0| // Otherwise iterate and escape all the single quotes. 41| 0| os << "'"; 42| 0| os << string.slice(0, singleQuotePos); 43| 0| for (auto idx = singleQuotePos; idx < string.size(); idx++) { 44| 0| if (string[idx] == '\'') { 45| 0| os << "'\\''"; 46| 0| } else { 47| 0| os << string[idx]; 48| 0| } 49| 0| } 50| 0| os << "'"; 51| 0|} 52| | 53| 0|std::string shellEscaped(StringRef string) { 54| 0| SmallString<16> out; 55| 0| llvm::raw_svector_ostream os(out); 56| 0| appendShellEscapedString(os, string); 57| 0| os.flush(); 58| 0| return out.str(); 59| 0|} 60| | 61| |} 62| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/Subprocess.cpp: 1| |//===-- Subprocess.cpp ----------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/Subprocess.h" 14| | 15| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 16| |#include "llbuild/Basic/PlatformUtility.h" 17| | 18| |#include "llvm/ADT/ArrayRef.h" 19| |#include "llvm/ADT/StringRef.h" 20| |#include "llvm/ADT/Twine.h" 21| |#include "llvm/Support/ConvertUTF.h" 22| |#include "llvm/Support/Path.h" 23| |#include "llvm/Support/Program.h" 24| | 25| |#include 26| |#include 27| | 28| |#include 29| |#if !defined(_WIN32) 30| |#include 31| |#endif 32| |#include 33| |#if defined(_WIN32) 34| |#include 35| |#include 36| |#include 37| |#else 38| |#include 39| |#include 40| |#include 41| |#include 42| |#endif 43| | 44| |#ifdef __APPLE__ 45| |#include 46| | 47| |extern "C" { 48| | // Provided by System.framework's libsystem_kernel interface 49| | extern int __pthread_chdir(const char *path); 50| | extern int __pthread_fchdir(int fd); 51| |} 52| | 53| |/// Set the thread specific working directory to the given path. 54| |int pthread_chdir_np(const char *path) 55| 0|{ 56| 0| return __pthread_chdir(path); 57| 0|} 58| | 59| |/// Set the thread specific working directory to that of the given file 60| |/// descriptor. Passing -1 clears the thread specific working directory, 61| |/// returning it to the process level working directory. 62| |int pthread_fchdir_np(int fd) 63| 0|{ 64| 0| return __pthread_fchdir(fd); 65| 0|} 66| | 67| |#endif 68| | 69| |#ifndef __GLIBC_PREREQ 70| |#define __GLIBC_PREREQ(maj, min) 0 71| |#endif 72| | 73| |#ifndef HAVE_POSIX_SPAWN_CHDIR 74| |#if defined(__sun) || \ 75| | __GLIBC_PREREQ(2, 29) 76| |#define HAVE_POSIX_SPAWN_CHDIR 1 77| |#else 78| |#define HAVE_POSIX_SPAWN_CHDIR 0 79| |#endif 80| |#endif 81| | 82| |#if !defined(_WIN32) 83| |static int posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t * __restrict file_actions, 84| 0| const char * __restrict path) { 85| |#if HAVE_POSIX_SPAWN_CHDIR 86| | return ::posix_spawn_file_actions_addchdir_np(file_actions, path); 87| |#else 88| | // Any other POSIX platform returns ENOSYS (Function not implemented), 89| 0| // to simplify the fallback logic around the call site. 90| 0| return ENOSYS; 91| 0|#endif 92| 0|} 93| |#endif 94| | 95| |using namespace llbuild; 96| |using namespace llbuild::basic; 97| | 98| |namespace { 99| | 100| | static std::atomic defaultQualityOfService{ 101| | QualityOfService::Normal }; 102| | 103| |#if defined(__APPLE__) 104| 0| qos_class_t _getDarwinQOSClass(QualityOfService level) { 105| 0| switch (getDefaultQualityOfService()) { 106| 0| case QualityOfService::Normal: 107| 0| return QOS_CLASS_DEFAULT; 108| 0| case QualityOfService::UserInitiated: 109| 0| return QOS_CLASS_USER_INITIATED; 110| 0| case QualityOfService::Utility: 111| 0| return QOS_CLASS_UTILITY; 112| 0| case QualityOfService::Background: 113| 0| return QOS_CLASS_BACKGROUND; 114| 0| default: 115| 0| assert(0 && "unknown command result"); 116| 0| return QOS_CLASS_DEFAULT; 117| 0| } 118| 0| } 119| | 120| |#endif 121| | 122| |} 123| | 124| 0|QualityOfService llbuild::basic::getDefaultQualityOfService() { 125| 0| return defaultQualityOfService; 126| 0|} 127| | 128| 0|void llbuild::basic::setDefaultQualityOfService(QualityOfService level) { 129| 0| defaultQualityOfService = level; 130| 0|} 131| | 132| 0|void llbuild::basic::setCurrentThreadQualityOfService(QualityOfService level) { 133| 0|#if defined(__APPLE__) 134| 0| pthread_set_qos_class_self_np( 135| 0| _getDarwinQOSClass(getDefaultQualityOfService()), 0); 136| 0|#endif 137| 0| 138| 0|} 139| | 140| 0|ProcessDelegate::~ProcessDelegate() { 141| 0|} 142| | 143| | 144| 0|ProcessGroup::~ProcessGroup() { 145| 0| // Wait for all processes in the process group to terminate 146| 0| std::unique_lock lock(mutex); 147| 0| while (!processes.empty()) { 148| 0| processesCondition.wait(lock); 149| 0| } 150| 0|} 151| | 152| 0|void ProcessGroup::signalAll(int signal) { 153| 0| std::lock_guard lock(mutex); 154| 0| 155| 0| for (const auto& it: processes) { 156| 0| // If we are interrupting, only interupt processes which are believed to 157| 0| // be safe to interrupt. 158| 0| if (signal == SIGINT && !it.second.canSafelyInterrupt) 159| 0| continue; 160| 0| 161| 0| // We are killing the whole process group here, this depends on us 162| 0| // spawning each process in its own group earlier. 163| |#if defined(_WIN32) 164| | TerminateProcess(it.first, signal); 165| |#else 166| 0| ::kill(-it.first, signal); 167| 0|#endif 168| 0| } 169| 0|} 170| | 171| | 172| |// Manage the state of a control protocol channel 173| |// 174| |// FIXME: This really should move out of subprocess and up a layer or two. The 175| |// process code should primarily handle reading file descriptors and pushing the 176| |// data up. For now, though, the goal is to move the code out of build system 177| |// and into a reusable layer. 178| |class ControlProtocolState { 179| | std::string controlID; 180| | 181| | bool negotiated = false; 182| | std::string partialMsg; 183| | bool releaseSeen = false; 184| | 185| | const size_t maxLength = 16; 186| | 187| |public: 188| 0| ControlProtocolState(const std::string& controlID) : controlID(controlID) {} 189| | 190| | /// Reads incoming control message buffer 191| | /// 192| | /// \return 0 on success, 1 on completion, -1 on error. 193| 0| int read(StringRef buf, std::string* errstr = nullptr) { 194| 0| while (buf.size()) { 195| 0| size_t nl = buf.find('\n'); 196| 0| if (nl == StringRef::npos) { 197| 0| if (partialMsg.size() + buf.size() > maxLength) { 198| 0| // protocol fault, msg length exceeded maximum 199| 0| partialMsg.clear(); 200| 0| if (errstr) { 201| 0| *errstr = "excessive message length"; 202| 0| } 203| 0| return -1; 204| 0| } 205| 0| 206| 0| // incomplete msg, store and continue 207| 0| partialMsg += buf.str(); 208| 0| return 0; 209| 0| } 210| 0| 211| 0| partialMsg += buf.slice(0, nl); 212| 0| 213| 0| if (!negotiated) { 214| 0| // negotiate protocol version 215| 0| if (partialMsg != "llbuild.1") { 216| 0| // incompatible protocol version 217| 0| if (errstr) { 218| 0| *errstr = "unsupported protocol: " + partialMsg; 219| 0| } 220| 0| partialMsg.clear(); 221| 0| return -1; 222| 0| } 223| 0| negotiated = true; 224| 0| } else { 225| 0| // check for supported control message 226| 0| if (partialMsg == controlID) { 227| 0| releaseSeen = true; 228| 0| } 229| 0| 230| 0| // We halt receiving anything after the first control message 231| 0| if (errstr) { 232| 0| *errstr = "bad ID"; 233| 0| } 234| 0| partialMsg.clear(); 235| 0| return 1; 236| 0| } 237| 0| 238| 0| partialMsg.clear(); 239| 0| buf = buf.drop_front(nl + 1); 240| 0| } 241| 0| return 0; 242| 0| } 243| | 244| 0| bool shouldRelease() const { return releaseSeen; } 245| |}; 246| | 247| |// Helper function to collect subprocess output 248| |static void captureExecutedProcessOutput(ProcessDelegate& delegate, 249| | FD outputPipe, ProcessHandle handle, 250| 0| ProcessContext* ctx) { 251| 0| while (true) { 252| 0| char buf[4096]; 253| 0| ssize_t numBytes = 254| 0| sys::FileDescriptorTraits<>::Read(outputPipe, buf, sizeof(buf)); 255| 0| if (numBytes < 0) { 256| 0| int err = errno; 257| 0| delegate.processHadError(ctx, handle, 258| 0| Twine("unable to read process output (") + 259| 0| sys::strerror(err) + ")"); 260| 0| break; 261| 0| } 262| 0| 263| 0| if (numBytes == 0) 264| 0| break; 265| 0| 266| 0| // Notify the client of the output. 267| 0| delegate.processHadOutput(ctx, handle, StringRef(buf, numBytes)); 268| 0| } 269| 0| // We have receieved the zero byte read that indicates an EOF. Go ahead and 270| 0| // close the pipe. 271| 0| sys::FileDescriptorTraits<>::Close(outputPipe); 272| 0|} 273| | 274| |// Helper function for cleaning up after a process has finished in 275| |// executeProcess 276| |static void cleanUpExecutedProcess(ProcessDelegate& delegate, 277| | ProcessGroup& pgrp, llbuild_pid_t pid, 278| | ProcessHandle handle, ProcessContext* ctx, 279| | ProcessCompletionFn&& completionFn, 280| 0| FD releaseFd) { 281| |#if defined(_WIN32) 282| | FILETIME creationTime; 283| | FILETIME exitTime; 284| | FILETIME utimeTicks; 285| | FILETIME stimeTicks; 286| | int waitResult = WaitForSingleObject(pid, INFINITE); 287| | int err = GetLastError(); 288| | DWORD exitCode = 0; 289| | GetExitCodeProcess(pid, &exitCode); 290| | 291| | if (waitResult == WAIT_FAILED || waitResult == WAIT_ABANDONED) { 292| | auto result = ProcessResult::makeFailed(exitCode); 293| | delegate.processHadError(ctx, handle, 294| | Twine("unable to wait for process (") + 295| | sys::strerror(GetLastError()) + ")"); 296| | delegate.processFinished(ctx, handle, result); 297| | completionFn(result); 298| | return; 299| | } 300| |#else 301| | // Wait for the command to complete. 302| 0| struct rusage usage; 303| 0| int exitCode, result = wait4(pid, &exitCode, 0, &usage); 304| 0| while (result == -1 && errno == EINTR) 305| 0| result = wait4(pid, &exitCode, 0, &usage); 306| 0|#endif 307| 0| // Close the release pipe 308| 0| // 309| 0| // Note: We purposely hold this open until after the process has finished as 310| 0| // it simplifies client implentation. If we close it early, clients need to be 311| 0| // aware of and potentially handle a SIGPIPE. 312| 0| if (releaseFd >= 0) { 313| 0| sys::FileDescriptorTraits<>::Close(releaseFd); 314| 0| } 315| 0| 316| 0| // Update the set of spawned processes. 317| 0| pgrp.remove(pid); 318| |#if defined(_WIN32) 319| | PROCESS_MEMORY_COUNTERS counters; 320| | bool res = 321| | GetProcessTimes(pid, &creationTime, &exitTime, &stimeTicks, &utimeTicks); 322| | if (!res) { 323| | auto result = ProcessResult::makeCancelled(); 324| | delegate.processHadError(ctx, handle, 325| | Twine("unable to get statistics for process: ") + 326| | sys::strerror(GetLastError()) + ")"); 327| | delegate.processFinished(ctx, handle, result); 328| | return; 329| | } 330| | // Each tick is 100ns 331| | uint64_t utime = 332| | ((uint64_t)utimeTicks.dwHighDateTime << 32 | utimeTicks.dwLowDateTime) / 333| | 10; 334| | uint64_t stime = 335| | ((uint64_t)stimeTicks.dwHighDateTime << 32 | stimeTicks.dwLowDateTime) / 336| | 10; 337| | GetProcessMemoryInfo(pid, &counters, sizeof(counters)); 338| | 339| | // We report additional info in the tracing interval 340| | // - user time, in µs 341| | // - sys time, in µs 342| | // - memory usage, in bytes 343| | 344| | // FIXME: We should report a statistic for how much output we read from the 345| | // subprocess (probably as a new point sample). 346| | 347| | // Notify of the process completion. 348| | ProcessStatus processStatus = 349| | (exitCode == 0) ? ProcessStatus::Succeeded : ProcessStatus::Failed; 350| | ProcessResult processResult(processStatus, exitCode, pid, utime, stime, 351| | counters.PeakWorkingSetSize); 352| |#else // !defined(_WIN32) 353| 0| if (result == -1) { 354| 0| auto result = ProcessResult::makeFailed(exitCode); 355| 0| delegate.processHadError(ctx, handle, 356| 0| Twine("unable to wait for process (") + 357| 0| strerror(errno) + ")"); 358| 0| delegate.processFinished(ctx, handle, result); 359| 0| completionFn(result); 360| 0| return; 361| 0| } 362| 0| 363| 0| // We report additional info in the tracing interval 364| 0| // - user time, in µs 365| 0| // - sys time, in µs 366| 0| // - memory usage, in bytes 367| 0| uint64_t utime = (uint64_t(usage.ru_utime.tv_sec) * 1000000 + 368| 0| uint64_t(usage.ru_utime.tv_usec)); 369| 0| uint64_t stime = (uint64_t(usage.ru_stime.tv_sec) * 1000000 + 370| 0| uint64_t(usage.ru_stime.tv_usec)); 371| 0| 372| 0| // FIXME: We should report a statistic for how much output we read from the 373| 0| // subprocess (probably as a new point sample). 374| 0| 375| 0| // Notify of the process completion. 376| 0| bool cancelled = WIFSIGNALED(exitCode) && (WTERMSIG(exitCode) == SIGINT || WTERMSIG(exitCode) == SIGKILL); 377| 0| ProcessStatus processStatus = cancelled ? ProcessStatus::Cancelled : (exitCode == 0) ? ProcessStatus::Succeeded : ProcessStatus::Failed; 378| 0| ProcessResult processResult(processStatus, exitCode, pid, utime, stime, 379| 0| usage.ru_maxrss); 380| 0|#endif // else !defined(_WIN32) 381| 0| delegate.processFinished(ctx, handle, processResult); 382| 0| completionFn(processResult); 383| 0|} 384| | 385| |void llbuild::basic::spawnProcess( 386| | ProcessDelegate& delegate, 387| | ProcessContext* ctx, 388| | ProcessGroup& pgrp, 389| | ProcessHandle handle, 390| | ArrayRef commandLine, 391| | POSIXEnvironment environment, 392| | ProcessAttributes attr, 393| | ProcessReleaseFn&& releaseFn, 394| | ProcessCompletionFn&& completionFn 395| 0|) { 396| 0| // Whether or not we are capturing output. 397| 0| const bool shouldCaptureOutput = true; 398| 0| 399| 0| delegate.processStarted(ctx, handle); 400| 0| 401| 0| if (commandLine.size() == 0) { 402| 0| auto result = ProcessResult::makeFailed(); 403| 0| delegate.processHadError(ctx, handle, Twine("no arguments for command")); 404| 0| delegate.processFinished(ctx, handle, result); 405| 0| completionFn(result); 406| 0| return; 407| 0| } 408| 0| 409| 0| // Form the complete C string command line. 410| 0| std::vector argsStorage(commandLine.begin(), commandLine.end()); 411| |#if defined(_WIN32) 412| | std::string args; 413| | // TODO: WARNING fix Windows command line escaping. This doesn't work at all 414| | // if the arguments contain spaces. This should instead use std::string 415| | // flattenWindowsCommandLine(ArrayRef Args) from llvm once that 416| | // gets pulled in. 417| | std::for_each(std::begin(argsStorage) + 1, std::end(argsStorage), 418| | [&args](auto arg) { args += arg + " "; }); 419| | if (!args.empty()) { 420| | args.pop_back(); 421| | } 422| | // Convert the command line string to utf16 423| | llvm::SmallVector u16Executable; 424| | llvm::SmallVector u16CmdLine; 425| | llvm::convertUTF8ToUTF16String(argsStorage[0], u16Executable); 426| | llvm::convertUTF8ToUTF16String(args, u16CmdLine); 427| |#else 428| | std::vector args(argsStorage.size() + 1); 429| 0| for (size_t i = 0; i != argsStorage.size(); ++i) { 430| 0| args[i] = argsStorage[i].c_str(); 431| 0| } 432| 0| args[argsStorage.size()] = nullptr; 433| 0|#endif 434| 0| 435| |#if defined(_WIN32) 436| | DWORD creationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP; 437| | PROCESS_INFORMATION processInfo = {0}; 438| | STARTUPINFOW startupInfo = {0}; 439| | 440| | startupInfo.dwFlags = STARTF_USESTDHANDLES; 441| | // Set NUL as stdin 442| | HANDLE nul = 443| | CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 444| | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 445| | startupInfo.hStdInput = nul; 446| |#else 447| | // Initialize the spawn attributes. 448| 0| posix_spawnattr_t attributes; 449| 0| posix_spawnattr_init(&attributes); 450| 0| 451| 0| // Unmask all signals. 452| 0| sigset_t noSignals; 453| 0| sigemptyset(&noSignals); 454| 0| posix_spawnattr_setsigmask(&attributes, &noSignals); 455| 0| 456| 0| // Reset all signals to default behavior. 457| 0| // 458| 0| // On Linux, this can only be used to reset signals that are legal to 459| 0| // modify, so we have to take care about the set we use. 460| |#if defined(__linux__) 461| | sigset_t mostSignals; 462| | sigemptyset(&mostSignals); 463| | for (int i = 1; i < SIGSYS; ++i) { 464| | if (i == SIGKILL || i == SIGSTOP) continue; 465| | sigaddset(&mostSignals, i); 466| | } 467| | posix_spawnattr_setsigdefault(&attributes, &mostSignals); 468| |#else 469| | sigset_t mostSignals; 470| 0| sigfillset(&mostSignals); 471| 0| sigdelset(&mostSignals, SIGKILL); 472| 0| sigdelset(&mostSignals, SIGSTOP); 473| 0| posix_spawnattr_setsigdefault(&attributes, &mostSignals); 474| 0|#endif // else !defined(_WIN32) 475| 0| 476| 0| // Establish a separate process group. 477| 0| posix_spawnattr_setpgroup(&attributes, 0); 478| 0| 479| 0| // Set the attribute flags. 480| 0| unsigned flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; 481| 0| flags |= POSIX_SPAWN_SETPGROUP; 482| 0| 483| 0| // Close all other files by default. 484| 0| // 485| 0| // FIXME: Note that this is an Apple-specific extension, and we will have to 486| 0| // do something else on other platforms (and unfortunately, there isn't 487| 0| // really an easy answer other than using a stub executable). 488| 0|#ifdef __APPLE__ 489| 0| flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; 490| 0|#endif 491| 0| 492| 0| // On Darwin, set the QOS of launched processes to the global default. 493| 0|#ifdef __APPLE__ 494| 0| posix_spawnattr_set_qos_class_np( 495| 0| &attributes, _getDarwinQOSClass(defaultQualityOfService)); 496| 0|#endif 497| 0| 498| 0| posix_spawnattr_setflags(&attributes, flags); 499| 0| 500| 0| // Setup the file actions. 501| 0| posix_spawn_file_actions_t fileActions; 502| 0| posix_spawn_file_actions_init(&fileActions); 503| 0| 504| 0| bool usePosixSpawnChdirFallback = true; 505| 0| const auto workingDir = attr.workingDir.str(); 506| 0| if (!workingDir.empty() && 507| 0| posix_spawn_file_actions_addchdir(&fileActions, workingDir.c_str()) != ENOSYS) { 508| 0| usePosixSpawnChdirFallback = false; 509| 0| } 510| 0| 511| 0| // Open /dev/null as stdin. 512| 0| posix_spawn_file_actions_addopen( 513| 0| &fileActions, 0, "/dev/null", O_RDONLY, 0); 514| 0|#endif 515| 0| 516| |#if defined(_WIN32) 517| | llvm::SmallVector u16Cwd; 518| | std::string workingDir = attr.workingDir.str(); 519| | if (!workingDir.empty()) { 520| | llvm::convertUTF8ToUTF16String(workingDir, u16Cwd); 521| | } 522| | 523| | HANDLE controlPipe[2]{NULL, NULL}; 524| | HANDLE* controlReadPipe = controlPipe; 525| | HANDLE* controlWritePipe = controlPipe + 1; 526| | if (attr.controlEnabled) { 527| | SECURITY_ATTRIBUTES secAttrs{sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; 528| | CreatePipe(controlReadPipe, controlWritePipe, &secAttrs, 0); 529| | SetHandleInformation(controlReadPipe, HANDLE_FLAG_INHERIT, TRUE); 530| | SetHandleInformation(controlWritePipe, HANDLE_FLAG_INHERIT, FALSE); 531| | } 532| | 533| | HANDLE outputPipe[2]{NULL, NULL}; 534| | if (shouldCaptureOutput) { 535| | SECURITY_ATTRIBUTES secAttrs{sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; 536| | CreatePipe(outputPipe, outputPipe + 1, &secAttrs, 0); 537| | SetHandleInformation(outputPipe[0], HANDLE_FLAG_INHERIT, FALSE); 538| | 539| | startupInfo.hStdOutput = outputPipe[1]; 540| | startupInfo.hStdError = outputPipe[1]; 541| | } else { 542| | // Otherwise, propagate the current stdout/stderr. 543| | startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 544| | startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); 545| | } 546| |#else 547| | // Create a pipe for the process to (potentially) release the lane while 548| 0| // still running. 549| 0| int controlPipe[2]{ -1, -1 }; 550| 0| if (attr.controlEnabled) { 551| 0| if (basic::sys::pipe(controlPipe) < 0) { 552| 0| delegate.processHadError(ctx, handle, 553| 0| Twine("unable to open control pipe (") + strerror(errno) + ")"); 554| 0| delegate.processFinished(ctx, handle, ProcessResult::makeFailed()); 555| 0| completionFn(ProcessStatus::Failed); 556| 0| return; 557| 0| } 558| 0|#ifdef __APPLE__ 559| 0| posix_spawn_file_actions_addinherit_np(&fileActions, controlPipe[1]); 560| |#else 561| | posix_spawn_file_actions_adddup2(&fileActions, controlPipe[1], controlPipe[1]); 562| |#endif 563| | posix_spawn_file_actions_addclose(&fileActions, controlPipe[0]); 564| 0| } 565| 0| 566| 0| // If we are capturing output, create a pipe and appropriate spawn actions. 567| 0| int outputPipe[2]{ -1, -1 }; 568| 0| if (shouldCaptureOutput) { 569| 0| if (basic::sys::pipe(outputPipe) < 0) { 570| 0| auto result = ProcessResult::makeFailed(); 571| 0| delegate.processHadError(ctx, handle, 572| 0| Twine("unable to open output pipe (") + strerror(errno) + ")"); 573| 0| delegate.processFinished(ctx, handle, result); 574| 0| completionFn(result); 575| 0| return; 576| 0| } 577| 0| 578| 0| // Open the write end of the pipe as stdout and stderr. 579| 0| posix_spawn_file_actions_adddup2(&fileActions, outputPipe[1], 1); 580| 0| posix_spawn_file_actions_adddup2(&fileActions, outputPipe[1], 2); 581| 0| 582| 0| // Close the read and write ends of the pipe. 583| 0| posix_spawn_file_actions_addclose(&fileActions, outputPipe[0]); 584| 0| posix_spawn_file_actions_addclose(&fileActions, outputPipe[1]); 585| 0| } else { 586| 0| // Otherwise, propagate the current stdout/stderr. 587| 0| posix_spawn_file_actions_adddup2(&fileActions, 1, 1); 588| 0| posix_spawn_file_actions_adddup2(&fileActions, 2, 2); 589| 0| } 590| 0|#endif 591| 0| 592| 0| // Export a task ID to subprocesses. 593| 0| auto taskID = Twine::utohexstr(handle.id); 594| 0| environment.setIfMissing("LLBUILD_TASK_ID", taskID.str()); 595| 0| if (attr.controlEnabled) { 596| 0| environment.setIfMissing("LLBUILD_CONTROL_FD", 597| 0| Twine((int)controlPipe[1]).str()); 598| 0| } 599| 0| 600| 0| // Resolve the executable path, if necessary. 601| 0| // 602| 0| // FIXME: This should be cached. 603| 0| if (!llvm::sys::path::is_absolute(argsStorage[0])) { 604| 0| auto res = llvm::sys::findProgramByName(argsStorage[0]); 605| 0| if (!res.getError()) { 606| 0| argsStorage[0] = *res; 607| |#if defined(_WIN32) 608| | u16Executable.clear(); 609| | llvm::convertUTF8ToUTF16String(argsStorage[0], u16Executable); 610| |#else 611| | args[0] = argsStorage[0].c_str(); 612| 0|#endif 613| 0| } 614| 0| } 615| 0| 616| 0| // Spawn the command. 617| 0| llbuild_pid_t pid = (llbuild_pid_t)-1; 618| 0| bool wasCancelled; 619| 0| { 620| 0| // We need to hold the spawn processes lock when we spawn, to ensure that 621| 0| // we don't create a process in between when we are cancelled. 622| 0| std::lock_guard guard(pgrp.mutex); 623| 0| wasCancelled = pgrp.isClosed(); 624| 0| 625| 0| // If we have been cancelled since we started, do nothing. 626| 0| if (!wasCancelled) { 627| 0| int result = 0; 628| 0| 629| 0| bool workingDirectoryUnsupported = false; 630| 0| 631| 0|#if !defined(_WIN32) 632| 0| if (usePosixSpawnChdirFallback) { 633| 0|#ifdef __APPLE__ 634| 0| thread_local std::string threadWorkingDir; 635| 0| 636| 0| if (workingDir.empty()) { 637| 0| if (!threadWorkingDir.empty()) { 638| 0| pthread_fchdir_np(-1); 639| 0| threadWorkingDir.clear(); 640| 0| } 641| 0| } else { 642| 0| if (threadWorkingDir != workingDir) { 643| 0| if (pthread_chdir_np(workingDir.c_str()) == -1) { 644| 0| result = errno; 645| 0| } else { 646| 0| threadWorkingDir = workingDir; 647| 0| } 648| 0| } 649| 0| } 650| |#else 651| | if (!workingDir.empty()) { 652| | workingDirectoryUnsupported = true; 653| | result = -1; 654| | } 655| |#endif // ifdef __APPLE__ 656| | } 657| 0|#endif // else !defined(_WIN32) 658| 0| 659| 0| if (result == 0) { 660| |#if defined(_WIN32) 661| | result = !CreateProcessW( 662| | /*lpApplicationName=*/(LPWSTR)u16Executable.data(), 663| | (LPWSTR)u16CmdLine.data(), 664| | /*lpProcessAttributes=*/NULL, 665| | /*lpThreadAttributes=*/NULL, 666| | /*bInheritHandles=*/TRUE, creationFlags, 667| | /*lpEnvironment=*/NULL, 668| | /*lpCurrentDirectory=*/u16Cwd.empty() ? NULL 669| | : (LPWSTR)u16Cwd.data(), 670| | &startupInfo, &processInfo); 671| |#else 672| | result = 673| 0| posix_spawn(&pid, args[0], /*file_actions=*/&fileActions, 674| 0| /*attrp=*/&attributes, const_cast(args.data()), 675| 0| const_cast(environment.getEnvp())); 676| 0|#endif 677| 0| } 678| 0| 679| 0| if (result != 0) { 680| 0| auto processResult = ProcessResult::makeFailed(); 681| |#if defined(_WIN32) 682| | result = GetLastError(); 683| |#endif 684| | delegate.processHadError( 685| 0| ctx, handle, 686| 0| workingDirectoryUnsupported 687| 0| ? Twine("working-directory unsupported on this platform") 688| 0| : Twine("unable to spawn process (") + sys::strerror(result) + 689| 0| ")"); 690| 0| delegate.processFinished(ctx, handle, processResult); 691| 0| pid = (llbuild_pid_t)-1; 692| 0| } else { 693| |#if defined(_WIN32) 694| | pid = processInfo.hProcess; 695| |#endif 696| | ProcessInfo info{ attr.canSafelyInterrupt }; 697| 0| pgrp.add(std::move(guard), pid, info); 698| 0| } 699| 0| } 700| 0| } 701| 0| 702| 0|#if !defined(_WIN32) 703| 0| posix_spawn_file_actions_destroy(&fileActions); 704| 0| posix_spawnattr_destroy(&attributes); 705| 0|#endif 706| 0| // Close the write end of the release pipe 707| 0| if (attr.controlEnabled) { 708| 0| sys::FileDescriptorTraits<>::Close(controlPipe[1]); 709| 0| } 710| 0| 711| 0| // If we failed to launch a process, clean up and abort. 712| 0| if (pid == (llbuild_pid_t)-1) { 713| 0| if (attr.controlEnabled) { 714| 0| sys::FileDescriptorTraits<>::Close(controlPipe[0]); 715| 0| } 716| 0| 717| 0| if (shouldCaptureOutput) { 718| 0| sys::FileDescriptorTraits<>::Close(outputPipe[1]); 719| 0| sys::FileDescriptorTraits<>::Close(outputPipe[0]); 720| 0| } 721| 0| auto result = wasCancelled ? ProcessResult::makeCancelled() : ProcessResult::makeFailed(); 722| 0| completionFn(result); 723| 0| return; 724| 0| } 725| 0| 726| 0|#if !defined(_WIN32) 727| 0| // Set up our select() structures 728| 0| pollfd readfds[] = { 729| 0| { controlPipe[0], 0, 0 }, 730| 0| { outputPipe[0], 0, 0 } 731| 0| }; 732| 0| int activeEvents = 0; 733| 0|#endif 734| 0| const int nfds = 2; 735| 0| ControlProtocolState control(taskID.str()); 736| 0| std::function readCbs[] = { 737| 0| // control callback handle 738| 0| [&delegate, &control, ctx, handle](StringRef buf) mutable -> bool { 739| 0| std::string errstr; 740| 0| int ret = control.read(buf, &errstr); 741| 0| if (ret < 0) { 742| 0| delegate.processHadError(ctx, handle, 743| 0| Twine("control protocol error" + errstr)); 744| 0| } 745| 0| return (ret == 0); 746| 0| }, 747| 0| // output capture callback 748| 0| [&delegate, ctx, handle](StringRef buf) -> bool { 749| 0| // Notify the client of the output. 750| 0| delegate.processHadOutput(ctx, handle, buf); 751| 0| return true; 752| 0| } 753| 0| }; 754| |#if defined(_WIN32) 755| | struct threadData { 756| | std::function reader; 757| | HANDLE handle; 758| | std::function cb; 759| | }; 760| | HANDLE readers[2] = {NULL, NULL}; 761| | auto reader = [&](void* lpArgs) { 762| | threadData* args = (threadData*)lpArgs; 763| | for (;;) { 764| | char buf[4096]; 765| | DWORD numBytes; 766| | bool result = ReadFile(args->handle, buf, sizeof(buf), &numBytes, NULL); 767| | 768| | if (!result || numBytes == 0) { 769| | if (GetLastError() == ERROR_BROKEN_PIPE) { 770| | // Pipe done, exit 771| | return; 772| | } else { 773| | delegate.processHadError(ctx, handle, 774| | Twine("unable to read process output (") + 775| | sys::strerror(GetLastError()) + ")"); 776| | } 777| | } 778| | 779| | if (numBytes <= 0 || !args->cb(StringRef(buf, numBytes))) { 780| | continue; 781| | } 782| | 783| | if (control.shouldRelease()) { 784| | releaseFn([&delegate, &pgrp, pid, handle, ctx, shouldCaptureOutput, 785| | outputFd = outputPipe[0], controlFd = controlPipe[0], 786| | completionFn = std::move(completionFn)]() mutable { 787| | if (shouldCaptureOutput) 788| | captureExecutedProcessOutput(delegate, outputFd, handle, ctx); 789| | 790| | cleanUpExecutedProcess(delegate, pgrp, pid, handle, ctx, 791| | std::move(completionFn), controlFd); 792| | }); 793| | return; 794| | } 795| | } 796| | }; 797| | struct threadData controlThreadParams = {reader, controlPipe[0], readCbs[0]}; 798| | struct threadData outputThreadParams = {reader, outputPipe[0], readCbs[1]}; 799| | HANDLE threads[2] = {NULL, NULL}; 800| |#endif // defined(_WIN32) 801| | 802| 0| if (attr.controlEnabled) { 803| |#if defined(_WIN32) 804| | threads[0] = (HANDLE)_beginthread( 805| | [](LPVOID lpParams) { ((threadData*)lpParams)->reader(lpParams); }, 0, 806| | &controlThreadParams); 807| |#else 808| | readfds[0].events = POLLIN; 809| 0| activeEvents |= POLLIN; 810| 0|#endif 811| 0| } 812| 0| 813| 0| // Read the command output, if capturing. 814| 0| if (shouldCaptureOutput) { 815| |#if defined(_WIN32) 816| | threads[1] = (HANDLE)_beginthread( 817| | [](LPVOID lpParams) { ((threadData*)lpParams)->reader(lpParams); }, 0, 818| | &outputThreadParams); 819| |#else 820| | readfds[1].events = POLLIN; 821| 0| activeEvents |= POLLIN; 822| 0|#endif 823| 0| 824| 0| // Close the write end of the output pipe. 825| 0| sys::FileDescriptorTraits<>::Close(outputPipe[1]); 826| 0| } 827| 0| 828| |#if defined(_WIN32) 829| | DWORD waitResult = WaitForMultipleObjects(2, threads, 830| | /*bWaitAll=*/false, 831| | /*dwMilliseconds=*/INFINITE); 832| | if (WAIT_FAILED == waitResult || WAIT_TIMEOUT == waitResult) { 833| | int err = GetLastError(); 834| | delegate.processHadError( 835| | ctx, handle, Twine("failed to poll (") + sys::strerror(err) + ")"); 836| | } 837| |#else // !defined(_WIN32) 838| 0| while (activeEvents) { 839| 0| char buf[4096]; 840| 0| activeEvents = 0; 841| 0| 842| 0| if (poll(readfds, nfds, -1) == -1) { 843| 0| int err = errno; 844| 0| delegate.processHadError(ctx, handle, 845| 0| Twine("failed to poll (") + strerror(err) + ")"); 846| 0| break; 847| 0| } 848| 0| 849| 0| 850| 0| for (int i = 0; i < nfds; i++) { 851| 0| if (readfds[i].revents & (POLLIN | POLLERR | POLLHUP)) { 852| 0| ssize_t numBytes = read(readfds[i].fd, buf, sizeof(buf)); 853| 0| if (numBytes < 0) { 854| 0| int err = errno; 855| 0| delegate.processHadError(ctx, handle, 856| 0| Twine("unable to read process output (") + strerror(err) + ")"); 857| 0| } 858| 0| if (numBytes <= 0 || !readCbs[i](StringRef(buf, numBytes))) { 859| 0| readfds[i].events = 0; 860| 0| continue; 861| 0| } 862| 0| } 863| 0| activeEvents |= readfds[i].events; 864| 0| } 865| 0| 866| 0| if (control.shouldRelease()) { 867| 0| releaseFn([ 868| 0| &delegate, &pgrp, pid, handle, ctx, 869| 0| outputFd=outputPipe[0], 870| 0| controlFd=controlPipe[0], 871| 0| completionFn=std::move(completionFn) 872| 0| ]() mutable { 873| 0| if (shouldCaptureOutput) 874| 0| captureExecutedProcessOutput(delegate, outputFd, handle, ctx); 875| 0| 876| 0| cleanUpExecutedProcess(delegate, pgrp, pid, handle, ctx, 877| 0| std::move(completionFn), controlFd); 878| 0| }); 879| 0| return; 880| 0| } 881| 0| } 882| 0|#endif // else !defined(_WIN32) 883| 0| if (shouldCaptureOutput) { 884| 0| // If we have reached here, both the control and read pipes have given us 885| 0| // the requisite EOF/hang-up events. Safe to close the read end of the 886| 0| // output pipe. 887| 0| sys::FileDescriptorTraits<>::Close(outputPipe[0]); 888| 0| } 889| 0| cleanUpExecutedProcess(delegate, pgrp, pid, handle, ctx, 890| 0| std::move(completionFn), controlPipe[0]); 891| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/Version.cpp: 1| |//===-- Version.cpp -------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Basic/Version.h" 14| | 15| |#include 16| | 17| |namespace llbuild { 18| | 19| 0|std::string getLLBuildFullVersion(StringRef productName) { 20| 0| std::string result = productName.str() + " version 3.0"; 21| 0| 22| 0| // Include the additional build version information, if present. 23| |#ifdef LLBUILD_VENDOR_STRING 24| | result = std::string(LLBUILD_VENDOR_STRING) + " " + result; 25| |#endif 26| |#ifdef LLBUILD_VERSION_STRING 27| | result = result + " (" + std::string(LLBUILD_VERSION_STRING) + ")"; 28| |#endif 29| | 30| 0| return result; 31| 0|} 32| | 33| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/BinaryCoding.h: 1| |//===- BinaryCoding.h -------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_BINARYCODING_H 14| |#define LLBUILD_BASIC_BINARYCODING_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/SmallVector.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |#include 23| |#include 24| | 25| |namespace llbuild { 26| |namespace basic { 27| | 28| |template 29| |struct BinaryCodingTraits { 30| | // static inline void encode(const T&, BinaryEncoder&); 31| | // static inline void decode(T&, BinaryDecoder&); 32| |}; 33| | 34| |/// A basic binary encoding utility. 35| |/// 36| |/// This encoder is design for small, relatively efficient, in-memory coding of 37| |/// objects. It is endian-neutral, and should be paired with \see BinaryDecoder 38| |/// for decoding. The specific encoding is not intended to be stable. 39| |/// 40| |/// The utility supports coding of user-defined types via specialization of the 41| |/// BinaryCodeableTraits type. 42| |class BinaryEncoder { 43| |private: 44| | // Copying is disabled. 45| | BinaryEncoder(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 46| | void operator=(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 47| | 48| | /// The encoded data. 49| | // 50| | // FIXME: Parameterize this size? 51| | llvm::SmallVector encdata; 52| | 53| |public: 54| | /// Construct a new binary encoder. 55| 0| BinaryEncoder() {} 56| | 57| | /// Encode a value to the stream. 58| 0| void write(bool value) { 59| 0| encdata.push_back(uint8_t(value)); 60| 0| } 61| | 62| | /// Encode a value to the stream. 63| 0| void write(uint8_t value) { 64| 0| encdata.push_back(value); 65| 0| } 66| | 67| | /// Encode a value to the stream. 68| 0| void write(uint16_t value) { 69| 0| write(uint8_t(value >> 0)); 70| 0| write(uint8_t(value >> 8)); 71| 0| } 72| | 73| | /// Encode a value to the stream. 74| 0| void write(uint32_t value) { 75| 0| write(uint16_t(value >> 0)); 76| 0| write(uint16_t(value >> 16)); 77| 0| } 78| | 79| | /// Encode a value to the stream. 80| 0| void write(uint64_t value) { 81| 0| write(uint32_t(value >> 0)); 82| 0| write(uint32_t(value >> 32)); 83| 0| } 84| | 85| | /// Encode a value to the stream. 86| | /// 87| | /// We do not support encoding values larger than 4GB. 88| 0| void write(const std::string& value) { 89| 0| uint32_t size = uint32_t(value.size()); 90| 0| assert(size == value.size()); 91| 0| write(size); 92| 0| writeBytes(StringRef(value)); 93| 0| } 94| | 95| | /// Encode a sequence of bytes to the stream. 96| 0| void writeBytes(StringRef bytes) { 97| 0| encdata.insert(encdata.end(), bytes.begin(), bytes.end()); 98| 0| } 99| | 100| | /// Encode a value to the stream. 101| | template 102| 0| void write(const T& value) { 103| 0| BinaryCodingTraits::encode(value, *this); 104| 0| } 105| | 106| | /// Get the encoded binary data. 107| | std::vector contents() { 108| | return std::vector(encdata.begin(), encdata.end()); 109| | } 110| | 111| | /// Get the encoded binary data (in place) 112| | const uint8_t* data() const { 113| | return encdata.data(); 114| | } 115| | 116| | /// Get the size of the encoded binary data 117| | const size_t size() const { 118| | return encdata.size(); 119| | } 120| |}; 121| | 122| |/// A basic binary decoding utility. 123| |/// 124| |/// \see BinaryEncoder. 125| |class BinaryDecoder { 126| |private: 127| | // Copying is disabled. 128| | BinaryDecoder(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 129| | void operator=(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 130| | 131| | /// The data being decoded. 132| | StringRef data; 133| | 134| | /// The current position in the stream. 135| | uint64_t pos = 0; 136| | 137| | uint8_t read8() { return data[pos++]; } 138| | uint16_t read16() { 139| | uint16_t result = read8(); 140| | result |= uint16_t(read8()) << 8; 141| | return result; 142| | } 143| | uint32_t read32() { 144| | uint32_t result = read16(); 145| | result |= uint32_t(read16()) << 16; 146| | return result; 147| | } 148| | uint64_t read64() { 149| | uint64_t result = read32(); 150| | result |= uint64_t(read32()) << 32; 151| | return result; 152| | } 153| | 154| |public: 155| | /// Construct a binary decoder. 156| 0| BinaryDecoder(StringRef data) : data(data) {} 157| | 158| | /// Construct a binary decoder. 159| | /// 160| | /// NOTE: The input data is supplied by reference, and its lifetime must 161| | /// exceed that of the decoder. 162| | BinaryDecoder(const std::vector& data) : BinaryDecoder( 163| 0| StringRef(reinterpret_cast(data.data()), data.size())) {} 164| | 165| | /// Check if the decoder is at the end of the stream. 166| | bool isEmpty() const { 167| | return pos == data.size(); 168| | } 169| | 170| | /// Decode a value from the stream. 171| 0| void read(bool& value) { value = read8() != 0; } 172| | 173| | /// Decode a value from the stream. 174| 0| void read(uint8_t& value) { value = read8(); } 175| | 176| | /// Decode a value from the stream. 177| 0| void read(uint16_t& value) { value = read16(); } 178| | 179| | /// Decode a value from the stream. 180| 0| void read(uint32_t& value) { value = read32(); } 181| | 182| | /// Decode a value from the stream. 183| 0| void read(uint64_t& value) { value = read64(); } 184| | 185| | /// Decode a value from the stream. 186| 0| void read(std::string& value) { 187| 0| uint32_t size; 188| 0| read(size); 189| 0| StringRef contents; 190| 0| readBytes(size, contents); 191| 0| value = contents.str(); 192| 0| } 193| | 194| | /// Decode a byte string from the stream. 195| | /// 196| | /// NOTE: The return value points into the decode stream, and must be copied 197| | /// by clients if it is to last longer than the lifetime of the decoder. 198| | void readBytes(size_t count, StringRef& value) { 199| | assert(pos + count <= data.size()); 200| | value = StringRef(data.begin() + pos, count); 201| | pos += count; 202| | } 203| | 204| | /// Decode a value from the stream. 205| | template 206| 0| void read(T& value) { 207| 0| BinaryCodingTraits::decode(value, *this); 208| 0| } 209| | 210| | /// Finish decoding and clean up. 211| | void finish() { 212| | assert(isEmpty()); 213| | } 214| |}; 215| | 216| |template<> 217| |struct BinaryCodingTraits { 218| 0| static inline void encode(const StringRef& value, BinaryEncoder& coder) { 219| 0| coder.writeBytes(value); 220| 0| } 221| |}; 222| | 223| |} 224| |} 225| | 226| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/ExecutionQueue.h: 1| |//===- ExecutionQueue.h -----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_EXECUTIONQUEUE_H 14| |#define LLBUILD_BASIC_EXECUTIONQUEUE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| |#include "llbuild/Basic/Subprocess.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| | namespace basic { 24| | 25| | /// MARK: Execution Queue 26| | 27| | class ExecutionQueueDelegate; 28| | 29| | /// Description of the queue job, used for scheduling and diagnostics. 30| | class JobDescriptor { 31| | public: 32| 0| JobDescriptor() {} 33| | virtual ~JobDescriptor(); 34| | 35| | /// Get a name used for ordering this job 36| | virtual StringRef getOrdinalName() const = 0; 37| | 38| | /// Get a short description of the command, for use in status reporting. 39| | virtual void getShortDescription(SmallVectorImpl &result) const = 0; 40| | 41| | /// Get a verbose description of the command, for use in status reporting. 42| | virtual void getVerboseDescription(SmallVectorImpl &result) const = 0; 43| | }; 44| | 45| | 46| | /// Opaque type which allows the queue implementation to maintain additional 47| | /// state and associate subsequent requests (e.g., \see executeProcess()) 48| | /// with the dispatching job. 49| | class QueueJobContext { 50| | public: 51| | virtual ~QueueJobContext(); 52| | virtual unsigned laneID() const = 0; 53| | }; 54| | 55| | /// Wrapper for individual pieces of work that are added to the execution 56| | /// queue. 57| | class QueueJob { 58| | JobDescriptor* desc = nullptr; 59| | 60| | /// The function to execute to do the work. 61| | typedef std::function work_fn_ty; 62| | work_fn_ty work; 63| | 64| | public: 65| | /// Default constructor, for use as a sentinel. 66| 0| QueueJob() {} 67| | 68| | /// General constructor. 69| | QueueJob(JobDescriptor* desc, work_fn_ty work) 70| 0| : desc(desc), work(work) {} 71| | 72| 0| JobDescriptor* getDescriptor() const { return desc; } 73| | 74| 0| void execute(QueueJobContext* context) { work(context); } 75| | }; 76| | 77| | /// This abstact class encapsulates the interface needed for contributing 78| | /// work which needs to be executed. 79| | class ExecutionQueue { 80| | // DO NOT COPY 81| | ExecutionQueue(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 82| | void operator=(const ExecutionQueue&) LLBUILD_DELETED_FUNCTION; 83| | ExecutionQueue& operator=(ExecutionQueue&&) LLBUILD_DELETED_FUNCTION; 84| | 85| | ExecutionQueueDelegate& delegate; 86| | 87| | public: 88| | ExecutionQueue(ExecutionQueueDelegate& delegate); 89| | virtual ~ExecutionQueue(); 90| | 91| | /// @name Accessors 92| | /// @{ 93| | 94| 0| ExecutionQueueDelegate& getDelegate() { return delegate; } 95| 0| const ExecutionQueueDelegate& getDelegate() const { return delegate; } 96| | 97| | /// @} 98| | 99| | /// Add a job to be executed. 100| | virtual void addJob(QueueJob job) = 0; 101| | 102| | /// Cancel all jobs and subprocesses of this queue. 103| | virtual void cancelAllJobs() = 0; 104| | 105| | 106| | /// @name Execution Interfaces 107| | /// 108| | /// These are additional interfaces provided by the execution queue which 109| | /// can be invoked by the individual \see QueueJob::execute() to perform 110| | /// particular actions. The benefit of delegating to the execution queue 111| | /// to perform these actions is that the queue can potentially do a better 112| | /// job of scheduling activities. 113| | /// 114| | /// @{ 115| | 116| | /// Execute the given command line. 117| | /// 118| | /// This will launch and execute the given command line and wait for it to 119| | /// complete or release its execution lane. 120| | /// 121| | /// \param context The context object passed to the job's worker function. 122| | /// 123| | /// \param commandLine The command line to execute. 124| | /// 125| | /// \param environment The environment to launch with. 126| | /// 127| | /// \param completionFn An optional function that, if supplied, will be 128| | /// run following the completion of the process. This may be run 129| | /// asynchronously from another thread if the executed process asks the 130| | /// system to release its execution lane. Callers should put cleanup and 131| | /// notification work here. 132| | /// 133| | /// \param inheritEnvironment If true, the supplied environment will be 134| | /// overlayed on top base environment supplied when creating the queue. If 135| | /// false, only the supplied environment will be passed to the subprocess. 136| | /// 137| | /// \param attributes Additional attributes for the process to be spawned. 138| | // 139| | // FIXME: This interface will need to get more complicated, and provide the 140| | // command result and facilities for dealing with the output. 141| | virtual void 142| | executeProcess(QueueJobContext* context, 143| | ArrayRef commandLine, 144| | ArrayRef> environment, 145| | bool inheritEnvironment = true, 146| | ProcessAttributes attributes = {true}, 147| | llvm::Optional completionFn = {llvm::None}) = 0; 148| | 149| | /// @} 150| | 151| | /// Execute the given command, using an inherited environment. 152| | ProcessStatus executeProcess(QueueJobContext* context, 153| | ArrayRef commandLine); 154| | 155| | /// Execute the given command using "/bin/sh". 156| | /// 157| | /// This will launch and execute the given command line and wait for it to 158| | /// complete. 159| | /// 160| | /// \param context The context object passed to the job's worker function. 161| | /// \param command The command to execute. 162| | /// \returns True on success. 163| | // 164| | // FIXME: This interface will need to get more complicated, and provide the 165| | // command result and facilities for dealing with the output. 166| | bool executeShellCommand(QueueJobContext* context, StringRef command); 167| | 168| | }; 169| | 170| | /// Delegate interface for execution queue status. 171| | /// 172| | /// All delegate interfaces are invoked synchronously by the execution queue, 173| | /// and should defer any long running operations to avoid blocking the queue 174| | /// unnecessarily. 175| | /// 176| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, which 177| | /// will arrive concurrently and without any specified thread. 178| | class ExecutionQueueDelegate : public ProcessDelegate { 179| | // DO NOT COPY 180| | ExecutionQueueDelegate(const ExecutionQueueDelegate&) 181| | LLBUILD_DELETED_FUNCTION; 182| | void operator=(const ExecutionQueueDelegate&) LLBUILD_DELETED_FUNCTION; 183| | ExecutionQueueDelegate &operator=(ExecutionQueueDelegate&& rhs) 184| | LLBUILD_DELETED_FUNCTION; 185| | 186| | public: 187| 0| ExecutionQueueDelegate() {} 188| | virtual ~ExecutionQueueDelegate(); 189| | 190| | /// Called when a command's job has been started. 191| | /// 192| | /// The queue guarantees that any jobStarted() call will be paired with 193| | /// exactly one \see jobFinished() call. 194| | // 195| | // FIXME: We may eventually want to allow the individual job to provide 196| | // some additional context here, for complex commands. 197| | // 198| | // FIXME: Design a way to communicate the "lane" here, for use in "super 199| | // console" like UIs. 200| | virtual void queueJobStarted(JobDescriptor*) = 0; 201| | 202| | /// Called when a command's job has been finished. 203| | /// 204| | /// NOTE: This callback is invoked by the queue without any understanding 205| | /// of how the command is tied to the engine. In particular, it is almost 206| | /// always the case that the command will have already completed from the 207| | /// perspective of the low-level engine (and its dependents may have 208| | /// started executing). Clients which want to understand when a command is 209| | /// complete before the engine has been notified as such should use \see 210| | /// BuildSystem::commandFinished(). 211| | virtual void queueJobFinished(JobDescriptor*) = 0; 212| | }; 213| | 214| | // MARK: Lane Based Execution Queue 215| | 216| | enum class SchedulerAlgorithm { 217| | /// Name priority queue based scheduling [default] 218| | NamePriority = 0, 219| | 220| | /// First in, first out 221| | FIFO = 1 222| | }; 223| | 224| | /// Create an execution queue that schedules jobs to individual lanes with a 225| | /// capped limit on the number of concurrent lanes. 226| | ExecutionQueue* createLaneBasedExecutionQueue( 227| | ExecutionQueueDelegate& delegate, int numLanes, SchedulerAlgorithm alg, 228| | const char* const* environment); 229| | } 230| |} 231| | 232| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileInfo.h: 1| |//===- FileInfo.h -----------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file contains the FileInfo wrapper which is shared by the Ninja and 14| |// BuildSystem libraries. 15| |// 16| |// FIXME: I am ambivalent about this living in Basic, I want all non-functional 17| |// pieces to generally be pretty isolated (and ideally always mediated by a 18| |// delegate access). We may eventually want a specific FileSystem component for 19| |// dealing with efficient and abstracted access to the file system and 20| |// containing other pieces (like stat caching, or dealing with distribution or 21| |// virtualization). 22| |// 23| |//===----------------------------------------------------------------------===// 24| | 25| |#ifndef LLBUILD_BASIC_FILEINFO_H 26| |#define LLBUILD_BASIC_FILEINFO_H 27| | 28| |#include "BinaryCoding.h" 29| | 30| |#include 31| |#include 32| | 33| |namespace llbuild { 34| |namespace basic { 35| | 36| |/// File timestamp wrapper. 37| |struct FileTimestamp { 38| | uint64_t seconds; 39| | uint64_t nanoseconds; 40| | 41| | bool operator==(const FileTimestamp& rhs) const { 42| | return seconds == rhs.seconds && nanoseconds == rhs.nanoseconds; 43| | } 44| 0| bool operator!=(const FileTimestamp& rhs) const { 45| 0| return !(*this == rhs); 46| 0| } 47| 0| bool operator<(const FileTimestamp& rhs) const { 48| 0| return (seconds < rhs.seconds || 49| 0| (seconds == rhs.seconds && nanoseconds < rhs.nanoseconds)); 50| 0| } 51| 0| bool operator<=(const FileTimestamp& rhs) const { 52| 0| return (seconds < rhs.seconds || 53| 0| (seconds == rhs.seconds && nanoseconds <= rhs.nanoseconds)); 54| 0| } 55| 0| bool operator>(const FileTimestamp& rhs) const { 56| 0| return rhs < *this; 57| 0| } 58| 0| bool operator>=(const FileTimestamp& rhs) const { 59| 0| return rhs <= *this; 60| 0| } 61| |}; 62| | 63| |/// File information which is intended to be used as a proxy for when a file has 64| |/// changed. 65| |/// 66| |/// This structure is intentionally sized to have no packing holes. 67| |struct FileInfo { 68| | /// The device number. 69| | uint64_t device; 70| | /// The inode number. 71| | uint64_t inode; 72| | /// The mode flags of the file. 73| | uint64_t mode; 74| | /// The size of the file. 75| | uint64_t size; 76| | /// The modification time of the file. 77| | FileTimestamp modTime; 78| | 79| | /// Check if this is a FileInfo representing a missing file. 80| 0| bool isMissing() const { 81| 0| // We use an all-zero FileInfo as a sentinel, under the assumption this can 82| 0| // never exist in normal circumstances. 83| 0| return (device == 0 && inode == 0 && mode == 0 && size == 0 && 84| 0| modTime.seconds == 0 && modTime.nanoseconds == 0); 85| 0| } 86| | 87| | /// Check if the FileInfo corresponds to a directory. 88| | bool isDirectory() const; 89| | 90| | bool operator==(const FileInfo& rhs) const { 91| | return (device == rhs.device && 92| | inode == rhs.inode && 93| | size == rhs.size && 94| | modTime == rhs.modTime); 95| | } 96| | bool operator!=(const FileInfo& rhs) const { 97| | return !(*this == rhs); 98| | } 99| | 100| | /// Get the information to represent the state of the given node in the file 101| | /// system. 102| | /// 103| | /// \param asLink If yes, checks the information for the file path without 104| | /// looking through symbolic links. 105| | /// 106| | /// \returns The FileInfo for the given path, which will be missing if the 107| | /// path does not exist (or any error was encountered). 108| | static FileInfo getInfoForPath(const std::string& path, bool asLink = false); 109| |}; 110| | 111| |template<> 112| |struct BinaryCodingTraits { 113| 0| static inline void encode(const FileTimestamp& value, BinaryEncoder& coder) { 114| 0| coder.write(value.seconds); 115| 0| coder.write(value.nanoseconds); 116| 0| } 117| 0| static inline void decode(FileTimestamp& value, BinaryDecoder& coder) { 118| 0| coder.read(value.seconds); 119| 0| coder.read(value.nanoseconds); 120| 0| } 121| |}; 122| | 123| |template<> 124| |struct BinaryCodingTraits { 125| 0| static inline void encode(const FileInfo& value, BinaryEncoder& coder) { 126| 0| coder.write(value.device); 127| 0| coder.write(value.inode); 128| 0| coder.write(value.mode); 129| 0| coder.write(value.size); 130| 0| coder.write(value.modTime); 131| 0| } 132| 0| static inline void decode(FileInfo& value, BinaryDecoder& coder) { 133| 0| coder.read(value.device); 134| 0| coder.read(value.inode); 135| 0| coder.read(value.mode); 136| 0| coder.read(value.size); 137| 0| coder.read(value.modTime); 138| 0| } 139| |}; 140| | 141| |} 142| |} 143| | 144| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/FileSystem.h: 1| |//===- FileSystem.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_FILESYSTEM_H 14| |#define LLBUILD_BASIC_FILESYSTEM_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/FileInfo.h" 18| |#include "llbuild/Basic/LLVM.h" 19| | 20| |#include "llvm/Support/ErrorOr.h" 21| | 22| |#include 23| | 24| |namespace llvm { 25| | 26| |class MemoryBuffer; 27| | 28| |} 29| | 30| |namespace llbuild { 31| |namespace basic { 32| | 33| |// Abstract interface for interacting with a file system. This allows mocking of 34| |// operations for testing, and for clients to provide virtualized interfaces. 35| |class FileSystem { 36| | // DO NOT COPY 37| | FileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 38| | void operator=(const FileSystem&) LLBUILD_DELETED_FUNCTION; 39| | FileSystem &operator=(FileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 40| | 41| |public: 42| 0| FileSystem() {} 43| | virtual ~FileSystem(); 44| | 45| | /// Create the given directory if it does not exist. 46| | /// 47| | /// \returns True on success (the directory was created, or already exists). 48| | virtual bool 49| | createDirectory(const std::string& path) = 0; 50| | 51| | /// Create the given directory (recursively) if it does not exist. 52| | /// 53| | /// \returns True on success (the directory was created, or already exists). 54| | virtual bool 55| | createDirectories(const std::string& path); 56| | 57| | /// Get a memory buffer for a given file on the file system. 58| | /// 59| | /// \returns The file contents, on success, or null on error. 60| | virtual std::unique_ptr 61| | getFileContents(const std::string& path) = 0; 62| | 63| | /// Remove the file or directory at the given path. 64| | /// 65| | /// Directory removal is recursive. 66| | /// 67| | /// \returns True if the item was removed, false otherwise. 68| | virtual bool remove(const std::string& path) = 0; 69| | 70| | /// Get the information to represent the state of the given path in the file 71| | /// system. 72| | /// 73| | /// \returns The FileInfo for the given path, which will be missing if the 74| | /// path does not exist (or any error was encountered). 75| | virtual FileInfo getFileInfo(const std::string& path) = 0; 76| | 77| | /// Get the information to represent the state of the given path in the file 78| | /// system, without looking through symbolic links. 79| | /// 80| | /// \returns The FileInfo for the given path, which will be missing if the 81| | /// path does not exist (or any error was encountered). 82| | virtual FileInfo getLinkInfo(const std::string& path) = 0; 83| |}; 84| | 85| |/// Create a FileSystem instance suitable for accessing the local filesystem. 86| |std::unique_ptr createLocalFileSystem(); 87| | 88| | 89| |/// Device/inode agnostic filesystem wrapper 90| |class DeviceAgnosticFileSystem : public FileSystem { 91| |private: 92| | std::unique_ptr impl; 93| | 94| |public: 95| | explicit DeviceAgnosticFileSystem(std::unique_ptr fs) 96| | : impl(std::move(fs)) 97| 0| { 98| 0| } 99| | 100| | DeviceAgnosticFileSystem(const FileSystem&) LLBUILD_DELETED_FUNCTION; 101| | void operator=(const DeviceAgnosticFileSystem&) LLBUILD_DELETED_FUNCTION; 102| | DeviceAgnosticFileSystem &operator=(DeviceAgnosticFileSystem&& rhs) LLBUILD_DELETED_FUNCTION; 103| | 104| | static std::unique_ptr from(std::unique_ptr fs); 105| | 106| | 107| | virtual bool 108| 0| createDirectory(const std::string& path) override { 109| 0| return impl->createDirectory(path); 110| 0| } 111| | 112| | virtual bool 113| 0| createDirectories(const std::string& path) override { 114| 0| return impl->createDirectories(path); 115| 0| } 116| | 117| | virtual std::unique_ptr 118| | getFileContents(const std::string& path) override; 119| | 120| 0| virtual bool remove(const std::string& path) override { 121| 0| return impl->remove(path); 122| 0| } 123| | 124| 0| virtual FileInfo getFileInfo(const std::string& path) override { 125| 0| auto info = impl->getFileInfo(path); 126| 0| 127| 0| // Device and inode numbers may (will) change when relocating files to 128| 0| // another device. Here we explicitly, unconditionally override them with 0, 129| 0| // enabling an entire build tree to be relocated or copied yet retain the 130| 0| // ability to perform incremental builds. 131| 0| info.device = 0; 132| 0| info.inode = 0; 133| 0| 134| 0| return info; 135| 0| } 136| | 137| 0| virtual FileInfo getLinkInfo(const std::string& path) override { 138| 0| auto info = impl->getLinkInfo(path); 139| 0| 140| 0| info.device = 0; 141| 0| info.inode = 0; 142| 0| 143| 0| return info; 144| 0| } 145| |}; 146| | 147| |} 148| |} 149| | 150| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Hashing.h: 1| |//===- Hashing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_HASHING_H 14| |#define LLBUILD_BASIC_HASHING_H 15| | 16| |#include "llbuild/Basic/BinaryCoding.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/Hashing.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |namespace llbuild { 23| |namespace basic { 24| | 25| |uint64_t hashString(StringRef value); 26| | 27| |class CommandSignature { 28| |public: 29| | CommandSignature() = default; 30| 0| CommandSignature(StringRef string) { 31| 0| value = size_t(llvm::hash_value(string)); 32| 0| } 33| 0| explicit CommandSignature(uint64_t sig) : value(sig) {} 34| | CommandSignature(const CommandSignature& other) = default; 35| | CommandSignature(CommandSignature&& other) = default; 36| | CommandSignature& operator=(const CommandSignature& other) = default; 37| | CommandSignature& operator=(CommandSignature&& other) = default; 38| | 39| | bool isNull() const { return value == 0; } 40| | 41| | bool operator==(const CommandSignature& other) const { return value == other.value; } 42| | bool operator!=(const CommandSignature& other) const { return value != other.value; } 43| | 44| | CommandSignature& combine(StringRef string) { 45| | // FIXME: Use a more appropriate hashing infrastructure. 46| | value = llvm::hash_combine(value, string); 47| | return *this; 48| | } 49| | 50| | CommandSignature& combine(const std::string &string) { 51| | // FIXME: Use a more appropriate hashing infrastructure. 52| | value = llvm::hash_combine(value, string); 53| | return *this; 54| | } 55| | 56| | CommandSignature& combine(bool b) { 57| | // FIXME: Use a more appropriate hashing infrastructure. 58| | value = llvm::hash_combine(value, b); 59| | return *this; 60| | } 61| | 62| | template 63| | CommandSignature& combine(const std::vector& list) { 64| | for (const auto& v: list) { 65| | combine(v); 66| | } 67| | return *this; 68| | } 69| | 70| | uint64_t value = 0; 71| |}; 72| | 73| |template<> 74| |struct BinaryCodingTraits { 75| 0| static inline void encode(const CommandSignature& value, BinaryEncoder& coder) { 76| 0| coder.write(value.value); 77| 0| } 78| 0| static inline void decode(CommandSignature& value, BinaryDecoder& coder) { 79| 0| coder.read(value.value); 80| 0| } 81| |}; 82| | 83| |} 84| |} 85| | 86| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/POSIXEnvironment.h: 1| |//===- POSIXEnvironment.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 14| |#define LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/SmallString.h" 19| |#include "llvm/ADT/StringRef.h" 20| |#include "llvm/ADT/Hashing.h" 21| | 22| |#include 23| |#include 24| |#include 25| | 26| |namespace std { 27| | template<> struct hash { 28| 0| size_t operator()(const llvm::StringRef& value) const { 29| 0| return size_t(hash_value(value)); 30| 0| } 31| | }; 32| |} 33| | 34| |namespace llbuild { 35| |namespace basic { 36| | 37| |/// A helper class for constructing a POSIX-style environment. 38| |class POSIXEnvironment { 39| | /// The actual environment, this is only populated once frozen. 40| | std::vector env; 41| | 42| | /// The underlying string storage. 43| | // 44| | // FIXME: This is not efficient, we could store into a single allocation. 45| | std::vector envStorage; 46| | 47| | /// The list of known keys in the environment. 48| | std::unordered_set keys{}; 49| | 50| | /// Whether the environment pointer has been vended, and assignments can no 51| | /// longer be mutated. 52| | bool isFrozen = false; 53| | 54| |public: 55| 0| POSIXEnvironment() {} 56| | 57| | /// Add a key to the environment, if missing. 58| | /// 59| | /// If the key has already been defined, it will **NOT** be inserted. 60| 0| void setIfMissing(StringRef key, StringRef value) { 61| 0| assert(!isFrozen); 62| 0| if (keys.insert(key).second) { 63| 0| llvm::SmallString<256> assignment; 64| 0| assignment += key; 65| 0| assignment += '='; 66| 0| assignment += value; 67| 0| assignment += '\0'; 68| 0| envStorage.emplace_back(assignment.str()); 69| 0| } 70| 0| } 71| | 72| | /// Get the envirnonment pointer. 73| | /// 74| | /// This pointer is only valid for the lifetime of the environment itself. 75| 0| const char* const* getEnvp() { 76| 0| isFrozen = true; 77| 0| 78| 0| // Form the final environment. 79| 0| env.clear(); 80| 0| for (const auto& entry: envStorage) { 81| 0| env.emplace_back(entry.c_str()); 82| 0| } 83| 0| env.emplace_back(nullptr); 84| 0| return env.data(); 85| 0| } 86| |}; 87| | 88| |} 89| |} 90| | 91| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/PlatformUtility.h: 1| |//===- PlatformUtility.h ----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file implements small platform compatability wrapper functions for 14| |// common functions. 15| |// 16| |//===----------------------------------------------------------------------===// 17| | 18| |#ifndef LLBUILD_BASIC_PLATFORMUTILITY_H 19| |#define LLBUILD_BASIC_PLATFORMUTILITY_H 20| | 21| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 22| |#include 23| |#include 24| |#include 25| |#if !defined(_WIN32) 26| |#include 27| |#endif 28| | 29| |namespace llbuild { 30| |namespace basic { 31| |namespace sys { 32| | 33| |bool chdir(const char *fileName); 34| |int close(int fileHandle); 35| |bool mkdir(const char *fileName); 36| |int pclose(FILE *stream); 37| |int pipe(int ptHandles[2]); 38| |FILE *popen(const char *command, const char *mode); 39| |int read(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 40| |int rmdir(const char *path); 41| |int symlink(const char *source, const char *target); 42| |int unlink(const char *fileName); 43| |int write(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 44| |std::string strerror(int error); 45| |char *strsep(char **stringp, const char *delim); 46| |// Create a directory in the temporary folder which doesn't exist and return 47| |// it's path. 48| |std::string makeTmpDir(); 49| | 50| |// Return a string containing all valid path separators on the current platform 51| |std::string getPathSeparators(); 52| | 53| |/// Sets the max open file limit to min(max(soft_limit, limit), hard_limit), 54| |/// where soft_limit and hard_limit are gathered from the system. 55| |/// 56| |/// Returns: 0 on success, -1 on failure (check errno). 57| |int raiseOpenFileLimit(llbuild_rlim_t limit = 2048); 58| | 59| |enum MATCH_RESULT { MATCH, NO_MATCH, MATCH_ERROR }; 60| |// Test if a path or filename matches a wildcard pattern 61| |// 62| |// Returns MATCH if a match is detected, NO_MATCH if there is no match, and 63| |// MATCH_ERROR on error. Windows callers may use GetLastError to get additional 64| |// error information. 65| |MATCH_RESULT filenameMatch(const std::string& pattern, const std::string& filename); 66| | 67| |void sleep(int seconds); 68| |template struct FileDescriptorTraits; 69| | 70| |#if defined(_WIN32) 71| |template <> struct FileDescriptorTraits { 72| | static void Close(HANDLE hFile) { CloseHandle(hFile); } 73| | static int Read(HANDLE hFile, void *destinationBuffer, 74| | unsigned int maxCharCount) { 75| | DWORD numBytes; 76| | if (!ReadFile(hFile, destinationBuffer, maxCharCount, &numBytes, nullptr)) { 77| | return -1; 78| | } 79| | return numBytes; 80| | } 81| |}; 82| |#endif 83| |template <> struct FileDescriptorTraits { 84| 0| static void Close(int fd) { close(fd); } 85| | static int Read(int hFile, void *destinationBuffer, 86| 0| unsigned int maxCharCount) { 87| 0| return read(hFile, destinationBuffer, maxCharCount); 88| 0| } 89| |}; 90| |} 91| |} 92| |} 93| | 94| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Subprocess.h: 1| |//===- Subprocess.h ---------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2018 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_SUBPROCESS_H 14| |#define LLBUILD_BASIC_SUBPROCESS_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 18| |#include "llbuild/Basic/LLVM.h" 19| |#include "llbuild/Basic/POSIXEnvironment.h" 20| | 21| |#include "llvm/ADT/Optional.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| | 29| |namespace llbuild { 30| | namespace basic { 31| | 32| | // MARK: Quality of Service 33| | 34| | enum class QualityOfService { 35| | /// A default quality of service (i.e. what the system would use without 36| | /// other advisement, generally this would be comparable to what would be 37| | /// done by `make`, `ninja`, etc.) 38| | Normal, 39| | 40| | /// User-initiated, high priority work. 41| | UserInitiated, 42| | 43| | /// Batch work performed on behalf of the user. 44| | Utility, 45| | 46| | /// Background work that is not directly visible to the user. 47| | Background 48| | }; 49| | 50| | QualityOfService getDefaultQualityOfService(); 51| | void setDefaultQualityOfService(QualityOfService level); 52| | 53| | void setCurrentThreadQualityOfService(QualityOfService level); 54| | 55| | 56| | // MARK: Process Info 57| | 58| | /// Handle used to communicate information about a launched process. 59| | struct ProcessHandle { 60| | /// Opaque ID. 61| | uint64_t id; 62| | }; 63| | 64| | struct ProcessInfo { 65| | /// Whether the process can be safely interrupted. 66| | bool canSafelyInterrupt; 67| | }; 68| | 69| | 70| | // MARK: Process Group 71| | 72| | class ProcessGroup { 73| | ProcessGroup(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 74| | void operator=(const ProcessGroup&) LLBUILD_DELETED_FUNCTION; 75| | ProcessGroup& operator=(ProcessGroup&&) LLBUILD_DELETED_FUNCTION; 76| | 77| | std::unordered_map processes; 78| | std::condition_variable processesCondition; 79| | bool closed = false; 80| | 81| | public: 82| 0| ProcessGroup() {} 83| | ~ProcessGroup(); 84| | 85| | std::mutex mutex; 86| | 87| 0| void close() { closed = true; } 88| 0| bool isClosed() const { return closed; } 89| | 90| | void add(std::lock_guard&& lock, llbuild_pid_t pid, 91| 0| ProcessInfo info) { 92| 0| processes.emplace(std::make_pair(pid, info)); 93| 0| } 94| | 95| 0| void remove(llbuild_pid_t pid) { 96| 0| { 97| 0| std::lock_guard lock(mutex); 98| 0| processes.erase(pid); 99| 0| } 100| 0| processesCondition.notify_all(); 101| 0| } 102| | 103| | void signalAll(int signal); 104| | }; 105| | 106| | 107| | // MARK: Process Execution 108| | 109| | /// Status of a process execution. 110| | enum class ProcessStatus { 111| | Succeeded = 0, 112| | Failed, 113| | Cancelled, 114| | Skipped, 115| | }; 116| | 117| | /// Result of a process execution. 118| | struct ProcessResult { 119| | 120| | /// The final status of the command 121| | ProcessStatus status; 122| | 123| | /// Process exit code 124| | int exitCode; 125| | 126| | /// Process identifier (can be -1 for failure reasons) 127| | llbuild_pid_t pid; 128| | 129| | /// User time (in us) 130| | uint64_t utime; 131| | 132| | /// System time (in us) 133| | uint64_t stime; 134| | 135| | /// Max RSS (in bytes) 136| | uint64_t maxrss; 137| | 138| | ProcessResult(ProcessStatus status, int exitCode = -1, 139| | llbuild_pid_t pid = (llbuild_pid_t)-1, uint64_t utime = 0, 140| | uint64_t stime = 0, uint64_t maxrss = 0) 141| | : status(status), exitCode(exitCode), pid(pid), utime(utime), 142| 0| stime(stime), maxrss(maxrss) {} 143| | 144| 0| static ProcessResult makeFailed(int exitCode = -1) { 145| 0| return ProcessResult(ProcessStatus::Failed, exitCode); 146| 0| } 147| | 148| 0| static ProcessResult makeCancelled(int exitCode = -1) { 149| 0| return ProcessResult(ProcessStatus::Cancelled, exitCode); 150| 0| } 151| | }; 152| | 153| | 154| | typedef std::function&&)> ProcessReleaseFn; 155| | typedef std::function ProcessCompletionFn; 156| | 157| | 158| | /// Opaque context passed on to the delegate 159| | struct ProcessContext; 160| | 161| | /// Delegate interface for process execution. 162| | /// 163| | /// All delegate interfaces are invoked synchronously by the subprocess 164| | /// methods (as called by the execution queue, for example) and should defer 165| | /// any long running operations to avoid blocking the queue unnecessarily. 166| | /// 167| | /// NOTE: The delegate *MUST* be thread-safe with respect to all calls, 168| | /// which will arrive concurrently and without any specified thread. 169| | class ProcessDelegate { 170| | // DO NOT COPY 171| | ProcessDelegate(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 172| | void operator=(const ProcessDelegate&) LLBUILD_DELETED_FUNCTION; 173| | ProcessDelegate& operator=(ProcessDelegate&& rhs) LLBUILD_DELETED_FUNCTION; 174| | 175| | public: 176| 0| ProcessDelegate() {} 177| | virtual ~ProcessDelegate(); 178| | 179| | /// Called when the external process has started executing. 180| | /// 181| | /// The subprocess code guarantees that any processStarted() call will be 182| | /// paired with exactly one \see processFinished() call. 183| | /// 184| | /// \param ctx - Opaque context passed on to the delegate 185| | /// \param handle - A unique handle used in subsequent delegate calls to 186| | /// identify the process. This handle should only be used to associate 187| | /// different status calls relating to the same process. It is only 188| | /// guaranteed to be unique from when it has been provided here to when it 189| | /// has been provided to the \see processFinished() call. 190| | virtual void processStarted(ProcessContext* ctx, ProcessHandle handle) = 0; 191| | 192| | /// Called to report an error in the management of a command process. 193| | /// 194| | /// \param ctx - Opaque context passed on to the delegate 195| | /// \param handle - The process handle. 196| | /// \param message - The error message. 197| | // 198| | // FIXME: Need to move to more structured error handling. 199| | virtual void processHadError(ProcessContext* ctx, ProcessHandle handle, 200| | const Twine& message) = 0; 201| | 202| | /// Called to report a command processes' (merged) standard output and error. 203| | /// 204| | /// \param ctx - Opaque context passed on to the delegate 205| | /// \param handle - The process handle. 206| | /// \param data - The process output. 207| | virtual void processHadOutput(ProcessContext* ctx, ProcessHandle handle, 208| | StringRef data) = 0; 209| | 210| | /// Called when a command's job has finished executing an external process. 211| | /// 212| | /// \param ctx - Opaque context passed on to the delegate 213| | /// \param handle - The handle used to identify the process. This handle 214| | /// will become invalid as soon as the client returns from this API call. 215| | /// \param result - Whether the process suceeded, failed or was cancelled. 216| | // 217| | // FIXME: Need to include additional information on the status here, e.g., the 218| | // signal status, and the process output (if buffering). 219| | virtual void processFinished(ProcessContext* ctx, ProcessHandle handle, 220| | const ProcessResult& result) = 0; 221| | }; 222| | 223| | 224| | struct ProcessAttributes { 225| | /// If true, whether it is safe to attempt to SIGINT the process to cancel 226| | /// it. If false, the process won't be interrupted during cancellation and 227| | /// will be given a chance to complete (if it fails to complete it will 228| | /// ultimately be sent a SIGKILL). 229| | bool canSafelyInterrupt; 230| | 231| | /// If set, the working directory to change into before spawning (support 232| | /// not guaranteed on all platforms). 233| | StringRef workingDir = {}; 234| | 235| | /// If true, exposes a control file descriptor that may be used to 236| | /// communicate with the build system. 237| | bool controlEnabled = true; 238| | }; 239| | 240| | /// Execute the given command line. 241| | /// 242| | /// This will launch and execute the given command line and wait for it to 243| | /// complete or release its execution lane. 244| | /// 245| | /// \param delegate The process delegate. 246| | /// 247| | /// \param ctx The context object passed to the delegate. 248| | /// 249| | /// \param pgrp The process group in which to track this process. 250| | /// 251| | /// \param handle The handle object passed to the delegate. 252| | /// 253| | /// \param commandLine The command line to execute. 254| | /// 255| | /// \param environment The environment to launch with. 256| | /// 257| | /// \param attributes Additional attributes for the process to be spawned. 258| | /// 259| | /// \param releaseFn Functional called when a process wishes to release its 260| | /// exclusive access to build system resources (namely an execution lane). 261| | /// 262| | /// \param completionFn An optional function that, if supplied, will be run 263| | /// following the completion of the process. This may be run asynchronously 264| | /// from another thread if the executed process asks the system to release 265| | /// its execution lane. Callers should put cleanup and notification work 266| | /// here. 267| | /// 268| | // 269| | // FIXME: This interface will need to get more complicated, and provide the 270| | // command result and facilities for dealing with the output. 271| | void spawnProcess(ProcessDelegate& delegate, 272| | ProcessContext* ctx, 273| | ProcessGroup& pgrp, 274| | ProcessHandle handle, 275| | ArrayRef commandLine, 276| | POSIXEnvironment environment, 277| | ProcessAttributes attributes, 278| | ProcessReleaseFn&& releaseFn, 279| | ProcessCompletionFn&& completionFn); 280| | 281| | /// @} 282| | 283| | } 284| |} 285| | 286| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Tracing.h: 1| |//===- Tracing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_TRACING_H 14| |#define LLBUILD_BASIC_TRACING_H 15| | 16| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 17| |#include "llvm/ADT/StringRef.h" 18| | 19| |// os_signpost is included in mac OS 10.14, if that header is not available, we don't trace at all. 20| |#if __has_include() 21| |#include 22| | 23| |/// Returns the singleton instance of os_log_t to use with os_log and os_signpost API. 24| |API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0)) 25| 0|static os_log_t getLog() { 26| 0| static os_log_t generalLog; 27| 0| static dispatch_once_t onceToken; 28| 0| dispatch_once(&onceToken, ^{ 29| 0| generalLog = os_log_create("org.swift.llbuild", "tracing"); 30| 0| }); 31| 0| return generalLog; 32| 0|} ------------------ | Unexecuted instantiation: LaneBasedExecutionQueue.cpp:_ZL6getLogv ------------------ | Unexecuted instantiation: Tracing.cpp:_ZL6getLogv ------------------ 33| | 34| |/// Returns a singleton id to use for all signpost calls during the lifetime of the program. 35| |API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) 36| 0|static os_signpost_id_t signpost_id() { 37| 0| static os_signpost_id_t signpost_id; 38| 0| static dispatch_once_t onceToken; 39| 0| dispatch_once(&onceToken, ^{ 40| 0| signpost_id = os_signpost_id_generate(getLog()); 41| 0| }); 42| 0| return signpost_id; 43| 0|} ------------------ | Unexecuted instantiation: LaneBasedExecutionQueue.cpp:_ZL11signpost_idv ------------------ | Unexecuted instantiation: Tracing.cpp:_ZL11signpost_idv ------------------ 44| | 45| |/// Begin an interval if tracing is enabled. 46| 0|#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { \ 47| 0|if (__builtin_available(macOS 10.14, *)) os_signpost_interval_begin(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 48| 0|} 49| | 50| |/// End an interval if tracing is enabled. 51| 0|#define LLBUILD_TRACE_INTERVAL_END(name, ...) { \ 52| 0|if (__builtin_available(macOS 10.14, *)) os_signpost_interval_end(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 53| 0|} 54| | 55| |/// Trace an event without duration at a point in time. 56| 0|#define LLBUILD_TRACE_POINT(name, ...) { \ 57| 0|if (__builtin_available(macOS 10.12, *)) os_log(getLog(), ##__VA_ARGS__); \ 58| 0|} 59| | 60| |#else 61| | 62| |// Define dummy definitions to do nothing 63| |#define LLBUILD_TRACE_POINT(name, ...) { (void)(name); } 64| |#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { (void)(name); } 65| |#define LLBUILD_TRACE_INTERVAL_END(name, ...) { (void)(name); } 66| |#define LLBUILD_TRACING_SET_ENABLED(on) { (void)on; } 67| | 68| |#endif // __has_include() 69| | 70| |namespace llbuild { 71| |extern bool TracingEnabled; 72| | 73| |struct TracingExecutionQueueJob { 74| 0| TracingExecutionQueueJob(int laneNumber, llvm::StringRef commandName) { 75| 0| if (!TracingEnabled) return; 76| 0| LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_job", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 77| 0| } 78| | 79| 0| ~TracingExecutionQueueJob() { 80| 0| if (!TracingEnabled) return; 81| 0| LLBUILD_TRACE_INTERVAL_END("execution_queue_job"); 82| 0| } 83| |}; 84| | 85| | 86| |inline void TracingExecutionQueueSubprocessStart(uint32_t laneNumber, 87| 0| llvm::StringRef commandName) { 88| 0| if (!TracingEnabled) return; 89| 0| LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 90| 0|} 91| | 92| |inline void TracingExecutionQueueSubprocessResult(uint32_t laneNumber, 93| | llbuild_pid_t pid, 94| | uint64_t utime, 95| 0| uint64_t stime, long maxrss) { 96| 0| if (!TracingEnabled) return; 97| 0| LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 98| 0|} 99| | 100| | 101| |struct TracingExecutionQueueSubprocess { 102| | TracingExecutionQueueSubprocess(uint32_t laneNumber, 103| | llvm::StringRef commandName) 104| 0| : laneNumber(laneNumber), pid(0), utime(0), stime(0), maxrss(0) { 105| 0| if (!TracingEnabled) return; 106| 0| LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 107| 0| } 108| | 109| | TracingExecutionQueueSubprocess(const TracingExecutionQueueSubprocess&) = delete; 110| | TracingExecutionQueueSubprocess(TracingExecutionQueueSubprocess&& t) 111| 0| : laneNumber(t.laneNumber), pid(t.pid), utime(t.utime), stime(t.stime), maxrss(t.maxrss) { 112| 0| t.active = false; 113| 0| } 114| | 115| 0| void update(llbuild_pid_t pid, uint64_t utime, uint64_t stime, long maxrss) { 116| 0| this->pid = pid; 117| 0| this->utime = utime; 118| 0| this->stime = stime; 119| 0| this->maxrss = maxrss; 120| 0| } 121| | 122| 0| ~TracingExecutionQueueSubprocess() { 123| 0| if (!TracingEnabled || !active) return; 124| 0| LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 125| 0| } 126| | 127| |private: 128| | bool active = true; 129| | uint32_t laneNumber; 130| | llbuild_pid_t pid; 131| | uint64_t utime; 132| | uint64_t stime; 133| | long maxrss; 134| |}; 135| | 136| |// Engine Task Callbacks 137| |enum class EngineTaskCallbackKind { 138| | Start = 0, 139| | ProvidePriorValue, 140| | ProvideValue, 141| | InputsAvailable, 142| |}; 143| | 144| |struct TracingEngineTaskCallback { 145| | TracingEngineTaskCallback(EngineTaskCallbackKind kind, uint64_t key) 146| | : key(key) { 147| | if (!TracingEnabled) return; 148| | LLBUILD_TRACE_INTERVAL_BEGIN("engine_task_callback", "key:%llu;kind:%d", key, uint32_t(kind)); 149| | } 150| | 151| | ~TracingEngineTaskCallback() { 152| | if (!TracingEnabled) return; 153| | LLBUILD_TRACE_INTERVAL_END("engine_task_callback", "key:%llu", key); 154| | key = 0; 155| | } 156| |private: 157| | uint64_t key; 158| |}; 159| | 160| |// Engine Queue Processing 161| |enum class EngineQueueItemKind { 162| | RuleToScan = 0, 163| | InputRequest, 164| | FinishedInputRequest, 165| | ReadyTask, 166| | FinishedTask, 167| | Waiting, 168| | FindingCycle, 169| | BreakingCycle, 170| |}; 171| | 172| |struct TracingEngineQueueItemEvent { 173| | TracingEngineQueueItemEvent(EngineQueueItemKind kind, char const *key) 174| | : key(key) { 175| | if (!TracingEnabled) return; 176| | LLBUILD_TRACE_INTERVAL_BEGIN("engine_queue_item_event", "key:%s;kind:%d", key, kind); 177| | } 178| | 179| | ~TracingEngineQueueItemEvent() { 180| | if (!TracingEnabled) return; 181| | LLBUILD_TRACE_INTERVAL_END("engine_queue_item_event", "key:%s", key) 182| | key = nullptr; 183| | } 184| |private: 185| | char const *key; 186| |}; 187| | 188| 0|inline void TracingExecutionQueueDepth(uint64_t depth) { 189| 0| if (!TracingEnabled) return; 190| 0| LLBUILD_TRACE_POINT("execution_queue_depth", "depth:%llu", depth); 191| 0|} 192| | 193| |} 194| | 195| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/ArrayRef.h: 1| |//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_ARRAYREF_H 11| |#define LLVM_ADT_ARRAYREF_H 12| | 13| |#include "llvm/ADT/None.h" 14| |#include "llvm/ADT/SmallVector.h" 15| |#include 16| | 17| |namespace llvm { 18| | 19| | /// ArrayRef - Represent a constant reference to an array (0 or more elements 20| | /// consecutively in memory), i.e. a start pointer and a length. It allows 21| | /// various APIs to take consecutive elements easily and conveniently. 22| | /// 23| | /// This class does not own the underlying data, it is expected to be used in 24| | /// situations where the data resides in some other buffer, whose lifetime 25| | /// extends past that of the ArrayRef. For this reason, it is not in general 26| | /// safe to store an ArrayRef. 27| | /// 28| | /// This is intended to be trivially copyable, so it should be passed by 29| | /// value. 30| | template 31| | class ArrayRef { 32| | public: 33| | typedef const T *iterator; 34| | typedef const T *const_iterator; 35| | typedef size_t size_type; 36| | 37| | typedef std::reverse_iterator reverse_iterator; 38| | 39| | private: 40| | /// The start of the array, in an external buffer. 41| | const T *Data; 42| | 43| | /// The number of elements. 44| | size_type Length; 45| | 46| | public: 47| | /// @name Constructors 48| | /// @{ 49| | 50| | /// Construct an empty ArrayRef. 51| 0| /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_9StringRefEEC2Ev ------------------ 52| | 53| | /// Construct an empty ArrayRef from None. 54| | /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} 55| | 56| | /// Construct an ArrayRef from a single element. 57| | /*implicit*/ ArrayRef(const T &OneElt) 58| | : Data(&OneElt), Length(1) {} 59| | 60| | /// Construct an ArrayRef from a pointer and length. 61| | /*implicit*/ ArrayRef(const T *data, size_t length) 62| | : Data(data), Length(length) {} 63| | 64| | /// Construct an ArrayRef from a range. 65| | ArrayRef(const T *begin, const T *end) 66| | : Data(begin), Length(end - begin) {} 67| | 68| | /// Construct an ArrayRef from a SmallVector. This is templated in order to 69| | /// avoid instantiating SmallVectorTemplateCommon whenever we 70| | /// copy-construct an ArrayRef. 71| | template 72| | /*implicit*/ ArrayRef(const SmallVectorTemplateCommon &Vec) 73| | : Data(Vec.data()), Length(Vec.size()) { 74| | } 75| | 76| | /// Construct an ArrayRef from a std::vector. 77| | template 78| | /*implicit*/ ArrayRef(const std::vector &Vec) 79| 0| : Data(Vec.data()), Length(Vec.size()) {} 80| | 81| | /// Construct an ArrayRef from a C array. 82| | template 83| | /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) 84| | : Data(Arr), Length(N) {} 85| | 86| | /// Construct an ArrayRef from a std::initializer_list. 87| | /*implicit*/ ArrayRef(const std::initializer_list &Vec) 88| | : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), 89| | Length(Vec.size()) {} 90| | 91| | /// Construct an ArrayRef from ArrayRef. This uses SFINAE to 92| | /// ensure that only ArrayRefs of pointers can be converted. 93| | template 94| | ArrayRef(const ArrayRef &A, 95| | typename std::enable_if< 96| | std::is_convertible::value>::type* = 0) 97| | : Data(A.data()), Length(A.size()) {} 98| | 99| | /// @} 100| | /// @name Simple Operations 101| | /// @{ 102| | 103| 0| iterator begin() const { return Data; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE5beginEv ------------------ 104| 0| iterator end() const { return Data + Length; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINSt3__14pairINS_9StringRefES3_EEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE3endEv ------------------ 105| | 106| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 107| | reverse_iterator rend() const { return reverse_iterator(begin()); } 108| | 109| | /// empty - Check if the array is empty. 110| | bool empty() const { return Length == 0; } 111| | 112| | const T *data() const { return Data; } 113| | 114| | /// size - Get the array size. 115| 0| size_t size() const { return Length; } 116| | 117| | /// front - Get the first element. 118| | const T &front() const { 119| | assert(!empty()); 120| | return Data[0]; 121| | } 122| | 123| | /// back - Get the last element. 124| | const T &back() const { 125| | assert(!empty()); 126| | return Data[Length-1]; 127| | } 128| | 129| | // copy - Allocate copy in Allocator and return ArrayRef to it. 130| | template ArrayRef copy(Allocator &A) { 131| | T *Buff = A.template Allocate(Length); 132| | std::copy(begin(), end(), Buff); 133| | return ArrayRef(Buff, Length); 134| | } 135| | 136| | /// equals - Check for element-wise equality. 137| | bool equals(ArrayRef RHS) const { 138| | if (Length != RHS.Length) 139| | return false; 140| | if (Length == 0) 141| | return true; 142| | return std::equal(begin(), end(), RHS.begin()); 143| | } 144| | 145| | /// slice(n) - Chop off the first N elements of the array. 146| | ArrayRef slice(unsigned N) const { 147| | assert(N <= size() && "Invalid specifier"); 148| | return ArrayRef(data()+N, size()-N); 149| | } 150| | 151| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 152| | /// elements in the array. 153| | ArrayRef slice(unsigned N, unsigned M) const { 154| | assert(N+M <= size() && "Invalid specifier"); 155| | return ArrayRef(data()+N, M); 156| | } 157| | 158| | // \brief Drop the last \p N elements of the array. 159| | ArrayRef drop_back(unsigned N = 1) const { 160| | assert(size() >= N && "Dropping more elements than exist"); 161| | return slice(0, size() - N); 162| | } 163| | 164| | /// @} 165| | /// @name Operator Overloads 166| | /// @{ 167| | const T &operator[](size_t Index) const { 168| | assert(Index < Length && "Invalid index!"); 169| | return Data[Index]; 170| | } 171| | 172| | /// @} 173| | /// @name Expensive Operations 174| | /// @{ 175| | std::vector vec() const { 176| | return std::vector(Data, Data+Length); 177| | } 178| | 179| | /// @} 180| | /// @name Conversion operators 181| | /// @{ 182| | operator std::vector() const { 183| | return std::vector(Data, Data+Length); 184| | } 185| | 186| | /// @} 187| | }; 188| | 189| | /// MutableArrayRef - Represent a mutable reference to an array (0 or more 190| | /// elements consecutively in memory), i.e. a start pointer and a length. It 191| | /// allows various APIs to take and modify consecutive elements easily and 192| | /// conveniently. 193| | /// 194| | /// This class does not own the underlying data, it is expected to be used in 195| | /// situations where the data resides in some other buffer, whose lifetime 196| | /// extends past that of the MutableArrayRef. For this reason, it is not in 197| | /// general safe to store a MutableArrayRef. 198| | /// 199| | /// This is intended to be trivially copyable, so it should be passed by 200| | /// value. 201| | template 202| | class MutableArrayRef : public ArrayRef { 203| | public: 204| | typedef T *iterator; 205| | 206| | typedef std::reverse_iterator reverse_iterator; 207| | 208| | /// Construct an empty MutableArrayRef. 209| | /*implicit*/ MutableArrayRef() : ArrayRef() {} 210| | 211| | /// Construct an empty MutableArrayRef from None. 212| | /*implicit*/ MutableArrayRef(NoneType) : ArrayRef() {} 213| | 214| | /// Construct an MutableArrayRef from a single element. 215| | /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef(OneElt) {} 216| | 217| | /// Construct an MutableArrayRef from a pointer and length. 218| | /*implicit*/ MutableArrayRef(T *data, size_t length) 219| | : ArrayRef(data, length) {} 220| | 221| | /// Construct an MutableArrayRef from a range. 222| | MutableArrayRef(T *begin, T *end) : ArrayRef(begin, end) {} 223| | 224| | /// Construct an MutableArrayRef from a SmallVector. 225| | /*implicit*/ MutableArrayRef(SmallVectorImpl &Vec) 226| | : ArrayRef(Vec) {} 227| | 228| | /// Construct a MutableArrayRef from a std::vector. 229| | /*implicit*/ MutableArrayRef(std::vector &Vec) 230| | : ArrayRef(Vec) {} 231| | 232| | /// Construct an MutableArrayRef from a C array. 233| | template 234| | /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) 235| | : ArrayRef(Arr) {} 236| | 237| | T *data() const { return const_cast(ArrayRef::data()); } 238| | 239| | iterator begin() const { return data(); } 240| | iterator end() const { return data() + this->size(); } 241| | 242| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 243| | reverse_iterator rend() const { return reverse_iterator(begin()); } 244| | 245| | /// front - Get the first element. 246| | T &front() const { 247| | assert(!this->empty()); 248| | return data()[0]; 249| | } 250| | 251| | /// back - Get the last element. 252| | T &back() const { 253| | assert(!this->empty()); 254| | return data()[this->size()-1]; 255| | } 256| | 257| | /// slice(n) - Chop off the first N elements of the array. 258| | MutableArrayRef slice(unsigned N) const { 259| | assert(N <= this->size() && "Invalid specifier"); 260| | return MutableArrayRef(data()+N, this->size()-N); 261| | } 262| | 263| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 264| | /// elements in the array. 265| | MutableArrayRef slice(unsigned N, unsigned M) const { 266| | assert(N+M <= this->size() && "Invalid specifier"); 267| | return MutableArrayRef(data()+N, M); 268| | } 269| | 270| | /// @} 271| | /// @name Operator Overloads 272| | /// @{ 273| | T &operator[](size_t Index) const { 274| | assert(Index < this->size() && "Invalid index!"); 275| | return data()[Index]; 276| | } 277| | }; 278| | 279| | /// @name ArrayRef Convenience constructors 280| | /// @{ 281| | 282| | /// Construct an ArrayRef from a single element. 283| | template 284| | ArrayRef makeArrayRef(const T &OneElt) { 285| | return OneElt; 286| | } 287| | 288| | /// Construct an ArrayRef from a pointer and length. 289| | template 290| | ArrayRef makeArrayRef(const T *data, size_t length) { 291| | return ArrayRef(data, length); 292| | } 293| | 294| | /// Construct an ArrayRef from a range. 295| | template 296| | ArrayRef makeArrayRef(const T *begin, const T *end) { 297| | return ArrayRef(begin, end); 298| | } 299| | 300| | /// Construct an ArrayRef from a SmallVector. 301| | template 302| | ArrayRef makeArrayRef(const SmallVectorImpl &Vec) { 303| | return Vec; 304| | } 305| | 306| | /// Construct an ArrayRef from a SmallVector. 307| | template 308| | ArrayRef makeArrayRef(const SmallVector &Vec) { 309| | return Vec; 310| | } 311| | 312| | /// Construct an ArrayRef from a std::vector. 313| | template 314| | ArrayRef makeArrayRef(const std::vector &Vec) { 315| | return Vec; 316| | } 317| | 318| | /// Construct an ArrayRef from a C array. 319| | template 320| | ArrayRef makeArrayRef(const T (&Arr)[N]) { 321| | return ArrayRef(Arr); 322| | } 323| | 324| | /// @} 325| | /// @name ArrayRef Comparison Operators 326| | /// @{ 327| | 328| | template 329| | inline bool operator==(ArrayRef LHS, ArrayRef RHS) { 330| | return LHS.equals(RHS); 331| | } 332| | 333| | template 334| | inline bool operator!=(ArrayRef LHS, ArrayRef RHS) { 335| | return !(LHS == RHS); 336| | } 337| | 338| | /// @} 339| | 340| | // ArrayRefs can be treated like a POD type. 341| | template struct isPodLike; 342| | template struct isPodLike > { 343| | static const bool value = true; 344| | }; 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Hashing.h: 1| |//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the newly proposed standard C++ interfaces for hashing 11| |// arbitrary data and building hash functions for user-defined types. This 12| |// interface was originally proposed in N3333[1] and is currently under review 13| |// for inclusion in a future TR and/or standard. 14| |// 15| |// The primary interfaces provide are comprised of one type and three functions: 16| |// 17| |// -- 'hash_code' class is an opaque type representing the hash code for some 18| |// data. It is the intended product of hashing, and can be used to implement 19| |// hash tables, checksumming, and other common uses of hashes. It is not an 20| |// integer type (although it can be converted to one) because it is risky 21| |// to assume much about the internals of a hash_code. In particular, each 22| |// execution of the program has a high probability of producing a different 23| |// hash_code for a given input. Thus their values are not stable to save or 24| |// persist, and should only be used during the execution for the 25| |// construction of hashing datastructures. 26| |// 27| |// -- 'hash_value' is a function designed to be overloaded for each 28| |// user-defined type which wishes to be used within a hashing context. It 29| |// should be overloaded within the user-defined type's namespace and found 30| |// via ADL. Overloads for primitive types are provided by this library. 31| |// 32| |// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid 33| |// programmers in easily and intuitively combining a set of data into 34| |// a single hash_code for their object. They should only logically be used 35| |// within the implementation of a 'hash_value' routine or similar context. 36| |// 37| |// Note that 'hash_combine_range' contains very special logic for hashing 38| |// a contiguous array of integers or pointers. This logic is *extremely* fast, 39| |// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were 40| |// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys 41| |// under 32-bytes. 42| |// 43| |//===----------------------------------------------------------------------===// 44| | 45| |#ifndef LLVM_ADT_HASHING_H 46| |#define LLVM_ADT_HASHING_H 47| | 48| |#include "llvm/Support/DataTypes.h" 49| |#include "llvm/Support/Host.h" 50| |#include "llvm/Support/SwapByteOrder.h" 51| |#include "llvm/Support/type_traits.h" 52| |#include 53| |#include 54| |#include 55| |#include 56| |#include 57| | 58| |namespace llvm { 59| | 60| |/// \brief An opaque object representing a hash code. 61| |/// 62| |/// This object represents the result of hashing some entity. It is intended to 63| |/// be used to implement hashtables or other hashing-based data structures. 64| |/// While it wraps and exposes a numeric value, this value should not be 65| |/// trusted to be stable or predictable across processes or executions. 66| |/// 67| |/// In order to obtain the hash_code for an object 'x': 68| |/// \code 69| |/// using llvm::hash_value; 70| |/// llvm::hash_code code = hash_value(x); 71| |/// \endcode 72| |class hash_code { 73| | size_t value; 74| | 75| |public: 76| | /// \brief Default construct a hash_code. 77| | /// Note that this leaves the value uninitialized. 78| 0| hash_code() {} 79| | 80| | /// \brief Form a hash code directly from a numerical value. 81| 0| hash_code(size_t value) : value(value) {} 82| | 83| | /// \brief Convert the hash code to its numerical value for use. 84| 0| /*explicit*/ operator size_t() const { return value; } 85| | 86| 0| friend bool operator==(const hash_code &lhs, const hash_code &rhs) { 87| 0| return lhs.value == rhs.value; 88| 0| } 89| 0| friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { 90| 0| return lhs.value != rhs.value; 91| 0| } 92| | 93| | /// \brief Allow a hash_code to be directly run through hash_value. 94| | friend size_t hash_value(const hash_code &code) { return code.value; } 95| |}; 96| | 97| |/// \brief Compute a hash_code for any integer value. 98| |/// 99| |/// Note that this function is intended to compute the same hash_code for 100| |/// a particular value without regard to the pre-promotion type. This is in 101| |/// contrast to hash_combine which may produce different hash_codes for 102| |/// differing argument types even if they would implicit promote to a common 103| |/// type without changing the value. 104| |template 105| |typename std::enable_if::value, hash_code>::type 106| |hash_value(T value); 107| | 108| |/// \brief Compute a hash_code for a pointer's address. 109| |/// 110| |/// N.B.: This hashes the *address*. Not the value and not the type. 111| |template hash_code hash_value(const T *ptr); 112| | 113| |/// \brief Compute a hash_code for a pair of objects. 114| |template 115| |hash_code hash_value(const std::pair &arg); 116| | 117| |/// \brief Compute a hash_code for a standard string. 118| |template 119| |hash_code hash_value(const std::basic_string &arg); 120| | 121| | 122| |/// \brief Override the execution seed with a fixed value. 123| |/// 124| |/// This hashing library uses a per-execution seed designed to change on each 125| |/// run with high probability in order to ensure that the hash codes are not 126| |/// attackable and to ensure that output which is intended to be stable does 127| |/// not rely on the particulars of the hash codes produced. 128| |/// 129| |/// That said, there are use cases where it is important to be able to 130| |/// reproduce *exactly* a specific behavior. To that end, we provide a function 131| |/// which will forcibly set the seed to a fixed value. This must be done at the 132| |/// start of the program, before any hashes are computed. Also, it cannot be 133| |/// undone. This makes it thread-hostile and very hard to use outside of 134| |/// immediately on start of a simple program designed for reproducible 135| |/// behavior. 136| |void set_fixed_execution_hash_seed(size_t fixed_value); 137| | 138| | 139| |// All of the implementation details of actually computing the various hash 140| |// code values are held within this namespace. These routines are included in 141| |// the header file mainly to allow inlining and constant propagation. 142| |namespace hashing { 143| |namespace detail { 144| | 145| |inline uint64_t fetch64(const char *p) { 146| | uint64_t result; 147| | memcpy(&result, p, sizeof(result)); 148| | if (sys::IsBigEndianHost) 149| | sys::swapByteOrder(result); 150| | return result; 151| |} 152| | 153| |inline uint32_t fetch32(const char *p) { 154| | uint32_t result; 155| | memcpy(&result, p, sizeof(result)); 156| | if (sys::IsBigEndianHost) 157| | sys::swapByteOrder(result); 158| | return result; 159| |} 160| | 161| |/// Some primes between 2^63 and 2^64 for various uses. 162| |static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; 163| |static const uint64_t k1 = 0xb492b66fbe98f273ULL; 164| |static const uint64_t k2 = 0x9ae16a3b2f90404fULL; 165| |static const uint64_t k3 = 0xc949d7c7509e6557ULL; 166| | 167| |/// \brief Bitwise right rotate. 168| |/// Normally this will compile to a single instruction, especially if the 169| |/// shift is a manifest constant. 170| |inline uint64_t rotate(uint64_t val, size_t shift) { 171| | // Avoid shifting by 64: doing so yields an undefined result. 172| | return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); 173| |} 174| | 175| |inline uint64_t shift_mix(uint64_t val) { 176| | return val ^ (val >> 47); 177| |} 178| | 179| |inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { 180| | // Murmur-inspired hashing. 181| | const uint64_t kMul = 0x9ddfea08eb382d69ULL; 182| | uint64_t a = (low ^ high) * kMul; 183| | a ^= (a >> 47); 184| | uint64_t b = (high ^ a) * kMul; 185| | b ^= (b >> 47); 186| | b *= kMul; 187| | return b; 188| |} 189| | 190| |inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { 191| | uint8_t a = s[0]; 192| | uint8_t b = s[len >> 1]; 193| | uint8_t c = s[len - 1]; 194| | uint32_t y = static_cast(a) + (static_cast(b) << 8); 195| | uint32_t z = len + (static_cast(c) << 2); 196| | return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; 197| |} 198| | 199| |inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { 200| | uint64_t a = fetch32(s); 201| | return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); 202| |} 203| | 204| |inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { 205| | uint64_t a = fetch64(s); 206| | uint64_t b = fetch64(s + len - 8); 207| | return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; 208| |} 209| | 210| |inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { 211| | uint64_t a = fetch64(s) * k1; 212| | uint64_t b = fetch64(s + 8); 213| | uint64_t c = fetch64(s + len - 8) * k2; 214| | uint64_t d = fetch64(s + len - 16) * k0; 215| | return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, 216| | a + rotate(b ^ k3, 20) - c + len + seed); 217| |} 218| | 219| |inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { 220| | uint64_t z = fetch64(s + 24); 221| | uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; 222| | uint64_t b = rotate(a + z, 52); 223| | uint64_t c = rotate(a, 37); 224| | a += fetch64(s + 8); 225| | c += rotate(a, 7); 226| | a += fetch64(s + 16); 227| | uint64_t vf = a + z; 228| | uint64_t vs = b + rotate(a, 31) + c; 229| | a = fetch64(s + 16) + fetch64(s + len - 32); 230| | z = fetch64(s + len - 8); 231| | b = rotate(a + z, 52); 232| | c = rotate(a, 37); 233| | a += fetch64(s + len - 24); 234| | c += rotate(a, 7); 235| | a += fetch64(s + len - 16); 236| | uint64_t wf = a + z; 237| | uint64_t ws = b + rotate(a, 31) + c; 238| | uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); 239| | return shift_mix((seed ^ (r * k0)) + vs) * k2; 240| |} 241| | 242| |inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { 243| | if (length >= 4 && length <= 8) 244| | return hash_4to8_bytes(s, length, seed); 245| | if (length > 8 && length <= 16) 246| | return hash_9to16_bytes(s, length, seed); 247| | if (length > 16 && length <= 32) 248| | return hash_17to32_bytes(s, length, seed); 249| | if (length > 32) 250| | return hash_33to64_bytes(s, length, seed); 251| | if (length != 0) 252| | return hash_1to3_bytes(s, length, seed); 253| | 254| | return k2 ^ seed; 255| |} 256| | 257| |/// \brief The intermediate state used during hashing. 258| |/// Currently, the algorithm for computing hash codes is based on CityHash and 259| |/// keeps 56 bytes of arbitrary state. 260| |struct hash_state { 261| | uint64_t h0, h1, h2, h3, h4, h5, h6; 262| | 263| | /// \brief Create a new hash_state structure and initialize it based on the 264| | /// seed and the first 64-byte chunk. 265| | /// This effectively performs the initial mix. 266| | static hash_state create(const char *s, uint64_t seed) { 267| | hash_state state = { 268| | 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), 269| | seed * k1, shift_mix(seed), 0 }; 270| | state.h6 = hash_16_bytes(state.h4, state.h5); 271| | state.mix(s); 272| | return state; 273| | } 274| | 275| | /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' 276| | /// and 'b', including whatever is already in 'a' and 'b'. 277| 0| static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { 278| 0| a += fetch64(s); 279| 0| uint64_t c = fetch64(s + 24); 280| 0| b = rotate(b + a + c, 21); 281| 0| uint64_t d = a; 282| 0| a += fetch64(s + 8) + fetch64(s + 16); 283| 0| b += rotate(a, 44) + d; 284| 0| a += c; 285| 0| } 286| | 287| | /// \brief Mix in a 64-byte buffer of data. 288| | /// We mix all 64 bytes even when the chunk length is smaller, but we 289| | /// record the actual length. 290| 0| void mix(const char *s) { 291| 0| h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; 292| 0| h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; 293| 0| h0 ^= h6; 294| 0| h1 += h3 + fetch64(s + 40); 295| 0| h2 = rotate(h2 + h5, 33) * k1; 296| 0| h3 = h4 * k1; 297| 0| h4 = h0 + h5; 298| 0| mix_32_bytes(s, h3, h4); 299| 0| h5 = h2 + h6; 300| 0| h6 = h1 + fetch64(s + 16); 301| 0| mix_32_bytes(s + 32, h5, h6); 302| 0| std::swap(h2, h0); 303| 0| } 304| | 305| | /// \brief Compute the final 64-bit hash code value based on the current 306| | /// state and the length of bytes hashed. 307| | uint64_t finalize(size_t length) { 308| | return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, 309| | hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); 310| | } 311| |}; 312| | 313| | 314| |/// \brief A global, fixed seed-override variable. 315| |/// 316| |/// This variable can be set using the \see llvm::set_fixed_execution_seed 317| |/// function. See that function for details. Do not, under any circumstances, 318| |/// set or read this variable. 319| |extern size_t fixed_seed_override; 320| | 321| |inline size_t get_execution_seed() { 322| | // FIXME: This needs to be a per-execution seed. This is just a placeholder 323| | // implementation. Switching to a per-execution seed is likely to flush out 324| | // instability bugs and so will happen as its own commit. 325| | // 326| | // However, if there is a fixed seed override set the first time this is 327| | // called, return that instead of the per-execution seed. 328| | const uint64_t seed_prime = 0xff51afd7ed558ccdULL; 329| | static size_t seed = fixed_seed_override ? fixed_seed_override 330| | : (size_t)seed_prime; 331| | return seed; 332| |} 333| | 334| | 335| |/// \brief Trait to indicate whether a type's bits can be hashed directly. 336| |/// 337| |/// A type trait which is true if we want to combine values for hashing by 338| |/// reading the underlying data. It is false if values of this type must 339| |/// first be passed to hash_value, and the resulting hash_codes combined. 340| |// 341| |// FIXME: We want to replace is_integral_or_enum and is_pointer here with 342| |// a predicate which asserts that comparing the underlying storage of two 343| |// values of the type for equality is equivalent to comparing the two values 344| |// for equality. For all the platforms we care about, this holds for integers 345| |// and pointers, but there are platforms where it doesn't and we would like to 346| |// support user-defined types which happen to satisfy this property. 347| |template struct is_hashable_data 348| | : std::integral_constant::value || 349| | std::is_pointer::value) && 350| | 64 % sizeof(T) == 0)> {}; 351| | 352| |// Special case std::pair to detect when both types are viable and when there 353| |// is no alignment-derived padding in the pair. This is a bit of a lie because 354| |// std::pair isn't truly POD, but it's close enough in all reasonable 355| |// implementations for our use case of hashing the underlying data. 356| |template struct is_hashable_data > 357| | : std::integral_constant::value && 358| | is_hashable_data::value && 359| | (sizeof(T) + sizeof(U)) == 360| | sizeof(std::pair))> {}; 361| | 362| |/// \brief Helper to get the hashable data representation for a type. 363| |/// This variant is enabled when the type itself can be used. 364| |template 365| |typename std::enable_if::value, T>::type 366| |get_hashable_data(const T &value) { 367| | return value; 368| |} 369| |/// \brief Helper to get the hashable data representation for a type. 370| |/// This variant is enabled when we must first call hash_value and use the 371| |/// result as our data. 372| |template 373| |typename std::enable_if::value, size_t>::type 374| |get_hashable_data(const T &value) { 375| | using ::llvm::hash_value; 376| | return hash_value(value); 377| |} 378| | 379| |/// \brief Helper to store data from a value into a buffer and advance the 380| |/// pointer into that buffer. 381| |/// 382| |/// This routine first checks whether there is enough space in the provided 383| |/// buffer, and if not immediately returns false. If there is space, it 384| |/// copies the underlying bytes of value into the buffer, advances the 385| |/// buffer_ptr past the copied bytes, and returns true. 386| |template 387| |bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, 388| | size_t offset = 0) { 389| | size_t store_size = sizeof(value) - offset; 390| | if (buffer_ptr + store_size > buffer_end) 391| | return false; 392| | const char *value_data = reinterpret_cast(&value); 393| | memcpy(buffer_ptr, value_data + offset, store_size); 394| | buffer_ptr += store_size; 395| | return true; 396| |} 397| | 398| |/// \brief Implement the combining of integral values into a hash_code. 399| |/// 400| |/// This overload is selected when the value type of the iterator is 401| |/// integral. Rather than computing a hash_code for each object and then 402| |/// combining them, this (as an optimization) directly combines the integers. 403| |template 404| |hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { 405| | const size_t seed = get_execution_seed(); 406| | char buffer[64], *buffer_ptr = buffer; 407| | char *const buffer_end = std::end(buffer); 408| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 409| | get_hashable_data(*first))) 410| | ++first; 411| | if (first == last) 412| | return hash_short(buffer, buffer_ptr - buffer, seed); 413| | assert(buffer_ptr == buffer_end); 414| | 415| | hash_state state = state.create(buffer, seed); 416| | size_t length = 64; 417| | while (first != last) { 418| | // Fill up the buffer. We don't clear it, which re-mixes the last round 419| | // when only a partial 64-byte chunk is left. 420| | buffer_ptr = buffer; 421| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 422| | get_hashable_data(*first))) 423| | ++first; 424| | 425| | // Rotate the buffer if we did a partial fill in order to simulate doing 426| | // a mix of the last 64-bytes. That is how the algorithm works when we 427| | // have a contiguous byte sequence, and we want to emulate that here. 428| | std::rotate(buffer, buffer_ptr, buffer_end); 429| | 430| | // Mix this chunk into the current state. 431| | state.mix(buffer); 432| | length += buffer_ptr - buffer; 433| | }; 434| | 435| | return state.finalize(length); 436| |} 437| | 438| |/// \brief Implement the combining of integral values into a hash_code. 439| |/// 440| |/// This overload is selected when the value type of the iterator is integral 441| |/// and when the input iterator is actually a pointer. Rather than computing 442| |/// a hash_code for each object and then combining them, this (as an 443| |/// optimization) directly combines the integers. Also, because the integers 444| |/// are stored in contiguous memory, this routine avoids copying each value 445| |/// and directly reads from the underlying memory. 446| |template 447| |typename std::enable_if::value, hash_code>::type 448| |hash_combine_range_impl(ValueT *first, ValueT *last) { 449| | const size_t seed = get_execution_seed(); 450| | const char *s_begin = reinterpret_cast(first); 451| | const char *s_end = reinterpret_cast(last); 452| | const size_t length = std::distance(s_begin, s_end); 453| | if (length <= 64) 454| | return hash_short(s_begin, length, seed); 455| | 456| | const char *s_aligned_end = s_begin + (length & ~63); 457| | hash_state state = state.create(s_begin, seed); 458| | s_begin += 64; 459| | while (s_begin != s_aligned_end) { 460| | state.mix(s_begin); 461| | s_begin += 64; 462| | } 463| | if (length & 63) 464| | state.mix(s_end - 64); 465| | 466| | return state.finalize(length); 467| |} 468| | 469| |} // namespace detail 470| |} // namespace hashing 471| | 472| | 473| |/// \brief Compute a hash_code for a sequence of values. 474| |/// 475| |/// This hashes a sequence of values. It produces the same hash_code as 476| |/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences 477| |/// and is significantly faster given pointers and types which can be hashed as 478| |/// a sequence of bytes. 479| |template 480| |hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { 481| | return ::llvm::hashing::detail::hash_combine_range_impl(first, last); 482| |} 483| | 484| | 485| |// Implementation details for hash_combine. 486| |namespace hashing { 487| |namespace detail { 488| | 489| |/// \brief Helper class to manage the recursive combining of hash_combine 490| |/// arguments. 491| |/// 492| |/// This class exists to manage the state and various calls involved in the 493| |/// recursive combining of arguments used in hash_combine. It is particularly 494| |/// useful at minimizing the code in the recursive calls to ease the pain 495| |/// caused by a lack of variadic functions. 496| |struct hash_combine_recursive_helper { 497| | char buffer[64]; 498| | hash_state state; 499| | const size_t seed; 500| | 501| |public: 502| | /// \brief Construct a recursive hash combining helper. 503| | /// 504| | /// This sets up the state for a recursive hash combine, including getting 505| | /// the seed and buffer setup. 506| | hash_combine_recursive_helper() 507| 0| : seed(get_execution_seed()) {} 508| | 509| | /// \brief Combine one chunk of data into the current in-flight hash. 510| | /// 511| | /// This merges one chunk of data into the hash. First it tries to buffer 512| | /// the data. If the buffer is full, it hashes the buffer into its 513| | /// hash_state, empties it, and then merges the new chunk in. This also 514| | /// handles cases where the data straddles the end of the buffer. 515| | template 516| | char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { 517| | if (!store_and_advance(buffer_ptr, buffer_end, data)) { 518| | // Check for skew which prevents the buffer from being packed, and do 519| | // a partial store into the buffer to fill it. This is only a concern 520| | // with the variadic combine because that formation can have varying 521| | // argument types. 522| | size_t partial_store_size = buffer_end - buffer_ptr; 523| | memcpy(buffer_ptr, &data, partial_store_size); 524| | 525| | // If the store fails, our buffer is full and ready to hash. We have to 526| | // either initialize the hash state (on the first full buffer) or mix 527| | // this buffer into the existing hash state. Length tracks the *hashed* 528| | // length, not the buffered length. 529| | if (length == 0) { 530| | state = state.create(buffer, seed); 531| | length = 64; 532| | } else { 533| | // Mix this chunk into the current state and bump length up by 64. 534| | state.mix(buffer); 535| | length += 64; 536| | } 537| | // Reset the buffer_ptr to the head of the buffer for the next chunk of 538| | // data. 539| | buffer_ptr = buffer; 540| | 541| | // Try again to store into the buffer -- this cannot fail as we only 542| | // store types smaller than the buffer. 543| | if (!store_and_advance(buffer_ptr, buffer_end, data, 544| | partial_store_size)) 545| | abort(); 546| | } 547| | return buffer_ptr; 548| | } 549| | 550| | /// \brief Recursive, variadic combining method. 551| | /// 552| | /// This function recurses through each argument, combining that argument 553| | /// into a single hash. 554| | template 555| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, 556| | const T &arg, const Ts &...args) { 557| | buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); 558| | 559| | // Recurse to the next argument. 560| | return combine(length, buffer_ptr, buffer_end, args...); 561| | } 562| | 563| | /// \brief Base case for recursive, variadic combining. 564| | /// 565| | /// The base case when combining arguments recursively is reached when all 566| | /// arguments have been handled. It flushes the remaining buffer and 567| | /// constructs a hash_code. 568| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { 569| | // Check whether the entire set of values fit in the buffer. If so, we'll 570| | // use the optimized short hashing routine and skip state entirely. 571| | if (length == 0) 572| | return hash_short(buffer, buffer_ptr - buffer, seed); 573| | 574| | // Mix the final buffer, rotating it if we did a partial fill in order to 575| | // simulate doing a mix of the last 64-bytes. That is how the algorithm 576| | // works when we have a contiguous byte sequence, and we want to emulate 577| | // that here. 578| | std::rotate(buffer, buffer_ptr, buffer_end); 579| | 580| | // Mix this chunk into the current state. 581| | state.mix(buffer); 582| | length += buffer_ptr - buffer; 583| | 584| | return state.finalize(length); 585| | } 586| |}; 587| | 588| |} // namespace detail 589| |} // namespace hashing 590| | 591| |/// \brief Combine values into a single hash_code. 592| |/// 593| |/// This routine accepts a varying number of arguments of any type. It will 594| |/// attempt to combine them into a single hash_code. For user-defined types it 595| |/// attempts to call a \see hash_value overload (via ADL) for the type. For 596| |/// integer and pointer types it directly combines their data into the 597| |/// resulting hash_code. 598| |/// 599| |/// The result is suitable for returning from a user's hash_value 600| |/// *implementation* for their user-defined type. Consumers of a type should 601| |/// *not* call this routine, they should instead call 'hash_value'. 602| |template hash_code hash_combine(const Ts &...args) { 603| | // Recursively hash each argument using a helper class. 604| | ::llvm::hashing::detail::hash_combine_recursive_helper helper; 605| | return helper.combine(0, helper.buffer, helper.buffer + 64, args...); 606| |} 607| | 608| |// Implementation details for implementations of hash_value overloads provided 609| |// here. 610| |namespace hashing { 611| |namespace detail { 612| | 613| |/// \brief Helper to hash the value of a single integer. 614| |/// 615| |/// Overloads for smaller integer types are not provided to ensure consistent 616| |/// behavior in the presence of integral promotions. Essentially, 617| |/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. 618| 0|inline hash_code hash_integer_value(uint64_t value) { 619| 0| // Similar to hash_4to8_bytes but using a seed instead of length. 620| 0| const uint64_t seed = get_execution_seed(); 621| 0| const char *s = reinterpret_cast(&value); 622| 0| const uint64_t a = fetch32(s); 623| 0| return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); 624| 0|} 625| | 626| |} // namespace detail 627| |} // namespace hashing 628| | 629| |// Declared and documented above, but defined here so that any of the hashing 630| |// infrastructure is available. 631| |template 632| |typename std::enable_if::value, hash_code>::type 633| |hash_value(T value) { 634| | return ::llvm::hashing::detail::hash_integer_value(value); 635| |} 636| | 637| |// Declared and documented above, but defined here so that any of the hashing 638| |// infrastructure is available. 639| |template hash_code hash_value(const T *ptr) { 640| | return ::llvm::hashing::detail::hash_integer_value( 641| | reinterpret_cast(ptr)); 642| |} 643| | 644| |// Declared and documented above, but defined here so that any of the hashing 645| |// infrastructure is available. 646| |template 647| |hash_code hash_value(const std::pair &arg) { 648| | return hash_combine(arg.first, arg.second); 649| |} 650| | 651| |// Declared and documented above, but defined here so that any of the hashing 652| |// infrastructure is available. 653| |template 654| |hash_code hash_value(const std::basic_string &arg) { 655| | return hash_combine_range(arg.begin(), arg.end()); 656| |} 657| | 658| |} // namespace llvm 659| | 660| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/IntrusiveRefCntPtr.h: 1| |//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines IntrusiveRefCntPtr, a template class that 11| |// implements a "smart" pointer for objects that maintain their own 12| |// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 13| |// generic base classes for objects that wish to have their lifetimes 14| |// managed using reference counting. 15| |// 16| |// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 17| |// LLVM-style casting. 18| |// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H 22| |#define LLVM_ADT_INTRUSIVEREFCNTPTR_H 23| | 24| |#include "llvm/Support/Casting.h" 25| |#include "llvm/Support/Compiler.h" 26| |#include 27| |#include 28| | 29| |namespace llvm { 30| | 31| | template 32| | class IntrusiveRefCntPtr; 33| | 34| |//===----------------------------------------------------------------------===// 35| |/// RefCountedBase - A generic base class for objects that wish to 36| |/// have their lifetimes managed using reference counts. Classes 37| |/// subclass RefCountedBase to obtain such functionality, and are 38| |/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 39| |/// which automatically handle the management of reference counts. 40| |/// Objects that subclass RefCountedBase should not be allocated on 41| |/// the stack, as invoking "delete" (which is called when the 42| |/// reference count hits 0) on such objects is an error. 43| |//===----------------------------------------------------------------------===// 44| | template 45| | class RefCountedBase { 46| | mutable unsigned ref_cnt; 47| | 48| | public: 49| 0| RefCountedBase() : ref_cnt(0) {} 50| | RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 51| | 52| 0| void Retain() const { ++ref_cnt; } ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail12DirIterStateEE6RetainEv ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail15RecDirIterStateEE6RetainEv ------------------ 53| 0| void Release() const { 54| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 55| 0| if (--ref_cnt == 0) delete static_cast(this); 56| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail12DirIterStateEE7ReleaseEv ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail15RecDirIterStateEE7ReleaseEv ------------------ 57| | }; 58| | 59| |//===----------------------------------------------------------------------===// 60| |/// RefCountedBaseVPTR - A class that has the same function as 61| |/// RefCountedBase, but with a virtual destructor. Should be used 62| |/// instead of RefCountedBase for classes that already have virtual 63| |/// methods to enforce dynamic allocation via 'new'. Classes that 64| |/// inherit from RefCountedBaseVPTR can't be allocated on stack - 65| |/// attempting to do this will produce a compile error. 66| |//===----------------------------------------------------------------------===// 67| | class RefCountedBaseVPTR { 68| | mutable unsigned ref_cnt; 69| | virtual void anchor(); 70| | 71| | protected: 72| 0| RefCountedBaseVPTR() : ref_cnt(0) {} 73| 0| RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 74| | 75| 0| virtual ~RefCountedBaseVPTR() {} 76| | 77| 0| void Retain() const { ++ref_cnt; } 78| 0| void Release() const { 79| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 80| 0| if (--ref_cnt == 0) delete this; 81| 0| } 82| | 83| | template 84| | friend struct IntrusiveRefCntPtrInfo; 85| | }; 86| | 87| | 88| | template struct IntrusiveRefCntPtrInfo { 89| 0| static void retain(T *obj) { obj->Retain(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE6retainEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE6retainEPS4_ ------------------ 90| 0| static void release(T *obj) { obj->Release(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE7releaseEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE7releaseEPS4_ ------------------ 91| | }; 92| | 93| |/// \brief A thread-safe version of \c llvm::RefCountedBase. 94| |/// 95| |/// A generic base class for objects that wish to have their lifetimes managed 96| |/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to 97| |/// obtain such functionality, and are typically handled with 98| |/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the 99| |/// management of reference counts. 100| |template 101| |class ThreadSafeRefCountedBase { 102| | mutable std::atomic RefCount; 103| | 104| |protected: 105| | ThreadSafeRefCountedBase() : RefCount(0) {} 106| | 107| |public: 108| | void Retain() const { ++RefCount; } 109| | 110| | void Release() const { 111| | int NewRefCount = --RefCount; 112| | assert(NewRefCount >= 0 && "Reference count was already zero."); 113| | if (NewRefCount == 0) 114| | delete static_cast(this); 115| | } 116| |}; 117| | 118| |//===----------------------------------------------------------------------===// 119| |/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 120| |/// that assumes the wrapped object has a reference count associated 121| |/// with it that can be managed via calls to 122| |/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 123| |/// manage reference counts via the RAII idiom: upon creation of 124| |/// smart pointer the reference count of the wrapped object is 125| |/// incremented and upon destruction of the smart pointer the 126| |/// reference count is decremented. This class also safely handles 127| |/// wrapping NULL pointers. 128| |/// 129| |/// Reference counting is implemented via calls to 130| |/// Obj->Retain()/Obj->Release(). Release() is required to destroy 131| |/// the object when the reference count reaches zero. Inheriting from 132| |/// RefCountedBase/RefCountedBaseVPTR takes care of this 133| |/// automatically. 134| |//===----------------------------------------------------------------------===// 135| | template 136| | class IntrusiveRefCntPtr { 137| | T* Obj; 138| | 139| | public: 140| | typedef T element_type; 141| | 142| 0| explicit IntrusiveRefCntPtr() : Obj(nullptr) {} 143| | 144| 0| IntrusiveRefCntPtr(T* obj) : Obj(obj) { 145| 0| retain(); 146| 0| } 147| | 148| | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 149| | retain(); 150| | } 151| | 152| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 153| | S.Obj = nullptr; 154| | } 155| | 156| | template 157| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.get()) { 158| | S.Obj = 0; 159| | } 160| | 161| | template 162| | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) 163| | : Obj(S.get()) { 164| | retain(); 165| | } 166| | 167| 0| IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 168| 0| swap(S); 169| 0| return *this; 170| 0| } 171| | 172| 0| ~IntrusiveRefCntPtr() { release(); } 173| | 174| 0| T& operator*() const { return *Obj; } 175| | 176| 0| T* operator->() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEEptEv ------------------ 177| | 178| 0| T* get() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE3getEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE3getEv ------------------ 179| | 180| 0| explicit operator bool() const { return Obj; } ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEEcvbEv ------------------ | Unexecuted instantiation: _ZNK4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEEcvbEv ------------------ 181| | 182| 0| void swap(IntrusiveRefCntPtr& other) { 183| 0| T* tmp = other.Obj; 184| 0| other.Obj = Obj; 185| 0| Obj = tmp; 186| 0| } 187| | 188| 0| void reset() { 189| 0| release(); 190| 0| Obj = nullptr; 191| 0| } 192| | 193| | void resetWithoutRelease() { 194| | Obj = 0; 195| | } 196| | 197| | private: 198| 0| void retain() { if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE6retainEv ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE6retainEv ------------------ 199| 0| void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); } ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail12DirIterStateEE7releaseEv ------------------ | Unexecuted instantiation: _ZN4llvm18IntrusiveRefCntPtrINS_3sys2fs6detail15RecDirIterStateEE7releaseEv ------------------ 200| | 201| | template 202| | friend class IntrusiveRefCntPtr; 203| | }; 204| | 205| | template 206| | inline bool operator==(const IntrusiveRefCntPtr& A, 207| | const IntrusiveRefCntPtr& B) 208| 0| { 209| 0| return A.get() == B.get(); 210| 0| } ------------------ | Unexecuted instantiation: _ZN4llvmeqINS_3sys2fs6detail12DirIterStateES4_EEbRKNS_18IntrusiveRefCntPtrIT_EERKNS5_IT0_EE ------------------ | Unexecuted instantiation: _ZN4llvmeqINS_3sys2fs6detail15RecDirIterStateES4_EEbRKNS_18IntrusiveRefCntPtrIT_EERKNS5_IT0_EE ------------------ 211| | 212| | template 213| | inline bool operator!=(const IntrusiveRefCntPtr& A, 214| | const IntrusiveRefCntPtr& B) 215| | { 216| | return A.get() != B.get(); 217| | } 218| | 219| | template 220| | inline bool operator==(const IntrusiveRefCntPtr& A, 221| | U* B) 222| | { 223| | return A.get() == B; 224| | } 225| | 226| | template 227| | inline bool operator!=(const IntrusiveRefCntPtr& A, 228| | U* B) 229| | { 230| | return A.get() != B; 231| | } 232| | 233| | template 234| | inline bool operator==(T* A, 235| | const IntrusiveRefCntPtr& B) 236| | { 237| | return A == B.get(); 238| | } 239| | 240| | template 241| | inline bool operator!=(T* A, 242| | const IntrusiveRefCntPtr& B) 243| | { 244| | return A != B.get(); 245| | } 246| | 247| | template 248| | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 249| | return !B; 250| | } 251| | 252| | template 253| | bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 254| | return B == A; 255| | } 256| | 257| | template 258| | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 259| | return !(A == B); 260| | } 261| | 262| | template 263| | bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 264| | return !(A == B); 265| | } 266| | 267| |//===----------------------------------------------------------------------===// 268| |// LLVM-style downcasting support for IntrusiveRefCntPtr objects 269| |//===----------------------------------------------------------------------===// 270| | 271| | template struct simplify_type > { 272| | typedef T* SimpleType; 273| | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr& Val) { 274| | return Val.get(); 275| | } 276| | }; 277| | 278| | template struct simplify_type > { 279| | typedef /*const*/ T* SimpleType; 280| | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { 281| | return Val.get(); 282| | } 283| | }; 284| | 285| |} // end namespace llvm 286| | 287| |#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Optional.h: 1| |//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides Optional, a template class modeled in the spirit of 11| |// OCaml's 'opt' variant. The idea is to strongly type whether or not 12| |// a value can be optional. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_ADT_OPTIONAL_H 17| |#define LLVM_ADT_OPTIONAL_H 18| | 19| |#include "llvm/ADT/None.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include "llvm/Support/Compiler.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |template 30| |class Optional { 31| | AlignedCharArrayUnion storage; 32| | bool hasVal; 33| |public: 34| | typedef T value_type; 35| | 36| | Optional(NoneType) : hasVal(false) {} 37| | explicit Optional() : hasVal(false) {} 38| | Optional(const T &y) : hasVal(true) { 39| | new (storage.buffer) T(y); 40| | } 41| 0| Optional(const Optional &O) : hasVal(O.hasVal) { 42| 0| if (hasVal) 43| 0| new (storage.buffer) T(*O); 44| 0| } 45| | 46| 0| Optional(T &&y) : hasVal(true) { 47| 0| new (storage.buffer) T(std::forward(y)); 48| 0| } 49| 0| Optional(Optional &&O) : hasVal(O) { 50| 0| if (O) { 51| 0| new (storage.buffer) T(std::move(*O)); 52| 0| O.reset(); 53| 0| } 54| 0| } 55| | Optional &operator=(T &&y) { 56| | if (hasVal) 57| | **this = std::move(y); 58| | else { 59| | new (storage.buffer) T(std::move(y)); 60| | hasVal = true; 61| | } 62| | return *this; 63| | } 64| | Optional &operator=(Optional &&O) { 65| | if (!O) 66| | reset(); 67| | else { 68| | *this = std::move(*O); 69| | O.reset(); 70| | } 71| | return *this; 72| | } 73| | 74| | /// Create a new object by constructing it in place with the given arguments. 75| | template 76| | void emplace(ArgTypes &&...Args) { 77| | reset(); 78| | hasVal = true; 79| | new (storage.buffer) T(std::forward(Args)...); 80| | } 81| | 82| | static inline Optional create(const T* y) { 83| | return y ? Optional(*y) : Optional(); 84| | } 85| | 86| | // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 87| | // could be made more efficient by passing by value, possibly unifying them 88| | // with the rvalue versions above - but this could place a different set of 89| | // requirements (notably: the existence of a default ctor) when implemented 90| | // in that way. Careful SFINAE to avoid such pitfalls would be required. 91| | Optional &operator=(const T &y) { 92| | if (hasVal) 93| | **this = y; 94| | else { 95| | new (storage.buffer) T(y); 96| | hasVal = true; 97| | } 98| | return *this; 99| | } 100| | 101| | Optional &operator=(const Optional &O) { 102| | if (!O) 103| | reset(); 104| | else 105| | *this = *O; 106| | return *this; 107| | } 108| | 109| 0| void reset() { 110| 0| if (hasVal) { 111| 0| (**this).~T(); 112| 0| hasVal = false; 113| 0| } 114| 0| } 115| | 116| 0| ~Optional() { 117| 0| reset(); 118| 0| } 119| | 120| 0| const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); } 121| 0| T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); } 122| | const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 123| 0| T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 124| | 125| 0| explicit operator bool() const { return hasVal; } 126| 0| bool hasValue() const { return hasVal; } 127| | const T* operator->() const { return getPointer(); } 128| | T* operator->() { return getPointer(); } 129| 0| const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 130| 0| T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 131| | 132| | template 133| | LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { 134| | return hasValue() ? getValue() : std::forward(value); 135| | } 136| | 137| 0| void unwrapIn(std::function fn) { 138| 0| if (hasValue()) 139| 0| fn(getValue()); 140| 0| } 141| | void unwrapIn(std::function fn) const { 142| | if (hasValue()) 143| | fn(getValue()); 144| | } 145| | 146| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 147| | T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 148| | T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 149| | 150| | template 151| | T getValueOr(U &&value) && { 152| | return hasValue() ? std::move(getValue()) : std::forward(value); 153| | } 154| |#endif 155| |}; 156| | 157| |template struct isPodLike; 158| |template struct isPodLike > { 159| | // An Optional is pod-like if T is. 160| | static const bool value = isPodLike::value; 161| |}; 162| | 163| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 164| |/// explicitly compare the underlying values and account for empty \c Optional 165| |/// objects. 166| |/// 167| |/// This routine will never be defined. It returns \c void to help diagnose 168| |/// errors at compile time. 169| |template 170| |void operator==(const Optional &X, const Optional &Y); 171| | 172| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 173| |/// explicitly compare the underlying values and account for empty \c Optional 174| |/// objects. 175| |/// 176| |/// This routine will never be defined. It returns \c void to help diagnose 177| |/// errors at compile time. 178| |template 179| |void operator!=(const Optional &X, const Optional &Y); 180| | 181| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 182| |/// explicitly compare the underlying values and account for empty \c Optional 183| |/// objects. 184| |/// 185| |/// This routine will never be defined. It returns \c void to help diagnose 186| |/// errors at compile time. 187| |template 188| |void operator<(const Optional &X, const Optional &Y); 189| | 190| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 191| |/// explicitly compare the underlying values and account for empty \c Optional 192| |/// objects. 193| |/// 194| |/// This routine will never be defined. It returns \c void to help diagnose 195| |/// errors at compile time. 196| |template 197| |void operator<=(const Optional &X, const Optional &Y); 198| | 199| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 200| |/// explicitly compare the underlying values and account for empty \c Optional 201| |/// objects. 202| |/// 203| |/// This routine will never be defined. It returns \c void to help diagnose 204| |/// errors at compile time. 205| |template 206| |void operator>=(const Optional &X, const Optional &Y); 207| | 208| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 209| |/// explicitly compare the underlying values and account for empty \c Optional 210| |/// objects. 211| |/// 212| |/// This routine will never be defined. It returns \c void to help diagnose 213| |/// errors at compile time. 214| |template 215| |void operator>(const Optional &X, const Optional &Y); 216| | 217| |} // end llvm namespace 218| | 219| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/STLExtras.h: 1| |//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some templates that are useful if you are working with the 11| |// STL at all. 12| |// 13| |// No library is required when using these functions. 14| |// 15| |//===----------------------------------------------------------------------===// 16| | 17| |#ifndef LLVM_ADT_STLEXTRAS_H 18| |#define LLVM_ADT_STLEXTRAS_H 19| | 20| |#include "llvm/Support/Compiler.h" 21| |#include 22| |#include // for std::size_t 23| |#include // for qsort 24| |#include 25| |#include 26| |#include 27| |#include // for std::pair 28| | 29| |namespace llvm { 30| | 31| |//===----------------------------------------------------------------------===// 32| |// Extra additions to 33| |//===----------------------------------------------------------------------===// 34| | 35| |template 36| |struct identity : public std::unary_function { 37| | Ty &operator()(Ty &self) const { 38| | return self; 39| | } 40| | const Ty &operator()(const Ty &self) const { 41| | return self; 42| | } 43| |}; 44| | 45| |template 46| |struct less_ptr : public std::binary_function { 47| | bool operator()(const Ty* left, const Ty* right) const { 48| | return *left < *right; 49| | } 50| |}; 51| | 52| |template 53| |struct greater_ptr : public std::binary_function { 54| | bool operator()(const Ty* left, const Ty* right) const { 55| | return *right < *left; 56| | } 57| |}; 58| | 59| |/// An efficient, type-erasing, non-owning reference to a callable. This is 60| |/// intended for use as the type of a function parameter that is not used 61| |/// after the function in question returns. 62| |/// 63| |/// This class does not own the callable, so it is not in general safe to store 64| |/// a function_ref. 65| |template class function_ref; 66| | 67| |template 68| |class function_ref { 69| | Ret (*callback)(intptr_t callable, Params ...params); 70| | intptr_t callable; 71| | 72| | template 73| | static Ret callback_fn(intptr_t callable, Params ...params) { 74| | return (*reinterpret_cast(callable))( 75| | std::forward(params)...); 76| | } 77| | 78| |public: 79| | template 80| | function_ref(Callable &&callable, 81| | typename std::enable_if< 82| | !std::is_same::type, 83| | function_ref>::value>::type * = nullptr) 84| | : callback(callback_fn::type>), 85| | callable(reinterpret_cast(&callable)) {} 86| | Ret operator()(Params ...params) const { 87| | return callback(callable, std::forward(params)...); 88| | } 89| |}; 90| | 91| |// deleter - Very very very simple method that is used to invoke operator 92| |// delete on something. It is used like this: 93| |// 94| |// for_each(V.begin(), B.end(), deleter); 95| |// 96| |template 97| |inline void deleter(T *Ptr) { 98| | delete Ptr; 99| |} 100| | 101| | 102| | 103| |//===----------------------------------------------------------------------===// 104| |// Extra additions to 105| |//===----------------------------------------------------------------------===// 106| | 107| |// mapped_iterator - This is a simple iterator adapter that causes a function to 108| |// be dereferenced whenever operator* is invoked on the iterator. 109| |// 110| |template 111| |class mapped_iterator { 112| | RootIt current; 113| | UnaryFunc Fn; 114| |public: 115| | typedef typename std::iterator_traits::iterator_category 116| | iterator_category; 117| | typedef typename std::iterator_traits::difference_type 118| | difference_type; 119| | typedef typename UnaryFunc::result_type value_type; 120| | 121| | typedef void pointer; 122| | //typedef typename UnaryFunc::result_type *pointer; 123| | typedef void reference; // Can't modify value returned by fn 124| | 125| | typedef RootIt iterator_type; 126| | 127| | inline const RootIt &getCurrent() const { return current; } 128| | inline const UnaryFunc &getFunc() const { return Fn; } 129| | 130| | inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) 131| | : current(I), Fn(F) {} 132| | 133| | inline value_type operator*() const { // All this work to do this 134| | return Fn(*current); // little change 135| | } 136| | 137| | mapped_iterator &operator++() { 138| | ++current; 139| | return *this; 140| | } 141| | mapped_iterator &operator--() { 142| | --current; 143| | return *this; 144| | } 145| | mapped_iterator operator++(int) { 146| | mapped_iterator __tmp = *this; 147| | ++current; 148| | return __tmp; 149| | } 150| | mapped_iterator operator--(int) { 151| | mapped_iterator __tmp = *this; 152| | --current; 153| | return __tmp; 154| | } 155| | mapped_iterator operator+(difference_type n) const { 156| | return mapped_iterator(current + n, Fn); 157| | } 158| | mapped_iterator &operator+=(difference_type n) { 159| | current += n; 160| | return *this; 161| | } 162| | mapped_iterator operator-(difference_type n) const { 163| | return mapped_iterator(current - n, Fn); 164| | } 165| | mapped_iterator &operator-=(difference_type n) { 166| | current -= n; 167| | return *this; 168| | } 169| | reference operator[](difference_type n) const { return *(*this + n); } 170| | 171| | bool operator!=(const mapped_iterator &X) const { return !operator==(X); } 172| | bool operator==(const mapped_iterator &X) const { 173| | return current == X.current; 174| | } 175| | bool operator<(const mapped_iterator &X) const { return current < X.current; } 176| | 177| | difference_type operator-(const mapped_iterator &X) const { 178| | return current - X.current; 179| | } 180| |}; 181| | 182| |template 183| |inline mapped_iterator 184| |operator+(typename mapped_iterator::difference_type N, 185| | const mapped_iterator &X) { 186| | return mapped_iterator(X.getCurrent() - N, X.getFunc()); 187| |} 188| | 189| | 190| |// map_iterator - Provide a convenient way to create mapped_iterators, just like 191| |// make_pair is useful for creating pairs... 192| |// 193| |template 194| |inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { 195| | return mapped_iterator(I, F); 196| |} 197| | 198| |//===----------------------------------------------------------------------===// 199| |// Extra additions to 200| |//===----------------------------------------------------------------------===// 201| | 202| |/// \brief Function object to check whether the first component of a std::pair 203| |/// compares less than the first component of another std::pair. 204| |struct less_first { 205| | template bool operator()(const T &lhs, const T &rhs) const { 206| | return lhs.first < rhs.first; 207| | } 208| |}; 209| | 210| |/// \brief Function object to check whether the second component of a std::pair 211| |/// compares less than the second component of another std::pair. 212| |struct less_second { 213| | template bool operator()(const T &lhs, const T &rhs) const { 214| | return lhs.second < rhs.second; 215| | } 216| |}; 217| | 218| |// A subset of N3658. More stuff can be added as-needed. 219| | 220| |/// \brief Represents a compile-time sequence of integers. 221| |template struct integer_sequence { 222| | typedef T value_type; 223| | 224| | static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } 225| |}; 226| | 227| |/// \brief Alias for the common case of a sequence of size_ts. 228| |template 229| |struct index_sequence : integer_sequence {}; 230| | 231| |template 232| |struct build_index_impl : build_index_impl {}; 233| |template 234| |struct build_index_impl<0, I...> : index_sequence {}; 235| | 236| |/// \brief Creates a compile-time integer sequence for a parameter pack. 237| |template 238| |struct index_sequence_for : build_index_impl {}; 239| | 240| |//===----------------------------------------------------------------------===// 241| |// Extra additions for arrays 242| |//===----------------------------------------------------------------------===// 243| | 244| |/// Find the length of an array. 245| |template 246| |LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { 247| | return N; 248| |} 249| | 250| |/// Adapt std::less for array_pod_sort. 251| |template 252| |inline int array_pod_sort_comparator(const void *P1, const void *P2) { 253| | if (std::less()(*reinterpret_cast(P1), 254| | *reinterpret_cast(P2))) 255| | return -1; 256| | if (std::less()(*reinterpret_cast(P2), 257| | *reinterpret_cast(P1))) 258| | return 1; 259| | return 0; 260| |} 261| | 262| |/// get_array_pod_sort_comparator - This is an internal helper function used to 263| |/// get type deduction of T right. 264| |template 265| |inline int (*get_array_pod_sort_comparator(const T &)) 266| | (const void*, const void*) { 267| | return array_pod_sort_comparator; 268| |} 269| | 270| | 271| |/// array_pod_sort - This sorts an array with the specified start and end 272| |/// extent. This is just like std::sort, except that it calls qsort instead of 273| |/// using an inlined template. qsort is slightly slower than std::sort, but 274| |/// most sorts are not performance critical in LLVM and std::sort has to be 275| |/// template instantiated for each type, leading to significant measured code 276| |/// bloat. This function should generally be used instead of std::sort where 277| |/// possible. 278| |/// 279| |/// This function assumes that you have simple POD-like types that can be 280| |/// compared with std::less and can be moved with memcpy. If this isn't true, 281| |/// you should use std::sort. 282| |/// 283| |/// NOTE: If qsort_r were portable, we could allow a custom comparator and 284| |/// default to std::less. 285| |template 286| |inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 287| | // Don't inefficiently call qsort with one element or trigger undefined 288| | // behavior with an empty sequence. 289| | auto NElts = End - Start; 290| | if (NElts <= 1) return; 291| | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 292| |} 293| | 294| |template 295| |inline void array_pod_sort( 296| | IteratorTy Start, IteratorTy End, 297| | int (*Compare)( 298| | const typename std::iterator_traits::value_type *, 299| | const typename std::iterator_traits::value_type *)) { 300| | // Don't inefficiently call qsort with one element or trigger undefined 301| | // behavior with an empty sequence. 302| | auto NElts = End - Start; 303| | if (NElts <= 1) return; 304| | qsort(&*Start, NElts, sizeof(*Start), 305| | reinterpret_cast(Compare)); 306| |} 307| | 308| |//===----------------------------------------------------------------------===// 309| |// Extra additions to 310| |//===----------------------------------------------------------------------===// 311| | 312| |/// For a container of pointers, deletes the pointers and then clears the 313| |/// container. 314| |template 315| |void DeleteContainerPointers(Container &C) { 316| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 317| | delete *I; 318| | C.clear(); 319| |} 320| | 321| |/// In a container of pairs (usually a map) whose second element is a pointer, 322| |/// deletes the second elements and then clears the container. 323| |template 324| |void DeleteContainerSeconds(Container &C) { 325| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 326| | delete I->second; 327| | C.clear(); 328| |} 329| | 330| |//===----------------------------------------------------------------------===// 331| |// Extra additions to 332| |//===----------------------------------------------------------------------===// 333| | 334| |// Implement make_unique according to N3656. 335| | 336| |/// \brief Constructs a `new T()` with the given args and returns a 337| |/// `unique_ptr` which owns the object. 338| |/// 339| |/// Example: 340| |/// 341| |/// auto p = make_unique(); 342| |/// auto p = make_unique>(0, 1); 343| |template 344| |typename std::enable_if::value, std::unique_ptr>::type 345| 0|make_unique(Args &&... args) { 346| 0| return std::unique_ptr(new T(std::forward(args)...)); 347| 0|} ------------------ | Unexecuted instantiation: FileSystem.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_115LocalFileSystemEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild5basic24DeviceAgnosticFileSystemEJNSt3__110unique_ptrINS2_10FileSystemENS4_14default_deleteIS6_EEEEEEENS4_9enable_ifIXntsr3std8is_arrayIT_EE5valueENS5_ISB_NS7_ISB_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: LaneBasedExecutionQueue.cpp:_ZN4llvm11make_uniqueINSt3__16threadEJMN12_GLOBAL__N_123LaneBasedExecutionQueueEFvvEPS4_EEENS1_9enable_ifIXntsr3std8is_arrayIT_EE5valueENS1_10unique_ptrIS9_NS1_14default_deleteIS9_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: SerialQueue.cpp:_ZN4llvm11make_uniqueINSt3__16threadEJMN12_GLOBAL__N_115SerialQueueImplEFvvEPS4_EEENS1_9enable_ifIXntsr3std8is_arrayIT_EE5valueENS1_10unique_ptrIS9_NS1_14default_deleteIS9_EEEEE4typeEDpOT0_ ------------------ 348| | 349| |/// \brief Constructs a `new T[n]` with the given args and returns a 350| |/// `unique_ptr` which owns the object. 351| |/// 352| |/// \param n size of the new array. 353| |/// 354| |/// Example: 355| |/// 356| |/// auto p = make_unique(2); // value-initializes the array with 0's. 357| |template 358| |typename std::enable_if::value && std::extent::value == 0, 359| | std::unique_ptr>::type 360| |make_unique(size_t n) { 361| | return std::unique_ptr(new typename std::remove_extent::type[n]()); 362| |} 363| | 364| |/// This function isn't used and is only here to provide better compile errors. 365| |template 366| |typename std::enable_if::value != 0>::type 367| |make_unique(Args &&...) = delete; 368| | 369| |struct FreeDeleter { 370| 0| void operator()(void* v) { 371| 0| ::free(v); 372| 0| } 373| |}; 374| | 375| |template 376| |struct pair_hash { 377| | size_t operator()(const std::pair &P) const { 378| | return std::hash()(P.first) * 31 + std::hash()(P.second); 379| | } 380| |}; 381| | 382| |/// A functor like C++14's std::less in its absence. 383| |struct less { 384| | template bool operator()(A &&a, B &&b) const { 385| | return std::forward(a) < std::forward(b); 386| | } 387| |}; 388| | 389| |/// A functor like C++14's std::equal in its absence. 390| |struct equal { 391| | template bool operator()(A &&a, B &&b) const { 392| | return std::forward(a) == std::forward(b); 393| | } 394| |}; 395| | 396| |/// Binary functor that adapts to any other binary functor after dereferencing 397| |/// operands. 398| |template struct deref { 399| | T func; 400| | // Could be further improved to cope with non-derivable functors and 401| | // non-binary functors (should be a variadic template member function 402| | // operator()). 403| | template 404| | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { 405| | assert(lhs); 406| | assert(rhs); 407| | return func(*lhs, *rhs); 408| | } 409| |}; 410| | 411| |} // End llvm namespace 412| | 413| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallString.h: 1| |//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallString class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLSTRING_H 15| |#define LLVM_ADT_SMALLSTRING_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |namespace llvm { 21| | 22| |/// SmallString - A SmallString is just a SmallVector with methods and accessors 23| |/// that make it work better as a string (e.g. operator+ etc). 24| |template 25| |class SmallString : public SmallVector { 26| |public: 27| | /// Default ctor - Initialize to empty. 28| 0| SmallString() {} ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj64EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj16EEC2Ev ------------------ 29| | 30| | /// Initialize from a StringRef. 31| 0| SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} 32| | 33| | /// Initialize with a range. 34| | template 35| | SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} 36| | 37| | // Note that in order to add new overloads for append & assign, we have to 38| | // duplicate the inherited versions so as not to inadvertently hide them. 39| | 40| | /// @} 41| | /// @name String Assignment 42| | /// @{ 43| | 44| | /// Assign from a repeated element. 45| | void assign(size_t NumElts, char Elt) { 46| | this->SmallVectorImpl::assign(NumElts, Elt); 47| | } 48| | 49| | /// Assign from an iterator pair. 50| | template 51| | void assign(in_iter S, in_iter E) { 52| | this->clear(); 53| | SmallVectorImpl::append(S, E); 54| | } 55| | 56| | /// Assign from a StringRef. 57| | void assign(StringRef RHS) { 58| | this->clear(); 59| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 60| | } 61| | 62| | /// Assign from a SmallVector. 63| | void assign(const SmallVectorImpl &RHS) { 64| | this->clear(); 65| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 66| | } 67| | 68| | /// @} 69| | /// @name String Concatenation 70| | /// @{ 71| | 72| | /// Append from an iterator pair. 73| | template 74| 0| void append(in_iter S, in_iter E) { 75| 0| SmallVectorImpl::append(S, E); 76| 0| } 77| | 78| | void append(size_t NumInputs, char Elt) { 79| | SmallVectorImpl::append(NumInputs, Elt); 80| | } 81| | 82| | 83| | /// Append from a StringRef. 84| | void append(StringRef RHS) { 85| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 86| | } 87| | 88| | /// Append from a SmallVector. 89| | void append(const SmallVectorImpl &RHS) { 90| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 91| | } 92| | 93| | /// @} 94| | /// @name String Comparison 95| | /// @{ 96| | 97| | /// Check for string equality. This is more efficient than compare() when 98| | /// the relative ordering of inequal strings isn't needed. 99| | bool equals(StringRef RHS) const { 100| | return str().equals(RHS); 101| | } 102| | 103| | /// Check for string equality, ignoring case. 104| | bool equals_lower(StringRef RHS) const { 105| | return str().equals_lower(RHS); 106| | } 107| | 108| | /// Compare two strings; the result is -1, 0, or 1 if this string is 109| | /// lexicographically less than, equal to, or greater than the \p RHS. 110| | int compare(StringRef RHS) const { 111| | return str().compare(RHS); 112| | } 113| | 114| | /// compare_lower - Compare two strings, ignoring case. 115| | int compare_lower(StringRef RHS) const { 116| | return str().compare_lower(RHS); 117| | } 118| | 119| | /// compare_numeric - Compare two strings, treating sequences of digits as 120| | /// numbers. 121| | int compare_numeric(StringRef RHS) const { 122| | return str().compare_numeric(RHS); 123| | } 124| | 125| | /// @} 126| | /// @name String Predicates 127| | /// @{ 128| | 129| | /// startswith - Check if this string starts with the given \p Prefix. 130| | bool startswith(StringRef Prefix) const { 131| | return str().startswith(Prefix); 132| | } 133| | 134| | /// endswith - Check if this string ends with the given \p Suffix. 135| | bool endswith(StringRef Suffix) const { 136| | return str().endswith(Suffix); 137| | } 138| | 139| | /// @} 140| | /// @name String Searching 141| | /// @{ 142| | 143| | /// find - Search for the first character \p C in the string. 144| | /// 145| | /// \return - The index of the first occurrence of \p C, or npos if not 146| | /// found. 147| | size_t find(char C, size_t From = 0) const { 148| | return str().find(C, From); 149| | } 150| | 151| | /// Search for the first string \p Str in the string. 152| | /// 153| | /// \returns The index of the first occurrence of \p Str, or npos if not 154| | /// found. 155| | size_t find(StringRef Str, size_t From = 0) const { 156| | return str().find(Str, From); 157| | } 158| | 159| | /// Search for the last character \p C in the string. 160| | /// 161| | /// \returns The index of the last occurrence of \p C, or npos if not 162| | /// found. 163| | size_t rfind(char C, size_t From = StringRef::npos) const { 164| | return str().rfind(C, From); 165| | } 166| | 167| | /// Search for the last string \p Str in the string. 168| | /// 169| | /// \returns The index of the last occurrence of \p Str, or npos if not 170| | /// found. 171| | size_t rfind(StringRef Str) const { 172| | return str().rfind(Str); 173| | } 174| | 175| | /// Find the first character in the string that is \p C, or npos if not 176| | /// found. Same as find. 177| | size_t find_first_of(char C, size_t From = 0) const { 178| | return str().find_first_of(C, From); 179| | } 180| | 181| | /// Find the first character in the string that is in \p Chars, or npos if 182| | /// not found. 183| | /// 184| | /// Complexity: O(size() + Chars.size()) 185| | size_t find_first_of(StringRef Chars, size_t From = 0) const { 186| | return str().find_first_of(Chars, From); 187| | } 188| | 189| | /// Find the first character in the string that is not \p C or npos if not 190| | /// found. 191| | size_t find_first_not_of(char C, size_t From = 0) const { 192| | return str().find_first_not_of(C, From); 193| | } 194| | 195| | /// Find the first character in the string that is not in the string 196| | /// \p Chars, or npos if not found. 197| | /// 198| | /// Complexity: O(size() + Chars.size()) 199| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const { 200| | return str().find_first_not_of(Chars, From); 201| | } 202| | 203| | /// Find the last character in the string that is \p C, or npos if not 204| | /// found. 205| | size_t find_last_of(char C, size_t From = StringRef::npos) const { 206| | return str().find_last_of(C, From); 207| | } 208| | 209| | /// Find the last character in the string that is in \p C, or npos if not 210| | /// found. 211| | /// 212| | /// Complexity: O(size() + Chars.size()) 213| | size_t find_last_of( 214| | StringRef Chars, size_t From = StringRef::npos) const { 215| | return str().find_last_of(Chars, From); 216| | } 217| | 218| | /// @} 219| | /// @name Helpful Algorithms 220| | /// @{ 221| | 222| | /// Return the number of occurrences of \p C in the string. 223| | size_t count(char C) const { 224| | return str().count(C); 225| | } 226| | 227| | /// Return the number of non-overlapped occurrences of \p Str in the 228| | /// string. 229| | size_t count(StringRef Str) const { 230| | return str().count(Str); 231| | } 232| | 233| | /// @} 234| | /// @name Substring Operations 235| | /// @{ 236| | 237| | /// Return a reference to the substring from [Start, Start + N). 238| | /// 239| | /// \param Start The index of the starting character in the substring; if 240| | /// the index is npos or greater than the length of the string then the 241| | /// empty substring will be returned. 242| | /// 243| | /// \param N The number of characters to included in the substring. If \p N 244| | /// exceeds the number of characters remaining in the string, the string 245| | /// suffix (starting with \p Start) will be returned. 246| | StringRef substr(size_t Start, size_t N = StringRef::npos) const { 247| | return str().substr(Start, N); 248| | } 249| | 250| | /// Return a reference to the substring from [Start, End). 251| | /// 252| | /// \param Start The index of the starting character in the substring; if 253| | /// the index is npos or greater than the length of the string then the 254| | /// empty substring will be returned. 255| | /// 256| | /// \param End The index following the last character to include in the 257| | /// substring. If this is npos, or less than \p Start, or exceeds the 258| | /// number of characters remaining in the string, the string suffix 259| | /// (starting with \p Start) will be returned. 260| | StringRef slice(size_t Start, size_t End) const { 261| | return str().slice(Start, End); 262| | } 263| | 264| | // Extra methods. 265| | 266| | /// Explicit conversion to StringRef. 267| 0| StringRef str() const { return StringRef(this->begin(), this->size()); } ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj256EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj64EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj16EE3strEv ------------------ 268| | 269| | // TODO: Make this const, if it's safe... 270| 0| const char* c_str() { 271| 0| this->push_back(0); 272| 0| this->pop_back(); 273| 0| return this->data(); 274| 0| } 275| | 276| | /// Implicit conversion to StringRef. 277| | operator StringRef() const { return str(); } 278| | 279| | // Extra operators. 280| | const SmallString &operator=(StringRef RHS) { 281| | this->clear(); 282| | return *this += RHS; 283| | } 284| | 285| 0| SmallString &operator+=(StringRef RHS) { 286| 0| this->append(RHS.begin(), RHS.end()); 287| 0| return *this; 288| 0| } 289| 0| SmallString &operator+=(char C) { 290| 0| this->push_back(C); 291| 0| return *this; 292| 0| } 293| |}; 294| | 295| |} 296| | 297| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallVector.h: 1| |//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLVECTOR_H 15| |#define LLVM_ADT_SMALLVECTOR_H 16| | 17| |#include "llvm/ADT/iterator_range.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/type_traits.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |namespace llvm { 32| | 33| |/// This is all the non-templated stuff common to all SmallVectors. 34| |class SmallVectorBase { 35| |protected: 36| | void *BeginX, *EndX, *CapacityX; 37| | 38| |protected: 39| | SmallVectorBase(void *FirstEl, size_t Size) 40| 0| : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} 41| | 42| | /// This is an implementation of the grow() method which only works 43| | /// on POD-like data types and is out of line to reduce code duplication. 44| | void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); 45| | 46| |public: 47| | /// This returns size()*sizeof(T). 48| | size_t size_in_bytes() const { 49| | return size_t((char*)EndX - (char*)BeginX); 50| | } 51| | 52| | /// capacity_in_bytes - This returns capacity()*sizeof(T). 53| | size_t capacity_in_bytes() const { 54| | return size_t((char*)CapacityX - (char*)BeginX); 55| | } 56| | 57| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } 58| |}; 59| | 60| |template struct SmallVectorStorage; 61| | 62| |/// This is the part of SmallVectorTemplateBase which does not depend on whether 63| |/// the type T is a POD. The extra dummy template argument is used by ArrayRef 64| |/// to avoid unnecessarily requiring T to be complete. 65| |template 66| |class SmallVectorTemplateCommon : public SmallVectorBase { 67| |private: 68| | template friend struct SmallVectorStorage; 69| | 70| | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 71| | // don't want it to be automatically run, so we need to represent the space as 72| | // something else. Use an array of char of sufficient alignment. 73| | typedef llvm::AlignedCharArrayUnion U; 74| | U FirstEl; 75| | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 76| | 77| |protected: 78| 0| SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} 79| | 80| 0| void grow_pod(size_t MinSizeInBytes, size_t TSize) { 81| 0| SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); 82| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE8grow_podEmm ------------------ 83| | 84| | /// Return true if this is a smallvector which has not had dynamic 85| | /// memory allocated for it. 86| 0| bool isSmall() const { 87| 0| return BeginX == static_cast(&FirstEl); 88| 0| } 89| | 90| | /// Put this vector in a state of being small. 91| | void resetToSmall() { 92| | BeginX = EndX = CapacityX = &FirstEl; 93| | } 94| | 95| 0| void setEnd(T *P) { this->EndX = P; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE6setEndEPc ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE6setEndEPh ------------------ 96| |public: 97| | typedef size_t size_type; 98| | typedef ptrdiff_t difference_type; 99| | typedef T value_type; 100| | typedef T *iterator; 101| | typedef const T *const_iterator; 102| | 103| | typedef std::reverse_iterator const_reverse_iterator; 104| | typedef std::reverse_iterator reverse_iterator; 105| | 106| | typedef T &reference; 107| | typedef const T &const_reference; 108| | typedef T *pointer; 109| | typedef const T *const_pointer; 110| | 111| | // forward iterator creation methods. 112| 0| iterator begin() { return (iterator)this->BeginX; } 113| 0| const_iterator begin() const { return (const_iterator)this->BeginX; } 114| 0| iterator end() { return (iterator)this->EndX; } 115| 0| const_iterator end() const { return (const_iterator)this->EndX; } 116| |protected: 117| 0| iterator capacity_ptr() { return (iterator)this->CapacityX; } 118| | const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} 119| |public: 120| | 121| | // reverse iterator creation methods. 122| | reverse_iterator rbegin() { return reverse_iterator(end()); } 123| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 124| | reverse_iterator rend() { return reverse_iterator(begin()); } 125| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 126| | 127| 0| size_type size() const { return end()-begin(); } 128| | size_type max_size() const { return size_type(-1) / sizeof(T); } 129| | 130| | /// Return the total number of elements in the currently allocated buffer. 131| | size_t capacity() const { return capacity_ptr() - begin(); } 132| | 133| | /// Return a pointer to the vector's buffer, even if empty(). 134| 0| pointer data() { return pointer(begin()); } 135| | /// Return a pointer to the vector's buffer, even if empty(). 136| | const_pointer data() const { return const_pointer(begin()); } 137| | 138| | reference operator[](size_type idx) { 139| | assert(idx < size()); 140| | return begin()[idx]; 141| | } 142| | const_reference operator[](size_type idx) const { 143| | assert(idx < size()); 144| | return begin()[idx]; 145| | } 146| | 147| | reference front() { 148| | assert(!empty()); 149| | return begin()[0]; 150| | } 151| | const_reference front() const { 152| | assert(!empty()); 153| | return begin()[0]; 154| | } 155| | 156| | reference back() { 157| | assert(!empty()); 158| | return end()[-1]; 159| | } 160| | const_reference back() const { 161| | assert(!empty()); 162| | return end()[-1]; 163| | } 164| |}; 165| | 166| |/// SmallVectorTemplateBase - This is where we put method 167| |/// implementations that are designed to work with non-POD-like T's. 168| |template 169| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 170| |protected: 171| | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 172| | 173| | static void destroy_range(T *S, T *E) { 174| | while (S != E) { 175| | --E; 176| | E->~T(); 177| | } 178| | } 179| | 180| | /// Use move-assignment to move the range [I, E) onto the 181| | /// objects starting with "Dest". This is just 's 182| | /// std::move, but not all stdlibs actually provide that. 183| | template 184| | static It2 move(It1 I, It1 E, It2 Dest) { 185| | for (; I != E; ++I, ++Dest) 186| | *Dest = ::std::move(*I); 187| | return Dest; 188| | } 189| | 190| | /// Use move-assignment to move the range 191| | /// [I, E) onto the objects ending at "Dest", moving objects 192| | /// in reverse order. This is just 's 193| | /// std::move_backward, but not all stdlibs actually provide that. 194| | template 195| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 196| | while (I != E) 197| | *--Dest = ::std::move(*--E); 198| | return Dest; 199| | } 200| | 201| | /// Move the range [I, E) into the uninitialized memory starting with "Dest", 202| | /// constructing elements as needed. 203| | template 204| | static void uninitialized_move(It1 I, It1 E, It2 Dest) { 205| | for (; I != E; ++I, ++Dest) 206| | ::new ((void*) &*Dest) T(::std::move(*I)); 207| | } 208| | 209| | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", 210| | /// constructing elements as needed. 211| | template 212| | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 213| | std::uninitialized_copy(I, E, Dest); 214| | } 215| | 216| | /// Grow the allocated memory (without initializing new elements), doubling 217| | /// the size of the allocated memory. Guarantees space for at least one more 218| | /// element, or MinSize more elements if specified. 219| | void grow(size_t MinSize = 0); 220| | 221| |public: 222| | void push_back(const T &Elt) { 223| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 224| | this->grow(); 225| | ::new ((void*) this->end()) T(Elt); 226| | this->setEnd(this->end()+1); 227| | } 228| | 229| | void push_back(T &&Elt) { 230| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 231| | this->grow(); 232| | ::new ((void*) this->end()) T(::std::move(Elt)); 233| | this->setEnd(this->end()+1); 234| | } 235| | 236| | void pop_back() { 237| | this->setEnd(this->end()-1); 238| | this->end()->~T(); 239| | } 240| |}; 241| | 242| |// Define this out-of-line to dissuade the C++ compiler from inlining it. 243| |template 244| |void SmallVectorTemplateBase::grow(size_t MinSize) { 245| | size_t CurCapacity = this->capacity(); 246| | size_t CurSize = this->size(); 247| | // Always grow, even from zero. 248| | size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); 249| | if (NewCapacity < MinSize) 250| | NewCapacity = MinSize; 251| | T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); 252| | 253| | // Move the elements over. 254| | this->uninitialized_move(this->begin(), this->end(), NewElts); 255| | 256| | // Destroy the original elements. 257| | destroy_range(this->begin(), this->end()); 258| | 259| | // If this wasn't grown from the inline copy, deallocate the old space. 260| | if (!this->isSmall()) 261| | free(this->begin()); 262| | 263| | this->setEnd(NewElts+CurSize); 264| | this->BeginX = NewElts; 265| | this->CapacityX = this->begin()+NewCapacity; 266| |} 267| | 268| | 269| |/// SmallVectorTemplateBase - This is where we put method 270| |/// implementations that are designed to work with POD-like T's. 271| |template 272| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 273| |protected: 274| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 275| | 276| | // No need to do a destroy loop for POD's. 277| 0| static void destroy_range(T *, T *) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE13destroy_rangeEPcS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE13destroy_rangeEPhS2_ ------------------ 278| | 279| | /// Use move-assignment to move the range [I, E) onto the 280| | /// objects starting with "Dest". For PODs, this is just memcpy. 281| | template 282| | static It2 move(It1 I, It1 E, It2 Dest) { 283| | return ::std::copy(I, E, Dest); 284| | } 285| | 286| | /// Use move-assignment to move the range [I, E) onto the objects ending at 287| | /// "Dest", moving objects in reverse order. 288| | template 289| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 290| | return ::std::copy_backward(I, E, Dest); 291| | } 292| | 293| | /// Move the range [I, E) onto the uninitialized memory 294| | /// starting with "Dest", constructing elements into it as needed. 295| | template 296| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 297| 0| // Just do a copy. 298| 0| uninitialized_copy(I, E, Dest); 299| 0| } 300| | 301| | /// Copy the range [I, E) onto the uninitialized memory 302| | /// starting with "Dest", constructing elements into it as needed. 303| | template 304| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 305| 0| // Arbitrary iterator types; just use the basic implementation. 306| 0| std::uninitialized_copy(I, E, Dest); 307| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyINSt3__113move_iteratorIPhEES5_EEvT_S7_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIPKcPhEEvT_S6_T0_ ------------------ 308| | 309| | /// Copy the range [I, E) onto the uninitialized memory 310| | /// starting with "Dest", constructing elements into it as needed. 311| | template 312| | static void uninitialized_copy( 313| | T1 *I, T1 *E, T2 *Dest, 314| | typename std::enable_if::type, 315| 0| T2>::value>::type * = nullptr) { 316| 0| // Use memcpy for PODs iterated by pointers (which includes SmallVector 317| 0| // iterators): std::uninitialized_copy optimizes to memmove, but we can 318| 0| // use memcpy here. 319| 0| memcpy(Dest, I, (E-I)*sizeof(T)); 320| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIKccEEvPT_S5_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS8_12remove_constIS4_E4typeES6_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIhhEEvPT_S4_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS7_12remove_constIS3_E4typeES5_EE5valueEvE4typeE ------------------ 321| | 322| | /// Double the size of the allocated memory, guaranteeing space for at 323| | /// least one more element or MinSize if specified. 324| 0| void grow(size_t MinSize = 0) { 325| 0| this->grow_pod(MinSize*sizeof(T), sizeof(T)); 326| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE4growEm ------------------ 327| |public: 328| 0| void push_back(const T &Elt) { 329| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 330| 0| this->grow(); 331| 0| memcpy(this->end(), &Elt, sizeof(T)); 332| 0| this->setEnd(this->end()+1); 333| 0| } 334| | 335| 0| void pop_back() { 336| 0| this->setEnd(this->end()-1); 337| 0| } 338| |}; 339| | 340| | 341| |/// This class consists of common code factored out of the SmallVector class to 342| |/// reduce code duplication based on the SmallVector 'N' template parameter. 343| |template 344| |class SmallVectorImpl : public SmallVectorTemplateBase::value> { 345| | typedef SmallVectorTemplateBase::value > SuperClass; 346| | 347| | SmallVectorImpl(const SmallVectorImpl&) = delete; 348| |public: 349| | typedef typename SuperClass::iterator iterator; 350| | typedef typename SuperClass::size_type size_type; 351| | 352| |protected: 353| | // Default ctor - Initialize to empty. 354| | explicit SmallVectorImpl(unsigned N) 355| 0| : SmallVectorTemplateBase::value>(N*sizeof(T)) { 356| 0| } 357| | 358| |public: 359| 0| ~SmallVectorImpl() { 360| 0| // Destroy the constructed elements in the vector. 361| 0| this->destroy_range(this->begin(), this->end()); 362| 0| 363| 0| // If this wasn't grown from the inline copy, deallocate the old space. 364| 0| if (!this->isSmall()) 365| 0| free(this->begin()); 366| 0| } 367| | 368| | 369| | void clear() { 370| | this->destroy_range(this->begin(), this->end()); 371| | this->EndX = this->BeginX; 372| | } 373| | 374| | void resize(size_type N) { 375| | if (N < this->size()) { 376| | this->destroy_range(this->begin()+N, this->end()); 377| | this->setEnd(this->begin()+N); 378| | } else if (N > this->size()) { 379| | if (this->capacity() < N) 380| | this->grow(N); 381| | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) 382| | new (&*I) T(); 383| | this->setEnd(this->begin()+N); 384| | } 385| | } 386| | 387| | void resize(size_type N, const T &NV) { 388| | if (N < this->size()) { 389| | this->destroy_range(this->begin()+N, this->end()); 390| | this->setEnd(this->begin()+N); 391| | } else if (N > this->size()) { 392| | if (this->capacity() < N) 393| | this->grow(N); 394| | std::uninitialized_fill(this->end(), this->begin()+N, NV); 395| | this->setEnd(this->begin()+N); 396| | } 397| | } 398| | 399| | void reserve(size_type N) { 400| | if (this->capacity() < N) 401| | this->grow(N); 402| | } 403| | 404| | T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { 405| | T Result = ::std::move(this->back()); 406| | this->pop_back(); 407| | return Result; 408| | } 409| | 410| | void swap(SmallVectorImpl &RHS); 411| | 412| | /// Add the specified range to the end of the SmallVector. 413| | template 414| 0| void append(in_iter in_start, in_iter in_end) { 415| 0| size_type NumInputs = std::distance(in_start, in_end); 416| 0| // Grow allocated space if needed. 417| 0| if (NumInputs > size_type(this->capacity_ptr()-this->end())) 418| 0| this->grow(this->size()+NumInputs); 419| 0| 420| 0| // Copy the new elements over. 421| 0| this->uninitialized_copy(in_start, in_end, this->end()); 422| 0| this->setEnd(this->end() + NumInputs); 423| 0| } 424| | 425| | /// Add the specified range to the end of the SmallVector. 426| | void append(size_type NumInputs, const T &Elt) { 427| | // Grow allocated space if needed. 428| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 429| | this->grow(this->size()+NumInputs); 430| | 431| | // Copy the new elements over. 432| | std::uninitialized_fill_n(this->end(), NumInputs, Elt); 433| | this->setEnd(this->end() + NumInputs); 434| | } 435| | 436| | void append(std::initializer_list IL) { 437| | append(IL.begin(), IL.end()); 438| | } 439| | 440| | void assign(size_type NumElts, const T &Elt) { 441| | clear(); 442| | if (this->capacity() < NumElts) 443| | this->grow(NumElts); 444| | this->setEnd(this->begin()+NumElts); 445| | std::uninitialized_fill(this->begin(), this->end(), Elt); 446| | } 447| | 448| | void assign(std::initializer_list IL) { 449| | clear(); 450| | append(IL); 451| | } 452| | 453| | iterator erase(iterator I) { 454| | assert(I >= this->begin() && "Iterator to erase is out of bounds."); 455| | assert(I < this->end() && "Erasing at past-the-end iterator."); 456| | 457| | iterator N = I; 458| | // Shift all elts down one. 459| | this->move(I+1, this->end(), I); 460| | // Drop the last elt. 461| | this->pop_back(); 462| | return(N); 463| | } 464| | 465| | iterator erase(iterator S, iterator E) { 466| | assert(S >= this->begin() && "Range to erase is out of bounds."); 467| | assert(S <= E && "Trying to erase invalid range."); 468| | assert(E <= this->end() && "Trying to erase past the end."); 469| | 470| | iterator N = S; 471| | // Shift all elts down. 472| | iterator I = this->move(E, this->end(), S); 473| | // Drop the last elts. 474| | this->destroy_range(I, this->end()); 475| | this->setEnd(I); 476| | return(N); 477| | } 478| | 479| | iterator insert(iterator I, T &&Elt) { 480| | if (I == this->end()) { // Important special case for empty vector. 481| | this->push_back(::std::move(Elt)); 482| | return this->end()-1; 483| | } 484| | 485| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 486| | assert(I <= this->end() && "Inserting past the end of the vector."); 487| | 488| | if (this->EndX >= this->CapacityX) { 489| | size_t EltNo = I-this->begin(); 490| | this->grow(); 491| | I = this->begin()+EltNo; 492| | } 493| | 494| | ::new ((void*) this->end()) T(::std::move(this->back())); 495| | // Push everything else over. 496| | this->move_backward(I, this->end()-1, this->end()); 497| | this->setEnd(this->end()+1); 498| | 499| | // If we just moved the element we're inserting, be sure to update 500| | // the reference. 501| | T *EltPtr = &Elt; 502| | if (I <= EltPtr && EltPtr < this->EndX) 503| | ++EltPtr; 504| | 505| | *I = ::std::move(*EltPtr); 506| | return I; 507| | } 508| | 509| | iterator insert(iterator I, const T &Elt) { 510| | if (I == this->end()) { // Important special case for empty vector. 511| | this->push_back(Elt); 512| | return this->end()-1; 513| | } 514| | 515| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 516| | assert(I <= this->end() && "Inserting past the end of the vector."); 517| | 518| | if (this->EndX >= this->CapacityX) { 519| | size_t EltNo = I-this->begin(); 520| | this->grow(); 521| | I = this->begin()+EltNo; 522| | } 523| | ::new ((void*) this->end()) T(std::move(this->back())); 524| | // Push everything else over. 525| | this->move_backward(I, this->end()-1, this->end()); 526| | this->setEnd(this->end()+1); 527| | 528| | // If we just moved the element we're inserting, be sure to update 529| | // the reference. 530| | const T *EltPtr = &Elt; 531| | if (I <= EltPtr && EltPtr < this->EndX) 532| | ++EltPtr; 533| | 534| | *I = *EltPtr; 535| | return I; 536| | } 537| | 538| | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 539| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 540| | size_t InsertElt = I - this->begin(); 541| | 542| | if (I == this->end()) { // Important special case for empty vector. 543| | append(NumToInsert, Elt); 544| | return this->begin()+InsertElt; 545| | } 546| | 547| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 548| | assert(I <= this->end() && "Inserting past the end of the vector."); 549| | 550| | // Ensure there is enough space. 551| | reserve(this->size() + NumToInsert); 552| | 553| | // Uninvalidate the iterator. 554| | I = this->begin()+InsertElt; 555| | 556| | // If there are more elements between the insertion point and the end of the 557| | // range than there are being inserted, we can use a simple approach to 558| | // insertion. Since we already reserved space, we know that this won't 559| | // reallocate the vector. 560| | if (size_t(this->end()-I) >= NumToInsert) { 561| | T *OldEnd = this->end(); 562| | append(std::move_iterator(this->end() - NumToInsert), 563| | std::move_iterator(this->end())); 564| | 565| | // Copy the existing elements that get replaced. 566| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 567| | 568| | std::fill_n(I, NumToInsert, Elt); 569| | return I; 570| | } 571| | 572| | // Otherwise, we're inserting more elements than exist already, and we're 573| | // not inserting at the end. 574| | 575| | // Move over the elements that we're about to overwrite. 576| | T *OldEnd = this->end(); 577| | this->setEnd(this->end() + NumToInsert); 578| | size_t NumOverwritten = OldEnd-I; 579| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 580| | 581| | // Replace the overwritten part. 582| | std::fill_n(I, NumOverwritten, Elt); 583| | 584| | // Insert the non-overwritten middle part. 585| | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 586| | return I; 587| | } 588| | 589| | template 590| | iterator insert(iterator I, ItTy From, ItTy To) { 591| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 592| | size_t InsertElt = I - this->begin(); 593| | 594| | if (I == this->end()) { // Important special case for empty vector. 595| | append(From, To); 596| | return this->begin()+InsertElt; 597| | } 598| | 599| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 600| | assert(I <= this->end() && "Inserting past the end of the vector."); 601| | 602| | size_t NumToInsert = std::distance(From, To); 603| | 604| | // Ensure there is enough space. 605| | reserve(this->size() + NumToInsert); 606| | 607| | // Uninvalidate the iterator. 608| | I = this->begin()+InsertElt; 609| | 610| | // If there are more elements between the insertion point and the end of the 611| | // range than there are being inserted, we can use a simple approach to 612| | // insertion. Since we already reserved space, we know that this won't 613| | // reallocate the vector. 614| | if (size_t(this->end()-I) >= NumToInsert) { 615| | T *OldEnd = this->end(); 616| | append(std::move_iterator(this->end() - NumToInsert), 617| | std::move_iterator(this->end())); 618| | 619| | // Copy the existing elements that get replaced. 620| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 621| | 622| | std::copy(From, To, I); 623| | return I; 624| | } 625| | 626| | // Otherwise, we're inserting more elements than exist already, and we're 627| | // not inserting at the end. 628| | 629| | // Move over the elements that we're about to overwrite. 630| | T *OldEnd = this->end(); 631| | this->setEnd(this->end() + NumToInsert); 632| | size_t NumOverwritten = OldEnd-I; 633| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 634| | 635| | // Replace the overwritten part. 636| | for (T *J = I; NumOverwritten > 0; --NumOverwritten) { 637| | *J = *From; 638| | ++J; ++From; 639| | } 640| | 641| | // Insert the non-overwritten middle part. 642| | this->uninitialized_copy(From, To, OldEnd); 643| | return I; 644| | } 645| | 646| | void insert(iterator I, std::initializer_list IL) { 647| | insert(I, IL.begin(), IL.end()); 648| | } 649| | 650| | template void emplace_back(ArgTypes &&... Args) { 651| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 652| | this->grow(); 653| | ::new ((void *)this->end()) T(std::forward(Args)...); 654| | this->setEnd(this->end() + 1); 655| | } 656| | 657| | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 658| | 659| | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); 660| | 661| | bool operator==(const SmallVectorImpl &RHS) const { 662| | if (this->size() != RHS.size()) return false; 663| | return std::equal(this->begin(), this->end(), RHS.begin()); 664| | } 665| | bool operator!=(const SmallVectorImpl &RHS) const { 666| | return !(*this == RHS); 667| | } 668| | 669| | bool operator<(const SmallVectorImpl &RHS) const { 670| | return std::lexicographical_compare(this->begin(), this->end(), 671| | RHS.begin(), RHS.end()); 672| | } 673| | 674| | /// Set the array size to \p N, which the current array must have enough 675| | /// capacity for. 676| | /// 677| | /// This does not construct or destroy any elements in the vector. 678| | /// 679| | /// Clients can use this in conjunction with capacity() to write past the end 680| | /// of the buffer when they know that more elements are available, and only 681| | /// update the size later. This avoids the cost of value initializing elements 682| | /// which will only be overwritten. 683| | void set_size(size_type N) { 684| | assert(N <= this->capacity()); 685| | this->setEnd(this->begin() + N); 686| | } 687| |}; 688| | 689| | 690| |template 691| |void SmallVectorImpl::swap(SmallVectorImpl &RHS) { 692| | if (this == &RHS) return; 693| | 694| | // We can only avoid copying elements if neither vector is small. 695| | if (!this->isSmall() && !RHS.isSmall()) { 696| | std::swap(this->BeginX, RHS.BeginX); 697| | std::swap(this->EndX, RHS.EndX); 698| | std::swap(this->CapacityX, RHS.CapacityX); 699| | return; 700| | } 701| | if (RHS.size() > this->capacity()) 702| | this->grow(RHS.size()); 703| | if (this->size() > RHS.capacity()) 704| | RHS.grow(this->size()); 705| | 706| | // Swap the shared elements. 707| | size_t NumShared = this->size(); 708| | if (NumShared > RHS.size()) NumShared = RHS.size(); 709| | for (size_type i = 0; i != NumShared; ++i) 710| | std::swap((*this)[i], RHS[i]); 711| | 712| | // Copy over the extra elts. 713| | if (this->size() > RHS.size()) { 714| | size_t EltDiff = this->size() - RHS.size(); 715| | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 716| | RHS.setEnd(RHS.end()+EltDiff); 717| | this->destroy_range(this->begin()+NumShared, this->end()); 718| | this->setEnd(this->begin()+NumShared); 719| | } else if (RHS.size() > this->size()) { 720| | size_t EltDiff = RHS.size() - this->size(); 721| | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 722| | this->setEnd(this->end() + EltDiff); 723| | this->destroy_range(RHS.begin()+NumShared, RHS.end()); 724| | RHS.setEnd(RHS.begin()+NumShared); 725| | } 726| |} 727| | 728| |template 729| |SmallVectorImpl &SmallVectorImpl:: 730| | operator=(const SmallVectorImpl &RHS) { 731| | // Avoid self-assignment. 732| | if (this == &RHS) return *this; 733| | 734| | // If we already have sufficient space, assign the common elements, then 735| | // destroy any excess. 736| | size_t RHSSize = RHS.size(); 737| | size_t CurSize = this->size(); 738| | if (CurSize >= RHSSize) { 739| | // Assign common elements. 740| | iterator NewEnd; 741| | if (RHSSize) 742| | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 743| | else 744| | NewEnd = this->begin(); 745| | 746| | // Destroy excess elements. 747| | this->destroy_range(NewEnd, this->end()); 748| | 749| | // Trim. 750| | this->setEnd(NewEnd); 751| | return *this; 752| | } 753| | 754| | // If we have to grow to have enough elements, destroy the current elements. 755| | // This allows us to avoid copying them during the grow. 756| | // FIXME: don't do this if they're efficiently moveable. 757| | if (this->capacity() < RHSSize) { 758| | // Destroy current elements. 759| | this->destroy_range(this->begin(), this->end()); 760| | this->setEnd(this->begin()); 761| | CurSize = 0; 762| | this->grow(RHSSize); 763| | } else if (CurSize) { 764| | // Otherwise, use assignment for the already-constructed elements. 765| | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 766| | } 767| | 768| | // Copy construct the new elements in place. 769| | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 770| | this->begin()+CurSize); 771| | 772| | // Set end. 773| | this->setEnd(this->begin()+RHSSize); 774| | return *this; 775| |} 776| | 777| |template 778| |SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { 779| | // Avoid self-assignment. 780| | if (this == &RHS) return *this; 781| | 782| | // If the RHS isn't small, clear this vector and then steal its buffer. 783| | if (!RHS.isSmall()) { 784| | this->destroy_range(this->begin(), this->end()); 785| | if (!this->isSmall()) free(this->begin()); 786| | this->BeginX = RHS.BeginX; 787| | this->EndX = RHS.EndX; 788| | this->CapacityX = RHS.CapacityX; 789| | RHS.resetToSmall(); 790| | return *this; 791| | } 792| | 793| | // If we already have sufficient space, assign the common elements, then 794| | // destroy any excess. 795| | size_t RHSSize = RHS.size(); 796| | size_t CurSize = this->size(); 797| | if (CurSize >= RHSSize) { 798| | // Assign common elements. 799| | iterator NewEnd = this->begin(); 800| | if (RHSSize) 801| | NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); 802| | 803| | // Destroy excess elements and trim the bounds. 804| | this->destroy_range(NewEnd, this->end()); 805| | this->setEnd(NewEnd); 806| | 807| | // Clear the RHS. 808| | RHS.clear(); 809| | 810| | return *this; 811| | } 812| | 813| | // If we have to grow to have enough elements, destroy the current elements. 814| | // This allows us to avoid copying them during the grow. 815| | // FIXME: this may not actually make any sense if we can efficiently move 816| | // elements. 817| | if (this->capacity() < RHSSize) { 818| | // Destroy current elements. 819| | this->destroy_range(this->begin(), this->end()); 820| | this->setEnd(this->begin()); 821| | CurSize = 0; 822| | this->grow(RHSSize); 823| | } else if (CurSize) { 824| | // Otherwise, use assignment for the already-constructed elements. 825| | this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); 826| | } 827| | 828| | // Move-construct the new elements in place. 829| | this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), 830| | this->begin()+CurSize); 831| | 832| | // Set end. 833| | this->setEnd(this->begin()+RHSSize); 834| | 835| | RHS.clear(); 836| | return *this; 837| |} 838| | 839| |/// Storage for the SmallVector elements which aren't contained in 840| |/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' 841| |/// element is in the base class. This is specialized for the N=1 and N=0 cases 842| |/// to avoid allocating unnecessary storage. 843| |template 844| |struct SmallVectorStorage { 845| | typename SmallVectorTemplateCommon::U InlineElts[N - 1]; 846| |}; 847| |template struct SmallVectorStorage {}; 848| |template struct SmallVectorStorage {}; 849| | 850| |/// This is a 'vector' (really, a variable-sized array), optimized 851| |/// for the case when the array is small. It contains some number of elements 852| |/// in-place, which allows it to avoid heap allocation when the actual number of 853| |/// elements is below that threshold. This allows normal "small" cases to be 854| |/// fast without losing generality for large inputs. 855| |/// 856| |/// Note that this does not attempt to be exception safe. 857| |/// 858| |template 859| |class SmallVector : public SmallVectorImpl { 860| | /// Inline space for elements which aren't stored in the base class. 861| | SmallVectorStorage Storage; 862| |public: 863| 0| SmallVector() : SmallVectorImpl(N) { 864| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj128EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj64EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj16EEC2Ev ------------------ 865| | 866| | explicit SmallVector(size_t Size, const T &Value = T()) 867| | : SmallVectorImpl(N) { 868| | this->assign(Size, Value); 869| | } 870| | 871| | template 872| 0| SmallVector(ItTy S, ItTy E) : SmallVectorImpl(N) { 873| 0| this->append(S, E); 874| 0| } 875| | 876| | template 877| | explicit SmallVector(const llvm::iterator_range R) 878| | : SmallVectorImpl(N) { 879| | this->append(R.begin(), R.end()); 880| | } 881| | 882| | SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { 883| | this->assign(IL); 884| | } 885| | 886| | SmallVector(const SmallVector &RHS) : SmallVectorImpl(N) { 887| | if (!RHS.empty()) 888| | SmallVectorImpl::operator=(RHS); 889| | } 890| | 891| | const SmallVector &operator=(const SmallVector &RHS) { 892| | SmallVectorImpl::operator=(RHS); 893| | return *this; 894| | } 895| | 896| | SmallVector(SmallVector &&RHS) : SmallVectorImpl(N) { 897| | if (!RHS.empty()) 898| | SmallVectorImpl::operator=(::std::move(RHS)); 899| | } 900| | 901| | const SmallVector &operator=(SmallVector &&RHS) { 902| | SmallVectorImpl::operator=(::std::move(RHS)); 903| | return *this; 904| | } 905| | 906| | SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { 907| | if (!RHS.empty()) 908| | SmallVectorImpl::operator=(::std::move(RHS)); 909| | } 910| | 911| | const SmallVector &operator=(SmallVectorImpl &&RHS) { 912| | SmallVectorImpl::operator=(::std::move(RHS)); 913| | return *this; 914| | } 915| | 916| | const SmallVector &operator=(std::initializer_list IL) { 917| | this->assign(IL); 918| | return *this; 919| | } 920| |}; 921| | 922| |template 923| |static inline size_t capacity_in_bytes(const SmallVector &X) { 924| | return X.capacity_in_bytes(); 925| |} 926| | 927| |} // End llvm namespace 928| | 929| |namespace std { 930| | /// Implement std::swap in terms of SmallVector swap. 931| | template 932| | inline void 933| | swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { 934| | LHS.swap(RHS); 935| | } 936| | 937| | /// Implement std::swap in terms of SmallVector swap. 938| | template 939| | inline void 940| | swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { 941| | LHS.swap(RHS); 942| | } 943| |} 944| | 945| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringMap.h: 1| |//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGMAP_H 15| |#define LLVM_ADT_STRINGMAP_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/Allocator.h" 19| |#include 20| |#include 21| | 22| |namespace llvm { 23| | template 24| | class StringMapConstIterator; 25| | template 26| | class StringMapIterator; 27| | template 28| | class StringMapEntry; 29| | 30| |/// StringMapEntryBase - Shared base class of StringMapEntry instances. 31| |class StringMapEntryBase { 32| | unsigned StrLen; 33| |public: 34| 0| explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 35| | 36| | unsigned getKeyLength() const { return StrLen; } 37| |}; 38| | 39| |/// StringMapImpl - This is the base class of StringMap that is shared among 40| |/// all of its instantiations. 41| |class StringMapImpl { 42| |protected: 43| | // Array of NumBuckets pointers to entries, null pointers are holes. 44| | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 45| | // by an array of the actual hash values as unsigned integers. 46| | StringMapEntryBase **TheTable; 47| | unsigned NumBuckets; 48| | unsigned NumItems; 49| | unsigned NumTombstones; 50| | unsigned ItemSize; 51| |protected: 52| | explicit StringMapImpl(unsigned itemSize) 53| | : TheTable(nullptr), 54| | // Initialize the map with zero buckets to allocation. 55| 0| NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 56| | StringMapImpl(StringMapImpl &&RHS) 57| | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 58| | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 59| 0| ItemSize(RHS.ItemSize) { 60| 0| RHS.TheTable = nullptr; 61| 0| RHS.NumBuckets = 0; 62| 0| RHS.NumItems = 0; 63| 0| RHS.NumTombstones = 0; 64| 0| } 65| | 66| | StringMapImpl(unsigned InitSize, unsigned ItemSize); 67| | unsigned RehashTable(unsigned BucketNo = 0); 68| | 69| | /// LookupBucketFor - Look up the bucket that the specified string should end 70| | /// up in. If it already exists as a key in the map, the Item pointer for the 71| | /// specified bucket will be non-null. Otherwise, it will be null. In either 72| | /// case, the FullHashValue field of the bucket will be set to the hash value 73| | /// of the string. 74| | unsigned LookupBucketFor(StringRef Key); 75| | 76| | /// FindKey - Look up the bucket that contains the specified key. If it exists 77| | /// in the map, return the bucket number of the key. Otherwise return -1. 78| | /// This does not modify the map. 79| | int FindKey(StringRef Key) const; 80| | 81| | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 82| | /// delete it. This aborts if the value isn't in the table. 83| | void RemoveKey(StringMapEntryBase *V); 84| | 85| | /// RemoveKey - Remove the StringMapEntry for the specified key from the 86| | /// table, returning it. If the key is not in the table, this returns null. 87| | StringMapEntryBase *RemoveKey(StringRef Key); 88| |private: 89| | void init(unsigned Size); 90| |public: 91| | static StringMapEntryBase *getTombstoneVal() { 92| | return (StringMapEntryBase*)-1; 93| | } 94| | 95| 0| unsigned getNumBuckets() const { return NumBuckets; } 96| 0| unsigned getNumItems() const { return NumItems; } 97| | 98| | bool empty() const { return NumItems == 0; } 99| 0| unsigned size() const { return NumItems; } 100| | 101| 0| void swap(StringMapImpl &Other) { 102| 0| std::swap(TheTable, Other.TheTable); 103| 0| std::swap(NumBuckets, Other.NumBuckets); 104| 0| std::swap(NumItems, Other.NumItems); 105| 0| std::swap(NumTombstones, Other.NumTombstones); 106| 0| } 107| |}; 108| | 109| |/// StringMapEntry - This is used to represent one value that is inserted into 110| |/// a StringMap. It contains the Value itself and the key: the string length 111| |/// and data. 112| |template 113| |class StringMapEntry : public StringMapEntryBase { 114| | StringMapEntry(StringMapEntry &E) = delete; 115| |public: 116| | ValueTy second; 117| | 118| | explicit StringMapEntry(unsigned strLen) 119| | : StringMapEntryBase(strLen), second() {} 120| | template 121| | StringMapEntry(unsigned strLen, InitTy &&V) 122| | : StringMapEntryBase(strLen), second(std::forward(V)) {} 123| | 124| | StringRef getKey() const { 125| | return StringRef(getKeyData(), getKeyLength()); 126| | } 127| | 128| | const ValueTy &getValue() const { return second; } 129| | ValueTy &getValue() { return second; } 130| | 131| | void setValue(const ValueTy &V) { second = V; } 132| | 133| | /// getKeyData - Return the start of the string data that is the key for this 134| | /// value. The string data is always stored immediately after the 135| | /// StringMapEntry object. 136| | const char *getKeyData() const {return reinterpret_cast(this+1);} 137| | 138| | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 139| | 140| | /// Create - Create a StringMapEntry for the specified key and default 141| | /// construct the value. 142| | template 143| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 144| | InitType &&InitVal) { 145| | unsigned KeyLength = Key.size(); 146| | 147| | // Allocate a new item with space for the string at the end and a null 148| | // terminator. 149| | unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ 150| | KeyLength+1; 151| | unsigned Alignment = alignOf(); 152| | 153| | StringMapEntry *NewItem = 154| | static_cast(Allocator.Allocate(AllocSize,Alignment)); 155| | 156| | // Default construct the value. 157| | new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); 158| | 159| | // Copy the string information. 160| | char *StrBuffer = const_cast(NewItem->getKeyData()); 161| | memcpy(StrBuffer, Key.data(), KeyLength); 162| | StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 163| | return NewItem; 164| | } 165| | 166| | template 167| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 168| | return Create(Key, Allocator, ValueTy()); 169| | } 170| | 171| | /// Create - Create a StringMapEntry with normal malloc/free. 172| | template 173| | static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { 174| | MallocAllocator A; 175| | return Create(Key, A, std::forward(InitVal)); 176| | } 177| | 178| | static StringMapEntry *Create(StringRef Key) { 179| | return Create(Key, ValueTy()); 180| | } 181| | 182| | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 183| | /// into a StringMapEntry, return the StringMapEntry itself. 184| | static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 185| | char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); 186| | return *reinterpret_cast(Ptr); 187| | } 188| | 189| | /// Destroy - Destroy this StringMapEntry, releasing memory back to the 190| | /// specified allocator. 191| | template 192| | void Destroy(AllocatorTy &Allocator) { 193| | // Free memory referenced by the item. 194| | unsigned AllocSize = 195| | static_cast(sizeof(StringMapEntry)) + getKeyLength() + 1; 196| | this->~StringMapEntry(); 197| | Allocator.Deallocate(static_cast(this), AllocSize); 198| | } 199| | 200| | /// Destroy this object, releasing memory back to the malloc allocator. 201| | void Destroy() { 202| | MallocAllocator A; 203| | Destroy(A); 204| | } 205| |}; 206| | 207| | 208| |/// StringMap - This is an unconventional map that is specialized for handling 209| |/// keys that are "strings", which are basically ranges of bytes. This does some 210| |/// funky memory allocation and hashing things to make it extremely efficient, 211| |/// storing the string data *after* the value in the map. 212| |template 213| |class StringMap : public StringMapImpl { 214| | AllocatorTy Allocator; 215| |public: 216| | typedef StringMapEntry MapEntryTy; 217| | 218| | StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} 219| | explicit StringMap(unsigned InitialSize) 220| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} 221| | 222| | explicit StringMap(AllocatorTy A) 223| | : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} 224| | 225| | StringMap(unsigned InitialSize, AllocatorTy A) 226| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), 227| | Allocator(A) {} 228| | 229| | StringMap(StringMap &&RHS) 230| | : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 231| | 232| | StringMap &operator=(StringMap RHS) { 233| | StringMapImpl::swap(RHS); 234| | std::swap(Allocator, RHS.Allocator); 235| | return *this; 236| | } 237| | 238| | // FIXME: Implement copy operations if/when they're needed. 239| | 240| | AllocatorTy &getAllocator() { return Allocator; } 241| | const AllocatorTy &getAllocator() const { return Allocator; } 242| | 243| | typedef const char* key_type; 244| | typedef ValueTy mapped_type; 245| | typedef StringMapEntry value_type; 246| | typedef size_t size_type; 247| | 248| | typedef StringMapConstIterator const_iterator; 249| | typedef StringMapIterator iterator; 250| | 251| | iterator begin() { 252| | return iterator(TheTable, NumBuckets == 0); 253| | } 254| | iterator end() { 255| | return iterator(TheTable+NumBuckets, true); 256| | } 257| | const_iterator begin() const { 258| | return const_iterator(TheTable, NumBuckets == 0); 259| | } 260| | const_iterator end() const { 261| | return const_iterator(TheTable+NumBuckets, true); 262| | } 263| | 264| | iterator find(StringRef Key) { 265| | int Bucket = FindKey(Key); 266| | if (Bucket == -1) return end(); 267| | return iterator(TheTable+Bucket, true); 268| | } 269| | 270| | const_iterator find(StringRef Key) const { 271| | int Bucket = FindKey(Key); 272| | if (Bucket == -1) return end(); 273| | return const_iterator(TheTable+Bucket, true); 274| | } 275| | 276| | /// lookup - Return the entry for the specified key, or a default 277| | /// constructed value if no such entry exists. 278| | ValueTy lookup(StringRef Key) const { 279| | const_iterator it = find(Key); 280| | if (it != end()) 281| | return it->second; 282| | return ValueTy(); 283| | } 284| | 285| | ValueTy &operator[](StringRef Key) { 286| | return insert(std::make_pair(Key, ValueTy())).first->second; 287| | } 288| | 289| | /// count - Return 1 if the element is in the map, 0 otherwise. 290| | size_type count(StringRef Key) const { 291| | return find(Key) == end() ? 0 : 1; 292| | } 293| | 294| | /// insert - Insert the specified key/value pair into the map. If the key 295| | /// already exists in the map, return false and ignore the request, otherwise 296| | /// insert it and return true. 297| | bool insert(MapEntryTy *KeyValue) { 298| | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 299| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 300| | if (Bucket && Bucket != getTombstoneVal()) 301| | return false; // Already exists in map. 302| | 303| | if (Bucket == getTombstoneVal()) 304| | --NumTombstones; 305| | Bucket = KeyValue; 306| | ++NumItems; 307| | assert(NumItems + NumTombstones <= NumBuckets); 308| | 309| | RehashTable(); 310| | return true; 311| | } 312| | 313| | /// insert - Inserts the specified key/value pair into the map if the key 314| | /// isn't already in the map. The bool component of the returned pair is true 315| | /// if and only if the insertion takes place, and the iterator component of 316| | /// the pair points to the element with key equivalent to the key of the pair. 317| | std::pair insert(std::pair KV) { 318| | unsigned BucketNo = LookupBucketFor(KV.first); 319| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 320| | if (Bucket && Bucket != getTombstoneVal()) 321| | return std::make_pair(iterator(TheTable + BucketNo, false), 322| | false); // Already exists in map. 323| | 324| | if (Bucket == getTombstoneVal()) 325| | --NumTombstones; 326| | Bucket = 327| | MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 328| | ++NumItems; 329| | assert(NumItems + NumTombstones <= NumBuckets); 330| | 331| | BucketNo = RehashTable(BucketNo); 332| | return std::make_pair(iterator(TheTable + BucketNo, false), true); 333| | } 334| | 335| | // clear - Empties out the StringMap 336| | void clear() { 337| | if (empty()) return; 338| | 339| | // Zap all values, resetting the keys back to non-present (not tombstone), 340| | // which is safe because we're removing all elements. 341| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 342| | StringMapEntryBase *&Bucket = TheTable[I]; 343| | if (Bucket && Bucket != getTombstoneVal()) { 344| | static_cast(Bucket)->Destroy(Allocator); 345| | } 346| | Bucket = nullptr; 347| | } 348| | 349| | NumItems = 0; 350| | NumTombstones = 0; 351| | } 352| | 353| | /// remove - Remove the specified key/value pair from the map, but do not 354| | /// erase it. This aborts if the key is not in the map. 355| | void remove(MapEntryTy *KeyValue) { 356| | RemoveKey(KeyValue); 357| | } 358| | 359| | void erase(iterator I) { 360| | MapEntryTy &V = *I; 361| | remove(&V); 362| | V.Destroy(Allocator); 363| | } 364| | 365| | bool erase(StringRef Key) { 366| | iterator I = find(Key); 367| | if (I == end()) return false; 368| | erase(I); 369| | return true; 370| | } 371| | 372| | ~StringMap() { 373| | // Delete all the elements in the map, but don't reset the elements 374| | // to default values. This is a copy of clear(), but avoids unnecessary 375| | // work not required in the destructor. 376| | if (!empty()) { 377| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 378| | StringMapEntryBase *Bucket = TheTable[I]; 379| | if (Bucket && Bucket != getTombstoneVal()) { 380| | static_cast(Bucket)->Destroy(Allocator); 381| | } 382| | } 383| | } 384| | free(TheTable); 385| | } 386| |}; 387| | 388| | 389| |template 390| |class StringMapConstIterator { 391| |protected: 392| | StringMapEntryBase **Ptr; 393| |public: 394| | typedef StringMapEntry value_type; 395| | 396| | StringMapConstIterator() : Ptr(nullptr) { } 397| | 398| | explicit StringMapConstIterator(StringMapEntryBase **Bucket, 399| | bool NoAdvance = false) 400| | : Ptr(Bucket) { 401| | if (!NoAdvance) AdvancePastEmptyBuckets(); 402| | } 403| | 404| | const value_type &operator*() const { 405| | return *static_cast*>(*Ptr); 406| | } 407| | const value_type *operator->() const { 408| | return static_cast*>(*Ptr); 409| | } 410| | 411| | bool operator==(const StringMapConstIterator &RHS) const { 412| | return Ptr == RHS.Ptr; 413| | } 414| | bool operator!=(const StringMapConstIterator &RHS) const { 415| | return Ptr != RHS.Ptr; 416| | } 417| | 418| | inline StringMapConstIterator& operator++() { // Preincrement 419| | ++Ptr; 420| | AdvancePastEmptyBuckets(); 421| | return *this; 422| | } 423| | StringMapConstIterator operator++(int) { // Postincrement 424| | StringMapConstIterator tmp = *this; ++*this; return tmp; 425| | } 426| | 427| |private: 428| | void AdvancePastEmptyBuckets() { 429| | while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 430| | ++Ptr; 431| | } 432| |}; 433| | 434| |template 435| |class StringMapIterator : public StringMapConstIterator { 436| |public: 437| | StringMapIterator() {} 438| | explicit StringMapIterator(StringMapEntryBase **Bucket, 439| | bool NoAdvance = false) 440| | : StringMapConstIterator(Bucket, NoAdvance) { 441| | } 442| | StringMapEntry &operator*() const { 443| | return *static_cast*>(*this->Ptr); 444| | } 445| | StringMapEntry *operator->() const { 446| | return static_cast*>(*this->Ptr); 447| | } 448| |}; 449| | 450| |} 451| | 452| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringRef.h: 1| |//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_STRINGREF_H 11| |#define LLVM_ADT_STRINGREF_H 12| | 13| |#include 14| |#include 15| |#include 16| |#include 17| |#include 18| |#include 19| | 20| |namespace llvm { 21| | template 22| | class SmallVectorImpl; 23| | class hash_code; 24| | class StringRef; 25| | 26| | /// Helper functions for StringRef::getAsInteger. 27| | bool getAsUnsignedInteger(StringRef Str, unsigned Radix, 28| | unsigned long long &Result); 29| | 30| | bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); 31| | 32| | /// StringRef - Represent a constant reference to a string, i.e. a character 33| | /// array and a length, which need not be null terminated. 34| | /// 35| | /// This class does not own the string data, it is expected to be used in 36| | /// situations where the character data resides in some other buffer, whose 37| | /// lifetime extends past that of the StringRef. For this reason, it is not in 38| | /// general safe to store a StringRef. 39| | class StringRef { 40| | public: 41| | typedef const char *iterator; 42| | typedef const char *const_iterator; 43| | static const size_t npos = ~size_t(0); 44| | typedef size_t size_type; 45| | 46| | private: 47| | /// The start of the string, in an external buffer. 48| | const char *Data; 49| | 50| | /// The length of the string. 51| | size_t Length; 52| | 53| | // Workaround memcmp issue with null pointers (undefined behavior) 54| | // by providing a specialized version 55| 0| static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { 56| 0| if (Length == 0) { return 0; } 57| 0| return ::memcmp(Lhs,Rhs,Length); 58| 0| } 59| | 60| | public: 61| | /// @name Constructors 62| | /// @{ 63| | 64| | /// Construct an empty string ref. 65| 0| /*implicit*/ StringRef() : Data(nullptr), Length(0) {} 66| | 67| | /// Construct a string ref from a cstring. 68| | /*implicit*/ StringRef(const char *Str) 69| 0| : Data(Str) { 70| 0| assert(Str && "StringRef cannot be built from a NULL argument"); 71| 0| Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior 72| 0| } 73| | 74| | /// Construct a string ref from a pointer and length. 75| | /*implicit*/ StringRef(const char *data, size_t length) 76| 0| : Data(data), Length(length) { 77| 0| assert((data || length == 0) && 78| 0| "StringRef cannot be built from a NULL argument with non-null length"); 79| 0| } 80| | 81| | /// Construct a string ref from an std::string. 82| | /*implicit*/ StringRef(const std::string &Str) 83| 0| : Data(Str.data()), Length(Str.length()) {} 84| | 85| | /// @} 86| | /// @name Iterators 87| | /// @{ 88| | 89| 0| iterator begin() const { return Data; } 90| | 91| 0| iterator end() const { return Data + Length; } 92| | 93| 0| const unsigned char *bytes_begin() const { 94| 0| return reinterpret_cast(begin()); 95| 0| } 96| 0| const unsigned char *bytes_end() const { 97| 0| return reinterpret_cast(end()); 98| 0| } 99| | 100| | /// @} 101| | /// @name String Operations 102| | /// @{ 103| | 104| | /// data - Get a pointer to the start of the string (which may not be null 105| | /// terminated). 106| 0| const char *data() const { return Data; } 107| | 108| | /// empty - Check if the string is empty. 109| 0| bool empty() const { return Length == 0; } 110| | 111| | /// size - Get the string size. 112| 0| size_t size() const { return Length; } 113| | 114| | /// front - Get the first character in the string. 115| | char front() const { 116| | assert(!empty()); 117| | return Data[0]; 118| | } 119| | 120| | /// back - Get the last character in the string. 121| | char back() const { 122| | assert(!empty()); 123| | return Data[Length-1]; 124| | } 125| | 126| | // copy - Allocate copy in Allocator and return StringRef to it. 127| | template StringRef copy(Allocator &A) const { 128| | char *S = A.template Allocate(Length); 129| | std::copy(begin(), end(), S); 130| | return StringRef(S, Length); 131| | } 132| | 133| | /// equals - Check for string equality, this is more efficient than 134| | /// compare() when the relative ordering of inequal strings isn't needed. 135| 0| bool equals(StringRef RHS) const { 136| 0| return (Length == RHS.Length && 137| 0| compareMemory(Data, RHS.Data, RHS.Length) == 0); 138| 0| } 139| | 140| | /// equals_lower - Check for string equality, ignoring case. 141| | bool equals_lower(StringRef RHS) const { 142| | return Length == RHS.Length && compare_lower(RHS) == 0; 143| | } 144| | 145| | /// compare - Compare two strings; the result is -1, 0, or 1 if this string 146| | /// is lexicographically less than, equal to, or greater than the \p RHS. 147| 0| int compare(StringRef RHS) const { 148| 0| // Check the prefix for a mismatch. 149| 0| if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) 150| 0| return Res < 0 ? -1 : 1; 151| 0| 152| 0| // Otherwise the prefixes match, so we only need to check the lengths. 153| 0| if (Length == RHS.Length) 154| 0| return 0; 155| 0| return Length < RHS.Length ? -1 : 1; 156| 0| } 157| | 158| | /// compare_lower - Compare two strings, ignoring case. 159| | int compare_lower(StringRef RHS) const; 160| | 161| | /// compare_numeric - Compare two strings, treating sequences of digits as 162| | /// numbers. 163| | int compare_numeric(StringRef RHS) const; 164| | 165| | /// \brief Determine the edit distance between this string and another 166| | /// string. 167| | /// 168| | /// \param Other the string to compare this string against. 169| | /// 170| | /// \param AllowReplacements whether to allow character 171| | /// replacements (change one character into another) as a single 172| | /// operation, rather than as two operations (an insertion and a 173| | /// removal). 174| | /// 175| | /// \param MaxEditDistance If non-zero, the maximum edit distance that 176| | /// this routine is allowed to compute. If the edit distance will exceed 177| | /// that maximum, returns \c MaxEditDistance+1. 178| | /// 179| | /// \returns the minimum number of character insertions, removals, 180| | /// or (if \p AllowReplacements is \c true) replacements needed to 181| | /// transform one of the given strings into the other. If zero, 182| | /// the strings are identical. 183| | unsigned edit_distance(StringRef Other, bool AllowReplacements = true, 184| | unsigned MaxEditDistance = 0) const; 185| | 186| | /// str - Get the contents as an std::string. 187| 0| std::string str() const { 188| 0| if (!Data) return std::string(); 189| 0| return std::string(Data, Length); 190| 0| } 191| | 192| | /// @} 193| | /// @name Operator Overloads 194| | /// @{ 195| | 196| 0| char operator[](size_t Index) const { 197| 0| assert(Index < Length && "Invalid index!"); 198| 0| return Data[Index]; 199| 0| } 200| | 201| | /// @} 202| | /// @name Type Conversions 203| | /// @{ 204| | 205| 0| operator std::string() const { 206| 0| return str(); 207| 0| } 208| | 209| | /// @} 210| | /// @name String Predicates 211| | /// @{ 212| | 213| | /// Check if this string starts with the given \p Prefix. 214| | bool startswith(StringRef Prefix) const { 215| | return Length >= Prefix.Length && 216| | compareMemory(Data, Prefix.Data, Prefix.Length) == 0; 217| | } 218| | 219| | /// Check if this string starts with the given \p Prefix, ignoring case. 220| | bool startswith_lower(StringRef Prefix) const; 221| | 222| | /// Check if this string ends with the given \p Suffix. 223| | bool endswith(StringRef Suffix) const { 224| | return Length >= Suffix.Length && 225| | compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 226| | } 227| | 228| | /// Check if this string ends with the given \p Suffix, ignoring case. 229| | bool endswith_lower(StringRef Suffix) const; 230| | 231| | /// @} 232| | /// @name String Searching 233| | /// @{ 234| | 235| | /// Search for the first character \p C in the string. 236| | /// 237| | /// \returns The index of the first occurrence of \p C, or npos if not 238| | /// found. 239| 0| size_t find(char C, size_t From = 0) const { 240| 0| for (size_t i = std::min(From, Length), e = Length; i != e; ++i) 241| 0| if (Data[i] == C) 242| 0| return i; 243| 0| return npos; 244| 0| } 245| | 246| | /// Search for the first string \p Str in the string. 247| | /// 248| | /// \returns The index of the first occurrence of \p Str, or npos if not 249| | /// found. 250| | size_t find(StringRef Str, size_t From = 0) const; 251| | 252| | /// Search for the last character \p C in the string. 253| | /// 254| | /// \returns The index of the last occurrence of \p C, or npos if not 255| | /// found. 256| | size_t rfind(char C, size_t From = npos) const { 257| | From = std::min(From, Length); 258| | size_t i = From; 259| | while (i != 0) { 260| | --i; 261| | if (Data[i] == C) 262| | return i; 263| | } 264| | return npos; 265| | } 266| | 267| | /// Search for the last string \p Str in the string. 268| | /// 269| | /// \returns The index of the last occurrence of \p Str, or npos if not 270| | /// found. 271| | size_t rfind(StringRef Str) const; 272| | 273| | /// Find the first character in the string that is \p C, or npos if not 274| | /// found. Same as find. 275| | size_t find_first_of(char C, size_t From = 0) const { 276| | return find(C, From); 277| | } 278| | 279| | /// Find the first character in the string that is in \p Chars, or npos if 280| | /// not found. 281| | /// 282| | /// Complexity: O(size() + Chars.size()) 283| | size_t find_first_of(StringRef Chars, size_t From = 0) const; 284| | 285| | /// Find the first character in the string that is not \p C or npos if not 286| | /// found. 287| | size_t find_first_not_of(char C, size_t From = 0) const; 288| | 289| | /// Find the first character in the string that is not in the string 290| | /// \p Chars, or npos if not found. 291| | /// 292| | /// Complexity: O(size() + Chars.size()) 293| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const; 294| | 295| | /// Find the last character in the string that is \p C, or npos if not 296| | /// found. 297| | size_t find_last_of(char C, size_t From = npos) const { 298| | return rfind(C, From); 299| | } 300| | 301| | /// Find the last character in the string that is in \p C, or npos if not 302| | /// found. 303| | /// 304| | /// Complexity: O(size() + Chars.size()) 305| | size_t find_last_of(StringRef Chars, size_t From = npos) const; 306| | 307| | /// Find the last character in the string that is not \p C, or npos if not 308| | /// found. 309| | size_t find_last_not_of(char C, size_t From = npos) const; 310| | 311| | /// Find the last character in the string that is not in \p Chars, or 312| | /// npos if not found. 313| | /// 314| | /// Complexity: O(size() + Chars.size()) 315| | size_t find_last_not_of(StringRef Chars, size_t From = npos) const; 316| | 317| | /// @} 318| | /// @name Helpful Algorithms 319| | /// @{ 320| | 321| | /// Return the number of occurrences of \p C in the string. 322| 0| size_t count(char C) const { 323| 0| size_t Count = 0; 324| 0| for (size_t i = 0, e = Length; i != e; ++i) 325| 0| if (Data[i] == C) 326| 0| ++Count; 327| 0| return Count; 328| 0| } 329| | 330| | /// Return the number of non-overlapped occurrences of \p Str in 331| | /// the string. 332| | size_t count(StringRef Str) const; 333| | 334| | /// Parse the current string as an integer of the specified radix. If 335| | /// \p Radix is specified as zero, this does radix autosensing using 336| | /// extended C rules: 0 is octal, 0x is hex, 0b is binary. 337| | /// 338| | /// If the string is invalid or if only a subset of the string is valid, 339| | /// this returns true to signify the error. The string is considered 340| | /// erroneous if empty or if it overflows T. 341| | template 342| | typename std::enable_if::is_signed, bool>::type 343| | getAsInteger(unsigned Radix, T &Result) const { 344| | long long LLVal; 345| | if (getAsSignedInteger(*this, Radix, LLVal) || 346| | static_cast(LLVal) != LLVal) 347| | return true; 348| | Result = LLVal; 349| | return false; 350| | } 351| | 352| | template 353| | typename std::enable_if::is_signed, bool>::type 354| | getAsInteger(unsigned Radix, T &Result) const { 355| | unsigned long long ULLVal; 356| | // The additional cast to unsigned long long is required to avoid the 357| | // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type 358| | // 'unsigned __int64' when instantiating getAsInteger with T = bool. 359| | if (getAsUnsignedInteger(*this, Radix, ULLVal) || 360| | static_cast(static_cast(ULLVal)) != ULLVal) 361| | return true; 362| | Result = ULLVal; 363| | return false; 364| | } 365| | 366| | /// @} 367| | /// @name String Operations 368| | /// @{ 369| | 370| | // Convert the given ASCII string to lowercase. 371| | std::string lower() const; 372| | 373| | /// Convert the given ASCII string to uppercase. 374| | std::string upper() const; 375| | 376| | /// @} 377| | /// @name Substring Operations 378| | /// @{ 379| | 380| | /// Return a reference to the substring from [Start, Start + N). 381| | /// 382| | /// \param Start The index of the starting character in the substring; if 383| | /// the index is npos or greater than the length of the string then the 384| | /// empty substring will be returned. 385| | /// 386| | /// \param N The number of characters to included in the substring. If N 387| | /// exceeds the number of characters remaining in the string, the string 388| | /// suffix (starting with \p Start) will be returned. 389| 0| StringRef substr(size_t Start, size_t N = npos) const { 390| 0| Start = std::min(Start, Length); 391| 0| return StringRef(Data + Start, std::min(N, Length - Start)); 392| 0| } 393| | 394| | /// Return a StringRef equal to 'this' but with the first \p N elements 395| | /// dropped. 396| 0| StringRef drop_front(size_t N = 1) const { 397| 0| assert(size() >= N && "Dropping more elements than exist"); 398| 0| return substr(N); 399| 0| } 400| | 401| | /// Return a StringRef equal to 'this' but with the last \p N elements 402| | /// dropped. 403| | StringRef drop_back(size_t N = 1) const { 404| | assert(size() >= N && "Dropping more elements than exist"); 405| | return substr(0, size()-N); 406| | } 407| | 408| | /// Return a reference to the substring from [Start, End). 409| | /// 410| | /// \param Start The index of the starting character in the substring; if 411| | /// the index is npos or greater than the length of the string then the 412| | /// empty substring will be returned. 413| | /// 414| | /// \param End The index following the last character to include in the 415| | /// substring. If this is npos, or less than \p Start, or exceeds the 416| | /// number of characters remaining in the string, the string suffix 417| | /// (starting with \p Start) will be returned. 418| 0| StringRef slice(size_t Start, size_t End) const { 419| 0| Start = std::min(Start, Length); 420| 0| End = std::min(std::max(Start, End), Length); 421| 0| return StringRef(Data + Start, End - Start); 422| 0| } 423| | 424| | /// Split into two substrings around the first occurrence of a separator 425| | /// character. 426| | /// 427| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 428| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 429| | /// maximal. If \p Separator is not in the string, then the result is a 430| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 431| | /// 432| | /// \param Separator The character to split on. 433| | /// \returns The split substrings. 434| 0| std::pair split(char Separator) const { 435| 0| size_t Idx = find(Separator); 436| 0| if (Idx == npos) 437| 0| return std::make_pair(*this, StringRef()); 438| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 439| 0| } 440| | 441| | /// Split into two substrings around the first occurrence of a separator 442| | /// string. 443| | /// 444| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 445| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 446| | /// maximal. If \p Separator is not in the string, then the result is a 447| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 448| | /// 449| | /// \param Separator - The string to split on. 450| | /// \return - The split substrings. 451| | std::pair split(StringRef Separator) const { 452| | size_t Idx = find(Separator); 453| | if (Idx == npos) 454| | return std::make_pair(*this, StringRef()); 455| | return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); 456| | } 457| | 458| | /// Split into substrings around the occurrences of a separator string. 459| | /// 460| | /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most 461| | /// \p MaxSplit splits are done and consequently <= \p MaxSplit 462| | /// elements are added to A. 463| | /// If \p KeepEmpty is false, empty strings are not added to \p A. They 464| | /// still count when considering \p MaxSplit 465| | /// An useful invariant is that 466| | /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true 467| | /// 468| | /// \param A - Where to put the substrings. 469| | /// \param Separator - The string to split on. 470| | /// \param MaxSplit - The maximum number of times the string is split. 471| | /// \param KeepEmpty - True if empty substring should be added. 472| | void split(SmallVectorImpl &A, 473| | StringRef Separator, int MaxSplit = -1, 474| | bool KeepEmpty = true) const; 475| | 476| | /// Split into two substrings around the last occurrence of a separator 477| | /// character. 478| | /// 479| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 480| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 481| | /// minimal. If \p Separator is not in the string, then the result is a 482| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 483| | /// 484| | /// \param Separator - The character to split on. 485| | /// \return - The split substrings. 486| 0| std::pair rsplit(char Separator) const { 487| 0| size_t Idx = rfind(Separator); 488| 0| if (Idx == npos) 489| 0| return std::make_pair(*this, StringRef()); 490| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 491| 0| } 492| | 493| | /// Return string with consecutive characters in \p Chars starting from 494| | /// the left removed. 495| | StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { 496| | return drop_front(std::min(Length, find_first_not_of(Chars))); 497| | } 498| | 499| | /// Return string with consecutive characters in \p Chars starting from 500| | /// the right removed. 501| | StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { 502| | return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); 503| | } 504| | 505| | /// Return string with consecutive characters in \p Chars starting from 506| | /// the left and right removed. 507| 0| StringRef trim(StringRef Chars = " \t\n\v\f\r") const { 508| 0| return ltrim(Chars).rtrim(Chars); 509| 0| } 510| | 511| | /// @} 512| | }; 513| | 514| | /// @name StringRef Comparison Operators 515| | /// @{ 516| | 517| 0| inline bool operator==(StringRef LHS, StringRef RHS) { 518| 0| return LHS.equals(RHS); 519| 0| } 520| | 521| | inline bool operator!=(StringRef LHS, StringRef RHS) { 522| | return !(LHS == RHS); 523| | } 524| | 525| 0| inline bool operator<(StringRef LHS, StringRef RHS) { 526| 0| return LHS.compare(RHS) == -1; 527| 0| } 528| | 529| 0| inline bool operator<=(StringRef LHS, StringRef RHS) { 530| 0| return LHS.compare(RHS) != 1; 531| 0| } 532| | 533| 0| inline bool operator>(StringRef LHS, StringRef RHS) { 534| 0| return LHS.compare(RHS) == 1; 535| 0| } 536| | 537| 0| inline bool operator>=(StringRef LHS, StringRef RHS) { 538| 0| return LHS.compare(RHS) != -1; 539| 0| } 540| | 541| 0| inline std::string &operator+=(std::string &buffer, StringRef string) { 542| 0| return buffer.append(string.data(), string.size()); 543| 0| } 544| | 545| | /// @} 546| | 547| | /// \brief Compute a hash_code for a StringRef. 548| | hash_code hash_value(StringRef S); 549| | 550| | // StringRefs can be treated like a POD type. 551| | template struct isPodLike; 552| | template <> struct isPodLike { static const bool value = true; }; 553| |} 554| | 555| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Twine.h: 1| |//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_TWINE_H 11| |#define LLVM_ADT_TWINE_H 12| | 13| |#include "llvm/ADT/StringRef.h" 14| |#include "llvm/Support/DataTypes.h" 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include 17| |#include 18| | 19| |namespace llvm { 20| | template 21| | class SmallVectorImpl; 22| | class StringRef; 23| | class raw_ostream; 24| | 25| | /// Twine - A lightweight data structure for efficiently representing the 26| | /// concatenation of temporary values as strings. 27| | /// 28| | /// A Twine is a kind of rope, it represents a concatenated string using a 29| | /// binary-tree, where the string is the preorder of the nodes. Since the 30| | /// Twine can be efficiently rendered into a buffer when its result is used, 31| | /// it avoids the cost of generating temporary values for intermediate string 32| | /// results -- particularly in cases when the Twine result is never 33| | /// required. By explicitly tracking the type of leaf nodes, we can also avoid 34| | /// the creation of temporary strings for conversions operations (such as 35| | /// appending an integer to a string). 36| | /// 37| | /// A Twine is not intended for use directly and should not be stored, its 38| | /// implementation relies on the ability to store pointers to temporary stack 39| | /// objects which may be deallocated at the end of a statement. Twines should 40| | /// only be used accepted as const references in arguments, when an API wishes 41| | /// to accept possibly-concatenated strings. 42| | /// 43| | /// Twines support a special 'null' value, which always concatenates to form 44| | /// itself, and renders as an empty string. This can be returned from APIs to 45| | /// effectively nullify any concatenations performed on the result. 46| | /// 47| | /// \b Implementation 48| | /// 49| | /// Given the nature of a Twine, it is not possible for the Twine's 50| | /// concatenation method to construct interior nodes; the result must be 51| | /// represented inside the returned value. For this reason a Twine object 52| | /// actually holds two values, the left- and right-hand sides of a 53| | /// concatenation. We also have nullary Twine objects, which are effectively 54| | /// sentinel values that represent empty strings. 55| | /// 56| | /// Thus, a Twine can effectively have zero, one, or two children. The \see 57| | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 58| | /// testing the number of children. 59| | /// 60| | /// We maintain a number of invariants on Twine objects (FIXME: Why): 61| | /// - Nullary twines are always represented with their Kind on the left-hand 62| | /// side, and the Empty kind on the right-hand side. 63| | /// - Unary twines are always represented with the value on the left-hand 64| | /// side, and the Empty kind on the right-hand side. 65| | /// - If a Twine has another Twine as a child, that child should always be 66| | /// binary (otherwise it could have been folded into the parent). 67| | /// 68| | /// These invariants are check by \see isValid(). 69| | /// 70| | /// \b Efficiency Considerations 71| | /// 72| | /// The Twine is designed to yield efficient and small code for common 73| | /// situations. For this reason, the concat() method is inlined so that 74| | /// concatenations of leaf nodes can be optimized into stores directly into a 75| | /// single stack allocated object. 76| | /// 77| | /// In practice, not all compilers can be trusted to optimize concat() fully, 78| | /// so we provide two additional methods (and accompanying operator+ 79| | /// overloads) to guarantee that particularly important cases (cstring plus 80| | /// StringRef) codegen as desired. 81| | class Twine { 82| | /// NodeKind - Represent the type of an argument. 83| | enum NodeKind : unsigned char { 84| | /// An empty string; the result of concatenating anything with it is also 85| | /// empty. 86| | NullKind, 87| | 88| | /// The empty string. 89| | EmptyKind, 90| | 91| | /// A pointer to a Twine instance. 92| | TwineKind, 93| | 94| | /// A pointer to a C string instance. 95| | CStringKind, 96| | 97| | /// A pointer to an std::string instance. 98| | StdStringKind, 99| | 100| | /// A pointer to a StringRef instance. 101| | StringRefKind, 102| | 103| | /// A char value reinterpreted as a pointer, to render as a character. 104| | CharKind, 105| | 106| | /// An unsigned int value reinterpreted as a pointer, to render as an 107| | /// unsigned decimal integer. 108| | DecUIKind, 109| | 110| | /// An int value reinterpreted as a pointer, to render as a signed 111| | /// decimal integer. 112| | DecIKind, 113| | 114| | /// A pointer to an unsigned long value, to render as an unsigned decimal 115| | /// integer. 116| | DecULKind, 117| | 118| | /// A pointer to a long value, to render as a signed decimal integer. 119| | DecLKind, 120| | 121| | /// A pointer to an unsigned long long value, to render as an unsigned 122| | /// decimal integer. 123| | DecULLKind, 124| | 125| | /// A pointer to a long long value, to render as a signed decimal integer. 126| | DecLLKind, 127| | 128| | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 129| | /// integer. 130| | UHexKind 131| | }; 132| | 133| | union Child 134| | { 135| | const Twine *twine; 136| | const char *cString; 137| | const std::string *stdString; 138| | const StringRef *stringRef; 139| | char character; 140| | unsigned int decUI; 141| | int decI; 142| | const unsigned long *decUL; 143| | const long *decL; 144| | const unsigned long long *decULL; 145| | const long long *decLL; 146| | const uint64_t *uHex; 147| | }; 148| | 149| | private: 150| | /// LHS - The prefix in the concatenation, which may be uninitialized for 151| | /// Null or Empty kinds. 152| | Child LHS; 153| | /// RHS - The suffix in the concatenation, which may be uninitialized for 154| | /// Null or Empty kinds. 155| | Child RHS; 156| | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 157| | NodeKind LHSKind; 158| | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). 159| | NodeKind RHSKind; 160| | 161| | private: 162| | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 163| | explicit Twine(NodeKind Kind) 164| 0| : LHSKind(Kind), RHSKind(EmptyKind) { 165| 0| assert(isNullary() && "Invalid kind!"); 166| 0| } 167| | 168| | /// Construct a binary twine. 169| | explicit Twine(const Twine &LHS, const Twine &RHS) 170| 0| : LHSKind(TwineKind), RHSKind(TwineKind) { 171| 0| this->LHS.twine = &LHS; 172| 0| this->RHS.twine = &RHS; 173| 0| assert(isValid() && "Invalid twine!"); 174| 0| } 175| | 176| | /// Construct a twine from explicit values. 177| | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) 178| 0| : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { 179| 0| assert(isValid() && "Invalid twine!"); 180| 0| } 181| | 182| | /// Since the intended use of twines is as temporary objects, assignments 183| | /// when concatenating might cause undefined behavior or stack corruptions 184| | Twine &operator=(const Twine &Other) = delete; 185| | 186| | /// isNull - Check for the null twine. 187| 0| bool isNull() const { 188| 0| return getLHSKind() == NullKind; 189| 0| } 190| | 191| | /// isEmpty - Check for the empty twine. 192| 0| bool isEmpty() const { 193| 0| return getLHSKind() == EmptyKind; 194| 0| } 195| | 196| | /// isNullary - Check if this is a nullary twine (null or empty). 197| 0| bool isNullary() const { 198| 0| return isNull() || isEmpty(); 199| 0| } 200| | 201| | /// isUnary - Check if this is a unary twine. 202| 0| bool isUnary() const { 203| 0| return getRHSKind() == EmptyKind && !isNullary(); 204| 0| } 205| | 206| | /// isBinary - Check if this is a binary twine. 207| 0| bool isBinary() const { 208| 0| return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 209| 0| } 210| | 211| | /// isValid - Check if this is a valid twine (satisfying the invariants on 212| | /// order and number of arguments). 213| 0| bool isValid() const { 214| 0| // Nullary twines always have Empty on the RHS. 215| 0| if (isNullary() && getRHSKind() != EmptyKind) 216| 0| return false; 217| 0| 218| 0| // Null should never appear on the RHS. 219| 0| if (getRHSKind() == NullKind) 220| 0| return false; 221| 0| 222| 0| // The RHS cannot be non-empty if the LHS is empty. 223| 0| if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 224| 0| return false; 225| 0| 226| 0| // A twine child should always be binary. 227| 0| if (getLHSKind() == TwineKind && 228| 0| !LHS.twine->isBinary()) 229| 0| return false; 230| 0| if (getRHSKind() == TwineKind && 231| 0| !RHS.twine->isBinary()) 232| 0| return false; 233| 0| 234| 0| return true; 235| 0| } 236| | 237| | /// getLHSKind - Get the NodeKind of the left-hand side. 238| 0| NodeKind getLHSKind() const { return LHSKind; } 239| | 240| | /// getRHSKind - Get the NodeKind of the right-hand side. 241| 0| NodeKind getRHSKind() const { return RHSKind; } 242| | 243| | /// printOneChild - Print one child from a twine. 244| | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; 245| | 246| | /// printOneChildRepr - Print the representation of one child from a twine. 247| | void printOneChildRepr(raw_ostream &OS, Child Ptr, 248| | NodeKind Kind) const; 249| | 250| | public: 251| | /// @name Constructors 252| | /// @{ 253| | 254| | /// Construct from an empty string. 255| 0| /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 256| 0| assert(isValid() && "Invalid twine!"); 257| 0| } 258| | 259| | Twine(const Twine &) = default; 260| | 261| | /// Construct from a C string. 262| | /// 263| | /// We take care here to optimize "" into the empty twine -- this will be 264| | /// optimized out for string constants. This allows Twine arguments have 265| | /// default "" values, without introducing unnecessary string constants. 266| | /*implicit*/ Twine(const char *Str) 267| 0| : RHSKind(EmptyKind) { 268| 0| if (Str[0] != '\0') { 269| 0| LHS.cString = Str; 270| 0| LHSKind = CStringKind; 271| 0| } else 272| 0| LHSKind = EmptyKind; 273| 0| 274| 0| assert(isValid() && "Invalid twine!"); 275| 0| } 276| | 277| | /// Construct from an std::string. 278| | /*implicit*/ Twine(const std::string &Str) 279| 0| : LHSKind(StdStringKind), RHSKind(EmptyKind) { 280| 0| LHS.stdString = &Str; 281| 0| assert(isValid() && "Invalid twine!"); 282| 0| } 283| | 284| | /// Construct from a StringRef. 285| | /*implicit*/ Twine(const StringRef &Str) 286| 0| : LHSKind(StringRefKind), RHSKind(EmptyKind) { 287| 0| LHS.stringRef = &Str; 288| 0| assert(isValid() && "Invalid twine!"); 289| 0| } 290| | 291| | /// Construct from a char. 292| | explicit Twine(char Val) 293| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 294| 0| LHS.character = Val; 295| 0| } 296| | 297| | /// Construct from a signed char. 298| | explicit Twine(signed char Val) 299| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 300| 0| LHS.character = static_cast(Val); 301| 0| } 302| | 303| | /// Construct from an unsigned char. 304| | explicit Twine(unsigned char Val) 305| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 306| 0| LHS.character = static_cast(Val); 307| 0| } 308| | 309| | /// Construct a twine to print \p Val as an unsigned decimal integer. 310| | explicit Twine(unsigned Val) 311| 0| : LHSKind(DecUIKind), RHSKind(EmptyKind) { 312| 0| LHS.decUI = Val; 313| 0| } 314| | 315| | /// Construct a twine to print \p Val as a signed decimal integer. 316| | explicit Twine(int Val) 317| 0| : LHSKind(DecIKind), RHSKind(EmptyKind) { 318| 0| LHS.decI = Val; 319| 0| } 320| | 321| | /// Construct a twine to print \p Val as an unsigned decimal integer. 322| | explicit Twine(const unsigned long &Val) 323| 0| : LHSKind(DecULKind), RHSKind(EmptyKind) { 324| 0| LHS.decUL = &Val; 325| 0| } 326| | 327| | /// Construct a twine to print \p Val as a signed decimal integer. 328| | explicit Twine(const long &Val) 329| 0| : LHSKind(DecLKind), RHSKind(EmptyKind) { 330| 0| LHS.decL = &Val; 331| 0| } 332| | 333| | /// Construct a twine to print \p Val as an unsigned decimal integer. 334| | explicit Twine(const unsigned long long &Val) 335| 0| : LHSKind(DecULLKind), RHSKind(EmptyKind) { 336| 0| LHS.decULL = &Val; 337| 0| } 338| | 339| | /// Construct a twine to print \p Val as a signed decimal integer. 340| | explicit Twine(const long long &Val) 341| 0| : LHSKind(DecLLKind), RHSKind(EmptyKind) { 342| 0| LHS.decLL = &Val; 343| 0| } 344| | 345| | // FIXME: Unfortunately, to make sure this is as efficient as possible we 346| | // need extra binary constructors from particular types. We can't rely on 347| | // the compiler to be smart enough to fold operator+()/concat() down to the 348| | // right thing. Yet. 349| | 350| | /// Construct as the concatenation of a C string and a StringRef. 351| | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) 352| | : LHSKind(CStringKind), RHSKind(StringRefKind) { 353| | this->LHS.cString = LHS; 354| | this->RHS.stringRef = &RHS; 355| | assert(isValid() && "Invalid twine!"); 356| | } 357| | 358| | /// Construct as the concatenation of a StringRef and a C string. 359| | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) 360| | : LHSKind(StringRefKind), RHSKind(CStringKind) { 361| | this->LHS.stringRef = &LHS; 362| | this->RHS.cString = RHS; 363| | assert(isValid() && "Invalid twine!"); 364| | } 365| | 366| | /// Create a 'null' string, which is an empty string that always 367| | /// concatenates to form another empty string. 368| 0| static Twine createNull() { 369| 0| return Twine(NullKind); 370| 0| } 371| | 372| | /// @} 373| | /// @name Numeric Conversions 374| | /// @{ 375| | 376| | // Construct a twine to print \p Val as an unsigned hexadecimal integer. 377| 0| static Twine utohexstr(const uint64_t &Val) { 378| 0| Child LHS, RHS; 379| 0| LHS.uHex = &Val; 380| 0| RHS.twine = nullptr; 381| 0| return Twine(LHS, UHexKind, RHS, EmptyKind); 382| 0| } 383| | 384| | /// @} 385| | /// @name Predicate Operations 386| | /// @{ 387| | 388| | /// isTriviallyEmpty - Check if this twine is trivially empty; a false 389| | /// return value does not necessarily mean the twine is empty. 390| | bool isTriviallyEmpty() const { 391| | return isNullary(); 392| | } 393| | 394| | /// isSingleStringRef - Return true if this twine can be dynamically 395| | /// accessed as a single StringRef value with getSingleStringRef(). 396| | bool isSingleStringRef() const { 397| | if (getRHSKind() != EmptyKind) return false; 398| | 399| | switch (getLHSKind()) { 400| | case EmptyKind: 401| | case CStringKind: 402| | case StdStringKind: 403| | case StringRefKind: 404| | return true; 405| | default: 406| | return false; 407| | } 408| | } 409| | 410| | /// @} 411| | /// @name String Operations 412| | /// @{ 413| | 414| | Twine concat(const Twine &Suffix) const; 415| | 416| | /// @} 417| | /// @name Output & Conversion. 418| | /// @{ 419| | 420| | /// str - Return the twine contents as a std::string. 421| | std::string str() const; 422| | 423| | /// toVector - Write the concatenated string into the given SmallString or 424| | /// SmallVector. 425| | void toVector(SmallVectorImpl &Out) const; 426| | 427| | /// getSingleStringRef - This returns the twine as a single StringRef. This 428| | /// method is only valid if isSingleStringRef() is true. 429| | StringRef getSingleStringRef() const { 430| | assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); 431| | switch (getLHSKind()) { 432| | default: llvm_unreachable("Out of sync with isSingleStringRef"); 433| | case EmptyKind: return StringRef(); 434| | case CStringKind: return StringRef(LHS.cString); 435| | case StdStringKind: return StringRef(*LHS.stdString); 436| | case StringRefKind: return *LHS.stringRef; 437| | } 438| | } 439| | 440| | /// toStringRef - This returns the twine as a single StringRef if it can be 441| | /// represented as such. Otherwise the twine is written into the given 442| | /// SmallVector and a StringRef to the SmallVector's data is returned. 443| | StringRef toStringRef(SmallVectorImpl &Out) const; 444| | 445| | /// toNullTerminatedStringRef - This returns the twine as a single null 446| | /// terminated StringRef if it can be represented as such. Otherwise the 447| | /// twine is written into the given SmallVector and a StringRef to the 448| | /// SmallVector's data is returned. 449| | /// 450| | /// The returned StringRef's size does not include the null terminator. 451| | StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; 452| | 453| | /// Write the concatenated string represented by this twine to the 454| | /// stream \p OS. 455| | void print(raw_ostream &OS) const; 456| | 457| | /// Dump the concatenated string represented by this twine to stderr. 458| | void dump() const; 459| | 460| | /// Write the representation of this twine to the stream \p OS. 461| | void printRepr(raw_ostream &OS) const; 462| | 463| | /// Dump the representation of this twine to stderr. 464| | void dumpRepr() const; 465| | 466| | /// @} 467| | }; 468| | 469| | /// @name Twine Inline Implementations 470| | /// @{ 471| | 472| 0| inline Twine Twine::concat(const Twine &Suffix) const { 473| 0| // Concatenation with null is null. 474| 0| if (isNull() || Suffix.isNull()) 475| 0| return Twine(NullKind); 476| 0| 477| 0| // Concatenation with empty yields the other side. 478| 0| if (isEmpty()) 479| 0| return Suffix; 480| 0| if (Suffix.isEmpty()) 481| 0| return *this; 482| 0| 483| 0| // Otherwise we need to create a new node, taking care to fold in unary 484| 0| // twines. 485| 0| Child NewLHS, NewRHS; 486| 0| NewLHS.twine = this; 487| 0| NewRHS.twine = &Suffix; 488| 0| NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 489| 0| if (isUnary()) { 490| 0| NewLHS = LHS; 491| 0| NewLHSKind = getLHSKind(); 492| 0| } 493| 0| if (Suffix.isUnary()) { 494| 0| NewRHS = Suffix.LHS; 495| 0| NewRHSKind = Suffix.getLHSKind(); 496| 0| } 497| 0| 498| 0| return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 499| 0| } 500| | 501| 0| inline Twine operator+(const Twine &LHS, const Twine &RHS) { 502| 0| return LHS.concat(RHS); 503| 0| } 504| | 505| | /// Additional overload to guarantee simplified codegen; this is equivalent to 506| | /// concat(). 507| | 508| | inline Twine operator+(const char *LHS, const StringRef &RHS) { 509| | return Twine(LHS, RHS); 510| | } 511| | 512| | /// Additional overload to guarantee simplified codegen; this is equivalent to 513| | /// concat(). 514| | 515| | inline Twine operator+(const StringRef &LHS, const char *RHS) { 516| | return Twine(LHS, RHS); 517| | } 518| | 519| | inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 520| | RHS.print(OS); 521| | return OS; 522| | } 523| | 524| | /// @} 525| |} 526| | 527| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Allocator.h: 1| |//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// \file 10| |/// 11| |/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both 12| |/// of these conform to an LLVM "Allocator" concept which consists of an 13| |/// Allocate method accepting a size and alignment, and a Deallocate accepting 14| |/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of 15| |/// Allocate and Deallocate for setting size and alignment based on the final 16| |/// type. These overloads are typically provided by a base class template \c 17| |/// AllocatorBase. 18| |/// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_SUPPORT_ALLOCATOR_H 22| |#define LLVM_SUPPORT_ALLOCATOR_H 23| | 24| |#include "llvm/ADT/SmallVector.h" 25| |#include "llvm/Support/AlignOf.h" 26| |#include "llvm/Support/DataTypes.h" 27| |#include "llvm/Support/MathExtras.h" 28| |#include "llvm/Support/Memory.h" 29| |#include 30| |#include 31| |#include 32| |#include 33| | 34| |namespace llvm { 35| | 36| |/// \brief CRTP base class providing obvious overloads for the core \c 37| |/// Allocate() methods of LLVM-style allocators. 38| |/// 39| |/// This base class both documents the full public interface exposed by all 40| |/// LLVM-style allocators, and redirects all of the overloads to a single core 41| |/// set of methods which the derived class must define. 42| |template class AllocatorBase { 43| |public: 44| | /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method 45| | /// must be implemented by \c DerivedT. 46| | void *Allocate(size_t Size, size_t Alignment) { 47| |#ifdef __clang__ 48| | static_assert(static_cast( 49| | &AllocatorBase::Allocate) != 50| | static_cast( 51| | &DerivedT::Allocate), 52| | "Class derives from AllocatorBase without implementing the " 53| | "core Allocate(size_t, size_t) overload!"); 54| |#endif 55| | return static_cast(this)->Allocate(Size, Alignment); 56| | } 57| | 58| | /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this 59| | /// allocator. 60| | void Deallocate(const void *Ptr, size_t Size) { 61| |#ifdef __clang__ 62| | static_assert(static_cast( 63| | &AllocatorBase::Deallocate) != 64| | static_cast( 65| | &DerivedT::Deallocate), 66| | "Class derives from AllocatorBase without implementing the " 67| | "core Deallocate(void *) overload!"); 68| |#endif 69| | return static_cast(this)->Deallocate(Ptr, Size); 70| | } 71| | 72| | // The rest of these methods are helpers that redirect to one of the above 73| | // core methods. 74| | 75| | /// \brief Allocate space for a sequence of objects without constructing them. 76| | template T *Allocate(size_t Num = 1) { 77| | return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); 78| | } 79| | 80| | /// \brief Deallocate space for a sequence of objects without constructing them. 81| | template 82| | typename std::enable_if< 83| | !std::is_same::type, void>::value, void>::type 84| | Deallocate(T *Ptr, size_t Num = 1) { 85| | Deallocate(static_cast(Ptr), Num * sizeof(T)); 86| | } 87| |}; 88| | 89| |class MallocAllocator : public AllocatorBase { 90| |public: 91| 0| void Reset() {} 92| | 93| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, 94| | size_t /*Alignment*/) { 95| | return malloc(Size); 96| | } 97| | 98| | // Pull in base class overloads. 99| | using AllocatorBase::Allocate; 100| | 101| 0| void Deallocate(const void *Ptr, size_t /*Size*/) { 102| 0| free(const_cast(Ptr)); 103| 0| } 104| | 105| | // Pull in base class overloads. 106| | using AllocatorBase::Deallocate; 107| | 108| 0| void PrintStats() const {} 109| |}; 110| | 111| |namespace detail { 112| | 113| |// We call out to an external function to actually print the message as the 114| |// printing code uses Allocator.h in its implementation. 115| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 116| | size_t TotalMemory); 117| |} // End namespace detail. 118| | 119| |/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. 120| |/// 121| |/// This isn't strictly a bump-pointer allocator as it uses backing slabs of 122| |/// memory rather than relying on a boundless contiguous heap. However, it has 123| |/// bump-pointer semantics in that it is a monotonically growing pool of memory 124| |/// where every allocation is found by merely allocating the next N bytes in 125| |/// the slab, or the next N bytes in the next slab. 126| |/// 127| |/// Note that this also has a threshold for forcing allocations above a certain 128| |/// size into their own slab. 129| |/// 130| |/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator 131| |/// object, which wraps malloc, to allocate memory, but it can be changed to 132| |/// use a custom allocator. 133| |template 135| |class BumpPtrAllocatorImpl 136| | : public AllocatorBase< 137| | BumpPtrAllocatorImpl> { 138| |public: 139| | static_assert(SizeThreshold <= SlabSize, 140| | "The SizeThreshold must be at most the SlabSize to ensure " 141| | "that objects larger than a slab go into their own memory " 142| | "allocation."); 143| | 144| | BumpPtrAllocatorImpl() 145| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} 146| | template 147| | BumpPtrAllocatorImpl(T &&Allocator) 148| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), 149| | Allocator(std::forward(Allocator)) {} 150| | 151| | // Manually implement a move constructor as we must clear the old allocators 152| | // slabs as a matter of correctness. 153| | BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) 154| | : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), 155| | CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), 156| | BytesAllocated(Old.BytesAllocated), 157| | Allocator(std::move(Old.Allocator)) { 158| | Old.CurPtr = Old.End = nullptr; 159| | Old.BytesAllocated = 0; 160| | Old.Slabs.clear(); 161| | Old.CustomSizedSlabs.clear(); 162| | } 163| | 164| | ~BumpPtrAllocatorImpl() { 165| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 166| | DeallocateCustomSizedSlabs(); 167| | } 168| | 169| | BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { 170| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 171| | DeallocateCustomSizedSlabs(); 172| | 173| | CurPtr = RHS.CurPtr; 174| | End = RHS.End; 175| | BytesAllocated = RHS.BytesAllocated; 176| | Slabs = std::move(RHS.Slabs); 177| | CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); 178| | Allocator = std::move(RHS.Allocator); 179| | 180| | RHS.CurPtr = RHS.End = nullptr; 181| | RHS.BytesAllocated = 0; 182| | RHS.Slabs.clear(); 183| | RHS.CustomSizedSlabs.clear(); 184| | return *this; 185| | } 186| | 187| | /// \brief Deallocate all but the current slab and reset the current pointer 188| | /// to the beginning of it, freeing all memory allocated so far. 189| | void Reset() { 190| | if (Slabs.empty()) 191| | return; 192| | 193| | // Reset the state. 194| | BytesAllocated = 0; 195| | CurPtr = (char *)Slabs.front(); 196| | End = CurPtr + SlabSize; 197| | 198| | // Deallocate all but the first slab, and all custome sized slabs. 199| | DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); 200| | Slabs.erase(std::next(Slabs.begin()), Slabs.end()); 201| | DeallocateCustomSizedSlabs(); 202| | CustomSizedSlabs.clear(); 203| | } 204| | 205| | /// \brief Allocate space at the specified alignment. 206| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { 207| | assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); 208| | 209| | // Keep track of how many bytes we've allocated. 210| | BytesAllocated += Size; 211| | 212| | size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); 213| | assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); 214| | 215| | // Check if we have enough space. 216| | if (Adjustment + Size <= size_t(End - CurPtr)) { 217| | char *AlignedPtr = CurPtr + Adjustment; 218| | CurPtr = AlignedPtr + Size; 219| | // Update the allocation point of this memory block in MemorySanitizer. 220| | // Without this, MemorySanitizer messages for values originated from here 221| | // will point to the allocation of the entire slab. 222| | __msan_allocated_memory(AlignedPtr, Size); 223| | return AlignedPtr; 224| | } 225| | 226| | // If Size is really big, allocate a separate slab for it. 227| | size_t PaddedSize = Size + Alignment - 1; 228| | if (PaddedSize > SizeThreshold) { 229| | void *NewSlab = Allocator.Allocate(PaddedSize, 0); 230| | CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); 231| | 232| | uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); 233| | assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); 234| | char *AlignedPtr = (char*)AlignedAddr; 235| | __msan_allocated_memory(AlignedPtr, Size); 236| | return AlignedPtr; 237| | } 238| | 239| | // Otherwise, start a new slab and try again. 240| | StartNewSlab(); 241| | uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); 242| | assert(AlignedAddr + Size <= (uintptr_t)End && 243| | "Unable to allocate memory!"); 244| | char *AlignedPtr = (char*)AlignedAddr; 245| | CurPtr = AlignedPtr + Size; 246| | __msan_allocated_memory(AlignedPtr, Size); 247| | return AlignedPtr; 248| | } 249| | 250| | // Pull in base class overloads. 251| | using AllocatorBase::Allocate; 252| | 253| | void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} 254| | 255| | // Pull in base class overloads. 256| | using AllocatorBase::Deallocate; 257| | 258| | size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } 259| | 260| | size_t getTotalMemory() const { 261| | size_t TotalMemory = 0; 262| | for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) 263| | TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); 264| | for (auto &PtrAndSize : CustomSizedSlabs) 265| | TotalMemory += PtrAndSize.second; 266| | return TotalMemory; 267| | } 268| | 269| | void PrintStats() const { 270| | detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, 271| | getTotalMemory()); 272| | } 273| | 274| |private: 275| | /// \brief The current pointer into the current slab. 276| | /// 277| | /// This points to the next free byte in the slab. 278| | char *CurPtr; 279| | 280| | /// \brief The end of the current slab. 281| | char *End; 282| | 283| | /// \brief The slabs allocated so far. 284| | SmallVector Slabs; 285| | 286| | /// \brief Custom-sized slabs allocated for too-large allocation requests. 287| | SmallVector, 0> CustomSizedSlabs; 288| | 289| | /// \brief How many bytes we've allocated. 290| | /// 291| | /// Used so that we can compute how much space was wasted. 292| | size_t BytesAllocated; 293| | 294| | /// \brief The allocator instance we use to get slabs of memory. 295| | AllocatorT Allocator; 296| | 297| | static size_t computeSlabSize(unsigned SlabIdx) { 298| | // Scale the actual allocated slab size based on the number of slabs 299| | // allocated. Every 128 slabs allocated, we double the allocated size to 300| | // reduce allocation frequency, but saturate at multiplying the slab size by 301| | // 2^30. 302| | return SlabSize * ((size_t)1 << std::min(30, SlabIdx / 128)); 303| | } 304| | 305| | /// \brief Allocate a new slab and move the bump pointers over into the new 306| | /// slab, modifying CurPtr and End. 307| | void StartNewSlab() { 308| | size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); 309| | 310| | void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); 311| | Slabs.push_back(NewSlab); 312| | CurPtr = (char *)(NewSlab); 313| | End = ((char *)NewSlab) + AllocatedSlabSize; 314| | } 315| | 316| | /// \brief Deallocate a sequence of slabs. 317| | void DeallocateSlabs(SmallVectorImpl::iterator I, 318| | SmallVectorImpl::iterator E) { 319| | for (; I != E; ++I) { 320| | size_t AllocatedSlabSize = 321| | computeSlabSize(std::distance(Slabs.begin(), I)); 322| |#ifndef NDEBUG 323| | // Poison the memory so stale pointers crash sooner. Note we must 324| | // preserve the Size and NextPtr fields at the beginning. 325| | if (AllocatedSlabSize != 0) { 326| | sys::Memory::setRangeWritable(*I, AllocatedSlabSize); 327| | memset(*I, 0xCD, AllocatedSlabSize); 328| | } 329| |#endif 330| | Allocator.Deallocate(*I, AllocatedSlabSize); 331| | } 332| | } 333| | 334| | /// \brief Deallocate all memory for custom sized slabs. 335| | void DeallocateCustomSizedSlabs() { 336| | for (auto &PtrAndSize : CustomSizedSlabs) { 337| | void *Ptr = PtrAndSize.first; 338| | size_t Size = PtrAndSize.second; 339| |#ifndef NDEBUG 340| | // Poison the memory so stale pointers crash sooner. Note we must 341| | // preserve the Size and NextPtr fields at the beginning. 342| | sys::Memory::setRangeWritable(Ptr, Size); 343| | memset(Ptr, 0xCD, Size); 344| |#endif 345| | Allocator.Deallocate(Ptr, Size); 346| | } 347| | } 348| | 349| | template friend class SpecificBumpPtrAllocator; 350| |}; 351| | 352| |/// \brief The standard BumpPtrAllocator which just uses the default template 353| |/// paramaters. 354| |typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 355| | 356| |/// \brief A BumpPtrAllocator that allows only elements of a specific type to be 357| |/// allocated. 358| |/// 359| |/// This allows calling the destructor in DestroyAll() and when the allocator is 360| |/// destroyed. 361| |template class SpecificBumpPtrAllocator { 362| | BumpPtrAllocator Allocator; 363| | 364| |public: 365| | SpecificBumpPtrAllocator() : Allocator() {} 366| | SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) 367| | : Allocator(std::move(Old.Allocator)) {} 368| | ~SpecificBumpPtrAllocator() { DestroyAll(); } 369| | 370| | SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { 371| | Allocator = std::move(RHS.Allocator); 372| | return *this; 373| | } 374| | 375| | /// Call the destructor of each allocated object and deallocate all but the 376| | /// current slab and reset the current pointer to the beginning of it, freeing 377| | /// all memory allocated so far. 378| | void DestroyAll() { 379| | auto DestroyElements = [](char *Begin, char *End) { 380| | assert(Begin == (char*)alignAddr(Begin, alignOf())); 381| | for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) 382| | reinterpret_cast(Ptr)->~T(); 383| | }; 384| | 385| | for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; 386| | ++I) { 387| | size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( 388| | std::distance(Allocator.Slabs.begin(), I)); 389| | char *Begin = (char*)alignAddr(*I, alignOf()); 390| | char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr 391| | : (char *)*I + AllocatedSlabSize; 392| | 393| | DestroyElements(Begin, End); 394| | } 395| | 396| | for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { 397| | void *Ptr = PtrAndSize.first; 398| | size_t Size = PtrAndSize.second; 399| | DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); 400| | } 401| | 402| | Allocator.Reset(); 403| | } 404| | 405| | /// \brief Allocate space for an array of objects without constructing them. 406| | T *Allocate(size_t num = 1) { return Allocator.Allocate(num); } 407| |}; 408| | 409| |} // end namespace llvm 410| | 411| |template 412| |void *operator new(size_t Size, 413| | llvm::BumpPtrAllocatorImpl &Allocator) { 415| | struct S { 416| | char c; 417| | union { 418| | double D; 419| | long double LD; 420| | long long L; 421| | void *P; 422| | } x; 423| | }; 424| | return Allocator.Allocate( 425| | Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); 426| |} 427| | 428| |template 429| |void operator delete( 430| | void *, llvm::BumpPtrAllocatorImpl &) { 431| |} 432| | 433| |#endif // LLVM_SUPPORT_ALLOCATOR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/CBindingWrapping.h: 1| |//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the wrapping macros for the C interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H 15| |#define LLVM_SUPPORT_CBINDINGWRAPPING_H 16| | 17| |#include "llvm/Support/Casting.h" 18| | 19| |#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 20| 0| inline ty *unwrap(ref P) { \ 21| 0| return reinterpret_cast(P); \ 22| 0| } \ 23| | \ 24| 0| inline ref wrap(const ty *P) { \ 25| 0| return reinterpret_cast(const_cast(P)); \ 26| 0| } 27| | 28| |#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ 29| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 30| | \ 31| | template \ 32| | inline T *unwrap(ref P) { \ 33| | return cast(unwrap(P)); \ 34| | } 35| | 36| |#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ 37| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 38| | \ 39| | template \ 40| | inline T *unwrap(ref P) { \ 41| | T *Q = (T*)unwrap(P); \ 42| | assert(Q && "Invalid cast!"); \ 43| | return Q; \ 44| | } 45| | 46| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Compiler.h: 1| |//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines several macros, based on the current compiler. This allows 11| |// use of compiler-specific features in a way that remains portable. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_COMPILER_H 16| |#define LLVM_SUPPORT_COMPILER_H 17| | 18| |#include "llvm/Config/llvm-config.h" 19| | 20| |#ifndef __has_feature 21| |# define __has_feature(x) 0 22| |#endif 23| | 24| |#ifndef __has_extension 25| |# define __has_extension(x) 0 26| |#endif 27| | 28| |#ifndef __has_attribute 29| |# define __has_attribute(x) 0 30| |#endif 31| | 32| |#ifndef __has_builtin 33| |# define __has_builtin(x) 0 34| |#endif 35| | 36| |/// \macro LLVM_GNUC_PREREQ 37| |/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't 38| |/// available. 39| |#ifndef LLVM_GNUC_PREREQ 40| |# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 42| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43| | ((maj) << 20) + ((min) << 10) + (patch)) 44| |# elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 46| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47| |# else 48| |# define LLVM_GNUC_PREREQ(maj, min, patch) 0 49| |# endif 50| |#endif 51| | 52| |/// \macro LLVM_MSC_PREREQ 53| |/// \brief Is the compiler MSVC of at least the specified version? 54| |/// The common \param version values to check for are: 55| |/// * 1800: Microsoft Visual Studio 2013 / 12.0 56| |/// * 1900: Microsoft Visual Studio 2015 / 14.0 57| |#ifdef _MSC_VER 58| |#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) 59| | 60| |// We require at least MSVC 2013. 61| |#if !LLVM_MSC_PREREQ(1800) 62| |#error LLVM requires at least MSVC 2013. 63| |#endif 64| | 65| |#else 66| |#define LLVM_MSC_PREREQ(version) 0 67| |#endif 68| | 69| |#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) 70| |#define LLVM_NOEXCEPT noexcept 71| |#else 72| |#define LLVM_NOEXCEPT 73| |#endif 74| | 75| |/// \brief Does the compiler support r-value reference *this? 76| |/// 77| |/// Sadly, this is separate from just r-value reference support because GCC 78| |/// implemented this later than everything else. 79| |#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) 80| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 81| |#else 82| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 83| |#endif 84| | 85| |/// Expands to '&' if r-value references are supported. 86| |/// 87| |/// This can be used to provide l-value/r-value overrides of member functions. 88| |/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS 89| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 90| |#define LLVM_LVALUE_FUNCTION & 91| |#else 92| |#define LLVM_LVALUE_FUNCTION 93| |#endif 94| | 95| |#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) 96| |# define LLVM_CONSTEXPR constexpr 97| |#else 98| |# define LLVM_CONSTEXPR 99| |#endif 100| | 101| |/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked 102| |/// into a shared library, then the class should be private to the library and 103| |/// not accessible from outside it. Can also be used to mark variables and 104| |/// functions, making them private to any shared library they are linked into. 105| |/// On PE/COFF targets, library visibility is the default, so this isn't needed. 106| |#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 107| | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) 108| |#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) 109| |#else 110| |#define LLVM_LIBRARY_VISIBILITY 111| |#endif 112| | 113| |#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) 114| |#define LLVM_END_WITH_NULL __attribute__((sentinel)) 115| |#else 116| |#define LLVM_END_WITH_NULL 117| |#endif 118| | 119| |#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) 120| |#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) 121| |#else 122| |#define LLVM_ATTRIBUTE_USED 123| |#endif 124| | 125| |#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) 126| |#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) 127| |#else 128| |#define LLVM_ATTRIBUTE_UNUSED_RESULT 129| |#endif 130| | 131| |// Some compilers warn about unused functions. When a function is sometimes 132| |// used or not depending on build settings (e.g. a function only called from 133| |// within "assert"), this attribute can be used to suppress such warnings. 134| |// 135| |// However, it shouldn't be used for unused *variables*, as those have a much 136| |// more portable solution: 137| |// (void)unused_var_name; 138| |// Prefer cast-to-void wherever it is sufficient. 139| |#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) 140| |#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) 141| |#else 142| |#define LLVM_ATTRIBUTE_UNUSED 143| |#endif 144| | 145| |// FIXME: Provide this for PE/COFF targets. 146| |#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 147| | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) 148| |#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) 149| |#else 150| |#define LLVM_ATTRIBUTE_WEAK 151| |#endif 152| | 153| |// Prior to clang 3.2, clang did not accept any spelling of 154| |// __has_attribute(const), so assume it is supported. 155| |#if defined(__clang__) || defined(__GNUC__) 156| |// aka 'CONST' but following LLVM Conventions. 157| |#define LLVM_READNONE __attribute__((__const__)) 158| |#else 159| |#define LLVM_READNONE 160| |#endif 161| | 162| |#if __has_attribute(pure) || defined(__GNUC__) 163| |// aka 'PURE' but following LLVM Conventions. 164| |#define LLVM_READONLY __attribute__((__pure__)) 165| |#else 166| |#define LLVM_READONLY 167| |#endif 168| | 169| |#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) 170| |#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) 171| 0|#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) 172| |#else 173| |#define LLVM_LIKELY(EXPR) (EXPR) 174| |#define LLVM_UNLIKELY(EXPR) (EXPR) 175| |#endif 176| | 177| |// C++ doesn't support 'extern template' of template specializations. GCC does, 178| |// but requires __extension__ before it. In the header, use this: 179| |// EXTERN_TEMPLATE_INSTANTIATION(class foo); 180| |// in the .cpp file, use this: 181| |// TEMPLATE_INSTANTIATION(class foo); 182| |#ifdef __GNUC__ 183| |#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X 184| |#define TEMPLATE_INSTANTIATION(X) template X 185| |#else 186| |#define EXTERN_TEMPLATE_INSTANTIATION(X) 187| |#define TEMPLATE_INSTANTIATION(X) 188| |#endif 189| | 190| |/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, 191| |/// mark a method "not for inlining". 192| |#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) 193| |#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) 194| |#elif defined(_MSC_VER) 195| |#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) 196| |#else 197| |#define LLVM_ATTRIBUTE_NOINLINE 198| |#endif 199| | 200| |/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do 201| |/// so, mark a method "always inline" because it is performance sensitive. GCC 202| |/// 3.4 supported this but is buggy in various cases and produces unimplemented 203| |/// errors, just use it in GCC 4.0 and later. 204| |#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) 205| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) 206| |#elif defined(_MSC_VER) 207| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline 208| |#else 209| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE 210| |#endif 211| | 212| |#ifdef __GNUC__ 213| |#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) 214| |#elif defined(_MSC_VER) 215| |#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) 216| |#else 217| |#define LLVM_ATTRIBUTE_NORETURN 218| |#endif 219| | 220| |#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) 221| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 222| |#else 223| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL 224| |#endif 225| | 226| |/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress 227| |/// pedantic diagnostics. 228| |#ifdef __GNUC__ 229| |#define LLVM_EXTENSION __extension__ 230| |#else 231| |#define LLVM_EXTENSION 232| |#endif 233| | 234| |// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") 235| |#if __has_feature(attribute_deprecated_with_message) 236| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 237| | decl __attribute__((deprecated(message))) 238| |#elif defined(__GNUC__) 239| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 240| | decl __attribute__((deprecated)) 241| |#elif defined(_MSC_VER) 242| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 243| | __declspec(deprecated(message)) decl 244| |#else 245| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 246| | decl 247| |#endif 248| | 249| |/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands 250| |/// to an expression which states that it is undefined behavior for the 251| |/// compiler to reach this point. Otherwise is not defined. 252| |#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) 253| |# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() 254| |#elif defined(_MSC_VER) 255| |# define LLVM_BUILTIN_UNREACHABLE __assume(false) 256| |#endif 257| | 258| |/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression 259| |/// which causes the program to exit abnormally. 260| |#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) 261| |# define LLVM_BUILTIN_TRAP __builtin_trap() 262| |#elif defined(_MSC_VER) 263| |// The __debugbreak intrinsic is supported by MSVC, does not require forward 264| |// declarations involving platform-specific typedefs (unlike RaiseException), 265| |// results in a call to vectored exception handlers, and encodes to a short 266| |// instruction that still causes the trapping behavior we want. 267| |# define LLVM_BUILTIN_TRAP __debugbreak() 268| |#else 269| |# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 270| |#endif 271| | 272| |/// \macro LLVM_ASSUME_ALIGNED 273| |/// \brief Returns a pointer with an assumed alignment. 274| |#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) 275| |# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) 276| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 277| |// As of today, clang does not support __builtin_assume_aligned. 278| |# define LLVM_ASSUME_ALIGNED(p, a) \ 279| | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) 280| |#else 281| |# define LLVM_ASSUME_ALIGNED(p, a) (p) 282| |#endif 283| | 284| |/// \macro LLVM_FUNCTION_NAME 285| |/// \brief Expands to __func__ on compilers which support it. Otherwise, 286| |/// expands to a compiler-dependent replacement. 287| |#if defined(_MSC_VER) 288| |# define LLVM_FUNCTION_NAME __FUNCTION__ 289| |#else 290| |# define LLVM_FUNCTION_NAME __func__ 291| |#endif 292| | 293| |/// \macro LLVM_MEMORY_SANITIZER_BUILD 294| |/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. 295| |#if __has_feature(memory_sanitizer) 296| |# define LLVM_MEMORY_SANITIZER_BUILD 1 297| |# include 298| |#else 299| |# define LLVM_MEMORY_SANITIZER_BUILD 0 300| |# define __msan_allocated_memory(p, size) 301| |# define __msan_unpoison(p, size) 302| |#endif 303| | 304| |/// \macro LLVM_ADDRESS_SANITIZER_BUILD 305| |/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. 306| |#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 307| |# define LLVM_ADDRESS_SANITIZER_BUILD 1 308| |#else 309| |# define LLVM_ADDRESS_SANITIZER_BUILD 0 310| |#endif 311| | 312| |/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST 313| |/// \brief Is unaligned memory access fast on the host machine. 314| |/// 315| |/// Don't specialize on alignment for platforms where unaligned memory accesses 316| |/// generates the same code as aligned memory accesses for common types. 317| |#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ 318| | defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ 319| | defined(_X86_) || defined(__i386) || defined(__i386__) 320| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 321| |#else 322| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 323| |#endif 324| | 325| |/// \brief Mark debug helper function definitions like dump() that should not be 326| |/// stripped from debug builds. 327| |// FIXME: Move this to a private config.h as it's not usable in public headers. 328| |#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED 330| |#else 331| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE 332| |#endif 333| | 334| |/// \macro LLVM_THREAD_LOCAL 335| |/// \brief A thread-local storage specifier which can be used with globals, 336| |/// extern globals, and static globals. 337| |/// 338| |/// This is essentially an extremely restricted analog to C++11's thread_local 339| |/// support, and uses that when available. However, it falls back on 340| |/// platform-specific or vendor-provided extensions when necessary. These 341| |/// extensions don't support many of the C++11 thread_local's features. You 342| |/// should only use this for PODs that you can statically initialize to 343| |/// some constant value. In almost all circumstances this is most appropriate 344| |/// for use with a pointer, integer, or small aggregation of pointers and 345| |/// integers. 346| |#if LLVM_ENABLE_THREADS 347| |#if __has_feature(cxx_thread_local) 348| |#define LLVM_THREAD_LOCAL thread_local 349| |#elif defined(_MSC_VER) 350| |// MSVC supports this with a __declspec. 351| |#define LLVM_THREAD_LOCAL __declspec(thread) 352| |#else 353| |// Clang, GCC, and other compatible compilers used __thread prior to C++11 and 354| |// we only need the restricted functionality that provides. 355| |#define LLVM_THREAD_LOCAL __thread 356| |#endif 357| |#else // !LLVM_ENABLE_THREADS 358| |// If threading is disabled entirely, this compiles to nothing and you get 359| |// a normal global variable. 360| |#define LLVM_THREAD_LOCAL 361| |#endif 362| | 363| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ConvertUTF.h: 1| |/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== 2| | * 3| | * The LLVM Compiler Infrastructure 4| | * 5| | * This file is distributed under the University of Illinois Open Source 6| | * License. See LICENSE.TXT for details. 7| | * 8| | *==------------------------------------------------------------------------==*/ 9| |/* 10| | * Copyright 2001-2004 Unicode, Inc. 11| | * 12| | * Disclaimer 13| | * 14| | * This source code is provided as is by Unicode, Inc. No claims are 15| | * made as to fitness for any particular purpose. No warranties of any 16| | * kind are expressed or implied. The recipient agrees to determine 17| | * applicability of information provided. If this file has been 18| | * purchased on magnetic or optical media from Unicode, Inc., the 19| | * sole remedy for any claim will be exchange of defective media 20| | * within 90 days of receipt. 21| | * 22| | * Limitations on Rights to Redistribute This Code 23| | * 24| | * Unicode, Inc. hereby grants the right to freely use the information 25| | * supplied in this file in the creation of products supporting the 26| | * Unicode Standard, and to make copies of this file in any form 27| | * for internal or external distribution as long as this notice 28| | * remains attached. 29| | */ 30| | 31| |/* --------------------------------------------------------------------- 32| | 33| | Conversions between UTF32, UTF-16, and UTF-8. Header file. 34| | 35| | Several funtions are included here, forming a complete set of 36| | conversions between the three formats. UTF-7 is not included 37| | here, but is handled in a separate source file. 38| | 39| | Each of these routines takes pointers to input buffers and output 40| | buffers. The input buffers are const. 41| | 42| | Each routine converts the text between *sourceStart and sourceEnd, 43| | putting the result into the buffer between *targetStart and 44| | targetEnd. Note: the end pointers are *after* the last item: e.g. 45| | *(sourceEnd - 1) is the last item. 46| | 47| | The return result indicates whether the conversion was successful, 48| | and if not, whether the problem was in the source or target buffers. 49| | (Only the first encountered problem is indicated.) 50| | 51| | After the conversion, *sourceStart and *targetStart are both 52| | updated to point to the end of last text successfully converted in 53| | the respective buffers. 54| | 55| | Input parameters: 56| | sourceStart - pointer to a pointer to the source buffer. 57| | The contents of this are modified on return so that 58| | it points at the next thing to be converted. 59| | targetStart - similarly, pointer to pointer to the target buffer. 60| | sourceEnd, targetEnd - respectively pointers to the ends of the 61| | two buffers, for overflow checking only. 62| | 63| | These conversion functions take a ConversionFlags argument. When this 64| | flag is set to strict, both irregular sequences and isolated surrogates 65| | will cause an error. When the flag is set to lenient, both irregular 66| | sequences and isolated surrogates are converted. 67| | 68| | Whether the flag is strict or lenient, all illegal sequences will cause 69| | an error return. This includes sequences such as: , , 70| | or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code 71| | must check for illegal sequences. 72| | 73| | When the flag is set to lenient, characters over 0x10FFFF are converted 74| | to the replacement character; otherwise (when the flag is set to strict) 75| | they constitute an error. 76| | 77| | Output parameters: 78| | The value "sourceIllegal" is returned from some routines if the input 79| | sequence is malformed. When "sourceIllegal" is returned, the source 80| | value will point to the illegal value that caused the problem. E.g., 81| | in UTF-8 when a sequence is malformed, it points to the start of the 82| | malformed sequence. 83| | 84| | Author: Mark E. Davis, 1994. 85| | Rev History: Rick McGowan, fixes & updates May 2001. 86| | Fixes & updates, Sept 2001. 87| | 88| |------------------------------------------------------------------------ */ 89| | 90| |#ifndef LLVM_SUPPORT_CONVERTUTF_H 91| |#define LLVM_SUPPORT_CONVERTUTF_H 92| | 93| |/* --------------------------------------------------------------------- 94| | The following 4 definitions are compiler-specific. 95| | The C standard does not guarantee that wchar_t has at least 96| | 16 bits, so wchar_t is no less portable than unsigned short! 97| | All should be unsigned values to avoid sign extension during 98| | bit mask & shift operations. 99| |------------------------------------------------------------------------ */ 100| | 101| |typedef unsigned int UTF32; /* at least 32 bits */ 102| |typedef unsigned short UTF16; /* at least 16 bits */ 103| |typedef unsigned char UTF8; /* typically 8 bits */ 104| |typedef unsigned char Boolean; /* 0 or 1 */ 105| | 106| |/* Some fundamental constants */ 107| |#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD 108| |#define UNI_MAX_BMP (UTF32)0x0000FFFF 109| |#define UNI_MAX_UTF16 (UTF32)0x0010FFFF 110| |#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF 111| |#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF 112| | 113| |#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 114| | 115| |#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF 116| |#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE 117| | 118| |typedef enum { 119| | conversionOK, /* conversion successful */ 120| | sourceExhausted, /* partial character in source, but hit end */ 121| | targetExhausted, /* insuff. room in target for conversion */ 122| | sourceIllegal /* source sequence is illegal/malformed */ 123| |} ConversionResult; 124| | 125| |typedef enum { 126| | strictConversion = 0, 127| | lenientConversion 128| |} ConversionFlags; 129| | 130| |/* This is for C++ and does no harm in C */ 131| |#ifdef __cplusplus 132| |extern "C" { 133| |#endif 134| | 135| |ConversionResult ConvertUTF8toUTF16 ( 136| | const UTF8** sourceStart, const UTF8* sourceEnd, 137| | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); 138| | 139| |/** 140| | * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an 141| | * incomplete code unit sequence, returns \c sourceExhausted. 142| | */ 143| |ConversionResult ConvertUTF8toUTF32Partial( 144| | const UTF8** sourceStart, const UTF8* sourceEnd, 145| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 146| | 147| |/** 148| | * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an 149| | * incomplete code unit sequence, returns \c sourceIllegal. 150| | */ 151| |ConversionResult ConvertUTF8toUTF32( 152| | const UTF8** sourceStart, const UTF8* sourceEnd, 153| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 154| | 155| |ConversionResult ConvertUTF16toUTF8 ( 156| | const UTF16** sourceStart, const UTF16* sourceEnd, 157| | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); 158| | 159| |ConversionResult ConvertUTF32toUTF8 ( 160| | const UTF32** sourceStart, const UTF32* sourceEnd, 161| | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); 162| | 163| |ConversionResult ConvertUTF16toUTF32 ( 164| | const UTF16** sourceStart, const UTF16* sourceEnd, 165| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 166| | 167| |ConversionResult ConvertUTF32toUTF16 ( 168| | const UTF32** sourceStart, const UTF32* sourceEnd, 169| | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); 170| | 171| |Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); 172| | 173| |Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); 174| | 175| |unsigned getNumBytesForUTF8(UTF8 firstByte); 176| | 177| |#ifdef __cplusplus 178| |} 179| | 180| |/*************************************************************************/ 181| |/* Below are LLVM-specific wrappers of the functions above. */ 182| | 183| |#include "llvm/ADT/ArrayRef.h" 184| |#include "llvm/ADT/StringRef.h" 185| | 186| |namespace llvm { 187| | 188| |/** 189| | * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on 190| | * WideCharWidth. The converted data is written to ResultPtr, which needs to 191| | * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, 192| | * ResultPtr will point one after the end of the copied string. On failure, 193| | * ResultPtr will not be changed, and ErrorPtr will be set to the location of 194| | * the first character which could not be converted. 195| | * \return true on success. 196| | */ 197| |bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, 198| | char *&ResultPtr, const UTF8 *&ErrorPtr); 199| | 200| |/** 201| | * Convert an Unicode code point to UTF8 sequence. 202| | * 203| | * \param Source a Unicode code point. 204| | * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least 205| | * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is 206| | * updated one past end of the converted sequence. 207| | * 208| | * \returns true on success. 209| | */ 210| |bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); 211| | 212| |/** 213| | * Convert the first UTF8 sequence in the given source buffer to a UTF32 214| | * code point. 215| | * 216| | * \param [in,out] source A pointer to the source buffer. If the conversion 217| | * succeeds, this pointer will be updated to point to the byte just past the 218| | * end of the converted sequence. 219| | * \param sourceEnd A pointer just past the end of the source buffer. 220| | * \param [out] target The converted code 221| | * \param flags Whether the conversion is strict or lenient. 222| | * 223| | * \returns conversionOK on success 224| | * 225| | * \sa ConvertUTF8toUTF32 226| | */ 227| |static inline ConversionResult convertUTF8Sequence(const UTF8 **source, 228| | const UTF8 *sourceEnd, 229| | UTF32 *target, 230| 0| ConversionFlags flags) { 231| 0| if (*source == sourceEnd) 232| 0| return sourceExhausted; 233| 0| unsigned size = getNumBytesForUTF8(**source); 234| 0| if ((ptrdiff_t)size > sourceEnd - *source) 235| 0| return sourceExhausted; 236| 0| return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); 237| 0|} ------------------ | Unexecuted instantiation: PlatformUtility.cpp:_ZN4llvmL19convertUTF8SequenceEPPKhS1_Pj15ConversionFlags ------------------ | Unexecuted instantiation: Subprocess.cpp:_ZN4llvmL19convertUTF8SequenceEPPKhS1_Pj15ConversionFlags ------------------ 238| | 239| |/** 240| | * Returns true if a blob of text starts with a UTF-16 big or little endian byte 241| | * order mark. 242| | */ 243| |bool hasUTF16ByteOrderMark(ArrayRef SrcBytes); 244| | 245| |/** 246| | * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. 247| | * 248| | * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. 249| | * \param [out] Out Converted UTF-8 is stored here on success. 250| | * \returns true on success 251| | */ 252| |bool convertUTF16ToUTF8String(ArrayRef SrcBytes, std::string &Out); 253| | 254| |/** 255| | * Converts a UTF-8 string into a UTF-16 string with native endianness. 256| | * 257| | * \returns true on success 258| | */ 259| |bool convertUTF8ToUTF16String(StringRef SrcUTF8, 260| | SmallVectorImpl &DstUTF16); 261| | 262| |} /* end namespace llvm */ 263| | 264| |#endif 265| | 266| |/* --------------------------------------------------------------------- */ 267| | 268| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorHandling.h: 1| |//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ERRORHANDLING_H 16| |#define LLVM_SUPPORT_ERRORHANDLING_H 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include 21| | 22| |namespace llvm { 23| | class Twine; 24| | 25| | /// An error handler callback. 26| | typedef void (*fatal_error_handler_t)(void *user_data, 27| | const std::string& reason, 28| | bool gen_crash_diag); 29| | 30| | /// install_fatal_error_handler - Installs a new error handler to be used 31| | /// whenever a serious (non-recoverable) error is encountered by LLVM. 32| | /// 33| | /// If no error handler is installed the default is to print the error message 34| | /// to stderr, and call exit(1). If an error handler is installed then it is 35| | /// the handler's responsibility to log the message, it will no longer be 36| | /// printed to stderr. If the error handler returns, then exit(1) will be 37| | /// called. 38| | /// 39| | /// It is dangerous to naively use an error handler which throws an exception. 40| | /// Even though some applications desire to gracefully recover from arbitrary 41| | /// faults, blindly throwing exceptions through unfamiliar code isn't a way to 42| | /// achieve this. 43| | /// 44| | /// \param user_data - An argument which will be passed to the install error 45| | /// handler. 46| | void install_fatal_error_handler(fatal_error_handler_t handler, 47| | void *user_data = nullptr); 48| | 49| | /// Restores default error handling behaviour. 50| | void remove_fatal_error_handler(); 51| | 52| | /// ScopedFatalErrorHandler - This is a simple helper class which just 53| | /// calls install_fatal_error_handler in its constructor and 54| | /// remove_fatal_error_handler in its destructor. 55| | struct ScopedFatalErrorHandler { 56| | explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, 57| 0| void *user_data = nullptr) { 58| 0| install_fatal_error_handler(handler, user_data); 59| 0| } 60| | 61| 0| ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } 62| | }; 63| | 64| | /// Reports a serious error, calling any installed error handler. These 65| | /// functions are intended to be used for error conditions which are outside 66| | /// the control of the compiler (I/O errors, invalid user input, etc.) 67| | /// 68| | /// If no error handler is installed the default is to print the message to 69| | /// standard error, followed by a newline. 70| | /// After the error handler is called this function will call exit(1), it 71| | /// does not return. 72| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, 73| | bool gen_crash_diag = true); 74| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, 75| | bool gen_crash_diag = true); 76| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, 77| | bool gen_crash_diag = true); 78| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, 79| | bool gen_crash_diag = true); 80| | 81| | /// This function calls abort(), and prints the optional message to stderr. 82| | /// Use the llvm_unreachable macro (that adds location info), instead of 83| | /// calling this function directly. 84| | LLVM_ATTRIBUTE_NORETURN void 85| | llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, 86| | unsigned line=0); 87| |} 88| | 89| |/// Marks that the current location is not supposed to be reachable. 90| |/// In !NDEBUG builds, prints the message and location info to stderr. 91| |/// In NDEBUG builds, becomes an optimizer hint that the current location 92| |/// is not supposed to be reachable. On compilers that don't support 93| |/// such hints, prints a reduced message instead. 94| |/// 95| |/// Use this instead of assert(0). It conveys intent more clearly and 96| |/// allows compilers to omit some unnecessary code. 97| |#ifndef NDEBUG 98| |#define llvm_unreachable(msg) \ 99| | ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) 100| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 101| |#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE 102| |#else 103| |#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() 104| |#endif 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorOr.h: 1| |//===- llvm/Support/ErrorOr.h - Error Smart Pointer -----------------------===// 2| |// 3| |// The LLVM Linker 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// 10| |/// \file 11| |/// 12| |/// Provides ErrorOr smart pointer. 13| |/// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_ERROROR_H 17| |#define LLVM_SUPPORT_ERROROR_H 18| | 19| |#include "llvm/ADT/PointerIntPair.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |template 27| |typename std::enable_if< std::is_constructible::value 28| | , typename std::remove_reference::type>::type && 29| | moveIfMoveConstructible(V &Val) { 30| | return std::move(Val); 31| |} 32| | 33| |template 34| |typename std::enable_if< !std::is_constructible::value 35| | , typename std::remove_reference::type>::type & 36| |moveIfMoveConstructible(V &Val) { 37| | return Val; 38| |} 39| | 40| |/// \brief Stores a reference that can be changed. 41| |template 42| |class ReferenceStorage { 43| | T *Storage; 44| | 45| |public: 46| | ReferenceStorage(T &Ref) : Storage(&Ref) {} 47| | 48| | operator T &() const { return *Storage; } 49| | T &get() const { return *Storage; } 50| |}; 51| | 52| |/// \brief Represents either an error or a value T. 53| |/// 54| |/// ErrorOr is a pointer-like class that represents the result of an 55| |/// operation. The result is either an error, or a value of type T. This is 56| |/// designed to emulate the usage of returning a pointer where nullptr indicates 57| |/// failure. However instead of just knowing that the operation failed, we also 58| |/// have an error_code and optional user data that describes why it failed. 59| |/// 60| |/// It is used like the following. 61| |/// \code 62| |/// ErrorOr getBuffer(); 63| |/// 64| |/// auto buffer = getBuffer(); 65| |/// if (error_code ec = buffer.getError()) 66| |/// return ec; 67| |/// buffer->write("adena"); 68| |/// \endcode 69| |/// 70| |/// 71| |/// Implicit conversion to bool returns true if there is a usable value. The 72| |/// unary * and -> operators provide pointer like access to the value. Accessing 73| |/// the value when there is an error has undefined behavior. 74| |/// 75| |/// When T is a reference type the behaivor is slightly different. The reference 76| |/// is held in a std::reference_wrapper::type>, and 77| |/// there is special handling to make operator -> work as if T was not a 78| |/// reference. 79| |/// 80| |/// T cannot be a rvalue reference. 81| |template 82| |class ErrorOr { 83| | template friend class ErrorOr; 84| | static const bool isRef = std::is_reference::value; 85| | typedef ReferenceStorage::type> wrap; 86| | 87| |public: 88| | typedef typename std::conditional::type storage_type; 89| | 90| |private: 91| | typedef typename std::remove_reference::type &reference; 92| | typedef const typename std::remove_reference::type &const_reference; 93| | typedef typename std::remove_reference::type *pointer; 94| | 95| |public: 96| | template 97| | ErrorOr(E ErrorCode, 98| | typename std::enable_if::value || 99| | std::is_error_condition_enum::value, 100| | void *>::type = 0) 101| | : HasError(true) { 102| | new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); 103| | } 104| | 105| | ErrorOr(std::error_code EC) : HasError(true) { 106| | new (getErrorStorage()) std::error_code(EC); 107| | } 108| | 109| | ErrorOr(T Val) : HasError(false) { 110| | new (getStorage()) storage_type(moveIfMoveConstructible(Val)); 111| | } 112| | 113| | ErrorOr(const ErrorOr &Other) { 114| | copyConstruct(Other); 115| | } 116| | 117| | template 118| | ErrorOr( 119| | const ErrorOr &Other, 120| | typename std::enable_if::value>::type * = 121| | nullptr) { 122| | copyConstruct(Other); 123| | } 124| | 125| | template 126| | explicit ErrorOr( 127| | const ErrorOr &Other, 128| | typename std::enable_if< 129| | !std::is_convertible::value>::type * = nullptr) { 130| | copyConstruct(Other); 131| | } 132| | 133| | ErrorOr(ErrorOr &&Other) { 134| | moveConstruct(std::move(Other)); 135| | } 136| | 137| | template 138| | ErrorOr( 139| | ErrorOr &&Other, 140| | typename std::enable_if::value>::type * = 141| | nullptr) { 142| | moveConstruct(std::move(Other)); 143| | } 144| | 145| | // This might eventually need SFINAE but it's more complex than is_convertible 146| | // & I'm too lazy to write it right now. 147| | template 148| | explicit ErrorOr( 149| | ErrorOr &&Other, 150| | typename std::enable_if::value>::type * = 151| | nullptr) { 152| | moveConstruct(std::move(Other)); 153| | } 154| | 155| | ErrorOr &operator=(const ErrorOr &Other) { 156| | copyAssign(Other); 157| | return *this; 158| | } 159| | 160| | ErrorOr &operator=(ErrorOr &&Other) { 161| | moveAssign(std::move(Other)); 162| | return *this; 163| | } 164| | 165| 0| ~ErrorOr() { 166| 0| if (!HasError) 167| 0| getStorage()->~storage_type(); 168| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEED2Ev ------------------ 169| | 170| | /// \brief Return false if there is an error. 171| | explicit operator bool() const { 172| | return !HasError; 173| | } 174| | 175| | reference get() { return *getStorage(); } 176| | const_reference get() const { return const_cast *>(this)->get(); } 177| | 178| 0| std::error_code getError() const { 179| 0| return HasError ? *getErrorStorage() : std::error_code(); 180| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE8getErrorEv ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE8getErrorEv ------------------ 181| | 182| 0| pointer operator ->() { 183| 0| return toPointer(getStorage()); 184| 0| } 185| | 186| 0| reference operator *() { 187| 0| return *getStorage(); 188| 0| } 189| | 190| |private: 191| | template 192| | void copyConstruct(const ErrorOr &Other) { 193| | if (!Other.HasError) { 194| | // Get the other value. 195| | HasError = false; 196| | new (getStorage()) storage_type(*Other.getStorage()); 197| | } else { 198| | // Get other's error. 199| | HasError = true; 200| | new (getErrorStorage()) std::error_code(Other.getError()); 201| | } 202| | } 203| | 204| | template 205| | static bool compareThisIfSameType(const T1 &a, const T1 &b) { 206| | return &a == &b; 207| | } 208| | 209| | template 210| | static bool compareThisIfSameType(const T1 &a, const T2 &b) { 211| | return false; 212| | } 213| | 214| | template 215| | void copyAssign(const ErrorOr &Other) { 216| | if (compareThisIfSameType(*this, Other)) 217| | return; 218| | 219| | this->~ErrorOr(); 220| | new (this) ErrorOr(Other); 221| | } 222| | 223| | template 224| 0| void moveConstruct(ErrorOr &&Other) { 225| 0| if (!Other.HasError) { 226| 0| // Get the other value. 227| 0| HasError = false; 228| 0| new (getStorage()) storage_type(std::move(*Other.getStorage())); 229| 0| } else { 230| 0| // Get other's error. 231| 0| HasError = true; 232| 0| new (getErrorStorage()) std::error_code(Other.getError()); 233| 0| } 234| 0| } 235| | 236| | template 237| | void moveAssign(ErrorOr &&Other) { 238| | if (compareThisIfSameType(*this, Other)) 239| | return; 240| | 241| | this->~ErrorOr(); 242| | new (this) ErrorOr(std::move(Other)); 243| | } 244| | 245| 0| pointer toPointer(pointer Val) { 246| 0| return Val; 247| 0| } 248| | 249| | pointer toPointer(wrap *Val) { 250| | return &Val->get(); 251| | } 252| | 253| 0| storage_type *getStorage() { 254| 0| assert(!HasError && "Cannot get value when an error exists!"); 255| 0| return reinterpret_cast(TStorage.buffer); 256| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE10getStorageEv ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE10getStorageEv ------------------ 257| | 258| | const storage_type *getStorage() const { 259| | assert(!HasError && "Cannot get value when an error exists!"); 260| | return reinterpret_cast(TStorage.buffer); 261| | } 262| | 263| 0| std::error_code *getErrorStorage() { 264| 0| assert(HasError && "Cannot get error when a value exists!"); 265| 0| return reinterpret_cast(ErrorStorage.buffer); 266| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE15getErrorStorageEv ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE15getErrorStorageEv ------------------ 267| | 268| 0| const std::error_code *getErrorStorage() const { 269| 0| return const_cast *>(this)->getErrorStorage(); 270| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE15getErrorStorageEv ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE15getErrorStorageEv ------------------ 271| | 272| | 273| | union { 274| | AlignedCharArrayUnion TStorage; 275| | AlignedCharArrayUnion ErrorStorage; 276| | }; 277| | bool HasError : 1; 278| |}; 279| | 280| |template 281| |typename std::enable_if::value || 282| | std::is_error_condition_enum::value, 283| | bool>::type 284| |operator==(ErrorOr &Err, E Code) { 285| | return std::error_code(Err) == Code; 286| |} 287| |} // end namespace llvm 288| | 289| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/FileSystem.h: 1| |//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::fs namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |// All functions return an error_code and their actual work via the last out 15| |// argument. The out argument is defined if and only if errc::success is 16| |// returned. A function may return any error code in the generic or system 17| |// category. However, they shall be equivalent to any error conditions listed 18| |// in each functions respective documentation if the condition applies. [ note: 19| |// this does not guarantee that error_code will be in the set of explicitly 20| |// listed codes, but it does guarantee that if any of the explicitly listed 21| |// errors occur, the correct error_code will be used ]. All functions may 22| |// return errc::not_enough_memory if there is not enough memory to complete the 23| |// operation. 24| |// 25| |//===----------------------------------------------------------------------===// 26| | 27| |#ifndef LLVM_SUPPORT_FILESYSTEM_H 28| |#define LLVM_SUPPORT_FILESYSTEM_H 29| | 30| |#include "llvm/ADT/IntrusiveRefCntPtr.h" 31| |#include "llvm/ADT/SmallString.h" 32| |#include "llvm/ADT/Twine.h" 33| |#include "llvm/Support/DataTypes.h" 34| |#include "llvm/Support/ErrorHandling.h" 35| |#include "llvm/Support/TimeValue.h" 36| |#include 37| |#include 38| |#include 39| |#include 40| |#include 41| |#include 42| |#include 43| | 44| |#ifdef HAVE_SYS_STAT_H 45| |#include 46| |#endif 47| | 48| |namespace llvm { 49| |namespace sys { 50| |namespace fs { 51| | 52| |/// An enumeration for the file system's view of the type. 53| |enum class file_type { 54| | status_error, 55| | file_not_found, 56| | regular_file, 57| | directory_file, 58| | symlink_file, 59| | block_file, 60| | character_file, 61| | fifo_file, 62| | socket_file, 63| | type_unknown 64| |}; 65| | 66| |/// space_info - Self explanatory. 67| |struct space_info { 68| | uint64_t capacity; 69| | uint64_t free; 70| | uint64_t available; 71| |}; 72| | 73| |enum perms { 74| | no_perms = 0, 75| | owner_read = 0400, 76| | owner_write = 0200, 77| | owner_exe = 0100, 78| | owner_all = owner_read | owner_write | owner_exe, 79| | group_read = 040, 80| | group_write = 020, 81| | group_exe = 010, 82| | group_all = group_read | group_write | group_exe, 83| | others_read = 04, 84| | others_write = 02, 85| | others_exe = 01, 86| | others_all = others_read | others_write | others_exe, 87| | all_read = owner_read | group_read | others_read, 88| | all_write = owner_write | group_write | others_write, 89| | all_exe = owner_exe | group_exe | others_exe, 90| | all_all = owner_all | group_all | others_all, 91| | set_uid_on_exe = 04000, 92| | set_gid_on_exe = 02000, 93| | sticky_bit = 01000, 94| | perms_not_known = 0xFFFF 95| |}; 96| | 97| |// Helper functions so that you can use & and | to manipulate perms bits: 98| |inline perms operator|(perms l , perms r) { 99| | return static_cast( 100| | static_cast(l) | static_cast(r)); 101| |} 102| 0|inline perms operator&(perms l , perms r) { 103| 0| return static_cast( 104| 0| static_cast(l) & static_cast(r)); 105| 0|} 106| 0|inline perms &operator|=(perms &l, perms r) { 107| 0| l = l | r; 108| 0| return l; 109| 0|} 110| 0|inline perms &operator&=(perms &l, perms r) { 111| 0| l = l & r; 112| 0| return l; 113| 0|} 114| 0|inline perms operator~(perms x) { 115| 0| return static_cast(~static_cast(x)); 116| 0|} 117| | 118| |class UniqueID { 119| | uint64_t Device; 120| | uint64_t File; 121| | 122| |public: 123| 0| UniqueID() {} 124| 0| UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 125| | bool operator==(const UniqueID &Other) const { 126| | return Device == Other.Device && File == Other.File; 127| | } 128| 0| bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 129| 0| bool operator<(const UniqueID &Other) const { 130| 0| return std::tie(Device, File) < std::tie(Other.Device, Other.File); 131| 0| } 132| 0| uint64_t getDevice() const { return Device; } 133| 0| uint64_t getFile() const { return File; } 134| |}; 135| | 136| |/// file_status - Represents the result of a call to stat and friends. It has 137| |/// a platform-specific member to store the result. 138| |class file_status 139| |{ 140| | #if defined(LLVM_ON_UNIX) 141| | dev_t fs_st_dev; 142| | ino_t fs_st_ino; 143| | time_t fs_st_mtime; 144| | uid_t fs_st_uid; 145| | gid_t fs_st_gid; 146| | off_t fs_st_size; 147| | #elif defined (LLVM_ON_WIN32) 148| | uint32_t LastWriteTimeHigh; 149| | uint32_t LastWriteTimeLow; 150| | uint32_t VolumeSerialNumber; 151| | uint32_t FileSizeHigh; 152| | uint32_t FileSizeLow; 153| | uint32_t FileIndexHigh; 154| | uint32_t FileIndexLow; 155| | #endif 156| | friend bool equivalent(file_status A, file_status B); 157| | file_type Type; 158| | perms Perms; 159| |public: 160| | #if defined(LLVM_ON_UNIX) 161| | file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 162| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), 163| 0| Type(file_type::status_error), Perms(perms_not_known) {} 164| | 165| | file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 166| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), 167| 0| Perms(perms_not_known) {} 168| | 169| | file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, 170| | uid_t UID, gid_t GID, off_t Size) 171| | : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), 172| 0| fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} 173| | #elif defined(LLVM_ON_WIN32) 174| | file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), 175| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 176| | FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), 177| | Perms(perms_not_known) {} 178| | 179| | file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), 180| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 181| | FileIndexHigh(0), FileIndexLow(0), Type(Type), 182| | Perms(perms_not_known) {} 183| | 184| | file_status(file_type Type, uint32_t LastWriteTimeHigh, 185| | uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, 186| | uint32_t FileSizeHigh, uint32_t FileSizeLow, 187| | uint32_t FileIndexHigh, uint32_t FileIndexLow) 188| | : LastWriteTimeHigh(LastWriteTimeHigh), 189| | LastWriteTimeLow(LastWriteTimeLow), 190| | VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), 191| | FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), 192| | FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} 193| | #endif 194| | 195| | // getters 196| 0| file_type type() const { return Type; } 197| 0| perms permissions() const { return Perms; } 198| | TimeValue getLastModificationTime() const; 199| | UniqueID getUniqueID() const; 200| | 201| | #if defined(LLVM_ON_UNIX) 202| 0| uint32_t getUser() const { return fs_st_uid; } 203| 0| uint32_t getGroup() const { return fs_st_gid; } 204| | uint64_t getSize() const { return fs_st_size; } 205| | #elif defined (LLVM_ON_WIN32) 206| | uint32_t getUser() const { 207| | return 9999; // Not applicable to Windows, so... 208| | } 209| | uint32_t getGroup() const { 210| | return 9999; // Not applicable to Windows, so... 211| | } 212| | uint64_t getSize() const { 213| | return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 214| | } 215| | #endif 216| | 217| | // setters 218| 0| void type(file_type v) { Type = v; } 219| 0| void permissions(perms p) { Perms = p; } 220| |}; 221| | 222| |/// file_magic - An "enum class" enumeration of file types based on magic (the first 223| |/// N bytes of the file). 224| |struct file_magic { 225| | enum Impl { 226| | unknown = 0, ///< Unrecognized file 227| | bitcode, ///< Bitcode file 228| | archive, ///< ar style archive file 229| | elf, ///< ELF Unknown type 230| | elf_relocatable, ///< ELF Relocatable object file 231| | elf_executable, ///< ELF Executable image 232| | elf_shared_object, ///< ELF dynamically linked shared lib 233| | elf_core, ///< ELF core image 234| | macho_object, ///< Mach-O Object file 235| | macho_executable, ///< Mach-O Executable 236| | macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 237| | macho_core, ///< Mach-O Core File 238| | macho_preload_executable, ///< Mach-O Preloaded Executable 239| | macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 240| | macho_dynamic_linker, ///< The Mach-O dynamic linker 241| | macho_bundle, ///< Mach-O Bundle file 242| | macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 243| | macho_dsym_companion, ///< Mach-O dSYM companion file 244| | macho_kext_bundle, ///< Mach-O kext bundle file 245| | macho_universal_binary, ///< Mach-O universal binary 246| | coff_object, ///< COFF object file 247| | coff_import_library, ///< COFF import library 248| | pecoff_executable, ///< PECOFF executable file 249| | windows_resource ///< Windows compiled resource file (.rc) 250| | }; 251| | 252| 0| bool is_object() const { 253| 0| return V == unknown ? false : true; 254| 0| } 255| | 256| 0| file_magic() : V(unknown) {} 257| 0| file_magic(Impl V) : V(V) {} 258| 0| operator Impl() const { return V; } 259| | 260| |private: 261| | Impl V; 262| |}; 263| | 264| |/// @} 265| |/// @name Physical Operators 266| |/// @{ 267| | 268| |/// @brief Make \a path an absolute path. 269| |/// 270| |/// Makes \a path absolute using the current directory if it is not already. An 271| |/// empty \a path will result in the current directory. 272| |/// 273| |/// /absolute/path => /absolute/path 274| |/// relative/../path => /relative/../path 275| |/// 276| |/// @param path A path that is modified to be an absolute path. 277| |/// @returns errc::success if \a path has been made absolute, otherwise a 278| |/// platform-specific error_code. 279| |std::error_code make_absolute(SmallVectorImpl &path); 280| | 281| |/// @brief Create all the non-existent directories in path. 282| |/// 283| |/// @param path Directories to create. 284| |/// @returns errc::success if is_directory(path), otherwise a platform 285| |/// specific error_code. If IgnoreExisting is false, also returns 286| |/// error if the directory already existed. 287| |std::error_code create_directories(const Twine &path, 288| | bool IgnoreExisting = true); 289| | 290| |/// @brief Create the directory in path. 291| |/// 292| |/// @param path Directory to create. 293| |/// @returns errc::success if is_directory(path), otherwise a platform 294| |/// specific error_code. If IgnoreExisting is false, also returns 295| |/// error if the directory already existed. 296| |std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); 297| | 298| |/// @brief Create a link from \a from to \a to. 299| |/// 300| |/// The link may be a soft or a hard link, depending on the platform. The caller 301| |/// may not assume which one. Currently on windows it creates a hard link since 302| |/// soft links require extra privileges. On unix, it creates a soft link since 303| |/// hard links don't work on SMB file systems. 304| |/// 305| |/// @param to The path to hard link to. 306| |/// @param from The path to hard link from. This is created. 307| |/// @returns errc::success if the link was created, otherwise a platform 308| |/// specific error_code. 309| |std::error_code create_link(const Twine &to, const Twine &from); 310| | 311| |/// @brief Get the current path. 312| |/// 313| |/// @param result Holds the current path on return. 314| |/// @returns errc::success if the current path has been stored in result, 315| |/// otherwise a platform-specific error_code. 316| |std::error_code current_path(SmallVectorImpl &result); 317| | 318| |/// @brief Remove path. Equivalent to POSIX remove(). 319| |/// 320| |/// @param path Input path. 321| |/// @returns errc::success if path has been removed or didn't exist, otherwise a 322| |/// platform-specific error code. If IgnoreNonExisting is false, also 323| |/// returns error if the file didn't exist. 324| |std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 325| | 326| |/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 327| |/// 328| |/// @param from The path to rename from. 329| |/// @param to The path to rename to. This is created. 330| |std::error_code rename(const Twine &from, const Twine &to); 331| | 332| |/// @brief Copy the contents of \a From to \a To. 333| |/// 334| |/// @param From The path to copy from. 335| |/// @param To The path to copy to. This is created. 336| |std::error_code copy_file(const Twine &From, const Twine &To); 337| | 338| |/// @brief Resize path to size. File is resized as if by POSIX truncate(). 339| |/// 340| |/// @param FD Input file descriptor. 341| |/// @param Size Size to resize to. 342| |/// @returns errc::success if \a path has been resized to \a size, otherwise a 343| |/// platform-specific error_code. 344| |std::error_code resize_file(int FD, uint64_t Size); 345| | 346| |/// @} 347| |/// @name Physical Observers 348| |/// @{ 349| | 350| |/// @brief Does file exist? 351| |/// 352| |/// @param status A file_status previously returned from stat. 353| |/// @returns True if the file represented by status exists, false if it does 354| |/// not. 355| |bool exists(file_status status); 356| | 357| |enum class AccessMode { Exist, Write, Execute }; 358| | 359| |/// @brief Can the file be accessed? 360| |/// 361| |/// @param Path Input path. 362| |/// @returns errc::success if the path can be accessed, otherwise a 363| |/// platform-specific error_code. 364| |std::error_code access(const Twine &Path, AccessMode Mode); 365| | 366| |/// @brief Does file exist? 367| |/// 368| |/// @param Path Input path. 369| |/// @returns True if it exists, false otherwise. 370| |inline bool exists(const Twine &Path) { 371| | return !access(Path, AccessMode::Exist); 372| |} 373| | 374| |/// @brief Can we execute this file? 375| |/// 376| |/// @param Path Input path. 377| |/// @returns True if we can execute it, false otherwise. 378| |inline bool can_execute(const Twine &Path) { 379| | return !access(Path, AccessMode::Execute); 380| |} 381| | 382| |/// @brief Can we write this file? 383| |/// 384| |/// @param Path Input path. 385| |/// @returns True if we can write to it, false otherwise. 386| 0|inline bool can_write(const Twine &Path) { 387| 0| return !access(Path, AccessMode::Write); 388| 0|} 389| | 390| |/// @brief Do file_status's represent the same thing? 391| |/// 392| |/// @param A Input file_status. 393| |/// @param B Input file_status. 394| |/// 395| |/// assert(status_known(A) || status_known(B)); 396| |/// 397| |/// @returns True if A and B both represent the same file system entity, false 398| |/// otherwise. 399| |bool equivalent(file_status A, file_status B); 400| | 401| |/// @brief Do paths represent the same thing? 402| |/// 403| |/// assert(status_known(A) || status_known(B)); 404| |/// 405| |/// @param A Input path A. 406| |/// @param B Input path B. 407| |/// @param result Set to true if stat(A) and stat(B) have the same device and 408| |/// inode (or equivalent). 409| |/// @returns errc::success if result has been successfully set, otherwise a 410| |/// platform-specific error_code. 411| |std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 412| | 413| |/// @brief Simpler version of equivalent for clients that don't need to 414| |/// differentiate between an error and false. 415| 0|inline bool equivalent(const Twine &A, const Twine &B) { 416| 0| bool result; 417| 0| return !equivalent(A, B, result) && result; 418| 0|} 419| | 420| |/// @brief Does status represent a directory? 421| |/// 422| |/// @param status A file_status previously returned from status. 423| |/// @returns status.type() == file_type::directory_file. 424| |bool is_directory(file_status status); 425| | 426| |/// @brief Is path a directory? 427| |/// 428| |/// @param path Input path. 429| |/// @param result Set to true if \a path is a directory, false if it is not. 430| |/// Undefined otherwise. 431| |/// @returns errc::success if result has been successfully set, otherwise a 432| |/// platform-specific error_code. 433| |std::error_code is_directory(const Twine &path, bool &result); 434| | 435| |/// @brief Simpler version of is_directory for clients that don't need to 436| |/// differentiate between an error and false. 437| 0|inline bool is_directory(const Twine &Path) { 438| 0| bool Result; 439| 0| return !is_directory(Path, Result) && Result; 440| 0|} 441| | 442| |/// @brief Does status represent a regular file? 443| |/// 444| |/// @param status A file_status previously returned from status. 445| |/// @returns status_known(status) && status.type() == file_type::regular_file. 446| |bool is_regular_file(file_status status); 447| | 448| |/// @brief Is path a regular file? 449| |/// 450| |/// @param path Input path. 451| |/// @param result Set to true if \a path is a regular file, false if it is not. 452| |/// Undefined otherwise. 453| |/// @returns errc::success if result has been successfully set, otherwise a 454| |/// platform-specific error_code. 455| |std::error_code is_regular_file(const Twine &path, bool &result); 456| | 457| |/// @brief Simpler version of is_regular_file for clients that don't need to 458| |/// differentiate between an error and false. 459| 0|inline bool is_regular_file(const Twine &Path) { 460| 0| bool Result; 461| 0| if (is_regular_file(Path, Result)) 462| 0| return false; 463| 0| return Result; 464| 0|} 465| | 466| |/// @brief Does this status represent something that exists but is not a 467| |/// directory, regular file, or symlink? 468| |/// 469| |/// @param status A file_status previously returned from status. 470| |/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 471| |bool is_other(file_status status); 472| | 473| |/// @brief Is path something that exists but is not a directory, 474| |/// regular file, or symlink? 475| |/// 476| |/// @param path Input path. 477| |/// @param result Set to true if \a path exists, but is not a directory, regular 478| |/// file, or a symlink, false if it does not. Undefined otherwise. 479| |/// @returns errc::success if result has been successfully set, otherwise a 480| |/// platform-specific error_code. 481| |std::error_code is_other(const Twine &path, bool &result); 482| | 483| |/// @brief Get file status as if by POSIX stat(). 484| |/// 485| |/// @param path Input path. 486| |/// @param result Set to the file status. 487| |/// @returns errc::success if result has been successfully set, otherwise a 488| |/// platform-specific error_code. 489| |std::error_code status(const Twine &path, file_status &result); 490| | 491| |/// @brief A version for when a file descriptor is already available. 492| |std::error_code status(int FD, file_status &Result); 493| | 494| |/// @brief Get file size. 495| |/// 496| |/// @param Path Input path. 497| |/// @param Result Set to the size of the file in \a Path. 498| |/// @returns errc::success if result has been successfully set, otherwise a 499| |/// platform-specific error_code. 500| 0|inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 501| 0| file_status Status; 502| 0| std::error_code EC = status(Path, Status); 503| 0| if (EC) 504| 0| return EC; 505| 0| Result = Status.getSize(); 506| 0| return std::error_code(); 507| 0|} 508| | 509| |/// @brief Set the file modification and access time. 510| |/// 511| |/// @returns errc::success if the file times were successfully set, otherwise a 512| |/// platform-specific error_code or errc::function_not_supported on 513| |/// platforms where the functionality isn't available. 514| |std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); 515| | 516| |/// @brief Is status available? 517| |/// 518| |/// @param s Input file status. 519| |/// @returns True if status() != status_error. 520| |bool status_known(file_status s); 521| | 522| |/// @brief Is status available? 523| |/// 524| |/// @param path Input path. 525| |/// @param result Set to true if status() != status_error. 526| |/// @returns errc::success if result has been successfully set, otherwise a 527| |/// platform-specific error_code. 528| |std::error_code status_known(const Twine &path, bool &result); 529| | 530| |/// @brief Create a uniquely named file. 531| |/// 532| |/// Generates a unique path suitable for a temporary file and then opens it as a 533| |/// file. The name is based on \a model with '%' replaced by a random char in 534| |/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 535| |/// directory will be prepended. 536| |/// 537| |/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 538| |/// 539| |/// This is an atomic operation. Either the file is created and opened, or the 540| |/// file system is left untouched. 541| |/// 542| |/// The intendend use is for files that are to be kept, possibly after 543| |/// renaming them. For example, when running 'clang -c foo.o', the file can 544| |/// be first created as foo-abc123.o and then renamed. 545| |/// 546| |/// @param Model Name to base unique path off of. 547| |/// @param ResultFD Set to the opened file's file descriptor. 548| |/// @param ResultPath Set to the opened file's absolute path. 549| |/// @returns errc::success if Result{FD,Path} have been successfully set, 550| |/// otherwise a platform-specific error_code. 551| |std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 552| | SmallVectorImpl &ResultPath, 553| | unsigned Mode = all_read | all_write); 554| | 555| |/// @brief Simpler version for clients that don't want an open file. 556| |std::error_code createUniqueFile(const Twine &Model, 557| | SmallVectorImpl &ResultPath); 558| | 559| |/// @brief Create a file in the system temporary directory. 560| |/// 561| |/// The filename is of the form prefix-random_chars.suffix. Since the directory 562| |/// is not know to the caller, Prefix and Suffix cannot have path separators. 563| |/// The files are created with mode 0600. 564| |/// 565| |/// This should be used for things like a temporary .s that is removed after 566| |/// running the assembler. 567| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 568| | int &ResultFD, 569| | SmallVectorImpl &ResultPath); 570| | 571| |/// @brief Simpler version for clients that don't want an open file. 572| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 573| | SmallVectorImpl &ResultPath); 574| | 575| |std::error_code createUniqueDirectory(const Twine &Prefix, 576| | SmallVectorImpl &ResultPath); 577| | 578| |enum OpenFlags : unsigned { 579| | F_None = 0, 580| | 581| | /// F_Excl - When opening a file, this flag makes raw_fd_ostream 582| | /// report an error if the file already exists. 583| | F_Excl = 1, 584| | 585| | /// F_Append - When opening a file, if it already exists append to the 586| | /// existing file instead of returning an error. This may not be specified 587| | /// with F_Excl. 588| | F_Append = 2, 589| | 590| | /// The file should be opened in text mode on platforms that make this 591| | /// distinction. 592| | F_Text = 4, 593| | 594| | /// Open the file for read and write. 595| | F_RW = 8 596| |}; 597| | 598| |inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 599| | return OpenFlags(unsigned(A) | unsigned(B)); 600| |} 601| | 602| 0|inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 603| 0| A = A | B; 604| 0| return A; 605| 0|} 606| | 607| |std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 608| | OpenFlags Flags, unsigned Mode = 0666); 609| | 610| |std::error_code openFileForRead(const Twine &Name, int &ResultFD); 611| | 612| |/// @brief Identify the type of a binary file based on how magical it is. 613| |file_magic identify_magic(StringRef magic); 614| | 615| |/// @brief Get and identify \a path's type based on its content. 616| |/// 617| |/// @param path Input path. 618| |/// @param result Set to the type of file, or file_magic::unknown. 619| |/// @returns errc::success if result has been successfully set, otherwise a 620| |/// platform-specific error_code. 621| |std::error_code identify_magic(const Twine &path, file_magic &result); 622| | 623| |std::error_code getUniqueID(const Twine Path, UniqueID &Result); 624| | 625| |/// This class represents a memory mapped file. It is based on 626| |/// boost::iostreams::mapped_file. 627| |class mapped_file_region { 628| | mapped_file_region() = delete; 629| | mapped_file_region(mapped_file_region&) = delete; 630| | mapped_file_region &operator =(mapped_file_region&) = delete; 631| | 632| |public: 633| | enum mapmode { 634| | readonly, ///< May only access map via const_data as read only. 635| | readwrite, ///< May access map via data and modify it. Written to path. 636| | priv ///< May modify via data, but changes are lost on destruction. 637| | }; 638| | 639| |private: 640| | /// Platform-specific mapping state. 641| | uint64_t Size; 642| | void *Mapping; 643| | 644| | std::error_code init(int FD, uint64_t Offset, mapmode Mode); 645| | 646| |public: 647| | /// \param fd An open file descriptor to map. mapped_file_region takes 648| | /// ownership if closefd is true. It must have been opended in the correct 649| | /// mode. 650| | mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, 651| | std::error_code &ec); 652| | 653| | ~mapped_file_region(); 654| | 655| | uint64_t size() const; 656| | char *data() const; 657| | 658| | /// Get a const view of the data. Modifying this memory has undefined 659| | /// behavior. 660| | const char *const_data() const; 661| | 662| | /// \returns The minimum alignment offset must be. 663| | static int alignment(); 664| |}; 665| | 666| |/// Return the path to the main executable, given the value of argv[0] from 667| |/// program startup and the address of main itself. In extremis, this function 668| |/// may fail and return an empty path. 669| |std::string getMainExecutable(const char *argv0, void *MainExecAddr); 670| | 671| |/// @} 672| |/// @name Iterators 673| |/// @{ 674| | 675| |/// directory_entry - A single entry in a directory. Caches the status either 676| |/// from the result of the iteration syscall, or the first time status is 677| |/// called. 678| |class directory_entry { 679| | std::string Path; 680| | mutable file_status Status; 681| | 682| |public: 683| | explicit directory_entry(const Twine &path, file_status st = file_status()) 684| | : Path(path.str()) 685| 0| , Status(st) {} 686| | 687| 0| directory_entry() {} 688| | 689| 0| void assign(const Twine &path, file_status st = file_status()) { 690| 0| Path = path.str(); 691| 0| Status = st; 692| 0| } 693| | 694| | void replace_filename(const Twine &filename, file_status st = file_status()); 695| | 696| 0| const std::string &path() const { return Path; } 697| | std::error_code status(file_status &result) const; 698| | 699| 0| bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 700| 0| bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 701| | bool operator< (const directory_entry& rhs) const; 702| | bool operator<=(const directory_entry& rhs) const; 703| | bool operator> (const directory_entry& rhs) const; 704| | bool operator>=(const directory_entry& rhs) const; 705| |}; 706| | 707| |namespace detail { 708| | struct DirIterState; 709| | 710| | std::error_code directory_iterator_construct(DirIterState &, StringRef); 711| | std::error_code directory_iterator_increment(DirIterState &); 712| | std::error_code directory_iterator_destruct(DirIterState &); 713| | 714| | /// DirIterState - Keeps state for the directory_iterator. It is reference 715| | /// counted in order to preserve InputIterator semantics on copy. 716| | struct DirIterState : public RefCountedBase { 717| | DirIterState() 718| 0| : IterationHandle(0) {} 719| | 720| 0| ~DirIterState() { 721| 0| directory_iterator_destruct(*this); 722| 0| } 723| | 724| | intptr_t IterationHandle; 725| | directory_entry CurrentEntry; 726| | }; 727| |} 728| | 729| |/// directory_iterator - Iterates through the entries in path. There is no 730| |/// operator++ because we need an error_code. If it's really needed we can make 731| |/// it call report_fatal_error on error. 732| |class directory_iterator { 733| | IntrusiveRefCntPtr State; 734| | 735| |public: 736| 0| explicit directory_iterator(const Twine &path, std::error_code &ec) { 737| 0| State = new detail::DirIterState; 738| 0| SmallString<128> path_storage; 739| 0| ec = detail::directory_iterator_construct(*State, 740| 0| path.toStringRef(path_storage)); 741| 0| } 742| | 743| 0| explicit directory_iterator(const directory_entry &de, std::error_code &ec) { 744| 0| State = new detail::DirIterState; 745| 0| ec = detail::directory_iterator_construct(*State, de.path()); 746| 0| } 747| | 748| | /// Construct end iterator. 749| 0| directory_iterator() : State(nullptr) {} 750| | 751| | // No operator++ because we need error_code. 752| 0| directory_iterator &increment(std::error_code &ec) { 753| 0| ec = directory_iterator_increment(*State); 754| 0| return *this; 755| 0| } 756| | 757| 0| const directory_entry &operator*() const { return State->CurrentEntry; } 758| 0| const directory_entry *operator->() const { return &State->CurrentEntry; } 759| | 760| 0| bool operator==(const directory_iterator &RHS) const { 761| 0| if (State == RHS.State) 762| 0| return true; 763| 0| if (!RHS.State) 764| 0| return State->CurrentEntry == directory_entry(); 765| 0| if (!State) 766| 0| return RHS.State->CurrentEntry == directory_entry(); 767| 0| return State->CurrentEntry == RHS.State->CurrentEntry; 768| 0| } 769| | 770| 0| bool operator!=(const directory_iterator &RHS) const { 771| 0| return !(*this == RHS); 772| 0| } 773| | // Other members as required by 774| | // C++ Std, 24.1.1 Input iterators [input.iterators] 775| |}; 776| | 777| |namespace detail { 778| | /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 779| | /// reference counted in order to preserve InputIterator semantics on copy. 780| | struct RecDirIterState : public RefCountedBase { 781| | RecDirIterState() 782| | : Level(0) 783| 0| , HasNoPushRequest(false) {} 784| | 785| | std::stack > Stack; 786| | uint16_t Level; 787| | bool HasNoPushRequest; 788| | }; 789| |} 790| | 791| |/// recursive_directory_iterator - Same as directory_iterator except for it 792| |/// recurses down into child directories. 793| |class recursive_directory_iterator { 794| | IntrusiveRefCntPtr State; 795| | 796| |public: 797| 0| recursive_directory_iterator() {} 798| | explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) 799| 0| : State(new detail::RecDirIterState) { 800| 0| State->Stack.push(directory_iterator(path, ec)); 801| 0| if (State->Stack.top() == directory_iterator()) 802| 0| State.reset(); 803| 0| } 804| | // No operator++ because we need error_code. 805| 0| recursive_directory_iterator &increment(std::error_code &ec) { 806| 0| const directory_iterator end_itr; 807| 0| 808| 0| if (State->HasNoPushRequest) 809| 0| State->HasNoPushRequest = false; 810| 0| else { 811| 0| file_status st; 812| 0| if ((ec = State->Stack.top()->status(st))) return *this; 813| 0| if (is_directory(st)) { 814| 0| State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 815| 0| if (ec) return *this; 816| 0| if (State->Stack.top() != end_itr) { 817| 0| ++State->Level; 818| 0| return *this; 819| 0| } 820| 0| State->Stack.pop(); 821| 0| } 822| 0| } 823| 0| 824| 0| while (!State->Stack.empty() 825| 0| && State->Stack.top().increment(ec) == end_itr) { 826| 0| State->Stack.pop(); 827| 0| --State->Level; 828| 0| } 829| 0| 830| 0| // Check if we are done. If so, create an end iterator. 831| 0| if (State->Stack.empty()) 832| 0| State.reset(); 833| 0| 834| 0| return *this; 835| 0| } 836| | 837| 0| const directory_entry &operator*() const { return *State->Stack.top(); } 838| 0| const directory_entry *operator->() const { return &*State->Stack.top(); } 839| | 840| | // observers 841| | /// Gets the current level. Starting path is at level 0. 842| 0| int level() const { return State->Level; } 843| | 844| | /// Returns true if no_push has been called for this directory_entry. 845| 0| bool no_push_request() const { return State->HasNoPushRequest; } 846| | 847| | // modifiers 848| | /// Goes up one level if Level > 0. 849| 0| void pop() { 850| 0| assert(State && "Cannot pop an end iterator!"); 851| 0| assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 852| 0| 853| 0| const directory_iterator end_itr; 854| 0| std::error_code ec; 855| 0| do { 856| 0| if (ec) 857| 0| report_fatal_error("Error incrementing directory iterator."); 858| 0| State->Stack.pop(); 859| 0| --State->Level; 860| 0| } while (!State->Stack.empty() 861| 0| && State->Stack.top().increment(ec) == end_itr); 862| 0| 863| 0| // Check if we are done. If so, create an end iterator. 864| 0| if (State->Stack.empty()) 865| 0| State.reset(); 866| 0| } 867| | 868| | /// Does not go down into the current directory_entry. 869| 0| void no_push() { State->HasNoPushRequest = true; } 870| | 871| 0| bool operator==(const recursive_directory_iterator &RHS) const { 872| 0| return State == RHS.State; 873| 0| } 874| | 875| 0| bool operator!=(const recursive_directory_iterator &RHS) const { 876| 0| return !(*this == RHS); 877| 0| } 878| | // Other members as required by 879| | // C++ Std, 24.1.1 Input iterators [input.iterators] 880| |}; 881| | 882| |/// @} 883| | 884| |} // end namespace fs 885| |} // end namespace sys 886| |} // end namespace llvm 887| | 888| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MathExtras.h: 1| |//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful for math stuff. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MATHEXTRAS_H 15| |#define LLVM_SUPPORT_MATHEXTRAS_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/SwapByteOrder.h" 19| |#include 20| |#include 21| |#include 22| | 23| |#ifdef _MSC_VER 24| |#include 25| |#endif 26| | 27| |namespace llvm { 28| |/// \brief The behavior an operation has on an input of 0. 29| |enum ZeroBehavior { 30| | /// \brief The returned value is undefined. 31| | ZB_Undefined, 32| | /// \brief The returned value is numeric_limits::max() 33| | ZB_Max, 34| | /// \brief The returned value is numeric_limits::digits 35| | ZB_Width 36| |}; 37| | 38| |namespace detail { 39| |template struct TrailingZerosCounter { 40| | static std::size_t count(T Val, ZeroBehavior) { 41| | if (!Val) 42| | return std::numeric_limits::digits; 43| | if (Val & 0x1) 44| | return 0; 45| | 46| | // Bisection method. 47| | std::size_t ZeroBits = 0; 48| | T Shift = std::numeric_limits::digits >> 1; 49| | T Mask = std::numeric_limits::max() >> Shift; 50| | while (Shift) { 51| | if ((Val & Mask) == 0) { 52| | Val >>= Shift; 53| | ZeroBits |= Shift; 54| | } 55| | Shift >>= 1; 56| | Mask >>= Shift; 57| | } 58| | return ZeroBits; 59| | } 60| |}; 61| | 62| |#if __GNUC__ >= 4 || _MSC_VER 63| |template struct TrailingZerosCounter { 64| | static std::size_t count(T Val, ZeroBehavior ZB) { 65| | if (ZB != ZB_Undefined && Val == 0) 66| | return 32; 67| | 68| |#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) 69| | return __builtin_ctz(Val); 70| |#elif _MSC_VER 71| | unsigned long Index; 72| | _BitScanForward(&Index, Val); 73| | return Index; 74| |#endif 75| | } 76| |}; 77| | 78| |#if !defined(_MSC_VER) || defined(_M_X64) 79| |template struct TrailingZerosCounter { 80| | static std::size_t count(T Val, ZeroBehavior ZB) { 81| | if (ZB != ZB_Undefined && Val == 0) 82| | return 64; 83| | 84| |#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) 85| | return __builtin_ctzll(Val); 86| |#elif _MSC_VER 87| | unsigned long Index; 88| | _BitScanForward64(&Index, Val); 89| | return Index; 90| |#endif 91| | } 92| |}; 93| |#endif 94| |#endif 95| |} // namespace detail 96| | 97| |/// \brief Count number of 0's from the least significant bit to the most 98| |/// stopping at the first 1. 99| |/// 100| |/// Only unsigned integral types are allowed. 101| |/// 102| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 103| |/// valid arguments. 104| |template 105| |std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 106| | static_assert(std::numeric_limits::is_integer && 107| | !std::numeric_limits::is_signed, 108| | "Only unsigned integral types are allowed."); 109| | return detail::TrailingZerosCounter::count(Val, ZB); 110| |} 111| | 112| |namespace detail { 113| |template struct LeadingZerosCounter { 114| | static std::size_t count(T Val, ZeroBehavior) { 115| | if (!Val) 116| | return std::numeric_limits::digits; 117| | 118| | // Bisection method. 119| | std::size_t ZeroBits = 0; 120| | for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) { 121| | T Tmp = Val >> Shift; 122| | if (Tmp) 123| | Val = Tmp; 124| | else 125| | ZeroBits |= Shift; 126| | } 127| | return ZeroBits; 128| | } 129| |}; 130| | 131| |#if __GNUC__ >= 4 || _MSC_VER 132| |template struct LeadingZerosCounter { 133| | static std::size_t count(T Val, ZeroBehavior ZB) { 134| | if (ZB != ZB_Undefined && Val == 0) 135| | return 32; 136| | 137| |#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) 138| | return __builtin_clz(Val); 139| |#elif _MSC_VER 140| | unsigned long Index; 141| | _BitScanReverse(&Index, Val); 142| | return Index ^ 31; 143| |#endif 144| | } 145| |}; 146| | 147| |#if !defined(_MSC_VER) || defined(_M_X64) 148| |template struct LeadingZerosCounter { 149| | static std::size_t count(T Val, ZeroBehavior ZB) { 150| | if (ZB != ZB_Undefined && Val == 0) 151| | return 64; 152| | 153| |#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) 154| | return __builtin_clzll(Val); 155| |#elif _MSC_VER 156| | unsigned long Index; 157| | _BitScanReverse64(&Index, Val); 158| | return Index ^ 63; 159| |#endif 160| | } 161| |}; 162| |#endif 163| |#endif 164| |} // namespace detail 165| | 166| |/// \brief Count number of 0's from the most significant bit to the least 167| |/// stopping at the first 1. 168| |/// 169| |/// Only unsigned integral types are allowed. 170| |/// 171| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 172| |/// valid arguments. 173| |template 174| |std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 175| | static_assert(std::numeric_limits::is_integer && 176| | !std::numeric_limits::is_signed, 177| | "Only unsigned integral types are allowed."); 178| | return detail::LeadingZerosCounter::count(Val, ZB); 179| |} 180| | 181| |/// \brief Get the index of the first set bit starting from the least 182| |/// significant bit. 183| |/// 184| |/// Only unsigned integral types are allowed. 185| |/// 186| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 187| |/// valid arguments. 188| |template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { 189| | if (ZB == ZB_Max && Val == 0) 190| | return std::numeric_limits::max(); 191| | 192| | return countTrailingZeros(Val, ZB_Undefined); 193| |} 194| | 195| |/// \brief Get the index of the last set bit starting from the least 196| |/// significant bit. 197| |/// 198| |/// Only unsigned integral types are allowed. 199| |/// 200| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 201| |/// valid arguments. 202| |template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { 203| | if (ZB == ZB_Max && Val == 0) 204| | return std::numeric_limits::max(); 205| | 206| | // Use ^ instead of - because both gcc and llvm can remove the associated ^ 207| | // in the __builtin_clz intrinsic on x86. 208| | return countLeadingZeros(Val, ZB_Undefined) ^ 209| | (std::numeric_limits::digits - 1); 210| |} 211| | 212| |/// \brief Macro compressed bit reversal table for 256 bits. 213| |/// 214| |/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable 215| |static const unsigned char BitReverseTable256[256] = { 216| |#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 217| |#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) 218| |#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) 219| | R6(0), R6(2), R6(1), R6(3) 220| |#undef R2 221| |#undef R4 222| |#undef R6 223| |}; 224| | 225| |/// \brief Reverse the bits in \p Val. 226| |template 227| |T reverseBits(T Val) { 228| | unsigned char in[sizeof(Val)]; 229| | unsigned char out[sizeof(Val)]; 230| | std::memcpy(in, &Val, sizeof(Val)); 231| | for (unsigned i = 0; i < sizeof(Val); ++i) 232| | out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; 233| | std::memcpy(&Val, out, sizeof(Val)); 234| | return Val; 235| |} 236| | 237| |// NOTE: The following support functions use the _32/_64 extensions instead of 238| |// type overloading so that signed and unsigned integers can be used without 239| |// ambiguity. 240| | 241| |/// Hi_32 - This function returns the high 32 bits of a 64 bit value. 242| 0|inline uint32_t Hi_32(uint64_t Value) { 243| 0| return static_cast(Value >> 32); 244| 0|} 245| | 246| |/// Lo_32 - This function returns the low 32 bits of a 64 bit value. 247| 0|inline uint32_t Lo_32(uint64_t Value) { 248| 0| return static_cast(Value); 249| 0|} 250| | 251| |/// Make_64 - This functions makes a 64-bit integer from a high / low pair of 252| |/// 32-bit integers. 253| 0|inline uint64_t Make_64(uint32_t High, uint32_t Low) { 254| 0| return ((uint64_t)High << 32) | (uint64_t)Low; 255| 0|} 256| | 257| |/// isInt - Checks if an integer fits into the given bit width. 258| |template 259| |inline bool isInt(int64_t x) { 260| | return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 261| |} 262| |// Template specializations to get better code for common cases. 263| |template<> 264| 0|inline bool isInt<8>(int64_t x) { 265| 0| return static_cast(x) == x; 266| 0|} 267| |template<> 268| 0|inline bool isInt<16>(int64_t x) { 269| 0| return static_cast(x) == x; 270| 0|} 271| |template<> 272| 0|inline bool isInt<32>(int64_t x) { 273| 0| return static_cast(x) == x; 274| 0|} 275| | 276| |/// isShiftedInt - Checks if a signed integer is an N bit number shifted 277| |/// left by S. 278| |template 279| |inline bool isShiftedInt(int64_t x) { 280| | return isInt(x) && (x % (1< 285| |inline bool isUInt(uint64_t x) { 286| | return N >= 64 || x < (UINT64_C(1)<<(N)); 287| |} 288| |// Template specializations to get better code for common cases. 289| |template<> 290| 0|inline bool isUInt<8>(uint64_t x) { 291| 0| return static_cast(x) == x; 292| 0|} 293| |template<> 294| 0|inline bool isUInt<16>(uint64_t x) { 295| 0| return static_cast(x) == x; 296| 0|} 297| |template<> 298| 0|inline bool isUInt<32>(uint64_t x) { 299| 0| return static_cast(x) == x; 300| 0|} 301| | 302| |/// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted 303| |/// left by S. 304| |template 305| |inline bool isShiftedUInt(uint64_t x) { 306| | return isUInt(x) && (x % (1<> (64 - N))); 313| 0|} 314| | 315| |/// isIntN - Checks if an signed integer fits into the given (dynamic) 316| |/// bit width. 317| 0|inline bool isIntN(unsigned N, int64_t x) { 318| 0| return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 319| 0|} 320| | 321| |/// isMask_32 - This function returns true if the argument is a sequence of ones 322| |/// starting at the least significant bit with the remainder zero (32 bit 323| |/// version). Ex. isMask_32(0x0000FFFFU) == true. 324| 0|inline bool isMask_32(uint32_t Value) { 325| 0| return Value && ((Value + 1) & Value) == 0; 326| 0|} 327| | 328| |/// isMask_64 - This function returns true if the argument is a sequence of ones 329| |/// starting at the least significant bit with the remainder zero (64 bit 330| |/// version). 331| 0|inline bool isMask_64(uint64_t Value) { 332| 0| return Value && ((Value + 1) & Value) == 0; 333| 0|} 334| | 335| |/// isShiftedMask_32 - This function returns true if the argument contains a 336| |/// sequence of ones with the remainder zero (32 bit version.) 337| |/// Ex. isShiftedMask_32(0x0000FF00U) == true. 338| 0|inline bool isShiftedMask_32(uint32_t Value) { 339| 0| return isMask_32((Value - 1) | Value); 340| 0|} 341| | 342| |/// isShiftedMask_64 - This function returns true if the argument contains a 343| |/// sequence of ones with the remainder zero (64 bit version.) 344| 0|inline bool isShiftedMask_64(uint64_t Value) { 345| 0| return isMask_64((Value - 1) | Value); 346| 0|} 347| | 348| |/// isPowerOf2_32 - This function returns true if the argument is a power of 349| |/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) 350| 0|inline bool isPowerOf2_32(uint32_t Value) { 351| 0| return Value && !(Value & (Value - 1)); 352| 0|} 353| | 354| |/// isPowerOf2_64 - This function returns true if the argument is a power of two 355| |/// > 0 (64 bit edition.) 356| |inline bool isPowerOf2_64(uint64_t Value) { 357| | return Value && !(Value & (Value - int64_t(1L))); 358| |} 359| | 360| |/// ByteSwap_16 - This function returns a byte-swapped representation of the 361| |/// 16-bit argument, Value. 362| 0|inline uint16_t ByteSwap_16(uint16_t Value) { 363| 0| return sys::SwapByteOrder_16(Value); 364| 0|} 365| | 366| |/// ByteSwap_32 - This function returns a byte-swapped representation of the 367| |/// 32-bit argument, Value. 368| 0|inline uint32_t ByteSwap_32(uint32_t Value) { 369| 0| return sys::SwapByteOrder_32(Value); 370| 0|} 371| | 372| |/// ByteSwap_64 - This function returns a byte-swapped representation of the 373| |/// 64-bit argument, Value. 374| 0|inline uint64_t ByteSwap_64(uint64_t Value) { 375| 0| return sys::SwapByteOrder_64(Value); 376| 0|} 377| | 378| |/// \brief Count the number of ones from the most significant bit to the first 379| |/// zero bit. 380| |/// 381| |/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. 382| |/// Only unsigned integral types are allowed. 383| |/// 384| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 385| |/// ZB_Undefined are valid arguments. 386| |template 387| |std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 388| | static_assert(std::numeric_limits::is_integer && 389| | !std::numeric_limits::is_signed, 390| | "Only unsigned integral types are allowed."); 391| | return countLeadingZeros(~Value, ZB); 392| |} 393| | 394| |/// \brief Count the number of ones from the least significant bit to the first 395| |/// zero bit. 396| |/// 397| |/// Ex. countTrailingOnes(0x00FF00FF) == 8. 398| |/// Only unsigned integral types are allowed. 399| |/// 400| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 401| |/// ZB_Undefined are valid arguments. 402| |template 403| |std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 404| | static_assert(std::numeric_limits::is_integer && 405| | !std::numeric_limits::is_signed, 406| | "Only unsigned integral types are allowed."); 407| | return countTrailingZeros(~Value, ZB); 408| |} 409| | 410| |namespace detail { 411| |template struct PopulationCounter { 412| | static unsigned count(T Value) { 413| | // Generic version, forward to 32 bits. 414| | static_assert(SizeOfT <= 4, "Not implemented!"); 415| |#if __GNUC__ >= 4 416| | return __builtin_popcount(Value); 417| |#else 418| | uint32_t v = Value; 419| | v = v - ((v >> 1) & 0x55555555); 420| | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 421| | return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 422| |#endif 423| | } 424| |}; 425| | 426| |template struct PopulationCounter { 427| | static unsigned count(T Value) { 428| |#if __GNUC__ >= 4 429| | return __builtin_popcountll(Value); 430| |#else 431| | uint64_t v = Value; 432| | v = v - ((v >> 1) & 0x5555555555555555ULL); 433| | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 434| | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 435| | return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); 436| |#endif 437| | } 438| |}; 439| |} // namespace detail 440| | 441| |/// \brief Count the number of set bits in a value. 442| |/// Ex. countPopulation(0xF000F000) = 8 443| |/// Returns 0 if the word is zero. 444| |template 445| |inline unsigned countPopulation(T Value) { 446| | static_assert(std::numeric_limits::is_integer && 447| | !std::numeric_limits::is_signed, 448| | "Only unsigned integral types are allowed."); 449| | return detail::PopulationCounter::count(Value); 450| |} 451| | 452| |/// Log2_32 - This function returns the floor log base 2 of the specified value, 453| |/// -1 if the value is zero. (32 bit edition.) 454| |/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 455| 0|inline unsigned Log2_32(uint32_t Value) { 456| 0| return 31 - countLeadingZeros(Value); 457| 0|} 458| | 459| |/// Log2_64 - This function returns the floor log base 2 of the specified value, 460| |/// -1 if the value is zero. (64 bit edition.) 461| 0|inline unsigned Log2_64(uint64_t Value) { 462| 0| return 63 - countLeadingZeros(Value); 463| 0|} 464| | 465| |/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified 466| |/// value, 32 if the value is zero. (32 bit edition). 467| |/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 468| |inline unsigned Log2_32_Ceil(uint32_t Value) { 469| | return 32 - countLeadingZeros(Value - 1); 470| |} 471| | 472| |/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified 473| |/// value, 64 if the value is zero. (64 bit edition.) 474| 0|inline unsigned Log2_64_Ceil(uint64_t Value) { 475| 0| return 64 - countLeadingZeros(Value - 1); 476| 0|} 477| | 478| |/// GreatestCommonDivisor64 - Return the greatest common divisor of the two 479| |/// values using Euclid's algorithm. 480| 0|inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { 481| 0| while (B) { 482| 0| uint64_t T = B; 483| 0| B = A % B; 484| 0| A = T; 485| 0| } 486| 0| return A; 487| 0|} 488| | 489| |/// BitsToDouble - This function takes a 64-bit integer and returns the bit 490| |/// equivalent double. 491| 0|inline double BitsToDouble(uint64_t Bits) { 492| 0| union { 493| 0| uint64_t L; 494| 0| double D; 495| 0| } T; 496| 0| T.L = Bits; 497| 0| return T.D; 498| 0|} 499| | 500| |/// BitsToFloat - This function takes a 32-bit integer and returns the bit 501| |/// equivalent float. 502| 0|inline float BitsToFloat(uint32_t Bits) { 503| 0| union { 504| 0| uint32_t I; 505| 0| float F; 506| 0| } T; 507| 0| T.I = Bits; 508| 0| return T.F; 509| 0|} 510| | 511| |/// DoubleToBits - This function takes a double and returns the bit 512| |/// equivalent 64-bit integer. Note that copying doubles around 513| |/// changes the bits of NaNs on some hosts, notably x86, so this 514| |/// routine cannot be used if these bits are needed. 515| 0|inline uint64_t DoubleToBits(double Double) { 516| 0| union { 517| 0| uint64_t L; 518| 0| double D; 519| 0| } T; 520| 0| T.D = Double; 521| 0| return T.L; 522| 0|} 523| | 524| |/// FloatToBits - This function takes a float and returns the bit 525| |/// equivalent 32-bit integer. Note that copying floats around 526| |/// changes the bits of NaNs on some hosts, notably x86, so this 527| |/// routine cannot be used if these bits are needed. 528| 0|inline uint32_t FloatToBits(float Float) { 529| 0| union { 530| 0| uint32_t I; 531| 0| float F; 532| 0| } T; 533| 0| T.F = Float; 534| 0| return T.I; 535| 0|} 536| | 537| |/// MinAlign - A and B are either alignments or offsets. Return the minimum 538| |/// alignment that may be assumed after adding the two together. 539| 0|inline uint64_t MinAlign(uint64_t A, uint64_t B) { 540| 0| // The largest power of 2 that divides both A and B. 541| 0| // 542| 0| // Replace "-Value" by "1+~Value" in the following commented code to avoid 543| 0| // MSVC warning C4146 544| 0| // return (A | B) & -(A | B); 545| 0| return (A | B) & (1 + ~(A | B)); 546| 0|} 547| | 548| |/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. 549| |/// 550| |/// Alignment should be a power of two. This method rounds up, so 551| |/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. 552| |inline uintptr_t alignAddr(void *Addr, size_t Alignment) { 553| | assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && 554| | "Alignment is not a power of two!"); 555| | 556| | assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); 557| | 558| | return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); 559| |} 560| | 561| |/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment 562| |/// bytes, rounding up. 563| |inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { 564| | return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; 565| |} 566| | 567| |/// NextPowerOf2 - Returns the next power of two (in 64-bits) 568| |/// that is strictly greater than A. Returns zero on overflow. 569| |inline uint64_t NextPowerOf2(uint64_t A) { 570| | A |= (A >> 1); 571| | A |= (A >> 2); 572| | A |= (A >> 4); 573| | A |= (A >> 8); 574| | A |= (A >> 16); 575| | A |= (A >> 32); 576| | return A + 1; 577| |} 578| | 579| |/// Returns the power of two which is less than or equal to the given value. 580| |/// Essentially, it is a floor operation across the domain of powers of two. 581| 0|inline uint64_t PowerOf2Floor(uint64_t A) { 582| 0| if (!A) return 0; 583| 0| return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); 584| 0|} 585| | 586| |/// Returns the next integer (mod 2**64) that is greater than or equal to 587| |/// \p Value and is a multiple of \p Align. \p Align must be non-zero. 588| |/// 589| |/// Examples: 590| |/// \code 591| |/// RoundUpToAlignment(5, 8) = 8 592| |/// RoundUpToAlignment(17, 8) = 24 593| |/// RoundUpToAlignment(~0LL, 8) = 0 594| |/// RoundUpToAlignment(321, 255) = 510 595| |/// \endcode 596| |inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { 597| | return (Value + Align - 1) / Align * Align; 598| |} 599| | 600| |/// Returns the offset to the next integer (mod 2**64) that is greater than 601| |/// or equal to \p Value and is a multiple of \p Align. \p Align must be 602| |/// non-zero. 603| 0|inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { 604| 0| return RoundUpToAlignment(Value, Align) - Value; 605| 0|} 606| | 607| |/// SignExtend32 - Sign extend B-bit number x to 32-bit int. 608| |/// Usage int32_t r = SignExtend32<5>(x); 609| |template inline int32_t SignExtend32(uint32_t x) { 610| | return int32_t(x << (32 - B)) >> (32 - B); 611| |} 612| | 613| |/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. 614| |/// Requires 0 < B <= 32. 615| 0|inline int32_t SignExtend32(uint32_t X, unsigned B) { 616| 0| return int32_t(X << (32 - B)) >> (32 - B); 617| 0|} 618| | 619| |/// SignExtend64 - Sign extend B-bit number x to 64-bit int. 620| |/// Usage int64_t r = SignExtend64<5>(x); 621| |template inline int64_t SignExtend64(uint64_t x) { 622| | return int64_t(x << (64 - B)) >> (64 - B); 623| |} 624| | 625| |/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. 626| |/// Requires 0 < B <= 64. 627| 0|inline int64_t SignExtend64(uint64_t X, unsigned B) { 628| 0| return int64_t(X << (64 - B)) >> (64 - B); 629| 0|} 630| | 631| |extern const float huge_valf; 632| |} // End llvm namespace 633| | 634| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Memory.h: 1| |//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Memory class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORY_H 15| |#define LLVM_SUPPORT_MEMORY_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| | /// This class encapsulates the notion of a memory block which has an address 25| | /// and a size. It is used by the Memory class (a friend) as the result of 26| | /// various memory allocation operations. 27| | /// @see Memory 28| | /// @brief Memory block abstraction. 29| | class MemoryBlock { 30| | public: 31| 0| MemoryBlock() : Address(nullptr), Size(0) { } 32| 0| MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } 33| | void *base() const { return Address; } 34| | size_t size() const { return Size; } 35| | private: 36| | void *Address; ///< Address of first byte of memory area 37| | size_t Size; ///< Size, in bytes of the memory area 38| | friend class Memory; 39| | }; 40| | 41| | /// This class provides various memory handling functions that manipulate 42| | /// MemoryBlock instances. 43| | /// @since 1.4 44| | /// @brief An abstraction for memory operations. 45| | class Memory { 46| | public: 47| | enum ProtectionFlags { 48| | MF_READ = 0x1000000, 49| | MF_WRITE = 0x2000000, 50| | MF_EXEC = 0x4000000 51| | }; 52| | 53| | /// This method allocates a block of memory that is suitable for loading 54| | /// dynamically generated code (e.g. JIT). An attempt to allocate 55| | /// \p NumBytes bytes of virtual memory is made. 56| | /// \p NearBlock may point to an existing allocation in which case 57| | /// an attempt is made to allocate more memory near the existing block. 58| | /// The actual allocated address is not guaranteed to be near the requested 59| | /// address. 60| | /// \p Flags is used to set the initial protection flags for the block 61| | /// of the memory. 62| | /// \p EC [out] returns an object describing any error that occurs. 63| | /// 64| | /// This method may allocate more than the number of bytes requested. The 65| | /// actual number of bytes allocated is indicated in the returned 66| | /// MemoryBlock. 67| | /// 68| | /// The start of the allocated block must be aligned with the 69| | /// system allocation granularity (64K on Windows, page size on Linux). 70| | /// If the address following \p NearBlock is not so aligned, it will be 71| | /// rounded up to the next allocation granularity boundary. 72| | /// 73| | /// \r a non-null MemoryBlock if the function was successful, 74| | /// otherwise a null MemoryBlock is with \p EC describing the error. 75| | /// 76| | /// @brief Allocate mapped memory. 77| | static MemoryBlock allocateMappedMemory(size_t NumBytes, 78| | const MemoryBlock *const NearBlock, 79| | unsigned Flags, 80| | std::error_code &EC); 81| | 82| | /// This method releases a block of memory that was allocated with the 83| | /// allocateMappedMemory method. It should not be used to release any 84| | /// memory block allocated any other way. 85| | /// \p Block describes the memory to be released. 86| | /// 87| | /// \r error_success if the function was successful, or an error_code 88| | /// describing the failure if an error occurred. 89| | /// 90| | /// @brief Release mapped memory. 91| | static std::error_code releaseMappedMemory(MemoryBlock &Block); 92| | 93| | /// This method sets the protection flags for a block of memory to the 94| | /// state specified by /p Flags. The behavior is not specified if the 95| | /// memory was not allocated using the allocateMappedMemory method. 96| | /// \p Block describes the memory block to be protected. 97| | /// \p Flags specifies the new protection state to be assigned to the block. 98| | /// \p ErrMsg [out] returns a string describing any error that occurred. 99| | /// 100| | /// If \p Flags is MF_WRITE, the actual behavior varies 101| | /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the 102| | /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 103| | /// 104| | /// \r error_success if the function was successful, or an error_code 105| | /// describing the failure if an error occurred. 106| | /// 107| | /// @brief Set memory protection state. 108| | static std::error_code protectMappedMemory(const MemoryBlock &Block, 109| | unsigned Flags); 110| | 111| | /// This method allocates a block of Read/Write/Execute memory that is 112| | /// suitable for executing dynamically generated code (e.g. JIT). An 113| | /// attempt to allocate \p NumBytes bytes of virtual memory is made. 114| | /// \p NearBlock may point to an existing allocation in which case 115| | /// an attempt is made to allocate more memory near the existing block. 116| | /// 117| | /// On success, this returns a non-null memory block, otherwise it returns 118| | /// a null memory block and fills in *ErrMsg. 119| | /// 120| | /// @brief Allocate Read/Write/Execute memory. 121| | static MemoryBlock AllocateRWX(size_t NumBytes, 122| | const MemoryBlock *NearBlock, 123| | std::string *ErrMsg = nullptr); 124| | 125| | /// This method releases a block of Read/Write/Execute memory that was 126| | /// allocated with the AllocateRWX method. It should not be used to 127| | /// release any memory block allocated any other way. 128| | /// 129| | /// On success, this returns false, otherwise it returns true and fills 130| | /// in *ErrMsg. 131| | /// @brief Release Read/Write/Execute memory. 132| | static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); 133| | 134| | 135| | /// InvalidateInstructionCache - Before the JIT can run a block of code 136| | /// that has been emitted it must invalidate the instruction cache on some 137| | /// platforms. 138| | static void InvalidateInstructionCache(const void *Addr, size_t Len); 139| | 140| | /// setExecutable - Before the JIT can run a block of code, it has to be 141| | /// given read and executable privilege. Return true if it is already r-x 142| | /// or the system is able to change its previlege. 143| | static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); 144| | 145| | /// setWritable - When adding to a block of code, the JIT may need 146| | /// to mark a block of code as RW since the protections are on page 147| | /// boundaries, and the JIT internal allocations are not page aligned. 148| | static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); 149| | 150| | /// setRangeExecutable - Mark the page containing a range of addresses 151| | /// as executable. 152| | static bool setRangeExecutable(const void *Addr, size_t Size); 153| | 154| | /// setRangeWritable - Mark the page containing a range of addresses 155| | /// as writable. 156| | static bool setRangeWritable(const void *Addr, size_t Size); 157| | }; 158| |} 159| |} 160| | 161| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MemoryBuffer.h: 1| |//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the MemoryBuffer interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORYBUFFER_H 15| |#define LLVM_SUPPORT_MEMORYBUFFER_H 16| | 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/Support/CBindingWrapping.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include "llvm/Support/ErrorOr.h" 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |class MemoryBufferRef; 27| | 28| |/// This interface provides simple read-only access to a block of memory, and 29| |/// provides simple methods for reading files and standard input into a memory 30| |/// buffer. In addition to basic access to the characters in the file, this 31| |/// interface guarantees you can read one character past the end of the file, 32| |/// and that this character will read as '\0'. 33| |/// 34| |/// The '\0' guarantee is needed to support an optimization -- it's intended to 35| |/// be more efficient for clients which are reading all the data to stop 36| |/// reading when they encounter a '\0' than to continually check the file 37| |/// position to see if it has reached the end of the file. 38| |class MemoryBuffer { 39| | const char *BufferStart; // Start of the buffer. 40| | const char *BufferEnd; // End of the buffer. 41| | 42| | MemoryBuffer(const MemoryBuffer &) = delete; 43| | MemoryBuffer &operator=(const MemoryBuffer &) = delete; 44| |protected: 45| 0| MemoryBuffer() {} 46| | void init(const char *BufStart, const char *BufEnd, 47| | bool RequiresNullTerminator); 48| |public: 49| | virtual ~MemoryBuffer(); 50| | 51| | const char *getBufferStart() const { return BufferStart; } 52| | const char *getBufferEnd() const { return BufferEnd; } 53| | size_t getBufferSize() const { return BufferEnd-BufferStart; } 54| | 55| | StringRef getBuffer() const { 56| | return StringRef(BufferStart, getBufferSize()); 57| | } 58| | 59| | /// Return an identifier for this buffer, typically the filename it was read 60| | /// from. 61| | virtual const char *getBufferIdentifier() const { 62| | return "Unknown buffer"; 63| | } 64| | 65| | /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer 66| | /// if successful, otherwise returning null. If FileSize is specified, this 67| | /// means that the client knows that the file exists and that it has the 68| | /// specified size. 69| | /// 70| | /// \param IsVolatileSize Set to true to indicate that the file size may be 71| | /// changing, e.g. when libclang tries to parse while the user is 72| | /// editing/updating the file. 73| | static ErrorOr> 74| | getFile(const Twine &Filename, int64_t FileSize = -1, 75| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 76| | 77| | /// Given an already-open file descriptor, map some slice of it into a 78| | /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. 79| | /// Since this is in the middle of a file, the buffer is not null terminated. 80| | static ErrorOr> 81| | getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, 82| | int64_t Offset); 83| | 84| | /// Given an already-open file descriptor, read the file and return a 85| | /// MemoryBuffer. 86| | /// 87| | /// \param IsVolatileSize Set to true to indicate that the file size may be 88| | /// changing, e.g. when libclang tries to parse while the user is 89| | /// editing/updating the file. 90| | static ErrorOr> 91| | getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, 92| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 93| | 94| | /// Open the specified memory range as a MemoryBuffer. Note that InputData 95| | /// must be null terminated if RequiresNullTerminator is true. 96| | static std::unique_ptr 97| | getMemBuffer(StringRef InputData, StringRef BufferName = "", 98| | bool RequiresNullTerminator = true); 99| | 100| | static std::unique_ptr 101| | getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); 102| | 103| | /// Open the specified memory range as a MemoryBuffer, copying the contents 104| | /// and taking ownership of it. InputData does not have to be null terminated. 105| | static std::unique_ptr 106| | getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); 107| | 108| | /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note 109| | /// that the caller need not initialize the memory allocated by this method. 110| | /// The memory is owned by the MemoryBuffer object. 111| | static std::unique_ptr 112| | getNewMemBuffer(size_t Size, StringRef BufferName = ""); 113| | 114| | /// Allocate a new MemoryBuffer of the specified size that is not initialized. 115| | /// Note that the caller should initialize the memory allocated by this 116| | /// method. The memory is owned by the MemoryBuffer object. 117| | static std::unique_ptr 118| | getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); 119| | 120| | /// Read all of stdin into a file buffer, and return it. 121| | static ErrorOr> getSTDIN(); 122| | 123| | /// Open the specified file as a MemoryBuffer, or open stdin if the Filename 124| | /// is "-". 125| | static ErrorOr> 126| | getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1); 127| | 128| | /// Map a subrange of the the specified file as a MemoryBuffer. 129| | static ErrorOr> 130| | getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); 131| | 132| | //===--------------------------------------------------------------------===// 133| | // Provided for performance analysis. 134| | //===--------------------------------------------------------------------===// 135| | 136| | /// The kind of memory backing used to support the MemoryBuffer. 137| | enum BufferKind { 138| | MemoryBuffer_Malloc, 139| | MemoryBuffer_MMap 140| | }; 141| | 142| | /// Return information on the memory mechanism used to support the 143| | /// MemoryBuffer. 144| | virtual BufferKind getBufferKind() const = 0; 145| | 146| | MemoryBufferRef getMemBufferRef() const; 147| |}; 148| | 149| |class MemoryBufferRef { 150| | StringRef Buffer; 151| | StringRef Identifier; 152| | 153| |public: 154| 0| MemoryBufferRef() {} 155| | MemoryBufferRef(StringRef Buffer, StringRef Identifier) 156| 0| : Buffer(Buffer), Identifier(Identifier) {} 157| | 158| | StringRef getBuffer() const { return Buffer; } 159| | 160| | StringRef getBufferIdentifier() const { return Identifier; } 161| | 162| | const char *getBufferStart() const { return Buffer.begin(); } 163| | const char *getBufferEnd() const { return Buffer.end(); } 164| 0| size_t getBufferSize() const { return Buffer.size(); } 165| |}; 166| | 167| |// Create wrappers for C Binding types (see CBindingWrapping.h). 168| |typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; 169| |DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) 170| | 171| |} // end namespace llvm 172| | 173| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Path.h: 1| |//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::path namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_PATH_H 17| |#define LLVM_SUPPORT_PATH_H 18| | 19| |#include "llvm/ADT/SmallString.h" 20| |#include "llvm/ADT/Twine.h" 21| |#include "llvm/Support/DataTypes.h" 22| |#include 23| | 24| |namespace llvm { 25| |namespace sys { 26| |namespace path { 27| | 28| |/// @name Lexical Component Iterator 29| |/// @{ 30| | 31| |/// @brief Path iterator. 32| |/// 33| |/// This is an input iterator that iterates over the individual components in 34| |/// \a path. The traversal order is as follows: 35| |/// * The root-name element, if present. 36| |/// * The root-directory element, if present. 37| |/// * Each successive filename element, if present. 38| |/// * Dot, if one or more trailing non-root slash characters are present. 39| |/// Traversing backwards is possible with \a reverse_iterator 40| |/// 41| |/// Iteration examples. Each component is separated by ',': 42| |/// @code 43| |/// / => / 44| |/// /foo => /,foo 45| |/// foo/ => foo,. 46| |/// /foo/bar => /,foo,bar 47| |/// ../ => ..,. 48| |/// C:\foo\bar => C:,/,foo,bar 49| |/// @endcode 50| |class const_iterator 51| | : public std::iterator { 52| | StringRef Path; ///< The entire path. 53| | StringRef Component; ///< The current component. Not necessarily in Path. 54| | size_t Position; ///< The iterators current position within Path. 55| | 56| | // An end iterator has Position = Path.size() + 1. 57| | friend const_iterator begin(StringRef path); 58| | friend const_iterator end(StringRef path); 59| | 60| |public: 61| | reference operator*() const { return Component; } 62| | pointer operator->() const { return &Component; } 63| | const_iterator &operator++(); // preincrement 64| | const_iterator &operator++(int); // postincrement 65| | bool operator==(const const_iterator &RHS) const; 66| | bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); } 67| | 68| | /// @brief Difference in bytes between this and RHS. 69| | ptrdiff_t operator-(const const_iterator &RHS) const; 70| |}; 71| | 72| |/// @brief Reverse path iterator. 73| |/// 74| |/// This is an input iterator that iterates over the individual components in 75| |/// \a path in reverse order. The traversal order is exactly reversed from that 76| |/// of \a const_iterator 77| |class reverse_iterator 78| | : public std::iterator { 79| | StringRef Path; ///< The entire path. 80| | StringRef Component; ///< The current component. Not necessarily in Path. 81| | size_t Position; ///< The iterators current position within Path. 82| | 83| | friend reverse_iterator rbegin(StringRef path); 84| | friend reverse_iterator rend(StringRef path); 85| | 86| |public: 87| | reference operator*() const { return Component; } 88| 0| pointer operator->() const { return &Component; } 89| | reverse_iterator &operator++(); // preincrement 90| | reverse_iterator &operator++(int); // postincrement 91| | bool operator==(const reverse_iterator &RHS) const; 92| 0| bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } 93| |}; 94| | 95| |/// @brief Get begin iterator over \a path. 96| |/// @param path Input path. 97| |/// @returns Iterator initialized with the first component of \a path. 98| |const_iterator begin(StringRef path); 99| | 100| |/// @brief Get end iterator over \a path. 101| |/// @param path Input path. 102| |/// @returns Iterator initialized to the end of \a path. 103| |const_iterator end(StringRef path); 104| | 105| |/// @brief Get reverse begin iterator over \a path. 106| |/// @param path Input path. 107| |/// @returns Iterator initialized with the first reverse component of \a path. 108| |reverse_iterator rbegin(StringRef path); 109| | 110| |/// @brief Get reverse end iterator over \a path. 111| |/// @param path Input path. 112| |/// @returns Iterator initialized to the reverse end of \a path. 113| |reverse_iterator rend(StringRef path); 114| | 115| |/// @} 116| |/// @name Lexical Modifiers 117| |/// @{ 118| | 119| |/// @brief Remove the last component from \a path unless it is the root dir. 120| |/// 121| |/// @code 122| |/// directory/filename.cpp => directory/ 123| |/// directory/ => directory 124| |/// filename.cpp => 125| |/// / => / 126| |/// @endcode 127| |/// 128| |/// @param path A path that is modified to not have a file component. 129| |void remove_filename(SmallVectorImpl &path); 130| | 131| |/// @brief Replace the file extension of \a path with \a extension. 132| |/// 133| |/// @code 134| |/// ./filename.cpp => ./filename.extension 135| |/// ./filename => ./filename.extension 136| |/// ./ => ./.extension 137| |/// @endcode 138| |/// 139| |/// @param path A path that has its extension replaced with \a extension. 140| |/// @param extension The extension to be added. It may be empty. It may also 141| |/// optionally start with a '.', if it does not, one will be 142| |/// prepended. 143| |void replace_extension(SmallVectorImpl &path, const Twine &extension); 144| | 145| |/// @brief Append to path. 146| |/// 147| |/// @code 148| |/// /foo + bar/f => /foo/bar/f 149| |/// /foo/ + bar/f => /foo/bar/f 150| |/// foo + bar/f => foo/bar/f 151| |/// @endcode 152| |/// 153| |/// @param path Set to \a path + \a component. 154| |/// @param a The component to be appended to \a path. 155| |void append(SmallVectorImpl &path, const Twine &a, 156| | const Twine &b = "", 157| | const Twine &c = "", 158| | const Twine &d = ""); 159| | 160| |/// @brief Append to path. 161| |/// 162| |/// @code 163| |/// /foo + [bar,f] => /foo/bar/f 164| |/// /foo/ + [bar,f] => /foo/bar/f 165| |/// foo + [bar,f] => foo/bar/f 166| |/// @endcode 167| |/// 168| |/// @param path Set to \a path + [\a begin, \a end). 169| |/// @param begin Start of components to append. 170| |/// @param end One past the end of components to append. 171| |void append(SmallVectorImpl &path, 172| | const_iterator begin, const_iterator end); 173| | 174| |/// @} 175| |/// @name Transforms (or some other better name) 176| |/// @{ 177| | 178| |/// Convert path to the native form. This is used to give paths to users and 179| |/// operating system calls in the platform's normal way. For example, on Windows 180| |/// all '/' are converted to '\'. 181| |/// 182| |/// @param path A path that is transformed to native format. 183| |/// @param result Holds the result of the transformation. 184| |void native(const Twine &path, SmallVectorImpl &result); 185| | 186| |/// Convert path to the native form in place. This is used to give paths to 187| |/// users and operating system calls in the platform's normal way. For example, 188| |/// on Windows all '/' are converted to '\'. 189| |/// 190| |/// @param path A path that is transformed to native format. 191| |void native(SmallVectorImpl &path); 192| | 193| |/// @} 194| |/// @name Lexical Observers 195| |/// @{ 196| | 197| |/// @brief Get root name. 198| |/// 199| |/// @code 200| |/// //net/hello => //net 201| |/// c:/hello => c: (on Windows, on other platforms nothing) 202| |/// /hello => 203| |/// @endcode 204| |/// 205| |/// @param path Input path. 206| |/// @result The root name of \a path if it has one, otherwise "". 207| |StringRef root_name(StringRef path); 208| | 209| |/// @brief Get root directory. 210| |/// 211| |/// @code 212| |/// /goo/hello => / 213| |/// c:/hello => / 214| |/// d/file.txt => 215| |/// @endcode 216| |/// 217| |/// @param path Input path. 218| |/// @result The root directory of \a path if it has one, otherwise 219| |/// "". 220| |StringRef root_directory(StringRef path); 221| | 222| |/// @brief Get root path. 223| |/// 224| |/// Equivalent to root_name + root_directory. 225| |/// 226| |/// @param path Input path. 227| |/// @result The root path of \a path if it has one, otherwise "". 228| |StringRef root_path(StringRef path); 229| | 230| |/// @brief Get relative path. 231| |/// 232| |/// @code 233| |/// C:\hello\world => hello\world 234| |/// foo/bar => foo/bar 235| |/// /foo/bar => foo/bar 236| |/// @endcode 237| |/// 238| |/// @param path Input path. 239| |/// @result The path starting after root_path if one exists, otherwise "". 240| |StringRef relative_path(StringRef path); 241| | 242| |/// @brief Get parent path. 243| |/// 244| |/// @code 245| |/// / => 246| |/// /foo => / 247| |/// foo/../bar => foo/.. 248| |/// @endcode 249| |/// 250| |/// @param path Input path. 251| |/// @result The parent path of \a path if one exists, otherwise "". 252| |StringRef parent_path(StringRef path); 253| | 254| |/// @brief Get filename. 255| |/// 256| |/// @code 257| |/// /foo.txt => foo.txt 258| |/// . => . 259| |/// .. => .. 260| |/// / => / 261| |/// @endcode 262| |/// 263| |/// @param path Input path. 264| |/// @result The filename part of \a path. This is defined as the last component 265| |/// of \a path. 266| |StringRef filename(StringRef path); 267| | 268| |/// @brief Get stem. 269| |/// 270| |/// If filename contains a dot but not solely one or two dots, result is the 271| |/// substring of filename ending at (but not including) the last dot. Otherwise 272| |/// it is filename. 273| |/// 274| |/// @code 275| |/// /foo/bar.txt => bar 276| |/// /foo/bar => bar 277| |/// /foo/.txt => 278| |/// /foo/. => . 279| |/// /foo/.. => .. 280| |/// @endcode 281| |/// 282| |/// @param path Input path. 283| |/// @result The stem of \a path. 284| |StringRef stem(StringRef path); 285| | 286| |/// @brief Get extension. 287| |/// 288| |/// If filename contains a dot but not solely one or two dots, result is the 289| |/// substring of filename starting at (and including) the last dot, and ending 290| |/// at the end of \a path. Otherwise "". 291| |/// 292| |/// @code 293| |/// /foo/bar.txt => .txt 294| |/// /foo/bar => 295| |/// /foo/.txt => .txt 296| |/// @endcode 297| |/// 298| |/// @param path Input path. 299| |/// @result The extension of \a path. 300| |StringRef extension(StringRef path); 301| | 302| |/// @brief Check whether the given char is a path separator on the host OS. 303| |/// 304| |/// @param value a character 305| |/// @result true if \a value is a path separator character on the host OS 306| |bool is_separator(char value); 307| | 308| |/// @brief Return the preferred separator for this platform. 309| |/// 310| |/// @result StringRef of the preferred separator, null-terminated. 311| |StringRef get_separator(); 312| | 313| |/// @brief Get the typical temporary directory for the system, e.g., 314| |/// "/var/tmp" or "C:/TEMP" 315| |/// 316| |/// @param erasedOnReboot Whether to favor a path that is erased on reboot 317| |/// rather than one that potentially persists longer. This parameter will be 318| |/// ignored if the user or system has set the typical environment variable 319| |/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. 320| |/// 321| |/// @param result Holds the resulting path name. 322| |void system_temp_directory(bool erasedOnReboot, SmallVectorImpl &result); 323| | 324| |/// @brief Get the user's home directory. 325| |/// 326| |/// @param result Holds the resulting path name. 327| |/// @result True if a home directory is set, false otherwise. 328| |bool home_directory(SmallVectorImpl &result); 329| | 330| |/// @brief Has root name? 331| |/// 332| |/// root_name != "" 333| |/// 334| |/// @param path Input path. 335| |/// @result True if the path has a root name, false otherwise. 336| |bool has_root_name(const Twine &path); 337| | 338| |/// @brief Has root directory? 339| |/// 340| |/// root_directory != "" 341| |/// 342| |/// @param path Input path. 343| |/// @result True if the path has a root directory, false otherwise. 344| |bool has_root_directory(const Twine &path); 345| | 346| |/// @brief Has root path? 347| |/// 348| |/// root_path != "" 349| |/// 350| |/// @param path Input path. 351| |/// @result True if the path has a root path, false otherwise. 352| |bool has_root_path(const Twine &path); 353| | 354| |/// @brief Has relative path? 355| |/// 356| |/// relative_path != "" 357| |/// 358| |/// @param path Input path. 359| |/// @result True if the path has a relative path, false otherwise. 360| |bool has_relative_path(const Twine &path); 361| | 362| |/// @brief Has parent path? 363| |/// 364| |/// parent_path != "" 365| |/// 366| |/// @param path Input path. 367| |/// @result True if the path has a parent path, false otherwise. 368| |bool has_parent_path(const Twine &path); 369| | 370| |/// @brief Has filename? 371| |/// 372| |/// filename != "" 373| |/// 374| |/// @param path Input path. 375| |/// @result True if the path has a filename, false otherwise. 376| |bool has_filename(const Twine &path); 377| | 378| |/// @brief Has stem? 379| |/// 380| |/// stem != "" 381| |/// 382| |/// @param path Input path. 383| |/// @result True if the path has a stem, false otherwise. 384| |bool has_stem(const Twine &path); 385| | 386| |/// @brief Has extension? 387| |/// 388| |/// extension != "" 389| |/// 390| |/// @param path Input path. 391| |/// @result True if the path has a extension, false otherwise. 392| |bool has_extension(const Twine &path); 393| | 394| |/// @brief Is path absolute? 395| |/// 396| |/// @param path Input path. 397| |/// @result True if the path is absolute, false if it is not. 398| |bool is_absolute(const Twine &path); 399| | 400| |/// @brief Is path relative? 401| |/// 402| |/// @param path Input path. 403| |/// @result True if the path is relative, false if it is not. 404| |bool is_relative(const Twine &path); 405| | 406| |} // end namespace path 407| |} // end namespace sys 408| |} // end namespace llvm 409| | 410| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/PointerLikeTypeTraits.h: 1| |//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the PointerLikeTypeTraits class. This allows data 11| |// structures to reason about pointers and other things that are pointer sized. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 16| |#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 17| | 18| |#include "llvm/Support/DataTypes.h" 19| | 20| |namespace llvm { 21| | 22| |/// PointerLikeTypeTraits - This is a traits object that is used to handle 23| |/// pointer types and things that are just wrappers for pointers as a uniform 24| |/// entity. 25| |template 26| |class PointerLikeTypeTraits { 27| | // getAsVoidPointer 28| | // getFromVoidPointer 29| | // getNumLowBitsAvailable 30| |}; 31| | 32| |// Provide PointerLikeTypeTraits for non-cvr pointers. 33| |template 34| |class PointerLikeTypeTraits { 35| |public: 36| | static inline void *getAsVoidPointer(T* P) { return P; } 37| | static inline T *getFromVoidPointer(void *P) { 38| | return static_cast(P); 39| | } 40| | 41| | /// Note, we assume here that malloc returns objects at least 4-byte aligned. 42| | /// However, this may be wrong, or pointers may be from something other than 43| | /// malloc. In this case, you should specialize this template to reduce this. 44| | /// 45| | /// All clients should use assertions to do a run-time check to ensure that 46| | /// this is actually true. 47| | enum { NumLowBitsAvailable = 2 }; 48| |}; 49| | 50| |// Provide PointerLikeTypeTraits for const pointers. 51| |template 52| |class PointerLikeTypeTraits { 53| | typedef PointerLikeTypeTraits NonConst; 54| | 55| |public: 56| | static inline const void *getAsVoidPointer(const T* P) { 57| | return NonConst::getAsVoidPointer(const_cast(P)); 58| | } 59| | static inline const T *getFromVoidPointer(const void *P) { 60| | return NonConst::getFromVoidPointer(const_cast(P)); 61| | } 62| | enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; 63| |}; 64| | 65| |// Provide PointerLikeTypeTraits for uintptr_t. 66| |template<> 67| |class PointerLikeTypeTraits { 68| |public: 69| 0| static inline void *getAsVoidPointer(uintptr_t P) { 70| 0| return reinterpret_cast(P); 71| 0| } 72| 0| static inline uintptr_t getFromVoidPointer(void *P) { 73| 0| return reinterpret_cast(P); 74| 0| } 75| | // No bits are available! 76| | enum { NumLowBitsAvailable = 0 }; 77| |}; 78| | 79| |} // end namespace llvm 80| | 81| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SwapByteOrder.h: 1| |//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic and optimized functions to swap the byte order of 11| |// an integral type. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H 16| |#define LLVM_SUPPORT_SWAPBYTEORDER_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| |namespace sys { 25| | 26| |/// SwapByteOrder_16 - This function returns a byte-swapped representation of 27| |/// the 16-bit argument. 28| |inline uint16_t SwapByteOrder_16(uint16_t value) { 29| |#if defined(_MSC_VER) && !defined(_DEBUG) 30| | // The DLL version of the runtime lacks these functions (bug!?), but in a 31| | // release build they're replaced with BSWAP instructions anyway. 32| | return _byteswap_ushort(value); 33| |#else 34| | uint16_t Hi = value << 8; 35| | uint16_t Lo = value >> 8; 36| | return Hi | Lo; 37| |#endif 38| |} 39| | 40| |/// SwapByteOrder_32 - This function returns a byte-swapped representation of 41| |/// the 32-bit argument. 42| 0|inline uint32_t SwapByteOrder_32(uint32_t value) { 43| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 44| 0| return __builtin_bswap32(value); 45| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 46| 0| return _byteswap_ulong(value); 47| 0|#else 48| 0| uint32_t Byte0 = value & 0x000000FF; 49| 0| uint32_t Byte1 = value & 0x0000FF00; 50| 0| uint32_t Byte2 = value & 0x00FF0000; 51| 0| uint32_t Byte3 = value & 0xFF000000; 52| 0| return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 53| 0|#endif 54| 0|} 55| | 56| |/// SwapByteOrder_64 - This function returns a byte-swapped representation of 57| |/// the 64-bit argument. 58| 0|inline uint64_t SwapByteOrder_64(uint64_t value) { 59| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 60| 0| return __builtin_bswap64(value); 61| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 62| 0| return _byteswap_uint64(value); 63| 0|#else 64| 0| uint64_t Hi = SwapByteOrder_32(uint32_t(value)); 65| 0| uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); 66| 0| return (Hi << 32) | Lo; 67| 0|#endif 68| 0|} 69| | 70| 0|inline unsigned char getSwappedBytes(unsigned char C) { return C; } 71| 0|inline signed char getSwappedBytes(signed char C) { return C; } 72| 0|inline char getSwappedBytes(char C) { return C; } 73| | 74| 0|inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } 75| 0|inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } 76| | 77| 0|inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } 78| 0|inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } 79| | 80| |#if __LONG_MAX__ == __INT_MAX__ 81| |inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } 82| |inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } 83| |#elif __LONG_MAX__ == __LONG_LONG_MAX__ 84| 0|inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } 85| 0|inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } 86| |#else 87| |#error "Unknown long size!" 88| |#endif 89| | 90| 0|inline unsigned long long getSwappedBytes(unsigned long long C) { 91| 0| return SwapByteOrder_64(C); 92| 0|} 93| 0|inline signed long long getSwappedBytes(signed long long C) { 94| 0| return SwapByteOrder_64(C); 95| 0|} 96| | 97| 0|inline float getSwappedBytes(float C) { 98| 0| union { 99| 0| uint32_t i; 100| 0| float f; 101| 0| } in, out; 102| 0| in.f = C; 103| 0| out.i = SwapByteOrder_32(in.i); 104| 0| return out.f; 105| 0|} 106| | 107| 0|inline float getSwappedBytes(double C) { 108| 0| union { 109| 0| uint64_t i; 110| 0| double d; 111| 0| } in, out; 112| 0| in.d = C; 113| 0| out.i = SwapByteOrder_64(in.i); 114| 0| return out.d; 115| 0|} 116| | 117| |template 118| 0|inline void swapByteOrder(T &Value) { 119| 0| Value = getSwappedBytes(Value); 120| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIyEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIjEEvRT_ ------------------ 121| | 122| |} // end namespace sys 123| |} // end namespace llvm 124| | 125| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/TimeValue.h: 1| |//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This header file declares the operating system TimeValue concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_TIMEVALUE_H 15| |#define LLVM_SUPPORT_TIMEVALUE_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| | 20| |namespace llvm { 21| |namespace sys { 22| | /// This class is used where a precise fixed point in time is required. The 23| | /// range of TimeValue spans many hundreds of billions of years both past and 24| | /// present. The precision of TimeValue is to the nanosecond. However, the 25| | /// actual precision of its values will be determined by the resolution of 26| | /// the system clock. The TimeValue class is used in conjunction with several 27| | /// other lib/System interfaces to specify the time at which a call should 28| | /// timeout, etc. 29| | /// @since 1.4 30| | /// @brief Provides an abstraction for a fixed point in time. 31| | class TimeValue { 32| | 33| | /// @name Constants 34| | /// @{ 35| | public: 36| | 37| | /// A constant TimeValue representing the smallest time 38| | /// value permissible by the class. MinTime is some point 39| | /// in the distant past, about 300 billion years BCE. 40| | /// @brief The smallest possible time value. 41| | static TimeValue MinTime() { 42| | return TimeValue ( INT64_MIN,0 ); 43| | } 44| | 45| | /// A constant TimeValue representing the largest time 46| | /// value permissible by the class. MaxTime is some point 47| | /// in the distant future, about 300 billion years AD. 48| | /// @brief The largest possible time value. 49| 0| static TimeValue MaxTime() { 50| 0| return TimeValue ( INT64_MAX,0 ); 51| 0| } 52| | 53| | /// A constant TimeValue representing the base time, 54| | /// or zero time of 00:00:00 (midnight) January 1st, 2000. 55| | /// @brief 00:00:00 Jan 1, 2000 UTC. 56| 0| static TimeValue ZeroTime() { 57| 0| return TimeValue ( 0,0 ); 58| 0| } 59| | 60| | /// A constant TimeValue for the Posix base time which is 61| | /// 00:00:00 (midnight) January 1st, 1970. 62| | /// @brief 00:00:00 Jan 1, 1970 UTC. 63| 0| static TimeValue PosixZeroTime() { 64| 0| return TimeValue ( PosixZeroTimeSeconds,0 ); 65| 0| } 66| | 67| | /// A constant TimeValue for the Win32 base time which is 68| | /// 00:00:00 (midnight) January 1st, 1601. 69| | /// @brief 00:00:00 Jan 1, 1601 UTC. 70| 0| static TimeValue Win32ZeroTime() { 71| 0| return TimeValue ( Win32ZeroTimeSeconds,0 ); 72| 0| } 73| | 74| | /// @} 75| | /// @name Types 76| | /// @{ 77| | public: 78| | typedef int64_t SecondsType; ///< Type used for representing seconds. 79| | typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. 80| | 81| | enum TimeConversions { 82| | NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion 83| | MICROSECONDS_PER_SECOND = 1000000, ///< One Million 84| | MILLISECONDS_PER_SECOND = 1000, ///< One Thousand 85| | NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand 86| | NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million 87| | NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) 88| | }; 89| | 90| | /// @} 91| | /// @name Constructors 92| | /// @{ 93| | public: 94| | /// \brief Default construct a time value, initializing to ZeroTime. 95| 0| TimeValue() : seconds_(0), nanos_(0) {} 96| | 97| | /// Caller provides the exact value in seconds and nanoseconds. The 98| | /// \p nanos argument defaults to zero for convenience. 99| | /// @brief Explicit constructor 100| | explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) 101| | : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } 102| | 103| | /// Caller provides the exact value as a double in seconds with the 104| | /// fractional part representing nanoseconds. 105| | /// @brief Double Constructor. 106| | explicit TimeValue( double new_time ) 107| 0| : seconds_( 0 ) , nanos_ ( 0 ) { 108| 0| SecondsType integer_part = static_cast( new_time ); 109| 0| seconds_ = integer_part; 110| 0| nanos_ = static_cast( (new_time - 111| 0| static_cast(integer_part)) * NANOSECONDS_PER_SECOND ); 112| 0| this->normalize(); 113| 0| } 114| | 115| | /// This is a static constructor that returns a TimeValue that represents 116| | /// the current time. 117| | /// @brief Creates a TimeValue with the current time (UTC). 118| | static TimeValue now(); 119| | 120| | /// @} 121| | /// @name Operators 122| | /// @{ 123| | public: 124| | /// Add \p that to \p this. 125| | /// @returns this 126| | /// @brief Incrementing assignment operator. 127| 0| TimeValue& operator += (const TimeValue& that ) { 128| 0| this->seconds_ += that.seconds_ ; 129| 0| this->nanos_ += that.nanos_ ; 130| 0| this->normalize(); 131| 0| return *this; 132| 0| } 133| | 134| | /// Subtract \p that from \p this. 135| | /// @returns this 136| | /// @brief Decrementing assignment operator. 137| 0| TimeValue& operator -= (const TimeValue &that ) { 138| 0| this->seconds_ -= that.seconds_ ; 139| 0| this->nanos_ -= that.nanos_ ; 140| 0| this->normalize(); 141| 0| return *this; 142| 0| } 143| | 144| | /// Determine if \p this is less than \p that. 145| | /// @returns True iff *this < that. 146| | /// @brief True if this < that. 147| 0| int operator < (const TimeValue &that) const { return that > *this; } 148| | 149| | /// Determine if \p this is greather than \p that. 150| | /// @returns True iff *this > that. 151| | /// @brief True if this > that. 152| 0| int operator > (const TimeValue &that) const { 153| 0| if ( this->seconds_ > that.seconds_ ) { 154| 0| return 1; 155| 0| } else if ( this->seconds_ == that.seconds_ ) { 156| 0| if ( this->nanos_ > that.nanos_ ) return 1; 157| 0| } 158| 0| return 0; 159| 0| } 160| | 161| | /// Determine if \p this is less than or equal to \p that. 162| | /// @returns True iff *this <= that. 163| | /// @brief True if this <= that. 164| 0| int operator <= (const TimeValue &that) const { return that >= *this; } 165| | 166| | /// Determine if \p this is greater than or equal to \p that. 167| | /// @returns True iff *this >= that. 168| 0| int operator >= (const TimeValue &that) const { 169| 0| if ( this->seconds_ > that.seconds_ ) { 170| 0| return 1; 171| 0| } else if ( this->seconds_ == that.seconds_ ) { 172| 0| if ( this->nanos_ >= that.nanos_ ) return 1; 173| 0| } 174| 0| return 0; 175| 0| } 176| | 177| | /// Determines if two TimeValue objects represent the same moment in time. 178| | /// @returns True iff *this == that. 179| 0| int operator == (const TimeValue &that) const { 180| 0| return (this->seconds_ == that.seconds_) && 181| 0| (this->nanos_ == that.nanos_); 182| 0| } 183| | 184| | /// Determines if two TimeValue objects represent times that are not the 185| | /// same. 186| | /// @returns True iff *this != that. 187| 0| int operator != (const TimeValue &that) const { return !(*this == that); } 188| | 189| | /// Adds two TimeValue objects together. 190| | /// @returns The sum of the two operands as a new TimeValue 191| | /// @brief Addition operator. 192| | friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); 193| | 194| | /// Subtracts two TimeValue objects. 195| | /// @returns The difference of the two operands as a new TimeValue 196| | /// @brief Subtraction operator. 197| | friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); 198| | 199| | /// @} 200| | /// @name Accessors 201| | /// @{ 202| | public: 203| | 204| | /// Returns only the seconds component of the TimeValue. The nanoseconds 205| | /// portion is ignored. No rounding is performed. 206| | /// @brief Retrieve the seconds component 207| 0| SecondsType seconds() const { return seconds_; } 208| | 209| | /// Returns only the nanoseconds component of the TimeValue. The seconds 210| | /// portion is ignored. 211| | /// @brief Retrieve the nanoseconds component. 212| | NanoSecondsType nanoseconds() const { return nanos_; } 213| | 214| | /// Returns only the fractional portion of the TimeValue rounded down to the 215| | /// nearest microsecond (divide by one thousand). 216| | /// @brief Retrieve the fractional part as microseconds; 217| 0| uint32_t microseconds() const { 218| 0| return nanos_ / NANOSECONDS_PER_MICROSECOND; 219| 0| } 220| | 221| | /// Returns only the fractional portion of the TimeValue rounded down to the 222| | /// nearest millisecond (divide by one million). 223| | /// @brief Retrieve the fractional part as milliseconds; 224| 0| uint32_t milliseconds() const { 225| 0| return nanos_ / NANOSECONDS_PER_MILLISECOND; 226| 0| } 227| | 228| | /// Returns the TimeValue as a number of microseconds. Note that the value 229| | /// returned can overflow because the range of a uint64_t is smaller than 230| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 231| | /// systems and is therefore provided. 232| | /// @brief Convert to a number of microseconds (can overflow) 233| 0| uint64_t usec() const { 234| 0| return seconds_ * MICROSECONDS_PER_SECOND + 235| 0| ( nanos_ / NANOSECONDS_PER_MICROSECOND ); 236| 0| } 237| | 238| | /// Returns the TimeValue as a number of milliseconds. Note that the value 239| | /// returned can overflow because the range of a uint64_t is smaller than 240| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 241| | /// systems and is therefore provided. 242| | /// @brief Convert to a number of milliseconds (can overflow) 243| 0| uint64_t msec() const { 244| 0| return seconds_ * MILLISECONDS_PER_SECOND + 245| 0| ( nanos_ / NANOSECONDS_PER_MILLISECOND ); 246| 0| } 247| | 248| | /// Converts the TimeValue into the corresponding number of seconds 249| | /// since the epoch (00:00:00 Jan 1,1970). 250| | uint64_t toEpochTime() const { 251| | return seconds_ - PosixZeroTimeSeconds; 252| | } 253| | 254| | /// Converts the TimeValue into the corresponding number of "ticks" for 255| | /// Win32 platforms, correcting for the difference in Win32 zero time. 256| | /// @brief Convert to Win32's FILETIME 257| | /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) 258| 0| uint64_t toWin32Time() const { 259| 0| uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); 260| 0| result += nanos_ / NANOSECONDS_PER_WIN32_TICK; 261| 0| return result; 262| 0| } 263| | 264| | /// Provides the seconds and nanoseconds as results in its arguments after 265| | /// correction for the Posix zero time. 266| | /// @brief Convert to timespec time (ala POSIX.1b) 267| 0| void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { 268| 0| seconds = seconds_ - PosixZeroTimeSeconds; 269| 0| nanos = nanos_; 270| 0| } 271| | 272| | /// Provides conversion of the TimeValue into a readable time & date. 273| | /// @returns std::string containing the readable time value 274| | /// @brief Convert time to a string. 275| | std::string str() const; 276| | 277| | /// @} 278| | /// @name Mutators 279| | /// @{ 280| | public: 281| | /// The seconds component of the TimeValue is set to \p sec without 282| | /// modifying the nanoseconds part. This is useful for whole second 283| | /// arithmetic. 284| | /// @brief Set the seconds component. 285| 0| void seconds (SecondsType sec ) { 286| 0| this->seconds_ = sec; 287| 0| this->normalize(); 288| 0| } 289| | 290| | /// The nanoseconds component of the TimeValue is set to \p nanos without 291| | /// modifying the seconds part. This is useful for basic computations 292| | /// involving just the nanoseconds portion. Note that the TimeValue will be 293| | /// normalized after this call so that the fractional (nanoseconds) portion 294| | /// will have the smallest equivalent value. 295| | /// @brief Set the nanoseconds component using a number of nanoseconds. 296| 0| void nanoseconds ( NanoSecondsType nanos ) { 297| 0| this->nanos_ = nanos; 298| 0| this->normalize(); 299| 0| } 300| | 301| | /// The seconds component remains unchanged. 302| | /// @brief Set the nanoseconds component using a number of microseconds. 303| 0| void microseconds ( int32_t micros ) { 304| 0| this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; 305| 0| this->normalize(); 306| 0| } 307| | 308| | /// The seconds component remains unchanged. 309| | /// @brief Set the nanoseconds component using a number of milliseconds. 310| 0| void milliseconds ( int32_t millis ) { 311| 0| this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; 312| 0| this->normalize(); 313| 0| } 314| | 315| | /// @brief Converts from microsecond format to TimeValue format 316| 0| void usec( int64_t microseconds ) { 317| 0| this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; 318| 0| this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * 319| 0| NANOSECONDS_PER_MICROSECOND; 320| 0| this->normalize(); 321| 0| } 322| | 323| | /// @brief Converts from millisecond format to TimeValue format 324| 0| void msec( int64_t milliseconds ) { 325| 0| this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; 326| 0| this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * 327| 0| NANOSECONDS_PER_MILLISECOND; 328| 0| this->normalize(); 329| 0| } 330| | 331| | /// Converts the \p seconds argument from PosixTime to the corresponding 332| | /// TimeValue and assigns that value to \p this. 333| | /// @brief Convert seconds form PosixTime to TimeValue 334| 0| void fromEpochTime( SecondsType seconds ) { 335| 0| seconds_ = seconds + PosixZeroTimeSeconds; 336| 0| nanos_ = 0; 337| 0| this->normalize(); 338| 0| } 339| | 340| | /// Converts the \p win32Time argument from Windows FILETIME to the 341| | /// corresponding TimeValue and assigns that value to \p this. 342| | /// @brief Convert seconds form Windows FILETIME to TimeValue 343| 0| void fromWin32Time( uint64_t win32Time ) { 344| 0| this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; 345| 0| this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; 346| 0| } 347| | 348| | /// @} 349| | /// @name Implementation 350| | /// @{ 351| | private: 352| | /// This causes the values to be represented so that the fractional 353| | /// part is minimized, possibly incrementing the seconds part. 354| | /// @brief Normalize to canonical form. 355| | void normalize(); 356| | 357| | /// @} 358| | /// @name Data 359| | /// @{ 360| | private: 361| | /// Store the values as a . 362| | SecondsType seconds_;///< Stores the seconds part of the TimeVal 363| | NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal 364| | 365| | static const SecondsType PosixZeroTimeSeconds; 366| | static const SecondsType Win32ZeroTimeSeconds; 367| | /// @} 368| | 369| | }; 370| | 371| 0|inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { 372| 0| TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); 373| 0| sum.normalize (); 374| 0| return sum; 375| 0|} 376| | 377| |inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { 378| | TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); 379| | difference.normalize (); 380| | return difference; 381| |} 382| | 383| |} 384| |} 385| | 386| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/raw_ostream.h: 1| |//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the raw_ostream class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_RAW_OSTREAM_H 15| |#define LLVM_SUPPORT_RAW_OSTREAM_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include 22| | 23| |namespace llvm { 24| | class format_object_base; 25| | class FormattedString; 26| | class FormattedNumber; 27| | template 28| | class SmallVectorImpl; 29| | 30| | namespace sys { 31| | namespace fs { 32| | enum OpenFlags : unsigned; 33| | } 34| | } 35| | 36| |/// raw_ostream - This class implements an extremely fast bulk output stream 37| |/// that can *only* output to a stream. It does not support seeking, reopening, 38| |/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs 39| |/// a chunk at a time. 40| |class raw_ostream { 41| |private: 42| | void operator=(const raw_ostream &) = delete; 43| | raw_ostream(const raw_ostream &) = delete; 44| | 45| | /// The buffer is handled in such a way that the buffer is 46| | /// uninitialized, unbuffered, or out of space when OutBufCur >= 47| | /// OutBufEnd. Thus a single comparison suffices to determine if we 48| | /// need to take the slow path to write a single character. 49| | /// 50| | /// The buffer is in one of three states: 51| | /// 1. Unbuffered (BufferMode == Unbuffered) 52| | /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). 53| | /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && 54| | /// OutBufEnd - OutBufStart >= 1). 55| | /// 56| | /// If buffered, then the raw_ostream owns the buffer if (BufferMode == 57| | /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is 58| | /// managed by the subclass. 59| | /// 60| | /// If a subclass installs an external buffer using SetBuffer then it can wait 61| | /// for a \see write_impl() call to handle the data which has been put into 62| | /// this buffer. 63| | char *OutBufStart, *OutBufEnd, *OutBufCur; 64| | 65| | enum BufferKind { 66| | Unbuffered = 0, 67| | InternalBuffer, 68| | ExternalBuffer 69| | } BufferMode; 70| | 71| |public: 72| | // color order matches ANSI escape sequence, don't change 73| | enum Colors { 74| | BLACK=0, 75| | RED, 76| | GREEN, 77| | YELLOW, 78| | BLUE, 79| | MAGENTA, 80| | CYAN, 81| | WHITE, 82| | SAVEDCOLOR 83| | }; 84| | 85| | explicit raw_ostream(bool unbuffered=false) 86| | : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { 87| | // Start out ready to flush. 88| | OutBufStart = OutBufEnd = OutBufCur = nullptr; 89| | } 90| | 91| | virtual ~raw_ostream(); 92| | 93| | /// tell - Return the current offset with the file. 94| | uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } 95| | 96| | //===--------------------------------------------------------------------===// 97| | // Configuration Interface 98| | //===--------------------------------------------------------------------===// 99| | 100| | /// SetBuffered - Set the stream to be buffered, with an automatically 101| | /// determined buffer size. 102| | void SetBuffered(); 103| | 104| | /// SetBufferSize - Set the stream to be buffered, using the 105| | /// specified buffer size. 106| 0| void SetBufferSize(size_t Size) { 107| 0| flush(); 108| 0| SetBufferAndMode(new char[Size], Size, InternalBuffer); 109| 0| } 110| | 111| 0| size_t GetBufferSize() const { 112| 0| // If we're supposed to be buffered but haven't actually gotten around 113| 0| // to allocating the buffer yet, return the value that would be used. 114| 0| if (BufferMode != Unbuffered && OutBufStart == nullptr) 115| 0| return preferred_buffer_size(); 116| 0| 117| 0| // Otherwise just return the size of the allocated buffer. 118| 0| return OutBufEnd - OutBufStart; 119| 0| } 120| | 121| | /// SetUnbuffered - Set the stream to be unbuffered. When 122| | /// unbuffered, the stream will flush after every write. This routine 123| | /// will also flush the buffer immediately when the stream is being 124| | /// set to unbuffered. 125| 0| void SetUnbuffered() { 126| 0| flush(); 127| 0| SetBufferAndMode(nullptr, 0, Unbuffered); 128| 0| } 129| | 130| | size_t GetNumBytesInBuffer() const { 131| | return OutBufCur - OutBufStart; 132| | } 133| | 134| | //===--------------------------------------------------------------------===// 135| | // Data Output Interface 136| | //===--------------------------------------------------------------------===// 137| | 138| 0| void flush() { 139| 0| if (OutBufCur != OutBufStart) 140| 0| flush_nonempty(); 141| 0| } 142| | 143| 0| raw_ostream &operator<<(char C) { 144| 0| if (OutBufCur >= OutBufEnd) 145| 0| return write(C); 146| 0| *OutBufCur++ = C; 147| 0| return *this; 148| 0| } 149| | 150| | raw_ostream &operator<<(unsigned char C) { 151| | if (OutBufCur >= OutBufEnd) 152| | return write(C); 153| | *OutBufCur++ = C; 154| | return *this; 155| | } 156| | 157| 0| raw_ostream &operator<<(signed char C) { 158| 0| if (OutBufCur >= OutBufEnd) 159| 0| return write(C); 160| 0| *OutBufCur++ = C; 161| 0| return *this; 162| 0| } 163| | 164| 0| raw_ostream &operator<<(StringRef Str) { 165| 0| // Inline fast path, particularly for strings with a known length. 166| 0| size_t Size = Str.size(); 167| 0| 168| 0| // Make sure we can use the fast path. 169| 0| if (Size > (size_t)(OutBufEnd - OutBufCur)) 170| 0| return write(Str.data(), Size); 171| 0| 172| 0| memcpy(OutBufCur, Str.data(), Size); 173| 0| OutBufCur += Size; 174| 0| return *this; 175| 0| } 176| | 177| 0| raw_ostream &operator<<(const char *Str) { 178| 0| // Inline fast path, particularly for constant strings where a sufficiently 179| 0| // smart compiler will simplify strlen. 180| 0| 181| 0| return this->operator<<(StringRef(Str)); 182| 0| } 183| | 184| | raw_ostream &operator<<(const std::string &Str) { 185| | // Avoid the fast path, it would only increase code size for a marginal win. 186| | return write(Str.data(), Str.length()); 187| | } 188| | 189| | raw_ostream &operator<<(const llvm::SmallVectorImpl &Str) { 190| | return write(Str.data(), Str.size()); 191| | } 192| | 193| | raw_ostream &operator<<(unsigned long N); 194| | raw_ostream &operator<<(long N); 195| | raw_ostream &operator<<(unsigned long long N); 196| | raw_ostream &operator<<(long long N); 197| | raw_ostream &operator<<(const void *P); 198| | raw_ostream &operator<<(unsigned int N) { 199| | return this->operator<<(static_cast(N)); 200| | } 201| | 202| | raw_ostream &operator<<(int N) { 203| | return this->operator<<(static_cast(N)); 204| | } 205| | 206| | raw_ostream &operator<<(double N); 207| | 208| | /// write_hex - Output \p N in hexadecimal, without any prefix or padding. 209| | raw_ostream &write_hex(unsigned long long N); 210| | 211| | /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and 212| | /// anything that doesn't satisfy std::isprint into an escape sequence. 213| | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); 214| | 215| | raw_ostream &write(unsigned char C); 216| | raw_ostream &write(const char *Ptr, size_t Size); 217| | 218| | // Formatted output, see the format() function in Support/Format.h. 219| | raw_ostream &operator<<(const format_object_base &Fmt); 220| | 221| | // Formatted output, see the leftJustify() function in Support/Format.h. 222| | raw_ostream &operator<<(const FormattedString &); 223| | 224| | // Formatted output, see the formatHex() function in Support/Format.h. 225| | raw_ostream &operator<<(const FormattedNumber &); 226| | 227| | /// indent - Insert 'NumSpaces' spaces. 228| | raw_ostream &indent(unsigned NumSpaces); 229| | 230| | 231| | /// Changes the foreground color of text that will be output from this point 232| | /// forward. 233| | /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to 234| | /// change only the bold attribute, and keep colors untouched 235| | /// @param Bold bold/brighter text, default false 236| | /// @param BG if true change the background, default: change foreground 237| | /// @returns itself so it can be used within << invocations 238| | virtual raw_ostream &changeColor(enum Colors Color, 239| | bool Bold = false, 240| | bool BG = false) { 241| | (void)Color; 242| | (void)Bold; 243| | (void)BG; 244| | return *this; 245| | } 246| | 247| | /// Resets the colors to terminal defaults. Call this when you are done 248| | /// outputting colored text, or before program exit. 249| | virtual raw_ostream &resetColor() { return *this; } 250| | 251| | /// Reverses the forground and background colors. 252| | virtual raw_ostream &reverseColor() { return *this; } 253| | 254| | /// This function determines if this stream is connected to a "tty" or 255| | /// "console" window. That is, the output would be displayed to the user 256| | /// rather than being put on a pipe or stored in a file. 257| | virtual bool is_displayed() const { return false; } 258| | 259| | /// This function determines if this stream is displayed and supports colors. 260| | virtual bool has_colors() const { return is_displayed(); } 261| | 262| | //===--------------------------------------------------------------------===// 263| | // Subclass Interface 264| | //===--------------------------------------------------------------------===// 265| | 266| |private: 267| | /// write_impl - The is the piece of the class that is implemented 268| | /// by subclasses. This writes the \p Size bytes starting at 269| | /// \p Ptr to the underlying stream. 270| | /// 271| | /// This function is guaranteed to only be called at a point at which it is 272| | /// safe for the subclass to install a new buffer via SetBuffer. 273| | /// 274| | /// \param Ptr The start of the data to be written. For buffered streams this 275| | /// is guaranteed to be the start of the buffer. 276| | /// 277| | /// \param Size The number of bytes to be written. 278| | /// 279| | /// \invariant { Size > 0 } 280| | virtual void write_impl(const char *Ptr, size_t Size) = 0; 281| | 282| | // An out of line virtual method to provide a home for the class vtable. 283| | virtual void handle(); 284| | 285| | /// current_pos - Return the current position within the stream, not 286| | /// counting the bytes currently in the buffer. 287| | virtual uint64_t current_pos() const = 0; 288| | 289| |protected: 290| | /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is 291| | /// intended for use only by subclasses which can arrange for the output to go 292| | /// directly into the desired output buffer, instead of being copied on each 293| | /// flush. 294| 0| void SetBuffer(char *BufferStart, size_t Size) { 295| 0| SetBufferAndMode(BufferStart, Size, ExternalBuffer); 296| 0| } 297| | 298| | /// preferred_buffer_size - Return an efficient buffer size for the 299| | /// underlying output mechanism. 300| | virtual size_t preferred_buffer_size() const; 301| | 302| | /// getBufferStart - Return the beginning of the current stream buffer, or 0 303| | /// if the stream is unbuffered. 304| 0| const char *getBufferStart() const { return OutBufStart; } 305| | 306| | //===--------------------------------------------------------------------===// 307| | // Private Interface 308| | //===--------------------------------------------------------------------===// 309| |private: 310| | /// SetBufferAndMode - Install the given buffer and mode. 311| | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); 312| | 313| | /// flush_nonempty - Flush the current buffer, which is known to be 314| | /// non-empty. This outputs the currently buffered data and resets 315| | /// the buffer to empty. 316| | void flush_nonempty(); 317| | 318| | /// copy_to_buffer - Copy data into the buffer. Size must not be 319| | /// greater than the number of unused bytes in the buffer. 320| | void copy_to_buffer(const char *Ptr, size_t Size); 321| |}; 322| | 323| |//===----------------------------------------------------------------------===// 324| |// File Output Streams 325| |//===----------------------------------------------------------------------===// 326| | 327| |/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. 328| |/// 329| |class raw_fd_ostream : public raw_ostream { 330| | int FD; 331| | bool ShouldClose; 332| | 333| | /// Error This flag is true if an error of any kind has been detected. 334| | /// 335| | bool Error; 336| | 337| | /// Controls whether the stream should attempt to use atomic writes, when 338| | /// possible. 339| | bool UseAtomicWrites; 340| | 341| | uint64_t pos; 342| | 343| | /// write_impl - See raw_ostream::write_impl. 344| | void write_impl(const char *Ptr, size_t Size) override; 345| | 346| | /// current_pos - Return the current position within the stream, not 347| | /// counting the bytes currently in the buffer. 348| | uint64_t current_pos() const override { return pos; } 349| | 350| | /// preferred_buffer_size - Determine an efficient buffer size. 351| | size_t preferred_buffer_size() const override; 352| | 353| | /// error_detected - Set the flag indicating that an output error has 354| | /// been encountered. 355| 0| void error_detected() { Error = true; } 356| | 357| |public: 358| | /// Open the specified file for writing. If an error occurs, information 359| | /// about the error is put into EC, and the stream should be immediately 360| | /// destroyed; 361| | /// \p Flags allows optional flags to control how the file will be opened. 362| | /// 363| | /// As a special case, if Filename is "-", then the stream will use 364| | /// STDOUT_FILENO instead of opening a file. Note that it will still consider 365| | /// itself to own the file descriptor. In particular, it will close the 366| | /// file descriptor when it is done (this is necessary to detect 367| | /// output errors). 368| | raw_fd_ostream(StringRef Filename, std::error_code &EC, 369| | sys::fs::OpenFlags Flags); 370| | 371| | /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 372| | /// ShouldClose is true, this closes the file when the stream is destroyed. 373| | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); 374| | 375| | ~raw_fd_ostream(); 376| | 377| | /// close - Manually flush the stream and close the file. 378| | /// Note that this does not call fsync. 379| | void close(); 380| | 381| | /// seek - Flushes the stream and repositions the underlying file descriptor 382| | /// position to the offset specified from the beginning of the file. 383| | uint64_t seek(uint64_t off); 384| | 385| | /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for 386| | /// individual output routines where possible. 387| | /// 388| | /// Note that because raw_ostream's are typically buffered, this flag is only 389| | /// sensible when used on unbuffered streams which will flush their output 390| | /// immediately. 391| 0| void SetUseAtomicWrites(bool Value) { 392| 0| UseAtomicWrites = Value; 393| 0| } 394| | 395| | raw_ostream &changeColor(enum Colors colors, bool bold=false, 396| | bool bg=false) override; 397| | raw_ostream &resetColor() override; 398| | 399| | raw_ostream &reverseColor() override; 400| | 401| | bool is_displayed() const override; 402| | 403| | bool has_colors() const override; 404| | 405| | /// has_error - Return the value of the flag in this raw_fd_ostream indicating 406| | /// whether an output error has been encountered. 407| | /// This doesn't implicitly flush any pending output. Also, it doesn't 408| | /// guarantee to detect all errors unless the stream has been closed. 409| | bool has_error() const { 410| | return Error; 411| | } 412| | 413| | /// clear_error - Set the flag read by has_error() to false. If the error 414| | /// flag is set at the time when this raw_ostream's destructor is called, 415| | /// report_fatal_error is called to report the error. Use clear_error() 416| | /// after handling the error to avoid this behavior. 417| | /// 418| | /// "Errors should never pass silently. 419| | /// Unless explicitly silenced." 420| | /// - from The Zen of Python, by Tim Peters 421| | /// 422| 0| void clear_error() { 423| 0| Error = false; 424| 0| } 425| |}; 426| | 427| |/// outs() - This returns a reference to a raw_ostream for standard output. 428| |/// Use it like: outs() << "foo" << "bar"; 429| |raw_ostream &outs(); 430| | 431| |/// errs() - This returns a reference to a raw_ostream for standard error. 432| |/// Use it like: errs() << "foo" << "bar"; 433| |raw_ostream &errs(); 434| | 435| |/// nulls() - This returns a reference to a raw_ostream which simply discards 436| |/// output. 437| |raw_ostream &nulls(); 438| | 439| |//===----------------------------------------------------------------------===// 440| |// Output Stream Adaptors 441| |//===----------------------------------------------------------------------===// 442| | 443| |/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a 444| |/// simple adaptor class. This class does not encounter output errors. 445| |class raw_string_ostream : public raw_ostream { 446| | std::string &OS; 447| | 448| | /// write_impl - See raw_ostream::write_impl. 449| | void write_impl(const char *Ptr, size_t Size) override; 450| | 451| | /// current_pos - Return the current position within the stream, not 452| | /// counting the bytes currently in the buffer. 453| | uint64_t current_pos() const override { return OS.size(); } 454| |public: 455| 0| explicit raw_string_ostream(std::string &O) : OS(O) {} 456| | ~raw_string_ostream(); 457| | 458| | /// str - Flushes the stream contents to the target string and returns 459| | /// the string's reference. 460| 0| std::string& str() { 461| 0| flush(); 462| 0| return OS; 463| 0| } 464| |}; 465| | 466| |/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or 467| |/// SmallString. This is a simple adaptor class. This class does not 468| |/// encounter output errors. 469| |class raw_svector_ostream : public raw_ostream { 470| | SmallVectorImpl &OS; 471| | 472| | /// write_impl - See raw_ostream::write_impl. 473| | void write_impl(const char *Ptr, size_t Size) override; 474| | 475| | /// current_pos - Return the current position within the stream, not 476| | /// counting the bytes currently in the buffer. 477| | uint64_t current_pos() const override; 478| |public: 479| | /// Construct a new raw_svector_ostream. 480| | /// 481| | /// \param O The vector to write to; this should generally have at least 128 482| | /// bytes free to avoid any extraneous memory overhead. 483| | explicit raw_svector_ostream(SmallVectorImpl &O); 484| | ~raw_svector_ostream(); 485| | 486| | /// resync - This is called when the SmallVector we're appending to is changed 487| | /// outside of the raw_svector_ostream's control. It is only safe to do this 488| | /// if the raw_svector_ostream has previously been flushed. 489| | void resync(); 490| | 491| | /// str - Flushes the stream contents to the target vector and return a 492| | /// StringRef for the vector contents. 493| | StringRef str(); 494| |}; 495| | 496| |/// raw_null_ostream - A raw_ostream that discards all output. 497| |class raw_null_ostream : public raw_ostream { 498| | /// write_impl - See raw_ostream::write_impl. 499| | void write_impl(const char *Ptr, size_t size) override; 500| | 501| | /// current_pos - Return the current position within the stream, not 502| | /// counting the bytes currently in the buffer. 503| | uint64_t current_pos() const override; 504| | 505| |public: 506| 0| explicit raw_null_ostream() {} 507| | ~raw_null_ostream(); 508| |}; 509| | 510| |} // end llvm namespace 511| | 512| |#endif <<<<<< EOF # path=llbuildCore.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/BinaryCoding.h: 1| |//===- BinaryCoding.h -------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_BINARYCODING_H 14| |#define LLBUILD_BASIC_BINARYCODING_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| |#include "llbuild/Basic/LLVM.h" 18| | 19| |#include "llvm/ADT/SmallVector.h" 20| |#include "llvm/ADT/StringRef.h" 21| | 22| |#include 23| |#include 24| | 25| |namespace llbuild { 26| |namespace basic { 27| | 28| |template 29| |struct BinaryCodingTraits { 30| | // static inline void encode(const T&, BinaryEncoder&); 31| | // static inline void decode(T&, BinaryDecoder&); 32| |}; 33| | 34| |/// A basic binary encoding utility. 35| |/// 36| |/// This encoder is design for small, relatively efficient, in-memory coding of 37| |/// objects. It is endian-neutral, and should be paired with \see BinaryDecoder 38| |/// for decoding. The specific encoding is not intended to be stable. 39| |/// 40| |/// The utility supports coding of user-defined types via specialization of the 41| |/// BinaryCodeableTraits type. 42| |class BinaryEncoder { 43| |private: 44| | // Copying is disabled. 45| | BinaryEncoder(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 46| | void operator=(const BinaryEncoder&) LLBUILD_DELETED_FUNCTION; 47| | 48| | /// The encoded data. 49| | // 50| | // FIXME: Parameterize this size? 51| | llvm::SmallVector encdata; 52| | 53| |public: 54| | /// Construct a new binary encoder. 55| 0| BinaryEncoder() {} 56| | 57| | /// Encode a value to the stream. 58| 0| void write(bool value) { 59| 0| encdata.push_back(uint8_t(value)); 60| 0| } 61| | 62| | /// Encode a value to the stream. 63| 0| void write(uint8_t value) { 64| 0| encdata.push_back(value); 65| 0| } 66| | 67| | /// Encode a value to the stream. 68| 0| void write(uint16_t value) { 69| 0| write(uint8_t(value >> 0)); 70| 0| write(uint8_t(value >> 8)); 71| 0| } 72| | 73| | /// Encode a value to the stream. 74| 0| void write(uint32_t value) { 75| 0| write(uint16_t(value >> 0)); 76| 0| write(uint16_t(value >> 16)); 77| 0| } 78| | 79| | /// Encode a value to the stream. 80| 0| void write(uint64_t value) { 81| 0| write(uint32_t(value >> 0)); 82| 0| write(uint32_t(value >> 32)); 83| 0| } 84| | 85| | /// Encode a value to the stream. 86| | /// 87| | /// We do not support encoding values larger than 4GB. 88| 0| void write(const std::string& value) { 89| 0| uint32_t size = uint32_t(value.size()); 90| 0| assert(size == value.size()); 91| 0| write(size); 92| 0| writeBytes(StringRef(value)); 93| 0| } 94| | 95| | /// Encode a sequence of bytes to the stream. 96| 0| void writeBytes(StringRef bytes) { 97| 0| encdata.insert(encdata.end(), bytes.begin(), bytes.end()); 98| 0| } 99| | 100| | /// Encode a value to the stream. 101| | template 102| | void write(const T& value) { 103| | BinaryCodingTraits::encode(value, *this); 104| | } 105| | 106| | /// Get the encoded binary data. 107| | std::vector contents() { 108| | return std::vector(encdata.begin(), encdata.end()); 109| | } 110| | 111| | /// Get the encoded binary data (in place) 112| 0| const uint8_t* data() const { 113| 0| return encdata.data(); 114| 0| } 115| | 116| | /// Get the size of the encoded binary data 117| 0| const size_t size() const { 118| 0| return encdata.size(); 119| 0| } 120| |}; 121| | 122| |/// A basic binary decoding utility. 123| |/// 124| |/// \see BinaryEncoder. 125| |class BinaryDecoder { 126| |private: 127| | // Copying is disabled. 128| | BinaryDecoder(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 129| | void operator=(const BinaryDecoder&) LLBUILD_DELETED_FUNCTION; 130| | 131| | /// The data being decoded. 132| | StringRef data; 133| | 134| | /// The current position in the stream. 135| | uint64_t pos = 0; 136| | 137| 0| uint8_t read8() { return data[pos++]; } 138| 0| uint16_t read16() { 139| 0| uint16_t result = read8(); 140| 0| result |= uint16_t(read8()) << 8; 141| 0| return result; 142| 0| } 143| 0| uint32_t read32() { 144| 0| uint32_t result = read16(); 145| 0| result |= uint32_t(read16()) << 16; 146| 0| return result; 147| 0| } 148| 0| uint64_t read64() { 149| 0| uint64_t result = read32(); 150| 0| result |= uint64_t(read32()) << 32; 151| 0| return result; 152| 0| } 153| | 154| |public: 155| | /// Construct a binary decoder. 156| 0| BinaryDecoder(StringRef data) : data(data) {} 157| | 158| | /// Construct a binary decoder. 159| | /// 160| | /// NOTE: The input data is supplied by reference, and its lifetime must 161| | /// exceed that of the decoder. 162| | BinaryDecoder(const std::vector& data) : BinaryDecoder( 163| 0| StringRef(reinterpret_cast(data.data()), data.size())) {} 164| | 165| | /// Check if the decoder is at the end of the stream. 166| | bool isEmpty() const { 167| | return pos == data.size(); 168| | } 169| | 170| | /// Decode a value from the stream. 171| 0| void read(bool& value) { value = read8() != 0; } 172| | 173| | /// Decode a value from the stream. 174| 0| void read(uint8_t& value) { value = read8(); } 175| | 176| | /// Decode a value from the stream. 177| 0| void read(uint16_t& value) { value = read16(); } 178| | 179| | /// Decode a value from the stream. 180| 0| void read(uint32_t& value) { value = read32(); } 181| | 182| | /// Decode a value from the stream. 183| 0| void read(uint64_t& value) { value = read64(); } 184| | 185| | /// Decode a value from the stream. 186| 0| void read(std::string& value) { 187| 0| uint32_t size; 188| 0| read(size); 189| 0| StringRef contents; 190| 0| readBytes(size, contents); 191| 0| value = contents.str(); 192| 0| } 193| | 194| | /// Decode a byte string from the stream. 195| | /// 196| | /// NOTE: The return value points into the decode stream, and must be copied 197| | /// by clients if it is to last longer than the lifetime of the decoder. 198| | void readBytes(size_t count, StringRef& value) { 199| | assert(pos + count <= data.size()); 200| | value = StringRef(data.begin() + pos, count); 201| | pos += count; 202| | } 203| | 204| | /// Decode a value from the stream. 205| | template 206| | void read(T& value) { 207| | BinaryCodingTraits::decode(value, *this); 208| | } 209| | 210| | /// Finish decoding and clean up. 211| | void finish() { 212| | assert(isEmpty()); 213| | } 214| |}; 215| | 216| |template<> 217| |struct BinaryCodingTraits { 218| 0| static inline void encode(const StringRef& value, BinaryEncoder& coder) { 219| 0| coder.writeBytes(value); 220| 0| } 221| |}; 222| | 223| |} 224| |} 225| | 226| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/PlatformUtility.h: 1| |//===- PlatformUtility.h ----------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| |// 13| |// This file implements small platform compatability wrapper functions for 14| |// common functions. 15| |// 16| |//===----------------------------------------------------------------------===// 17| | 18| |#ifndef LLBUILD_BASIC_PLATFORMUTILITY_H 19| |#define LLBUILD_BASIC_PLATFORMUTILITY_H 20| | 21| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 22| |#include 23| |#include 24| |#include 25| |#if !defined(_WIN32) 26| |#include 27| |#endif 28| | 29| |namespace llbuild { 30| |namespace basic { 31| |namespace sys { 32| | 33| |bool chdir(const char *fileName); 34| |int close(int fileHandle); 35| |bool mkdir(const char *fileName); 36| |int pclose(FILE *stream); 37| |int pipe(int ptHandles[2]); 38| |FILE *popen(const char *command, const char *mode); 39| |int read(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 40| |int rmdir(const char *path); 41| |int symlink(const char *source, const char *target); 42| |int unlink(const char *fileName); 43| |int write(int fileHandle, void *destinationBuffer, unsigned int maxCharCount); 44| |std::string strerror(int error); 45| |char *strsep(char **stringp, const char *delim); 46| |// Create a directory in the temporary folder which doesn't exist and return 47| |// it's path. 48| |std::string makeTmpDir(); 49| | 50| |// Return a string containing all valid path separators on the current platform 51| |std::string getPathSeparators(); 52| | 53| |/// Sets the max open file limit to min(max(soft_limit, limit), hard_limit), 54| |/// where soft_limit and hard_limit are gathered from the system. 55| |/// 56| |/// Returns: 0 on success, -1 on failure (check errno). 57| |int raiseOpenFileLimit(llbuild_rlim_t limit = 2048); 58| | 59| |enum MATCH_RESULT { MATCH, NO_MATCH, MATCH_ERROR }; 60| |// Test if a path or filename matches a wildcard pattern 61| |// 62| |// Returns MATCH if a match is detected, NO_MATCH if there is no match, and 63| |// MATCH_ERROR on error. Windows callers may use GetLastError to get additional 64| |// error information. 65| |MATCH_RESULT filenameMatch(const std::string& pattern, const std::string& filename); 66| | 67| |void sleep(int seconds); 68| |template struct FileDescriptorTraits; 69| | 70| |#if defined(_WIN32) 71| |template <> struct FileDescriptorTraits { 72| | static void Close(HANDLE hFile) { CloseHandle(hFile); } 73| | static int Read(HANDLE hFile, void *destinationBuffer, 74| | unsigned int maxCharCount) { 75| | DWORD numBytes; 76| | if (!ReadFile(hFile, destinationBuffer, maxCharCount, &numBytes, nullptr)) { 77| | return -1; 78| | } 79| | return numBytes; 80| | } 81| |}; 82| |#endif 83| |template <> struct FileDescriptorTraits { 84| 0| static void Close(int fd) { close(fd); } 85| | static int Read(int hFile, void *destinationBuffer, 86| | unsigned int maxCharCount) { 87| | return read(hFile, destinationBuffer, maxCharCount); 88| | } 89| |}; 90| |} 91| |} 92| |} 93| | 94| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Basic/include/llbuild/Basic/Tracing.h: 1| |//===- Tracing.h ------------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_BASIC_TRACING_H 14| |#define LLBUILD_BASIC_TRACING_H 15| | 16| |#include "llbuild/Basic/CrossPlatformCompatibility.h" 17| |#include "llvm/ADT/StringRef.h" 18| | 19| |// os_signpost is included in mac OS 10.14, if that header is not available, we don't trace at all. 20| |#if __has_include() 21| |#include 22| | 23| |/// Returns the singleton instance of os_log_t to use with os_log and os_signpost API. 24| |API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0)) 25| 0|static os_log_t getLog() { 26| 0| static os_log_t generalLog; 27| 0| static dispatch_once_t onceToken; 28| 0| dispatch_once(&onceToken, ^{ 29| 0| generalLog = os_log_create("org.swift.llbuild", "tracing"); 30| 0| }); 31| 0| return generalLog; 32| 0|} 33| | 34| |/// Returns a singleton id to use for all signpost calls during the lifetime of the program. 35| |API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) 36| 0|static os_signpost_id_t signpost_id() { 37| 0| static os_signpost_id_t signpost_id; 38| 0| static dispatch_once_t onceToken; 39| 0| dispatch_once(&onceToken, ^{ 40| 0| signpost_id = os_signpost_id_generate(getLog()); 41| 0| }); 42| 0| return signpost_id; 43| 0|} 44| | 45| |/// Begin an interval if tracing is enabled. 46| 0|#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { \ 47| 0|if (__builtin_available(macOS 10.14, *)) os_signpost_interval_begin(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 48| 0|} 49| | 50| |/// End an interval if tracing is enabled. 51| 0|#define LLBUILD_TRACE_INTERVAL_END(name, ...) { \ 52| 0|if (__builtin_available(macOS 10.14, *)) os_signpost_interval_end(getLog(), signpost_id(), name, ##__VA_ARGS__); \ 53| 0|} 54| | 55| |/// Trace an event without duration at a point in time. 56| |#define LLBUILD_TRACE_POINT(name, ...) { \ 57| |if (__builtin_available(macOS 10.12, *)) os_log(getLog(), ##__VA_ARGS__); \ 58| |} 59| | 60| |#else 61| | 62| |// Define dummy definitions to do nothing 63| |#define LLBUILD_TRACE_POINT(name, ...) { (void)(name); } 64| |#define LLBUILD_TRACE_INTERVAL_BEGIN(name, ...) { (void)(name); } 65| |#define LLBUILD_TRACE_INTERVAL_END(name, ...) { (void)(name); } 66| |#define LLBUILD_TRACING_SET_ENABLED(on) { (void)on; } 67| | 68| |#endif // __has_include() 69| | 70| |namespace llbuild { 71| |extern bool TracingEnabled; 72| | 73| |struct TracingExecutionQueueJob { 74| | TracingExecutionQueueJob(int laneNumber, llvm::StringRef commandName) { 75| | if (!TracingEnabled) return; 76| | LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_job", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 77| | } 78| | 79| | ~TracingExecutionQueueJob() { 80| | if (!TracingEnabled) return; 81| | LLBUILD_TRACE_INTERVAL_END("execution_queue_job"); 82| | } 83| |}; 84| | 85| | 86| |inline void TracingExecutionQueueSubprocessStart(uint32_t laneNumber, 87| | llvm::StringRef commandName) { 88| | if (!TracingEnabled) return; 89| | LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 90| |} 91| | 92| |inline void TracingExecutionQueueSubprocessResult(uint32_t laneNumber, 93| | llbuild_pid_t pid, 94| | uint64_t utime, 95| | uint64_t stime, long maxrss) { 96| | if (!TracingEnabled) return; 97| | LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 98| |} 99| | 100| | 101| |struct TracingExecutionQueueSubprocess { 102| | TracingExecutionQueueSubprocess(uint32_t laneNumber, 103| | llvm::StringRef commandName) 104| 0| : laneNumber(laneNumber), pid(0), utime(0), stime(0), maxrss(0) { 105| 0| if (!TracingEnabled) return; 106| 0| LLBUILD_TRACE_INTERVAL_BEGIN("execution_queue_subprocess", "lane:%d;command:%s", laneNumber, commandName.str().c_str()); 107| 0| } 108| | 109| | TracingExecutionQueueSubprocess(const TracingExecutionQueueSubprocess&) = delete; 110| | TracingExecutionQueueSubprocess(TracingExecutionQueueSubprocess&& t) 111| 0| : laneNumber(t.laneNumber), pid(t.pid), utime(t.utime), stime(t.stime), maxrss(t.maxrss) { 112| 0| t.active = false; 113| 0| } 114| | 115| 0| void update(llbuild_pid_t pid, uint64_t utime, uint64_t stime, long maxrss) { 116| 0| this->pid = pid; 117| 0| this->utime = utime; 118| 0| this->stime = stime; 119| 0| this->maxrss = maxrss; 120| 0| } 121| | 122| 0| ~TracingExecutionQueueSubprocess() { 123| 0| if (!TracingEnabled || !active) return; 124| 0| LLBUILD_TRACE_INTERVAL_END("execution_queue_subprocess", "lane:%d;pid:%d;utime:%llu;stime:%llu;maxrss:%ld", laneNumber, pid, utime, stime, maxrss); 125| 0| } 126| | 127| |private: 128| | bool active = true; 129| | uint32_t laneNumber; 130| | llbuild_pid_t pid; 131| | uint64_t utime; 132| | uint64_t stime; 133| | long maxrss; 134| |}; 135| | 136| |// Engine Task Callbacks 137| |enum class EngineTaskCallbackKind { 138| | Start = 0, 139| | ProvidePriorValue, 140| | ProvideValue, 141| | InputsAvailable, 142| |}; 143| | 144| |struct TracingEngineTaskCallback { 145| | TracingEngineTaskCallback(EngineTaskCallbackKind kind, uint64_t key) 146| 0| : key(key) { 147| 0| if (!TracingEnabled) return; 148| 0| LLBUILD_TRACE_INTERVAL_BEGIN("engine_task_callback", "key:%llu;kind:%d", key, uint32_t(kind)); 149| 0| } 150| | 151| 0| ~TracingEngineTaskCallback() { 152| 0| if (!TracingEnabled) return; 153| 0| LLBUILD_TRACE_INTERVAL_END("engine_task_callback", "key:%llu", key); 154| 0| key = 0; 155| 0| } 156| |private: 157| | uint64_t key; 158| |}; 159| | 160| |// Engine Queue Processing 161| |enum class EngineQueueItemKind { 162| | RuleToScan = 0, 163| | InputRequest, 164| | FinishedInputRequest, 165| | ReadyTask, 166| | FinishedTask, 167| | Waiting, 168| | FindingCycle, 169| | BreakingCycle, 170| |}; 171| | 172| |struct TracingEngineQueueItemEvent { 173| | TracingEngineQueueItemEvent(EngineQueueItemKind kind, char const *key) 174| 0| : key(key) { 175| 0| if (!TracingEnabled) return; 176| 0| LLBUILD_TRACE_INTERVAL_BEGIN("engine_queue_item_event", "key:%s;kind:%d", key, kind); 177| 0| } 178| | 179| 0| ~TracingEngineQueueItemEvent() { 180| 0| if (!TracingEnabled) return; 181| 0| LLBUILD_TRACE_INTERVAL_END("engine_queue_item_event", "key:%s", key) 182| 0| key = nullptr; 183| 0| } 184| |private: 185| | char const *key; 186| |}; 187| | 188| |inline void TracingExecutionQueueDepth(uint64_t depth) { 189| | if (!TracingEnabled) return; 190| | LLBUILD_TRACE_POINT("execution_queue_depth", "depth:%llu", depth); 191| |} 192| | 193| |} 194| | 195| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/BuildDB.cpp: 1| |//===-- BuildDB.cpp -------------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Core/BuildDB.h" 14| | 15| |using namespace llbuild; 16| |using namespace llbuild::core; 17| | 18| 0|BuildDBDelegate::~BuildDBDelegate() { } 19| | 20| 0|BuildDB::~BuildDB() { } /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/BuildEngine.cpp: 1| |//===-- BuildEngine.cpp ---------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Core/BuildEngine.h" 14| | 15| |#include "llbuild/Basic/Tracing.h" 16| |#include "llbuild/Core/BuildDB.h" 17| | 18| |#include "llvm/ADT/STLExtras.h" 19| |#include "llvm/ADT/StringMap.h" 20| | 21| |#include "BuildEngineTrace.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| |#include 31| |#include 32| |#include 33| |#include 34| |#include 35| | 36| |using namespace llbuild; 37| |using namespace llbuild::core; 38| | 39| 0|Task::~Task() {} 40| | 41| 0|BuildEngineDelegate::~BuildEngineDelegate() {} 42| | 43| |bool BuildEngineDelegate::shouldResolveCycle(const std::vector& items, 44| | Rule* candidateRule, 45| 0| Rule::CycleAction action) { 46| 0| return false; 47| 0|} 48| | 49| |#pragma mark - BuildEngine implementation 50| | 51| |namespace { 52| | 53| |class BuildEngineImpl : public BuildDBDelegate { 54| | struct RuleInfo; 55| | struct TaskInfo; 56| | 57| | /// Reserved input IDs. 58| | enum: uintptr_t { 59| | kMustFollowInputID = ~(uintptr_t)0 60| | }; 61| | 62| | BuildEngine& buildEngine; 63| | 64| | BuildEngineDelegate& delegate; 65| | 66| | /// The key table, used when there is no database. 67| | llvm::StringMap keyTable; 68| | 69| | /// The mutex that protects the key table. 70| | std::mutex keyTableMutex; 71| | 72| | /// The build database, if attached. 73| | std::unique_ptr db; 74| | 75| | /// The tracing implementation, if enabled. 76| | std::unique_ptr trace; 77| | 78| | /// The current build iteration, used to sequentially timestamp build results. 79| | uint64_t currentTimestamp = 0; 80| | 81| | /// Whether the build should be cancelled. 82| | std::atomic buildCancelled{ false }; 83| | 84| | /// The queue of input requests to process. 85| | struct TaskInputRequest { 86| | /// The task making the request. 87| | TaskInfo* taskInfo; 88| | /// The rule for the input which was requested. 89| | RuleInfo* inputRuleInfo; 90| | /// The task provided input ID, for its own use in identifying the input. 91| | uintptr_t inputID; 92| | /// Force the use of a prior value 93| | bool forcePriorValue = false; 94| | }; 95| | std::vector inputRequests; 96| | std::vector finishedInputRequests; 97| | 98| | /// The queue of rules being scanned. 99| | struct RuleScanRequest { 100| | /// The rule making the request. 101| | RuleInfo* ruleInfo; 102| | /// The input index being considered. 103| | unsigned inputIndex; 104| | /// The input being considered, if already looked up. 105| | /// 106| | /// This is used when a scan request is deferred waiting on its input to be 107| | /// scanned, to avoid a redundant hash lookup. 108| | struct RuleInfo* inputRuleInfo; 109| | }; 110| | std::vector ruleInfosToScan; 111| | 112| | struct RuleScanRecord { 113| | /// The vector of paused input requests, waiting for the dependency scan on 114| | /// this rule to complete. 115| | std::vector pausedInputRequests; 116| | /// The vector of deferred scan requests, for rules which are waiting on 117| | /// this one to be scanned. 118| | std::vector deferredScanRequests; 119| | }; 120| | 121| | /// Wrapper for information specific to a single rule. 122| | struct RuleInfo { 123| | enum class StateKind { 124| | /// The initial rule state. 125| | Incomplete = 0, 126| | 127| | /// The rule is being scanned to determine if it needs to run. 128| | IsScanning, 129| | 130| | /// The rule needs to run, but has not yet been started. 131| | NeedsToRun, 132| | 133| | /// The rule does not need to run, but has not yet been marked as 134| | /// complete. 135| | DoesNotNeedToRun, 136| | 137| | /// The rule is in progress, but is waiting on additional inputs. 138| | InProgressWaiting, 139| | 140| | /// The rule is in progress, and is computing its result. 141| | InProgressComputing, 142| | 143| | /// The rule is complete, with an available result. 144| | /// 145| | /// Note that as an optimization, when the build timestamp is incremented 146| | /// we do not immediately reset the state, rather we do it lazily as part 147| | /// of \see demandRule() in conjunction with the Result::builtAt field. 148| | Complete 149| | }; 150| | 151| 0| RuleInfo(KeyID keyID, Rule&& rule) : keyID(keyID), rule(rule) {} 152| | 153| | /// The ID for the rule key. 154| | KeyID keyID; 155| | 156| | /// The rule this information describes. 157| | Rule rule; 158| | 159| | /// The state dependent record for in-progress information. 160| | union { 161| | RuleScanRecord* pendingScanRecord; 162| | TaskInfo* pendingTaskInfo; 163| | } inProgressInfo = { nullptr }; 164| | /// The most recent rule result. 165| | Result result = {}; 166| | /// The current state of the rule. 167| | StateKind state = StateKind::Incomplete; 168| | bool wasForced = false; 169| | 170| | public: 171| 0| bool isScanning() const { 172| 0| return state == StateKind::IsScanning; 173| 0| } 174| | 175| 0| bool isScanned(const BuildEngineImpl* engine) const { 176| 0| // If the rule is marked as complete, just check that state. 177| 0| if (state == StateKind::Complete) 178| 0| return isComplete(engine); 179| 0| 180| 0| // Otherwise, the rule is scanned if it has passed the scanning state. 181| 0| return int(state) > int(StateKind::IsScanning); 182| 0| } 183| | 184| 0| bool isInProgressWaiting() const { 185| 0| return state == StateKind::InProgressWaiting; 186| 0| } 187| | 188| 0| bool isInProgressComputing() const { 189| 0| return state == StateKind::InProgressComputing; 190| 0| } 191| | 192| 0| bool isInProgress() const { 193| 0| return isInProgressWaiting() || isInProgressComputing(); 194| 0| } 195| | 196| 0| bool isComplete(const BuildEngineImpl* engine) const { 197| 0| return state == StateKind::Complete && 198| 0| result.builtAt == engine->getCurrentTimestamp(); 199| 0| } 200| | 201| 0| void setComplete(const BuildEngineImpl* engine) { 202| 0| state = StateKind::Complete; 203| 0| // Note we do not push this change to the database. This is essentially a 204| 0| // mark we maintain to allow a lazy transition to Incomplete when the 205| 0| // timestamp is incremented. 206| 0| // 207| 0| // FIXME: This is a bit dubious, and wouldn't work anymore if we moved the 208| 0| // Result to being totally managed by the database. However, it is just a 209| 0| // matter of keeping an extra timestamp outside the Result to fix. 210| 0| result.builtAt = engine->getCurrentTimestamp(); 211| 0| } 212| | 213| 0| void setCancelled() { 214| 0| // If we have to cancel a task, it becomes incomplete. We do not need to 215| 0| // sync this to the database, the database won't see an updated record and 216| 0| // can continue to maintain the previous view of state -- however, we must 217| 0| // mark the internal representation as incomplete because the result is no 218| 0| // longer valid. 219| 0| state = StateKind::Incomplete; 220| 0| } 221| | 222| 0| RuleScanRecord* getPendingScanRecord() { 223| 0| assert(isScanning()); 224| 0| return inProgressInfo.pendingScanRecord; 225| 0| } 226| 0| const RuleScanRecord* getPendingScanRecord() const { 227| 0| assert(isScanning()); 228| 0| return inProgressInfo.pendingScanRecord; 229| 0| } 230| 0| void setPendingScanRecord(RuleScanRecord* value) { 231| 0| inProgressInfo.pendingScanRecord = value; 232| 0| } 233| | 234| 0| TaskInfo* getPendingTaskInfo() { 235| 0| assert(isInProgress()); 236| 0| return inProgressInfo.pendingTaskInfo; 237| 0| } 238| 0| const TaskInfo* getPendingTaskInfo() const { 239| 0| assert(isInProgress()); 240| 0| return inProgressInfo.pendingTaskInfo; 241| 0| } 242| 0| void setPendingTaskInfo(TaskInfo* value) { 243| 0| assert(isInProgress()); 244| 0| inProgressInfo.pendingTaskInfo = value; 245| 0| } 246| | }; 247| | 248| | // The map of registered rules. 249| | // 250| | // NOTE: We currently rely on the unordered_map behavior that ensures that 251| | // references to elements are not invalidated by insertion. We will need to 252| | // move to an alternate allocation strategy if we switch to DenseMap style 253| | // table. This is probably a good idea in any case, because we would benefit 254| | // from pool allocating RuleInfo instances. 255| | std::unordered_map ruleInfos; 256| | 257| | /// Information tracked for executing tasks. 258| | // 259| | // FIXME: Keeping this in a side table is very inefficient, we always have to 260| | // look it up. It might make much more sense to require the Task to have a 261| | // private field available for our use to store this. 262| | struct TaskInfo { 263| 0| TaskInfo(Task* task) : task(task) {} 264| | 265| | std::unique_ptr task; 266| | /// The list of input requests that are waiting on this task, which will be 267| | /// fulfilled once the task is complete. 268| | // 269| | // FIXME: Note that this structure is redundant here, as 270| | // (TaskInputRequest::InputTaskInfo == this) for all items, but we reuse the 271| | // existing structure for simplicity. 272| | std::vector requestedBy; 273| | /// The vector of deferred scan requests, for rules which are waiting on 274| | /// this one to be scanned. 275| | // 276| | // FIXME: As above, this structure has redundancy in it. 277| | std::vector deferredScanRequests; 278| | /// The rule that this task is computing. 279| | RuleInfo* forRuleInfo = nullptr; 280| | /// The number of outstanding inputs that this task is waiting on to be 281| | /// provided. 282| | unsigned waitCount = 0; 283| | /// The list of discovered dependencies found during execution of the task. 284| | std::vector discoveredDependencies; 285| | 286| |#ifndef NDEBUG 287| 0| void dump() const { 288| 0| fprintf(stderr, 289| 0| "\n", 290| 0| this, task.get(), 291| 0| forRuleInfo ? forRuleInfo->rule.key.c_str() : "(null)", 292| 0| waitCount); 293| 0| for (const auto& request: requestedBy) { 294| 0| fprintf(stderr, " requested by: %s\n", 295| 0| request.taskInfo->forRuleInfo->rule.key.c_str()); 296| 0| } 297| 0| } 298| |#endif 299| | }; 300| | 301| | /// The tracked information for executing tasks. 302| | /// 303| | /// Access to this must be protected via \see taskInfosMutex. 304| | std::unordered_map taskInfos; 305| | 306| | /// The mutex that protects the task info map. 307| | std::mutex taskInfosMutex; 308| | 309| | /// The queue of tasks ready to be finalized. 310| | std::vector readyTaskInfos; 311| | 312| | /// The number of tasks which have been readied but not yet finished. 313| | unsigned numOutstandingUnfinishedTasks = 0; 314| | 315| | /// The queue of tasks which are complete, accesses to this member variable 316| | /// must be protected via \see finishedTaskInfosMutex. 317| | std::vector finishedTaskInfos; 318| | 319| | /// The mutex that protects finished task infos. 320| | std::mutex finishedTaskInfosMutex; 321| | 322| | /// This variable is used to signal when additional work is added to the 323| | /// FinishedTaskInfos queue, which the engine may need to wait on. 324| | std::condition_variable finishedTaskInfosCondition; 325| | 326| | 327| | 328| |private: 329| | /// @name RuleScanRecord Allocation 330| | /// 331| | /// The execution of a single build may use a substantial amount of 332| | /// additional memory in recording the bookkeeping information used to do 333| | /// dependency scanning. While we could keep this information adjacent to 334| | /// every \see RuleInfo, that adds up to a substantial chunk of memory which 335| | /// is wasted except during dependency scanning. 336| | /// 337| | /// Instead, we allocate \see RuleScanRecord objects for each rule only as it 338| | /// is being scanned, and use a custom allocator for the objects to try and 339| | /// make this efficient. Currently we use a bounded free-list backed by a slab 340| | /// allocator. 341| | /// 342| | /// Note that this still has a fairly large impact on dependency scanning 343| | /// performance, in the worst case a deep linear graph takes ~50% longer to 344| | /// scan, but it also provides an overall 15-20% memory savings on resident 345| | /// engine size. 346| | /// 347| | /// @{ 348| | 349| | // FIXME: This should be abstracted into a helper class. 350| | 351| | /// A free-list of RuleScanRecord objects. 352| | std::vector freeRuleScanRecords; 353| | /// The maximum number of free-list items to keep. 354| | const size_t maximumFreeRuleScanRecords = 8096; 355| | /// The list of blocks (of size \see NumScanRecordsPerBlock) we have 356| | /// allocated. 357| | std::vector ruleScanRecordBlocks; 358| | /// The number of records to allocate per block. 359| | const size_t numScanRecordsPerBlock = 4096; 360| | /// The buffer positions of the current block. 361| | RuleScanRecord* currentBlockPos = nullptr, * currentBlockEnd = nullptr; 362| | 363| 0| RuleScanRecord* newRuleScanRecord() { 364| 0| // If we have an item on the free list, return it. 365| 0| if (!freeRuleScanRecords.empty()) { 366| 0| auto result = freeRuleScanRecords.back(); 367| 0| freeRuleScanRecords.pop_back(); 368| 0| return result; 369| 0| } 370| 0| 371| 0| // If we are at the end of a block, allocate a new one. 372| 0| if (currentBlockPos == currentBlockEnd) { 373| 0| currentBlockPos = new RuleScanRecord[numScanRecordsPerBlock]; 374| 0| ruleScanRecordBlocks.push_back(currentBlockPos); 375| 0| currentBlockEnd = currentBlockPos + numScanRecordsPerBlock; 376| 0| } 377| 0| return currentBlockPos++; 378| 0| } 379| | 380| 0| void freeRuleScanRecord(RuleScanRecord* scanRecord) { 381| 0| if (freeRuleScanRecords.size() < maximumFreeRuleScanRecords) { 382| 0| scanRecord->pausedInputRequests.clear(); 383| 0| scanRecord->deferredScanRequests.clear(); 384| 0| freeRuleScanRecords.push_back(scanRecord); 385| 0| } 386| 0| } 387| | 388| | /// @} 389| | 390| | /// @name Build Execution 391| | /// @{ 392| | 393| | /// Request the scanning of the given rule to determine if it needs to run in 394| | /// the current environment. 395| | /// 396| | /// \returns True if the rule is already scanned, otherwise the rule will be 397| | /// enqueued for processing. 398| 0| bool scanRule(RuleInfo& ruleInfo) { 399| 0| // If the rule is already scanned, we are done. 400| 0| if (ruleInfo.isScanned(this)) 401| 0| return true; 402| 0| 403| 0| // If the rule is being scanned, we don't need to do anything. 404| 0| if (ruleInfo.isScanning()) 405| 0| return false; 406| 0| 407| 0| // Otherwise, start scanning the rule. 408| 0| if (trace) 409| 0| trace->checkingRuleNeedsToRun(&ruleInfo.rule); 410| 0| 411| 0| // Report the status change. 412| 0| if (ruleInfo.rule.updateStatus) 413| 0| ruleInfo.rule.updateStatus(buildEngine, Rule::StatusKind::IsScanning); 414| 0| 415| 0| ruleInfo.wasForced = false; 416| 0| 417| 0| // If the rule has never been run, it needs to run. 418| 0| if (ruleInfo.result.builtAt == 0) { 419| 0| if (trace) 420| 0| trace->ruleNeedsToRunBecauseNeverBuilt(&ruleInfo.rule); 421| 0| ruleInfo.state = RuleInfo::StateKind::NeedsToRun; 422| 0| return true; 423| 0| } 424| 0| 425| 0| // If the rule indicates its computed value is out of date, it needs to run. 426| 0| // 427| 0| // FIXME: We should probably try and move this so that it can be done by 428| 0| // clients in the background, either by us backgrounding it, or by using a 429| 0| // completion model as we do for inputs. 430| 0| if (ruleInfo.rule.isResultValid && 431| 0| !ruleInfo.rule.isResultValid(buildEngine, ruleInfo.rule, 432| 0| ruleInfo.result.value)) { 433| 0| if (trace) 434| 0| trace->ruleNeedsToRunBecauseInvalidValue(&ruleInfo.rule); 435| 0| ruleInfo.state = RuleInfo::StateKind::NeedsToRun; 436| 0| return true; 437| 0| } 438| 0| 439| 0| // If the rule has no dependencies, then it is ready to run. 440| 0| if (ruleInfo.result.dependencies.empty()) { 441| 0| if (trace) 442| 0| trace->ruleDoesNotNeedToRun(&ruleInfo.rule); 443| 0| ruleInfo.state = RuleInfo::StateKind::DoesNotNeedToRun; 444| 0| return true; 445| 0| } 446| 0| 447| 0| // Otherwise, we need to do a recursive scan of the inputs so enqueue this 448| 0| // rule for scanning. 449| 0| // 450| 0| // We could also take an approach where we enqueue each of the individual 451| 0| // inputs, but in my experiments with that approach it has always performed 452| 0| // significantly worse. 453| 0| if (trace) 454| 0| trace->ruleScheduledForScanning(&ruleInfo.rule); 455| 0| ruleInfo.state = RuleInfo::StateKind::IsScanning; 456| 0| ruleInfo.setPendingScanRecord(newRuleScanRecord()); 457| 0| ruleInfosToScan.push_back({ &ruleInfo, /*InputIndex=*/0, nullptr }); 458| 0| 459| 0| return false; 460| 0| } 461| | 462| | /// Request the construction of the key specified by the given rule. 463| | /// 464| | /// \returns True if the rule is already available, otherwise the rule will be 465| | /// enqueued for processing. 466| 0| bool demandRule(RuleInfo& ruleInfo) { 467| 0| // The rule must have already been scanned. 468| 0| assert(ruleInfo.isScanned(this)); 469| 0| 470| 0| // If the rule is complete, we are done. 471| 0| if (ruleInfo.isComplete(this)) 472| 0| return true; 473| 0| 474| 0| // If the rule is in progress, we don't need to do anything. 475| 0| if (ruleInfo.isInProgress()) 476| 0| return false; 477| 0| 478| 0| // If the rule isn't marked complete, but doesn't need to actually run, then 479| 0| // just update it. 480| 0| if (ruleInfo.state == RuleInfo::StateKind::DoesNotNeedToRun) { 481| 0| ruleInfo.setComplete(this); 482| 0| 483| 0| // Report the status change. 484| 0| if (ruleInfo.rule.updateStatus) 485| 0| ruleInfo.rule.updateStatus(buildEngine, Rule::StatusKind::IsUpToDate); 486| 0| 487| 0| return true; 488| 0| } 489| 0| 490| 0| // Otherwise, we actually need to initiate the processing of this rule. 491| 0| assert(ruleInfo.state == RuleInfo::StateKind::NeedsToRun); 492| 0| 493| 0| // Create the task for this rule. 494| 0| Task* task = ruleInfo.rule.action(buildEngine); 495| 0| assert(task && "rule action returned null task"); 496| 0| 497| 0| // Find the task info for this task. 498| 0| auto taskInfo = getTaskInfo(task); 499| 0| assert(taskInfo && "rule action returned an unregistered task"); 500| 0| taskInfo->forRuleInfo = &ruleInfo; 501| 0| 502| 0| if (trace) 503| 0| trace->createdTaskForRule(taskInfo->task.get(), &ruleInfo.rule); 504| 0| 505| 0| // Transition the rule state. 506| 0| ruleInfo.state = RuleInfo::StateKind::InProgressWaiting; 507| 0| ruleInfo.setPendingTaskInfo(taskInfo); 508| 0| 509| 0| // Reset the Rule Dependencies, which we just append to during processing, 510| 0| // but we reset the others to ensure no one ever inadvertently uses them 511| 0| // during an invalid state. 512| 0| ruleInfo.result.dependencies.clear(); 513| 0| 514| 0| // Inform the task it should start. 515| 0| { 516| 0| TracingEngineTaskCallback i(EngineTaskCallbackKind::Start, ruleInfo.keyID); 517| 0| task->start(buildEngine); 518| 0| } 519| 0| 520| 0| // Provide the task the prior result, if present. 521| 0| // 522| 0| // FIXME: This should perhaps just be lumped in with the start call? Or 523| 0| // alternately, maybe there should just be an API call to fetch this, and 524| 0| // the clients that want it can ask? It's cheap to provide here, so 525| 0| // ultimately this is mostly a matter of cleanliness. 526| 0| if (ruleInfo.result.builtAt != 0) { 527| 0| TracingEngineTaskCallback i(EngineTaskCallbackKind::ProvidePriorValue, ruleInfo.keyID); 528| 0| task->providePriorValue(buildEngine, ruleInfo.result.value); 529| 0| } 530| 0| 531| 0| // If this task has no waiters, schedule it immediately for finalization. 532| 0| if (!taskInfo->waitCount) { 533| 0| readyTaskInfos.push_back(taskInfo); 534| 0| } 535| 0| 536| 0| return false; 537| 0| } 538| | 539| | /// Process an individual scan request. 540| | /// 541| | /// This will process all of the inputs required by the requesting rule, in 542| | /// order, unless the scan needs to be deferred waiting for an input. 543| 0| void processRuleScanRequest(RuleScanRequest request) { 544| 0| auto& ruleInfo = *request.ruleInfo; 545| 0| 546| 0| // With forced builds in cycle breaking, we may end up being asked to scan 547| 0| // something that has already been 'scanned' 548| 0| assert(ruleInfo.isScanning() || ruleInfo.wasForced); 549| 0| if (!ruleInfo.isScanning()) 550| 0| return; 551| 0| 552| 0| // Process each of the remaining inputs. 553| 0| do { 554| 0| // Look up the input rule info, if not yet cached. 555| 0| if (!request.inputRuleInfo) { 556| 0| const auto& inputID = ruleInfo.result.dependencies[request.inputIndex]; 557| 0| request.inputRuleInfo = &getRuleInfoForKey(inputID); 558| 0| } 559| 0| auto& inputRuleInfo = *request.inputRuleInfo; 560| 0| 561| 0| // Scan the input. 562| 0| bool isScanned = scanRule(inputRuleInfo); 563| 0| 564| 0| // If the input isn't scanned yet, enqueue this input scan request. 565| 0| if (!isScanned) { 566| 0| assert(inputRuleInfo.isScanning()); 567| 0| if (trace) 568| 0| trace->ruleScanningDeferredOnInput(&ruleInfo.rule, 569| 0| &inputRuleInfo.rule); 570| 0| inputRuleInfo.getPendingScanRecord() 571| 0| ->deferredScanRequests.push_back(request); 572| 0| return; 573| 0| } 574| 0| 575| 0| if (trace) 576| 0| trace->ruleScanningNextInput(&ruleInfo.rule, &inputRuleInfo.rule); 577| 0| 578| 0| // Demand the input. 579| 0| bool isAvailable = demandRule(inputRuleInfo); 580| 0| 581| 0| // If the input isn't already available, enqueue this scan request on the 582| 0| // input. 583| 0| // 584| 0| // FIXME: We need to continue scanning the rest of the inputs to ensure we 585| 0| // are not delaying necessary work. See . 586| 0| if (!isAvailable) { 587| 0| if (trace) 588| 0| trace->ruleScanningDeferredOnTask( 589| 0| &ruleInfo.rule, inputRuleInfo.getPendingTaskInfo()->task.get()); 590| 0| assert(inputRuleInfo.isInProgress()); 591| 0| inputRuleInfo.getPendingTaskInfo()-> 592| 0| deferredScanRequests.push_back(request); 593| 0| return; 594| 0| } 595| 0| 596| 0| // If the input has been computed since the last time this rule was 597| 0| // built, it needs to run. 598| 0| if (ruleInfo.result.builtAt < inputRuleInfo.result.computedAt) { 599| 0| if (trace) 600| 0| trace->ruleNeedsToRunBecauseInputRebuilt( 601| 0| &ruleInfo.rule, &inputRuleInfo.rule); 602| 0| finishScanRequest(ruleInfo, RuleInfo::StateKind::NeedsToRun); 603| 0| return; 604| 0| } 605| 0| 606| 0| // Otherwise, increment the scan index. 607| 0| ++request.inputIndex; 608| 0| request.inputRuleInfo = nullptr; 609| 0| } while (request.inputIndex != ruleInfo.result.dependencies.size()); 610| 0| 611| 0| // If we reached the end of the inputs, the rule does not need to run. 612| 0| if (trace) 613| 0| trace->ruleDoesNotNeedToRun(&ruleInfo.rule); 614| 0| finishScanRequest(ruleInfo, RuleInfo::StateKind::DoesNotNeedToRun); 615| 0| } 616| | 617| | void finishScanRequest(RuleInfo& inputRuleInfo, 618| 0| RuleInfo::StateKind newState) { 619| 0| assert(inputRuleInfo.isScanning()); 620| 0| auto scanRecord = inputRuleInfo.getPendingScanRecord(); 621| 0| 622| 0| // Wake up all of the pending scan requests. 623| 0| for (const auto& request: scanRecord->deferredScanRequests) { 624| 0| ruleInfosToScan.push_back(request); 625| 0| } 626| 0| 627| 0| // Wake up all of the input requests on this rule. 628| 0| for (const auto& request: scanRecord->pausedInputRequests) { 629| 0| inputRequests.push_back(request); 630| 0| } 631| 0| 632| 0| // Update the rule state. 633| 0| freeRuleScanRecord(scanRecord); 634| 0| inputRuleInfo.setPendingScanRecord(nullptr); 635| 0| inputRuleInfo.state = newState; 636| 0| } 637| | 638| | /// Decrement the task's wait count, and move it to the ready queue if 639| | /// necessary. 640| 0| void decrementTaskWaitCount(TaskInfo* taskInfo) { 641| 0| --taskInfo->waitCount; 642| 0| if (trace) 643| 0| trace->updatedTaskWaitCount(taskInfo->task.get(), taskInfo->waitCount); 644| 0| if (taskInfo->waitCount == 0) { 645| 0| if (trace) 646| 0| trace->unblockedTask(taskInfo->task.get()); 647| 0| readyTaskInfos.push_back(taskInfo); 648| 0| } 649| 0| } 650| | 651| | /// Execute all of the work pending in the engine queues until they are empty. 652| | /// 653| | /// \param buildKey The key to build. 654| | /// \returns True on success, false if the build could not be completed; the 655| | /// latter only occurs when the build contains a cycle currently. 656| 0| bool executeTasks(const KeyType& buildKey) { 657| 0| // Clear any previous build state 658| 0| finishedInputRequests.clear(); 659| 0| 660| 0| // Push a dummy input request for the rule to build. 661| 0| inputRequests.push_back({ nullptr, &getRuleInfoForKey(buildKey) }); 662| 0| 663| 0| // Process requests as long as we have work to do. 664| 0| while (true) { 665| 0| bool didWork = false; 666| 0| 667| 0| // Cancel the build, if requested. 668| 0| if (buildCancelled) { 669| 0| // Force completion of all outstanding tasks. 670| 0| cancelRemainingTasks(); 671| 0| return false; 672| 0| } 673| 0| 674| 0| // Process all of the pending rule scan requests. 675| 0| // 676| 0| // FIXME: We don't want to process all of these requests, this amounts to 677| 0| // doing all of the dependency scanning up-front. 678| 0| while (!ruleInfosToScan.empty()) { 679| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::RuleToScan, buildKey.c_str()); 680| 0| 681| 0| didWork = true; 682| 0| 683| 0| auto request = ruleInfosToScan.back(); 684| 0| ruleInfosToScan.pop_back(); 685| 0| 686| 0| processRuleScanRequest(request); 687| 0| } 688| 0| 689| 0| // Process all of the pending input requests. 690| 0| while (!inputRequests.empty()) { 691| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::InputRequest, buildKey.c_str()); 692| 0| 693| 0| didWork = true; 694| 0| 695| 0| auto request = inputRequests.back(); 696| 0| inputRequests.pop_back(); 697| 0| 698| 0| if (trace) { 699| 0| if (request.taskInfo) { 700| 0| trace->handlingTaskInputRequest(request.taskInfo->task.get(), 701| 0| &request.inputRuleInfo->rule); 702| 0| } else { 703| 0| trace->handlingBuildInputRequest(&request.inputRuleInfo->rule); 704| 0| } 705| 0| } 706| 0| 707| 0| // Request the input rule be scanned. 708| 0| bool isScanned = scanRule(*request.inputRuleInfo); 709| 0| 710| 0| // If the rule is not yet scanned, suspend this input request. 711| 0| if (!isScanned) { 712| 0| assert(request.inputRuleInfo->isScanning()); 713| 0| if (trace) 714| 0| trace->pausedInputRequestForRuleScan( 715| 0| &request.inputRuleInfo->rule); 716| 0| request.inputRuleInfo->getPendingScanRecord() 717| 0| ->pausedInputRequests.push_back(request); 718| 0| continue; 719| 0| } 720| 0| 721| 0| // Request the input rule be computed. 722| 0| bool isAvailable = demandRule(*request.inputRuleInfo); 723| 0| 724| 0| // If this is a dummy input request, we are done. 725| 0| if (!request.taskInfo) 726| 0| continue; 727| 0| 728| 0| // If the rule is already available, enqueue the finalize request. 729| 0| if (isAvailable) { 730| 0| if (trace) 731| 0| trace->readyingTaskInputRequest(request.taskInfo->task.get(), 732| 0| &request.inputRuleInfo->rule); 733| 0| finishedInputRequests.push_back(request); 734| 0| } else { 735| 0| // Otherwise, record the pending input request. 736| 0| assert(request.inputRuleInfo->getPendingTaskInfo()); 737| 0| if (trace) 738| 0| trace->addedRulePendingTask(&request.inputRuleInfo->rule, 739| 0| request.taskInfo->task.get()); 740| 0| request.inputRuleInfo->getPendingTaskInfo()->requestedBy.push_back( 741| 0| request); 742| 0| } 743| 0| } 744| 0| 745| 0| // Process all of the finished inputs. 746| 0| while (!finishedInputRequests.empty()) { 747| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::FinishedInputRequest, buildKey.c_str()); 748| 0| 749| 0| didWork = true; 750| 0| 751| 0| auto request = finishedInputRequests.back(); 752| 0| finishedInputRequests.pop_back(); 753| 0| 754| 0| if (trace) 755| 0| trace->completedTaskInputRequest(request.taskInfo->task.get(), 756| 0| &request.inputRuleInfo->rule); 757| 0| 758| 0| // If this is a must follow input, we simply decrement the task wait 759| 0| // count. 760| 0| // 761| 0| // This works because must follow inputs do not need to be recorded or 762| 0| // scanned -- they are only relevant if the task is executing, in which 763| 0| // case it is responsible for having supplied the request. 764| 0| if (request.inputID == kMustFollowInputID) { 765| 0| decrementTaskWaitCount(request.taskInfo); 766| 0| continue; 767| 0| } 768| 0| 769| 0| // Otherwise, we are processing a regular input dependency. 770| 0| 771| 0| // Update the recorded dependencies of this task. 772| 0| // 773| 0| // FIXME: This is very performance critical and should be highly 774| 0| // optimized. By itself, this addition added about 25% user time to the 775| 0| // "ack 3 16" experiment. 776| 0| // 777| 0| // FIXME: Think about where the best place to record this is. Our 778| 0| // options are: 779| 0| // * Record at the time it is requested. 780| 0| // * Record at the time it is popped off the input request queue. 781| 0| // * Record at the time the input is supplied (here). 782| 0| request.taskInfo->forRuleInfo->result.dependencies.push_back( 783| 0| request.inputRuleInfo->keyID); 784| 0| 785| 0| // Provide the requesting task with the input. 786| 0| // 787| 0| // FIXME: Should we provide the input key here? We have it available 788| 0| // cheaply. 789| 0| assert(request.inputRuleInfo->isComplete(this) || request.forcePriorValue); 790| 0| { 791| 0| TracingEngineTaskCallback i(EngineTaskCallbackKind::ProvideValue, request.inputRuleInfo->keyID); 792| 0| request.taskInfo->task->provideValue( 793| 0| buildEngine, request.inputID, request.inputRuleInfo->result.value); 794| 0| } 795| 0| 796| 0| // Decrement the wait count, and move to finish queue if necessary. 797| 0| decrementTaskWaitCount(request.taskInfo); 798| 0| } 799| 0| 800| 0| // Process all of the ready to run tasks. 801| 0| while (!readyTaskInfos.empty()) { 802| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::ReadyTask, buildKey.c_str()); 803| 0| 804| 0| didWork = true; 805| 0| 806| 0| TaskInfo* taskInfo = readyTaskInfos.back(); 807| 0| readyTaskInfos.pop_back(); 808| 0| 809| 0| RuleInfo* ruleInfo = taskInfo->forRuleInfo; 810| 0| assert(taskInfo == ruleInfo->getPendingTaskInfo()); 811| 0| 812| 0| if (trace) 813| 0| trace->readiedTask(taskInfo->task.get(), &ruleInfo->rule); 814| 0| 815| 0| // Transition the rule state. 816| 0| assert(ruleInfo->isInProgressWaiting()); 817| 0| ruleInfo->state = RuleInfo::StateKind::InProgressComputing; 818| 0| 819| 0| // Inform the task its inputs are ready and it should finish. 820| 0| // 821| 0| // FIXME: We need to track this state, and generate an error if this 822| 0| // task ever requests additional inputs. 823| 0| { 824| 0| TracingEngineTaskCallback i(EngineTaskCallbackKind::InputsAvailable, ruleInfo->keyID); 825| 0| taskInfo->task->inputsAvailable(buildEngine); 826| 0| } 827| 0| 828| 0| // Increment our count of outstanding tasks. 829| 0| ++numOutstandingUnfinishedTasks; 830| 0| } 831| 0| 832| 0| // Process all of the finished tasks. 833| 0| while (true) { 834| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::FinishedTask, buildKey.c_str()); 835| 0| 836| 0| // Try to take a task from the finished queue. 837| 0| TaskInfo* taskInfo = nullptr; 838| 0| { 839| 0| std::lock_guard guard(finishedTaskInfosMutex); 840| 0| if (!finishedTaskInfos.empty()) { 841| 0| taskInfo = finishedTaskInfos.back(); 842| 0| finishedTaskInfos.pop_back(); 843| 0| } 844| 0| } 845| 0| if (!taskInfo) 846| 0| break; 847| 0| 848| 0| didWork = true; 849| 0| 850| 0| RuleInfo* ruleInfo = taskInfo->forRuleInfo; 851| 0| assert(taskInfo == ruleInfo->getPendingTaskInfo()); 852| 0| 853| 0| // The task was changed if was computed in the current iteration. 854| 0| if (trace) { 855| 0| bool wasChanged = ruleInfo->result.computedAt == currentTimestamp; 856| 0| trace->finishedTask(taskInfo->task.get(), &ruleInfo->rule, 857| 0| wasChanged); 858| 0| } 859| 0| 860| 0| // Transition the rule state by completing the rule (the value itself is 861| 0| // stored in the taskIsFinished call). 862| 0| assert(ruleInfo->state == RuleInfo::StateKind::InProgressComputing); 863| 0| ruleInfo->setPendingTaskInfo(nullptr); 864| 0| ruleInfo->setComplete(this); 865| 0| 866| 0| // Report the status change. 867| 0| if (ruleInfo->rule.updateStatus) 868| 0| ruleInfo->rule.updateStatus(buildEngine, 869| 0| Rule::StatusKind::IsComplete); 870| 0| 871| 0| // Add all of the task's discovered dependencies. 872| 0| // 873| 0| // FIXME: We could audit these dependencies at this point to verify that 874| 0| // they are not keys for rules which have not been run, which would 875| 0| // indicate an underspecified build (e.g., a generated header). 876| 0| ruleInfo->result.dependencies.insert( 877| 0| ruleInfo->result.dependencies.end(), 878| 0| taskInfo->discoveredDependencies.begin(), 879| 0| taskInfo->discoveredDependencies.end()); 880| 0| 881| 0| // Push back dummy input requests for any discovered dependencies, which 882| 0| // must be at least built in order to be brought up-to-date. 883| 0| // 884| 0| // FIXME: The need to do this makes it questionable that we use this 885| 0| // approach for discovered dependencies instead of just providing 886| 0| // support for taskNeedsInput() even after the task has started 887| 0| // computing and from parallel contexts. 888| 0| for (KeyID inputID: taskInfo->discoveredDependencies) { 889| 0| inputRequests.push_back({ nullptr, &getRuleInfoForKey(inputID) }); 890| 0| } 891| 0| 892| 0| // Update the database record, if attached. 893| 0| if (db) { 894| 0| std::string error; 895| 0| bool result = db->setRuleResult( 896| 0| ruleInfo->keyID, ruleInfo->rule, ruleInfo->result, &error); 897| 0| if (!result) { 898| 0| delegate.error(error); 899| 0| cancelRemainingTasks(); 900| 0| return false; 901| 0| } 902| 0| } 903| 0| 904| 0| // Wake up all of the pending scan requests. 905| 0| for (const auto& request: taskInfo->deferredScanRequests) { 906| 0| ruleInfosToScan.push_back(request); 907| 0| } 908| 0| 909| 0| // Push all pending input requests onto the work queue. 910| 0| if (trace) { 911| 0| for (auto& request: taskInfo->requestedBy) { 912| 0| trace->readyingTaskInputRequest(request.taskInfo->task.get(), 913| 0| &request.inputRuleInfo->rule); 914| 0| } 915| 0| } 916| 0| finishedInputRequests.insert(finishedInputRequests.end(), 917| 0| taskInfo->requestedBy.begin(), 918| 0| taskInfo->requestedBy.end()); 919| 0| 920| 0| // Decrement our count of outstanding tasks. 921| 0| --numOutstandingUnfinishedTasks; 922| 0| 923| 0| // Delete the pending task. 924| 0| { 925| 0| std::lock_guard guard(taskInfosMutex); 926| 0| auto it = taskInfos.find(taskInfo->task.get()); 927| 0| assert(it != taskInfos.end()); 928| 0| taskInfos.erase(it); 929| 0| } 930| 0| } 931| 0| 932| 0| // If we haven't done any other work at this point but we have pending 933| 0| // tasks, we need to wait for a task to complete. 934| 0| // 935| 0| // NOTE: Cancellation also implements this process, if you modify this 936| 0| // code please also validate that \see cancelRemainingTasks() is still 937| 0| // correct. 938| 0| if (!didWork && numOutstandingUnfinishedTasks != 0) { 939| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::Waiting, buildKey.c_str()); 940| 0| 941| 0| // Wait for our condition variable. 942| 0| std::unique_lock lock(finishedTaskInfosMutex); 943| 0| 944| 0| // Ensure we still don't have enqueued operations under the protection 945| 0| // of the mutex, if one has been added then we may have already missed 946| 0| // the condition notification and cannot safely wait. 947| 0| if (finishedTaskInfos.empty()) { 948| 0| finishedTaskInfosCondition.wait(lock); 949| 0| } 950| 0| 951| 0| didWork = true; 952| 0| } 953| 0| 954| 0| if (!didWork) { 955| 0| // If there was no work to do, but we still have running tasks, then 956| 0| // we have found a cycle. Try to resolve it and continue. 957| 0| if (!taskInfos.empty()) { 958| 0| if (resolveCycle(buildKey)) { 959| 0| continue; 960| 0| } else { 961| 0| cancelRemainingTasks(); 962| 0| return false; 963| 0| } 964| 0| } 965| 0| 966| 0| // We didn't do any work, and we have nothing more we can/need to do. 967| 0| break; 968| 0| } 969| 0| } 970| 0| 971| 0| return true; 972| 0| } 973| | 974| | /// Attempt to resolve a cycle which has called the engine to be unable to make forward 975| | /// progress. 976| | /// 977| | /// \param buildKey The key which was requested to build (the reported cycle 978| | /// with start with this node). 979| | /// \returns True if the engine should try to proceed, false if the build the could not 980| | /// be broken. 981| 0| bool resolveCycle(const KeyType& buildKey) { 982| 0| // Take all available locks, to ensure we dump a consistent state. 983| 0| std::lock_guard guard1(taskInfosMutex); 984| 0| std::lock_guard guard2(finishedTaskInfosMutex); 985| 0| 986| 0| std::vector cycleList = findCycle(buildKey); 987| 0| assert(!cycleList.empty()); 988| 0| 989| 0| if (breakCycle(cycleList)) 990| 0| return true; 991| 0| 992| 0| delegate.cycleDetected(cycleList); 993| 0| return false; 994| 0| } 995| | 996| 0| std::vector findCycle(const KeyType& buildKey) { 997| 0| TracingEngineQueueItemEvent i(EngineQueueItemKind::FindingCycle, buildKey.c_str()); 998| 0| 999| 0| // Gather all of the successor relationships. 1000| 0| std::unordered_map> successorGraph; 1001| 0| std::vector activeRuleScanRecords; 1002| 0| for (const auto& it: taskInfos) { 1003| 0| const TaskInfo& taskInfo = it.second; 1004| 0| assert(taskInfo.forRuleInfo); 1005| 0| std::vector successors; 1006| 0| for (const auto& request: taskInfo.requestedBy) { 1007| 0| assert(request.taskInfo->forRuleInfo); 1008| 0| successors.push_back(&request.taskInfo->forRuleInfo->rule); 1009| 0| } 1010| 0| for (const auto& request: taskInfo.deferredScanRequests) { 1011| 0| // Add the sucessor for the deferred relationship itself. 1012| 0| successors.push_back(&request.ruleInfo->rule); 1013| 0| } 1014| 0| successorGraph.insert({ &taskInfo.forRuleInfo->rule, successors }); 1015| 0| } 1016| 0| 1017| 0| // Add the pending scan records for every rule. 1018| 0| // 1019| 0| // NOTE: There is a very subtle condition around this versus adding the ones 1020| 0| // accessible via the tasks, see https://bugs.swift.org/browse/SR-1948. 1021| 0| // Unfortunately, we do not have a test case for this! 1022| 0| for (const auto& it: ruleInfos) { 1023| 0| const RuleInfo& ruleInfo = it.second; 1024| 0| if (ruleInfo.isScanning()) { 1025| 0| const auto* scanRecord = ruleInfo.getPendingScanRecord(); 1026| 0| activeRuleScanRecords.push_back(scanRecord); 1027| 0| } 1028| 0| } 1029| 0| 1030| 0| // Gather dependencies from all of the active scan records. 1031| 0| std::unordered_set visitedRuleScanRecords; 1032| 0| while (!activeRuleScanRecords.empty()) { 1033| 0| const auto* record = activeRuleScanRecords.back(); 1034| 0| activeRuleScanRecords.pop_back(); 1035| 0| 1036| 0| // Mark the record and ignore it if not scanned. 1037| 0| if (!visitedRuleScanRecords.insert(record).second) 1038| 0| continue; 1039| 0| 1040| 0| // For each paused request, add the dependency. 1041| 0| for (const auto& request: record->pausedInputRequests) { 1042| 0| if (request.taskInfo) { 1043| 0| successorGraph[&request.inputRuleInfo->rule].push_back( 1044| 0| &request.taskInfo->forRuleInfo->rule); 1045| 0| } 1046| 0| } 1047| 0| 1048| 0| // Process the deferred scan requests. 1049| 0| for (const auto& request: record->deferredScanRequests) { 1050| 0| // Add the sucessor for the deferred relationship itself. 1051| 0| successorGraph[&request.inputRuleInfo->rule].push_back( 1052| 0| &request.ruleInfo->rule); 1053| 0| 1054| 0| // Add the active rule scan record which needs to be traversed. 1055| 0| assert(request.ruleInfo->isScanning() || request.ruleInfo->wasForced); 1056| 0| if (request.ruleInfo->isScanning()) { 1057| 0| activeRuleScanRecords.push_back( 1058| 0| request.ruleInfo->getPendingScanRecord()); 1059| 0| } 1060| 0| } 1061| 0| } 1062| 0| 1063| 0| // Invert the graph, so we can search from the root. 1064| 0| std::unordered_map> predecessorGraph; 1065| 0| for (auto& entry: successorGraph) { 1066| 0| Rule* node = entry.first; 1067| 0| for (auto& succ: entry.second) { 1068| 0| predecessorGraph[succ].push_back(node); 1069| 0| } 1070| 0| } 1071| 0| 1072| 0| // Normalize predecessor order, to ensure a deterministic result (at least, 1073| 0| // if the graph reaches the same cycle). 1074| 0| for (auto& entry: predecessorGraph) { 1075| 0| std::sort(entry.second.begin(), entry.second.end(), [](Rule* a, Rule* b) { 1076| 0| return a->key < b->key; 1077| 0| }); 1078| 0| } 1079| 0| 1080| 0| // Find the cycle by searching from the entry node. 1081| 0| struct WorkItem { 1082| 0| WorkItem(Rule * node) { this->node = node; } 1083| 0| 1084| 0| Rule* node; 1085| 0| unsigned predecessorIndex = 0; 1086| 0| }; 1087| 0| std::vector cycleList; 1088| 0| std::unordered_set cycleItems; 1089| 0| std::vector stack{ 1090| 0| WorkItem{ &getRuleInfoForKey(buildKey).rule } }; 1091| 0| while (!stack.empty()) { 1092| 0| // Take the top item. 1093| 0| auto& entry = stack.back(); 1094| 0| const auto& predecessors = predecessorGraph[entry.node]; 1095| 0| 1096| 0| // If the index is 0, we just started visiting the node. 1097| 0| if (entry.predecessorIndex == 0) { 1098| 0| // Push the node on the stack. 1099| 0| cycleList.push_back(entry.node); 1100| 0| auto it = cycleItems.insert(entry.node); 1101| 0| 1102| 0| // If the node is already in the stack, we found a cycle. 1103| 0| if (!it.second) 1104| 0| break; 1105| 0| } 1106| 0| 1107| 0| // Visit the next predecessor, if possible. 1108| 0| if (entry.predecessorIndex != predecessors.size()) { 1109| 0| auto* child = predecessors[entry.predecessorIndex]; 1110| 0| entry.predecessorIndex += 1; 1111| 0| stack.emplace_back(WorkItem{ child }); 1112| 0| continue; 1113| 0| } 1114| 0| 1115| 0| // Otherwise, we are done visiting this node. 1116| 0| cycleItems.erase(entry.node); 1117| 0| cycleList.pop_back(); 1118| 0| stack.pop_back(); 1119| 0| } 1120| 0| 1121| 0| return cycleList; 1122| 0| } 1123| | 1124| 0| bool breakCycle(const std::vector& cycleList) { 1125| 0| // BreakingCycle doesn't need a key since it will not be called in parallel 1126| 0| TracingEngineQueueItemEvent _(EngineQueueItemKind::BreakingCycle, "0"); 1127| 0| 1128| 0| // Search the cycle for potential means for breaking the cycle. Right now 1129| 0| // we use two principle approaches, force a rule to be built (skipping 1130| 0| // scanning its dependencies) and supply a previously built result. 1131| 0| for (auto ruleIt = cycleList.rbegin(); ruleIt != cycleList.rend(); ruleIt++) { 1132| 0| auto& ruleInfo = getRuleInfoForKey((*ruleIt)->key); 1133| 0| 1134| 0| // If this rule is scanning, try to force a rebuild to break the cycle 1135| 0| if (ruleInfo.isScanning()) { 1136| 0| // Ask the delegate if we should try to resolve this cycle by forcing 1137| 0| // a rule to be built? 1138| 0| if (!delegate.shouldResolveCycle(cycleList, &ruleInfo.rule, Rule::CycleAction::ForceBuild)) 1139| 0| return false; 1140| 0| 1141| 0| if (trace) { 1142| 0| trace->cycleForceRuleNeedsToRun(&ruleInfo.rule); 1143| 0| } 1144| 0| 1145| 0| // Find the rule scan request, if not already deferred, for this rule 1146| 0| // and remove it. If the rule scan request was already deferred, we use 1147| 0| // the wasForced condition to ignore it later. 1148| 0| auto it = findRuleScanRequestForRule(ruleInfosToScan, &ruleInfo); 1149| 0| if (it != ruleInfosToScan.end()) { 1150| 0| ruleInfosToScan.erase(it); 1151| 0| } 1152| 0| 1153| 0| // mark this rule as needs to run (forced) 1154| 0| finishScanRequest(ruleInfo, RuleInfo::StateKind::NeedsToRun); 1155| 0| ruleInfo.wasForced = true; 1156| 0| 1157| 0| return true; 1158| 0| } 1159| 0| 1160| 0| // Check if this rule has a (potentially) valid previous result and if so 1161| 0| // try to provide it to the node requesting it to break the cycle. 1162| 0| if (ruleInfo.isInProgressWaiting() && ruleInfo.result.builtAt != 0) { 1163| 0| auto* taskInfo = ruleInfo.getPendingTaskInfo(); 1164| 0| 1165| 0| // find downstream node in the cycle that wants this input 1166| 0| auto& nextRuleInfo = getRuleInfoForKey((*std::next(ruleIt))->key); 1167| 0| 1168| 0| // find the corresponding request on this task 1169| 0| auto it = findTaskInputRequestForRule(taskInfo->requestedBy, &nextRuleInfo); 1170| 0| if (it == taskInfo->requestedBy.end()) { 1171| 0| // this rule has not generated an input request yet, so we cannot 1172| 0| // provide a value to it 1173| 0| continue; 1174| 0| } 1175| 0| 1176| 0| // Ask the delegate if we should try to resolve this cycle by supplying 1177| 0| // a prior value? 1178| 0| if (!delegate.shouldResolveCycle(cycleList, &ruleInfo.rule, Rule::CycleAction::SupplyPriorValue)) 1179| 0| return false; 1180| 0| 1181| 0| // supply the prior value to the node 1182| 0| if (trace) { 1183| 0| trace->cycleSupplyPriorValue(&ruleInfo.rule, it->taskInfo->task.get()); 1184| 0| } 1185| 0| it->forcePriorValue = true; 1186| 0| finishedInputRequests.insert(finishedInputRequests.end(), *it); 1187| 0| 1188| 0| // remove this request from the task info 1189| 0| taskInfo->requestedBy.erase(it); 1190| 0| return true; 1191| 0| } 1192| 0| } 1193| 0| 1194| 0| return false; 1195| 0| } 1196| | 1197| | // Helper function for breakCycle, finds a rule in a RuleScanRequest vector 1198| | std::vector::iterator findRuleScanRequestForRule( 1199| 0| std::vector& requests, RuleInfo* ruleInfo) { 1200| 0| for (auto it = requests.begin(); it != requests.end(); it++) { 1201| 0| if (it->ruleInfo == ruleInfo) { 1202| 0| return it; 1203| 0| } 1204| 0| } 1205| 0| 1206| 0| return requests.end(); 1207| 0| } 1208| | 1209| | // Helper function for breakCycle, finds a rule in a TaskInputRequest vector 1210| | std::vector::iterator findTaskInputRequestForRule( 1211| 0| std::vector& requests, RuleInfo* ruleInfo) { 1212| 0| for (auto it = requests.begin(); it != requests.end(); it++) { 1213| 0| if (it->taskInfo->forRuleInfo == ruleInfo) { 1214| 0| return it; 1215| 0| } 1216| 0| } 1217| 0| 1218| 0| return requests.end(); 1219| 0| } 1220| | 1221| | // Cancel all of the remaining tasks. 1222| 0| void cancelRemainingTasks() { 1223| 0| // We need to wait for any currently running tasks to be reported as 1224| 0| // complete. Not doing this would mean we could get asynchronous calls 1225| 0| // attempting to modify the task state concurrently with the cancellation 1226| 0| // process, which isn't something we want to need to synchronize on. 1227| 0| // 1228| 0| // We don't process the requests at all, we simply drain them. In practice, 1229| 0| // we expect clients to implement cancellation in conjection with causing 1230| 0| // long-running tasks to also cancel and fail, so preserving those results 1231| 0| // is not valuable. 1232| 0| while (numOutstandingUnfinishedTasks != 0) { 1233| 0| std::unique_lock lock(finishedTaskInfosMutex); 1234| 0| if (finishedTaskInfos.empty()) { 1235| 0| finishedTaskInfosCondition.wait(lock); 1236| 0| } else { 1237| 0| assert(finishedTaskInfos.size() <= numOutstandingUnfinishedTasks); 1238| 0| numOutstandingUnfinishedTasks -= finishedTaskInfos.size(); 1239| 0| finishedTaskInfos.clear(); 1240| 0| } 1241| 0| } 1242| 0| 1243| 0| std::lock_guard guard(taskInfosMutex); 1244| 0| 1245| 0| for (auto& it: taskInfos) { 1246| 0| // Cancel the task, marking it incomplete. 1247| 0| // 1248| 0| // This will force it to rerun in a later build, but since it was already 1249| 0| // running in this build that was almost certainly going to be 1250| 0| // required. Technically, there are rare situations where it wouldn't have 1251| 0| // to rerun (e.g., if resultIsValid becomes true after being false in this 1252| 0| // run), and if we were willing to restore the tasks state--either by 1253| 0| // keeping the old one or by restoring from the database--we could ensure 1254| 0| // that doesn't happen. 1255| 0| // 1256| 0| // NOTE: Actually, we currently don't sync this write to the database, so 1257| 0| // in some cases we do actually preserve this information (if the client 1258| 0| // ends up cancelling, then reloading froom the database). 1259| 0| TaskInfo* taskInfo = &it.second; 1260| 0| RuleInfo* ruleInfo = taskInfo->forRuleInfo; 1261| 0| assert(taskInfo == ruleInfo->getPendingTaskInfo()); 1262| 0| ruleInfo->setPendingTaskInfo(nullptr); 1263| 0| ruleInfo->setCancelled(); 1264| 0| } 1265| 0| 1266| 0| // FIXME: This is currently an O(n) operation that could be relatively 1267| 0| // expensive on larger projects. We should be able to do something more 1268| 0| // targeted. rdar://problem/39386591 1269| 0| for (auto& it: ruleInfos) { 1270| 0| // Cancel outstanding activity on rules 1271| 0| if (it.second.isScanning()) { 1272| 0| it.second.setCancelled(); 1273| 0| } 1274| 0| } 1275| 0| 1276| 0| // Delete all of the tasks. 1277| 0| taskInfos.clear(); 1278| 0| } 1279| | 1280| |public: 1281| | BuildEngineImpl(class BuildEngine& buildEngine, 1282| | BuildEngineDelegate& delegate) 1283| 0| : buildEngine(buildEngine), delegate(delegate) {} 1284| | 1285| 0| ~BuildEngineImpl() { 1286| 0| // If tracing is enabled, close it. 1287| 0| if (trace) { 1288| 0| std::string error; 1289| 0| trace->close(&error); 1290| 0| } 1291| 0| } 1292| | 1293| 0| BuildEngineDelegate* getDelegate() { 1294| 0| return &delegate; 1295| 0| } 1296| | 1297| 0| Timestamp getCurrentTimestamp() { 1298| 0| return currentTimestamp; 1299| 0| } 1300| | 1301| 0| virtual KeyID getKeyID(const KeyType& key) override { 1302| 0| std::lock_guard guard(keyTableMutex); 1303| 0| 1304| 0| // The RHS of the mapping is actually ignored, we use the StringMap's ptr 1305| 0| // identity because it allows us to efficiently map back to the key string 1306| 0| // in `getRuleInfoForKey`. 1307| 0| auto it = keyTable.insert(std::make_pair(key, 0)).first; 1308| 0| return (KeyID)(uintptr_t)it->getKey().data(); 1309| 0| } 1310| | 1311| 0| virtual KeyType getKeyForID(KeyID key) override { 1312| 0| // Note that we don't need to lock `keyTable` here because the key entries 1313| 0| // themselves don't change once created. 1314| 0| return llvm::StringMapEntry::GetStringMapEntryFromKeyData( 1315| 0| (const char*)(uintptr_t)key).getKey(); 1316| 0| } 1317| | 1318| 0| RuleInfo& getRuleInfoForKey(const KeyType& key) { 1319| 0| auto keyID = getKeyID(key); 1320| 0| 1321| 0| // Check if we have already found the rule. 1322| 0| auto it = ruleInfos.find(keyID); 1323| 0| if (it != ruleInfos.end()) 1324| 0| return it->second; 1325| 0| 1326| 0| // Otherwise, request it from the delegate and add it. 1327| 0| return addRule(keyID, delegate.lookupRule(key)); 1328| 0| } 1329| | 1330| 0| RuleInfo& getRuleInfoForKey(KeyID keyID) { 1331| 0| // Check if we have already found the rule. 1332| 0| auto it = ruleInfos.find(keyID); 1333| 0| if (it != ruleInfos.end()) 1334| 0| return it->second; 1335| 0| 1336| 0| // Otherwise, we need to resolve the full key so we can request it from the 1337| 0| // delegate. 1338| 0| return addRule(keyID, delegate.lookupRule(getKeyForID(keyID))); 1339| 0| } 1340| | 1341| 0| TaskInfo* getTaskInfo(Task* task) { 1342| 0| std::lock_guard guard(taskInfosMutex); 1343| 0| auto it = taskInfos.find(task); 1344| 0| return it == taskInfos.end() ? nullptr : &it->second; 1345| 0| } 1346| | 1347| | /// @name Rule Definition 1348| | /// @{ 1349| | 1350| 0| RuleInfo& addRule(Rule&& rule) { 1351| 0| return addRule(getKeyID(rule.key), std::move(rule)); 1352| 0| } 1353| | 1354| 0| RuleInfo& addRule(KeyID keyID, Rule&& rule) { 1355| 0| auto result = ruleInfos.emplace(keyID, RuleInfo(keyID, std::move(rule))); 1356| 0| if (!result.second) { 1357| 0| delegate.error("attempt to register duplicate rule \"" + rule.key + "\"\n"); 1358| 0| 1359| 0| // Set cancelled, but return something 'valid' for use until it is 1360| 0| // processed. 1361| 0| buildCancelled = true; 1362| 0| return result.first->second; 1363| 0| } 1364| 0| 1365| 0| // If we have a database attached, retrieve any stored result. 1366| 0| // 1367| 0| // FIXME: Investigate retrieving this result lazily. If the DB is 1368| 0| // particularly efficient, it may be best to retrieve this only when we need 1369| 0| // it and never duplicate it. 1370| 0| RuleInfo& ruleInfo = result.first->second; 1371| 0| if (db) { 1372| 0| std::string error; 1373| 0| db->lookupRuleResult(ruleInfo.keyID, ruleInfo.rule, &ruleInfo.result, &error); 1374| 0| if (!error.empty()) { 1375| 0| // FIXME: Investigate changing the database error handling model to 1376| 0| // allow builds to proceed without the database. 1377| 0| delegate.error(error); 1378| 0| buildCancelled = true; 1379| 0| } 1380| 0| } 1381| 0| 1382| 0| return ruleInfo; 1383| 0| } 1384| | 1385| | /// @} 1386| | 1387| | /// @name Client API 1388| | /// @{ 1389| | 1390| 0| const ValueType& build(const KeyType& key) { 1391| 0| if (db) { 1392| 0| std::string error; 1393| 0| bool result = db->buildStarted(&error); 1394| 0| if (!result) { 1395| 0| delegate.error(error); 1396| 0| static ValueType emptyValue{}; 1397| 0| return emptyValue; 1398| 0| } 1399| 0| } 1400| 0| 1401| 0| // Increment our running iteration count. 1402| 0| // 1403| 0| // At this point, we should conceptually mark each complete rule as 1404| 0| // incomplete. However, instead of doing all that work immediately, we 1405| 0| // perform it lazily by reusing the Result::builtAt field for each rule as 1406| 0| // an additional mark. When a rule is demanded, if its builtAt index isn't 1407| 0| // up-to-date then we lazily reset it to be Incomplete, \see demandRule() 1408| 0| // and \see RuleInfo::isComplete(). 1409| 0| ++currentTimestamp; 1410| 0| 1411| 0| if (trace) 1412| 0| trace->buildStarted(); 1413| 0| 1414| 0| // Run the build engine, to process any necessary tasks. 1415| 0| buildCancelled = false; 1416| 0| bool success = executeTasks(key); 1417| 0| 1418| 0| // Update the build database, if attached. 1419| 0| // 1420| 0| // FIXME: Is it correct to do this here, or earlier? 1421| 0| if (db) { 1422| 0| std::string error; 1423| 0| bool result = db->setCurrentIteration(currentTimestamp, &error); 1424| 0| if (!result) { 1425| 0| delegate.error(error); 1426| 0| static ValueType emptyValue{}; 1427| 0| return emptyValue; 1428| 0| } 1429| 0| db->buildComplete(); 1430| 0| } 1431| 0| 1432| 0| if (trace) 1433| 0| trace->buildEnded(); 1434| 0| 1435| 0| // Clear the rule scan free-lists. 1436| 0| // 1437| 0| // FIXME: Introduce a per-build context object to hold this. 1438| 0| for (auto block: ruleScanRecordBlocks) 1439| 0| delete[] block; 1440| 0| currentBlockPos = currentBlockEnd = nullptr; 1441| 0| freeRuleScanRecords.clear(); 1442| 0| ruleScanRecordBlocks.clear(); 1443| 0| 1444| 0| // If the build failed, return the empty result. 1445| 0| if (!success) { 1446| 0| static ValueType emptyValue{}; 1447| 0| return emptyValue; 1448| 0| } 1449| 0| 1450| 0| // The task queue should be empty and the rule complete. 1451| 0| auto& ruleInfo = getRuleInfoForKey(key); 1452| 0| assert(taskInfos.empty() && ruleInfo.isComplete(this)); 1453| 0| return ruleInfo.result.value; 1454| 0| } 1455| | 1456| 0| void cancelBuild() { 1457| 0| // Set the build cancelled marker. 1458| 0| // 1459| 0| // We do not need to handle waking the engine up, if it is waiting, because 1460| 0| // our current cancellation model requires us to wait for all outstanding 1461| 0| // tasks in any case. 1462| 0| buildCancelled = true; 1463| 0| } 1464| | 1465| 0| bool attachDB(std::unique_ptr database, std::string* error_out) { 1466| 0| assert(!db && "invalid attachDB() call"); 1467| 0| assert(currentTimestamp == 0 && "invalid attachDB() call"); 1468| 0| assert(ruleInfos.empty() && "invalid attachDB() call"); 1469| 0| db = std::move(database); 1470| 0| db->attachDelegate(this); 1471| 0| 1472| 0| // Load our initial state from the database. 1473| 0| bool success; 1474| 0| currentTimestamp = db->getCurrentIteration(&success, error_out); 1475| 0| return success; 1476| 0| } 1477| | 1478| 0| bool enableTracing(const std::string& filename, std::string* error_out) { 1479| 0| auto trace = llvm::make_unique(); 1480| 0| 1481| 0| if (!trace->open(filename, error_out)) 1482| 0| return false; 1483| 0| 1484| 0| this->trace = std::move(trace); 1485| 0| return true; 1486| 0| } 1487| | 1488| | /// Dump the build state to a file in Graphviz DOT format. 1489| 0| void dumpGraphToFile(const std::string& path) { 1490| 0| FILE* fp = ::fopen(path.c_str(), "w"); 1491| 0| if (!fp) { 1492| 0| delegate.error("unable to open graph output path \"" + path + "\""); 1493| 0| return; 1494| 0| } 1495| 0| 1496| 0| // Write the graph header. 1497| 0| fprintf(fp, "digraph llbuild {\n"); 1498| 0| fprintf(fp, "rankdir=\"LR\"\n"); 1499| 0| fprintf(fp, "node [fontsize=10, shape=box, height=0.25]\n"); 1500| 0| fprintf(fp, "edge [fontsize=10]\n"); 1501| 0| fprintf(fp, "\n"); 1502| 0| 1503| 0| // Create a canonical node ordering. 1504| 0| std::vector orderedRuleInfos; 1505| 0| for (const auto& entry: ruleInfos) 1506| 0| orderedRuleInfos.push_back(&entry.second); 1507| 0| std::sort(orderedRuleInfos.begin(), orderedRuleInfos.end(), 1508| 0| [] (const RuleInfo* a, const RuleInfo* b) { 1509| 0| return a->rule.key < b->rule.key; 1510| 0| }); 1511| 0| 1512| 0| // Write out all of the rules. 1513| 0| for (const auto& ruleInfo: orderedRuleInfos) { 1514| 0| fprintf(fp, "\"%s\"\n", ruleInfo->rule.key.c_str()); 1515| 0| for (KeyID inputID: ruleInfo->result.dependencies) { 1516| 0| const auto& dependency = getRuleInfoForKey(inputID); 1517| 0| fprintf(fp, "\"%s\" -> \"%s\"\n", ruleInfo->rule.key.c_str(), 1518| 0| dependency.rule.key.c_str()); 1519| 0| } 1520| 0| fprintf(fp, "\n"); 1521| 0| } 1522| 0| 1523| 0| // Write the footer and close. 1524| 0| fprintf(fp, "}\n"); 1525| 0| fclose(fp); 1526| 0| } 1527| | 1528| 0| void addTaskInputRequest(Task* task, const KeyType& key, uintptr_t inputID) { 1529| 0| auto taskInfo = getTaskInfo(task); 1530| 0| 1531| 0| // Validate that the task is in a valid state to request inputs. 1532| 0| if (!taskInfo->forRuleInfo->isInProgressWaiting()) { 1533| 0| // FIXME: Error handling. 1534| 0| abort(); 1535| 0| } 1536| 0| 1537| 0| // Lookup the rule for this task. 1538| 0| RuleInfo* ruleInfo = &getRuleInfoForKey(key); 1539| 0| 1540| 0| inputRequests.push_back({ taskInfo, ruleInfo, inputID }); 1541| 0| taskInfo->waitCount++; 1542| 0| } 1543| | 1544| | /// @} 1545| | 1546| | /// @name Task Management Client APIs 1547| | /// @{ 1548| | 1549| 0| Task* registerTask(Task* task) { 1550| 0| { 1551| 0| std::lock_guard guard(taskInfosMutex); 1552| 0| auto result = taskInfos.emplace(task, TaskInfo(task)); 1553| 0| assert(result.second && "task already registered"); 1554| 0| (void)result; 1555| 0| } 1556| 0| return task; 1557| 0| } 1558| | 1559| 0| void taskNeedsInput(Task* task, const KeyType& key, uintptr_t inputID) { 1560| 0| // Validate the InputID. 1561| 0| if (inputID > BuildEngine::kMaximumInputID) { 1562| 0| delegate.error("attempt to use reserved input ID"); 1563| 0| buildCancelled = true; 1564| 0| return; 1565| 0| } 1566| 0| 1567| 0| addTaskInputRequest(task, key, inputID); 1568| 0| } 1569| | 1570| 0| void taskMustFollow(Task* task, const KeyType& key) { 1571| 0| addTaskInputRequest(task, key, kMustFollowInputID); 1572| 0| } 1573| | 1574| 0| void taskDiscoveredDependency(Task* task, const KeyType& key) { 1575| 0| // Find the task info. 1576| 0| auto taskInfo = getTaskInfo(task); 1577| 0| assert(taskInfo && "cannot request inputs for an unknown task"); 1578| 0| 1579| 0| if (!taskInfo->forRuleInfo->isInProgressComputing()) { 1580| 0| delegate.error("invalid state for adding discovered dependency"); 1581| 0| buildCancelled = true; 1582| 0| return; 1583| 0| } 1584| 0| 1585| 0| auto dependencyID = getKeyID(key); 1586| 0| taskInfo->discoveredDependencies.push_back(dependencyID); 1587| 0| } 1588| | 1589| 0| void taskIsComplete(Task* task, ValueType&& value, bool forceChange) { 1590| 0| // FIXME: We should flag the task to ensure this is only called once, and 1591| 0| // that no other API calls are made once complete. 1592| 0| 1593| 0| auto taskInfo = getTaskInfo(task); 1594| 0| assert(taskInfo && "cannot request inputs for an unknown task"); 1595| 0| 1596| 0| if (!taskInfo->forRuleInfo->isInProgressComputing()) { 1597| 0| delegate.error("invalid state for marking task complete"); 1598| 0| buildCancelled = true; 1599| 0| return; 1600| 0| } 1601| 0| 1602| 0| RuleInfo* ruleInfo = taskInfo->forRuleInfo; 1603| 0| assert(taskInfo == ruleInfo->getPendingTaskInfo()); 1604| 0| 1605| 0| // Process the provided result. 1606| 0| if (!forceChange && value == ruleInfo->result.value) { 1607| 0| // If the value is unchanged, do nothing. 1608| 0| } else { 1609| 0| // Otherwise, updated the result and the computed at time. 1610| 0| ruleInfo->result.value = std::move(value); 1611| 0| ruleInfo->result.computedAt = currentTimestamp; 1612| 0| } 1613| 0| 1614| 0| // Enqueue the finished task. 1615| 0| { 1616| 0| std::lock_guard guard(finishedTaskInfosMutex); 1617| 0| finishedTaskInfos.push_back(taskInfo); 1618| 0| } 1619| 0| 1620| 0| // Notify the engine to wake up, if necessary. 1621| 0| finishedTaskInfosCondition.notify_one(); 1622| 0| } 1623| | 1624| | /// @} 1625| | 1626| | /// @name Internal APIs 1627| | /// @{ 1628| | 1629| 0| uint64_t getCurrentTimestamp() const { return currentTimestamp; } 1630| | 1631| | /// @} 1632| |}; 1633| | 1634| |} 1635| | 1636| |#pragma mark - BuildEngine 1637| | 1638| |BuildEngine::BuildEngine(BuildEngineDelegate& delegate) 1639| | : impl(new BuildEngineImpl(*this, delegate)) 1640| 0|{ 1641| 0|} 1642| | 1643| 0|BuildEngine::~BuildEngine() { 1644| 0| delete static_cast(impl); 1645| 0|} 1646| | 1647| 0|BuildEngineDelegate* BuildEngine::getDelegate() { 1648| 0| return static_cast(impl)->getDelegate(); 1649| 0|} 1650| | 1651| 0|Timestamp BuildEngine::getCurrentTimestamp() { 1652| 0| return static_cast(impl)->getCurrentTimestamp(); 1653| 0|} 1654| | 1655| 0|void BuildEngine::addRule(Rule&& rule) { 1656| 0| static_cast(impl)->addRule(std::move(rule)); 1657| 0|} 1658| | 1659| 0|const ValueType& BuildEngine::build(const KeyType& key) { 1660| 0| return static_cast(impl)->build(key); 1661| 0|} 1662| | 1663| 0|void BuildEngine::cancelBuild() { 1664| 0| return static_cast(impl)->cancelBuild(); 1665| 0|} 1666| | 1667| 0|void BuildEngine::dumpGraphToFile(const std::string& path) { 1668| 0| static_cast(impl)->dumpGraphToFile(path); 1669| 0|} 1670| | 1671| 0|bool BuildEngine::attachDB(std::unique_ptr database, std::string* error_out) { 1672| 0| return static_cast(impl)->attachDB(std::move(database), error_out); 1673| 0|} 1674| | 1675| |bool BuildEngine::enableTracing(const std::string& path, 1676| 0| std::string* error_out) { 1677| 0| return static_cast(impl)->enableTracing(path, error_out); 1678| 0|} 1679| | 1680| 0|Task* BuildEngine::registerTask(Task* task) { 1681| 0| return static_cast(impl)->registerTask(task); 1682| 0|} 1683| | 1684| |void BuildEngine::taskNeedsInput(Task* task, const KeyType& key, 1685| 0| uintptr_t inputID) { 1686| 0| static_cast(impl)->taskNeedsInput(task, key, inputID); 1687| 0|} 1688| | 1689| 0|void BuildEngine::taskDiscoveredDependency(Task* task, const KeyType& key) { 1690| 0| static_cast(impl)->taskDiscoveredDependency(task, key); 1691| 0|} 1692| | 1693| 0|void BuildEngine::taskMustFollow(Task* task, const KeyType& key) { 1694| 0| static_cast(impl)->taskMustFollow(task, key); 1695| 0|} 1696| | 1697| |void BuildEngine::taskIsComplete(Task* task, ValueType&& value, 1698| 0| bool forceChange) { 1699| 0| static_cast(impl)->taskIsComplete(task, std::move(value), 1700| 0| forceChange); 1701| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/BuildEngineTrace.cpp: 1| |//===-- BuildEngineTrace.cpp ----------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "BuildEngineTrace.h" 14| | 15| |#include "llbuild/Core/BuildEngine.h" 16| | 17| |#include 18| |#include 19| |#include 20| | 21| |#include 22| | 23| |using namespace llbuild; 24| |using namespace llbuild::core; 25| | 26| 0|BuildEngineTrace::BuildEngineTrace() {} 27| | 28| 0|BuildEngineTrace::~BuildEngineTrace() {} 29| | 30| |bool BuildEngineTrace::open(const std::string& filename, 31| 0| std::string* error_out) { 32| 0| assert(!isOpen()); 33| 0| 34| 0| FILE *fp = fopen(filename.c_str(), "wb"); 35| 0| if (!fp) { 36| 0| *error_out = "unable to open '" + filename + "' (" + 37| 0| ::strerror(errno) + ")"; 38| 0| return false; 39| 0| } 40| 0| outputPtr = fp; 41| 0| assert(isOpen()); 42| 0| 43| 0| // Write the opening header. 44| 0| fprintf(fp, "[\n"); 45| 0| return true; 46| 0|} 47| | 48| 0|bool BuildEngineTrace::close(std::string* error_out) { 49| 0| assert(isOpen()); 50| 0| 51| 0| FILE *fp = static_cast(outputPtr); 52| 0| 53| 0| // Write the footer. 54| 0| fprintf(fp, "]\n"); 55| 0| 56| 0| bool success = fclose(fp) == 0; 57| 0| outputPtr = nullptr; 58| 0| assert(!isOpen()); 59| 0| 60| 0| if (!success) { 61| 0| *error_out = "unable to close file"; 62| 0| return false; 63| 0| } 64| 0| 65| 0| return true; 66| 0|} 67| | 68| |#pragma mark - Tracing APIs 69| | 70| 0|const char* BuildEngineTrace::getTaskName(const Task* task) { 71| 0| FILE *fp = static_cast(outputPtr); 72| 0| 73| 0| // See if we have already assigned a name. 74| 0| auto it = taskNames.find(task); 75| 0| if (it != taskNames.end()) 76| 0| return it->second.c_str(); 77| 0| 78| 0| // Otherwise, create a name. 79| 0| char name[64]; 80| 0| sprintf(name, "T%d", ++numNamedTasks); 81| 0| auto result = taskNames.emplace(task, name); 82| 0| 83| 0| // Report the newly seen rule. 84| 0| fprintf(fp, "{ \"new-task\", \"%s\" },\n", name); 85| 0| 86| 0| return result.first->second.c_str(); 87| 0|} 88| | 89| 0|const char* BuildEngineTrace::getRuleName(const Rule* rule) { 90| 0| FILE *fp = static_cast(outputPtr); 91| 0| 92| 0| // See if we have already assigned a name. 93| 0| auto it = ruleNames.find(rule); 94| 0| if (it != ruleNames.end()) 95| 0| return it->second.c_str(); 96| 0| 97| 0| // Otherwise, create a name. 98| 0| char name[64]; 99| 0| sprintf(name, "R%d", ++numNamedRules); 100| 0| auto result = ruleNames.emplace(rule, name); 101| 0| 102| 0| // Report the newly seen rule. 103| 0| // FIXME: This is currently encoding the key by merely stripping the 104| 0| // non-printable characters. Should probably encode this into a real encoding. 105| 0| std::string encoded = rule->key; 106| 0| encoded.erase( 107| 0| std::remove_if(encoded.begin(), encoded.end(), 108| 0| [](char c) -> bool { 109| 0| return c < 32 || c > 127; }), 110| 0| encoded.end()); 111| 0| fprintf(fp, "{ \"new-rule\", \"%s\", \"%s\" },\n", name, encoded.c_str()); 112| 0| 113| 0| return result.first->second.c_str(); 114| 0|} 115| | 116| 0|void BuildEngineTrace::buildStarted() { 117| 0| FILE *fp = static_cast(outputPtr); 118| 0| 119| 0| fprintf(fp, "{ \"build-started\" },\n"); 120| 0|} 121| | 122| 0|void BuildEngineTrace::handlingBuildInputRequest(const Rule* rule) { 123| 0| FILE *fp = static_cast(outputPtr); 124| 0| 125| 0| fprintf(fp, "{ \"handling-build-input-request\", \"%s\" },\n", 126| 0| getRuleName(rule)); 127| 0|} 128| | 129| |void BuildEngineTrace::createdTaskForRule(const Task* task, 130| 0| const Rule* rule) { 131| 0| FILE *fp = static_cast(outputPtr); 132| 0| 133| 0| fprintf(fp, "{ \"created-task-for-rule\", \"%s\", \"%s\" },\n", 134| 0| getTaskName(task), getRuleName(rule)); 135| 0|} 136| | 137| |void BuildEngineTrace::handlingTaskInputRequest(const Task* task, 138| 0| const Rule* rule) { 139| 0| FILE *fp = static_cast(outputPtr); 140| 0| 141| 0| fprintf(fp, "{ \"handling-task-input-request\", \"%s\", \"%s\" },\n", 142| 0| getTaskName(task), getRuleName(rule)); 143| 0|} 144| | 145| 0|void BuildEngineTrace::pausedInputRequestForRuleScan(const Rule* rule) { 146| 0| FILE *fp = static_cast(outputPtr); 147| 0| 148| 0| fprintf(fp, "{ \"paused-input-request-for-rule-scan\", \"%s\" },\n", 149| 0| getRuleName(rule)); 150| 0|} 151| | 152| |void BuildEngineTrace::readyingTaskInputRequest(const Task* task, 153| 0| const Rule* rule) { 154| 0| FILE *fp = static_cast(outputPtr); 155| 0| 156| 0| fprintf(fp, "{ \"readying-task-input-request\", \"%s\", \"%s\" },\n", 157| 0| getTaskName(task), getRuleName(rule)); 158| 0|} 159| | 160| |void BuildEngineTrace::addedRulePendingTask(const Rule* rule, 161| 0| const Task* task) { 162| 0| FILE *fp = static_cast(outputPtr); 163| 0| 164| 0| fprintf(fp, "{ \"added-rule-pending-task\", \"%s\", \"%s\" },\n", 165| 0| getRuleName(rule), getTaskName(task)); 166| 0|} 167| | 168| |void BuildEngineTrace::completedTaskInputRequest(const Task* task, 169| 0| const Rule* rule) { 170| 0| FILE *fp = static_cast(outputPtr); 171| 0| 172| 0| fprintf(fp, "{ \"completed-task-input-request\", \"%s\", \"%s\" },\n", 173| 0| getTaskName(task), getRuleName(rule)); 174| 0|} 175| | 176| |void BuildEngineTrace::updatedTaskWaitCount(const Task* task, 177| 0| unsigned waitCount) { 178| 0| FILE *fp = static_cast(outputPtr); 179| 0| 180| 0| fprintf(fp, "{ \"updated-task-wait-count\", \"%s\", %d },\n", 181| 0| getTaskName(task), waitCount); 182| 0|} 183| | 184| 0|void BuildEngineTrace::unblockedTask(const Task* task) { 185| 0| FILE *fp = static_cast(outputPtr); 186| 0| 187| 0| fprintf(fp, "{ \"unblocked-task\", \"%s\" },\n", getTaskName(task)); 188| 0|} 189| | 190| 0|void BuildEngineTrace::readiedTask(const Task* task, const Rule* rule) { 191| 0| FILE *fp = static_cast(outputPtr); 192| 0| 193| 0| fprintf(fp, "{ \"readied-task\", \"%s\", \"%s\" },\n", 194| 0| getTaskName(task), getRuleName(rule)); 195| 0|} 196| | 197| |void BuildEngineTrace::finishedTask(const Task* task, const Rule* rule, 198| 0| bool wasChanged) { 199| 0| FILE *fp = static_cast(outputPtr); 200| 0| 201| 0| fprintf(fp, "{ \"finished-task\", \"%s\", \"%s\", \"%s\" },\n", 202| 0| getTaskName(task), getRuleName(rule), 203| 0| wasChanged ? "changed" : "unchanged"); 204| 0| 205| 0| // Delete the task entry, as it could be reused. 206| 0| taskNames.erase(taskNames.find(task)); 207| 0|} 208| | 209| 0|void BuildEngineTrace::buildEnded() { 210| 0| FILE *fp = static_cast(outputPtr); 211| 0| 212| 0| fprintf(fp, "{ \"build-ended\" },\n"); 213| 0|} 214| | 215| |#pragma mark - Dependency Scanning Tracing APIs 216| | 217| 0|void BuildEngineTrace::checkingRuleNeedsToRun(const Rule* forRule) { 218| 0| FILE *fp = static_cast(outputPtr); 219| 0| 220| 0| fprintf(fp, "{ \"checking-rule-needs-to-run\", \"%s\" },\n", 221| 0| getRuleName(forRule)); 222| 0|} 223| | 224| 0|void BuildEngineTrace::ruleScheduledForScanning(const Rule* forRule) { 225| 0| FILE *fp = static_cast(outputPtr); 226| 0| 227| 0| fprintf(fp, ("{ \"rule-scheduled-for-scanning\", \"%s\"},\n"), 228| 0| getRuleName(forRule)); 229| 0|} 230| | 231| |void BuildEngineTrace::ruleScanningNextInput(const Rule* forRule, 232| 0| const Rule* inputRule) { 233| 0| FILE *fp = static_cast(outputPtr); 234| 0| 235| 0| fprintf(fp, ("{ \"rule-scanning-next-input\", \"%s\", \"%s\" },\n"), 236| 0| getRuleName(forRule), getRuleName(inputRule)); 237| 0|} 238| | 239| |void 240| |BuildEngineTrace::ruleScanningDeferredOnInput(const Rule* forRule, 241| 0| const Rule* inputRule) { 242| 0| FILE *fp = static_cast(outputPtr); 243| 0| 244| 0| fprintf(fp, ("{ \"rule-scanning-deferred-on-input\", \"%s\", \"%s\" },\n"), 245| 0| getRuleName(forRule), getRuleName(inputRule)); 246| 0|} 247| | 248| |void 249| |BuildEngineTrace::ruleScanningDeferredOnTask(const Rule* forRule, 250| 0| const Task* inputTask) { 251| 0| FILE *fp = static_cast(outputPtr); 252| 0| 253| 0| fprintf(fp, ("{ \"rule-scanning-deferred-on-task\", \"%s\", \"%s\" },\n"), 254| 0| getRuleName(forRule), getTaskName(inputTask)); 255| 0|} 256| | 257| 0|void BuildEngineTrace::ruleNeedsToRunBecauseNeverBuilt(const Rule* forRule) { 258| 0| FILE *fp = static_cast(outputPtr); 259| 0| 260| 0| fprintf(fp, "{ \"rule-needs-to-run\", \"%s\", \"never-built\" },\n", 261| 0| getRuleName(forRule)); 262| 0|} 263| | 264| 0|void BuildEngineTrace::ruleNeedsToRunBecauseInvalidValue(const Rule* forRule) { 265| 0| FILE *fp = static_cast(outputPtr); 266| 0| 267| 0| fprintf(fp, "{ \"rule-needs-to-run\", \"%s\", \"invalid-value\" },\n", 268| 0| getRuleName(forRule)); 269| 0|} 270| | 271| |void 272| 0|BuildEngineTrace::ruleNeedsToRunBecauseInputMissing(const Rule* forRule) { 273| 0| FILE *fp = static_cast(outputPtr); 274| 0| 275| 0| fprintf(fp, "{ \"rule-needs-to-run\", \"%s\", \"input-missing\" },\n", 276| 0| getRuleName(forRule)); 277| 0|} 278| | 279| |void 280| |BuildEngineTrace::ruleNeedsToRunBecauseInputRebuilt(const Rule* forRule, 281| 0| const Rule* inputRule) { 282| 0| FILE *fp = static_cast(outputPtr); 283| 0| 284| 0| fprintf(fp, ("{ \"rule-needs-to-run\", \"%s\", " 285| 0| "\"input-rebuilt\", \"%s\" },\n"), 286| 0| getRuleName(forRule), getRuleName(inputRule)); 287| 0|} 288| | 289| 0|void BuildEngineTrace::ruleDoesNotNeedToRun(const Rule* forRule) { 290| 0| FILE *fp = static_cast(outputPtr); 291| 0| 292| 0| fprintf(fp, "{ \"rule-does-not-need-to-run\", \"%s\" },\n", 293| 0| getRuleName(forRule)); 294| 0|} 295| | 296| 0|void BuildEngineTrace::cycleForceRuleNeedsToRun(const Rule* forRule) { 297| 0| FILE *fp = static_cast(outputPtr); 298| 0| 299| 0| fprintf(fp, "{ \"cycle-force-rule-needs-to-run\", \"%s\" },\n", 300| 0| getRuleName(forRule)); 301| 0|} 302| | 303| 0|void BuildEngineTrace::cycleSupplyPriorValue(const Rule* forRule, const Task* toTask) { 304| 0| FILE *fp = static_cast(outputPtr); 305| 0| 306| 0| fprintf(fp, "{ \"cycle-supply-prior-value\", \"%s\", \"%s\" },\n", 307| 0| getRuleName(forRule), getTaskName(toTask)); 308| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/BuildEngineTrace.h: 1| |//===- BuildEngineTrace.h ---------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_BUILDENGINETRACE_H 14| |#define LLBUILD_CORE_BUILDENGINETRACE_H 15| | 16| |#include 17| |#include 18| | 19| |namespace llbuild { 20| |namespace core { 21| | 22| |class Rule; 23| |class Task; 24| | 25| |/// This class assists in writing build engine tracing information to an 26| |/// external log file, suitable for ex post facto debugging and analysis. 27| |class BuildEngineTrace { 28| | /// The output file pointer. 29| | void* outputPtr = nullptr; 30| | 31| | unsigned numNamedTasks = 0; 32| | std::unordered_map taskNames; 33| | unsigned numNamedRules = 0; 34| | std::unordered_map ruleNames; 35| | 36| |private: 37| | const char* getTaskName(const Task*); 38| | const char* getRuleName(const Rule*); 39| | 40| |public: 41| | BuildEngineTrace(); 42| | ~BuildEngineTrace(); 43| | 44| | /// Open an output file for writing, must be called prior to any trace 45| | /// recording, and may only be called once per trace object. 46| | /// 47| | /// \returns True on success. 48| | bool open(const std::string& path, std::string* error_out); 49| | 50| | /// Close the output file; no subsequest trace recording may be done. 51| | /// 52| | /// \returns True on success. 53| | bool close(std::string* error_out); 54| | 55| | /// Check if the trace output is open. 56| 0| bool isOpen() const { return outputPtr != nullptr; } 57| | 58| | /// @name Trace Recording APIs 59| | /// @{ 60| | 61| | /// @name Core Engine Operation 62| | /// @{ 63| | 64| | void buildStarted(); 65| | void handlingBuildInputRequest(const Rule* rule); 66| | void createdTaskForRule(const Task* task, const Rule* rule); 67| | void handlingTaskInputRequest(const Task* task, const Rule* rule); 68| | void pausedInputRequestForRuleScan(const Rule* rule); 69| | void readyingTaskInputRequest(const Task* task, const Rule* rule); 70| | void addedRulePendingTask(const Rule* rule, const Task* task); 71| | void completedTaskInputRequest(const Task* task, const Rule* rule); 72| | void updatedTaskWaitCount(const Task* task, unsigned waitCount); 73| | void unblockedTask(const Task* task); 74| | void readiedTask(const Task* task, const Rule* rule); 75| | void finishedTask(const Task* task, const Rule* rule, bool wasChanged); 76| | void buildEnded(); 77| | 78| | /// @} 79| | 80| | /// @name Dependency Checking 81| | /// @{ 82| | 83| | void checkingRuleNeedsToRun(const Rule* forRule); 84| | void ruleScheduledForScanning(const Rule* forRule); 85| | void ruleScanningNextInput(const Rule* forRule, const Rule* inputRule); 86| | void ruleScanningDeferredOnInput(const Rule* forRule, 87| | const Rule* inputRule); 88| | void ruleScanningDeferredOnTask(const Rule* forRule, 89| | const Task* inputTask); 90| | void ruleNeedsToRunBecauseNeverBuilt(const Rule* forRule); 91| | void ruleNeedsToRunBecauseInvalidValue(const Rule* forRule); 92| | void ruleNeedsToRunBecauseInputMissing(const Rule* forRule); 93| | void ruleNeedsToRunBecauseInputRebuilt(const Rule* forRule, 94| | const Rule* inputRule); 95| | void ruleDoesNotNeedToRun(const Rule* forRule); 96| | 97| | /// @} 98| | 99| | /// @name Cycle Resolution 100| | /// @{ 101| | 102| | void cycleForceRuleNeedsToRun(const Rule* forRule); 103| | void cycleSupplyPriorValue(const Rule* forRule, const Task* toTask); 104| | 105| | /// @} 106| | 107| | /// @} 108| |}; 109| | 110| |} 111| |} 112| | 113| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/DependencyInfoParser.cpp: 1| |//===-- DependencyInfoParser.cpp ------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Core/DependencyInfoParser.h" 14| | 15| |using namespace llbuild; 16| |using namespace llbuild::core; 17| | 18| 0|DependencyInfoParser::ParseActions::~ParseActions() {} 19| | 20| |#pragma mark - DependencyInfoParser Implementation 21| | 22| |namespace { 23| | 24| |// This format isn't really documented anywhere other than the ld64 source, 25| |// see, e.g.: 26| |// 27| |// http://www.opensource.apple.com/source/ld64/ld64-253.3/src/ld/Options.h 28| |// 29| |// and: 30| |// 31| |// http://www.opensource.apple.com/source/ld64/ld64-253.3/src/ld/Options.cpp 32| | 33| |// The format itself is very simple, it is just a sequence of (, 34| |// ). The version record is required to be the first version 35| |// in the file. 36| | 37| |/// The known set of opcodes. 38| |enum class Opcode : uint8_t { 39| | /// Version information of the producer. 40| | Version = 0x00, 41| | 42| | /// An input path. 43| | Input = 0x10, 44| | 45| | /// A missing file. 46| | Missing = 0x11, 47| | 48| | /// An output path, 49| | Output = 0x40, 50| |}; 51| | 52| |} 53| | 54| 0|void DependencyInfoParser::parse() { 55| 0| // Validate that the file ends with a null byte, if not it is malformed and we 56| 0| // just bail on parsing. 57| 0| if (!data.endswith(StringRef("\0", 1))) { 58| 0| actions.error("missing null terminator", data.size()); 59| 0| return; 60| 0| } 61| 0| 62| 0| // Validate that the file starts with the version record. 63| 0| if (Opcode(data[0]) != Opcode::Version) { 64| 0| actions.error("missing version record", 0); 65| 0| return; 66| 0| } 67| 0| 68| 0| // Parse the records in turn. 69| 0| const char* cur = data.begin(); 70| 0| const char* end = data.end(); 71| 0| while (cur != end) { 72| 0| const char* opcodeStart = cur; 73| 0| auto opcode = Opcode(*cur++); 74| 0| const char* operandStart = cur; 75| 0| while (*cur != '\0') { 76| 0| ++cur; 77| 0| // We require the file have a terminating null, so we can never scan past 78| 0| // the end. 79| 0| assert (cur < end); 80| 0| } 81| 0| const char* operandEnd = cur; 82| 0| assert(*operandEnd == '\x00' && cur < end); 83| 0| ++cur; 84| 0| 85| 0| // Diagnose empty operands (missing isn't possible. 86| 0| auto operand = StringRef(operandStart, operandEnd - operandStart); 87| 0| if (operand.empty()) { 88| 0| actions.error("empty operand", opcodeStart - data.data()); 89| 0| break; 90| 0| } 91| 0| 92| 0| // Handle the opcode. 93| 0| switch (opcode) { 94| 0| case Opcode::Version: { 95| 0| // Diagnose duplicate version records. 96| 0| if (opcodeStart != data.begin()) { 97| 0| actions.error("invalid duplicate version", opcodeStart - data.data()); 98| 0| break; 99| 0| } 100| 0| actions.actOnVersion(operand); 101| 0| break; 102| 0| } 103| 0| 104| 0| case Opcode::Input: { 105| 0| actions.actOnInput(operand); 106| 0| break; 107| 0| } 108| 0| 109| 0| case Opcode::Missing: { 110| 0| actions.actOnMissing(operand); 111| 0| break; 112| 0| } 113| 0| 114| 0| case Opcode::Output: { 115| 0| actions.actOnOutput(operand); 116| 0| break; 117| 0| } 118| 0| 119| 0| default: 120| 0| actions.error("unknown opcode in file", opcodeStart - data.data()); 121| 0| break; 122| 0| } 123| 0| } 124| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/MakefileDepsParser.cpp: 1| |//===-- MakefileDepsParser.cpp --------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Core/MakefileDepsParser.h" 14| | 15| |#include "llvm/ADT/SmallString.h" 16| | 17| |using namespace llvm; 18| |using namespace llbuild; 19| |using namespace llbuild::core; 20| | 21| 0|MakefileDepsParser::ParseActions::~ParseActions() {} 22| | 23| |#pragma mark - MakefileDepsParser Implementation 24| | 25| 0|static bool isWordChar(int c) { 26| 0| switch (c) { 27| 0| case '\0': 28| 0| case '\t': 29| 0| case '\n': 30| 0| case ' ': 31| 0| case '$': 32| 0| case ':': 33| 0| return false; 34| 0| default: 35| 0| return true; 36| 0| } 37| 0|} 38| | 39| 0|static void skipWhitespaceAndComments(const char*& cur, const char* end) { 40| 0| for (; cur != end; ++cur) { 41| 0| int c = *cur; 42| 0| 43| 0| // Skip comments. 44| 0| if (c == '#') { 45| 0| // Skip to the next newline. 46| 0| while (cur + 1 != end && cur[1] == '\n') 47| 0| ++cur; 48| 0| continue; 49| 0| } 50| 0| 51| 0| if (c == ' ' || c == '\t' || c == '\n') 52| 0| continue; 53| 0| 54| 0| break; 55| 0| } 56| 0|} 57| | 58| 0|static void skipNonNewlineWhitespace(const char*& cur, const char* end) { 59| 0| for (; cur != end; ++cur) { 60| 0| int c = *cur; 61| 0| 62| 0| // Skip regular whitespace. 63| 0| if (c == ' ' || c == '\t') 64| 0| continue; 65| 0| 66| 0| // If this is an escaped newline, also skip it. 67| 0| if (c == '\\' && cur + 1 != end && cur[1] == '\n') { 68| 0| ++cur; 69| 0| continue; 70| 0| } 71| 0| 72| 0| // Otherwise, stop scanning. 73| 0| break; 74| 0| } 75| 0|} 76| | 77| 0|static void skipToEndOfLine(const char*& cur, const char* end) { 78| 0| for (; cur != end; ++cur) { 79| 0| int c = *cur; 80| 0| 81| 0| if (c == '\n') { 82| 0| ++cur; 83| 0| break; 84| 0| } 85| 0| } 86| 0|} 87| | 88| |static void lexWord(const char*& cur, const char* end, 89| 0| SmallVectorImpl &unescapedWord) { 90| 0| for (; cur != end; ++cur) { 91| 0| int c = *cur; 92| 0| 93| 0| // Check if this is an escape sequence. 94| 0| if (c == '\\') { 95| 0| // If this is a line continuation, it ends the word. 96| 0| if (cur + 1 != end && cur[1] == '\n') 97| 0| break; 98| 0| 99| 0| // Otherwise, skip the escaped character. 100| 0| ++cur; 101| 0| int c = *cur; 102| 0| 103| 0| // Honor the escaping rules as generated by Clang and GCC, which are *not 104| 0| // necessarily* the actual escaping rules of BSD Make or GNU Make. Due to 105| 0| // incompatibilities in the escape syntax between those two makes, and the 106| 0| // GNU make behavior of retrying an escaped string with the original 107| 0| // input, GCC/Clang adopt a strategy around escaping ' ' and '#', but not 108| 0| // r"\\" itself, or any other characters. However, there are some 109| 0| // situations where Clang *will* generate an escaped '\\' using the 110| 0| // r"\\\\" sequence, so we also honor that. 111| 0| // 112| 0| // FIXME: Make this more complete, or move to a better dependency format. 113| 0| if (c == ' ' || c == '#' || c == '\\') { 114| 0| unescapedWord.push_back(c); 115| 0| } else { 116| 0| unescapedWord.push_back('\\'); 117| 0| unescapedWord.push_back(c); 118| 0| } 119| 0| continue; 120| 0| } else if (c == '$' && cur + 1 != end && cur[1] == '$') { 121| 0| // "$$" is an escaped '$'. 122| 0| unescapedWord.push_back(c); 123| 0| ++cur; 124| 0| continue; 125| 0| } 126| 0| 127| 0| // Otherwise, if this is not a valid word character then skip it. 128| 0| if (!isWordChar(c)) 129| 0| break; 130| 0| unescapedWord.push_back(c); 131| 0| } 132| 0|} 133| | 134| 0|void MakefileDepsParser::parse() { 135| 0| const char* cur = data; 136| 0| const char* end = data + length; 137| 0| // Storage for currently begin lexed unescaped word. 138| 0| SmallString<256> unescapedWord; 139| 0| 140| 0| // While we have input data... 141| 0| while (cur != end) { 142| 0| // Skip leading whitespace and comments. 143| 0| skipWhitespaceAndComments(cur, end); 144| 0| 145| 0| // If we have reached the end of the input, we are done. 146| 0| if (cur == end) 147| 0| break; 148| 0| 149| 0| // The next token should be a word. 150| 0| const char* wordStart = cur; 151| 0| unescapedWord.clear(); 152| 0| lexWord(cur, end, unescapedWord); 153| 0| if (cur == wordStart) { 154| 0| actions.error("unexpected character in file", cur - data); 155| 0| skipToEndOfLine(cur, end); 156| 0| continue; 157| 0| } 158| 0| actions.actOnRuleStart(wordStart, cur - wordStart, unescapedWord.str()); 159| 0| 160| 0| // The next token should be a colon. 161| 0| skipNonNewlineWhitespace(cur, end); 162| 0| if (cur == end || *cur != ':') { 163| 0| actions.error("missing ':' following rule", cur - data); 164| 0| actions.actOnRuleEnd(); 165| 0| skipToEndOfLine(cur, end); 166| 0| continue; 167| 0| } 168| 0| 169| 0| // Skip the colon. 170| 0| ++cur; 171| 0| 172| 0| // Consume dependency words until we reach the end of a line. 173| 0| while (cur != end) { 174| 0| // Skip forward and check for EOL. 175| 0| skipNonNewlineWhitespace(cur, end); 176| 0| if (cur == end || *cur == '\n') 177| 0| break; 178| 0| 179| 0| // Otherwise, we should have a word. 180| 0| const char* wordStart = cur; 181| 0| unescapedWord.clear(); 182| 0| lexWord(cur, end, unescapedWord); 183| 0| if (cur == wordStart) { 184| 0| actions.error("unexpected character in prerequisites", cur - data); 185| 0| skipToEndOfLine(cur, end); 186| 0| continue; 187| 0| } 188| 0| // Given that GCC/Clang generally do not escape any special characters in 189| 0| // paths, we may encounter paths that contain them. Our lexer 190| 0| // automatically stops on some such characters, namely ':'. If the we find 191| 0| // a ':' at this point, we push it onto the word and continue lexing. 192| 0| while (cur != end && *cur == ':') { 193| 0| unescapedWord.push_back(*cur); 194| 0| ++cur; 195| 0| lexWord(cur, end, unescapedWord); 196| 0| } 197| 0| actions.actOnRuleDependency(wordStart, cur - wordStart, 198| 0| unescapedWord.str()); 199| 0| } 200| 0| actions.actOnRuleEnd(); 201| 0| } 202| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/SQLiteBuildDB.cpp: 1| |//===-- SQLiteBuildDB.cpp -------------------------------------------------===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#include "llbuild/Core/BuildDB.h" 14| | 15| |#include "llbuild/Basic/BinaryCoding.h" 16| |#include "llbuild/Basic/PlatformUtility.h" 17| |#include "llbuild/Core/BuildEngine.h" 18| | 19| |#include "llvm/ADT/DenseMap.h" 20| |#include "llvm/ADT/STLExtras.h" 21| |#include "llvm/Support/raw_ostream.h" 22| | 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |#include 29| | 30| |using namespace llbuild; 31| |using namespace llbuild::core; 32| | 33| |// SQLite BuildDB Implementation 34| | 35| |/// Internal key ID type used for linking rule dependencies. Related to, but 36| |/// distinct from the build engine's KeyID type. 37| |struct DBKeyID { 38| | uint64_t value = 0; 39| | 40| 0| DBKeyID() { ; } 41| | DBKeyID(const DBKeyID&) = default; 42| 0| explicit DBKeyID(uint64_t value) : value(value) { ; } 43| |}; 44| | 45| |// Provide DenseMapInfo for DBKeyID. 46| |template<> struct ::llvm::DenseMapInfo { 47| 0| static inline DBKeyID getEmptyKey() { return DBKeyID(~0ULL); } 48| 0| static inline DBKeyID getTombstoneKey() { return DBKeyID(~0ULL - 1ULL); } 49| 0| static unsigned getHashValue(const DBKeyID& Val) { 50| 0| return (unsigned)(Val.value * 37ULL); 51| 0| } 52| 0| static bool isEqual(const DBKeyID& LHS, const DBKeyID& RHS) { 53| 0| return LHS.value == RHS.value; 54| 0| } 55| |}; 56| | 57| |// Helper macro checking and returning error messages for failed SQLite calls 58| 0|#define checkSQLiteResultOKReturnFalse(result) \ 59| 0|if (result != SQLITE_OK) { \ 60| 0| *error_out = getCurrentErrorMessage(); \ 61| 0| return false; \ 62| 0|} 63| | 64| | 65| |namespace { 66| | 67| |class SQLiteBuildDB : public BuildDB { 68| | /// Version History: 69| | /// * 9: Add filtered directory contents, related build key changes 70| | /// * 8: Remove ID from rule results 71| | /// * 7: De-normalized the rule result dependencies. 72| | /// * 6: Added `ordinal` field for dependencies. 73| | /// * 5: Switched to using `WITHOUT ROWID` for dependencies. 74| | /// * 4: Pre-history 75| | static const int currentSchemaVersion = 9; 76| | 77| | std::string path; 78| | uint32_t clientSchemaVersion; 79| | 80| | sqlite3 *db = nullptr; 81| | 82| | /// The mutex to protect all access to the database and statements. 83| | std::mutex dbMutex; 84| | 85| | /// The delegate pointer 86| | BuildDBDelegate* delegate = nullptr; 87| | 88| 0| std::string getCurrentErrorMessage() { 89| 0| int err_code = sqlite3_errcode(db); 90| 0| const char* err_message = sqlite3_errmsg(db); 91| 0| const char* filename = sqlite3_db_filename(db, "main"); 92| 0| 93| 0| std::string out; 94| 0| llvm::raw_string_ostream outStream(out); 95| 0| outStream << "error: accessing build database \"" << filename << "\": " << err_message; 96| 0| 97| 0| if (err_code == SQLITE_BUSY || err_code == SQLITE_LOCKED) { 98| 0| outStream << " Possibly there are two concurrent builds running in the same filesystem location."; 99| 0| } 100| 0| 101| 0| outStream.flush(); 102| 0| return out; 103| 0| } 104| | 105| 0| bool open(std::string *error_out) { 106| 0| // The db is opened lazily whenever an operation on it occurs. Thus if it is 107| 0| // already open, we don't need to do any further work. 108| 0| if (db) return true; 109| 0| 110| 0| // Configure SQLite3 on first use. 111| 0| // 112| 0| // We attempt to set multi-threading mode, but can settle for serialized if 113| 0| // the library can't be reinitialized (there are only two modes). 114| 0| static int sqliteConfigureResult = []() -> int { 115| 0| // We access a single connection from multiple threads. 116| 0| return sqlite3_config(SQLITE_CONFIG_MULTITHREAD); 117| 0| }(); 118| 0| if (sqliteConfigureResult != SQLITE_OK) { 119| 0| if (!sqlite3_threadsafe()) { 120| 0| *error_out = "unable to configure database: not thread-safe"; 121| 0| return false; 122| 0| } 123| 0| } 124| 0| 125| 0| int result = sqlite3_open(path.c_str(), &db); 126| 0| if (result != SQLITE_OK) { 127| 0| *error_out = "unable to open database: " + std::string( 128| 0| sqlite3_errstr(result)); 129| 0| return false; 130| 0| } 131| 0| 132| 0| sqlite3_busy_timeout(db, 5000); 133| 0| // Create the database schema, if necessary. 134| 0| char *cError; 135| 0| int version; 136| 0| uint32_t clientVersion = 0; 137| 0| sqlite3_stmt* stmt; 138| 0| result = sqlite3_prepare_v2( 139| 0| db, "SELECT version,client_version FROM info LIMIT 1", 140| 0| -1, &stmt, nullptr); 141| 0| if (result == SQLITE_ERROR) { 142| 0| version = -1; 143| 0| } else { 144| 0| if (result != SQLITE_OK) { 145| 0| *error_out = getCurrentErrorMessage(); 146| 0| return false; 147| 0| } 148| 0| result = sqlite3_step(stmt); 149| 0| if (result == SQLITE_DONE) { 150| 0| version = -1; 151| 0| } else if (result == SQLITE_ROW) { 152| 0| assert(sqlite3_column_count(stmt) == 2); 153| 0| version = sqlite3_column_int(stmt, 0); 154| 0| clientVersion = sqlite3_column_int(stmt, 1); 155| 0| } else { 156| 0| *error_out = getCurrentErrorMessage(); 157| 0| return false; 158| 0| } 159| 0| sqlite3_finalize(stmt); 160| 0| } 161| 0| 162| 0| if (version != currentSchemaVersion || 163| 0| clientVersion != clientSchemaVersion) { 164| 0| // Close the database before we try to recreate it. 165| 0| sqlite3_close(db); 166| 0| 167| 0| // Always recreate the database from scratch when the schema changes. 168| 0| result = basic::sys::unlink(path.c_str()); 169| 0| if (result == -1) { 170| 0| if (errno != ENOENT) { 171| 0| *error_out = std::string("unable to unlink existing database: ") + 172| 0| ::strerror(errno); 173| 0| sqlite3_close(db); 174| 0| return false; 175| 0| } 176| 0| } else { 177| 0| // If the remove was successful, reopen the database. 178| 0| int result = sqlite3_open(path.c_str(), &db); 179| 0| if (result != SQLITE_OK) { 180| 0| *error_out = getCurrentErrorMessage(); 181| 0| return false; 182| 0| } 183| 0| } 184| 0| 185| 0| // Create the schema in a single transaction. 186| 0| result = sqlite3_exec(db, "BEGIN EXCLUSIVE;", nullptr, nullptr, &cError); 187| 0| 188| 0| // Create the info table. 189| 0| if (result == SQLITE_OK) { 190| 0| result = sqlite3_exec( 191| 0| db, ("CREATE TABLE info (" 192| 0| "id INTEGER PRIMARY KEY, " 193| 0| "version INTEGER, " 194| 0| "client_version INTEGER, " 195| 0| "iteration INTEGER);"), 196| 0| nullptr, nullptr, &cError); 197| 0| } 198| 0| if (result == SQLITE_OK) { 199| 0| char* query = sqlite3_mprintf( 200| 0| "INSERT INTO info VALUES (0, %d, %d, 0);", 201| 0| currentSchemaVersion, clientSchemaVersion); 202| 0| result = sqlite3_exec(db, query, nullptr, nullptr, &cError); 203| 0| sqlite3_free(query); 204| 0| } 205| 0| if (result == SQLITE_OK) { 206| 0| result = sqlite3_exec( 207| 0| db, ("CREATE TABLE key_names (" 208| 0| "id INTEGER PRIMARY KEY, " 209| 0| "key STRING UNIQUE);"), 210| 0| nullptr, nullptr, &cError); 211| 0| } 212| 0| if (result == SQLITE_OK) { 213| 0| result = sqlite3_exec( 214| 0| db, ("CREATE TABLE rule_results (" 215| 0| "key_id INTEGER PRIMARY KEY, " 216| 0| "value BLOB, " 217| 0| "built_at INTEGER, " 218| 0| "computed_at INTEGER, " 219| 0| "dependencies BLOB, " 220| 0| "FOREIGN KEY(key_id) REFERENCES key_names(id));"), 221| 0| nullptr, nullptr, &cError); 222| 0| } 223| 0| 224| 0| // Create the indices on the rule tables. 225| 0| if (result == SQLITE_OK) { 226| 0| // Create an index to be used for efficiently looking up rule 227| 0| // information from a key. 228| 0| result = sqlite3_exec( 229| 0| db, "CREATE UNIQUE INDEX rule_results_idx ON rule_results (key_id);", 230| 0| nullptr, nullptr, &cError); 231| 0| } 232| 0| 233| 0| // Sync changes to disk. 234| 0| if (result == SQLITE_OK) { 235| 0| result = sqlite3_exec(db, "END;", nullptr, nullptr, &cError); 236| 0| } 237| 0| 238| 0| if (result != SQLITE_OK) { 239| 0| *error_out = (std::string("unable to initialize database (") + cError 240| 0| + ")"); 241| 0| sqlite3_free(cError); 242| 0| sqlite3_close(db); 243| 0| return false; 244| 0| } 245| 0| } 246| 0| 247| 0| // Initialize prepared statements. 248| 0| result = sqlite3_prepare_v2( 249| 0| db, findKeyIDForKeyStmtSQL, 250| 0| -1, &findKeyIDForKeyStmt, nullptr); 251| 0| checkSQLiteResultOKReturnFalse(result); 252| 0| 253| 0| result = sqlite3_prepare_v2( 254| 0| db, findKeyNameForKeyIDStmtSQL, 255| 0| -1, &findKeyNameForKeyIDStmt, nullptr); 256| 0| checkSQLiteResultOKReturnFalse(result); 257| 0| 258| 0| result = sqlite3_prepare_v2( 259| 0| db, insertIntoKeysStmtSQL, 260| 0| -1, &insertIntoKeysStmt, nullptr); 261| 0| checkSQLiteResultOKReturnFalse(result); 262| 0| 263| 0| result = sqlite3_prepare_v2( 264| 0| db, insertIntoRuleResultsStmtSQL, 265| 0| -1, &insertIntoRuleResultsStmt, nullptr); 266| 0| checkSQLiteResultOKReturnFalse(result); 267| 0| 268| 0| result = sqlite3_prepare_v2( 269| 0| db, deleteFromKeysStmtSQL, 270| 0| -1, &deleteFromKeysStmt, nullptr); 271| 0| checkSQLiteResultOKReturnFalse(result); 272| 0| 273| 0| result = sqlite3_prepare_v2( 274| 0| db, findRuleResultStmtSQL, 275| 0| -1, &findRuleResultStmt, nullptr); 276| 0| checkSQLiteResultOKReturnFalse(result); 277| 0| 278| 0| result = sqlite3_prepare_v2( 279| 0| db, fastFindRuleResultStmtSQL, 280| 0| -1, &fastFindRuleResultStmt, nullptr); 281| 0| checkSQLiteResultOKReturnFalse(result); 282| 0| 283| 0| return true; 284| 0| } 285| | 286| 0| void close() { 287| 0| if (!db) return; 288| 0| 289| 0| // Destroy prepared statements. 290| 0| sqlite3_finalize(findKeyIDForKeyStmt); 291| 0| findKeyIDForKeyStmt = nullptr; 292| 0| sqlite3_finalize(findKeyNameForKeyIDStmt); 293| 0| findKeyNameForKeyIDStmt = nullptr; 294| 0| sqlite3_finalize(findRuleResultStmt); 295| 0| findRuleResultStmt = nullptr; 296| 0| sqlite3_finalize(fastFindRuleResultStmt); 297| 0| fastFindRuleResultStmt = nullptr; 298| 0| sqlite3_finalize(deleteFromKeysStmt); 299| 0| deleteFromKeysStmt = nullptr; 300| 0| sqlite3_finalize(insertIntoKeysStmt); 301| 0| insertIntoKeysStmt = nullptr; 302| 0| sqlite3_finalize(insertIntoRuleResultsStmt); 303| 0| insertIntoRuleResultsStmt = nullptr; 304| 0| 305| 0| sqlite3_close(db); 306| 0| db = nullptr; 307| 0| } 308| | 309| |public: 310| | SQLiteBuildDB(StringRef path, uint32_t clientSchemaVersion) 311| 0| : path(path), clientSchemaVersion(clientSchemaVersion) { } 312| | 313| 0| virtual ~SQLiteBuildDB() { 314| 0| std::lock_guard guard(dbMutex); 315| 0| if (db) 316| 0| close(); 317| 0| } 318| | 319| | /// @name BuildDB API 320| | /// @{ 321| | 322| 0| virtual void attachDelegate(BuildDBDelegate* delegate) override { 323| 0| this->delegate = delegate; 324| 0| } 325| | 326| 0| virtual uint64_t getCurrentIteration(bool* success_out, std::string *error_out) override { 327| 0| std::lock_guard guard(dbMutex); 328| 0| 329| 0| if (!open(error_out)) { 330| 0| *success_out = false; 331| 0| return 0; 332| 0| } 333| 0| 334| 0| // Fetch the iteration from the info table. 335| 0| sqlite3_stmt* stmt; 336| 0| int result; 337| 0| result = sqlite3_prepare_v2( 338| 0| db, "SELECT iteration FROM info LIMIT 1", 339| 0| -1, &stmt, nullptr); 340| 0| if (result != SQLITE_OK) { 341| 0| *success_out = false; 342| 0| *error_out = getCurrentErrorMessage(); 343| 0| return 0; 344| 0| } 345| 0| 346| 0| result = sqlite3_step(stmt); 347| 0| if (result != SQLITE_ROW) { 348| 0| *success_out = false; 349| 0| *error_out = getCurrentErrorMessage(); 350| 0| return 0; 351| 0| } 352| 0| 353| 0| assert(sqlite3_column_count(stmt) == 1); 354| 0| uint64_t iteration = sqlite3_column_int64(stmt, 0); 355| 0| 356| 0| sqlite3_finalize(stmt); 357| 0| 358| 0| *success_out = true; 359| 0| return iteration; 360| 0| } 361| | 362| 0| virtual bool setCurrentIteration(uint64_t value, std::string *error_out) override { 363| 0| std::lock_guard guard(dbMutex); 364| 0| 365| 0| if (!open(error_out)) { 366| 0| return false; 367| 0| } 368| 0| 369| 0| sqlite3_stmt* stmt; 370| 0| int result; 371| 0| result = sqlite3_prepare_v2( 372| 0| db, "UPDATE info SET iteration = ? WHERE id == 0;", 373| 0| -1, &stmt, nullptr); 374| 0| checkSQLiteResultOKReturnFalse(result); 375| 0| result = sqlite3_bind_int64(stmt, /*index=*/1, value); 376| 0| checkSQLiteResultOKReturnFalse(result); 377| 0| 378| 0| result = sqlite3_step(stmt); 379| 0| if (result != SQLITE_DONE) { 380| 0| *error_out = getCurrentErrorMessage(); 381| 0| return false; 382| 0| } 383| 0| 384| 0| sqlite3_finalize(stmt); 385| 0| return true; 386| 0| } 387| | 388| | static constexpr const char *deleteFromKeysStmtSQL = ( 389| | "DELETE FROM key_names WHERE key == ?;"); 390| | sqlite3_stmt* deleteFromKeysStmt = nullptr; 391| | 392| | // Although we have the engine's KeyID, we explictly use the key itself to 393| | // do the mapping via a table join. This is substantially more performant when 394| | // running an initial full build against empty tables. It is also essentially 395| | // equivalent to the mapping we would have to do for the DBKeyID, but defers 396| | // the creation of new IDs until we actually need them in setRuleResult(). 397| | static constexpr const char *findRuleResultStmtSQL = ( 398| | "SELECT rule_results.key_id, value, built_at, computed_at, dependencies FROM rule_results " 399| | "INNER JOIN key_names ON key_names.id = rule_results.key_id WHERE key == ?;"); 400| | sqlite3_stmt* findRuleResultStmt = nullptr; 401| | 402| | // Fast path find result for rules we already know they ID for 403| | static constexpr const char *fastFindRuleResultStmtSQL = ( 404| | "SELECT key_id, value, built_at, computed_at, dependencies FROM rule_results " 405| | "WHERE key_id == ?;"); 406| | sqlite3_stmt* fastFindRuleResultStmt = nullptr; 407| | 408| | virtual bool lookupRuleResult(KeyID keyID, const Rule& rule, 409| | Result* result_out, 410| 0| std::string *error_out) override { 411| 0| assert(delegate != nullptr); 412| 0| std::lock_guard guard(dbMutex); 413| 0| assert(result_out->builtAt == 0); 414| 0| 415| 0| if (!open(error_out)) { 416| 0| return false; 417| 0| } 418| 0| 419| 0| // Fetch the basic rule information. 420| 0| int result; 421| 0| int numDependencyBytes = 0; 422| 0| const void* dependencyBytes = nullptr; 423| 0| DBKeyID dbKeyID; 424| 0| 425| 0| // Check if we already have the key mapping 426| 0| auto it = dbKeyIDs.find(keyID); 427| 0| if (it != dbKeyIDs.end()) { 428| 0| // DBKeyID is known, perform the fast path that avoids table joining 429| 0| 430| 0| result = sqlite3_reset(fastFindRuleResultStmt); 431| 0| checkSQLiteResultOKReturnFalse(result); 432| 0| result = sqlite3_clear_bindings(fastFindRuleResultStmt); 433| 0| checkSQLiteResultOKReturnFalse(result); 434| 0| result = sqlite3_bind_int64(fastFindRuleResultStmt, /*index=*/1, 435| 0| it->second.value); 436| 0| checkSQLiteResultOKReturnFalse(result); 437| 0| 438| 0| // If the rule wasn't found, we are done. 439| 0| result = sqlite3_step(fastFindRuleResultStmt); 440| 0| if (result == SQLITE_DONE) 441| 0| return false; 442| 0| if (result != SQLITE_ROW) { 443| 0| *error_out = getCurrentErrorMessage(); 444| 0| return false; 445| 0| } 446| 0| 447| 0| // Otherwise, read the result contents from the row. 448| 0| assert(sqlite3_column_count(fastFindRuleResultStmt) == 5); 449| 0| dbKeyID = DBKeyID(sqlite3_column_int64(fastFindRuleResultStmt, 0)); 450| 0| int numValueBytes = sqlite3_column_bytes(fastFindRuleResultStmt, 1); 451| 0| result_out->value.resize(numValueBytes); 452| 0| memcpy(result_out->value.data(), 453| 0| sqlite3_column_blob(fastFindRuleResultStmt, 1), 454| 0| numValueBytes); 455| 0| result_out->builtAt = sqlite3_column_int64(fastFindRuleResultStmt, 2); 456| 0| result_out->computedAt = sqlite3_column_int64(fastFindRuleResultStmt, 3); 457| 0| 458| 0| // Extract the dependencies binary blob. 459| 0| numDependencyBytes = sqlite3_column_bytes(fastFindRuleResultStmt, 4); 460| 0| dependencyBytes = sqlite3_column_blob(fastFindRuleResultStmt, 4); 461| 0| } else { 462| 0| // KeyID is not known, perform the 'normal' search using the key value 463| 0| 464| 0| result = sqlite3_reset(findRuleResultStmt); 465| 0| checkSQLiteResultOKReturnFalse(result); 466| 0| result = sqlite3_clear_bindings(findRuleResultStmt); 467| 0| checkSQLiteResultOKReturnFalse(result); 468| 0| result = sqlite3_bind_text(findRuleResultStmt, /*index=*/1, 469| 0| rule.key.data(), rule.key.size(), 470| 0| SQLITE_STATIC); 471| 0| checkSQLiteResultOKReturnFalse(result); 472| 0| 473| 0| // If the rule wasn't found, we are done. 474| 0| result = sqlite3_step(findRuleResultStmt); 475| 0| if (result == SQLITE_DONE) 476| 0| return false; 477| 0| if (result != SQLITE_ROW) { 478| 0| *error_out = getCurrentErrorMessage(); 479| 0| return false; 480| 0| } 481| 0| 482| 0| // Otherwise, read the result contents from the row. 483| 0| assert(sqlite3_column_count(findRuleResultStmt) == 5); 484| 0| dbKeyID = DBKeyID(sqlite3_column_int64(findRuleResultStmt, 0)); 485| 0| int numValueBytes = sqlite3_column_bytes(findRuleResultStmt, 1); 486| 0| result_out->value.resize(numValueBytes); 487| 0| memcpy(result_out->value.data(), 488| 0| sqlite3_column_blob(findRuleResultStmt, 1), 489| 0| numValueBytes); 490| 0| result_out->builtAt = sqlite3_column_int64(findRuleResultStmt, 2); 491| 0| result_out->computedAt = sqlite3_column_int64(findRuleResultStmt, 3); 492| 0| 493| 0| // Cache the engine key mapping 494| 0| engineKeyIDs[dbKeyID] = keyID; 495| 0| dbKeyIDs[keyID] = dbKeyID; 496| 0| 497| 0| // Extract the dependencies binary blob. 498| 0| numDependencyBytes = sqlite3_column_bytes(findRuleResultStmt, 4); 499| 0| dependencyBytes = sqlite3_column_blob(findRuleResultStmt, 4); 500| 0| } 501| 0| 502| 0| 503| 0| int numDependencies = numDependencyBytes / sizeof(uint64_t); 504| 0| if (numDependencyBytes != numDependencies * sizeof(uint64_t)) { 505| 0| *error_out = (llvm::Twine("unexpected contents for database result: ") + 506| 0| llvm::Twine((int)dbKeyID.value)).str(); 507| 0| return false; 508| 0| } 509| 0| result_out->dependencies.resize(numDependencies); 510| 0| basic::BinaryDecoder decoder( 511| 0| StringRef((const char*)dependencyBytes, numDependencyBytes)); 512| 0| for (auto i = 0; i != numDependencies; ++i) { 513| 0| DBKeyID dbKeyID; 514| 0| decoder.read(dbKeyID.value); 515| 0| 516| 0| // Map the database key ID into an engine key ID (note that we already 517| 0| // hold the dbMutex at this point as required by getKeyIDforID()) 518| 0| KeyID keyID = getKeyIDForID(dbKeyID, error_out); 519| 0| if (!error_out->empty()) { 520| 0| return false; 521| 0| } 522| 0| result_out->dependencies[i] = keyID; 523| 0| } 524| 0| 525| 0| return true; 526| 0| } 527| | 528| | static constexpr const char *insertIntoRuleResultsStmtSQL = 529| | "INSERT OR REPLACE INTO rule_results VALUES (?, ?, ?, ?, ?);"; 530| | sqlite3_stmt* insertIntoRuleResultsStmt = nullptr; 531| | 532| | static constexpr const char *findKeyIDForKeyStmtSQL = ( 533| | "SELECT id FROM key_names " 534| | "WHERE key == ? LIMIT 1;"); 535| | sqlite3_stmt* findKeyIDForKeyStmt = nullptr; 536| | 537| | static constexpr const char *findKeyNameForKeyIDStmtSQL = ( 538| | "SELECT key FROM key_names " 539| | "WHERE id == ? LIMIT 1;"); 540| | sqlite3_stmt* findKeyNameForKeyIDStmt = nullptr; 541| | 542| | static constexpr const char *insertIntoKeysStmtSQL = 543| | "INSERT OR IGNORE INTO key_names(key) VALUES (?);"; 544| | sqlite3_stmt* insertIntoKeysStmt = nullptr; 545| | 546| | virtual bool setRuleResult(KeyID keyID, 547| | const Rule& rule, 548| | const Result& ruleResult, 549| 0| std::string *error_out) override { 550| 0| assert(delegate != nullptr); 551| 0| std::lock_guard guard(dbMutex); 552| 0| int result; 553| 0| 554| 0| if (!open(error_out)) { 555| 0| return false; 556| 0| } 557| 0| 558| 0| auto dbKeyID = getKeyID(keyID, error_out); 559| 0| if (!error_out->empty()) { 560| 0| return false; 561| 0| } 562| 0| 563| 0| // Create the encoded dependency list. 564| 0| // 565| 0| // FIXME: We could save some reallocation by having a templated SmallVector 566| 0| // size here. 567| 0| basic::BinaryEncoder encoder{}; 568| 0| for (auto keyID: ruleResult.dependencies) { 569| 0| // Map the enging keyID to a database key ID 570| 0| // 571| 0| // FIXME: This is naively mapping all keys with no caching at this point, 572| 0| // thus likely to perform poorly. Should refactor this into a bulk 573| 0| // query or a DB layer cache. 574| 0| auto dbKeyID = getKeyID(keyID, error_out); 575| 0| if (!error_out->empty()) { 576| 0| return false; 577| 0| } 578| 0| encoder.write(dbKeyID.value); 579| 0| } 580| 0| 581| 0| // Insert the actual rule result. 582| 0| result = sqlite3_reset(insertIntoRuleResultsStmt); 583| 0| checkSQLiteResultOKReturnFalse(result); 584| 0| result = sqlite3_clear_bindings(insertIntoRuleResultsStmt); 585| 0| checkSQLiteResultOKReturnFalse(result); 586| 0| result = sqlite3_bind_int64(insertIntoRuleResultsStmt, /*index=*/1, 587| 0| dbKeyID.value); 588| 0| checkSQLiteResultOKReturnFalse(result); 589| 0| result = sqlite3_bind_blob(insertIntoRuleResultsStmt, /*index=*/2, 590| 0| ruleResult.value.data(), 591| 0| ruleResult.value.size(), 592| 0| SQLITE_STATIC); 593| 0| checkSQLiteResultOKReturnFalse(result); 594| 0| result = sqlite3_bind_int64(insertIntoRuleResultsStmt, /*index=*/3, 595| 0| ruleResult.builtAt); 596| 0| checkSQLiteResultOKReturnFalse(result); 597| 0| result = sqlite3_bind_int64(insertIntoRuleResultsStmt, /*index=*/4, 598| 0| ruleResult.computedAt); 599| 0| checkSQLiteResultOKReturnFalse(result); 600| 0| result = sqlite3_bind_blob(insertIntoRuleResultsStmt, /*index=*/5, 601| 0| encoder.data(), 602| 0| encoder.size(), 603| 0| SQLITE_STATIC); 604| 0| checkSQLiteResultOKReturnFalse(result); 605| 0| result = sqlite3_step(insertIntoRuleResultsStmt); 606| 0| if (result != SQLITE_DONE) { 607| 0| *error_out = getCurrentErrorMessage(); 608| 0| return false; 609| 0| } 610| 0| 611| 0| return true; 612| 0| } 613| | 614| 0| virtual bool buildStarted(std::string *error_out) override { 615| 0| std::lock_guard guard(dbMutex); 616| 0| 617| 0| if (!open(error_out)) 618| 0| return false; 619| 0| 620| 0| // Execute the entire build inside a single transaction. 621| 0| // 622| 0| // FIXME: We should revist this, as we probably wouldn't want a crash in the 623| 0| // build system to totally lose all build results. 624| 0| int result = sqlite3_exec(db, "BEGIN EXCLUSIVE;", nullptr, nullptr, nullptr); 625| 0| 626| 0| if (result != SQLITE_OK) { 627| 0| *error_out = getCurrentErrorMessage(); 628| 0| return false; 629| 0| } 630| 0| 631| 0| return true; 632| 0| } 633| | 634| 0| virtual void buildComplete() override { 635| 0| std::lock_guard guard(dbMutex); 636| 0| 637| 0| // Sync changes to disk. 638| 0| int result = sqlite3_exec(db, "END;", nullptr, nullptr, nullptr); 639| 0| assert(result == SQLITE_OK); 640| 0| (void)result; 641| 0| 642| 0| // We close the connection whenever a build completes so that we release 643| 0| // any locks that we may have on the file. 644| 0| close(); 645| 0| } 646| | 647| | /// @} 648| | 649| | 650| |private: 651| | /// Local cache of database DBKeyID (values) to engine KeyIDs 652| | llvm::DenseMap engineKeyIDs; 653| | 654| | /// Local cache of database engine KeyIDs to DBKeyIDs 655| | llvm::DenseMap dbKeyIDs; 656| | 657| | /// Lookup or create a DBKeyID for a given engine KeyID 658| | /// 659| | /// This method is not thread-safe. The caller must protect access via the 660| | /// dbMutex. 661| 0| DBKeyID getKeyID(KeyID keyID, std::string *error_out) { 662| 0| // Try to fetch the DBKeyID from the cache 663| 0| auto it = dbKeyIDs.find(keyID); 664| 0| if (it != dbKeyIDs.end()) { 665| 0| return it->second; 666| 0| } 667| 0| 668| 0| auto dbKeyID = getKeyIDFromDB(keyID, error_out); 669| 0| 670| 0| if (dbKeyID.value != 0) { 671| 0| // Cache the ID mappings 672| 0| engineKeyIDs[dbKeyID] = keyID; 673| 0| dbKeyIDs[keyID] = dbKeyID; 674| 0| } 675| 0| 676| 0| return dbKeyID; 677| 0| } 678| | 679| | // Helper function that searches and updates the key_names table as needed to 680| | // return a DBKeyID for the given engine KeyID. This should really only be 681| | // used by the above cached getKeyID() method. 682| 0| DBKeyID getKeyIDFromDB(KeyID keyID, std::string *error_out) { 683| 0|#define checkSQLiteResultOKReturnDBKeyID(result) \ 684| 0|if (result != SQLITE_OK) { \ 685| 0| *error_out = getCurrentErrorMessage(); \ 686| 0| return DBKeyID(); \ 687| 0|} 688| 0| 689| 0| int result; 690| 0| 691| 0| // Search for the key in the key_names table 692| 0| auto key = delegate->getKeyForID(keyID); 693| 0| result = sqlite3_reset(findKeyIDForKeyStmt); 694| 0| checkSQLiteResultOKReturnDBKeyID(result); 695| 0| result = sqlite3_clear_bindings(findKeyIDForKeyStmt); 696| 0| checkSQLiteResultOKReturnDBKeyID(result); 697| 0| result = sqlite3_bind_text(findKeyIDForKeyStmt, /*index=*/1, 698| 0| key.data(), key.size(), 699| 0| SQLITE_STATIC); 700| 0| checkSQLiteResultOKReturnDBKeyID(result); 701| 0| 702| 0| result = sqlite3_step(findKeyIDForKeyStmt); 703| 0| if (result == SQLITE_ROW) { 704| 0| assert(sqlite3_column_count(findKeyIDForKeyStmt) == 1); 705| 0| 706| 0| // Found a keyID. 707| 0| return DBKeyID(sqlite3_column_int64(findKeyIDForKeyStmt, 0)); 708| 0| } 709| 0| 710| 0| // Did not find the key, need to insert. 711| 0| result = sqlite3_reset(insertIntoKeysStmt); 712| 0| checkSQLiteResultOKReturnDBKeyID(result); 713| 0| result = sqlite3_clear_bindings(insertIntoKeysStmt); 714| 0| checkSQLiteResultOKReturnDBKeyID(result); 715| 0| result = sqlite3_bind_text(insertIntoKeysStmt, /*index=*/1, 716| 0| key.data(), key.size(), 717| 0| SQLITE_STATIC); 718| 0| checkSQLiteResultOKReturnDBKeyID(result); 719| 0| result = sqlite3_step(insertIntoKeysStmt); 720| 0| if (result != SQLITE_DONE) { 721| 0| *error_out = getCurrentErrorMessage(); 722| 0| return DBKeyID(); 723| 0| } 724| 0| 725| 0| return DBKeyID(sqlite3_last_insert_rowid(db)); 726| 0|#undef checkSQLiteResultOKReturnDBKeyID 727| 0| } 728| | 729| | /// Maps a DBKeyID into an engine KeyID 730| | /// 731| | /// This method is not thread-safe. The caller must protect access via the 732| | /// dbMutex. 733| 0| KeyID getKeyIDForID(DBKeyID keyID, std::string *error_out) { 734| 0|#define checkSQLiteResultOKReturnKeyID(result) \ 735| 0|if (result != SQLITE_OK) { \ 736| 0| *error_out = getCurrentErrorMessage(); \ 737| 0| return KeyID(); \ 738| 0|} 739| 0| 740| 0| // Search local db <-> engine mapping cache 741| 0| auto it = engineKeyIDs.find(keyID); 742| 0| if (it != engineKeyIDs.end()) 743| 0| return it->second; 744| 0| 745| 0| // Search for the key in the database 746| 0| int result; 747| 0| result = sqlite3_reset(findKeyNameForKeyIDStmt); 748| 0| checkSQLiteResultOKReturnKeyID(result); 749| 0| result = sqlite3_clear_bindings(findKeyNameForKeyIDStmt); 750| 0| checkSQLiteResultOKReturnKeyID(result); 751| 0| result = sqlite3_bind_int64(findKeyNameForKeyIDStmt, /*index=*/1, keyID.value); 752| 0| checkSQLiteResultOKReturnKeyID(result); 753| 0| 754| 0| result = sqlite3_step(findKeyNameForKeyIDStmt); 755| 0| if (result != SQLITE_ROW) { 756| 0| *error_out = getCurrentErrorMessage(); 757| 0| return KeyID(); 758| 0| } 759| 0| assert(sqlite3_column_count(findKeyNameForKeyIDStmt) == 1); 760| 0| 761| 0| // Found a key 762| 0| auto size = sqlite3_column_bytes(findKeyNameForKeyIDStmt, 0); 763| 0| auto text = (const char*) sqlite3_column_text(findKeyNameForKeyIDStmt, 0); 764| 0| 765| 0| // Map the key to an engine ID 766| 0| auto engineKeyID = delegate->getKeyID(KeyType(text, size)); 767| 0| 768| 0| // Cache the mapping locally 769| 0| engineKeyIDs[keyID] = engineKeyID; 770| 0| dbKeyIDs[engineKeyID] = keyID; 771| 0| 772| 0| return engineKeyID; 773| 0|#undef checkSQLiteResultOKReturnKeyID 774| 0| } 775| |}; 776| | 777| |} 778| | 779| |std::unique_ptr core::createSQLiteBuildDB(StringRef path, 780| | uint32_t clientSchemaVersion, 781| 0| std::string* error_out) { 782| 0| return llvm::make_unique(path, clientSchemaVersion); 783| 0|} 784| | 785| |#undef checkSQLiteResultOKReturnFalse /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/BuildEngine.h: 1| |//===- BuildEngine.h --------------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_BUILDENGINE_H 14| |#define LLBUILD_CORE_BUILDENGINE_H 15| | 16| |#include "llbuild/Basic/Compiler.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/ADT/Twine.h" 20| | 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| | 28| |namespace llbuild { 29| |namespace core { 30| | 31| |// FIXME: Need to abstract KeyType; 32| |typedef std::string KeyType; 33| |typedef uint64_t KeyID; 34| |typedef std::vector ValueType; 35| | 36| |class BuildDB; 37| |class BuildEngine; 38| | 39| |/// A monotonically increasing timestamp identifying which iteration of a build 40| |/// an event occurred during. 41| |typedef uint64_t Timestamp; 42| | 43| |/// This object contains the result of executing a task to produce the value for 44| |/// a key. 45| |struct Result { 46| | /// The last value that resulted from executing the task. 47| | ValueType value = {}; 48| | 49| | /// The build timestamp during which the result \see Value was computed. 50| | uint64_t computedAt = 0; 51| | 52| | /// The build timestamp at which this result was last checked to be 53| | /// up-to-date. 54| | /// 55| | /// \invariant builtAt >= computedAt 56| | // 57| | // FIXME: Think about this representation more. The problem with storing this 58| | // field here in this fashion is that every build will result in bringing all 59| | // of the \see builtAt fields up to date. That is unfortunate from a 60| | // persistence perspective, where it would be ideal if we didn't touch any 61| | // disk state for null builds. 62| | uint64_t builtAt = 0; 63| | 64| | /// The explicit dependencies required by the generation. 65| | // 66| | // FIXME: At some point, figure out the optimal representation for this field, 67| | // which is likely to be a lot of the resident memory size. 68| | std::vector dependencies; 69| |}; 70| | 71| |/// A task object represents an abstract in-progress computation in the build 72| |/// engine. 73| |/// 74| |/// The task represents not just the primary computation, but also the process 75| |/// of starting the computation and necessary input dependencies. Tasks are 76| |/// expected to be created in response to \see BuildEngine requests to initiate 77| |/// the production of particular result value. 78| |/// 79| |/// The creator may use \see BuildEngine::taskNeedsInput() to specify input 80| |/// dependencies on the Task. The Task itself may also specify additional input 81| |/// dependencies dynamically during the execution of \see Task::start() or \see 82| |/// Task::provideValue(). 83| |/// 84| |/// Once a task has been created and registered, the BuildEngine will invoke 85| |/// \see Task::start() to initiate the computation. The BuildEngine will provide 86| |/// the in progress task with its requested inputs via \see 87| |/// Task::provideValue(). 88| |/// 89| |/// After all inputs requested by the Task have been delivered, the BuildEngine 90| |/// will invoke \see Task::inputsAvailable() to instruct the Task it should 91| |/// complete its computation and provide the output. The Task is responsible for 92| |/// providing the engine with the computed value when ready using \see 93| |/// BuildEngine::taskIsComplete(). 94| |/// 95| |/// A task which has been cancelled may be destroyed without any of the above 96| |/// behaviors having been completed. 97| |class Task { 98| |public: 99| 0| Task() {} 100| | virtual ~Task(); 101| | 102| | /// Executed by the build engine when the task should be started. 103| | virtual void start(BuildEngine&) = 0; 104| | 105| | /// Invoked by the build engine to provide the prior result for the task's 106| | /// output, if present. 107| | /// 108| | /// This callback will always be invoked immediately after the task is 109| | /// started, and prior to its receipt of any other callbacks. 110| 0| virtual void providePriorValue(BuildEngine&, const ValueType& value) {}; 111| | 112| | /// Invoked by the build engine to provide an input value as it becomes 113| | /// available. 114| | /// 115| | /// \param inputID The unique identifier provided to the build engine to 116| | /// represent this input when requested in \see 117| | /// BuildEngine::taskNeedsInput(). 118| | /// 119| | /// \param value The computed value for the given input. 120| | virtual void provideValue(BuildEngine&, uintptr_t inputID, 121| | const ValueType& value) = 0; 122| | 123| | /// Executed by the build engine to indicate that all inputs have been 124| | /// provided, and the task should begin its computation. 125| | /// 126| | /// The task is expected to call \see BuildEngine::taskIsComplete() when it is 127| | /// done with its computation. 128| | /// 129| | /// It is an error for any client to request an additional input for a task 130| | /// after the last requested input has been provided by the build engine. 131| | virtual void inputsAvailable(BuildEngine&) = 0; 132| |}; 133| | 134| |/// A rule represents an individual element of computation that can be performed 135| |/// by the build engine. 136| |/// 137| |/// Each rule is identified by a unique key and the value for that key can be 138| |/// computed to produce a result, and supplies a set of callbacks that are used 139| |/// to implement the rule's behavior. 140| |/// 141| |/// The computation for a rule is done by invocation of its \see Action 142| |/// callback, which is responsible for creating a Task object which will manage 143| |/// the computation. 144| |/// 145| |/// All callbacks for the Rule are always invoked synchronously on the primary 146| |/// BuildEngine thread. 147| |// 148| |// FIXME: The intent of having a callback like Rule structure and a decoupled 149| |// (virtual) Task is that the Rule objects (of which there can be very many) can 150| |// be optimized for being lightweight. We don't currently make much of an 151| |// attempt in this direction with the std::functions, but we should investigate 152| |// if this can be lighter weight -- especially since many clients are likely to 153| |// need little more than a place to stuff a context object and register their 154| |// callbacks. 155| |// 156| |// FIXME: We also need to figure out if a richer concurrency model is needed for 157| |// the callbacks. The current intent is that they should be lightweight and 158| |// Tasks should be used when real concurrency is needed. 159| |class Rule { 160| |public: 161| | enum class StatusKind { 162| | /// Indicates the rule is being scanned. 163| | IsScanning = 0, 164| | 165| | /// Indicates the rule is up-to-date, and doesn't need to run. 166| | IsUpToDate = 1, 167| | 168| | /// Indicates the rule was run, and is now complete. 169| | IsComplete = 2 170| | }; 171| | 172| | enum class CycleAction { 173| | /// Indicates a rule will be forced to build 174| | ForceBuild = 0, 175| | 176| | /// Indicates a rule's prior value will be supplied to a downstream rule 177| | SupplyPriorValue = 1 178| | }; 179| | 180| | /// The key computed by the rule. 181| | KeyType key; 182| | 183| | /// Called to create the task to build the rule, when necessary. 184| | std::function action; 185| | 186| | /// Called to check whether the previously computed value for this rule is 187| | /// still valid. 188| | /// 189| | /// This callback is designed for use in synchronizing values which represent 190| | /// state managed externally to the build engine. For example, a rule which 191| | /// computes something on the file system may use this to verify that the 192| | /// computed output has not changed since it was built. 193| | std::function isResultValid; 195| | 196| | /// Called to indicate a change in the rule status. 197| | std::function updateStatus; 198| |}; 199| | 200| |/// Delegate interface for use with the build engine. 201| |class BuildEngineDelegate { 202| |public: 203| | virtual ~BuildEngineDelegate(); 204| | 205| | /// Get the rule to use for the given Key. 206| | /// 207| | /// The delegate *must* provide a rule for any possible key that can be 208| | /// requested (either by a client, through \see BuildEngine::build(), or via a 209| | /// Task through mechanisms such as \see BuildEngine::taskNeedsInput(). If a 210| | /// requested Key cannot be supplied, the delegate should provide a dummy rule 211| | /// that the client can translate into an error. 212| | virtual Rule lookupRule(const KeyType& key) = 0; 213| | 214| | /// Called when a cycle is detected by the build engine to check if it should 215| | /// attempt to resolve the cycle and continue 216| | /// 217| | /// \param items The ordered list of items comprising the cycle, starting from 218| | /// the node which was requested to build and ending with the first node in 219| | /// the cycle (i.e., the node participating in the cycle will appear twice). 220| | /// \param candidateRule The rule the engine will use to attempt to break the 221| | /// cycle. 222| | /// \param action The action the engine will take on the candidateRule. 223| | /// \returns True if the engine should attempt to resolve the cycle, false 224| | /// otherwise. Resolution is attempted by either forcing items to be built, or 225| | /// supplying a previously built result to a node in the cycle. The latter 226| | /// action may yield unexpected results and thus this should be opted into 227| | /// with care. 228| | virtual bool shouldResolveCycle(const std::vector& items, 229| | Rule* candidateRule, 230| | Rule::CycleAction action); 231| | 232| | /// Called when a cycle is detected by the build engine and it cannot make 233| | /// forward progress. 234| | /// 235| | /// \param items The ordered list of items comprising the cycle, starting from 236| | /// the node which was requested to build and ending with the first node in 237| | /// the cycle (i.e., the node participating in the cycle will appear twice). 238| | virtual void cycleDetected(const std::vector& items) = 0; 239| | 240| | /// Called when a fatal error is encountered by the build engine. 241| | /// 242| | /// \param message The diagnostic message. 243| | virtual void error(const llvm::Twine& message) = 0; 244| | 245| |}; 246| | 247| |/// A build engine supports fast, incremental, persistent, and parallel 248| |/// execution of computational graphs. 249| |/// 250| |/// Computational elements in the graph are modeled by \see Rule objects, which 251| |/// are assocated with a specific \see KeyType, and which can be executed to 252| |/// produce an output \see ValueType for that key. 253| |/// 254| |/// Rule objects are evaluated by first invoking their action to produce a \see 255| |/// Task object which is responsible for the live execution of the 256| |/// computation. The Task object can interact with the BuildEngine to request 257| |/// inputs or to notify the engine of its completion, and receives various 258| |/// callbacks from the engine as the computation progresses. 259| |/// 260| |/// The engine itself executes using a deterministic, serial operation, but it 261| |/// supports parallel computation by allowing the individual Task objects to 262| |/// defer their own computation to signal the BuildEngine of its completion on 263| |/// alternate threads. 264| |/// 265| |/// To support persistence, the engine allows attaching a database (\see 266| |/// attachDB()) which can be used to record the prior results of evaluating Rule 267| |/// instances. 268| |class BuildEngine { 269| | void *impl; 270| | 271| | // Copying is disabled. 272| | BuildEngine(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 273| | void operator=(const BuildEngine&) LLBUILD_DELETED_FUNCTION; 274| | 275| |public: 276| | /// Create a build engine with the given delegate. 277| | explicit BuildEngine(BuildEngineDelegate& delegate); 278| | ~BuildEngine(); 279| | 280| | /// Return the delegate the engine was configured with. 281| | BuildEngineDelegate* getDelegate(); 282| | 283| | /// Get the current build timestamp used by the engine. 284| | /// 285| | /// The timestamp is a monotonically increasing value which is incremented 286| | /// with each requested build. 287| | Timestamp getCurrentTimestamp(); 288| | 289| | /// @name Rule Definition 290| | /// @{ 291| | 292| | /// Add a rule which the engine can use to produce outputs. 293| | void addRule(Rule&& rule); 294| | 295| | /// @} 296| | 297| | /// @name Client API 298| | /// @{ 299| | 300| | /// Build the result for a particular key. 301| | /// 302| | /// \returns The result of computing the key, or the empty value if the key 303| | /// could not be computed; the latter case only happens if a cycle was 304| | /// discovered currently. 305| | const ValueType& build(const KeyType& key); 306| | 307| | /// Cancel the currently running build. 308| | /// 309| | /// The engine guarantees that it will not *start* any task after processing 310| | /// the current engine work loop iteration after it has been cancelled. 311| | /// 312| | /// This method is thread-safe. 313| | /// 314| | /// This method should only be used when a build is actively running. Invoking 315| | /// this method before a build has started will have no effect. 316| | // 317| | // FIXME: This method is hard to use correctly, we should modify build to 318| | // return an explicit object to represent an in-flight build, and then expose 319| | // cancellation on that. 320| | void cancelBuild(); 321| | 322| | /// Attach a database for persisting build state. 323| | /// 324| | /// A database should only be attached immediately after creating the engine, 325| | /// it is an error to attach a database after adding rules or initiating any 326| | /// builds, or to attempt to attach multiple databases. 327| | /// 328| | /// \param error_out [out] Error string if return value is false. 329| | /// \returns false if the build database could not be attached. 330| | bool attachDB(std::unique_ptr database, std::string* error_out); 331| | 332| | /// Enable tracing into the given output file. 333| | /// 334| | /// \returns True on success. 335| | bool enableTracing(const std::string& path, std::string* error_out); 336| | 337| | /// Dump the build state to a file in Graphviz DOT format. 338| | void dumpGraphToFile(const std::string &path); 339| | 340| | /// @} 341| | 342| | /// @name Task Management APIs 343| | /// @{ 344| | 345| | /// Register the given task, in response to a Rule evaluation. 346| | /// 347| | /// The engine tasks ownership of the \arg Task, and it is expected to 348| | /// subsequently be returned as the task to execute for a Rule evaluation. 349| | /// 350| | /// \returns The provided task, for the convenience of the client. 351| | Task* registerTask(Task* task); 352| | 353| | /// The maximum allowed input ID. 354| | static const uintptr_t kMaximumInputID = ~(uintptr_t)0xFF; 355| | 356| | /// Specify the given \arg Task depends upon the result of computing \arg Key. 357| | /// 358| | /// The result, when available, will be provided to the task via \see 359| | /// Task::provideValue(), supplying the provided \arg InputID to allow the 360| | /// task to identify the particular input. 361| | /// 362| | /// NOTE: It is an unchecked error for a task to request the same input value 363| | /// multiple times. 364| | /// 365| | /// \param inputID An arbitrary value that may be provided by the client to 366| | /// use in efficiently associating this input. The range of this parameter is 367| | /// intentionally chosen to allow a pointer to be provided, but note that all 368| | /// input IDs greater than \see kMaximumInputID are reserved for internal use 369| | /// by the engine. 370| | void taskNeedsInput(Task* task, const KeyType& key, uintptr_t inputID); 371| | 372| | /// Specify that the given \arg Task must be built subsequent to the 373| | /// computation of \arg Key. 374| | /// 375| | /// The value of the computation of \arg Key is not available to the task, and 376| | /// the only guarantee the engine provides is that if \arg Key is computed 377| | /// during a build, then \arg Task will not be computed until after it. 378| | void taskMustFollow(Task* task, const KeyType& key); 379| | 380| | /// Inform the engine of an input dependency that was discovered by the task 381| | /// during its execution, a la compiler generated dependency files. 382| | /// 383| | /// This call may only be made after a task has received all of its inputs; 384| | /// inputs discovered prior to that point should simply be requested as normal 385| | /// input dependencies. 386| | /// 387| | /// Such a dependency is not used to provide additional input to the task, 388| | /// rather it is a way for the task to report an additional input which should 389| | /// be considered the next time the rule is evaluated. The expected use case 390| | /// for a discovered dependency is is when a processing task cannot predict 391| | /// all of its inputs prior to being run, but can presume that any unknown 392| | /// inputs already exist. In such cases, the task can go ahead and run and can 393| | /// report the all of the discovered inputs as it executes. Once the task is 394| | /// complete, these inputs will be recorded as being dependencies of the task 395| | /// so that it will be recomputed when any of the inputs change. 396| | /// 397| | /// It is legal to call this method from any thread, but the caller is 398| | /// responsible for ensuring that it is never called concurrently for the same 399| | /// task. 400| | void taskDiscoveredDependency(Task* task, const KeyType& key); 401| | 402| | /// Called by a task to indicate it has completed and to provide its value. 403| | /// 404| | /// It is legal to call this method from any thread. 405| | /// 406| | /// \param value The new value for the task's rule. 407| | /// 408| | /// \param forceChange If true, treat the value as changed and trigger 409| | /// dependents to rebuild, even if the value itself is not different from the 410| | /// prior result. 411| | void taskIsComplete(Task* task, ValueType&& value, bool forceChange = false); 412| | 413| | /// @} 414| |}; 415| | 416| |} 417| |} 418| | 419| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/DependencyInfoParser.h: 1| |//===- DependencyInfoParser.h -----------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_DEPENDENCYINFOPARSER_H 14| |#define LLBUILD_CORE_DEPENDENCYINFOPARSER_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| |namespace core { 24| | 25| |/// Interface for parsing the "dependency info" format used by Darwin tools. 26| |class DependencyInfoParser { 27| |public: 28| | /// Delegate interface for parser behavior. 29| | struct ParseActions { 30| | virtual ~ParseActions(); 31| | 32| | /// Called if an error is encountered in parsing the input. 33| | /// 34| | /// \param message A C-string text message including information on the 35| | /// error. 36| | /// 37| | /// \param position The approximate position of the error in the input 38| | /// buffer. 39| | virtual void error(const char* message, uint64_t position) = 0; 40| | 41| | /// Called when the version information is found. 42| | /// 43| | /// There can only ever be one version info record in the file. 44| | virtual void actOnVersion(StringRef) = 0; 45| | 46| | /// Called when an input is found. 47| | virtual void actOnInput(StringRef) = 0; 48| | 49| | /// Called when an output is found. 50| | virtual void actOnOutput(StringRef) = 0; 51| | 52| | /// Called when a missing file entry is found. 53| | /// 54| | /// These entries indicate a file which was looked for by the tool, but not 55| | /// found, and can be used to track anti-dependencies. 56| | virtual void actOnMissing(StringRef) = 0; 57| | }; 58| | 59| | StringRef data; 60| | ParseActions& actions; 61| | 62| |public: 63| | DependencyInfoParser(StringRef data, ParseActions& actions) 64| 0| : data(data), actions(actions) {} 65| | 66| | void parse(); 67| |}; 68| | 69| |} 70| |} 71| | 72| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/Core/include/llbuild/Core/MakefileDepsParser.h: 1| |//===- MakefileDepsParser.h -------------------------------------*- C++ -*-===// 2| |// 3| |// This source file is part of the Swift.org open source project 4| |// 5| |// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors 6| |// Licensed under Apache License v2.0 with Runtime Library Exception 7| |// 8| |// See http://swift.org/LICENSE.txt for license information 9| |// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10| |// 11| |//===----------------------------------------------------------------------===// 12| | 13| |#ifndef LLBUILD_CORE_MAKEFILEDEPSPARSER_H 14| |#define LLBUILD_CORE_MAKEFILEDEPSPARSER_H 15| | 16| |#include "llbuild/Basic/LLVM.h" 17| | 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |#include 21| | 22| |namespace llbuild { 23| |namespace core { 24| | 25| |/// Interface for parsing compiler-style dependencies output, which is a 26| |/// restricted subset of the Makefile syntax. 27| |class MakefileDepsParser { 28| |public: 29| | /// Delegate interface for parser behavior. 30| | struct ParseActions { 31| | virtual ~ParseActions(); 32| | 33| | /// Called if an error is encountered in parsing the input. 34| | /// 35| | /// \param message A C-string text message including information on the 36| | /// error. 37| | /// 38| | /// \param position The approximate position of the error in the input 39| | /// buffer. 40| | virtual void error(const char* message, uint64_t position) = 0; 41| | 42| | /// Called when a new rule is encountered. 43| | /// 44| | /// \param name - A pointer to the rule name string start. 45| | /// 46| | /// \param length - The raw length of the rule name string, including escape 47| | /// sequences. 48| | /// 49| | /// \param unescapedWord - An unescaped version of the name. 50| | virtual void actOnRuleStart(const char* name, uint64_t length, 51| | const StringRef unescapedWord) = 0; 52| | 53| | /// Called when a new dependency is found for the current rule. 54| | /// 55| | /// This is only called between paired calls to \see actOnRuleStart() and 56| | /// \see actOnRuleEnd(). 57| | /// 58| | /// \param dependency - A pointer to the dependency string start. 59| | /// 60| | /// \param length - The raw length of the dependency string, including 61| | /// escape sequences. 62| | /// 63| | /// \param unescapedWord - An unescaped version of the dependency. 64| | virtual void actOnRuleDependency(const char* dependency, uint64_t length, 65| | const StringRef unescapedWord) = 0; 66| | 67| | /// Called when a rule is complete. 68| | virtual void actOnRuleEnd() = 0; 69| | }; 70| | 71| | const char* data; 72| | uint64_t length; 73| | ParseActions& actions; 74| | 75| |public: 76| | MakefileDepsParser(const char* data, uint64_t length, ParseActions& actions) 77| 0| : data(data), length(length), actions(actions) {} 78| | 79| | void parse(); 80| |}; 81| | 82| |} 83| |} 84| | 85| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/DenseMap.h: 1| |//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the DenseMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_DENSEMAP_H 15| |#define LLVM_ADT_DENSEMAP_H 16| | 17| |#include "llvm/ADT/DenseMapInfo.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/PointerLikeTypeTraits.h" 22| |#include "llvm/Support/type_traits.h" 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| |#include 31| | 32| |namespace llvm { 33| | 34| |namespace detail { 35| |// We extend a pair to allow users to override the bucket type with their own 36| |// implementation without requiring two members. 37| |template 38| |struct DenseMapPair : public std::pair { 39| 0| KeyT &getFirst() { return std::pair::first; } ------------------ | Unexecuted instantiation: _ZN4llvm6detail12DenseMapPairI7DBKeyIDyE8getFirstEv ------------------ | Unexecuted instantiation: _ZN4llvm6detail12DenseMapPairIy7DBKeyIDE8getFirstEv ------------------ 40| 0| const KeyT &getFirst() const { return std::pair::first; } ------------------ | Unexecuted instantiation: _ZNK4llvm6detail12DenseMapPairIy7DBKeyIDE8getFirstEv ------------------ | Unexecuted instantiation: _ZNK4llvm6detail12DenseMapPairI7DBKeyIDyE8getFirstEv ------------------ 41| 0| ValueT &getSecond() { return std::pair::second; } ------------------ | Unexecuted instantiation: _ZN4llvm6detail12DenseMapPairI7DBKeyIDyE9getSecondEv ------------------ | Unexecuted instantiation: _ZN4llvm6detail12DenseMapPairIy7DBKeyIDE9getSecondEv ------------------ 42| | const ValueT &getSecond() const { return std::pair::second; } 43| |}; 44| |} 45| | 46| |template < 47| | typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, 48| | typename Bucket = detail::DenseMapPair, bool IsConst = false> 49| |class DenseMapIterator; 50| | 51| |template 53| |class DenseMapBase { 54| |public: 55| | typedef unsigned size_type; 56| | typedef KeyT key_type; 57| | typedef ValueT mapped_type; 58| | typedef BucketT value_type; 59| | 60| | typedef DenseMapIterator iterator; 61| | typedef DenseMapIterator 62| | const_iterator; 63| | inline iterator begin() { 64| | // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). 65| | return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); 66| | } 67| 0| inline iterator end() { 68| 0| return iterator(getBucketsEnd(), getBucketsEnd(), true); 69| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E3endEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E3endEv ------------------ 70| | inline const_iterator begin() const { 71| | return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd()); 72| | } 73| | inline const_iterator end() const { 74| | return const_iterator(getBucketsEnd(), getBucketsEnd(), true); 75| | } 76| | 77| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { 78| | return getNumEntries() == 0; 79| | } 80| | unsigned size() const { return getNumEntries(); } 81| | 82| | /// Grow the densemap so that it has at least Size buckets. Does not shrink 83| | void resize(size_type Size) { 84| | if (Size > getNumBuckets()) 85| | grow(Size); 86| | } 87| | 88| | void clear() { 89| | if (getNumEntries() == 0 && getNumTombstones() == 0) return; 90| | 91| | // If the capacity of the array is huge, and the # elements used is small, 92| | // shrink the array. 93| | if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { 94| | shrink_and_clear(); 95| | return; 96| | } 97| | 98| | const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 99| | for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 100| | if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { 101| | if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 102| | P->getSecond().~ValueT(); 103| | decrementNumEntries(); 104| | } 105| | P->getFirst() = EmptyKey; 106| | } 107| | } 108| | assert(getNumEntries() == 0 && "Node count imbalance!"); 109| | setNumTombstones(0); 110| | } 111| | 112| | /// Return 1 if the specified key is in the map, 0 otherwise. 113| | size_type count(const KeyT &Val) const { 114| | const BucketT *TheBucket; 115| | return LookupBucketFor(Val, TheBucket) ? 1 : 0; 116| | } 117| | 118| 0| iterator find(const KeyT &Val) { 119| 0| BucketT *TheBucket; 120| 0| if (LookupBucketFor(Val, TheBucket)) 121| 0| return iterator(TheBucket, getBucketsEnd(), true); 122| 0| return end(); 123| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E4findERKy ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E4findERKS2_ ------------------ 124| | const_iterator find(const KeyT &Val) const { 125| | const BucketT *TheBucket; 126| | if (LookupBucketFor(Val, TheBucket)) 127| | return const_iterator(TheBucket, getBucketsEnd(), true); 128| | return end(); 129| | } 130| | 131| | /// Alternate version of find() which allows a different, and possibly 132| | /// less expensive, key type. 133| | /// The DenseMapInfo is responsible for supplying methods 134| | /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key 135| | /// type used. 136| | template 137| | iterator find_as(const LookupKeyT &Val) { 138| | BucketT *TheBucket; 139| | if (LookupBucketFor(Val, TheBucket)) 140| | return iterator(TheBucket, getBucketsEnd(), true); 141| | return end(); 142| | } 143| | template 144| | const_iterator find_as(const LookupKeyT &Val) const { 145| | const BucketT *TheBucket; 146| | if (LookupBucketFor(Val, TheBucket)) 147| | return const_iterator(TheBucket, getBucketsEnd(), true); 148| | return end(); 149| | } 150| | 151| | /// lookup - Return the entry for the specified key, or a default 152| | /// constructed value if no such entry exists. 153| | ValueT lookup(const KeyT &Val) const { 154| | const BucketT *TheBucket; 155| | if (LookupBucketFor(Val, TheBucket)) 156| | return TheBucket->getSecond(); 157| | return ValueT(); 158| | } 159| | 160| | // Inserts key,value pair into the map if the key isn't already in the map. 161| | // If the key is already in the map, it returns false and doesn't update the 162| | // value. 163| | std::pair insert(const std::pair &KV) { 164| | BucketT *TheBucket; 165| | if (LookupBucketFor(KV.first, TheBucket)) 166| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 167| | false); // Already in map. 168| | 169| | // Otherwise, insert the new element. 170| | TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); 171| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 172| | } 173| | 174| | // Inserts key,value pair into the map if the key isn't already in the map. 175| | // If the key is already in the map, it returns false and doesn't update the 176| | // value. 177| | std::pair insert(std::pair &&KV) { 178| | BucketT *TheBucket; 179| | if (LookupBucketFor(KV.first, TheBucket)) 180| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), 181| | false); // Already in map. 182| | 183| | // Otherwise, insert the new element. 184| | TheBucket = InsertIntoBucket(std::move(KV.first), 185| | std::move(KV.second), 186| | TheBucket); 187| | return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); 188| | } 189| | 190| | /// insert - Range insertion of pairs. 191| | template 192| | void insert(InputIt I, InputIt E) { 193| | for (; I != E; ++I) 194| | insert(*I); 195| | } 196| | 197| | 198| | bool erase(const KeyT &Val) { 199| | BucketT *TheBucket; 200| | if (!LookupBucketFor(Val, TheBucket)) 201| | return false; // not in map. 202| | 203| | TheBucket->getSecond().~ValueT(); 204| | TheBucket->getFirst() = getTombstoneKey(); 205| | decrementNumEntries(); 206| | incrementNumTombstones(); 207| | return true; 208| | } 209| | void erase(iterator I) { 210| | BucketT *TheBucket = &*I; 211| | TheBucket->getSecond().~ValueT(); 212| | TheBucket->getFirst() = getTombstoneKey(); 213| | decrementNumEntries(); 214| | incrementNumTombstones(); 215| | } 216| | 217| 0| value_type& FindAndConstruct(const KeyT &Key) { 218| 0| BucketT *TheBucket; 219| 0| if (LookupBucketFor(Key, TheBucket)) 220| 0| return *TheBucket; 221| 0| 222| 0| return *InsertIntoBucket(Key, ValueT(), TheBucket); 223| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E16FindAndConstructERKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E16FindAndConstructERKy ------------------ 224| | 225| 0| ValueT &operator[](const KeyT &Key) { 226| 0| return FindAndConstruct(Key).second; 227| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_EixERKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_EixERKy ------------------ 228| | 229| | value_type& FindAndConstruct(KeyT &&Key) { 230| | BucketT *TheBucket; 231| | if (LookupBucketFor(Key, TheBucket)) 232| | return *TheBucket; 233| | 234| | return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket); 235| | } 236| | 237| | ValueT &operator[](KeyT &&Key) { 238| | return FindAndConstruct(std::move(Key)).second; 239| | } 240| | 241| | /// isPointerIntoBucketsArray - Return true if the specified pointer points 242| | /// somewhere into the DenseMap's array of buckets (i.e. either to a key or 243| | /// value in the DenseMap). 244| | bool isPointerIntoBucketsArray(const void *Ptr) const { 245| | return Ptr >= getBuckets() && Ptr < getBucketsEnd(); 246| | } 247| | 248| | /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets 249| | /// array. In conjunction with the previous method, this can be used to 250| | /// determine whether an insertion caused the DenseMap to reallocate. 251| | const void *getPointerIntoBucketsArray() const { return getBuckets(); } 252| | 253| |protected: 254| 0| DenseMapBase() {} ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_EC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_EC2Ev ------------------ 255| | 256| 0| void destroyAll() { 257| 0| if (getNumBuckets() == 0) // Nothing to do. 258| 0| return; 259| 0| 260| 0| const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 261| 0| for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 262| 0| if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 263| 0| !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) 264| 0| P->getSecond().~ValueT(); 265| 0| P->getFirst().~KeyT(); 266| 0| } 267| 0| 268| 0|#ifndef NDEBUG 269| 0| memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); 270| 0|#endif 271| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E10destroyAllEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E10destroyAllEv ------------------ 272| | 273| 0| void initEmpty() { 274| 0| setNumEntries(0); 275| 0| setNumTombstones(0); 276| 0| 277| 0| assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && 278| 0| "# initial buckets must be a power of two!"); 279| 0| const KeyT EmptyKey = getEmptyKey(); 280| 0| for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) 281| 0| new (&B->getFirst()) KeyT(EmptyKey); 282| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E9initEmptyEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E9initEmptyEv ------------------ 283| | 284| 0| void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { 285| 0| initEmpty(); 286| 0| 287| 0| // Insert all the old elements. 288| 0| const KeyT EmptyKey = getEmptyKey(); 289| 0| const KeyT TombstoneKey = getTombstoneKey(); 290| 0| for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { 291| 0| if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && 292| 0| !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { 293| 0| // Insert the key/value into the new table. 294| 0| BucketT *DestBucket; 295| 0| bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); 296| 0| (void)FoundVal; // silence warning. 297| 0| assert(!FoundVal && "Key already in new map?"); 298| 0| DestBucket->getFirst() = std::move(B->getFirst()); 299| 0| new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); 300| 0| incrementNumEntries(); 301| 0| 302| 0| // Free the value. 303| 0| B->getSecond().~ValueT(); 304| 0| } 305| 0| B->getFirst().~KeyT(); 306| 0| } 307| 0| 308| 0|#ifndef NDEBUG 309| 0| if (OldBucketsBegin != OldBucketsEnd) 310| 0| memset((void*)OldBucketsBegin, 0x5a, 311| 0| sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); 312| 0|#endif 313| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E18moveFromOldBucketsEPS7_SA_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E18moveFromOldBucketsEPS7_SA_ ------------------ 314| | 315| | template 316| | void copyFrom( 317| | const DenseMapBase &other) { 318| | assert(&other != this); 319| | assert(getNumBuckets() == other.getNumBuckets()); 320| | 321| | setNumEntries(other.getNumEntries()); 322| | setNumTombstones(other.getNumTombstones()); 323| | 324| | if (isPodLike::value && isPodLike::value) 325| | memcpy(getBuckets(), other.getBuckets(), 326| | getNumBuckets() * sizeof(BucketT)); 327| | else 328| | for (size_t i = 0; i < getNumBuckets(); ++i) { 329| | new (&getBuckets()[i].getFirst()) 330| | KeyT(other.getBuckets()[i].getFirst()); 331| | if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && 332| | !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) 333| | new (&getBuckets()[i].getSecond()) 334| | ValueT(other.getBuckets()[i].getSecond()); 335| | } 336| | } 337| | 338| | void swap(DenseMapBase& RHS) { 339| | std::swap(getNumEntries(), RHS.getNumEntries()); 340| | std::swap(getNumTombstones(), RHS.getNumTombstones()); 341| | } 342| | 343| 0| static unsigned getHashValue(const KeyT &Val) { 344| 0| return KeyInfoT::getHashValue(Val); 345| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E12getHashValueERKy ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E12getHashValueERKS2_ ------------------ 346| | template 347| | static unsigned getHashValue(const LookupKeyT &Val) { 348| | return KeyInfoT::getHashValue(Val); 349| | } 350| 0| static const KeyT getEmptyKey() { 351| 0| return KeyInfoT::getEmptyKey(); 352| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E11getEmptyKeyEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E11getEmptyKeyEv ------------------ 353| 0| static const KeyT getTombstoneKey() { 354| 0| return KeyInfoT::getTombstoneKey(); 355| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E15getTombstoneKeyEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E15getTombstoneKeyEv ------------------ 356| | 357| |private: 358| 0| unsigned getNumEntries() const { 359| 0| return static_cast(this)->getNumEntries(); 360| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E13getNumEntriesEv ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E13getNumEntriesEv ------------------ 361| 0| void setNumEntries(unsigned Num) { 362| 0| static_cast(this)->setNumEntries(Num); 363| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E13setNumEntriesEj ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E13setNumEntriesEj ------------------ 364| 0| void incrementNumEntries() { 365| 0| setNumEntries(getNumEntries() + 1); 366| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E19incrementNumEntriesEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E19incrementNumEntriesEv ------------------ 367| | void decrementNumEntries() { 368| | setNumEntries(getNumEntries() - 1); 369| | } 370| 0| unsigned getNumTombstones() const { 371| 0| return static_cast(this)->getNumTombstones(); 372| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E16getNumTombstonesEv ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E16getNumTombstonesEv ------------------ 373| 0| void setNumTombstones(unsigned Num) { 374| 0| static_cast(this)->setNumTombstones(Num); 375| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E16setNumTombstonesEj ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E16setNumTombstonesEj ------------------ 376| | void incrementNumTombstones() { 377| | setNumTombstones(getNumTombstones() + 1); 378| | } 379| 0| void decrementNumTombstones() { 380| 0| setNumTombstones(getNumTombstones() - 1); 381| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E22decrementNumTombstonesEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E22decrementNumTombstonesEv ------------------ 382| 0| const BucketT *getBuckets() const { 383| 0| return static_cast(this)->getBuckets(); 384| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E10getBucketsEv ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E10getBucketsEv ------------------ 385| 0| BucketT *getBuckets() { 386| 0| return static_cast(this)->getBuckets(); 387| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E10getBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E10getBucketsEv ------------------ 388| 0| unsigned getNumBuckets() const { 389| 0| return static_cast(this)->getNumBuckets(); 390| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E13getNumBucketsEv ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E13getNumBucketsEv ------------------ 391| 0| BucketT *getBucketsEnd() { 392| 0| return getBuckets() + getNumBuckets(); 393| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E13getBucketsEndEv ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E13getBucketsEndEv ------------------ 394| | const BucketT *getBucketsEnd() const { 395| | return getBuckets() + getNumBuckets(); 396| | } 397| | 398| 0| void grow(unsigned AtLeast) { 399| 0| static_cast(this)->grow(AtLeast); 400| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E4growEj ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E4growEj ------------------ 401| | 402| | void shrink_and_clear() { 403| | static_cast(this)->shrink_and_clear(); 404| | } 405| | 406| | 407| | BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, 408| | BucketT *TheBucket) { 409| | TheBucket = InsertIntoBucketImpl(Key, TheBucket); 410| | 411| | TheBucket->getFirst() = Key; 412| | new (&TheBucket->getSecond()) ValueT(Value); 413| | return TheBucket; 414| | } 415| | 416| | BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, 417| 0| BucketT *TheBucket) { 418| 0| TheBucket = InsertIntoBucketImpl(Key, TheBucket); 419| 0| 420| 0| TheBucket->getFirst() = Key; 421| 0| new (&TheBucket->getSecond()) ValueT(std::move(Value)); 422| 0| return TheBucket; 423| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E16InsertIntoBucketERKS2_OyPS7_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E16InsertIntoBucketERKyOS2_PS7_ ------------------ 424| | 425| | BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { 426| | TheBucket = InsertIntoBucketImpl(Key, TheBucket); 427| | 428| | TheBucket->getFirst() = std::move(Key); 429| | new (&TheBucket->getSecond()) ValueT(std::move(Value)); 430| | return TheBucket; 431| | } 432| | 433| 0| BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { 434| 0| // If the load of the hash table is more than 3/4, or if fewer than 1/8 of 435| 0| // the buckets are empty (meaning that many are filled with tombstones), 436| 0| // grow the table. 437| 0| // 438| 0| // The later case is tricky. For example, if we had one empty bucket with 439| 0| // tons of tombstones, failing lookups (e.g. for insertion) would have to 440| 0| // probe almost the entire table until it found the empty bucket. If the 441| 0| // table completely filled with tombstones, no lookup would ever succeed, 442| 0| // causing infinite loops in lookup. 443| 0| unsigned NewNumEntries = getNumEntries() + 1; 444| 0| unsigned NumBuckets = getNumBuckets(); 445| 0| if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { 446| 0| this->grow(NumBuckets * 2); 447| 0| LookupBucketFor(Key, TheBucket); 448| 0| NumBuckets = getNumBuckets(); 449| 0| } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= 450| 0| NumBuckets/8)) { 451| 0| this->grow(NumBuckets); 452| 0| LookupBucketFor(Key, TheBucket); 453| 0| } 454| 0| assert(TheBucket); 455| 0| 456| 0| // Only update the state after we've grown our bucket space appropriately 457| 0| // so that when growing buckets we have self-consistent entry count. 458| 0| incrementNumEntries(); 459| 0| 460| 0| // If we are writing over a tombstone, remember this. 461| 0| const KeyT EmptyKey = getEmptyKey(); 462| 0| if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) 463| 0| decrementNumTombstones(); 464| 0| 465| 0| return TheBucket; 466| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E20InsertIntoBucketImplERKS2_PS7_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E20InsertIntoBucketImplERKyPS7_ ------------------ 467| | 468| | /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in 469| | /// FoundBucket. If the bucket contains the key and a value, this returns 470| | /// true, otherwise it returns a bucket with an empty marker or tombstone and 471| | /// returns false. 472| | template 473| | bool LookupBucketFor(const LookupKeyT &Val, 474| 0| const BucketT *&FoundBucket) const { 475| 0| const BucketT *BucketsPtr = getBuckets(); 476| 0| const unsigned NumBuckets = getNumBuckets(); 477| 0| 478| 0| if (NumBuckets == 0) { 479| 0| FoundBucket = nullptr; 480| 0| return false; 481| 0| } 482| 0| 483| 0| // FoundTombstone - Keep track of whether we find a tombstone while probing. 484| 0| const BucketT *FoundTombstone = nullptr; 485| 0| const KeyT EmptyKey = getEmptyKey(); 486| 0| const KeyT TombstoneKey = getTombstoneKey(); 487| 0| assert(!KeyInfoT::isEqual(Val, EmptyKey) && 488| 0| !KeyInfoT::isEqual(Val, TombstoneKey) && 489| 0| "Empty/Tombstone value shouldn't be inserted into map!"); 490| 0| 491| 0| unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); 492| 0| unsigned ProbeAmt = 1; 493| 0| while (1) { 494| 0| const BucketT *ThisBucket = BucketsPtr + BucketNo; 495| 0| // Found Val's bucket? If so, return it. 496| 0| if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { 497| 0| FoundBucket = ThisBucket; 498| 0| return true; 499| 0| } 500| 0| 501| 0| // If we found an empty bucket, the key doesn't exist in the set. 502| 0| // Insert it and return the default value. 503| 0| if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { 504| 0| // If we've already seen a tombstone while probing, fill it in instead 505| 0| // of the empty bucket we eventually probed to. 506| 0| FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; 507| 0| return false; 508| 0| } 509| 0| 510| 0| // If this is a tombstone, remember it. If Val ends up not in the map, we 511| 0| // prefer to return it than something that would require more probing. 512| 0| if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && 513| 0| !FoundTombstone) 514| 0| FoundTombstone = ThisBucket; // Remember the first tombstone found. 515| 0| 516| 0| // Otherwise, it's a hash collision or a tombstone, continue quadratic 517| 0| // probing. 518| 0| BucketNo += ProbeAmt++; 519| 0| BucketNo &= (NumBuckets-1); 520| 0| } 521| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E15LookupBucketForIyEEbRKT_RPKS7_ ------------------ | Unexecuted instantiation: _ZNK4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E15LookupBucketForIS2_EEbRKT_RPKS7_ ------------------ 522| | 523| | template 524| 0| bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { 525| 0| const BucketT *ConstFoundBucket; 526| 0| bool Result = const_cast(this) 527| 0| ->LookupBucketFor(Val, ConstFoundBucket); 528| 0| FoundBucket = const_cast(ConstFoundBucket); 529| 0| return Result; 530| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS2_EEEEyS2_S4_S7_E15LookupBucketForIyEEbRKT_RPS7_ ------------------ | Unexecuted instantiation: _ZN4llvm12DenseMapBaseINS_8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS2_EENS_6detail12DenseMapPairIS2_yEEEES2_yS4_S7_E15LookupBucketForIS2_EEbRKT_RPS7_ ------------------ 531| | 532| |public: 533| | /// Return the approximate size (in bytes) of the actual map. 534| | /// This is just the raw memory used by DenseMap. 535| | /// If entries are pointers to objects, the size of the referenced objects 536| | /// are not included. 537| | size_t getMemorySize() const { 538| | return getNumBuckets() * sizeof(BucketT); 539| | } 540| |}; 541| | 542| |template , 544| | typename BucketT = detail::DenseMapPair> 545| |class DenseMap : public DenseMapBase, 546| | KeyT, ValueT, KeyInfoT, BucketT> { 547| | // Lift some types from the dependent base class into this class for 548| | // simplicity of referring to them. 549| | typedef DenseMapBase BaseT; 550| | friend class DenseMapBase; 551| | 552| | BucketT *Buckets; 553| | unsigned NumEntries; 554| | unsigned NumTombstones; 555| | unsigned NumBuckets; 556| | 557| |public: 558| 0| explicit DenseMap(unsigned NumInitBuckets = 0) { 559| 0| init(NumInitBuckets); 560| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEEC2Ej ------------------ 561| | 562| | DenseMap(const DenseMap &other) : BaseT() { 563| | init(0); 564| | copyFrom(other); 565| | } 566| | 567| | DenseMap(DenseMap &&other) : BaseT() { 568| | init(0); 569| | swap(other); 570| | } 571| | 572| | template 573| | DenseMap(const InputIt &I, const InputIt &E) { 574| | init(NextPowerOf2(std::distance(I, E))); 575| | this->insert(I, E); 576| | } 577| | 578| 0| ~DenseMap() { 579| 0| this->destroyAll(); 580| 0| operator delete(Buckets); 581| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEED2Ev ------------------ 582| | 583| | void swap(DenseMap& RHS) { 584| | std::swap(Buckets, RHS.Buckets); 585| | std::swap(NumEntries, RHS.NumEntries); 586| | std::swap(NumTombstones, RHS.NumTombstones); 587| | std::swap(NumBuckets, RHS.NumBuckets); 588| | } 589| | 590| | DenseMap& operator=(const DenseMap& other) { 591| | if (&other != this) 592| | copyFrom(other); 593| | return *this; 594| | } 595| | 596| | DenseMap& operator=(DenseMap &&other) { 597| | this->destroyAll(); 598| | operator delete(Buckets); 599| | init(0); 600| | swap(other); 601| | return *this; 602| | } 603| | 604| | void copyFrom(const DenseMap& other) { 605| | this->destroyAll(); 606| | operator delete(Buckets); 607| | if (allocateBuckets(other.NumBuckets)) { 608| | this->BaseT::copyFrom(other); 609| | } else { 610| | NumEntries = 0; 611| | NumTombstones = 0; 612| | } 613| | } 614| | 615| 0| void init(unsigned InitBuckets) { 616| 0| if (allocateBuckets(InitBuckets)) { 617| 0| this->BaseT::initEmpty(); 618| 0| } else { 619| 0| NumEntries = 0; 620| 0| NumTombstones = 0; 621| 0| } 622| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE4initEj ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE4initEj ------------------ 623| | 624| 0| void grow(unsigned AtLeast) { 625| 0| unsigned OldNumBuckets = NumBuckets; 626| 0| BucketT *OldBuckets = Buckets; 627| 0| 628| 0| allocateBuckets(std::max(64, static_cast(NextPowerOf2(AtLeast-1)))); 629| 0| assert(Buckets); 630| 0| if (!OldBuckets) { 631| 0| this->BaseT::initEmpty(); 632| 0| return; 633| 0| } 634| 0| 635| 0| this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); 636| 0| 637| 0| // Free the old table. 638| 0| operator delete(OldBuckets); 639| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE4growEj ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE4growEj ------------------ 640| | 641| | void shrink_and_clear() { 642| | unsigned OldNumEntries = NumEntries; 643| | this->destroyAll(); 644| | 645| | // Reduce the number of buckets. 646| | unsigned NewNumBuckets = 0; 647| | if (OldNumEntries) 648| | NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); 649| | if (NewNumBuckets == NumBuckets) { 650| | this->BaseT::initEmpty(); 651| | return; 652| | } 653| | 654| | operator delete(Buckets); 655| | init(NewNumBuckets); 656| | } 657| | 658| |private: 659| 0| unsigned getNumEntries() const { 660| 0| return NumEntries; 661| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE13getNumEntriesEv ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE13getNumEntriesEv ------------------ 662| 0| void setNumEntries(unsigned Num) { 663| 0| NumEntries = Num; 664| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE13setNumEntriesEj ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE13setNumEntriesEj ------------------ 665| | 666| 0| unsigned getNumTombstones() const { 667| 0| return NumTombstones; 668| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE16getNumTombstonesEv ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE16getNumTombstonesEv ------------------ 669| 0| void setNumTombstones(unsigned Num) { 670| 0| NumTombstones = Num; 671| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE16setNumTombstonesEj ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE16setNumTombstonesEj ------------------ 672| | 673| 0| BucketT *getBuckets() const { 674| 0| return Buckets; 675| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE10getBucketsEv ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE10getBucketsEv ------------------ 676| | 677| 0| unsigned getNumBuckets() const { 678| 0| return NumBuckets; 679| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE13getNumBucketsEv ------------------ | Unexecuted instantiation: _ZNK4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE13getNumBucketsEv ------------------ 680| | 681| 0| bool allocateBuckets(unsigned Num) { 682| 0| NumBuckets = Num; 683| 0| if (NumBuckets == 0) { 684| 0| Buckets = nullptr; 685| 0| return false; 686| 0| } 687| 0| 688| 0| Buckets = static_cast(operator new(sizeof(BucketT) * NumBuckets)); 689| 0| return true; 690| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEEE15allocateBucketsEj ------------------ | Unexecuted instantiation: _ZN4llvm8DenseMapIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EEE15allocateBucketsEj ------------------ 691| |}; 692| | 693| |template , 695| | typename BucketT = detail::DenseMapPair> 696| |class SmallDenseMap 697| | : public DenseMapBase< 698| | SmallDenseMap, KeyT, 699| | ValueT, KeyInfoT, BucketT> { 700| | // Lift some types from the dependent base class into this class for 701| | // simplicity of referring to them. 702| | typedef DenseMapBase BaseT; 703| | friend class DenseMapBase; 704| | 705| | unsigned Small : 1; 706| | unsigned NumEntries : 31; 707| | unsigned NumTombstones; 708| | 709| | struct LargeRep { 710| | BucketT *Buckets; 711| | unsigned NumBuckets; 712| | }; 713| | 714| | /// A "union" of an inline bucket array and the struct representing 715| | /// a large bucket. This union will be discriminated by the 'Small' bit. 716| | AlignedCharArrayUnion storage; 717| | 718| |public: 719| | explicit SmallDenseMap(unsigned NumInitBuckets = 0) { 720| | init(NumInitBuckets); 721| | } 722| | 723| | SmallDenseMap(const SmallDenseMap &other) : BaseT() { 724| | init(0); 725| | copyFrom(other); 726| | } 727| | 728| | SmallDenseMap(SmallDenseMap &&other) : BaseT() { 729| | init(0); 730| | swap(other); 731| | } 732| | 733| | template 734| | SmallDenseMap(const InputIt &I, const InputIt &E) { 735| | init(NextPowerOf2(std::distance(I, E))); 736| | this->insert(I, E); 737| | } 738| | 739| | ~SmallDenseMap() { 740| | this->destroyAll(); 741| | deallocateBuckets(); 742| | } 743| | 744| | void swap(SmallDenseMap& RHS) { 745| | unsigned TmpNumEntries = RHS.NumEntries; 746| | RHS.NumEntries = NumEntries; 747| | NumEntries = TmpNumEntries; 748| | std::swap(NumTombstones, RHS.NumTombstones); 749| | 750| | const KeyT EmptyKey = this->getEmptyKey(); 751| | const KeyT TombstoneKey = this->getTombstoneKey(); 752| | if (Small && RHS.Small) { 753| | // If we're swapping inline bucket arrays, we have to cope with some of 754| | // the tricky bits of DenseMap's storage system: the buckets are not 755| | // fully initialized. Thus we swap every key, but we may have 756| | // a one-directional move of the value. 757| | for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 758| | BucketT *LHSB = &getInlineBuckets()[i], 759| | *RHSB = &RHS.getInlineBuckets()[i]; 760| | bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && 761| | !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); 762| | bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && 763| | !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); 764| | if (hasLHSValue && hasRHSValue) { 765| | // Swap together if we can... 766| | std::swap(*LHSB, *RHSB); 767| | continue; 768| | } 769| | // Swap separately and handle any assymetry. 770| | std::swap(LHSB->getFirst(), RHSB->getFirst()); 771| | if (hasLHSValue) { 772| | new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); 773| | LHSB->getSecond().~ValueT(); 774| | } else if (hasRHSValue) { 775| | new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); 776| | RHSB->getSecond().~ValueT(); 777| | } 778| | } 779| | return; 780| | } 781| | if (!Small && !RHS.Small) { 782| | std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); 783| | std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); 784| | return; 785| | } 786| | 787| | SmallDenseMap &SmallSide = Small ? *this : RHS; 788| | SmallDenseMap &LargeSide = Small ? RHS : *this; 789| | 790| | // First stash the large side's rep and move the small side across. 791| | LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); 792| | LargeSide.getLargeRep()->~LargeRep(); 793| | LargeSide.Small = true; 794| | // This is similar to the standard move-from-old-buckets, but the bucket 795| | // count hasn't actually rotated in this case. So we have to carefully 796| | // move construct the keys and values into their new locations, but there 797| | // is no need to re-hash things. 798| | for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 799| | BucketT *NewB = &LargeSide.getInlineBuckets()[i], 800| | *OldB = &SmallSide.getInlineBuckets()[i]; 801| | new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); 802| | OldB->getFirst().~KeyT(); 803| | if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && 804| | !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { 805| | new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); 806| | OldB->getSecond().~ValueT(); 807| | } 808| | } 809| | 810| | // The hard part of moving the small buckets across is done, just move 811| | // the TmpRep into its new home. 812| | SmallSide.Small = false; 813| | new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); 814| | } 815| | 816| | SmallDenseMap& operator=(const SmallDenseMap& other) { 817| | if (&other != this) 818| | copyFrom(other); 819| | return *this; 820| | } 821| | 822| | SmallDenseMap& operator=(SmallDenseMap &&other) { 823| | this->destroyAll(); 824| | deallocateBuckets(); 825| | init(0); 826| | swap(other); 827| | return *this; 828| | } 829| | 830| | void copyFrom(const SmallDenseMap& other) { 831| | this->destroyAll(); 832| | deallocateBuckets(); 833| | Small = true; 834| | if (other.getNumBuckets() > InlineBuckets) { 835| | Small = false; 836| | new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); 837| | } 838| | this->BaseT::copyFrom(other); 839| | } 840| | 841| | void init(unsigned InitBuckets) { 842| | Small = true; 843| | if (InitBuckets > InlineBuckets) { 844| | Small = false; 845| | new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); 846| | } 847| | this->BaseT::initEmpty(); 848| | } 849| | 850| | void grow(unsigned AtLeast) { 851| | if (AtLeast >= InlineBuckets) 852| | AtLeast = std::max(64, NextPowerOf2(AtLeast-1)); 853| | 854| | if (Small) { 855| | if (AtLeast < InlineBuckets) 856| | return; // Nothing to do. 857| | 858| | // First move the inline buckets into a temporary storage. 859| | AlignedCharArrayUnion TmpStorage; 860| | BucketT *TmpBegin = reinterpret_cast(TmpStorage.buffer); 861| | BucketT *TmpEnd = TmpBegin; 862| | 863| | // Loop over the buckets, moving non-empty, non-tombstones into the 864| | // temporary storage. Have the loop move the TmpEnd forward as it goes. 865| | const KeyT EmptyKey = this->getEmptyKey(); 866| | const KeyT TombstoneKey = this->getTombstoneKey(); 867| | for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { 868| | if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 869| | !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 870| | assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && 871| | "Too many inline buckets!"); 872| | new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); 873| | new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); 874| | ++TmpEnd; 875| | P->getSecond().~ValueT(); 876| | } 877| | P->getFirst().~KeyT(); 878| | } 879| | 880| | // Now make this map use the large rep, and move all the entries back 881| | // into it. 882| | Small = false; 883| | new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 884| | this->moveFromOldBuckets(TmpBegin, TmpEnd); 885| | return; 886| | } 887| | 888| | LargeRep OldRep = std::move(*getLargeRep()); 889| | getLargeRep()->~LargeRep(); 890| | if (AtLeast <= InlineBuckets) { 891| | Small = true; 892| | } else { 893| | new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 894| | } 895| | 896| | this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); 897| | 898| | // Free the old table. 899| | operator delete(OldRep.Buckets); 900| | } 901| | 902| | void shrink_and_clear() { 903| | unsigned OldSize = this->size(); 904| | this->destroyAll(); 905| | 906| | // Reduce the number of buckets. 907| | unsigned NewNumBuckets = 0; 908| | if (OldSize) { 909| | NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); 910| | if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) 911| | NewNumBuckets = 64; 912| | } 913| | if ((Small && NewNumBuckets <= InlineBuckets) || 914| | (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { 915| | this->BaseT::initEmpty(); 916| | return; 917| | } 918| | 919| | deallocateBuckets(); 920| | init(NewNumBuckets); 921| | } 922| | 923| |private: 924| | unsigned getNumEntries() const { 925| | return NumEntries; 926| | } 927| | void setNumEntries(unsigned Num) { 928| | assert(Num < INT_MAX && "Cannot support more than INT_MAX entries"); 929| | NumEntries = Num; 930| | } 931| | 932| | unsigned getNumTombstones() const { 933| | return NumTombstones; 934| | } 935| | void setNumTombstones(unsigned Num) { 936| | NumTombstones = Num; 937| | } 938| | 939| | const BucketT *getInlineBuckets() const { 940| | assert(Small); 941| | // Note that this cast does not violate aliasing rules as we assert that 942| | // the memory's dynamic type is the small, inline bucket buffer, and the 943| | // 'storage.buffer' static type is 'char *'. 944| | return reinterpret_cast(storage.buffer); 945| | } 946| | BucketT *getInlineBuckets() { 947| | return const_cast( 948| | const_cast(this)->getInlineBuckets()); 949| | } 950| | const LargeRep *getLargeRep() const { 951| | assert(!Small); 952| | // Note, same rule about aliasing as with getInlineBuckets. 953| | return reinterpret_cast(storage.buffer); 954| | } 955| | LargeRep *getLargeRep() { 956| | return const_cast( 957| | const_cast(this)->getLargeRep()); 958| | } 959| | 960| | const BucketT *getBuckets() const { 961| | return Small ? getInlineBuckets() : getLargeRep()->Buckets; 962| | } 963| | BucketT *getBuckets() { 964| | return const_cast( 965| | const_cast(this)->getBuckets()); 966| | } 967| | unsigned getNumBuckets() const { 968| | return Small ? InlineBuckets : getLargeRep()->NumBuckets; 969| | } 970| | 971| | void deallocateBuckets() { 972| | if (Small) 973| | return; 974| | 975| | operator delete(getLargeRep()->Buckets); 976| | getLargeRep()->~LargeRep(); 977| | } 978| | 979| | LargeRep allocateBuckets(unsigned Num) { 980| | assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); 981| | LargeRep Rep = { 982| | static_cast(operator new(sizeof(BucketT) * Num)), Num 983| | }; 984| | return Rep; 985| | } 986| |}; 987| | 988| |template 990| |class DenseMapIterator { 991| | typedef DenseMapIterator ConstIterator; 992| | friend class DenseMapIterator; 993| | 994| |public: 995| | typedef ptrdiff_t difference_type; 996| | typedef typename std::conditional::type 997| | value_type; 998| | typedef value_type *pointer; 999| | typedef value_type &reference; 1000| | typedef std::forward_iterator_tag iterator_category; 1001| |private: 1002| | pointer Ptr, End; 1003| |public: 1004| | DenseMapIterator() : Ptr(nullptr), End(nullptr) {} 1005| | 1006| | DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false) 1007| 0| : Ptr(Pos), End(E) { 1008| 0| if (!NoAdvance) AdvancePastEmptyBuckets(); 1009| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb0EEC2EPS6_S8_b ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb0EEC2EPS6_S8_b ------------------ 1010| | 1011| | // Converting ctor from non-const iterators to const iterators. SFINAE'd out 1012| | // for const iterator destinations so it doesn't end up as a user defined copy 1013| | // constructor. 1014| | template ::type> 1016| | DenseMapIterator( 1017| | const DenseMapIterator &I) 1018| 0| : Ptr(I.Ptr), End(I.End) {} ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb1EEC2ILb0EvEERKNS0_IyS1_S3_S6_XT_EEE ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb1EEC2ILb0EvEERKNS0_IS1_yS3_S6_XT_EEE ------------------ 1019| | 1020| | reference operator*() const { 1021| | return *Ptr; 1022| | } 1023| 0| pointer operator->() const { 1024| 0| return Ptr; 1025| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb1EEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb0EEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb1EEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb0EEptEv ------------------ 1026| | 1027| | bool operator==(const ConstIterator &RHS) const { 1028| | return Ptr == RHS.operator->(); 1029| | } 1030| 0| bool operator!=(const ConstIterator &RHS) const { 1031| 0| return Ptr != RHS.operator->(); 1032| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb0EEneERKNS0_IyS1_S3_S6_Lb1EEE ------------------ | Unexecuted instantiation: _ZNK4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb0EEneERKNS0_IS1_yS3_S6_Lb1EEE ------------------ 1033| | 1034| | inline DenseMapIterator& operator++() { // Preincrement 1035| | ++Ptr; 1036| | AdvancePastEmptyBuckets(); 1037| | return *this; 1038| | } 1039| | DenseMapIterator operator++(int) { // Postincrement 1040| | DenseMapIterator tmp = *this; ++*this; return tmp; 1041| | } 1042| | 1043| |private: 1044| 0| void AdvancePastEmptyBuckets() { 1045| 0| const KeyT Empty = KeyInfoT::getEmptyKey(); 1046| 0| const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 1047| 0| 1048| 0| while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || 1049| 0| KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) 1050| 0| ++Ptr; 1051| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorIy7DBKeyIDNS_12DenseMapInfoIyEENS_6detail12DenseMapPairIyS1_EELb0EE23AdvancePastEmptyBucketsEv ------------------ | Unexecuted instantiation: _ZN4llvm16DenseMapIteratorI7DBKeyIDyNS_12DenseMapInfoIS1_EENS_6detail12DenseMapPairIS1_yEELb0EE23AdvancePastEmptyBucketsEv ------------------ 1052| |}; 1053| | 1054| |template 1055| |static inline size_t 1056| |capacity_in_bytes(const DenseMap &X) { 1057| | return X.getMemorySize(); 1058| |} 1059| | 1060| |} // end namespace llvm 1061| | 1062| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/DenseMapInfo.h: 1| |//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines DenseMapInfo traits for DenseMap. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_DENSEMAPINFO_H 15| |#define LLVM_ADT_DENSEMAPINFO_H 16| | 17| |#include "llvm/Support/PointerLikeTypeTraits.h" 18| |#include "llvm/Support/type_traits.h" 19| | 20| |namespace llvm { 21| | 22| |template 23| |struct DenseMapInfo { 24| | //static inline T getEmptyKey(); 25| | //static inline T getTombstoneKey(); 26| | //static unsigned getHashValue(const T &Val); 27| | //static bool isEqual(const T &LHS, const T &RHS); 28| |}; 29| | 30| |// Provide DenseMapInfo for all pointers. 31| |template 32| |struct DenseMapInfo { 33| | static inline T* getEmptyKey() { 34| | uintptr_t Val = static_cast(-1); 35| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 36| | return reinterpret_cast(Val); 37| | } 38| | static inline T* getTombstoneKey() { 39| | uintptr_t Val = static_cast(-2); 40| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 41| | return reinterpret_cast(Val); 42| | } 43| | static unsigned getHashValue(const T *PtrVal) { 44| | return (unsigned((uintptr_t)PtrVal) >> 4) ^ 45| | (unsigned((uintptr_t)PtrVal) >> 9); 46| | } 47| | static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } 48| |}; 49| | 50| |// Provide DenseMapInfo for chars. 51| |template<> struct DenseMapInfo { 52| 0| static inline char getEmptyKey() { return ~0; } 53| 0| static inline char getTombstoneKey() { return ~0 - 1; } 54| 0| static unsigned getHashValue(const char& Val) { return Val * 37U; } 55| 0| static bool isEqual(const char &LHS, const char &RHS) { 56| 0| return LHS == RHS; 57| 0| } 58| |}; 59| | 60| |// Provide DenseMapInfo for unsigned ints. 61| |template<> struct DenseMapInfo { 62| 0| static inline unsigned getEmptyKey() { return ~0U; } 63| 0| static inline unsigned getTombstoneKey() { return ~0U - 1; } 64| 0| static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } 65| 0| static bool isEqual(const unsigned& LHS, const unsigned& RHS) { 66| 0| return LHS == RHS; 67| 0| } 68| |}; 69| | 70| |// Provide DenseMapInfo for unsigned longs. 71| |template<> struct DenseMapInfo { 72| | static inline unsigned long getEmptyKey() { return ~0UL; } 73| | static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } 74| | static unsigned getHashValue(const unsigned long& Val) { 75| | return (unsigned)(Val * 37UL); 76| | } 77| | static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { 78| | return LHS == RHS; 79| | } 80| |}; 81| | 82| |// Provide DenseMapInfo for unsigned long longs. 83| |template<> struct DenseMapInfo { 84| 0| static inline unsigned long long getEmptyKey() { return ~0ULL; } 85| 0| static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } 86| 0| static unsigned getHashValue(const unsigned long long& Val) { 87| 0| return (unsigned)(Val * 37ULL); 88| 0| } 89| | static bool isEqual(const unsigned long long& LHS, 90| 0| const unsigned long long& RHS) { 91| 0| return LHS == RHS; 92| 0| } 93| |}; 94| | 95| |// Provide DenseMapInfo for ints. 96| |template<> struct DenseMapInfo { 97| 0| static inline int getEmptyKey() { return 0x7fffffff; } 98| 0| static inline int getTombstoneKey() { return -0x7fffffff - 1; } 99| 0| static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } 100| 0| static bool isEqual(const int& LHS, const int& RHS) { 101| 0| return LHS == RHS; 102| 0| } 103| |}; 104| | 105| |// Provide DenseMapInfo for longs. 106| |template<> struct DenseMapInfo { 107| 0| static inline long getEmptyKey() { 108| 0| return (1UL << (sizeof(long) * 8 - 1)) - 1UL; 109| 0| } 110| 0| static inline long getTombstoneKey() { return getEmptyKey() - 1L; } 111| 0| static unsigned getHashValue(const long& Val) { 112| 0| return (unsigned)(Val * 37UL); 113| 0| } 114| 0| static bool isEqual(const long& LHS, const long& RHS) { 115| 0| return LHS == RHS; 116| 0| } 117| |}; 118| | 119| |// Provide DenseMapInfo for long longs. 120| |template<> struct DenseMapInfo { 121| 0| static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } 122| 0| static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } 123| 0| static unsigned getHashValue(const long long& Val) { 124| 0| return (unsigned)(Val * 37ULL); 125| 0| } 126| | static bool isEqual(const long long& LHS, 127| 0| const long long& RHS) { 128| 0| return LHS == RHS; 129| 0| } 130| |}; 131| | 132| |// Provide DenseMapInfo for all pairs whose members have info. 133| |template 134| |struct DenseMapInfo > { 135| | typedef std::pair Pair; 136| | typedef DenseMapInfo FirstInfo; 137| | typedef DenseMapInfo SecondInfo; 138| | 139| | static inline Pair getEmptyKey() { 140| | return std::make_pair(FirstInfo::getEmptyKey(), 141| | SecondInfo::getEmptyKey()); 142| | } 143| | static inline Pair getTombstoneKey() { 144| | return std::make_pair(FirstInfo::getTombstoneKey(), 145| | SecondInfo::getTombstoneKey()); 146| | } 147| | static unsigned getHashValue(const Pair& PairVal) { 148| | uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 149| | | (uint64_t)SecondInfo::getHashValue(PairVal.second); 150| | key += ~(key << 32); 151| | key ^= (key >> 22); 152| | key += ~(key << 13); 153| | key ^= (key >> 8); 154| | key += (key << 3); 155| | key ^= (key >> 15); 156| | key += ~(key << 27); 157| | key ^= (key >> 31); 158| | return (unsigned)key; 159| | } 160| | static bool isEqual(const Pair &LHS, const Pair &RHS) { 161| | return FirstInfo::isEqual(LHS.first, RHS.first) && 162| | SecondInfo::isEqual(LHS.second, RHS.second); 163| | } 164| |}; 165| | 166| |} // end namespace llvm 167| | 168| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/STLExtras.h: 1| |//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some templates that are useful if you are working with the 11| |// STL at all. 12| |// 13| |// No library is required when using these functions. 14| |// 15| |//===----------------------------------------------------------------------===// 16| | 17| |#ifndef LLVM_ADT_STLEXTRAS_H 18| |#define LLVM_ADT_STLEXTRAS_H 19| | 20| |#include "llvm/Support/Compiler.h" 21| |#include 22| |#include // for std::size_t 23| |#include // for qsort 24| |#include 25| |#include 26| |#include 27| |#include // for std::pair 28| | 29| |namespace llvm { 30| | 31| |//===----------------------------------------------------------------------===// 32| |// Extra additions to 33| |//===----------------------------------------------------------------------===// 34| | 35| |template 36| |struct identity : public std::unary_function { 37| | Ty &operator()(Ty &self) const { 38| | return self; 39| | } 40| | const Ty &operator()(const Ty &self) const { 41| | return self; 42| | } 43| |}; 44| | 45| |template 46| |struct less_ptr : public std::binary_function { 47| | bool operator()(const Ty* left, const Ty* right) const { 48| | return *left < *right; 49| | } 50| |}; 51| | 52| |template 53| |struct greater_ptr : public std::binary_function { 54| | bool operator()(const Ty* left, const Ty* right) const { 55| | return *right < *left; 56| | } 57| |}; 58| | 59| |/// An efficient, type-erasing, non-owning reference to a callable. This is 60| |/// intended for use as the type of a function parameter that is not used 61| |/// after the function in question returns. 62| |/// 63| |/// This class does not own the callable, so it is not in general safe to store 64| |/// a function_ref. 65| |template class function_ref; 66| | 67| |template 68| |class function_ref { 69| | Ret (*callback)(intptr_t callable, Params ...params); 70| | intptr_t callable; 71| | 72| | template 73| | static Ret callback_fn(intptr_t callable, Params ...params) { 74| | return (*reinterpret_cast(callable))( 75| | std::forward(params)...); 76| | } 77| | 78| |public: 79| | template 80| | function_ref(Callable &&callable, 81| | typename std::enable_if< 82| | !std::is_same::type, 83| | function_ref>::value>::type * = nullptr) 84| | : callback(callback_fn::type>), 85| | callable(reinterpret_cast(&callable)) {} 86| | Ret operator()(Params ...params) const { 87| | return callback(callable, std::forward(params)...); 88| | } 89| |}; 90| | 91| |// deleter - Very very very simple method that is used to invoke operator 92| |// delete on something. It is used like this: 93| |// 94| |// for_each(V.begin(), B.end(), deleter); 95| |// 96| |template 97| |inline void deleter(T *Ptr) { 98| | delete Ptr; 99| |} 100| | 101| | 102| | 103| |//===----------------------------------------------------------------------===// 104| |// Extra additions to 105| |//===----------------------------------------------------------------------===// 106| | 107| |// mapped_iterator - This is a simple iterator adapter that causes a function to 108| |// be dereferenced whenever operator* is invoked on the iterator. 109| |// 110| |template 111| |class mapped_iterator { 112| | RootIt current; 113| | UnaryFunc Fn; 114| |public: 115| | typedef typename std::iterator_traits::iterator_category 116| | iterator_category; 117| | typedef typename std::iterator_traits::difference_type 118| | difference_type; 119| | typedef typename UnaryFunc::result_type value_type; 120| | 121| | typedef void pointer; 122| | //typedef typename UnaryFunc::result_type *pointer; 123| | typedef void reference; // Can't modify value returned by fn 124| | 125| | typedef RootIt iterator_type; 126| | 127| | inline const RootIt &getCurrent() const { return current; } 128| | inline const UnaryFunc &getFunc() const { return Fn; } 129| | 130| | inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) 131| | : current(I), Fn(F) {} 132| | 133| | inline value_type operator*() const { // All this work to do this 134| | return Fn(*current); // little change 135| | } 136| | 137| | mapped_iterator &operator++() { 138| | ++current; 139| | return *this; 140| | } 141| | mapped_iterator &operator--() { 142| | --current; 143| | return *this; 144| | } 145| | mapped_iterator operator++(int) { 146| | mapped_iterator __tmp = *this; 147| | ++current; 148| | return __tmp; 149| | } 150| | mapped_iterator operator--(int) { 151| | mapped_iterator __tmp = *this; 152| | --current; 153| | return __tmp; 154| | } 155| | mapped_iterator operator+(difference_type n) const { 156| | return mapped_iterator(current + n, Fn); 157| | } 158| | mapped_iterator &operator+=(difference_type n) { 159| | current += n; 160| | return *this; 161| | } 162| | mapped_iterator operator-(difference_type n) const { 163| | return mapped_iterator(current - n, Fn); 164| | } 165| | mapped_iterator &operator-=(difference_type n) { 166| | current -= n; 167| | return *this; 168| | } 169| | reference operator[](difference_type n) const { return *(*this + n); } 170| | 171| | bool operator!=(const mapped_iterator &X) const { return !operator==(X); } 172| | bool operator==(const mapped_iterator &X) const { 173| | return current == X.current; 174| | } 175| | bool operator<(const mapped_iterator &X) const { return current < X.current; } 176| | 177| | difference_type operator-(const mapped_iterator &X) const { 178| | return current - X.current; 179| | } 180| |}; 181| | 182| |template 183| |inline mapped_iterator 184| |operator+(typename mapped_iterator::difference_type N, 185| | const mapped_iterator &X) { 186| | return mapped_iterator(X.getCurrent() - N, X.getFunc()); 187| |} 188| | 189| | 190| |// map_iterator - Provide a convenient way to create mapped_iterators, just like 191| |// make_pair is useful for creating pairs... 192| |// 193| |template 194| |inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { 195| | return mapped_iterator(I, F); 196| |} 197| | 198| |//===----------------------------------------------------------------------===// 199| |// Extra additions to 200| |//===----------------------------------------------------------------------===// 201| | 202| |/// \brief Function object to check whether the first component of a std::pair 203| |/// compares less than the first component of another std::pair. 204| |struct less_first { 205| | template bool operator()(const T &lhs, const T &rhs) const { 206| | return lhs.first < rhs.first; 207| | } 208| |}; 209| | 210| |/// \brief Function object to check whether the second component of a std::pair 211| |/// compares less than the second component of another std::pair. 212| |struct less_second { 213| | template bool operator()(const T &lhs, const T &rhs) const { 214| | return lhs.second < rhs.second; 215| | } 216| |}; 217| | 218| |// A subset of N3658. More stuff can be added as-needed. 219| | 220| |/// \brief Represents a compile-time sequence of integers. 221| |template struct integer_sequence { 222| | typedef T value_type; 223| | 224| | static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } 225| |}; 226| | 227| |/// \brief Alias for the common case of a sequence of size_ts. 228| |template 229| |struct index_sequence : integer_sequence {}; 230| | 231| |template 232| |struct build_index_impl : build_index_impl {}; 233| |template 234| |struct build_index_impl<0, I...> : index_sequence {}; 235| | 236| |/// \brief Creates a compile-time integer sequence for a parameter pack. 237| |template 238| |struct index_sequence_for : build_index_impl {}; 239| | 240| |//===----------------------------------------------------------------------===// 241| |// Extra additions for arrays 242| |//===----------------------------------------------------------------------===// 243| | 244| |/// Find the length of an array. 245| |template 246| |LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { 247| | return N; 248| |} 249| | 250| |/// Adapt std::less for array_pod_sort. 251| |template 252| |inline int array_pod_sort_comparator(const void *P1, const void *P2) { 253| | if (std::less()(*reinterpret_cast(P1), 254| | *reinterpret_cast(P2))) 255| | return -1; 256| | if (std::less()(*reinterpret_cast(P2), 257| | *reinterpret_cast(P1))) 258| | return 1; 259| | return 0; 260| |} 261| | 262| |/// get_array_pod_sort_comparator - This is an internal helper function used to 263| |/// get type deduction of T right. 264| |template 265| |inline int (*get_array_pod_sort_comparator(const T &)) 266| | (const void*, const void*) { 267| | return array_pod_sort_comparator; 268| |} 269| | 270| | 271| |/// array_pod_sort - This sorts an array with the specified start and end 272| |/// extent. This is just like std::sort, except that it calls qsort instead of 273| |/// using an inlined template. qsort is slightly slower than std::sort, but 274| |/// most sorts are not performance critical in LLVM and std::sort has to be 275| |/// template instantiated for each type, leading to significant measured code 276| |/// bloat. This function should generally be used instead of std::sort where 277| |/// possible. 278| |/// 279| |/// This function assumes that you have simple POD-like types that can be 280| |/// compared with std::less and can be moved with memcpy. If this isn't true, 281| |/// you should use std::sort. 282| |/// 283| |/// NOTE: If qsort_r were portable, we could allow a custom comparator and 284| |/// default to std::less. 285| |template 286| |inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 287| | // Don't inefficiently call qsort with one element or trigger undefined 288| | // behavior with an empty sequence. 289| | auto NElts = End - Start; 290| | if (NElts <= 1) return; 291| | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 292| |} 293| | 294| |template 295| |inline void array_pod_sort( 296| | IteratorTy Start, IteratorTy End, 297| | int (*Compare)( 298| | const typename std::iterator_traits::value_type *, 299| | const typename std::iterator_traits::value_type *)) { 300| | // Don't inefficiently call qsort with one element or trigger undefined 301| | // behavior with an empty sequence. 302| | auto NElts = End - Start; 303| | if (NElts <= 1) return; 304| | qsort(&*Start, NElts, sizeof(*Start), 305| | reinterpret_cast(Compare)); 306| |} 307| | 308| |//===----------------------------------------------------------------------===// 309| |// Extra additions to 310| |//===----------------------------------------------------------------------===// 311| | 312| |/// For a container of pointers, deletes the pointers and then clears the 313| |/// container. 314| |template 315| |void DeleteContainerPointers(Container &C) { 316| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 317| | delete *I; 318| | C.clear(); 319| |} 320| | 321| |/// In a container of pairs (usually a map) whose second element is a pointer, 322| |/// deletes the second elements and then clears the container. 323| |template 324| |void DeleteContainerSeconds(Container &C) { 325| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 326| | delete I->second; 327| | C.clear(); 328| |} 329| | 330| |//===----------------------------------------------------------------------===// 331| |// Extra additions to 332| |//===----------------------------------------------------------------------===// 333| | 334| |// Implement make_unique according to N3656. 335| | 336| |/// \brief Constructs a `new T()` with the given args and returns a 337| |/// `unique_ptr` which owns the object. 338| |/// 339| |/// Example: 340| |/// 341| |/// auto p = make_unique(); 342| |/// auto p = make_unique>(0, 1); 343| |template 344| |typename std::enable_if::value, std::unique_ptr>::type 345| 0|make_unique(Args &&... args) { 346| 0| return std::unique_ptr(new T(std::forward(args)...)); 347| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm11make_uniqueIN7llbuild4core16BuildEngineTraceEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS4_10unique_ptrIS6_NS4_14default_deleteIS6_EEEEE4typeEDpOT0_ ------------------ | Unexecuted instantiation: SQLiteBuildDB.cpp:_ZN4llvm11make_uniqueIN12_GLOBAL__N_113SQLiteBuildDBEJRNS_9StringRefERjEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS6_10unique_ptrIS8_NS6_14default_deleteIS8_EEEEE4typeEDpOT0_ ------------------ 348| | 349| |/// \brief Constructs a `new T[n]` with the given args and returns a 350| |/// `unique_ptr` which owns the object. 351| |/// 352| |/// \param n size of the new array. 353| |/// 354| |/// Example: 355| |/// 356| |/// auto p = make_unique(2); // value-initializes the array with 0's. 357| |template 358| |typename std::enable_if::value && std::extent::value == 0, 359| | std::unique_ptr>::type 360| |make_unique(size_t n) { 361| | return std::unique_ptr(new typename std::remove_extent::type[n]()); 362| |} 363| | 364| |/// This function isn't used and is only here to provide better compile errors. 365| |template 366| |typename std::enable_if::value != 0>::type 367| |make_unique(Args &&...) = delete; 368| | 369| |struct FreeDeleter { 370| 0| void operator()(void* v) { 371| 0| ::free(v); 372| 0| } 373| |}; 374| | 375| |template 376| |struct pair_hash { 377| | size_t operator()(const std::pair &P) const { 378| | return std::hash()(P.first) * 31 + std::hash()(P.second); 379| | } 380| |}; 381| | 382| |/// A functor like C++14's std::less in its absence. 383| |struct less { 384| | template bool operator()(A &&a, B &&b) const { 385| | return std::forward(a) < std::forward(b); 386| | } 387| |}; 388| | 389| |/// A functor like C++14's std::equal in its absence. 390| |struct equal { 391| | template bool operator()(A &&a, B &&b) const { 392| | return std::forward(a) == std::forward(b); 393| | } 394| |}; 395| | 396| |/// Binary functor that adapts to any other binary functor after dereferencing 397| |/// operands. 398| |template struct deref { 399| | T func; 400| | // Could be further improved to cope with non-derivable functors and 401| | // non-binary functors (should be a variadic template member function 402| | // operator()). 403| | template 404| | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { 405| | assert(lhs); 406| | assert(rhs); 407| | return func(*lhs, *rhs); 408| | } 409| |}; 410| | 411| |} // End llvm namespace 412| | 413| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallString.h: 1| |//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallString class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLSTRING_H 15| |#define LLVM_ADT_SMALLSTRING_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |namespace llvm { 21| | 22| |/// SmallString - A SmallString is just a SmallVector with methods and accessors 23| |/// that make it work better as a string (e.g. operator+ etc). 24| |template 25| |class SmallString : public SmallVector { 26| |public: 27| | /// Default ctor - Initialize to empty. 28| 0| SmallString() {} 29| | 30| | /// Initialize from a StringRef. 31| | SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} 32| | 33| | /// Initialize with a range. 34| | template 35| | SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} 36| | 37| | // Note that in order to add new overloads for append & assign, we have to 38| | // duplicate the inherited versions so as not to inadvertently hide them. 39| | 40| | /// @} 41| | /// @name String Assignment 42| | /// @{ 43| | 44| | /// Assign from a repeated element. 45| | void assign(size_t NumElts, char Elt) { 46| | this->SmallVectorImpl::assign(NumElts, Elt); 47| | } 48| | 49| | /// Assign from an iterator pair. 50| | template 51| | void assign(in_iter S, in_iter E) { 52| | this->clear(); 53| | SmallVectorImpl::append(S, E); 54| | } 55| | 56| | /// Assign from a StringRef. 57| | void assign(StringRef RHS) { 58| | this->clear(); 59| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 60| | } 61| | 62| | /// Assign from a SmallVector. 63| | void assign(const SmallVectorImpl &RHS) { 64| | this->clear(); 65| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 66| | } 67| | 68| | /// @} 69| | /// @name String Concatenation 70| | /// @{ 71| | 72| | /// Append from an iterator pair. 73| | template 74| | void append(in_iter S, in_iter E) { 75| | SmallVectorImpl::append(S, E); 76| | } 77| | 78| | void append(size_t NumInputs, char Elt) { 79| | SmallVectorImpl::append(NumInputs, Elt); 80| | } 81| | 82| | 83| | /// Append from a StringRef. 84| | void append(StringRef RHS) { 85| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 86| | } 87| | 88| | /// Append from a SmallVector. 89| | void append(const SmallVectorImpl &RHS) { 90| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 91| | } 92| | 93| | /// @} 94| | /// @name String Comparison 95| | /// @{ 96| | 97| | /// Check for string equality. This is more efficient than compare() when 98| | /// the relative ordering of inequal strings isn't needed. 99| | bool equals(StringRef RHS) const { 100| | return str().equals(RHS); 101| | } 102| | 103| | /// Check for string equality, ignoring case. 104| | bool equals_lower(StringRef RHS) const { 105| | return str().equals_lower(RHS); 106| | } 107| | 108| | /// Compare two strings; the result is -1, 0, or 1 if this string is 109| | /// lexicographically less than, equal to, or greater than the \p RHS. 110| | int compare(StringRef RHS) const { 111| | return str().compare(RHS); 112| | } 113| | 114| | /// compare_lower - Compare two strings, ignoring case. 115| | int compare_lower(StringRef RHS) const { 116| | return str().compare_lower(RHS); 117| | } 118| | 119| | /// compare_numeric - Compare two strings, treating sequences of digits as 120| | /// numbers. 121| | int compare_numeric(StringRef RHS) const { 122| | return str().compare_numeric(RHS); 123| | } 124| | 125| | /// @} 126| | /// @name String Predicates 127| | /// @{ 128| | 129| | /// startswith - Check if this string starts with the given \p Prefix. 130| | bool startswith(StringRef Prefix) const { 131| | return str().startswith(Prefix); 132| | } 133| | 134| | /// endswith - Check if this string ends with the given \p Suffix. 135| | bool endswith(StringRef Suffix) const { 136| | return str().endswith(Suffix); 137| | } 138| | 139| | /// @} 140| | /// @name String Searching 141| | /// @{ 142| | 143| | /// find - Search for the first character \p C in the string. 144| | /// 145| | /// \return - The index of the first occurrence of \p C, or npos if not 146| | /// found. 147| | size_t find(char C, size_t From = 0) const { 148| | return str().find(C, From); 149| | } 150| | 151| | /// Search for the first string \p Str in the string. 152| | /// 153| | /// \returns The index of the first occurrence of \p Str, or npos if not 154| | /// found. 155| | size_t find(StringRef Str, size_t From = 0) const { 156| | return str().find(Str, From); 157| | } 158| | 159| | /// Search for the last character \p C in the string. 160| | /// 161| | /// \returns The index of the last occurrence of \p C, or npos if not 162| | /// found. 163| | size_t rfind(char C, size_t From = StringRef::npos) const { 164| | return str().rfind(C, From); 165| | } 166| | 167| | /// Search for the last string \p Str in the string. 168| | /// 169| | /// \returns The index of the last occurrence of \p Str, or npos if not 170| | /// found. 171| | size_t rfind(StringRef Str) const { 172| | return str().rfind(Str); 173| | } 174| | 175| | /// Find the first character in the string that is \p C, or npos if not 176| | /// found. Same as find. 177| | size_t find_first_of(char C, size_t From = 0) const { 178| | return str().find_first_of(C, From); 179| | } 180| | 181| | /// Find the first character in the string that is in \p Chars, or npos if 182| | /// not found. 183| | /// 184| | /// Complexity: O(size() + Chars.size()) 185| | size_t find_first_of(StringRef Chars, size_t From = 0) const { 186| | return str().find_first_of(Chars, From); 187| | } 188| | 189| | /// Find the first character in the string that is not \p C or npos if not 190| | /// found. 191| | size_t find_first_not_of(char C, size_t From = 0) const { 192| | return str().find_first_not_of(C, From); 193| | } 194| | 195| | /// Find the first character in the string that is not in the string 196| | /// \p Chars, or npos if not found. 197| | /// 198| | /// Complexity: O(size() + Chars.size()) 199| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const { 200| | return str().find_first_not_of(Chars, From); 201| | } 202| | 203| | /// Find the last character in the string that is \p C, or npos if not 204| | /// found. 205| | size_t find_last_of(char C, size_t From = StringRef::npos) const { 206| | return str().find_last_of(C, From); 207| | } 208| | 209| | /// Find the last character in the string that is in \p C, or npos if not 210| | /// found. 211| | /// 212| | /// Complexity: O(size() + Chars.size()) 213| | size_t find_last_of( 214| | StringRef Chars, size_t From = StringRef::npos) const { 215| | return str().find_last_of(Chars, From); 216| | } 217| | 218| | /// @} 219| | /// @name Helpful Algorithms 220| | /// @{ 221| | 222| | /// Return the number of occurrences of \p C in the string. 223| | size_t count(char C) const { 224| | return str().count(C); 225| | } 226| | 227| | /// Return the number of non-overlapped occurrences of \p Str in the 228| | /// string. 229| | size_t count(StringRef Str) const { 230| | return str().count(Str); 231| | } 232| | 233| | /// @} 234| | /// @name Substring Operations 235| | /// @{ 236| | 237| | /// Return a reference to the substring from [Start, Start + N). 238| | /// 239| | /// \param Start The index of the starting character in the substring; if 240| | /// the index is npos or greater than the length of the string then the 241| | /// empty substring will be returned. 242| | /// 243| | /// \param N The number of characters to included in the substring. If \p N 244| | /// exceeds the number of characters remaining in the string, the string 245| | /// suffix (starting with \p Start) will be returned. 246| | StringRef substr(size_t Start, size_t N = StringRef::npos) const { 247| | return str().substr(Start, N); 248| | } 249| | 250| | /// Return a reference to the substring from [Start, End). 251| | /// 252| | /// \param Start The index of the starting character in the substring; if 253| | /// the index is npos or greater than the length of the string then the 254| | /// empty substring will be returned. 255| | /// 256| | /// \param End The index following the last character to include in the 257| | /// substring. If this is npos, or less than \p Start, or exceeds the 258| | /// number of characters remaining in the string, the string suffix 259| | /// (starting with \p Start) will be returned. 260| | StringRef slice(size_t Start, size_t End) const { 261| | return str().slice(Start, End); 262| | } 263| | 264| | // Extra methods. 265| | 266| | /// Explicit conversion to StringRef. 267| 0| StringRef str() const { return StringRef(this->begin(), this->size()); } 268| | 269| | // TODO: Make this const, if it's safe... 270| | const char* c_str() { 271| | this->push_back(0); 272| | this->pop_back(); 273| | return this->data(); 274| | } 275| | 276| | /// Implicit conversion to StringRef. 277| | operator StringRef() const { return str(); } 278| | 279| | // Extra operators. 280| | const SmallString &operator=(StringRef RHS) { 281| | this->clear(); 282| | return *this += RHS; 283| | } 284| | 285| | SmallString &operator+=(StringRef RHS) { 286| | this->append(RHS.begin(), RHS.end()); 287| | return *this; 288| | } 289| | SmallString &operator+=(char C) { 290| | this->push_back(C); 291| | return *this; 292| | } 293| |}; 294| | 295| |} 296| | 297| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallVector.h: 1| |//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLVECTOR_H 15| |#define LLVM_ADT_SMALLVECTOR_H 16| | 17| |#include "llvm/ADT/iterator_range.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/type_traits.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |namespace llvm { 32| | 33| |/// This is all the non-templated stuff common to all SmallVectors. 34| |class SmallVectorBase { 35| |protected: 36| | void *BeginX, *EndX, *CapacityX; 37| | 38| |protected: 39| | SmallVectorBase(void *FirstEl, size_t Size) 40| 0| : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} 41| | 42| | /// This is an implementation of the grow() method which only works 43| | /// on POD-like data types and is out of line to reduce code duplication. 44| | void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); 45| | 46| |public: 47| | /// This returns size()*sizeof(T). 48| | size_t size_in_bytes() const { 49| | return size_t((char*)EndX - (char*)BeginX); 50| | } 51| | 52| | /// capacity_in_bytes - This returns capacity()*sizeof(T). 53| | size_t capacity_in_bytes() const { 54| | return size_t((char*)CapacityX - (char*)BeginX); 55| | } 56| | 57| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } 58| |}; 59| | 60| |template struct SmallVectorStorage; 61| | 62| |/// This is the part of SmallVectorTemplateBase which does not depend on whether 63| |/// the type T is a POD. The extra dummy template argument is used by ArrayRef 64| |/// to avoid unnecessarily requiring T to be complete. 65| |template 66| |class SmallVectorTemplateCommon : public SmallVectorBase { 67| |private: 68| | template friend struct SmallVectorStorage; 69| | 70| | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 71| | // don't want it to be automatically run, so we need to represent the space as 72| | // something else. Use an array of char of sufficient alignment. 73| | typedef llvm::AlignedCharArrayUnion U; 74| | U FirstEl; 75| | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 76| | 77| |protected: 78| 0| SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvEC2Em ------------------ 79| | 80| 0| void grow_pod(size_t MinSizeInBytes, size_t TSize) { 81| 0| SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); 82| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE8grow_podEmm ------------------ 83| | 84| | /// Return true if this is a smallvector which has not had dynamic 85| | /// memory allocated for it. 86| 0| bool isSmall() const { 87| 0| return BeginX == static_cast(&FirstEl); 88| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE7isSmallEv ------------------ 89| | 90| | /// Put this vector in a state of being small. 91| | void resetToSmall() { 92| | BeginX = EndX = CapacityX = &FirstEl; 93| | } 94| | 95| 0| void setEnd(T *P) { this->EndX = P; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE6setEndEPc ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE6setEndEPh ------------------ 96| |public: 97| | typedef size_t size_type; 98| | typedef ptrdiff_t difference_type; 99| | typedef T value_type; 100| | typedef T *iterator; 101| | typedef const T *const_iterator; 102| | 103| | typedef std::reverse_iterator const_reverse_iterator; 104| | typedef std::reverse_iterator reverse_iterator; 105| | 106| | typedef T &reference; 107| | typedef const T &const_reference; 108| | typedef T *pointer; 109| | typedef const T *const_pointer; 110| | 111| | // forward iterator creation methods. 112| 0| iterator begin() { return (iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE5beginEv ------------------ 113| 0| const_iterator begin() const { return (const_iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE5beginEv ------------------ 114| 0| iterator end() { return (iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIhvE3endEv ------------------ 115| 0| const_iterator end() const { return (const_iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE3endEv ------------------ 116| |protected: 117| | iterator capacity_ptr() { return (iterator)this->CapacityX; } 118| | const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} 119| |public: 120| | 121| | // reverse iterator creation methods. 122| | reverse_iterator rbegin() { return reverse_iterator(end()); } 123| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 124| | reverse_iterator rend() { return reverse_iterator(begin()); } 125| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 126| | 127| 0| size_type size() const { return end()-begin(); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIhvE4sizeEv ------------------ 128| | size_type max_size() const { return size_type(-1) / sizeof(T); } 129| | 130| | /// Return the total number of elements in the currently allocated buffer. 131| | size_t capacity() const { return capacity_ptr() - begin(); } 132| | 133| | /// Return a pointer to the vector's buffer, even if empty(). 134| | pointer data() { return pointer(begin()); } 135| | /// Return a pointer to the vector's buffer, even if empty(). 136| 0| const_pointer data() const { return const_pointer(begin()); } 137| | 138| | reference operator[](size_type idx) { 139| | assert(idx < size()); 140| | return begin()[idx]; 141| | } 142| | const_reference operator[](size_type idx) const { 143| | assert(idx < size()); 144| | return begin()[idx]; 145| | } 146| | 147| | reference front() { 148| | assert(!empty()); 149| | return begin()[0]; 150| | } 151| | const_reference front() const { 152| | assert(!empty()); 153| | return begin()[0]; 154| | } 155| | 156| | reference back() { 157| | assert(!empty()); 158| | return end()[-1]; 159| | } 160| | const_reference back() const { 161| | assert(!empty()); 162| | return end()[-1]; 163| | } 164| |}; 165| | 166| |/// SmallVectorTemplateBase - This is where we put method 167| |/// implementations that are designed to work with non-POD-like T's. 168| |template 169| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 170| |protected: 171| | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 172| | 173| | static void destroy_range(T *S, T *E) { 174| | while (S != E) { 175| | --E; 176| | E->~T(); 177| | } 178| | } 179| | 180| | /// Use move-assignment to move the range [I, E) onto the 181| | /// objects starting with "Dest". This is just 's 182| | /// std::move, but not all stdlibs actually provide that. 183| | template 184| | static It2 move(It1 I, It1 E, It2 Dest) { 185| | for (; I != E; ++I, ++Dest) 186| | *Dest = ::std::move(*I); 187| | return Dest; 188| | } 189| | 190| | /// Use move-assignment to move the range 191| | /// [I, E) onto the objects ending at "Dest", moving objects 192| | /// in reverse order. This is just 's 193| | /// std::move_backward, but not all stdlibs actually provide that. 194| | template 195| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 196| | while (I != E) 197| | *--Dest = ::std::move(*--E); 198| | return Dest; 199| | } 200| | 201| | /// Move the range [I, E) into the uninitialized memory starting with "Dest", 202| | /// constructing elements as needed. 203| | template 204| | static void uninitialized_move(It1 I, It1 E, It2 Dest) { 205| | for (; I != E; ++I, ++Dest) 206| | ::new ((void*) &*Dest) T(::std::move(*I)); 207| | } 208| | 209| | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", 210| | /// constructing elements as needed. 211| | template 212| | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 213| | std::uninitialized_copy(I, E, Dest); 214| | } 215| | 216| | /// Grow the allocated memory (without initializing new elements), doubling 217| | /// the size of the allocated memory. Guarantees space for at least one more 218| | /// element, or MinSize more elements if specified. 219| | void grow(size_t MinSize = 0); 220| | 221| |public: 222| | void push_back(const T &Elt) { 223| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 224| | this->grow(); 225| | ::new ((void*) this->end()) T(Elt); 226| | this->setEnd(this->end()+1); 227| | } 228| | 229| | void push_back(T &&Elt) { 230| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 231| | this->grow(); 232| | ::new ((void*) this->end()) T(::std::move(Elt)); 233| | this->setEnd(this->end()+1); 234| | } 235| | 236| | void pop_back() { 237| | this->setEnd(this->end()-1); 238| | this->end()->~T(); 239| | } 240| |}; 241| | 242| |// Define this out-of-line to dissuade the C++ compiler from inlining it. 243| |template 244| |void SmallVectorTemplateBase::grow(size_t MinSize) { 245| | size_t CurCapacity = this->capacity(); 246| | size_t CurSize = this->size(); 247| | // Always grow, even from zero. 248| | size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); 249| | if (NewCapacity < MinSize) 250| | NewCapacity = MinSize; 251| | T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); 252| | 253| | // Move the elements over. 254| | this->uninitialized_move(this->begin(), this->end(), NewElts); 255| | 256| | // Destroy the original elements. 257| | destroy_range(this->begin(), this->end()); 258| | 259| | // If this wasn't grown from the inline copy, deallocate the old space. 260| | if (!this->isSmall()) 261| | free(this->begin()); 262| | 263| | this->setEnd(NewElts+CurSize); 264| | this->BeginX = NewElts; 265| | this->CapacityX = this->begin()+NewCapacity; 266| |} 267| | 268| | 269| |/// SmallVectorTemplateBase - This is where we put method 270| |/// implementations that are designed to work with POD-like T's. 271| |template 272| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 273| |protected: 274| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EEC2Em ------------------ 275| | 276| | // No need to do a destroy loop for POD's. 277| 0| static void destroy_range(T *, T *) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE13destroy_rangeEPcS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE13destroy_rangeEPhS2_ ------------------ 278| | 279| | /// Use move-assignment to move the range [I, E) onto the 280| | /// objects starting with "Dest". For PODs, this is just memcpy. 281| | template 282| | static It2 move(It1 I, It1 E, It2 Dest) { 283| | return ::std::copy(I, E, Dest); 284| | } 285| | 286| | /// Use move-assignment to move the range [I, E) onto the objects ending at 287| | /// "Dest", moving objects in reverse order. 288| | template 289| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 290| | return ::std::copy_backward(I, E, Dest); 291| | } 292| | 293| | /// Move the range [I, E) onto the uninitialized memory 294| | /// starting with "Dest", constructing elements into it as needed. 295| | template 296| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 297| 0| // Just do a copy. 298| 0| uninitialized_copy(I, E, Dest); 299| 0| } 300| | 301| | /// Copy the range [I, E) onto the uninitialized memory 302| | /// starting with "Dest", constructing elements into it as needed. 303| | template 304| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 305| 0| // Arbitrary iterator types; just use the basic implementation. 306| 0| std::uninitialized_copy(I, E, Dest); 307| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyINSt3__113move_iteratorIPhEES5_EEvT_S7_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE18uninitialized_copyIPKcPhEEvT_S6_T0_ ------------------ 308| | 309| | /// Copy the range [I, E) onto the uninitialized memory 310| | /// starting with "Dest", constructing elements into it as needed. 311| | template 312| | static void uninitialized_copy( 313| | T1 *I, T1 *E, T2 *Dest, 314| | typename std::enable_if::type, 315| 0| T2>::value>::type * = nullptr) { 316| 0| // Use memcpy for PODs iterated by pointers (which includes SmallVector 317| 0| // iterators): std::uninitialized_copy optimizes to memmove, but we can 318| 0| // use memcpy here. 319| 0| memcpy(Dest, I, (E-I)*sizeof(T)); 320| 0| } 321| | 322| | /// Double the size of the allocated memory, guaranteeing space for at 323| | /// least one more element or MinSize if specified. 324| 0| void grow(size_t MinSize = 0) { 325| 0| this->grow_pod(MinSize*sizeof(T), sizeof(T)); 326| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE4growEm ------------------ 327| |public: 328| 0| void push_back(const T &Elt) { 329| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 330| 0| this->grow(); 331| 0| memcpy(this->end(), &Elt, sizeof(T)); 332| 0| this->setEnd(this->end()+1); 333| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE9push_backERKc ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIhLb1EE9push_backERKh ------------------ 334| | 335| | void pop_back() { 336| | this->setEnd(this->end()-1); 337| | } 338| |}; 339| | 340| | 341| |/// This class consists of common code factored out of the SmallVector class to 342| |/// reduce code duplication based on the SmallVector 'N' template parameter. 343| |template 344| |class SmallVectorImpl : public SmallVectorTemplateBase::value> { 345| | typedef SmallVectorTemplateBase::value > SuperClass; 346| | 347| | SmallVectorImpl(const SmallVectorImpl&) = delete; 348| |public: 349| | typedef typename SuperClass::iterator iterator; 350| | typedef typename SuperClass::size_type size_type; 351| | 352| |protected: 353| | // Default ctor - Initialize to empty. 354| | explicit SmallVectorImpl(unsigned N) 355| 0| : SmallVectorTemplateBase::value>(N*sizeof(T)) { 356| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhEC2Ej ------------------ 357| | 358| |public: 359| 0| ~SmallVectorImpl() { 360| 0| // Destroy the constructed elements in the vector. 361| 0| this->destroy_range(this->begin(), this->end()); 362| 0| 363| 0| // If this wasn't grown from the inline copy, deallocate the old space. 364| 0| if (!this->isSmall()) 365| 0| free(this->begin()); 366| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIhED2Ev ------------------ 367| | 368| | 369| 0| void clear() { 370| 0| this->destroy_range(this->begin(), this->end()); 371| 0| this->EndX = this->BeginX; 372| 0| } 373| | 374| | void resize(size_type N) { 375| | if (N < this->size()) { 376| | this->destroy_range(this->begin()+N, this->end()); 377| | this->setEnd(this->begin()+N); 378| | } else if (N > this->size()) { 379| | if (this->capacity() < N) 380| | this->grow(N); 381| | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) 382| | new (&*I) T(); 383| | this->setEnd(this->begin()+N); 384| | } 385| | } 386| | 387| | void resize(size_type N, const T &NV) { 388| | if (N < this->size()) { 389| | this->destroy_range(this->begin()+N, this->end()); 390| | this->setEnd(this->begin()+N); 391| | } else if (N > this->size()) { 392| | if (this->capacity() < N) 393| | this->grow(N); 394| | std::uninitialized_fill(this->end(), this->begin()+N, NV); 395| | this->setEnd(this->begin()+N); 396| | } 397| | } 398| | 399| | void reserve(size_type N) { 400| | if (this->capacity() < N) 401| | this->grow(N); 402| | } 403| | 404| | T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { 405| | T Result = ::std::move(this->back()); 406| | this->pop_back(); 407| | return Result; 408| | } 409| | 410| | void swap(SmallVectorImpl &RHS); 411| | 412| | /// Add the specified range to the end of the SmallVector. 413| | template 414| | void append(in_iter in_start, in_iter in_end) { 415| | size_type NumInputs = std::distance(in_start, in_end); 416| | // Grow allocated space if needed. 417| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 418| | this->grow(this->size()+NumInputs); 419| | 420| | // Copy the new elements over. 421| | this->uninitialized_copy(in_start, in_end, this->end()); 422| | this->setEnd(this->end() + NumInputs); 423| | } 424| | 425| | /// Add the specified range to the end of the SmallVector. 426| | void append(size_type NumInputs, const T &Elt) { 427| | // Grow allocated space if needed. 428| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 429| | this->grow(this->size()+NumInputs); 430| | 431| | // Copy the new elements over. 432| | std::uninitialized_fill_n(this->end(), NumInputs, Elt); 433| | this->setEnd(this->end() + NumInputs); 434| | } 435| | 436| | void append(std::initializer_list IL) { 437| | append(IL.begin(), IL.end()); 438| | } 439| | 440| | void assign(size_type NumElts, const T &Elt) { 441| | clear(); 442| | if (this->capacity() < NumElts) 443| | this->grow(NumElts); 444| | this->setEnd(this->begin()+NumElts); 445| | std::uninitialized_fill(this->begin(), this->end(), Elt); 446| | } 447| | 448| | void assign(std::initializer_list IL) { 449| | clear(); 450| | append(IL); 451| | } 452| | 453| | iterator erase(iterator I) { 454| | assert(I >= this->begin() && "Iterator to erase is out of bounds."); 455| | assert(I < this->end() && "Erasing at past-the-end iterator."); 456| | 457| | iterator N = I; 458| | // Shift all elts down one. 459| | this->move(I+1, this->end(), I); 460| | // Drop the last elt. 461| | this->pop_back(); 462| | return(N); 463| | } 464| | 465| | iterator erase(iterator S, iterator E) { 466| | assert(S >= this->begin() && "Range to erase is out of bounds."); 467| | assert(S <= E && "Trying to erase invalid range."); 468| | assert(E <= this->end() && "Trying to erase past the end."); 469| | 470| | iterator N = S; 471| | // Shift all elts down. 472| | iterator I = this->move(E, this->end(), S); 473| | // Drop the last elts. 474| | this->destroy_range(I, this->end()); 475| | this->setEnd(I); 476| | return(N); 477| | } 478| | 479| | iterator insert(iterator I, T &&Elt) { 480| | if (I == this->end()) { // Important special case for empty vector. 481| | this->push_back(::std::move(Elt)); 482| | return this->end()-1; 483| | } 484| | 485| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 486| | assert(I <= this->end() && "Inserting past the end of the vector."); 487| | 488| | if (this->EndX >= this->CapacityX) { 489| | size_t EltNo = I-this->begin(); 490| | this->grow(); 491| | I = this->begin()+EltNo; 492| | } 493| | 494| | ::new ((void*) this->end()) T(::std::move(this->back())); 495| | // Push everything else over. 496| | this->move_backward(I, this->end()-1, this->end()); 497| | this->setEnd(this->end()+1); 498| | 499| | // If we just moved the element we're inserting, be sure to update 500| | // the reference. 501| | T *EltPtr = &Elt; 502| | if (I <= EltPtr && EltPtr < this->EndX) 503| | ++EltPtr; 504| | 505| | *I = ::std::move(*EltPtr); 506| | return I; 507| | } 508| | 509| | iterator insert(iterator I, const T &Elt) { 510| | if (I == this->end()) { // Important special case for empty vector. 511| | this->push_back(Elt); 512| | return this->end()-1; 513| | } 514| | 515| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 516| | assert(I <= this->end() && "Inserting past the end of the vector."); 517| | 518| | if (this->EndX >= this->CapacityX) { 519| | size_t EltNo = I-this->begin(); 520| | this->grow(); 521| | I = this->begin()+EltNo; 522| | } 523| | ::new ((void*) this->end()) T(std::move(this->back())); 524| | // Push everything else over. 525| | this->move_backward(I, this->end()-1, this->end()); 526| | this->setEnd(this->end()+1); 527| | 528| | // If we just moved the element we're inserting, be sure to update 529| | // the reference. 530| | const T *EltPtr = &Elt; 531| | if (I <= EltPtr && EltPtr < this->EndX) 532| | ++EltPtr; 533| | 534| | *I = *EltPtr; 535| | return I; 536| | } 537| | 538| | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 539| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 540| | size_t InsertElt = I - this->begin(); 541| | 542| | if (I == this->end()) { // Important special case for empty vector. 543| | append(NumToInsert, Elt); 544| | return this->begin()+InsertElt; 545| | } 546| | 547| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 548| | assert(I <= this->end() && "Inserting past the end of the vector."); 549| | 550| | // Ensure there is enough space. 551| | reserve(this->size() + NumToInsert); 552| | 553| | // Uninvalidate the iterator. 554| | I = this->begin()+InsertElt; 555| | 556| | // If there are more elements between the insertion point and the end of the 557| | // range than there are being inserted, we can use a simple approach to 558| | // insertion. Since we already reserved space, we know that this won't 559| | // reallocate the vector. 560| | if (size_t(this->end()-I) >= NumToInsert) { 561| | T *OldEnd = this->end(); 562| | append(std::move_iterator(this->end() - NumToInsert), 563| | std::move_iterator(this->end())); 564| | 565| | // Copy the existing elements that get replaced. 566| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 567| | 568| | std::fill_n(I, NumToInsert, Elt); 569| | return I; 570| | } 571| | 572| | // Otherwise, we're inserting more elements than exist already, and we're 573| | // not inserting at the end. 574| | 575| | // Move over the elements that we're about to overwrite. 576| | T *OldEnd = this->end(); 577| | this->setEnd(this->end() + NumToInsert); 578| | size_t NumOverwritten = OldEnd-I; 579| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 580| | 581| | // Replace the overwritten part. 582| | std::fill_n(I, NumOverwritten, Elt); 583| | 584| | // Insert the non-overwritten middle part. 585| | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 586| | return I; 587| | } 588| | 589| | template 590| | iterator insert(iterator I, ItTy From, ItTy To) { 591| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 592| | size_t InsertElt = I - this->begin(); 593| | 594| | if (I == this->end()) { // Important special case for empty vector. 595| | append(From, To); 596| | return this->begin()+InsertElt; 597| | } 598| | 599| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 600| | assert(I <= this->end() && "Inserting past the end of the vector."); 601| | 602| | size_t NumToInsert = std::distance(From, To); 603| | 604| | // Ensure there is enough space. 605| | reserve(this->size() + NumToInsert); 606| | 607| | // Uninvalidate the iterator. 608| | I = this->begin()+InsertElt; 609| | 610| | // If there are more elements between the insertion point and the end of the 611| | // range than there are being inserted, we can use a simple approach to 612| | // insertion. Since we already reserved space, we know that this won't 613| | // reallocate the vector. 614| | if (size_t(this->end()-I) >= NumToInsert) { 615| | T *OldEnd = this->end(); 616| | append(std::move_iterator(this->end() - NumToInsert), 617| | std::move_iterator(this->end())); 618| | 619| | // Copy the existing elements that get replaced. 620| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 621| | 622| | std::copy(From, To, I); 623| | return I; 624| | } 625| | 626| | // Otherwise, we're inserting more elements than exist already, and we're 627| | // not inserting at the end. 628| | 629| | // Move over the elements that we're about to overwrite. 630| | T *OldEnd = this->end(); 631| | this->setEnd(this->end() + NumToInsert); 632| | size_t NumOverwritten = OldEnd-I; 633| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 634| | 635| | // Replace the overwritten part. 636| | for (T *J = I; NumOverwritten > 0; --NumOverwritten) { 637| | *J = *From; 638| | ++J; ++From; 639| | } 640| | 641| | // Insert the non-overwritten middle part. 642| | this->uninitialized_copy(From, To, OldEnd); 643| | return I; 644| | } 645| | 646| | void insert(iterator I, std::initializer_list IL) { 647| | insert(I, IL.begin(), IL.end()); 648| | } 649| | 650| | template void emplace_back(ArgTypes &&... Args) { 651| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 652| | this->grow(); 653| | ::new ((void *)this->end()) T(std::forward(Args)...); 654| | this->setEnd(this->end() + 1); 655| | } 656| | 657| | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 658| | 659| | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); 660| | 661| | bool operator==(const SmallVectorImpl &RHS) const { 662| | if (this->size() != RHS.size()) return false; 663| | return std::equal(this->begin(), this->end(), RHS.begin()); 664| | } 665| | bool operator!=(const SmallVectorImpl &RHS) const { 666| | return !(*this == RHS); 667| | } 668| | 669| | bool operator<(const SmallVectorImpl &RHS) const { 670| | return std::lexicographical_compare(this->begin(), this->end(), 671| | RHS.begin(), RHS.end()); 672| | } 673| | 674| | /// Set the array size to \p N, which the current array must have enough 675| | /// capacity for. 676| | /// 677| | /// This does not construct or destroy any elements in the vector. 678| | /// 679| | /// Clients can use this in conjunction with capacity() to write past the end 680| | /// of the buffer when they know that more elements are available, and only 681| | /// update the size later. This avoids the cost of value initializing elements 682| | /// which will only be overwritten. 683| | void set_size(size_type N) { 684| | assert(N <= this->capacity()); 685| | this->setEnd(this->begin() + N); 686| | } 687| |}; 688| | 689| | 690| |template 691| |void SmallVectorImpl::swap(SmallVectorImpl &RHS) { 692| | if (this == &RHS) return; 693| | 694| | // We can only avoid copying elements if neither vector is small. 695| | if (!this->isSmall() && !RHS.isSmall()) { 696| | std::swap(this->BeginX, RHS.BeginX); 697| | std::swap(this->EndX, RHS.EndX); 698| | std::swap(this->CapacityX, RHS.CapacityX); 699| | return; 700| | } 701| | if (RHS.size() > this->capacity()) 702| | this->grow(RHS.size()); 703| | if (this->size() > RHS.capacity()) 704| | RHS.grow(this->size()); 705| | 706| | // Swap the shared elements. 707| | size_t NumShared = this->size(); 708| | if (NumShared > RHS.size()) NumShared = RHS.size(); 709| | for (size_type i = 0; i != NumShared; ++i) 710| | std::swap((*this)[i], RHS[i]); 711| | 712| | // Copy over the extra elts. 713| | if (this->size() > RHS.size()) { 714| | size_t EltDiff = this->size() - RHS.size(); 715| | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 716| | RHS.setEnd(RHS.end()+EltDiff); 717| | this->destroy_range(this->begin()+NumShared, this->end()); 718| | this->setEnd(this->begin()+NumShared); 719| | } else if (RHS.size() > this->size()) { 720| | size_t EltDiff = RHS.size() - this->size(); 721| | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 722| | this->setEnd(this->end() + EltDiff); 723| | this->destroy_range(RHS.begin()+NumShared, RHS.end()); 724| | RHS.setEnd(RHS.begin()+NumShared); 725| | } 726| |} 727| | 728| |template 729| |SmallVectorImpl &SmallVectorImpl:: 730| | operator=(const SmallVectorImpl &RHS) { 731| | // Avoid self-assignment. 732| | if (this == &RHS) return *this; 733| | 734| | // If we already have sufficient space, assign the common elements, then 735| | // destroy any excess. 736| | size_t RHSSize = RHS.size(); 737| | size_t CurSize = this->size(); 738| | if (CurSize >= RHSSize) { 739| | // Assign common elements. 740| | iterator NewEnd; 741| | if (RHSSize) 742| | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 743| | else 744| | NewEnd = this->begin(); 745| | 746| | // Destroy excess elements. 747| | this->destroy_range(NewEnd, this->end()); 748| | 749| | // Trim. 750| | this->setEnd(NewEnd); 751| | return *this; 752| | } 753| | 754| | // If we have to grow to have enough elements, destroy the current elements. 755| | // This allows us to avoid copying them during the grow. 756| | // FIXME: don't do this if they're efficiently moveable. 757| | if (this->capacity() < RHSSize) { 758| | // Destroy current elements. 759| | this->destroy_range(this->begin(), this->end()); 760| | this->setEnd(this->begin()); 761| | CurSize = 0; 762| | this->grow(RHSSize); 763| | } else if (CurSize) { 764| | // Otherwise, use assignment for the already-constructed elements. 765| | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 766| | } 767| | 768| | // Copy construct the new elements in place. 769| | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 770| | this->begin()+CurSize); 771| | 772| | // Set end. 773| | this->setEnd(this->begin()+RHSSize); 774| | return *this; 775| |} 776| | 777| |template 778| |SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { 779| | // Avoid self-assignment. 780| | if (this == &RHS) return *this; 781| | 782| | // If the RHS isn't small, clear this vector and then steal its buffer. 783| | if (!RHS.isSmall()) { 784| | this->destroy_range(this->begin(), this->end()); 785| | if (!this->isSmall()) free(this->begin()); 786| | this->BeginX = RHS.BeginX; 787| | this->EndX = RHS.EndX; 788| | this->CapacityX = RHS.CapacityX; 789| | RHS.resetToSmall(); 790| | return *this; 791| | } 792| | 793| | // If we already have sufficient space, assign the common elements, then 794| | // destroy any excess. 795| | size_t RHSSize = RHS.size(); 796| | size_t CurSize = this->size(); 797| | if (CurSize >= RHSSize) { 798| | // Assign common elements. 799| | iterator NewEnd = this->begin(); 800| | if (RHSSize) 801| | NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); 802| | 803| | // Destroy excess elements and trim the bounds. 804| | this->destroy_range(NewEnd, this->end()); 805| | this->setEnd(NewEnd); 806| | 807| | // Clear the RHS. 808| | RHS.clear(); 809| | 810| | return *this; 811| | } 812| | 813| | // If we have to grow to have enough elements, destroy the current elements. 814| | // This allows us to avoid copying them during the grow. 815| | // FIXME: this may not actually make any sense if we can efficiently move 816| | // elements. 817| | if (this->capacity() < RHSSize) { 818| | // Destroy current elements. 819| | this->destroy_range(this->begin(), this->end()); 820| | this->setEnd(this->begin()); 821| | CurSize = 0; 822| | this->grow(RHSSize); 823| | } else if (CurSize) { 824| | // Otherwise, use assignment for the already-constructed elements. 825| | this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); 826| | } 827| | 828| | // Move-construct the new elements in place. 829| | this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), 830| | this->begin()+CurSize); 831| | 832| | // Set end. 833| | this->setEnd(this->begin()+RHSSize); 834| | 835| | RHS.clear(); 836| | return *this; 837| |} 838| | 839| |/// Storage for the SmallVector elements which aren't contained in 840| |/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' 841| |/// element is in the base class. This is specialized for the N=1 and N=0 cases 842| |/// to avoid allocating unnecessary storage. 843| |template 844| |struct SmallVectorStorage { 845| | typename SmallVectorTemplateCommon::U InlineElts[N - 1]; 846| |}; 847| |template struct SmallVectorStorage {}; 848| |template struct SmallVectorStorage {}; 849| | 850| |/// This is a 'vector' (really, a variable-sized array), optimized 851| |/// for the case when the array is small. It contains some number of elements 852| |/// in-place, which allows it to avoid heap allocation when the actual number of 853| |/// elements is below that threshold. This allows normal "small" cases to be 854| |/// fast without losing generality for large inputs. 855| |/// 856| |/// Note that this does not attempt to be exception safe. 857| |/// 858| |template 859| |class SmallVector : public SmallVectorImpl { 860| | /// Inline space for elements which aren't stored in the base class. 861| | SmallVectorStorage Storage; 862| |public: 863| 0| SmallVector() : SmallVectorImpl(N) { 864| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIhLj256EEC2Ev ------------------ 865| | 866| | explicit SmallVector(size_t Size, const T &Value = T()) 867| | : SmallVectorImpl(N) { 868| | this->assign(Size, Value); 869| | } 870| | 871| | template 872| | SmallVector(ItTy S, ItTy E) : SmallVectorImpl(N) { 873| | this->append(S, E); 874| | } 875| | 876| | template 877| | explicit SmallVector(const llvm::iterator_range R) 878| | : SmallVectorImpl(N) { 879| | this->append(R.begin(), R.end()); 880| | } 881| | 882| | SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { 883| | this->assign(IL); 884| | } 885| | 886| | SmallVector(const SmallVector &RHS) : SmallVectorImpl(N) { 887| | if (!RHS.empty()) 888| | SmallVectorImpl::operator=(RHS); 889| | } 890| | 891| | const SmallVector &operator=(const SmallVector &RHS) { 892| | SmallVectorImpl::operator=(RHS); 893| | return *this; 894| | } 895| | 896| | SmallVector(SmallVector &&RHS) : SmallVectorImpl(N) { 897| | if (!RHS.empty()) 898| | SmallVectorImpl::operator=(::std::move(RHS)); 899| | } 900| | 901| | const SmallVector &operator=(SmallVector &&RHS) { 902| | SmallVectorImpl::operator=(::std::move(RHS)); 903| | return *this; 904| | } 905| | 906| | SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { 907| | if (!RHS.empty()) 908| | SmallVectorImpl::operator=(::std::move(RHS)); 909| | } 910| | 911| | const SmallVector &operator=(SmallVectorImpl &&RHS) { 912| | SmallVectorImpl::operator=(::std::move(RHS)); 913| | return *this; 914| | } 915| | 916| | const SmallVector &operator=(std::initializer_list IL) { 917| | this->assign(IL); 918| | return *this; 919| | } 920| |}; 921| | 922| |template 923| |static inline size_t capacity_in_bytes(const SmallVector &X) { 924| | return X.capacity_in_bytes(); 925| |} 926| | 927| |} // End llvm namespace 928| | 929| |namespace std { 930| | /// Implement std::swap in terms of SmallVector swap. 931| | template 932| | inline void 933| | swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { 934| | LHS.swap(RHS); 935| | } 936| | 937| | /// Implement std::swap in terms of SmallVector swap. 938| | template 939| | inline void 940| | swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { 941| | LHS.swap(RHS); 942| | } 943| |} 944| | 945| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringMap.h: 1| |//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGMAP_H 15| |#define LLVM_ADT_STRINGMAP_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/Allocator.h" 19| |#include 20| |#include 21| | 22| |namespace llvm { 23| | template 24| | class StringMapConstIterator; 25| | template 26| | class StringMapIterator; 27| | template 28| | class StringMapEntry; 29| | 30| |/// StringMapEntryBase - Shared base class of StringMapEntry instances. 31| |class StringMapEntryBase { 32| | unsigned StrLen; 33| |public: 34| 0| explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 35| | 36| 0| unsigned getKeyLength() const { return StrLen; } 37| |}; 38| | 39| |/// StringMapImpl - This is the base class of StringMap that is shared among 40| |/// all of its instantiations. 41| |class StringMapImpl { 42| |protected: 43| | // Array of NumBuckets pointers to entries, null pointers are holes. 44| | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 45| | // by an array of the actual hash values as unsigned integers. 46| | StringMapEntryBase **TheTable; 47| | unsigned NumBuckets; 48| | unsigned NumItems; 49| | unsigned NumTombstones; 50| | unsigned ItemSize; 51| |protected: 52| | explicit StringMapImpl(unsigned itemSize) 53| | : TheTable(nullptr), 54| | // Initialize the map with zero buckets to allocation. 55| 0| NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 56| | StringMapImpl(StringMapImpl &&RHS) 57| | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 58| | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 59| 0| ItemSize(RHS.ItemSize) { 60| 0| RHS.TheTable = nullptr; 61| 0| RHS.NumBuckets = 0; 62| 0| RHS.NumItems = 0; 63| 0| RHS.NumTombstones = 0; 64| 0| } 65| | 66| | StringMapImpl(unsigned InitSize, unsigned ItemSize); 67| | unsigned RehashTable(unsigned BucketNo = 0); 68| | 69| | /// LookupBucketFor - Look up the bucket that the specified string should end 70| | /// up in. If it already exists as a key in the map, the Item pointer for the 71| | /// specified bucket will be non-null. Otherwise, it will be null. In either 72| | /// case, the FullHashValue field of the bucket will be set to the hash value 73| | /// of the string. 74| | unsigned LookupBucketFor(StringRef Key); 75| | 76| | /// FindKey - Look up the bucket that contains the specified key. If it exists 77| | /// in the map, return the bucket number of the key. Otherwise return -1. 78| | /// This does not modify the map. 79| | int FindKey(StringRef Key) const; 80| | 81| | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 82| | /// delete it. This aborts if the value isn't in the table. 83| | void RemoveKey(StringMapEntryBase *V); 84| | 85| | /// RemoveKey - Remove the StringMapEntry for the specified key from the 86| | /// table, returning it. If the key is not in the table, this returns null. 87| | StringMapEntryBase *RemoveKey(StringRef Key); 88| |private: 89| | void init(unsigned Size); 90| |public: 91| 0| static StringMapEntryBase *getTombstoneVal() { 92| 0| return (StringMapEntryBase*)-1; 93| 0| } 94| | 95| 0| unsigned getNumBuckets() const { return NumBuckets; } 96| 0| unsigned getNumItems() const { return NumItems; } 97| | 98| 0| bool empty() const { return NumItems == 0; } 99| 0| unsigned size() const { return NumItems; } 100| | 101| 0| void swap(StringMapImpl &Other) { 102| 0| std::swap(TheTable, Other.TheTable); 103| 0| std::swap(NumBuckets, Other.NumBuckets); 104| 0| std::swap(NumItems, Other.NumItems); 105| 0| std::swap(NumTombstones, Other.NumTombstones); 106| 0| } 107| |}; 108| | 109| |/// StringMapEntry - This is used to represent one value that is inserted into 110| |/// a StringMap. It contains the Value itself and the key: the string length 111| |/// and data. 112| |template 113| |class StringMapEntry : public StringMapEntryBase { 114| | StringMapEntry(StringMapEntry &E) = delete; 115| |public: 116| | ValueTy second; 117| | 118| | explicit StringMapEntry(unsigned strLen) 119| | : StringMapEntryBase(strLen), second() {} 120| | template 121| | StringMapEntry(unsigned strLen, InitTy &&V) 122| 0| : StringMapEntryBase(strLen), second(std::forward(V)) {} 123| | 124| 0| StringRef getKey() const { 125| 0| return StringRef(getKeyData(), getKeyLength()); 126| 0| } 127| | 128| | const ValueTy &getValue() const { return second; } 129| | ValueTy &getValue() { return second; } 130| | 131| | void setValue(const ValueTy &V) { second = V; } 132| | 133| | /// getKeyData - Return the start of the string data that is the key for this 134| | /// value. The string data is always stored immediately after the 135| | /// StringMapEntry object. 136| 0| const char *getKeyData() const {return reinterpret_cast(this+1);} 137| | 138| | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 139| | 140| | /// Create - Create a StringMapEntry for the specified key and default 141| | /// construct the value. 142| | template 143| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 144| 0| InitType &&InitVal) { 145| 0| unsigned KeyLength = Key.size(); 146| 0| 147| 0| // Allocate a new item with space for the string at the end and a null 148| 0| // terminator. 149| 0| unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ 150| 0| KeyLength+1; 151| 0| unsigned Alignment = alignOf(); 152| 0| 153| 0| StringMapEntry *NewItem = 154| 0| static_cast(Allocator.Allocate(AllocSize,Alignment)); 155| 0| 156| 0| // Default construct the value. 157| 0| new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); 158| 0| 159| 0| // Copy the string information. 160| 0| char *StrBuffer = const_cast(NewItem->getKeyData()); 161| 0| memcpy(StrBuffer, Key.data(), KeyLength); 162| 0| StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 163| 0| return NewItem; 164| 0| } 165| | 166| | template 167| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 168| | return Create(Key, Allocator, ValueTy()); 169| | } 170| | 171| | /// Create - Create a StringMapEntry with normal malloc/free. 172| | template 173| | static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { 174| | MallocAllocator A; 175| | return Create(Key, A, std::forward(InitVal)); 176| | } 177| | 178| | static StringMapEntry *Create(StringRef Key) { 179| | return Create(Key, ValueTy()); 180| | } 181| | 182| | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 183| | /// into a StringMapEntry, return the StringMapEntry itself. 184| 0| static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 185| 0| char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); 186| 0| return *reinterpret_cast(Ptr); 187| 0| } 188| | 189| | /// Destroy - Destroy this StringMapEntry, releasing memory back to the 190| | /// specified allocator. 191| | template 192| 0| void Destroy(AllocatorTy &Allocator) { 193| 0| // Free memory referenced by the item. 194| 0| unsigned AllocSize = 195| 0| static_cast(sizeof(StringMapEntry)) + getKeyLength() + 1; 196| 0| this->~StringMapEntry(); 197| 0| Allocator.Deallocate(static_cast(this), AllocSize); 198| 0| } 199| | 200| | /// Destroy this object, releasing memory back to the malloc allocator. 201| | void Destroy() { 202| | MallocAllocator A; 203| | Destroy(A); 204| | } 205| |}; 206| | 207| | 208| |/// StringMap - This is an unconventional map that is specialized for handling 209| |/// keys that are "strings", which are basically ranges of bytes. This does some 210| |/// funky memory allocation and hashing things to make it extremely efficient, 211| |/// storing the string data *after* the value in the map. 212| |template 213| |class StringMap : public StringMapImpl { 214| | AllocatorTy Allocator; 215| |public: 216| | typedef StringMapEntry MapEntryTy; 217| | 218| 0| StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} 219| | explicit StringMap(unsigned InitialSize) 220| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} 221| | 222| | explicit StringMap(AllocatorTy A) 223| | : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} 224| | 225| | StringMap(unsigned InitialSize, AllocatorTy A) 226| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), 227| | Allocator(A) {} 228| | 229| | StringMap(StringMap &&RHS) 230| | : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 231| | 232| | StringMap &operator=(StringMap RHS) { 233| | StringMapImpl::swap(RHS); 234| | std::swap(Allocator, RHS.Allocator); 235| | return *this; 236| | } 237| | 238| | // FIXME: Implement copy operations if/when they're needed. 239| | 240| | AllocatorTy &getAllocator() { return Allocator; } 241| | const AllocatorTy &getAllocator() const { return Allocator; } 242| | 243| | typedef const char* key_type; 244| | typedef ValueTy mapped_type; 245| | typedef StringMapEntry value_type; 246| | typedef size_t size_type; 247| | 248| | typedef StringMapConstIterator const_iterator; 249| | typedef StringMapIterator iterator; 250| | 251| | iterator begin() { 252| | return iterator(TheTable, NumBuckets == 0); 253| | } 254| | iterator end() { 255| | return iterator(TheTable+NumBuckets, true); 256| | } 257| | const_iterator begin() const { 258| | return const_iterator(TheTable, NumBuckets == 0); 259| | } 260| | const_iterator end() const { 261| | return const_iterator(TheTable+NumBuckets, true); 262| | } 263| | 264| | iterator find(StringRef Key) { 265| | int Bucket = FindKey(Key); 266| | if (Bucket == -1) return end(); 267| | return iterator(TheTable+Bucket, true); 268| | } 269| | 270| | const_iterator find(StringRef Key) const { 271| | int Bucket = FindKey(Key); 272| | if (Bucket == -1) return end(); 273| | return const_iterator(TheTable+Bucket, true); 274| | } 275| | 276| | /// lookup - Return the entry for the specified key, or a default 277| | /// constructed value if no such entry exists. 278| | ValueTy lookup(StringRef Key) const { 279| | const_iterator it = find(Key); 280| | if (it != end()) 281| | return it->second; 282| | return ValueTy(); 283| | } 284| | 285| | ValueTy &operator[](StringRef Key) { 286| | return insert(std::make_pair(Key, ValueTy())).first->second; 287| | } 288| | 289| | /// count - Return 1 if the element is in the map, 0 otherwise. 290| | size_type count(StringRef Key) const { 291| | return find(Key) == end() ? 0 : 1; 292| | } 293| | 294| | /// insert - Insert the specified key/value pair into the map. If the key 295| | /// already exists in the map, return false and ignore the request, otherwise 296| | /// insert it and return true. 297| | bool insert(MapEntryTy *KeyValue) { 298| | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 299| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 300| | if (Bucket && Bucket != getTombstoneVal()) 301| | return false; // Already exists in map. 302| | 303| | if (Bucket == getTombstoneVal()) 304| | --NumTombstones; 305| | Bucket = KeyValue; 306| | ++NumItems; 307| | assert(NumItems + NumTombstones <= NumBuckets); 308| | 309| | RehashTable(); 310| | return true; 311| | } 312| | 313| | /// insert - Inserts the specified key/value pair into the map if the key 314| | /// isn't already in the map. The bool component of the returned pair is true 315| | /// if and only if the insertion takes place, and the iterator component of 316| | /// the pair points to the element with key equivalent to the key of the pair. 317| 0| std::pair insert(std::pair KV) { 318| 0| unsigned BucketNo = LookupBucketFor(KV.first); 319| 0| StringMapEntryBase *&Bucket = TheTable[BucketNo]; 320| 0| if (Bucket && Bucket != getTombstoneVal()) 321| 0| return std::make_pair(iterator(TheTable + BucketNo, false), 322| 0| false); // Already exists in map. 323| 0| 324| 0| if (Bucket == getTombstoneVal()) 325| 0| --NumTombstones; 326| 0| Bucket = 327| 0| MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 328| 0| ++NumItems; 329| 0| assert(NumItems + NumTombstones <= NumBuckets); 330| 0| 331| 0| BucketNo = RehashTable(BucketNo); 332| 0| return std::make_pair(iterator(TheTable + BucketNo, false), true); 333| 0| } 334| | 335| | // clear - Empties out the StringMap 336| | void clear() { 337| | if (empty()) return; 338| | 339| | // Zap all values, resetting the keys back to non-present (not tombstone), 340| | // which is safe because we're removing all elements. 341| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 342| | StringMapEntryBase *&Bucket = TheTable[I]; 343| | if (Bucket && Bucket != getTombstoneVal()) { 344| | static_cast(Bucket)->Destroy(Allocator); 345| | } 346| | Bucket = nullptr; 347| | } 348| | 349| | NumItems = 0; 350| | NumTombstones = 0; 351| | } 352| | 353| | /// remove - Remove the specified key/value pair from the map, but do not 354| | /// erase it. This aborts if the key is not in the map. 355| | void remove(MapEntryTy *KeyValue) { 356| | RemoveKey(KeyValue); 357| | } 358| | 359| | void erase(iterator I) { 360| | MapEntryTy &V = *I; 361| | remove(&V); 362| | V.Destroy(Allocator); 363| | } 364| | 365| | bool erase(StringRef Key) { 366| | iterator I = find(Key); 367| | if (I == end()) return false; 368| | erase(I); 369| | return true; 370| | } 371| | 372| 0| ~StringMap() { 373| 0| // Delete all the elements in the map, but don't reset the elements 374| 0| // to default values. This is a copy of clear(), but avoids unnecessary 375| 0| // work not required in the destructor. 376| 0| if (!empty()) { 377| 0| for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 378| 0| StringMapEntryBase *Bucket = TheTable[I]; 379| 0| if (Bucket && Bucket != getTombstoneVal()) { 380| 0| static_cast(Bucket)->Destroy(Allocator); 381| 0| } 382| 0| } 383| 0| } 384| 0| free(TheTable); 385| 0| } 386| |}; 387| | 388| | 389| |template 390| |class StringMapConstIterator { 391| |protected: 392| | StringMapEntryBase **Ptr; 393| |public: 394| | typedef StringMapEntry value_type; 395| | 396| | StringMapConstIterator() : Ptr(nullptr) { } 397| | 398| | explicit StringMapConstIterator(StringMapEntryBase **Bucket, 399| | bool NoAdvance = false) 400| 0| : Ptr(Bucket) { 401| 0| if (!NoAdvance) AdvancePastEmptyBuckets(); 402| 0| } 403| | 404| | const value_type &operator*() const { 405| | return *static_cast*>(*Ptr); 406| | } 407| | const value_type *operator->() const { 408| | return static_cast*>(*Ptr); 409| | } 410| | 411| | bool operator==(const StringMapConstIterator &RHS) const { 412| | return Ptr == RHS.Ptr; 413| | } 414| | bool operator!=(const StringMapConstIterator &RHS) const { 415| | return Ptr != RHS.Ptr; 416| | } 417| | 418| | inline StringMapConstIterator& operator++() { // Preincrement 419| | ++Ptr; 420| | AdvancePastEmptyBuckets(); 421| | return *this; 422| | } 423| | StringMapConstIterator operator++(int) { // Postincrement 424| | StringMapConstIterator tmp = *this; ++*this; return tmp; 425| | } 426| | 427| |private: 428| 0| void AdvancePastEmptyBuckets() { 429| 0| while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 430| 0| ++Ptr; 431| 0| } 432| |}; 433| | 434| |template 435| |class StringMapIterator : public StringMapConstIterator { 436| |public: 437| | StringMapIterator() {} 438| | explicit StringMapIterator(StringMapEntryBase **Bucket, 439| | bool NoAdvance = false) 440| 0| : StringMapConstIterator(Bucket, NoAdvance) { 441| 0| } 442| | StringMapEntry &operator*() const { 443| | return *static_cast*>(*this->Ptr); 444| | } 445| 0| StringMapEntry *operator->() const { 446| 0| return static_cast*>(*this->Ptr); 447| 0| } 448| |}; 449| | 450| |} 451| | 452| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringRef.h: 1| |//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_STRINGREF_H 11| |#define LLVM_ADT_STRINGREF_H 12| | 13| |#include 14| |#include 15| |#include 16| |#include 17| |#include 18| |#include 19| | 20| |namespace llvm { 21| | template 22| | class SmallVectorImpl; 23| | class hash_code; 24| | class StringRef; 25| | 26| | /// Helper functions for StringRef::getAsInteger. 27| | bool getAsUnsignedInteger(StringRef Str, unsigned Radix, 28| | unsigned long long &Result); 29| | 30| | bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); 31| | 32| | /// StringRef - Represent a constant reference to a string, i.e. a character 33| | /// array and a length, which need not be null terminated. 34| | /// 35| | /// This class does not own the string data, it is expected to be used in 36| | /// situations where the character data resides in some other buffer, whose 37| | /// lifetime extends past that of the StringRef. For this reason, it is not in 38| | /// general safe to store a StringRef. 39| | class StringRef { 40| | public: 41| | typedef const char *iterator; 42| | typedef const char *const_iterator; 43| | static const size_t npos = ~size_t(0); 44| | typedef size_t size_type; 45| | 46| | private: 47| | /// The start of the string, in an external buffer. 48| | const char *Data; 49| | 50| | /// The length of the string. 51| | size_t Length; 52| | 53| | // Workaround memcmp issue with null pointers (undefined behavior) 54| | // by providing a specialized version 55| 0| static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { 56| 0| if (Length == 0) { return 0; } 57| 0| return ::memcmp(Lhs,Rhs,Length); 58| 0| } 59| | 60| | public: 61| | /// @name Constructors 62| | /// @{ 63| | 64| | /// Construct an empty string ref. 65| 0| /*implicit*/ StringRef() : Data(nullptr), Length(0) {} 66| | 67| | /// Construct a string ref from a cstring. 68| | /*implicit*/ StringRef(const char *Str) 69| 0| : Data(Str) { 70| 0| assert(Str && "StringRef cannot be built from a NULL argument"); 71| 0| Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior 72| 0| } 73| | 74| | /// Construct a string ref from a pointer and length. 75| | /*implicit*/ StringRef(const char *data, size_t length) 76| 0| : Data(data), Length(length) { 77| 0| assert((data || length == 0) && 78| 0| "StringRef cannot be built from a NULL argument with non-null length"); 79| 0| } 80| | 81| | /// Construct a string ref from an std::string. 82| | /*implicit*/ StringRef(const std::string &Str) 83| 0| : Data(Str.data()), Length(Str.length()) {} 84| | 85| | /// @} 86| | /// @name Iterators 87| | /// @{ 88| | 89| 0| iterator begin() const { return Data; } 90| | 91| 0| iterator end() const { return Data + Length; } 92| | 93| 0| const unsigned char *bytes_begin() const { 94| 0| return reinterpret_cast(begin()); 95| 0| } 96| 0| const unsigned char *bytes_end() const { 97| 0| return reinterpret_cast(end()); 98| 0| } 99| | 100| | /// @} 101| | /// @name String Operations 102| | /// @{ 103| | 104| | /// data - Get a pointer to the start of the string (which may not be null 105| | /// terminated). 106| 0| const char *data() const { return Data; } 107| | 108| | /// empty - Check if the string is empty. 109| 0| bool empty() const { return Length == 0; } 110| | 111| | /// size - Get the string size. 112| 0| size_t size() const { return Length; } 113| | 114| | /// front - Get the first character in the string. 115| | char front() const { 116| | assert(!empty()); 117| | return Data[0]; 118| | } 119| | 120| | /// back - Get the last character in the string. 121| | char back() const { 122| | assert(!empty()); 123| | return Data[Length-1]; 124| | } 125| | 126| | // copy - Allocate copy in Allocator and return StringRef to it. 127| | template StringRef copy(Allocator &A) const { 128| | char *S = A.template Allocate(Length); 129| | std::copy(begin(), end(), S); 130| | return StringRef(S, Length); 131| | } 132| | 133| | /// equals - Check for string equality, this is more efficient than 134| | /// compare() when the relative ordering of inequal strings isn't needed. 135| | bool equals(StringRef RHS) const { 136| | return (Length == RHS.Length && 137| | compareMemory(Data, RHS.Data, RHS.Length) == 0); 138| | } 139| | 140| | /// equals_lower - Check for string equality, ignoring case. 141| | bool equals_lower(StringRef RHS) const { 142| | return Length == RHS.Length && compare_lower(RHS) == 0; 143| | } 144| | 145| | /// compare - Compare two strings; the result is -1, 0, or 1 if this string 146| | /// is lexicographically less than, equal to, or greater than the \p RHS. 147| | int compare(StringRef RHS) const { 148| | // Check the prefix for a mismatch. 149| | if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) 150| | return Res < 0 ? -1 : 1; 151| | 152| | // Otherwise the prefixes match, so we only need to check the lengths. 153| | if (Length == RHS.Length) 154| | return 0; 155| | return Length < RHS.Length ? -1 : 1; 156| | } 157| | 158| | /// compare_lower - Compare two strings, ignoring case. 159| | int compare_lower(StringRef RHS) const; 160| | 161| | /// compare_numeric - Compare two strings, treating sequences of digits as 162| | /// numbers. 163| | int compare_numeric(StringRef RHS) const; 164| | 165| | /// \brief Determine the edit distance between this string and another 166| | /// string. 167| | /// 168| | /// \param Other the string to compare this string against. 169| | /// 170| | /// \param AllowReplacements whether to allow character 171| | /// replacements (change one character into another) as a single 172| | /// operation, rather than as two operations (an insertion and a 173| | /// removal). 174| | /// 175| | /// \param MaxEditDistance If non-zero, the maximum edit distance that 176| | /// this routine is allowed to compute. If the edit distance will exceed 177| | /// that maximum, returns \c MaxEditDistance+1. 178| | /// 179| | /// \returns the minimum number of character insertions, removals, 180| | /// or (if \p AllowReplacements is \c true) replacements needed to 181| | /// transform one of the given strings into the other. If zero, 182| | /// the strings are identical. 183| | unsigned edit_distance(StringRef Other, bool AllowReplacements = true, 184| | unsigned MaxEditDistance = 0) const; 185| | 186| | /// str - Get the contents as an std::string. 187| 0| std::string str() const { 188| 0| if (!Data) return std::string(); 189| 0| return std::string(Data, Length); 190| 0| } 191| | 192| | /// @} 193| | /// @name Operator Overloads 194| | /// @{ 195| | 196| 0| char operator[](size_t Index) const { 197| 0| assert(Index < Length && "Invalid index!"); 198| 0| return Data[Index]; 199| 0| } 200| | 201| | /// @} 202| | /// @name Type Conversions 203| | /// @{ 204| | 205| 0| operator std::string() const { 206| 0| return str(); 207| 0| } 208| | 209| | /// @} 210| | /// @name String Predicates 211| | /// @{ 212| | 213| | /// Check if this string starts with the given \p Prefix. 214| | bool startswith(StringRef Prefix) const { 215| | return Length >= Prefix.Length && 216| | compareMemory(Data, Prefix.Data, Prefix.Length) == 0; 217| | } 218| | 219| | /// Check if this string starts with the given \p Prefix, ignoring case. 220| | bool startswith_lower(StringRef Prefix) const; 221| | 222| | /// Check if this string ends with the given \p Suffix. 223| 0| bool endswith(StringRef Suffix) const { 224| 0| return Length >= Suffix.Length && 225| 0| compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 226| 0| } 227| | 228| | /// Check if this string ends with the given \p Suffix, ignoring case. 229| | bool endswith_lower(StringRef Suffix) const; 230| | 231| | /// @} 232| | /// @name String Searching 233| | /// @{ 234| | 235| | /// Search for the first character \p C in the string. 236| | /// 237| | /// \returns The index of the first occurrence of \p C, or npos if not 238| | /// found. 239| | size_t find(char C, size_t From = 0) const { 240| | for (size_t i = std::min(From, Length), e = Length; i != e; ++i) 241| | if (Data[i] == C) 242| | return i; 243| | return npos; 244| | } 245| | 246| | /// Search for the first string \p Str in the string. 247| | /// 248| | /// \returns The index of the first occurrence of \p Str, or npos if not 249| | /// found. 250| | size_t find(StringRef Str, size_t From = 0) const; 251| | 252| | /// Search for the last character \p C in the string. 253| | /// 254| | /// \returns The index of the last occurrence of \p C, or npos if not 255| | /// found. 256| | size_t rfind(char C, size_t From = npos) const { 257| | From = std::min(From, Length); 258| | size_t i = From; 259| | while (i != 0) { 260| | --i; 261| | if (Data[i] == C) 262| | return i; 263| | } 264| | return npos; 265| | } 266| | 267| | /// Search for the last string \p Str in the string. 268| | /// 269| | /// \returns The index of the last occurrence of \p Str, or npos if not 270| | /// found. 271| | size_t rfind(StringRef Str) const; 272| | 273| | /// Find the first character in the string that is \p C, or npos if not 274| | /// found. Same as find. 275| | size_t find_first_of(char C, size_t From = 0) const { 276| | return find(C, From); 277| | } 278| | 279| | /// Find the first character in the string that is in \p Chars, or npos if 280| | /// not found. 281| | /// 282| | /// Complexity: O(size() + Chars.size()) 283| | size_t find_first_of(StringRef Chars, size_t From = 0) const; 284| | 285| | /// Find the first character in the string that is not \p C or npos if not 286| | /// found. 287| | size_t find_first_not_of(char C, size_t From = 0) const; 288| | 289| | /// Find the first character in the string that is not in the string 290| | /// \p Chars, or npos if not found. 291| | /// 292| | /// Complexity: O(size() + Chars.size()) 293| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const; 294| | 295| | /// Find the last character in the string that is \p C, or npos if not 296| | /// found. 297| | size_t find_last_of(char C, size_t From = npos) const { 298| | return rfind(C, From); 299| | } 300| | 301| | /// Find the last character in the string that is in \p C, or npos if not 302| | /// found. 303| | /// 304| | /// Complexity: O(size() + Chars.size()) 305| | size_t find_last_of(StringRef Chars, size_t From = npos) const; 306| | 307| | /// Find the last character in the string that is not \p C, or npos if not 308| | /// found. 309| | size_t find_last_not_of(char C, size_t From = npos) const; 310| | 311| | /// Find the last character in the string that is not in \p Chars, or 312| | /// npos if not found. 313| | /// 314| | /// Complexity: O(size() + Chars.size()) 315| | size_t find_last_not_of(StringRef Chars, size_t From = npos) const; 316| | 317| | /// @} 318| | /// @name Helpful Algorithms 319| | /// @{ 320| | 321| | /// Return the number of occurrences of \p C in the string. 322| 0| size_t count(char C) const { 323| 0| size_t Count = 0; 324| 0| for (size_t i = 0, e = Length; i != e; ++i) 325| 0| if (Data[i] == C) 326| 0| ++Count; 327| 0| return Count; 328| 0| } 329| | 330| | /// Return the number of non-overlapped occurrences of \p Str in 331| | /// the string. 332| | size_t count(StringRef Str) const; 333| | 334| | /// Parse the current string as an integer of the specified radix. If 335| | /// \p Radix is specified as zero, this does radix autosensing using 336| | /// extended C rules: 0 is octal, 0x is hex, 0b is binary. 337| | /// 338| | /// If the string is invalid or if only a subset of the string is valid, 339| | /// this returns true to signify the error. The string is considered 340| | /// erroneous if empty or if it overflows T. 341| | template 342| | typename std::enable_if::is_signed, bool>::type 343| | getAsInteger(unsigned Radix, T &Result) const { 344| | long long LLVal; 345| | if (getAsSignedInteger(*this, Radix, LLVal) || 346| | static_cast(LLVal) != LLVal) 347| | return true; 348| | Result = LLVal; 349| | return false; 350| | } 351| | 352| | template 353| | typename std::enable_if::is_signed, bool>::type 354| | getAsInteger(unsigned Radix, T &Result) const { 355| | unsigned long long ULLVal; 356| | // The additional cast to unsigned long long is required to avoid the 357| | // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type 358| | // 'unsigned __int64' when instantiating getAsInteger with T = bool. 359| | if (getAsUnsignedInteger(*this, Radix, ULLVal) || 360| | static_cast(static_cast(ULLVal)) != ULLVal) 361| | return true; 362| | Result = ULLVal; 363| | return false; 364| | } 365| | 366| | /// @} 367| | /// @name String Operations 368| | /// @{ 369| | 370| | // Convert the given ASCII string to lowercase. 371| | std::string lower() const; 372| | 373| | /// Convert the given ASCII string to uppercase. 374| | std::string upper() const; 375| | 376| | /// @} 377| | /// @name Substring Operations 378| | /// @{ 379| | 380| | /// Return a reference to the substring from [Start, Start + N). 381| | /// 382| | /// \param Start The index of the starting character in the substring; if 383| | /// the index is npos or greater than the length of the string then the 384| | /// empty substring will be returned. 385| | /// 386| | /// \param N The number of characters to included in the substring. If N 387| | /// exceeds the number of characters remaining in the string, the string 388| | /// suffix (starting with \p Start) will be returned. 389| | StringRef substr(size_t Start, size_t N = npos) const { 390| | Start = std::min(Start, Length); 391| | return StringRef(Data + Start, std::min(N, Length - Start)); 392| | } 393| | 394| | /// Return a StringRef equal to 'this' but with the first \p N elements 395| | /// dropped. 396| | StringRef drop_front(size_t N = 1) const { 397| | assert(size() >= N && "Dropping more elements than exist"); 398| | return substr(N); 399| | } 400| | 401| | /// Return a StringRef equal to 'this' but with the last \p N elements 402| | /// dropped. 403| | StringRef drop_back(size_t N = 1) const { 404| | assert(size() >= N && "Dropping more elements than exist"); 405| | return substr(0, size()-N); 406| | } 407| | 408| | /// Return a reference to the substring from [Start, End). 409| | /// 410| | /// \param Start The index of the starting character in the substring; if 411| | /// the index is npos or greater than the length of the string then the 412| | /// empty substring will be returned. 413| | /// 414| | /// \param End The index following the last character to include in the 415| | /// substring. If this is npos, or less than \p Start, or exceeds the 416| | /// number of characters remaining in the string, the string suffix 417| | /// (starting with \p Start) will be returned. 418| | StringRef slice(size_t Start, size_t End) const { 419| | Start = std::min(Start, Length); 420| | End = std::min(std::max(Start, End), Length); 421| | return StringRef(Data + Start, End - Start); 422| | } 423| | 424| | /// Split into two substrings around the first occurrence of a separator 425| | /// character. 426| | /// 427| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 428| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 429| | /// maximal. If \p Separator is not in the string, then the result is a 430| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 431| | /// 432| | /// \param Separator The character to split on. 433| | /// \returns The split substrings. 434| | std::pair split(char Separator) const { 435| | size_t Idx = find(Separator); 436| | if (Idx == npos) 437| | return std::make_pair(*this, StringRef()); 438| | return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 439| | } 440| | 441| | /// Split into two substrings around the first occurrence of a separator 442| | /// string. 443| | /// 444| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 445| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 446| | /// maximal. If \p Separator is not in the string, then the result is a 447| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 448| | /// 449| | /// \param Separator - The string to split on. 450| | /// \return - The split substrings. 451| | std::pair split(StringRef Separator) const { 452| | size_t Idx = find(Separator); 453| | if (Idx == npos) 454| | return std::make_pair(*this, StringRef()); 455| | return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); 456| | } 457| | 458| | /// Split into substrings around the occurrences of a separator string. 459| | /// 460| | /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most 461| | /// \p MaxSplit splits are done and consequently <= \p MaxSplit 462| | /// elements are added to A. 463| | /// If \p KeepEmpty is false, empty strings are not added to \p A. They 464| | /// still count when considering \p MaxSplit 465| | /// An useful invariant is that 466| | /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true 467| | /// 468| | /// \param A - Where to put the substrings. 469| | /// \param Separator - The string to split on. 470| | /// \param MaxSplit - The maximum number of times the string is split. 471| | /// \param KeepEmpty - True if empty substring should be added. 472| | void split(SmallVectorImpl &A, 473| | StringRef Separator, int MaxSplit = -1, 474| | bool KeepEmpty = true) const; 475| | 476| | /// Split into two substrings around the last occurrence of a separator 477| | /// character. 478| | /// 479| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 480| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 481| | /// minimal. If \p Separator is not in the string, then the result is a 482| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 483| | /// 484| | /// \param Separator - The character to split on. 485| | /// \return - The split substrings. 486| 0| std::pair rsplit(char Separator) const { 487| 0| size_t Idx = rfind(Separator); 488| 0| if (Idx == npos) 489| 0| return std::make_pair(*this, StringRef()); 490| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 491| 0| } 492| | 493| | /// Return string with consecutive characters in \p Chars starting from 494| | /// the left removed. 495| | StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { 496| | return drop_front(std::min(Length, find_first_not_of(Chars))); 497| | } 498| | 499| | /// Return string with consecutive characters in \p Chars starting from 500| | /// the right removed. 501| | StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { 502| | return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); 503| | } 504| | 505| | /// Return string with consecutive characters in \p Chars starting from 506| | /// the left and right removed. 507| 0| StringRef trim(StringRef Chars = " \t\n\v\f\r") const { 508| 0| return ltrim(Chars).rtrim(Chars); 509| 0| } 510| | 511| | /// @} 512| | }; 513| | 514| | /// @name StringRef Comparison Operators 515| | /// @{ 516| | 517| | inline bool operator==(StringRef LHS, StringRef RHS) { 518| | return LHS.equals(RHS); 519| | } 520| | 521| | inline bool operator!=(StringRef LHS, StringRef RHS) { 522| | return !(LHS == RHS); 523| | } 524| | 525| | inline bool operator<(StringRef LHS, StringRef RHS) { 526| | return LHS.compare(RHS) == -1; 527| | } 528| | 529| 0| inline bool operator<=(StringRef LHS, StringRef RHS) { 530| 0| return LHS.compare(RHS) != 1; 531| 0| } 532| | 533| 0| inline bool operator>(StringRef LHS, StringRef RHS) { 534| 0| return LHS.compare(RHS) == 1; 535| 0| } 536| | 537| 0| inline bool operator>=(StringRef LHS, StringRef RHS) { 538| 0| return LHS.compare(RHS) != -1; 539| 0| } 540| | 541| | inline std::string &operator+=(std::string &buffer, StringRef string) { 542| | return buffer.append(string.data(), string.size()); 543| | } 544| | 545| | /// @} 546| | 547| | /// \brief Compute a hash_code for a StringRef. 548| | hash_code hash_value(StringRef S); 549| | 550| | // StringRefs can be treated like a POD type. 551| | template struct isPodLike; 552| | template <> struct isPodLike { static const bool value = true; }; 553| |} 554| | 555| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Twine.h: 1| |//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_TWINE_H 11| |#define LLVM_ADT_TWINE_H 12| | 13| |#include "llvm/ADT/StringRef.h" 14| |#include "llvm/Support/DataTypes.h" 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include 17| |#include 18| | 19| |namespace llvm { 20| | template 21| | class SmallVectorImpl; 22| | class StringRef; 23| | class raw_ostream; 24| | 25| | /// Twine - A lightweight data structure for efficiently representing the 26| | /// concatenation of temporary values as strings. 27| | /// 28| | /// A Twine is a kind of rope, it represents a concatenated string using a 29| | /// binary-tree, where the string is the preorder of the nodes. Since the 30| | /// Twine can be efficiently rendered into a buffer when its result is used, 31| | /// it avoids the cost of generating temporary values for intermediate string 32| | /// results -- particularly in cases when the Twine result is never 33| | /// required. By explicitly tracking the type of leaf nodes, we can also avoid 34| | /// the creation of temporary strings for conversions operations (such as 35| | /// appending an integer to a string). 36| | /// 37| | /// A Twine is not intended for use directly and should not be stored, its 38| | /// implementation relies on the ability to store pointers to temporary stack 39| | /// objects which may be deallocated at the end of a statement. Twines should 40| | /// only be used accepted as const references in arguments, when an API wishes 41| | /// to accept possibly-concatenated strings. 42| | /// 43| | /// Twines support a special 'null' value, which always concatenates to form 44| | /// itself, and renders as an empty string. This can be returned from APIs to 45| | /// effectively nullify any concatenations performed on the result. 46| | /// 47| | /// \b Implementation 48| | /// 49| | /// Given the nature of a Twine, it is not possible for the Twine's 50| | /// concatenation method to construct interior nodes; the result must be 51| | /// represented inside the returned value. For this reason a Twine object 52| | /// actually holds two values, the left- and right-hand sides of a 53| | /// concatenation. We also have nullary Twine objects, which are effectively 54| | /// sentinel values that represent empty strings. 55| | /// 56| | /// Thus, a Twine can effectively have zero, one, or two children. The \see 57| | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 58| | /// testing the number of children. 59| | /// 60| | /// We maintain a number of invariants on Twine objects (FIXME: Why): 61| | /// - Nullary twines are always represented with their Kind on the left-hand 62| | /// side, and the Empty kind on the right-hand side. 63| | /// - Unary twines are always represented with the value on the left-hand 64| | /// side, and the Empty kind on the right-hand side. 65| | /// - If a Twine has another Twine as a child, that child should always be 66| | /// binary (otherwise it could have been folded into the parent). 67| | /// 68| | /// These invariants are check by \see isValid(). 69| | /// 70| | /// \b Efficiency Considerations 71| | /// 72| | /// The Twine is designed to yield efficient and small code for common 73| | /// situations. For this reason, the concat() method is inlined so that 74| | /// concatenations of leaf nodes can be optimized into stores directly into a 75| | /// single stack allocated object. 76| | /// 77| | /// In practice, not all compilers can be trusted to optimize concat() fully, 78| | /// so we provide two additional methods (and accompanying operator+ 79| | /// overloads) to guarantee that particularly important cases (cstring plus 80| | /// StringRef) codegen as desired. 81| | class Twine { 82| | /// NodeKind - Represent the type of an argument. 83| | enum NodeKind : unsigned char { 84| | /// An empty string; the result of concatenating anything with it is also 85| | /// empty. 86| | NullKind, 87| | 88| | /// The empty string. 89| | EmptyKind, 90| | 91| | /// A pointer to a Twine instance. 92| | TwineKind, 93| | 94| | /// A pointer to a C string instance. 95| | CStringKind, 96| | 97| | /// A pointer to an std::string instance. 98| | StdStringKind, 99| | 100| | /// A pointer to a StringRef instance. 101| | StringRefKind, 102| | 103| | /// A char value reinterpreted as a pointer, to render as a character. 104| | CharKind, 105| | 106| | /// An unsigned int value reinterpreted as a pointer, to render as an 107| | /// unsigned decimal integer. 108| | DecUIKind, 109| | 110| | /// An int value reinterpreted as a pointer, to render as a signed 111| | /// decimal integer. 112| | DecIKind, 113| | 114| | /// A pointer to an unsigned long value, to render as an unsigned decimal 115| | /// integer. 116| | DecULKind, 117| | 118| | /// A pointer to a long value, to render as a signed decimal integer. 119| | DecLKind, 120| | 121| | /// A pointer to an unsigned long long value, to render as an unsigned 122| | /// decimal integer. 123| | DecULLKind, 124| | 125| | /// A pointer to a long long value, to render as a signed decimal integer. 126| | DecLLKind, 127| | 128| | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 129| | /// integer. 130| | UHexKind 131| | }; 132| | 133| | union Child 134| | { 135| | const Twine *twine; 136| | const char *cString; 137| | const std::string *stdString; 138| | const StringRef *stringRef; 139| | char character; 140| | unsigned int decUI; 141| | int decI; 142| | const unsigned long *decUL; 143| | const long *decL; 144| | const unsigned long long *decULL; 145| | const long long *decLL; 146| | const uint64_t *uHex; 147| | }; 148| | 149| | private: 150| | /// LHS - The prefix in the concatenation, which may be uninitialized for 151| | /// Null or Empty kinds. 152| | Child LHS; 153| | /// RHS - The suffix in the concatenation, which may be uninitialized for 154| | /// Null or Empty kinds. 155| | Child RHS; 156| | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 157| | NodeKind LHSKind; 158| | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). 159| | NodeKind RHSKind; 160| | 161| | private: 162| | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 163| | explicit Twine(NodeKind Kind) 164| 0| : LHSKind(Kind), RHSKind(EmptyKind) { 165| 0| assert(isNullary() && "Invalid kind!"); 166| 0| } 167| | 168| | /// Construct a binary twine. 169| | explicit Twine(const Twine &LHS, const Twine &RHS) 170| 0| : LHSKind(TwineKind), RHSKind(TwineKind) { 171| 0| this->LHS.twine = &LHS; 172| 0| this->RHS.twine = &RHS; 173| 0| assert(isValid() && "Invalid twine!"); 174| 0| } 175| | 176| | /// Construct a twine from explicit values. 177| | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) 178| 0| : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { 179| 0| assert(isValid() && "Invalid twine!"); 180| 0| } 181| | 182| | /// Since the intended use of twines is as temporary objects, assignments 183| | /// when concatenating might cause undefined behavior or stack corruptions 184| | Twine &operator=(const Twine &Other) = delete; 185| | 186| | /// isNull - Check for the null twine. 187| 0| bool isNull() const { 188| 0| return getLHSKind() == NullKind; 189| 0| } 190| | 191| | /// isEmpty - Check for the empty twine. 192| 0| bool isEmpty() const { 193| 0| return getLHSKind() == EmptyKind; 194| 0| } 195| | 196| | /// isNullary - Check if this is a nullary twine (null or empty). 197| 0| bool isNullary() const { 198| 0| return isNull() || isEmpty(); 199| 0| } 200| | 201| | /// isUnary - Check if this is a unary twine. 202| 0| bool isUnary() const { 203| 0| return getRHSKind() == EmptyKind && !isNullary(); 204| 0| } 205| | 206| | /// isBinary - Check if this is a binary twine. 207| 0| bool isBinary() const { 208| 0| return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 209| 0| } 210| | 211| | /// isValid - Check if this is a valid twine (satisfying the invariants on 212| | /// order and number of arguments). 213| 0| bool isValid() const { 214| 0| // Nullary twines always have Empty on the RHS. 215| 0| if (isNullary() && getRHSKind() != EmptyKind) 216| 0| return false; 217| 0| 218| 0| // Null should never appear on the RHS. 219| 0| if (getRHSKind() == NullKind) 220| 0| return false; 221| 0| 222| 0| // The RHS cannot be non-empty if the LHS is empty. 223| 0| if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 224| 0| return false; 225| 0| 226| 0| // A twine child should always be binary. 227| 0| if (getLHSKind() == TwineKind && 228| 0| !LHS.twine->isBinary()) 229| 0| return false; 230| 0| if (getRHSKind() == TwineKind && 231| 0| !RHS.twine->isBinary()) 232| 0| return false; 233| 0| 234| 0| return true; 235| 0| } 236| | 237| | /// getLHSKind - Get the NodeKind of the left-hand side. 238| 0| NodeKind getLHSKind() const { return LHSKind; } 239| | 240| | /// getRHSKind - Get the NodeKind of the right-hand side. 241| 0| NodeKind getRHSKind() const { return RHSKind; } 242| | 243| | /// printOneChild - Print one child from a twine. 244| | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; 245| | 246| | /// printOneChildRepr - Print the representation of one child from a twine. 247| | void printOneChildRepr(raw_ostream &OS, Child Ptr, 248| | NodeKind Kind) const; 249| | 250| | public: 251| | /// @name Constructors 252| | /// @{ 253| | 254| | /// Construct from an empty string. 255| 0| /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 256| 0| assert(isValid() && "Invalid twine!"); 257| 0| } 258| | 259| | Twine(const Twine &) = default; 260| | 261| | /// Construct from a C string. 262| | /// 263| | /// We take care here to optimize "" into the empty twine -- this will be 264| | /// optimized out for string constants. This allows Twine arguments have 265| | /// default "" values, without introducing unnecessary string constants. 266| | /*implicit*/ Twine(const char *Str) 267| 0| : RHSKind(EmptyKind) { 268| 0| if (Str[0] != '\0') { 269| 0| LHS.cString = Str; 270| 0| LHSKind = CStringKind; 271| 0| } else 272| 0| LHSKind = EmptyKind; 273| 0| 274| 0| assert(isValid() && "Invalid twine!"); 275| 0| } 276| | 277| | /// Construct from an std::string. 278| | /*implicit*/ Twine(const std::string &Str) 279| 0| : LHSKind(StdStringKind), RHSKind(EmptyKind) { 280| 0| LHS.stdString = &Str; 281| 0| assert(isValid() && "Invalid twine!"); 282| 0| } 283| | 284| | /// Construct from a StringRef. 285| | /*implicit*/ Twine(const StringRef &Str) 286| | : LHSKind(StringRefKind), RHSKind(EmptyKind) { 287| | LHS.stringRef = &Str; 288| | assert(isValid() && "Invalid twine!"); 289| | } 290| | 291| | /// Construct from a char. 292| | explicit Twine(char Val) 293| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 294| 0| LHS.character = Val; 295| 0| } 296| | 297| | /// Construct from a signed char. 298| | explicit Twine(signed char Val) 299| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 300| 0| LHS.character = static_cast(Val); 301| 0| } 302| | 303| | /// Construct from an unsigned char. 304| | explicit Twine(unsigned char Val) 305| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 306| 0| LHS.character = static_cast(Val); 307| 0| } 308| | 309| | /// Construct a twine to print \p Val as an unsigned decimal integer. 310| | explicit Twine(unsigned Val) 311| 0| : LHSKind(DecUIKind), RHSKind(EmptyKind) { 312| 0| LHS.decUI = Val; 313| 0| } 314| | 315| | /// Construct a twine to print \p Val as a signed decimal integer. 316| | explicit Twine(int Val) 317| 0| : LHSKind(DecIKind), RHSKind(EmptyKind) { 318| 0| LHS.decI = Val; 319| 0| } 320| | 321| | /// Construct a twine to print \p Val as an unsigned decimal integer. 322| | explicit Twine(const unsigned long &Val) 323| 0| : LHSKind(DecULKind), RHSKind(EmptyKind) { 324| 0| LHS.decUL = &Val; 325| 0| } 326| | 327| | /// Construct a twine to print \p Val as a signed decimal integer. 328| | explicit Twine(const long &Val) 329| 0| : LHSKind(DecLKind), RHSKind(EmptyKind) { 330| 0| LHS.decL = &Val; 331| 0| } 332| | 333| | /// Construct a twine to print \p Val as an unsigned decimal integer. 334| | explicit Twine(const unsigned long long &Val) 335| 0| : LHSKind(DecULLKind), RHSKind(EmptyKind) { 336| 0| LHS.decULL = &Val; 337| 0| } 338| | 339| | /// Construct a twine to print \p Val as a signed decimal integer. 340| | explicit Twine(const long long &Val) 341| 0| : LHSKind(DecLLKind), RHSKind(EmptyKind) { 342| 0| LHS.decLL = &Val; 343| 0| } 344| | 345| | // FIXME: Unfortunately, to make sure this is as efficient as possible we 346| | // need extra binary constructors from particular types. We can't rely on 347| | // the compiler to be smart enough to fold operator+()/concat() down to the 348| | // right thing. Yet. 349| | 350| | /// Construct as the concatenation of a C string and a StringRef. 351| | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) 352| | : LHSKind(CStringKind), RHSKind(StringRefKind) { 353| | this->LHS.cString = LHS; 354| | this->RHS.stringRef = &RHS; 355| | assert(isValid() && "Invalid twine!"); 356| | } 357| | 358| | /// Construct as the concatenation of a StringRef and a C string. 359| | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) 360| | : LHSKind(StringRefKind), RHSKind(CStringKind) { 361| | this->LHS.stringRef = &LHS; 362| | this->RHS.cString = RHS; 363| | assert(isValid() && "Invalid twine!"); 364| | } 365| | 366| | /// Create a 'null' string, which is an empty string that always 367| | /// concatenates to form another empty string. 368| 0| static Twine createNull() { 369| 0| return Twine(NullKind); 370| 0| } 371| | 372| | /// @} 373| | /// @name Numeric Conversions 374| | /// @{ 375| | 376| | // Construct a twine to print \p Val as an unsigned hexadecimal integer. 377| | static Twine utohexstr(const uint64_t &Val) { 378| | Child LHS, RHS; 379| | LHS.uHex = &Val; 380| | RHS.twine = nullptr; 381| | return Twine(LHS, UHexKind, RHS, EmptyKind); 382| | } 383| | 384| | /// @} 385| | /// @name Predicate Operations 386| | /// @{ 387| | 388| | /// isTriviallyEmpty - Check if this twine is trivially empty; a false 389| | /// return value does not necessarily mean the twine is empty. 390| | bool isTriviallyEmpty() const { 391| | return isNullary(); 392| | } 393| | 394| | /// isSingleStringRef - Return true if this twine can be dynamically 395| | /// accessed as a single StringRef value with getSingleStringRef(). 396| | bool isSingleStringRef() const { 397| | if (getRHSKind() != EmptyKind) return false; 398| | 399| | switch (getLHSKind()) { 400| | case EmptyKind: 401| | case CStringKind: 402| | case StdStringKind: 403| | case StringRefKind: 404| | return true; 405| | default: 406| | return false; 407| | } 408| | } 409| | 410| | /// @} 411| | /// @name String Operations 412| | /// @{ 413| | 414| | Twine concat(const Twine &Suffix) const; 415| | 416| | /// @} 417| | /// @name Output & Conversion. 418| | /// @{ 419| | 420| | /// str - Return the twine contents as a std::string. 421| | std::string str() const; 422| | 423| | /// toVector - Write the concatenated string into the given SmallString or 424| | /// SmallVector. 425| | void toVector(SmallVectorImpl &Out) const; 426| | 427| | /// getSingleStringRef - This returns the twine as a single StringRef. This 428| | /// method is only valid if isSingleStringRef() is true. 429| | StringRef getSingleStringRef() const { 430| | assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); 431| | switch (getLHSKind()) { 432| | default: llvm_unreachable("Out of sync with isSingleStringRef"); 433| | case EmptyKind: return StringRef(); 434| | case CStringKind: return StringRef(LHS.cString); 435| | case StdStringKind: return StringRef(*LHS.stdString); 436| | case StringRefKind: return *LHS.stringRef; 437| | } 438| | } 439| | 440| | /// toStringRef - This returns the twine as a single StringRef if it can be 441| | /// represented as such. Otherwise the twine is written into the given 442| | /// SmallVector and a StringRef to the SmallVector's data is returned. 443| | StringRef toStringRef(SmallVectorImpl &Out) const; 444| | 445| | /// toNullTerminatedStringRef - This returns the twine as a single null 446| | /// terminated StringRef if it can be represented as such. Otherwise the 447| | /// twine is written into the given SmallVector and a StringRef to the 448| | /// SmallVector's data is returned. 449| | /// 450| | /// The returned StringRef's size does not include the null terminator. 451| | StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; 452| | 453| | /// Write the concatenated string represented by this twine to the 454| | /// stream \p OS. 455| | void print(raw_ostream &OS) const; 456| | 457| | /// Dump the concatenated string represented by this twine to stderr. 458| | void dump() const; 459| | 460| | /// Write the representation of this twine to the stream \p OS. 461| | void printRepr(raw_ostream &OS) const; 462| | 463| | /// Dump the representation of this twine to stderr. 464| | void dumpRepr() const; 465| | 466| | /// @} 467| | }; 468| | 469| | /// @name Twine Inline Implementations 470| | /// @{ 471| | 472| 0| inline Twine Twine::concat(const Twine &Suffix) const { 473| 0| // Concatenation with null is null. 474| 0| if (isNull() || Suffix.isNull()) 475| 0| return Twine(NullKind); 476| 0| 477| 0| // Concatenation with empty yields the other side. 478| 0| if (isEmpty()) 479| 0| return Suffix; 480| 0| if (Suffix.isEmpty()) 481| 0| return *this; 482| 0| 483| 0| // Otherwise we need to create a new node, taking care to fold in unary 484| 0| // twines. 485| 0| Child NewLHS, NewRHS; 486| 0| NewLHS.twine = this; 487| 0| NewRHS.twine = &Suffix; 488| 0| NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 489| 0| if (isUnary()) { 490| 0| NewLHS = LHS; 491| 0| NewLHSKind = getLHSKind(); 492| 0| } 493| 0| if (Suffix.isUnary()) { 494| 0| NewRHS = Suffix.LHS; 495| 0| NewRHSKind = Suffix.getLHSKind(); 496| 0| } 497| 0| 498| 0| return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 499| 0| } 500| | 501| 0| inline Twine operator+(const Twine &LHS, const Twine &RHS) { 502| 0| return LHS.concat(RHS); 503| 0| } 504| | 505| | /// Additional overload to guarantee simplified codegen; this is equivalent to 506| | /// concat(). 507| | 508| | inline Twine operator+(const char *LHS, const StringRef &RHS) { 509| | return Twine(LHS, RHS); 510| | } 511| | 512| | /// Additional overload to guarantee simplified codegen; this is equivalent to 513| | /// concat(). 514| | 515| | inline Twine operator+(const StringRef &LHS, const char *RHS) { 516| | return Twine(LHS, RHS); 517| | } 518| | 519| | inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 520| | RHS.print(OS); 521| | return OS; 522| | } 523| | 524| | /// @} 525| |} 526| | 527| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/AlignOf.h: 1| |//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the AlignOf function that computes alignments for 11| |// arbitrary types. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ALIGNOF_H 16| |#define LLVM_SUPPORT_ALIGNOF_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include 20| | 21| |namespace llvm { 22| |template 23| |struct AlignmentCalcImpl { 24| | char x; 25| | T t; 26| |private: 27| | AlignmentCalcImpl() {} // Never instantiate. 28| |}; 29| | 30| |/// AlignOf - A templated class that contains an enum value representing 31| |/// the alignment of the template argument. For example, 32| |/// AlignOf::Alignment represents the alignment of type "int". The 33| |/// alignment calculated is the minimum alignment, and not necessarily 34| |/// the "desired" alignment returned by GCC's __alignof__ (for example). Note 35| |/// that because the alignment is an enum value, it can be used as a 36| |/// compile-time constant (e.g., for template instantiation). 37| |template 38| |struct AlignOf { 39| | enum { Alignment = 40| | static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; 41| | 42| | enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; 43| | enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; 44| | enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; 45| | enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; 46| | 47| | enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; 48| | enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; 49| | enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; 50| | enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; 51| |}; 52| | 53| |/// alignOf - A templated function that returns the minimum alignment of 54| |/// of a type. This provides no extra functionality beyond the AlignOf 55| |/// class besides some cosmetic cleanliness. Example usage: 56| |/// alignOf() returns the alignment of an int. 57| |template 58| 0|inline unsigned alignOf() { return AlignOf::Alignment; } 59| | 60| |/// \struct AlignedCharArray 61| |/// \brief Helper for building an aligned character array type. 62| |/// 63| |/// This template is used to explicitly build up a collection of aligned 64| |/// character array types. We have to build these up using a macro and explicit 65| |/// specialization to cope with old versions of MSVC and GCC where only an 66| |/// integer literal can be used to specify an alignment constraint. Once built 67| |/// up here, we can then begin to indirect between these using normal C++ 68| |/// template parameters. 69| | 70| |// MSVC requires special handling here. 71| |#ifndef _MSC_VER 72| | 73| |#if __has_feature(cxx_alignas) 74| |template 75| |struct AlignedCharArray { 76| | alignas(Alignment) char buffer[Size]; 77| |}; 78| | 79| |#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) 80| |/// \brief Create a type with an aligned char buffer. 81| |template 82| |struct AlignedCharArray; 83| | 84| |#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 85| | template \ 86| | struct AlignedCharArray { \ 87| | __attribute__((aligned(x))) char buffer[Size]; \ 88| | }; 89| | 90| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) 91| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) 92| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) 93| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) 94| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 95| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 96| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 97| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 98| | 99| |#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 100| | 101| |#else 102| |# error No supported align as directive. 103| |#endif 104| | 105| |#else // _MSC_VER 106| | 107| |/// \brief Create a type with an aligned char buffer. 108| |template 109| |struct AlignedCharArray; 110| | 111| |// We provide special variations of this template for the most common 112| |// alignments because __declspec(align(...)) doesn't actually work when it is 113| |// a member of a by-value function argument in MSVC, even if the alignment 114| |// request is something reasonably like 8-byte or 16-byte. Note that we can't 115| |// even include the declspec with the union that forces the alignment because 116| |// MSVC warns on the existence of the declspec despite the union member forcing 117| |// proper alignment. 118| | 119| |template 120| |struct AlignedCharArray<1, Size> { 121| | union { 122| | char aligned; 123| | char buffer[Size]; 124| | }; 125| |}; 126| | 127| |template 128| |struct AlignedCharArray<2, Size> { 129| | union { 130| | short aligned; 131| | char buffer[Size]; 132| | }; 133| |}; 134| | 135| |template 136| |struct AlignedCharArray<4, Size> { 137| | union { 138| | int aligned; 139| | char buffer[Size]; 140| | }; 141| |}; 142| | 143| |template 144| |struct AlignedCharArray<8, Size> { 145| | union { 146| | double aligned; 147| | char buffer[Size]; 148| | }; 149| |}; 150| | 151| | 152| |// The rest of these are provided with a __declspec(align(...)) and we simply 153| |// can't pass them by-value as function arguments on MSVC. 154| | 155| |#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 156| | template \ 157| | struct AlignedCharArray { \ 158| | __declspec(align(x)) char buffer[Size]; \ 159| | }; 160| | 161| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 162| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 163| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 164| |LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 165| | 166| |#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 167| | 168| |#endif // _MSC_VER 169| | 170| |namespace detail { 171| |template 175| |class AlignerImpl { 176| | T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; 177| | 178| | AlignerImpl(); // Never defined or instantiated. 179| |}; 180| | 181| |template 185| |union SizerImpl { 186| | char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], 187| | arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], 188| | arr9[sizeof(T9)], arr10[sizeof(T10)]; 189| |}; 190| |} // end namespace detail 191| | 192| |/// \brief This union template exposes a suitably aligned and sized character 193| |/// array member which can hold elements of any of up to four types. 194| |/// 195| |/// These types may be arrays, structs, or any other types. The goal is to 196| |/// expose a char array buffer member which can be used as suitable storage for 197| |/// a placement new of any of these types. Support for more than seven types can 198| |/// be added at the cost of more boiler plate. 199| |template 203| |struct AlignedCharArrayUnion : llvm::AlignedCharArray< 204| | AlignOf >::Alignment, 206| | sizeof(detail::SizerImpl)> { 208| |}; 209| |} // end namespace llvm 210| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Allocator.h: 1| |//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// \file 10| |/// 11| |/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both 12| |/// of these conform to an LLVM "Allocator" concept which consists of an 13| |/// Allocate method accepting a size and alignment, and a Deallocate accepting 14| |/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of 15| |/// Allocate and Deallocate for setting size and alignment based on the final 16| |/// type. These overloads are typically provided by a base class template \c 17| |/// AllocatorBase. 18| |/// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_SUPPORT_ALLOCATOR_H 22| |#define LLVM_SUPPORT_ALLOCATOR_H 23| | 24| |#include "llvm/ADT/SmallVector.h" 25| |#include "llvm/Support/AlignOf.h" 26| |#include "llvm/Support/DataTypes.h" 27| |#include "llvm/Support/MathExtras.h" 28| |#include "llvm/Support/Memory.h" 29| |#include 30| |#include 31| |#include 32| |#include 33| | 34| |namespace llvm { 35| | 36| |/// \brief CRTP base class providing obvious overloads for the core \c 37| |/// Allocate() methods of LLVM-style allocators. 38| |/// 39| |/// This base class both documents the full public interface exposed by all 40| |/// LLVM-style allocators, and redirects all of the overloads to a single core 41| |/// set of methods which the derived class must define. 42| |template class AllocatorBase { 43| |public: 44| | /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method 45| | /// must be implemented by \c DerivedT. 46| | void *Allocate(size_t Size, size_t Alignment) { 47| |#ifdef __clang__ 48| | static_assert(static_cast( 49| | &AllocatorBase::Allocate) != 50| | static_cast( 51| | &DerivedT::Allocate), 52| | "Class derives from AllocatorBase without implementing the " 53| | "core Allocate(size_t, size_t) overload!"); 54| |#endif 55| | return static_cast(this)->Allocate(Size, Alignment); 56| | } 57| | 58| | /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this 59| | /// allocator. 60| | void Deallocate(const void *Ptr, size_t Size) { 61| |#ifdef __clang__ 62| | static_assert(static_cast( 63| | &AllocatorBase::Deallocate) != 64| | static_cast( 65| | &DerivedT::Deallocate), 66| | "Class derives from AllocatorBase without implementing the " 67| | "core Deallocate(void *) overload!"); 68| |#endif 69| | return static_cast(this)->Deallocate(Ptr, Size); 70| | } 71| | 72| | // The rest of these methods are helpers that redirect to one of the above 73| | // core methods. 74| | 75| | /// \brief Allocate space for a sequence of objects without constructing them. 76| | template T *Allocate(size_t Num = 1) { 77| | return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); 78| | } 79| | 80| | /// \brief Deallocate space for a sequence of objects without constructing them. 81| | template 82| | typename std::enable_if< 83| | !std::is_same::type, void>::value, void>::type 84| | Deallocate(T *Ptr, size_t Num = 1) { 85| | Deallocate(static_cast(Ptr), Num * sizeof(T)); 86| | } 87| |}; 88| | 89| |class MallocAllocator : public AllocatorBase { 90| |public: 91| 0| void Reset() {} 92| | 93| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, 94| 0| size_t /*Alignment*/) { 95| 0| return malloc(Size); 96| 0| } 97| | 98| | // Pull in base class overloads. 99| | using AllocatorBase::Allocate; 100| | 101| 0| void Deallocate(const void *Ptr, size_t /*Size*/) { 102| 0| free(const_cast(Ptr)); 103| 0| } 104| | 105| | // Pull in base class overloads. 106| | using AllocatorBase::Deallocate; 107| | 108| 0| void PrintStats() const {} 109| |}; 110| | 111| |namespace detail { 112| | 113| |// We call out to an external function to actually print the message as the 114| |// printing code uses Allocator.h in its implementation. 115| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 116| | size_t TotalMemory); 117| |} // End namespace detail. 118| | 119| |/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. 120| |/// 121| |/// This isn't strictly a bump-pointer allocator as it uses backing slabs of 122| |/// memory rather than relying on a boundless contiguous heap. However, it has 123| |/// bump-pointer semantics in that it is a monotonically growing pool of memory 124| |/// where every allocation is found by merely allocating the next N bytes in 125| |/// the slab, or the next N bytes in the next slab. 126| |/// 127| |/// Note that this also has a threshold for forcing allocations above a certain 128| |/// size into their own slab. 129| |/// 130| |/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator 131| |/// object, which wraps malloc, to allocate memory, but it can be changed to 132| |/// use a custom allocator. 133| |template 135| |class BumpPtrAllocatorImpl 136| | : public AllocatorBase< 137| | BumpPtrAllocatorImpl> { 138| |public: 139| | static_assert(SizeThreshold <= SlabSize, 140| | "The SizeThreshold must be at most the SlabSize to ensure " 141| | "that objects larger than a slab go into their own memory " 142| | "allocation."); 143| | 144| | BumpPtrAllocatorImpl() 145| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} 146| | template 147| | BumpPtrAllocatorImpl(T &&Allocator) 148| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), 149| | Allocator(std::forward(Allocator)) {} 150| | 151| | // Manually implement a move constructor as we must clear the old allocators 152| | // slabs as a matter of correctness. 153| | BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) 154| | : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), 155| | CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), 156| | BytesAllocated(Old.BytesAllocated), 157| | Allocator(std::move(Old.Allocator)) { 158| | Old.CurPtr = Old.End = nullptr; 159| | Old.BytesAllocated = 0; 160| | Old.Slabs.clear(); 161| | Old.CustomSizedSlabs.clear(); 162| | } 163| | 164| | ~BumpPtrAllocatorImpl() { 165| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 166| | DeallocateCustomSizedSlabs(); 167| | } 168| | 169| | BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { 170| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 171| | DeallocateCustomSizedSlabs(); 172| | 173| | CurPtr = RHS.CurPtr; 174| | End = RHS.End; 175| | BytesAllocated = RHS.BytesAllocated; 176| | Slabs = std::move(RHS.Slabs); 177| | CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); 178| | Allocator = std::move(RHS.Allocator); 179| | 180| | RHS.CurPtr = RHS.End = nullptr; 181| | RHS.BytesAllocated = 0; 182| | RHS.Slabs.clear(); 183| | RHS.CustomSizedSlabs.clear(); 184| | return *this; 185| | } 186| | 187| | /// \brief Deallocate all but the current slab and reset the current pointer 188| | /// to the beginning of it, freeing all memory allocated so far. 189| | void Reset() { 190| | if (Slabs.empty()) 191| | return; 192| | 193| | // Reset the state. 194| | BytesAllocated = 0; 195| | CurPtr = (char *)Slabs.front(); 196| | End = CurPtr + SlabSize; 197| | 198| | // Deallocate all but the first slab, and all custome sized slabs. 199| | DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); 200| | Slabs.erase(std::next(Slabs.begin()), Slabs.end()); 201| | DeallocateCustomSizedSlabs(); 202| | CustomSizedSlabs.clear(); 203| | } 204| | 205| | /// \brief Allocate space at the specified alignment. 206| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { 207| | assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); 208| | 209| | // Keep track of how many bytes we've allocated. 210| | BytesAllocated += Size; 211| | 212| | size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); 213| | assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); 214| | 215| | // Check if we have enough space. 216| | if (Adjustment + Size <= size_t(End - CurPtr)) { 217| | char *AlignedPtr = CurPtr + Adjustment; 218| | CurPtr = AlignedPtr + Size; 219| | // Update the allocation point of this memory block in MemorySanitizer. 220| | // Without this, MemorySanitizer messages for values originated from here 221| | // will point to the allocation of the entire slab. 222| | __msan_allocated_memory(AlignedPtr, Size); 223| | return AlignedPtr; 224| | } 225| | 226| | // If Size is really big, allocate a separate slab for it. 227| | size_t PaddedSize = Size + Alignment - 1; 228| | if (PaddedSize > SizeThreshold) { 229| | void *NewSlab = Allocator.Allocate(PaddedSize, 0); 230| | CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); 231| | 232| | uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); 233| | assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); 234| | char *AlignedPtr = (char*)AlignedAddr; 235| | __msan_allocated_memory(AlignedPtr, Size); 236| | return AlignedPtr; 237| | } 238| | 239| | // Otherwise, start a new slab and try again. 240| | StartNewSlab(); 241| | uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); 242| | assert(AlignedAddr + Size <= (uintptr_t)End && 243| | "Unable to allocate memory!"); 244| | char *AlignedPtr = (char*)AlignedAddr; 245| | CurPtr = AlignedPtr + Size; 246| | __msan_allocated_memory(AlignedPtr, Size); 247| | return AlignedPtr; 248| | } 249| | 250| | // Pull in base class overloads. 251| | using AllocatorBase::Allocate; 252| | 253| | void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} 254| | 255| | // Pull in base class overloads. 256| | using AllocatorBase::Deallocate; 257| | 258| | size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } 259| | 260| | size_t getTotalMemory() const { 261| | size_t TotalMemory = 0; 262| | for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) 263| | TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); 264| | for (auto &PtrAndSize : CustomSizedSlabs) 265| | TotalMemory += PtrAndSize.second; 266| | return TotalMemory; 267| | } 268| | 269| | void PrintStats() const { 270| | detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, 271| | getTotalMemory()); 272| | } 273| | 274| |private: 275| | /// \brief The current pointer into the current slab. 276| | /// 277| | /// This points to the next free byte in the slab. 278| | char *CurPtr; 279| | 280| | /// \brief The end of the current slab. 281| | char *End; 282| | 283| | /// \brief The slabs allocated so far. 284| | SmallVector Slabs; 285| | 286| | /// \brief Custom-sized slabs allocated for too-large allocation requests. 287| | SmallVector, 0> CustomSizedSlabs; 288| | 289| | /// \brief How many bytes we've allocated. 290| | /// 291| | /// Used so that we can compute how much space was wasted. 292| | size_t BytesAllocated; 293| | 294| | /// \brief The allocator instance we use to get slabs of memory. 295| | AllocatorT Allocator; 296| | 297| | static size_t computeSlabSize(unsigned SlabIdx) { 298| | // Scale the actual allocated slab size based on the number of slabs 299| | // allocated. Every 128 slabs allocated, we double the allocated size to 300| | // reduce allocation frequency, but saturate at multiplying the slab size by 301| | // 2^30. 302| | return SlabSize * ((size_t)1 << std::min(30, SlabIdx / 128)); 303| | } 304| | 305| | /// \brief Allocate a new slab and move the bump pointers over into the new 306| | /// slab, modifying CurPtr and End. 307| | void StartNewSlab() { 308| | size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); 309| | 310| | void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); 311| | Slabs.push_back(NewSlab); 312| | CurPtr = (char *)(NewSlab); 313| | End = ((char *)NewSlab) + AllocatedSlabSize; 314| | } 315| | 316| | /// \brief Deallocate a sequence of slabs. 317| | void DeallocateSlabs(SmallVectorImpl::iterator I, 318| | SmallVectorImpl::iterator E) { 319| | for (; I != E; ++I) { 320| | size_t AllocatedSlabSize = 321| | computeSlabSize(std::distance(Slabs.begin(), I)); 322| |#ifndef NDEBUG 323| | // Poison the memory so stale pointers crash sooner. Note we must 324| | // preserve the Size and NextPtr fields at the beginning. 325| | if (AllocatedSlabSize != 0) { 326| | sys::Memory::setRangeWritable(*I, AllocatedSlabSize); 327| | memset(*I, 0xCD, AllocatedSlabSize); 328| | } 329| |#endif 330| | Allocator.Deallocate(*I, AllocatedSlabSize); 331| | } 332| | } 333| | 334| | /// \brief Deallocate all memory for custom sized slabs. 335| | void DeallocateCustomSizedSlabs() { 336| | for (auto &PtrAndSize : CustomSizedSlabs) { 337| | void *Ptr = PtrAndSize.first; 338| | size_t Size = PtrAndSize.second; 339| |#ifndef NDEBUG 340| | // Poison the memory so stale pointers crash sooner. Note we must 341| | // preserve the Size and NextPtr fields at the beginning. 342| | sys::Memory::setRangeWritable(Ptr, Size); 343| | memset(Ptr, 0xCD, Size); 344| |#endif 345| | Allocator.Deallocate(Ptr, Size); 346| | } 347| | } 348| | 349| | template friend class SpecificBumpPtrAllocator; 350| |}; 351| | 352| |/// \brief The standard BumpPtrAllocator which just uses the default template 353| |/// paramaters. 354| |typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 355| | 356| |/// \brief A BumpPtrAllocator that allows only elements of a specific type to be 357| |/// allocated. 358| |/// 359| |/// This allows calling the destructor in DestroyAll() and when the allocator is 360| |/// destroyed. 361| |template class SpecificBumpPtrAllocator { 362| | BumpPtrAllocator Allocator; 363| | 364| |public: 365| | SpecificBumpPtrAllocator() : Allocator() {} 366| | SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) 367| | : Allocator(std::move(Old.Allocator)) {} 368| | ~SpecificBumpPtrAllocator() { DestroyAll(); } 369| | 370| | SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { 371| | Allocator = std::move(RHS.Allocator); 372| | return *this; 373| | } 374| | 375| | /// Call the destructor of each allocated object and deallocate all but the 376| | /// current slab and reset the current pointer to the beginning of it, freeing 377| | /// all memory allocated so far. 378| | void DestroyAll() { 379| | auto DestroyElements = [](char *Begin, char *End) { 380| | assert(Begin == (char*)alignAddr(Begin, alignOf())); 381| | for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) 382| | reinterpret_cast(Ptr)->~T(); 383| | }; 384| | 385| | for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; 386| | ++I) { 387| | size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( 388| | std::distance(Allocator.Slabs.begin(), I)); 389| | char *Begin = (char*)alignAddr(*I, alignOf()); 390| | char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr 391| | : (char *)*I + AllocatedSlabSize; 392| | 393| | DestroyElements(Begin, End); 394| | } 395| | 396| | for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { 397| | void *Ptr = PtrAndSize.first; 398| | size_t Size = PtrAndSize.second; 399| | DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); 400| | } 401| | 402| | Allocator.Reset(); 403| | } 404| | 405| | /// \brief Allocate space for an array of objects without constructing them. 406| | T *Allocate(size_t num = 1) { return Allocator.Allocate(num); } 407| |}; 408| | 409| |} // end namespace llvm 410| | 411| |template 412| |void *operator new(size_t Size, 413| | llvm::BumpPtrAllocatorImpl &Allocator) { 415| | struct S { 416| | char c; 417| | union { 418| | double D; 419| | long double LD; 420| | long long L; 421| | void *P; 422| | } x; 423| | }; 424| | return Allocator.Allocate( 425| | Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); 426| |} 427| | 428| |template 429| |void operator delete( 430| | void *, llvm::BumpPtrAllocatorImpl &) { 431| |} 432| | 433| |#endif // LLVM_SUPPORT_ALLOCATOR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Compiler.h: 1| |//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines several macros, based on the current compiler. This allows 11| |// use of compiler-specific features in a way that remains portable. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_COMPILER_H 16| |#define LLVM_SUPPORT_COMPILER_H 17| | 18| |#include "llvm/Config/llvm-config.h" 19| | 20| |#ifndef __has_feature 21| |# define __has_feature(x) 0 22| |#endif 23| | 24| |#ifndef __has_extension 25| |# define __has_extension(x) 0 26| |#endif 27| | 28| |#ifndef __has_attribute 29| |# define __has_attribute(x) 0 30| |#endif 31| | 32| |#ifndef __has_builtin 33| |# define __has_builtin(x) 0 34| |#endif 35| | 36| |/// \macro LLVM_GNUC_PREREQ 37| |/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't 38| |/// available. 39| |#ifndef LLVM_GNUC_PREREQ 40| |# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 42| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43| | ((maj) << 20) + ((min) << 10) + (patch)) 44| |# elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 46| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47| |# else 48| |# define LLVM_GNUC_PREREQ(maj, min, patch) 0 49| |# endif 50| |#endif 51| | 52| |/// \macro LLVM_MSC_PREREQ 53| |/// \brief Is the compiler MSVC of at least the specified version? 54| |/// The common \param version values to check for are: 55| |/// * 1800: Microsoft Visual Studio 2013 / 12.0 56| |/// * 1900: Microsoft Visual Studio 2015 / 14.0 57| |#ifdef _MSC_VER 58| |#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) 59| | 60| |// We require at least MSVC 2013. 61| |#if !LLVM_MSC_PREREQ(1800) 62| |#error LLVM requires at least MSVC 2013. 63| |#endif 64| | 65| |#else 66| |#define LLVM_MSC_PREREQ(version) 0 67| |#endif 68| | 69| |#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) 70| |#define LLVM_NOEXCEPT noexcept 71| |#else 72| |#define LLVM_NOEXCEPT 73| |#endif 74| | 75| |/// \brief Does the compiler support r-value reference *this? 76| |/// 77| |/// Sadly, this is separate from just r-value reference support because GCC 78| |/// implemented this later than everything else. 79| |#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) 80| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 81| |#else 82| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 83| |#endif 84| | 85| |/// Expands to '&' if r-value references are supported. 86| |/// 87| |/// This can be used to provide l-value/r-value overrides of member functions. 88| |/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS 89| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 90| |#define LLVM_LVALUE_FUNCTION & 91| |#else 92| |#define LLVM_LVALUE_FUNCTION 93| |#endif 94| | 95| |#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) 96| |# define LLVM_CONSTEXPR constexpr 97| |#else 98| |# define LLVM_CONSTEXPR 99| |#endif 100| | 101| |/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked 102| |/// into a shared library, then the class should be private to the library and 103| |/// not accessible from outside it. Can also be used to mark variables and 104| |/// functions, making them private to any shared library they are linked into. 105| |/// On PE/COFF targets, library visibility is the default, so this isn't needed. 106| |#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 107| | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) 108| |#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) 109| |#else 110| |#define LLVM_LIBRARY_VISIBILITY 111| |#endif 112| | 113| |#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) 114| |#define LLVM_END_WITH_NULL __attribute__((sentinel)) 115| |#else 116| |#define LLVM_END_WITH_NULL 117| |#endif 118| | 119| |#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) 120| |#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) 121| |#else 122| |#define LLVM_ATTRIBUTE_USED 123| |#endif 124| | 125| |#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) 126| |#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) 127| |#else 128| |#define LLVM_ATTRIBUTE_UNUSED_RESULT 129| |#endif 130| | 131| |// Some compilers warn about unused functions. When a function is sometimes 132| |// used or not depending on build settings (e.g. a function only called from 133| |// within "assert"), this attribute can be used to suppress such warnings. 134| |// 135| |// However, it shouldn't be used for unused *variables*, as those have a much 136| |// more portable solution: 137| |// (void)unused_var_name; 138| |// Prefer cast-to-void wherever it is sufficient. 139| |#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) 140| |#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) 141| |#else 142| |#define LLVM_ATTRIBUTE_UNUSED 143| |#endif 144| | 145| |// FIXME: Provide this for PE/COFF targets. 146| |#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 147| | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) 148| |#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) 149| |#else 150| |#define LLVM_ATTRIBUTE_WEAK 151| |#endif 152| | 153| |// Prior to clang 3.2, clang did not accept any spelling of 154| |// __has_attribute(const), so assume it is supported. 155| |#if defined(__clang__) || defined(__GNUC__) 156| |// aka 'CONST' but following LLVM Conventions. 157| |#define LLVM_READNONE __attribute__((__const__)) 158| |#else 159| |#define LLVM_READNONE 160| |#endif 161| | 162| |#if __has_attribute(pure) || defined(__GNUC__) 163| |// aka 'PURE' but following LLVM Conventions. 164| |#define LLVM_READONLY __attribute__((__pure__)) 165| |#else 166| |#define LLVM_READONLY 167| |#endif 168| | 169| |#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) 170| 0|#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) 171| 0|#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) 172| |#else 173| |#define LLVM_LIKELY(EXPR) (EXPR) 174| |#define LLVM_UNLIKELY(EXPR) (EXPR) 175| |#endif 176| | 177| |// C++ doesn't support 'extern template' of template specializations. GCC does, 178| |// but requires __extension__ before it. In the header, use this: 179| |// EXTERN_TEMPLATE_INSTANTIATION(class foo); 180| |// in the .cpp file, use this: 181| |// TEMPLATE_INSTANTIATION(class foo); 182| |#ifdef __GNUC__ 183| |#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X 184| |#define TEMPLATE_INSTANTIATION(X) template X 185| |#else 186| |#define EXTERN_TEMPLATE_INSTANTIATION(X) 187| |#define TEMPLATE_INSTANTIATION(X) 188| |#endif 189| | 190| |/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, 191| |/// mark a method "not for inlining". 192| |#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) 193| |#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) 194| |#elif defined(_MSC_VER) 195| |#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) 196| |#else 197| |#define LLVM_ATTRIBUTE_NOINLINE 198| |#endif 199| | 200| |/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do 201| |/// so, mark a method "always inline" because it is performance sensitive. GCC 202| |/// 3.4 supported this but is buggy in various cases and produces unimplemented 203| |/// errors, just use it in GCC 4.0 and later. 204| |#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) 205| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) 206| |#elif defined(_MSC_VER) 207| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline 208| |#else 209| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE 210| |#endif 211| | 212| |#ifdef __GNUC__ 213| |#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) 214| |#elif defined(_MSC_VER) 215| |#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) 216| |#else 217| |#define LLVM_ATTRIBUTE_NORETURN 218| |#endif 219| | 220| |#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) 221| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 222| |#else 223| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL 224| |#endif 225| | 226| |/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress 227| |/// pedantic diagnostics. 228| |#ifdef __GNUC__ 229| |#define LLVM_EXTENSION __extension__ 230| |#else 231| |#define LLVM_EXTENSION 232| |#endif 233| | 234| |// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") 235| |#if __has_feature(attribute_deprecated_with_message) 236| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 237| | decl __attribute__((deprecated(message))) 238| |#elif defined(__GNUC__) 239| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 240| | decl __attribute__((deprecated)) 241| |#elif defined(_MSC_VER) 242| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 243| | __declspec(deprecated(message)) decl 244| |#else 245| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 246| | decl 247| |#endif 248| | 249| |/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands 250| |/// to an expression which states that it is undefined behavior for the 251| |/// compiler to reach this point. Otherwise is not defined. 252| |#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) 253| |# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() 254| |#elif defined(_MSC_VER) 255| |# define LLVM_BUILTIN_UNREACHABLE __assume(false) 256| |#endif 257| | 258| |/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression 259| |/// which causes the program to exit abnormally. 260| |#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) 261| |# define LLVM_BUILTIN_TRAP __builtin_trap() 262| |#elif defined(_MSC_VER) 263| |// The __debugbreak intrinsic is supported by MSVC, does not require forward 264| |// declarations involving platform-specific typedefs (unlike RaiseException), 265| |// results in a call to vectored exception handlers, and encodes to a short 266| |// instruction that still causes the trapping behavior we want. 267| |# define LLVM_BUILTIN_TRAP __debugbreak() 268| |#else 269| |# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 270| |#endif 271| | 272| |/// \macro LLVM_ASSUME_ALIGNED 273| |/// \brief Returns a pointer with an assumed alignment. 274| |#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) 275| |# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) 276| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 277| |// As of today, clang does not support __builtin_assume_aligned. 278| |# define LLVM_ASSUME_ALIGNED(p, a) \ 279| | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) 280| |#else 281| |# define LLVM_ASSUME_ALIGNED(p, a) (p) 282| |#endif 283| | 284| |/// \macro LLVM_FUNCTION_NAME 285| |/// \brief Expands to __func__ on compilers which support it. Otherwise, 286| |/// expands to a compiler-dependent replacement. 287| |#if defined(_MSC_VER) 288| |# define LLVM_FUNCTION_NAME __FUNCTION__ 289| |#else 290| |# define LLVM_FUNCTION_NAME __func__ 291| |#endif 292| | 293| |/// \macro LLVM_MEMORY_SANITIZER_BUILD 294| |/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. 295| |#if __has_feature(memory_sanitizer) 296| |# define LLVM_MEMORY_SANITIZER_BUILD 1 297| |# include 298| |#else 299| |# define LLVM_MEMORY_SANITIZER_BUILD 0 300| |# define __msan_allocated_memory(p, size) 301| |# define __msan_unpoison(p, size) 302| |#endif 303| | 304| |/// \macro LLVM_ADDRESS_SANITIZER_BUILD 305| |/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. 306| |#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 307| |# define LLVM_ADDRESS_SANITIZER_BUILD 1 308| |#else 309| |# define LLVM_ADDRESS_SANITIZER_BUILD 0 310| |#endif 311| | 312| |/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST 313| |/// \brief Is unaligned memory access fast on the host machine. 314| |/// 315| |/// Don't specialize on alignment for platforms where unaligned memory accesses 316| |/// generates the same code as aligned memory accesses for common types. 317| |#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ 318| | defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ 319| | defined(_X86_) || defined(__i386) || defined(__i386__) 320| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 321| |#else 322| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 323| |#endif 324| | 325| |/// \brief Mark debug helper function definitions like dump() that should not be 326| |/// stripped from debug builds. 327| |// FIXME: Move this to a private config.h as it's not usable in public headers. 328| |#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED 330| |#else 331| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE 332| |#endif 333| | 334| |/// \macro LLVM_THREAD_LOCAL 335| |/// \brief A thread-local storage specifier which can be used with globals, 336| |/// extern globals, and static globals. 337| |/// 338| |/// This is essentially an extremely restricted analog to C++11's thread_local 339| |/// support, and uses that when available. However, it falls back on 340| |/// platform-specific or vendor-provided extensions when necessary. These 341| |/// extensions don't support many of the C++11 thread_local's features. You 342| |/// should only use this for PODs that you can statically initialize to 343| |/// some constant value. In almost all circumstances this is most appropriate 344| |/// for use with a pointer, integer, or small aggregation of pointers and 345| |/// integers. 346| |#if LLVM_ENABLE_THREADS 347| |#if __has_feature(cxx_thread_local) 348| |#define LLVM_THREAD_LOCAL thread_local 349| |#elif defined(_MSC_VER) 350| |// MSVC supports this with a __declspec. 351| |#define LLVM_THREAD_LOCAL __declspec(thread) 352| |#else 353| |// Clang, GCC, and other compatible compilers used __thread prior to C++11 and 354| |// we only need the restricted functionality that provides. 355| |#define LLVM_THREAD_LOCAL __thread 356| |#endif 357| |#else // !LLVM_ENABLE_THREADS 358| |// If threading is disabled entirely, this compiles to nothing and you get 359| |// a normal global variable. 360| |#define LLVM_THREAD_LOCAL 361| |#endif 362| | 363| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorHandling.h: 1| |//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ERRORHANDLING_H 16| |#define LLVM_SUPPORT_ERRORHANDLING_H 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include 21| | 22| |namespace llvm { 23| | class Twine; 24| | 25| | /// An error handler callback. 26| | typedef void (*fatal_error_handler_t)(void *user_data, 27| | const std::string& reason, 28| | bool gen_crash_diag); 29| | 30| | /// install_fatal_error_handler - Installs a new error handler to be used 31| | /// whenever a serious (non-recoverable) error is encountered by LLVM. 32| | /// 33| | /// If no error handler is installed the default is to print the error message 34| | /// to stderr, and call exit(1). If an error handler is installed then it is 35| | /// the handler's responsibility to log the message, it will no longer be 36| | /// printed to stderr. If the error handler returns, then exit(1) will be 37| | /// called. 38| | /// 39| | /// It is dangerous to naively use an error handler which throws an exception. 40| | /// Even though some applications desire to gracefully recover from arbitrary 41| | /// faults, blindly throwing exceptions through unfamiliar code isn't a way to 42| | /// achieve this. 43| | /// 44| | /// \param user_data - An argument which will be passed to the install error 45| | /// handler. 46| | void install_fatal_error_handler(fatal_error_handler_t handler, 47| | void *user_data = nullptr); 48| | 49| | /// Restores default error handling behaviour. 50| | void remove_fatal_error_handler(); 51| | 52| | /// ScopedFatalErrorHandler - This is a simple helper class which just 53| | /// calls install_fatal_error_handler in its constructor and 54| | /// remove_fatal_error_handler in its destructor. 55| | struct ScopedFatalErrorHandler { 56| | explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, 57| 0| void *user_data = nullptr) { 58| 0| install_fatal_error_handler(handler, user_data); 59| 0| } 60| | 61| 0| ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } 62| | }; 63| | 64| | /// Reports a serious error, calling any installed error handler. These 65| | /// functions are intended to be used for error conditions which are outside 66| | /// the control of the compiler (I/O errors, invalid user input, etc.) 67| | /// 68| | /// If no error handler is installed the default is to print the message to 69| | /// standard error, followed by a newline. 70| | /// After the error handler is called this function will call exit(1), it 71| | /// does not return. 72| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, 73| | bool gen_crash_diag = true); 74| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, 75| | bool gen_crash_diag = true); 76| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, 77| | bool gen_crash_diag = true); 78| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, 79| | bool gen_crash_diag = true); 80| | 81| | /// This function calls abort(), and prints the optional message to stderr. 82| | /// Use the llvm_unreachable macro (that adds location info), instead of 83| | /// calling this function directly. 84| | LLVM_ATTRIBUTE_NORETURN void 85| | llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, 86| | unsigned line=0); 87| |} 88| | 89| |/// Marks that the current location is not supposed to be reachable. 90| |/// In !NDEBUG builds, prints the message and location info to stderr. 91| |/// In NDEBUG builds, becomes an optimizer hint that the current location 92| |/// is not supposed to be reachable. On compilers that don't support 93| |/// such hints, prints a reduced message instead. 94| |/// 95| |/// Use this instead of assert(0). It conveys intent more clearly and 96| |/// allows compilers to omit some unnecessary code. 97| |#ifndef NDEBUG 98| |#define llvm_unreachable(msg) \ 99| | ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) 100| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 101| |#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE 102| |#else 103| |#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() 104| |#endif 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MathExtras.h: 1| |//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful for math stuff. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MATHEXTRAS_H 15| |#define LLVM_SUPPORT_MATHEXTRAS_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/SwapByteOrder.h" 19| |#include 20| |#include 21| |#include 22| | 23| |#ifdef _MSC_VER 24| |#include 25| |#endif 26| | 27| |namespace llvm { 28| |/// \brief The behavior an operation has on an input of 0. 29| |enum ZeroBehavior { 30| | /// \brief The returned value is undefined. 31| | ZB_Undefined, 32| | /// \brief The returned value is numeric_limits::max() 33| | ZB_Max, 34| | /// \brief The returned value is numeric_limits::digits 35| | ZB_Width 36| |}; 37| | 38| |namespace detail { 39| |template struct TrailingZerosCounter { 40| | static std::size_t count(T Val, ZeroBehavior) { 41| | if (!Val) 42| | return std::numeric_limits::digits; 43| | if (Val & 0x1) 44| | return 0; 45| | 46| | // Bisection method. 47| | std::size_t ZeroBits = 0; 48| | T Shift = std::numeric_limits::digits >> 1; 49| | T Mask = std::numeric_limits::max() >> Shift; 50| | while (Shift) { 51| | if ((Val & Mask) == 0) { 52| | Val >>= Shift; 53| | ZeroBits |= Shift; 54| | } 55| | Shift >>= 1; 56| | Mask >>= Shift; 57| | } 58| | return ZeroBits; 59| | } 60| |}; 61| | 62| |#if __GNUC__ >= 4 || _MSC_VER 63| |template struct TrailingZerosCounter { 64| | static std::size_t count(T Val, ZeroBehavior ZB) { 65| | if (ZB != ZB_Undefined && Val == 0) 66| | return 32; 67| | 68| |#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) 69| | return __builtin_ctz(Val); 70| |#elif _MSC_VER 71| | unsigned long Index; 72| | _BitScanForward(&Index, Val); 73| | return Index; 74| |#endif 75| | } 76| |}; 77| | 78| |#if !defined(_MSC_VER) || defined(_M_X64) 79| |template struct TrailingZerosCounter { 80| | static std::size_t count(T Val, ZeroBehavior ZB) { 81| | if (ZB != ZB_Undefined && Val == 0) 82| | return 64; 83| | 84| |#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) 85| | return __builtin_ctzll(Val); 86| |#elif _MSC_VER 87| | unsigned long Index; 88| | _BitScanForward64(&Index, Val); 89| | return Index; 90| |#endif 91| | } 92| |}; 93| |#endif 94| |#endif 95| |} // namespace detail 96| | 97| |/// \brief Count number of 0's from the least significant bit to the most 98| |/// stopping at the first 1. 99| |/// 100| |/// Only unsigned integral types are allowed. 101| |/// 102| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 103| |/// valid arguments. 104| |template 105| |std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 106| | static_assert(std::numeric_limits::is_integer && 107| | !std::numeric_limits::is_signed, 108| | "Only unsigned integral types are allowed."); 109| | return detail::TrailingZerosCounter::count(Val, ZB); 110| |} 111| | 112| |namespace detail { 113| |template struct LeadingZerosCounter { 114| | static std::size_t count(T Val, ZeroBehavior) { 115| | if (!Val) 116| | return std::numeric_limits::digits; 117| | 118| | // Bisection method. 119| | std::size_t ZeroBits = 0; 120| | for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) { 121| | T Tmp = Val >> Shift; 122| | if (Tmp) 123| | Val = Tmp; 124| | else 125| | ZeroBits |= Shift; 126| | } 127| | return ZeroBits; 128| | } 129| |}; 130| | 131| |#if __GNUC__ >= 4 || _MSC_VER 132| |template struct LeadingZerosCounter { 133| | static std::size_t count(T Val, ZeroBehavior ZB) { 134| | if (ZB != ZB_Undefined && Val == 0) 135| | return 32; 136| | 137| |#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) 138| | return __builtin_clz(Val); 139| |#elif _MSC_VER 140| | unsigned long Index; 141| | _BitScanReverse(&Index, Val); 142| | return Index ^ 31; 143| |#endif 144| | } 145| |}; 146| | 147| |#if !defined(_MSC_VER) || defined(_M_X64) 148| |template struct LeadingZerosCounter { 149| | static std::size_t count(T Val, ZeroBehavior ZB) { 150| | if (ZB != ZB_Undefined && Val == 0) 151| | return 64; 152| | 153| |#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) 154| | return __builtin_clzll(Val); 155| |#elif _MSC_VER 156| | unsigned long Index; 157| | _BitScanReverse64(&Index, Val); 158| | return Index ^ 63; 159| |#endif 160| | } 161| |}; 162| |#endif 163| |#endif 164| |} // namespace detail 165| | 166| |/// \brief Count number of 0's from the most significant bit to the least 167| |/// stopping at the first 1. 168| |/// 169| |/// Only unsigned integral types are allowed. 170| |/// 171| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 172| |/// valid arguments. 173| |template 174| |std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 175| | static_assert(std::numeric_limits::is_integer && 176| | !std::numeric_limits::is_signed, 177| | "Only unsigned integral types are allowed."); 178| | return detail::LeadingZerosCounter::count(Val, ZB); 179| |} 180| | 181| |/// \brief Get the index of the first set bit starting from the least 182| |/// significant bit. 183| |/// 184| |/// Only unsigned integral types are allowed. 185| |/// 186| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 187| |/// valid arguments. 188| |template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { 189| | if (ZB == ZB_Max && Val == 0) 190| | return std::numeric_limits::max(); 191| | 192| | return countTrailingZeros(Val, ZB_Undefined); 193| |} 194| | 195| |/// \brief Get the index of the last set bit starting from the least 196| |/// significant bit. 197| |/// 198| |/// Only unsigned integral types are allowed. 199| |/// 200| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 201| |/// valid arguments. 202| |template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { 203| | if (ZB == ZB_Max && Val == 0) 204| | return std::numeric_limits::max(); 205| | 206| | // Use ^ instead of - because both gcc and llvm can remove the associated ^ 207| | // in the __builtin_clz intrinsic on x86. 208| | return countLeadingZeros(Val, ZB_Undefined) ^ 209| | (std::numeric_limits::digits - 1); 210| |} 211| | 212| |/// \brief Macro compressed bit reversal table for 256 bits. 213| |/// 214| |/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable 215| |static const unsigned char BitReverseTable256[256] = { 216| |#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 217| |#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) 218| |#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) 219| | R6(0), R6(2), R6(1), R6(3) 220| |#undef R2 221| |#undef R4 222| |#undef R6 223| |}; 224| | 225| |/// \brief Reverse the bits in \p Val. 226| |template 227| |T reverseBits(T Val) { 228| | unsigned char in[sizeof(Val)]; 229| | unsigned char out[sizeof(Val)]; 230| | std::memcpy(in, &Val, sizeof(Val)); 231| | for (unsigned i = 0; i < sizeof(Val); ++i) 232| | out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; 233| | std::memcpy(&Val, out, sizeof(Val)); 234| | return Val; 235| |} 236| | 237| |// NOTE: The following support functions use the _32/_64 extensions instead of 238| |// type overloading so that signed and unsigned integers can be used without 239| |// ambiguity. 240| | 241| |/// Hi_32 - This function returns the high 32 bits of a 64 bit value. 242| 0|inline uint32_t Hi_32(uint64_t Value) { 243| 0| return static_cast(Value >> 32); 244| 0|} 245| | 246| |/// Lo_32 - This function returns the low 32 bits of a 64 bit value. 247| 0|inline uint32_t Lo_32(uint64_t Value) { 248| 0| return static_cast(Value); 249| 0|} 250| | 251| |/// Make_64 - This functions makes a 64-bit integer from a high / low pair of 252| |/// 32-bit integers. 253| 0|inline uint64_t Make_64(uint32_t High, uint32_t Low) { 254| 0| return ((uint64_t)High << 32) | (uint64_t)Low; 255| 0|} 256| | 257| |/// isInt - Checks if an integer fits into the given bit width. 258| |template 259| |inline bool isInt(int64_t x) { 260| | return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 261| |} 262| |// Template specializations to get better code for common cases. 263| |template<> 264| 0|inline bool isInt<8>(int64_t x) { 265| 0| return static_cast(x) == x; 266| 0|} 267| |template<> 268| 0|inline bool isInt<16>(int64_t x) { 269| 0| return static_cast(x) == x; 270| 0|} 271| |template<> 272| 0|inline bool isInt<32>(int64_t x) { 273| 0| return static_cast(x) == x; 274| 0|} 275| | 276| |/// isShiftedInt - Checks if a signed integer is an N bit number shifted 277| |/// left by S. 278| |template 279| |inline bool isShiftedInt(int64_t x) { 280| | return isInt(x) && (x % (1< 285| |inline bool isUInt(uint64_t x) { 286| | return N >= 64 || x < (UINT64_C(1)<<(N)); 287| |} 288| |// Template specializations to get better code for common cases. 289| |template<> 290| 0|inline bool isUInt<8>(uint64_t x) { 291| 0| return static_cast(x) == x; 292| 0|} 293| |template<> 294| 0|inline bool isUInt<16>(uint64_t x) { 295| 0| return static_cast(x) == x; 296| 0|} 297| |template<> 298| 0|inline bool isUInt<32>(uint64_t x) { 299| 0| return static_cast(x) == x; 300| 0|} 301| | 302| |/// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted 303| |/// left by S. 304| |template 305| |inline bool isShiftedUInt(uint64_t x) { 306| | return isUInt(x) && (x % (1<> (64 - N))); 313| 0|} 314| | 315| |/// isIntN - Checks if an signed integer fits into the given (dynamic) 316| |/// bit width. 317| 0|inline bool isIntN(unsigned N, int64_t x) { 318| 0| return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 319| 0|} 320| | 321| |/// isMask_32 - This function returns true if the argument is a sequence of ones 322| |/// starting at the least significant bit with the remainder zero (32 bit 323| |/// version). Ex. isMask_32(0x0000FFFFU) == true. 324| 0|inline bool isMask_32(uint32_t Value) { 325| 0| return Value && ((Value + 1) & Value) == 0; 326| 0|} 327| | 328| |/// isMask_64 - This function returns true if the argument is a sequence of ones 329| |/// starting at the least significant bit with the remainder zero (64 bit 330| |/// version). 331| 0|inline bool isMask_64(uint64_t Value) { 332| 0| return Value && ((Value + 1) & Value) == 0; 333| 0|} 334| | 335| |/// isShiftedMask_32 - This function returns true if the argument contains a 336| |/// sequence of ones with the remainder zero (32 bit version.) 337| |/// Ex. isShiftedMask_32(0x0000FF00U) == true. 338| 0|inline bool isShiftedMask_32(uint32_t Value) { 339| 0| return isMask_32((Value - 1) | Value); 340| 0|} 341| | 342| |/// isShiftedMask_64 - This function returns true if the argument contains a 343| |/// sequence of ones with the remainder zero (64 bit version.) 344| 0|inline bool isShiftedMask_64(uint64_t Value) { 345| 0| return isMask_64((Value - 1) | Value); 346| 0|} 347| | 348| |/// isPowerOf2_32 - This function returns true if the argument is a power of 349| |/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) 350| 0|inline bool isPowerOf2_32(uint32_t Value) { 351| 0| return Value && !(Value & (Value - 1)); 352| 0|} 353| | 354| |/// isPowerOf2_64 - This function returns true if the argument is a power of two 355| |/// > 0 (64 bit edition.) 356| |inline bool isPowerOf2_64(uint64_t Value) { 357| | return Value && !(Value & (Value - int64_t(1L))); 358| |} 359| | 360| |/// ByteSwap_16 - This function returns a byte-swapped representation of the 361| |/// 16-bit argument, Value. 362| 0|inline uint16_t ByteSwap_16(uint16_t Value) { 363| 0| return sys::SwapByteOrder_16(Value); 364| 0|} 365| | 366| |/// ByteSwap_32 - This function returns a byte-swapped representation of the 367| |/// 32-bit argument, Value. 368| 0|inline uint32_t ByteSwap_32(uint32_t Value) { 369| 0| return sys::SwapByteOrder_32(Value); 370| 0|} 371| | 372| |/// ByteSwap_64 - This function returns a byte-swapped representation of the 373| |/// 64-bit argument, Value. 374| 0|inline uint64_t ByteSwap_64(uint64_t Value) { 375| 0| return sys::SwapByteOrder_64(Value); 376| 0|} 377| | 378| |/// \brief Count the number of ones from the most significant bit to the first 379| |/// zero bit. 380| |/// 381| |/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. 382| |/// Only unsigned integral types are allowed. 383| |/// 384| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 385| |/// ZB_Undefined are valid arguments. 386| |template 387| |std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 388| | static_assert(std::numeric_limits::is_integer && 389| | !std::numeric_limits::is_signed, 390| | "Only unsigned integral types are allowed."); 391| | return countLeadingZeros(~Value, ZB); 392| |} 393| | 394| |/// \brief Count the number of ones from the least significant bit to the first 395| |/// zero bit. 396| |/// 397| |/// Ex. countTrailingOnes(0x00FF00FF) == 8. 398| |/// Only unsigned integral types are allowed. 399| |/// 400| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 401| |/// ZB_Undefined are valid arguments. 402| |template 403| |std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 404| | static_assert(std::numeric_limits::is_integer && 405| | !std::numeric_limits::is_signed, 406| | "Only unsigned integral types are allowed."); 407| | return countTrailingZeros(~Value, ZB); 408| |} 409| | 410| |namespace detail { 411| |template struct PopulationCounter { 412| | static unsigned count(T Value) { 413| | // Generic version, forward to 32 bits. 414| | static_assert(SizeOfT <= 4, "Not implemented!"); 415| |#if __GNUC__ >= 4 416| | return __builtin_popcount(Value); 417| |#else 418| | uint32_t v = Value; 419| | v = v - ((v >> 1) & 0x55555555); 420| | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 421| | return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 422| |#endif 423| | } 424| |}; 425| | 426| |template struct PopulationCounter { 427| | static unsigned count(T Value) { 428| |#if __GNUC__ >= 4 429| | return __builtin_popcountll(Value); 430| |#else 431| | uint64_t v = Value; 432| | v = v - ((v >> 1) & 0x5555555555555555ULL); 433| | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 434| | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 435| | return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); 436| |#endif 437| | } 438| |}; 439| |} // namespace detail 440| | 441| |/// \brief Count the number of set bits in a value. 442| |/// Ex. countPopulation(0xF000F000) = 8 443| |/// Returns 0 if the word is zero. 444| |template 445| |inline unsigned countPopulation(T Value) { 446| | static_assert(std::numeric_limits::is_integer && 447| | !std::numeric_limits::is_signed, 448| | "Only unsigned integral types are allowed."); 449| | return detail::PopulationCounter::count(Value); 450| |} 451| | 452| |/// Log2_32 - This function returns the floor log base 2 of the specified value, 453| |/// -1 if the value is zero. (32 bit edition.) 454| |/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 455| 0|inline unsigned Log2_32(uint32_t Value) { 456| 0| return 31 - countLeadingZeros(Value); 457| 0|} 458| | 459| |/// Log2_64 - This function returns the floor log base 2 of the specified value, 460| |/// -1 if the value is zero. (64 bit edition.) 461| 0|inline unsigned Log2_64(uint64_t Value) { 462| 0| return 63 - countLeadingZeros(Value); 463| 0|} 464| | 465| |/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified 466| |/// value, 32 if the value is zero. (32 bit edition). 467| |/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 468| |inline unsigned Log2_32_Ceil(uint32_t Value) { 469| | return 32 - countLeadingZeros(Value - 1); 470| |} 471| | 472| |/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified 473| |/// value, 64 if the value is zero. (64 bit edition.) 474| 0|inline unsigned Log2_64_Ceil(uint64_t Value) { 475| 0| return 64 - countLeadingZeros(Value - 1); 476| 0|} 477| | 478| |/// GreatestCommonDivisor64 - Return the greatest common divisor of the two 479| |/// values using Euclid's algorithm. 480| 0|inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { 481| 0| while (B) { 482| 0| uint64_t T = B; 483| 0| B = A % B; 484| 0| A = T; 485| 0| } 486| 0| return A; 487| 0|} 488| | 489| |/// BitsToDouble - This function takes a 64-bit integer and returns the bit 490| |/// equivalent double. 491| 0|inline double BitsToDouble(uint64_t Bits) { 492| 0| union { 493| 0| uint64_t L; 494| 0| double D; 495| 0| } T; 496| 0| T.L = Bits; 497| 0| return T.D; 498| 0|} 499| | 500| |/// BitsToFloat - This function takes a 32-bit integer and returns the bit 501| |/// equivalent float. 502| 0|inline float BitsToFloat(uint32_t Bits) { 503| 0| union { 504| 0| uint32_t I; 505| 0| float F; 506| 0| } T; 507| 0| T.I = Bits; 508| 0| return T.F; 509| 0|} 510| | 511| |/// DoubleToBits - This function takes a double and returns the bit 512| |/// equivalent 64-bit integer. Note that copying doubles around 513| |/// changes the bits of NaNs on some hosts, notably x86, so this 514| |/// routine cannot be used if these bits are needed. 515| 0|inline uint64_t DoubleToBits(double Double) { 516| 0| union { 517| 0| uint64_t L; 518| 0| double D; 519| 0| } T; 520| 0| T.D = Double; 521| 0| return T.L; 522| 0|} 523| | 524| |/// FloatToBits - This function takes a float and returns the bit 525| |/// equivalent 32-bit integer. Note that copying floats around 526| |/// changes the bits of NaNs on some hosts, notably x86, so this 527| |/// routine cannot be used if these bits are needed. 528| 0|inline uint32_t FloatToBits(float Float) { 529| 0| union { 530| 0| uint32_t I; 531| 0| float F; 532| 0| } T; 533| 0| T.F = Float; 534| 0| return T.I; 535| 0|} 536| | 537| |/// MinAlign - A and B are either alignments or offsets. Return the minimum 538| |/// alignment that may be assumed after adding the two together. 539| 0|inline uint64_t MinAlign(uint64_t A, uint64_t B) { 540| 0| // The largest power of 2 that divides both A and B. 541| 0| // 542| 0| // Replace "-Value" by "1+~Value" in the following commented code to avoid 543| 0| // MSVC warning C4146 544| 0| // return (A | B) & -(A | B); 545| 0| return (A | B) & (1 + ~(A | B)); 546| 0|} 547| | 548| |/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. 549| |/// 550| |/// Alignment should be a power of two. This method rounds up, so 551| |/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. 552| |inline uintptr_t alignAddr(void *Addr, size_t Alignment) { 553| | assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && 554| | "Alignment is not a power of two!"); 555| | 556| | assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); 557| | 558| | return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); 559| |} 560| | 561| |/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment 562| |/// bytes, rounding up. 563| |inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { 564| | return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; 565| |} 566| | 567| |/// NextPowerOf2 - Returns the next power of two (in 64-bits) 568| |/// that is strictly greater than A. Returns zero on overflow. 569| 0|inline uint64_t NextPowerOf2(uint64_t A) { 570| 0| A |= (A >> 1); 571| 0| A |= (A >> 2); 572| 0| A |= (A >> 4); 573| 0| A |= (A >> 8); 574| 0| A |= (A >> 16); 575| 0| A |= (A >> 32); 576| 0| return A + 1; 577| 0|} 578| | 579| |/// Returns the power of two which is less than or equal to the given value. 580| |/// Essentially, it is a floor operation across the domain of powers of two. 581| 0|inline uint64_t PowerOf2Floor(uint64_t A) { 582| 0| if (!A) return 0; 583| 0| return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); 584| 0|} 585| | 586| |/// Returns the next integer (mod 2**64) that is greater than or equal to 587| |/// \p Value and is a multiple of \p Align. \p Align must be non-zero. 588| |/// 589| |/// Examples: 590| |/// \code 591| |/// RoundUpToAlignment(5, 8) = 8 592| |/// RoundUpToAlignment(17, 8) = 24 593| |/// RoundUpToAlignment(~0LL, 8) = 0 594| |/// RoundUpToAlignment(321, 255) = 510 595| |/// \endcode 596| |inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { 597| | return (Value + Align - 1) / Align * Align; 598| |} 599| | 600| |/// Returns the offset to the next integer (mod 2**64) that is greater than 601| |/// or equal to \p Value and is a multiple of \p Align. \p Align must be 602| |/// non-zero. 603| 0|inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { 604| 0| return RoundUpToAlignment(Value, Align) - Value; 605| 0|} 606| | 607| |/// SignExtend32 - Sign extend B-bit number x to 32-bit int. 608| |/// Usage int32_t r = SignExtend32<5>(x); 609| |template inline int32_t SignExtend32(uint32_t x) { 610| | return int32_t(x << (32 - B)) >> (32 - B); 611| |} 612| | 613| |/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. 614| |/// Requires 0 < B <= 32. 615| 0|inline int32_t SignExtend32(uint32_t X, unsigned B) { 616| 0| return int32_t(X << (32 - B)) >> (32 - B); 617| 0|} 618| | 619| |/// SignExtend64 - Sign extend B-bit number x to 64-bit int. 620| |/// Usage int64_t r = SignExtend64<5>(x); 621| |template inline int64_t SignExtend64(uint64_t x) { 622| | return int64_t(x << (64 - B)) >> (64 - B); 623| |} 624| | 625| |/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. 626| |/// Requires 0 < B <= 64. 627| 0|inline int64_t SignExtend64(uint64_t X, unsigned B) { 628| 0| return int64_t(X << (64 - B)) >> (64 - B); 629| 0|} 630| | 631| |extern const float huge_valf; 632| |} // End llvm namespace 633| | 634| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Memory.h: 1| |//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Memory class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORY_H 15| |#define LLVM_SUPPORT_MEMORY_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| | /// This class encapsulates the notion of a memory block which has an address 25| | /// and a size. It is used by the Memory class (a friend) as the result of 26| | /// various memory allocation operations. 27| | /// @see Memory 28| | /// @brief Memory block abstraction. 29| | class MemoryBlock { 30| | public: 31| 0| MemoryBlock() : Address(nullptr), Size(0) { } 32| 0| MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } 33| | void *base() const { return Address; } 34| | size_t size() const { return Size; } 35| | private: 36| | void *Address; ///< Address of first byte of memory area 37| | size_t Size; ///< Size, in bytes of the memory area 38| | friend class Memory; 39| | }; 40| | 41| | /// This class provides various memory handling functions that manipulate 42| | /// MemoryBlock instances. 43| | /// @since 1.4 44| | /// @brief An abstraction for memory operations. 45| | class Memory { 46| | public: 47| | enum ProtectionFlags { 48| | MF_READ = 0x1000000, 49| | MF_WRITE = 0x2000000, 50| | MF_EXEC = 0x4000000 51| | }; 52| | 53| | /// This method allocates a block of memory that is suitable for loading 54| | /// dynamically generated code (e.g. JIT). An attempt to allocate 55| | /// \p NumBytes bytes of virtual memory is made. 56| | /// \p NearBlock may point to an existing allocation in which case 57| | /// an attempt is made to allocate more memory near the existing block. 58| | /// The actual allocated address is not guaranteed to be near the requested 59| | /// address. 60| | /// \p Flags is used to set the initial protection flags for the block 61| | /// of the memory. 62| | /// \p EC [out] returns an object describing any error that occurs. 63| | /// 64| | /// This method may allocate more than the number of bytes requested. The 65| | /// actual number of bytes allocated is indicated in the returned 66| | /// MemoryBlock. 67| | /// 68| | /// The start of the allocated block must be aligned with the 69| | /// system allocation granularity (64K on Windows, page size on Linux). 70| | /// If the address following \p NearBlock is not so aligned, it will be 71| | /// rounded up to the next allocation granularity boundary. 72| | /// 73| | /// \r a non-null MemoryBlock if the function was successful, 74| | /// otherwise a null MemoryBlock is with \p EC describing the error. 75| | /// 76| | /// @brief Allocate mapped memory. 77| | static MemoryBlock allocateMappedMemory(size_t NumBytes, 78| | const MemoryBlock *const NearBlock, 79| | unsigned Flags, 80| | std::error_code &EC); 81| | 82| | /// This method releases a block of memory that was allocated with the 83| | /// allocateMappedMemory method. It should not be used to release any 84| | /// memory block allocated any other way. 85| | /// \p Block describes the memory to be released. 86| | /// 87| | /// \r error_success if the function was successful, or an error_code 88| | /// describing the failure if an error occurred. 89| | /// 90| | /// @brief Release mapped memory. 91| | static std::error_code releaseMappedMemory(MemoryBlock &Block); 92| | 93| | /// This method sets the protection flags for a block of memory to the 94| | /// state specified by /p Flags. The behavior is not specified if the 95| | /// memory was not allocated using the allocateMappedMemory method. 96| | /// \p Block describes the memory block to be protected. 97| | /// \p Flags specifies the new protection state to be assigned to the block. 98| | /// \p ErrMsg [out] returns a string describing any error that occurred. 99| | /// 100| | /// If \p Flags is MF_WRITE, the actual behavior varies 101| | /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the 102| | /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 103| | /// 104| | /// \r error_success if the function was successful, or an error_code 105| | /// describing the failure if an error occurred. 106| | /// 107| | /// @brief Set memory protection state. 108| | static std::error_code protectMappedMemory(const MemoryBlock &Block, 109| | unsigned Flags); 110| | 111| | /// This method allocates a block of Read/Write/Execute memory that is 112| | /// suitable for executing dynamically generated code (e.g. JIT). An 113| | /// attempt to allocate \p NumBytes bytes of virtual memory is made. 114| | /// \p NearBlock may point to an existing allocation in which case 115| | /// an attempt is made to allocate more memory near the existing block. 116| | /// 117| | /// On success, this returns a non-null memory block, otherwise it returns 118| | /// a null memory block and fills in *ErrMsg. 119| | /// 120| | /// @brief Allocate Read/Write/Execute memory. 121| | static MemoryBlock AllocateRWX(size_t NumBytes, 122| | const MemoryBlock *NearBlock, 123| | std::string *ErrMsg = nullptr); 124| | 125| | /// This method releases a block of Read/Write/Execute memory that was 126| | /// allocated with the AllocateRWX method. It should not be used to 127| | /// release any memory block allocated any other way. 128| | /// 129| | /// On success, this returns false, otherwise it returns true and fills 130| | /// in *ErrMsg. 131| | /// @brief Release Read/Write/Execute memory. 132| | static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); 133| | 134| | 135| | /// InvalidateInstructionCache - Before the JIT can run a block of code 136| | /// that has been emitted it must invalidate the instruction cache on some 137| | /// platforms. 138| | static void InvalidateInstructionCache(const void *Addr, size_t Len); 139| | 140| | /// setExecutable - Before the JIT can run a block of code, it has to be 141| | /// given read and executable privilege. Return true if it is already r-x 142| | /// or the system is able to change its previlege. 143| | static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); 144| | 145| | /// setWritable - When adding to a block of code, the JIT may need 146| | /// to mark a block of code as RW since the protections are on page 147| | /// boundaries, and the JIT internal allocations are not page aligned. 148| | static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); 149| | 150| | /// setRangeExecutable - Mark the page containing a range of addresses 151| | /// as executable. 152| | static bool setRangeExecutable(const void *Addr, size_t Size); 153| | 154| | /// setRangeWritable - Mark the page containing a range of addresses 155| | /// as writable. 156| | static bool setRangeWritable(const void *Addr, size_t Size); 157| | }; 158| |} 159| |} 160| | 161| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/PointerLikeTypeTraits.h: 1| |//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the PointerLikeTypeTraits class. This allows data 11| |// structures to reason about pointers and other things that are pointer sized. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 16| |#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 17| | 18| |#include "llvm/Support/DataTypes.h" 19| | 20| |namespace llvm { 21| | 22| |/// PointerLikeTypeTraits - This is a traits object that is used to handle 23| |/// pointer types and things that are just wrappers for pointers as a uniform 24| |/// entity. 25| |template 26| |class PointerLikeTypeTraits { 27| | // getAsVoidPointer 28| | // getFromVoidPointer 29| | // getNumLowBitsAvailable 30| |}; 31| | 32| |// Provide PointerLikeTypeTraits for non-cvr pointers. 33| |template 34| |class PointerLikeTypeTraits { 35| |public: 36| | static inline void *getAsVoidPointer(T* P) { return P; } 37| | static inline T *getFromVoidPointer(void *P) { 38| | return static_cast(P); 39| | } 40| | 41| | /// Note, we assume here that malloc returns objects at least 4-byte aligned. 42| | /// However, this may be wrong, or pointers may be from something other than 43| | /// malloc. In this case, you should specialize this template to reduce this. 44| | /// 45| | /// All clients should use assertions to do a run-time check to ensure that 46| | /// this is actually true. 47| | enum { NumLowBitsAvailable = 2 }; 48| |}; 49| | 50| |// Provide PointerLikeTypeTraits for const pointers. 51| |template 52| |class PointerLikeTypeTraits { 53| | typedef PointerLikeTypeTraits NonConst; 54| | 55| |public: 56| | static inline const void *getAsVoidPointer(const T* P) { 57| | return NonConst::getAsVoidPointer(const_cast(P)); 58| | } 59| | static inline const T *getFromVoidPointer(const void *P) { 60| | return NonConst::getFromVoidPointer(const_cast(P)); 61| | } 62| | enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; 63| |}; 64| | 65| |// Provide PointerLikeTypeTraits for uintptr_t. 66| |template<> 67| |class PointerLikeTypeTraits { 68| |public: 69| 0| static inline void *getAsVoidPointer(uintptr_t P) { 70| 0| return reinterpret_cast(P); 71| 0| } 72| 0| static inline uintptr_t getFromVoidPointer(void *P) { 73| 0| return reinterpret_cast(P); 74| 0| } 75| | // No bits are available! 76| | enum { NumLowBitsAvailable = 0 }; 77| |}; 78| | 79| |} // end namespace llvm 80| | 81| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SwapByteOrder.h: 1| |//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic and optimized functions to swap the byte order of 11| |// an integral type. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H 16| |#define LLVM_SUPPORT_SWAPBYTEORDER_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| |namespace sys { 25| | 26| |/// SwapByteOrder_16 - This function returns a byte-swapped representation of 27| |/// the 16-bit argument. 28| |inline uint16_t SwapByteOrder_16(uint16_t value) { 29| |#if defined(_MSC_VER) && !defined(_DEBUG) 30| | // The DLL version of the runtime lacks these functions (bug!?), but in a 31| | // release build they're replaced with BSWAP instructions anyway. 32| | return _byteswap_ushort(value); 33| |#else 34| | uint16_t Hi = value << 8; 35| | uint16_t Lo = value >> 8; 36| | return Hi | Lo; 37| |#endif 38| |} 39| | 40| |/// SwapByteOrder_32 - This function returns a byte-swapped representation of 41| |/// the 32-bit argument. 42| 0|inline uint32_t SwapByteOrder_32(uint32_t value) { 43| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 44| 0| return __builtin_bswap32(value); 45| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 46| 0| return _byteswap_ulong(value); 47| 0|#else 48| 0| uint32_t Byte0 = value & 0x000000FF; 49| 0| uint32_t Byte1 = value & 0x0000FF00; 50| 0| uint32_t Byte2 = value & 0x00FF0000; 51| 0| uint32_t Byte3 = value & 0xFF000000; 52| 0| return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 53| 0|#endif 54| 0|} 55| | 56| |/// SwapByteOrder_64 - This function returns a byte-swapped representation of 57| |/// the 64-bit argument. 58| 0|inline uint64_t SwapByteOrder_64(uint64_t value) { 59| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 60| 0| return __builtin_bswap64(value); 61| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 62| 0| return _byteswap_uint64(value); 63| 0|#else 64| 0| uint64_t Hi = SwapByteOrder_32(uint32_t(value)); 65| 0| uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); 66| 0| return (Hi << 32) | Lo; 67| 0|#endif 68| 0|} 69| | 70| 0|inline unsigned char getSwappedBytes(unsigned char C) { return C; } 71| 0|inline signed char getSwappedBytes(signed char C) { return C; } 72| 0|inline char getSwappedBytes(char C) { return C; } 73| | 74| 0|inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } 75| 0|inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } 76| | 77| 0|inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } 78| 0|inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } 79| | 80| |#if __LONG_MAX__ == __INT_MAX__ 81| |inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } 82| |inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } 83| |#elif __LONG_MAX__ == __LONG_LONG_MAX__ 84| 0|inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } 85| 0|inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } 86| |#else 87| |#error "Unknown long size!" 88| |#endif 89| | 90| 0|inline unsigned long long getSwappedBytes(unsigned long long C) { 91| 0| return SwapByteOrder_64(C); 92| 0|} 93| 0|inline signed long long getSwappedBytes(signed long long C) { 94| 0| return SwapByteOrder_64(C); 95| 0|} 96| | 97| 0|inline float getSwappedBytes(float C) { 98| 0| union { 99| 0| uint32_t i; 100| 0| float f; 101| 0| } in, out; 102| 0| in.f = C; 103| 0| out.i = SwapByteOrder_32(in.i); 104| 0| return out.f; 105| 0|} 106| | 107| 0|inline float getSwappedBytes(double C) { 108| 0| union { 109| 0| uint64_t i; 110| 0| double d; 111| 0| } in, out; 112| 0| in.d = C; 113| 0| out.i = SwapByteOrder_64(in.i); 114| 0| return out.d; 115| 0|} 116| | 117| |template 118| |inline void swapByteOrder(T &Value) { 119| | Value = getSwappedBytes(Value); 120| |} 121| | 122| |} // end namespace sys 123| |} // end namespace llvm 124| | 125| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/raw_ostream.h: 1| |//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the raw_ostream class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_RAW_OSTREAM_H 15| |#define LLVM_SUPPORT_RAW_OSTREAM_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include 22| | 23| |namespace llvm { 24| | class format_object_base; 25| | class FormattedString; 26| | class FormattedNumber; 27| | template 28| | class SmallVectorImpl; 29| | 30| | namespace sys { 31| | namespace fs { 32| | enum OpenFlags : unsigned; 33| | } 34| | } 35| | 36| |/// raw_ostream - This class implements an extremely fast bulk output stream 37| |/// that can *only* output to a stream. It does not support seeking, reopening, 38| |/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs 39| |/// a chunk at a time. 40| |class raw_ostream { 41| |private: 42| | void operator=(const raw_ostream &) = delete; 43| | raw_ostream(const raw_ostream &) = delete; 44| | 45| | /// The buffer is handled in such a way that the buffer is 46| | /// uninitialized, unbuffered, or out of space when OutBufCur >= 47| | /// OutBufEnd. Thus a single comparison suffices to determine if we 48| | /// need to take the slow path to write a single character. 49| | /// 50| | /// The buffer is in one of three states: 51| | /// 1. Unbuffered (BufferMode == Unbuffered) 52| | /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). 53| | /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && 54| | /// OutBufEnd - OutBufStart >= 1). 55| | /// 56| | /// If buffered, then the raw_ostream owns the buffer if (BufferMode == 57| | /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is 58| | /// managed by the subclass. 59| | /// 60| | /// If a subclass installs an external buffer using SetBuffer then it can wait 61| | /// for a \see write_impl() call to handle the data which has been put into 62| | /// this buffer. 63| | char *OutBufStart, *OutBufEnd, *OutBufCur; 64| | 65| | enum BufferKind { 66| | Unbuffered = 0, 67| | InternalBuffer, 68| | ExternalBuffer 69| | } BufferMode; 70| | 71| |public: 72| | // color order matches ANSI escape sequence, don't change 73| | enum Colors { 74| | BLACK=0, 75| | RED, 76| | GREEN, 77| | YELLOW, 78| | BLUE, 79| | MAGENTA, 80| | CYAN, 81| | WHITE, 82| | SAVEDCOLOR 83| | }; 84| | 85| | explicit raw_ostream(bool unbuffered=false) 86| 0| : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { 87| 0| // Start out ready to flush. 88| 0| OutBufStart = OutBufEnd = OutBufCur = nullptr; 89| 0| } 90| | 91| | virtual ~raw_ostream(); 92| | 93| | /// tell - Return the current offset with the file. 94| | uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } 95| | 96| | //===--------------------------------------------------------------------===// 97| | // Configuration Interface 98| | //===--------------------------------------------------------------------===// 99| | 100| | /// SetBuffered - Set the stream to be buffered, with an automatically 101| | /// determined buffer size. 102| | void SetBuffered(); 103| | 104| | /// SetBufferSize - Set the stream to be buffered, using the 105| | /// specified buffer size. 106| 0| void SetBufferSize(size_t Size) { 107| 0| flush(); 108| 0| SetBufferAndMode(new char[Size], Size, InternalBuffer); 109| 0| } 110| | 111| 0| size_t GetBufferSize() const { 112| 0| // If we're supposed to be buffered but haven't actually gotten around 113| 0| // to allocating the buffer yet, return the value that would be used. 114| 0| if (BufferMode != Unbuffered && OutBufStart == nullptr) 115| 0| return preferred_buffer_size(); 116| 0| 117| 0| // Otherwise just return the size of the allocated buffer. 118| 0| return OutBufEnd - OutBufStart; 119| 0| } 120| | 121| | /// SetUnbuffered - Set the stream to be unbuffered. When 122| | /// unbuffered, the stream will flush after every write. This routine 123| | /// will also flush the buffer immediately when the stream is being 124| | /// set to unbuffered. 125| 0| void SetUnbuffered() { 126| 0| flush(); 127| 0| SetBufferAndMode(nullptr, 0, Unbuffered); 128| 0| } 129| | 130| | size_t GetNumBytesInBuffer() const { 131| | return OutBufCur - OutBufStart; 132| | } 133| | 134| | //===--------------------------------------------------------------------===// 135| | // Data Output Interface 136| | //===--------------------------------------------------------------------===// 137| | 138| 0| void flush() { 139| 0| if (OutBufCur != OutBufStart) 140| 0| flush_nonempty(); 141| 0| } 142| | 143| | raw_ostream &operator<<(char C) { 144| | if (OutBufCur >= OutBufEnd) 145| | return write(C); 146| | *OutBufCur++ = C; 147| | return *this; 148| | } 149| | 150| | raw_ostream &operator<<(unsigned char C) { 151| | if (OutBufCur >= OutBufEnd) 152| | return write(C); 153| | *OutBufCur++ = C; 154| | return *this; 155| | } 156| | 157| 0| raw_ostream &operator<<(signed char C) { 158| 0| if (OutBufCur >= OutBufEnd) 159| 0| return write(C); 160| 0| *OutBufCur++ = C; 161| 0| return *this; 162| 0| } 163| | 164| 0| raw_ostream &operator<<(StringRef Str) { 165| 0| // Inline fast path, particularly for strings with a known length. 166| 0| size_t Size = Str.size(); 167| 0| 168| 0| // Make sure we can use the fast path. 169| 0| if (Size > (size_t)(OutBufEnd - OutBufCur)) 170| 0| return write(Str.data(), Size); 171| 0| 172| 0| memcpy(OutBufCur, Str.data(), Size); 173| 0| OutBufCur += Size; 174| 0| return *this; 175| 0| } 176| | 177| 0| raw_ostream &operator<<(const char *Str) { 178| 0| // Inline fast path, particularly for constant strings where a sufficiently 179| 0| // smart compiler will simplify strlen. 180| 0| 181| 0| return this->operator<<(StringRef(Str)); 182| 0| } 183| | 184| | raw_ostream &operator<<(const std::string &Str) { 185| | // Avoid the fast path, it would only increase code size for a marginal win. 186| | return write(Str.data(), Str.length()); 187| | } 188| | 189| | raw_ostream &operator<<(const llvm::SmallVectorImpl &Str) { 190| | return write(Str.data(), Str.size()); 191| | } 192| | 193| | raw_ostream &operator<<(unsigned long N); 194| | raw_ostream &operator<<(long N); 195| | raw_ostream &operator<<(unsigned long long N); 196| | raw_ostream &operator<<(long long N); 197| | raw_ostream &operator<<(const void *P); 198| | raw_ostream &operator<<(unsigned int N) { 199| | return this->operator<<(static_cast(N)); 200| | } 201| | 202| | raw_ostream &operator<<(int N) { 203| | return this->operator<<(static_cast(N)); 204| | } 205| | 206| | raw_ostream &operator<<(double N); 207| | 208| | /// write_hex - Output \p N in hexadecimal, without any prefix or padding. 209| | raw_ostream &write_hex(unsigned long long N); 210| | 211| | /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and 212| | /// anything that doesn't satisfy std::isprint into an escape sequence. 213| | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); 214| | 215| | raw_ostream &write(unsigned char C); 216| | raw_ostream &write(const char *Ptr, size_t Size); 217| | 218| | // Formatted output, see the format() function in Support/Format.h. 219| | raw_ostream &operator<<(const format_object_base &Fmt); 220| | 221| | // Formatted output, see the leftJustify() function in Support/Format.h. 222| | raw_ostream &operator<<(const FormattedString &); 223| | 224| | // Formatted output, see the formatHex() function in Support/Format.h. 225| | raw_ostream &operator<<(const FormattedNumber &); 226| | 227| | /// indent - Insert 'NumSpaces' spaces. 228| | raw_ostream &indent(unsigned NumSpaces); 229| | 230| | 231| | /// Changes the foreground color of text that will be output from this point 232| | /// forward. 233| | /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to 234| | /// change only the bold attribute, and keep colors untouched 235| | /// @param Bold bold/brighter text, default false 236| | /// @param BG if true change the background, default: change foreground 237| | /// @returns itself so it can be used within << invocations 238| | virtual raw_ostream &changeColor(enum Colors Color, 239| | bool Bold = false, 240| | bool BG = false) { 241| | (void)Color; 242| | (void)Bold; 243| | (void)BG; 244| | return *this; 245| | } 246| | 247| | /// Resets the colors to terminal defaults. Call this when you are done 248| | /// outputting colored text, or before program exit. 249| | virtual raw_ostream &resetColor() { return *this; } 250| | 251| | /// Reverses the forground and background colors. 252| | virtual raw_ostream &reverseColor() { return *this; } 253| | 254| | /// This function determines if this stream is connected to a "tty" or 255| | /// "console" window. That is, the output would be displayed to the user 256| | /// rather than being put on a pipe or stored in a file. 257| | virtual bool is_displayed() const { return false; } 258| | 259| | /// This function determines if this stream is displayed and supports colors. 260| | virtual bool has_colors() const { return is_displayed(); } 261| | 262| | //===--------------------------------------------------------------------===// 263| | // Subclass Interface 264| | //===--------------------------------------------------------------------===// 265| | 266| |private: 267| | /// write_impl - The is the piece of the class that is implemented 268| | /// by subclasses. This writes the \p Size bytes starting at 269| | /// \p Ptr to the underlying stream. 270| | /// 271| | /// This function is guaranteed to only be called at a point at which it is 272| | /// safe for the subclass to install a new buffer via SetBuffer. 273| | /// 274| | /// \param Ptr The start of the data to be written. For buffered streams this 275| | /// is guaranteed to be the start of the buffer. 276| | /// 277| | /// \param Size The number of bytes to be written. 278| | /// 279| | /// \invariant { Size > 0 } 280| | virtual void write_impl(const char *Ptr, size_t Size) = 0; 281| | 282| | // An out of line virtual method to provide a home for the class vtable. 283| | virtual void handle(); 284| | 285| | /// current_pos - Return the current position within the stream, not 286| | /// counting the bytes currently in the buffer. 287| | virtual uint64_t current_pos() const = 0; 288| | 289| |protected: 290| | /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is 291| | /// intended for use only by subclasses which can arrange for the output to go 292| | /// directly into the desired output buffer, instead of being copied on each 293| | /// flush. 294| 0| void SetBuffer(char *BufferStart, size_t Size) { 295| 0| SetBufferAndMode(BufferStart, Size, ExternalBuffer); 296| 0| } 297| | 298| | /// preferred_buffer_size - Return an efficient buffer size for the 299| | /// underlying output mechanism. 300| | virtual size_t preferred_buffer_size() const; 301| | 302| | /// getBufferStart - Return the beginning of the current stream buffer, or 0 303| | /// if the stream is unbuffered. 304| 0| const char *getBufferStart() const { return OutBufStart; } 305| | 306| | //===--------------------------------------------------------------------===// 307| | // Private Interface 308| | //===--------------------------------------------------------------------===// 309| |private: 310| | /// SetBufferAndMode - Install the given buffer and mode. 311| | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); 312| | 313| | /// flush_nonempty - Flush the current buffer, which is known to be 314| | /// non-empty. This outputs the currently buffered data and resets 315| | /// the buffer to empty. 316| | void flush_nonempty(); 317| | 318| | /// copy_to_buffer - Copy data into the buffer. Size must not be 319| | /// greater than the number of unused bytes in the buffer. 320| | void copy_to_buffer(const char *Ptr, size_t Size); 321| |}; 322| | 323| |//===----------------------------------------------------------------------===// 324| |// File Output Streams 325| |//===----------------------------------------------------------------------===// 326| | 327| |/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. 328| |/// 329| |class raw_fd_ostream : public raw_ostream { 330| | int FD; 331| | bool ShouldClose; 332| | 333| | /// Error This flag is true if an error of any kind has been detected. 334| | /// 335| | bool Error; 336| | 337| | /// Controls whether the stream should attempt to use atomic writes, when 338| | /// possible. 339| | bool UseAtomicWrites; 340| | 341| | uint64_t pos; 342| | 343| | /// write_impl - See raw_ostream::write_impl. 344| | void write_impl(const char *Ptr, size_t Size) override; 345| | 346| | /// current_pos - Return the current position within the stream, not 347| | /// counting the bytes currently in the buffer. 348| | uint64_t current_pos() const override { return pos; } 349| | 350| | /// preferred_buffer_size - Determine an efficient buffer size. 351| | size_t preferred_buffer_size() const override; 352| | 353| | /// error_detected - Set the flag indicating that an output error has 354| | /// been encountered. 355| 0| void error_detected() { Error = true; } 356| | 357| |public: 358| | /// Open the specified file for writing. If an error occurs, information 359| | /// about the error is put into EC, and the stream should be immediately 360| | /// destroyed; 361| | /// \p Flags allows optional flags to control how the file will be opened. 362| | /// 363| | /// As a special case, if Filename is "-", then the stream will use 364| | /// STDOUT_FILENO instead of opening a file. Note that it will still consider 365| | /// itself to own the file descriptor. In particular, it will close the 366| | /// file descriptor when it is done (this is necessary to detect 367| | /// output errors). 368| | raw_fd_ostream(StringRef Filename, std::error_code &EC, 369| | sys::fs::OpenFlags Flags); 370| | 371| | /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 372| | /// ShouldClose is true, this closes the file when the stream is destroyed. 373| | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); 374| | 375| | ~raw_fd_ostream(); 376| | 377| | /// close - Manually flush the stream and close the file. 378| | /// Note that this does not call fsync. 379| | void close(); 380| | 381| | /// seek - Flushes the stream and repositions the underlying file descriptor 382| | /// position to the offset specified from the beginning of the file. 383| | uint64_t seek(uint64_t off); 384| | 385| | /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for 386| | /// individual output routines where possible. 387| | /// 388| | /// Note that because raw_ostream's are typically buffered, this flag is only 389| | /// sensible when used on unbuffered streams which will flush their output 390| | /// immediately. 391| 0| void SetUseAtomicWrites(bool Value) { 392| 0| UseAtomicWrites = Value; 393| 0| } 394| | 395| | raw_ostream &changeColor(enum Colors colors, bool bold=false, 396| | bool bg=false) override; 397| | raw_ostream &resetColor() override; 398| | 399| | raw_ostream &reverseColor() override; 400| | 401| | bool is_displayed() const override; 402| | 403| | bool has_colors() const override; 404| | 405| | /// has_error - Return the value of the flag in this raw_fd_ostream indicating 406| | /// whether an output error has been encountered. 407| | /// This doesn't implicitly flush any pending output. Also, it doesn't 408| | /// guarantee to detect all errors unless the stream has been closed. 409| | bool has_error() const { 410| | return Error; 411| | } 412| | 413| | /// clear_error - Set the flag read by has_error() to false. If the error 414| | /// flag is set at the time when this raw_ostream's destructor is called, 415| | /// report_fatal_error is called to report the error. Use clear_error() 416| | /// after handling the error to avoid this behavior. 417| | /// 418| | /// "Errors should never pass silently. 419| | /// Unless explicitly silenced." 420| | /// - from The Zen of Python, by Tim Peters 421| | /// 422| 0| void clear_error() { 423| 0| Error = false; 424| 0| } 425| |}; 426| | 427| |/// outs() - This returns a reference to a raw_ostream for standard output. 428| |/// Use it like: outs() << "foo" << "bar"; 429| |raw_ostream &outs(); 430| | 431| |/// errs() - This returns a reference to a raw_ostream for standard error. 432| |/// Use it like: errs() << "foo" << "bar"; 433| |raw_ostream &errs(); 434| | 435| |/// nulls() - This returns a reference to a raw_ostream which simply discards 436| |/// output. 437| |raw_ostream &nulls(); 438| | 439| |//===----------------------------------------------------------------------===// 440| |// Output Stream Adaptors 441| |//===----------------------------------------------------------------------===// 442| | 443| |/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a 444| |/// simple adaptor class. This class does not encounter output errors. 445| |class raw_string_ostream : public raw_ostream { 446| | std::string &OS; 447| | 448| | /// write_impl - See raw_ostream::write_impl. 449| | void write_impl(const char *Ptr, size_t Size) override; 450| | 451| | /// current_pos - Return the current position within the stream, not 452| | /// counting the bytes currently in the buffer. 453| | uint64_t current_pos() const override { return OS.size(); } 454| |public: 455| 0| explicit raw_string_ostream(std::string &O) : OS(O) {} 456| | ~raw_string_ostream(); 457| | 458| | /// str - Flushes the stream contents to the target string and returns 459| | /// the string's reference. 460| 0| std::string& str() { 461| 0| flush(); 462| 0| return OS; 463| 0| } 464| |}; 465| | 466| |/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or 467| |/// SmallString. This is a simple adaptor class. This class does not 468| |/// encounter output errors. 469| |class raw_svector_ostream : public raw_ostream { 470| | SmallVectorImpl &OS; 471| | 472| | /// write_impl - See raw_ostream::write_impl. 473| | void write_impl(const char *Ptr, size_t Size) override; 474| | 475| | /// current_pos - Return the current position within the stream, not 476| | /// counting the bytes currently in the buffer. 477| | uint64_t current_pos() const override; 478| |public: 479| | /// Construct a new raw_svector_ostream. 480| | /// 481| | /// \param O The vector to write to; this should generally have at least 128 482| | /// bytes free to avoid any extraneous memory overhead. 483| | explicit raw_svector_ostream(SmallVectorImpl &O); 484| | ~raw_svector_ostream(); 485| | 486| | /// resync - This is called when the SmallVector we're appending to is changed 487| | /// outside of the raw_svector_ostream's control. It is only safe to do this 488| | /// if the raw_svector_ostream has previously been flushed. 489| | void resync(); 490| | 491| | /// str - Flushes the stream contents to the target vector and return a 492| | /// StringRef for the vector contents. 493| | StringRef str(); 494| |}; 495| | 496| |/// raw_null_ostream - A raw_ostream that discards all output. 497| |class raw_null_ostream : public raw_ostream { 498| | /// write_impl - See raw_ostream::write_impl. 499| | void write_impl(const char *Ptr, size_t size) override; 500| | 501| | /// current_pos - Return the current position within the stream, not 502| | /// counting the bytes currently in the buffer. 503| | uint64_t current_pos() const override; 504| | 505| |public: 506| 0| explicit raw_null_ostream() {} 507| | ~raw_null_ostream(); 508| |}; 509| | 510| |} // end llvm namespace 511| | 512| |#endif <<<<<< EOF # path=Workspace.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/CheckoutState.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import PackageGraph 13| |import SourceControl 14| |import SPMUtility 15| | 16| |/// A checkout state represents the current state of a repository. 17| |/// 18| |/// A state will always has a revision. It can also have a branch or a version but not both. 19| |public struct CheckoutState: Equatable, CustomStringConvertible { 20| | 21| | /// The revision of the checkout. 22| | public let revision: Revision 23| | 24| | /// The version of the checkout, if known. 25| | public let version: Version? 26| | 27| | /// The branch of the checkout, if known. 28| | public let branch: String? 29| | 30| | /// Create a checkout state with given data. It is invalid to provide both version and branch. 31| | /// 32| | /// This is deliberately fileprivate so CheckoutState is not initialized 33| | /// with both version and branch. All other initializers should delegate to it. 34| 0| fileprivate init(revision: Revision, version: Version?, branch: String?) { 35| 0| assert(version == nil || branch == nil, "Can't set both branch and version.") 36| 0| self.revision = revision 37| 0| self.version = version 38| 0| self.branch = branch 39| 0| } 40| | 41| | /// Create a checkout state with given revision and branch. 42| 0| public init(revision: Revision, branch: String? = nil) { 43| 0| self.init(revision: revision, version: nil, branch: branch) 44| 0| } 45| | 46| | /// Create a checkout state with given revision and version. 47| 0| public init(revision: Revision, version: Version) { 48| 0| self.init(revision: revision, version: version, branch: nil) 49| 0| } 50| | 51| 0| public var description: String { 52| 0| return version?.description ?? branch ?? revision.identifier 53| 0| } 54| |} 55| | 56| |extension CheckoutState { 57| | 58| | /// Returns requirement induced by this state. 59| 0| func requirement() -> PackageRequirement { 60| 0| if let version = version { 61| 0| return .versionSet(.exact(version)) 62| 0| } else if let branch = branch { 63| 0| return .revision(branch) 64| 0| } 65| 0| return .revision(revision.identifier) 66| 0| } 67| |} 68| | 69| |// MARK: - JSON 70| | 71| |extension CheckoutState: JSONMappable, JSONSerializable { 72| 0| public init(json: JSON) throws { 73| 0| self.init( 74| 0| revision: try json.get("revision"), 75| 0| version: json.get("version"), 76| 0| branch: json.get("branch") 77| 0| ) 78| 0| } 79| | 80| 0| public func toJSON() -> JSON { 81| 0| return .init([ 82| 0| "revision": revision.identifier, 83| 0| "version": version.toJSON(), 84| 0| "branch": branch.toJSON(), 85| 0| ]) 86| 0| } 87| |} 88| | 89| |extension ManagedDependency { 90| 0| public var checkoutState: CheckoutState? { 91| 0| if case .checkout(let checkoutState) = state { 92| 0| return checkoutState 93| 0| } 94| 0| return nil 95| 0| } 96| |} 97| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/Destination.swift: 1| |import Basic 2| |import Build 3| |import SPMUtility 4| |import POSIX 5| | 6| |public enum DestinationError: Swift.Error { 7| | /// Couldn't find the Xcode installation. 8| | case invalidInstallation(String) 9| | 10| | /// The schema version is invalid. 11| | case invalidSchemaVersion 12| |} 13| | 14| |extension DestinationError: CustomStringConvertible { 15| 0| public var description: String { 16| 0| switch self { 17| 0| case .invalidSchemaVersion: 18| 0| return "unsupported destination file schema version" 19| 0| case .invalidInstallation(let problem): 20| 0| return problem 21| 0| } 22| 0| } 23| |} 24| | 25| |/// The compilation destination, has information about everything that's required for a certain destination. 26| |public struct Destination { 27| | 28| | /// The clang/LLVM triple describing the target OS and architecture. 29| | /// 30| | /// The triple has the general format ---, where: 31| | /// - arch = x86_64, i386, arm, thumb, mips, etc. 32| | /// - sub = for ex. on ARM: v5, v6m, v7a, v7m, etc. 33| | /// - vendor = pc, apple, nvidia, ibm, etc. 34| | /// - sys = none, linux, win32, darwin, cuda, etc. 35| | /// - abi = eabi, gnu, android, macho, elf, etc. 36| | /// 37| | /// for more information see //https://clang.llvm.org/docs/CrossCompilation.html 38| | public let target: Triple 39| | 40| | /// The SDK used to compile for the destination. 41| | public let sdk: AbsolutePath 42| | 43| | /// The binDir in the containing the compilers/linker to be used for the compilation. 44| | public let binDir: AbsolutePath 45| | 46| | /// Additional flags to be passed to the C compiler. 47| | public let extraCCFlags: [String] 48| | 49| | /// Additional flags to be passed to the Swift compiler. 50| | public let extraSwiftCFlags: [String] 51| | 52| | /// Additional flags to be passed when compiling with C++. 53| | public let extraCPPFlags: [String] 54| | 55| | /// Returns the bin directory for the host. 56| | /// 57| | /// - Parameter originalWorkingDirectory: The working directory when the program was launched. 58| | private static func hostBinDir( 59| | originalWorkingDirectory: AbsolutePath? = localFileSystem.currentWorkingDirectory 60| 0| ) -> AbsolutePath { 61| 0| #if Xcode 62| 0| // For Xcode, set bin directory to the build directory containing the fake 63| 0| // toolchain created during bootstraping. This is obviously not production ready 64| 0| // and only exists as a development utility right now. 65| 0| // 66| 0| // This also means that we should have bootstrapped with the same Swift toolchain 67| 0| // we're using inside Xcode otherwise we will not be able to load the runtime libraries. 68| 0| // 69| 0| // FIXME: We may want to allow overriding this using an env variable but that 70| 0| // doesn't seem urgent or extremely useful as of now. 71| 0| return AbsolutePath(#file).parentDirectory 72| 0| .parentDirectory.parentDirectory.appending(components: ".build", hostTargetTriple.tripleString, "debug") 73| 0| #else 74| 0| guard let cwd = originalWorkingDirectory else { 75| 0| return try! AbsolutePath(validating: CommandLine.arguments[0]).parentDirectory 76| 0| } 77| 0| return AbsolutePath(CommandLine.arguments[0], relativeTo: cwd).parentDirectory 78| 0| #endif 79| 0| } 80| | 81| | /// The destination describing the host OS. 82| | public static func hostDestination( 83| | _ binDir: AbsolutePath? = nil, 84| | originalWorkingDirectory: AbsolutePath? = localFileSystem.currentWorkingDirectory, 85| | environment: [String:String] = Process.env 86| 0| ) throws -> Destination { 87| 0| // Select the correct binDir. 88| 0| let binDir = binDir ?? Destination.hostBinDir( 89| 0| originalWorkingDirectory: originalWorkingDirectory) 90| 0| 91| 0| #if os(macOS) 92| 0| // Get the SDK. 93| 0| let sdkPath: AbsolutePath 94| 0| if let value = lookupExecutablePath(filename: getenv("SDKROOT")) { 95| 0| sdkPath = value 96| 0| } else { 97| 0| // No value in env, so search for it. 98| 0| let sdkPathStr = try Process.checkNonZeroExit( 99| 0| arguments: ["xcrun", "--sdk", "macosx", "--show-sdk-path"], environment: environment).spm_chomp() 100| 0| guard !sdkPathStr.isEmpty else { 101| 0| throw DestinationError.invalidInstallation("default SDK not found") 102| 0| } 103| 0| sdkPath = AbsolutePath(sdkPathStr) 104| 0| } 105| 0| 106| 0| // Compute common arguments for clang and swift. 107| 0| // This is currently just frameworks path. 108| 0| let commonArgs = Destination.sdkPlatformFrameworkPath(environment: environment).map({ ["-F", $0.pathString] }) ?? [] 109| 0| 110| 0| return Destination( 111| 0| target: hostTargetTriple, 112| 0| sdk: sdkPath, 113| 0| binDir: binDir, 114| 0| extraCCFlags: commonArgs, 115| 0| extraSwiftCFlags: commonArgs, 116| 0| extraCPPFlags: ["-lc++"] 117| 0| ) 118| 0| #else 119| 0| return Destination( 120| 0| target: hostTargetTriple, 121| 0| sdk: .root, 122| 0| binDir: binDir, 123| 0| extraCCFlags: ["-fPIC"], 124| 0| extraSwiftCFlags: [], 125| 0| extraCPPFlags: ["-lstdc++"] 126| 0| ) 127| 0| #endif 128| 0| } 129| | 130| | /// Returns macosx sdk platform framework path. 131| 0| public static func sdkPlatformFrameworkPath(environment: [String:String] = Process.env) -> AbsolutePath? { 132| 0| if let path = _sdkPlatformFrameworkPath { 133| 0| return path 134| 0| } 135| 0| let platformPath = try? Process.checkNonZeroExit( 136| 0| arguments: ["xcrun", "--sdk", "macosx", "--show-sdk-platform-path"], environment: environment).spm_chomp() 137| 0| 138| 0| if let platformPath = platformPath, !platformPath.isEmpty { 139| 0| _sdkPlatformFrameworkPath = AbsolutePath(platformPath).appending( 140| 0| components: "Developer", "Library", "Frameworks") 141| 0| } 142| 0| return _sdkPlatformFrameworkPath 143| 0| } 144| | /// Cache storage for sdk platform path. 145| | private static var _sdkPlatformFrameworkPath: AbsolutePath? = nil 146| | 147| | /// Target triple for the host system. 148| | private static let hostTargetTriple = Triple.hostTriple 149| |} 150| | 151| |extension Destination { 152| | 153| | /// Load a Destination description from a JSON representation from disk. 154| 0| public init(fromFile path: AbsolutePath, fileSystem: FileSystem = localFileSystem) throws { 155| 0| let json = try JSON(bytes: fileSystem.readFileContents(path)) 156| 0| try self.init(json: json) 157| 0| } 158| |} 159| | 160| |extension Destination: JSONMappable { 161| | 162| | /// The current schema version. 163| | static let schemaVersion = 1 164| | 165| 0| public init(json: JSON) throws { 166| 0| 167| 0| // Check schema version. 168| 0| guard try json.get("version") == Destination.schemaVersion else { 169| 0| throw DestinationError.invalidSchemaVersion 170| 0| } 171| 0| 172| 0| try self.init( 173| 0| target: Triple(json.get("target")), 174| 0| sdk: AbsolutePath(json.get("sdk")), 175| 0| binDir: AbsolutePath(json.get("toolchain-bin-dir")), 176| 0| extraCCFlags: json.get("extra-cc-flags"), 177| 0| extraSwiftCFlags: json.get("extra-swiftc-flags"), 178| 0| extraCPPFlags: json.get("extra-cpp-flags") 179| 0| ) 180| 0| } 181| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/Diagnostics.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import SPMUtility 13| |import PackageModel 14| |import PackageLoading 15| |import PackageGraph 16| |import Foundation 17| | 18| |public struct ManifestParseDiagnostic: DiagnosticData { 19| | public static let id = DiagnosticID( 20| | type: ManifestParseDiagnostic.self, 21| | name: "org.swift.diags.manifest-parse", 22| | description: { 23| 0| $0 <<< { "manifest parse error(s):\n" + $0.errors.joined(separator: "\n") } 24| | } 25| | ) 26| | 27| | public let errors: [String] 28| 0| public init(_ errors: [String]) { 29| 0| self.errors = errors 30| 0| } 31| |} 32| | 33| |public struct ManifestDuplicateDeclDiagnostic: DiagnosticData { 34| | public static let id = DiagnosticID( 35| | type: ManifestParseDiagnostic.self, 36| | name: "org.swift.diags.manifest-dup-dep-decl", 37| | description: { 38| 0| $0 <<< .substitution({ 39| 0| let `self` = $0 as! ManifestDuplicateDeclDiagnostic 40| 0| let stream = BufferedOutputByteStream() 41| 0| 42| 0| stream <<< "manifest parse error(s): duplicate dependency declaration\n" 43| 0| let indent = Format.asRepeating(string: " ", count: 4) 44| 0| 45| 0| for duplicateDecls in self.duplicates { 46| 0| for duplicate in duplicateDecls { 47| 0| stream <<< indent <<< duplicate.url <<< " @ " <<< "\(duplicate.requirement)" <<< "\n" 48| 0| } 49| 0| stream <<< "\n" 50| 0| } 51| 0| 52| 0| return stream.bytes.description 53| 0| }, preference: .default) 54| | } 55| | ) 56| | 57| | public let duplicates: [[PackageDependencyDescription]] 58| 0| public init(_ duplicates: [[PackageDependencyDescription]]) { 59| 0| self.duplicates = duplicates 60| 0| } 61| |} 62| | 63| |extension ManifestParseError: DiagnosticDataConvertible { 64| 0| public var diagnosticData: DiagnosticData { 65| 0| switch self { 66| 0| case .invalidManifestFormat(let error): 67| 0| return ManifestParseDiagnostic([error]) 68| 0| case .runtimeManifestErrors(let errors): 69| 0| return ManifestParseDiagnostic(errors) 70| 0| case .duplicateDependencyDecl(let duplicates): 71| 0| return ManifestDuplicateDeclDiagnostic(duplicates) 72| 0| case .unsupportedAPI(let api, let supportedVersions): 73| 0| var error = "'\(api)' is only supported by manifest version(s): " 74| 0| error += supportedVersions.map({ $0.description }).joined(separator: ", ") 75| 0| return ManifestParseDiagnostic([error]) 76| 0| } 77| 0| } 78| |} 79| | 80| |public enum ResolverDiagnostics { 81| | 82| | public struct Unsatisfiable: DiagnosticData { 83| | public static let id = DiagnosticID( 84| | type: Unsatisfiable.self, 85| | name: "org.swift.diags.resolver.unsatisfiable", 86| 0| description: { 87| 0| $0 <<< "dependency graph is unresolvable;" 88| 0| $0 <<< .substitution({ 89| 0| let `self` = $0 as! Unsatisfiable 90| 0| 91| 0| // If we don't have any additional data, return empty string. 92| 0| if self.dependencies.isEmpty && self.pins.isEmpty { 93| 0| return "" 94| 0| } 95| 0| var diag = "found these conflicting requirements:" 96| 0| let indent = " " 97| 0| 98| 0| if !self.dependencies.isEmpty { 99| 0| diag += "\n\nDependencies: \n" 100| 0| diag += self.dependencies.map({ indent + Unsatisfiable.toString($0) }).joined(separator: "\n") 101| 0| } 102| 0| 103| 0| if !self.pins.isEmpty { 104| 0| diag += "\n\nPins: \n" 105| 0| diag += self.pins.map({ indent + Unsatisfiable.toString($0) }).joined(separator: "\n") 106| 0| } 107| 0| return diag 108| 0| }, preference: .default) 109| 0| } 110| | ) 111| | 112| 0| static func toString(_ constraint: RepositoryPackageConstraint) -> String { 113| 0| let stream = BufferedOutputByteStream() 114| 0| stream <<< constraint.identifier.path <<< " @ " 115| 0| 116| 0| switch constraint.requirement { 117| 0| case .versionSet(let set): 118| 0| stream <<< set.description 119| 0| case .revision(let revision): 120| 0| stream <<< revision 121| 0| case .unversioned: 122| 0| stream <<< "unversioned" 123| 0| } 124| 0| 125| 0| return stream.bytes.description 126| 0| } 127| | 128| | /// The conflicting dependencies. 129| | public let dependencies: [RepositoryPackageConstraint] 130| | 131| | /// The conflicting pins. 132| | public let pins: [RepositoryPackageConstraint] 133| | 134| 0| public init( dependencies: [RepositoryPackageConstraint], pins: [RepositoryPackageConstraint]) { 135| 0| self.dependencies = dependencies 136| 0| self.pins = pins 137| 0| } 138| | } 139| |} 140| | 141| |public struct InvalidToolchainDiagnostic: DiagnosticData, Error { 142| | public static let id = DiagnosticID( 143| | type: InvalidToolchainDiagnostic.self, 144| | name: "org.swift.diags.invalid-toolchain", 145| | description: { 146| 0| $0 <<< "toolchain is invalid:" <<< { $0.error } 147| | } 148| | ) 149| | 150| | public let error: String 151| 0| public init(_ error: String) { 152| 0| self.error = error 153| 0| } 154| |} 155| | 156| |public enum WorkspaceDiagnostics { 157| | 158| | //MARK: - Errors 159| | 160| | /// The diagnostic triggered when an operation fails because its completion 161| | /// would loose the uncommited changes in a repository. 162| | public struct UncommitedChanges: DiagnosticData, Swift.Error { 163| | public static var id = DiagnosticID( 164| | type: UncommitedChanges.self, 165| | name: "org.swift.diags.workspace.uncommited-changes", 166| | description: { 167| 0| $0 <<< "repository" <<< { "'\($0.repositoryPath)'" } <<< "has uncommited changes" 168| | }) 169| | 170| | /// The local path to the repository. 171| | public let repositoryPath: AbsolutePath 172| | } 173| | 174| | /// The diagnostic triggered when an operation fails because its completion 175| | /// would loose the unpushed changes in a repository. 176| | public struct UnpushedChanges: DiagnosticData, Swift.Error { 177| | public static var id = DiagnosticID( 178| | type: UnpushedChanges.self, 179| | name: "org.swift.diags.workspace.unpushed-changes", 180| | description: { 181| 0| $0 <<< "repository" <<< { "'\($0.repositoryPath)'" } <<< "has unpushed changes" 182| | }) 183| | 184| | /// The local path to the repository. 185| | public let repositoryPath: AbsolutePath 186| | } 187| | 188| | public struct LocalDependencyEdited: DiagnosticData, Swift.Error { 189| | public static var id = DiagnosticID( 190| | type: LocalDependencyEdited.self, 191| | name: "org.swift.diags.workspace.local-dependency-edited", 192| | description: { 193| 0| $0 <<< "local dependency" <<< { "'\($0.dependencyName)'" } <<< "can't be edited" 194| | }) 195| | 196| | /// The name of the dependency being edited. 197| | public let dependencyName: String 198| | } 199| | 200| | /// The diagnostic triggered when the edit operation fails because the dependency 201| | /// is already in edit mode. 202| | public struct DependencyAlreadyInEditMode: DiagnosticData, Swift.Error { 203| | public static var id = DiagnosticID( 204| | type: DependencyAlreadyInEditMode.self, 205| | name: "org.swift.diags.workspace.dependency-already-in-edit-mode", 206| | description: { 207| 0| $0 <<< "dependency" <<< { "'\($0.dependencyName)'" } <<< "already in edit mode" 208| | }) 209| | 210| | /// The name of the dependency being edited. 211| | public let dependencyName: String 212| | } 213| | 214| | /// The diagnostic triggered when the unedit operation fails because the dependency 215| | /// is not in edit mode. 216| | public struct DependencyNotInEditMode: DiagnosticData, Swift.Error { 217| | public static var id = DiagnosticID( 218| | type: DependencyNotInEditMode.self, 219| | name: "org.swift.diags.workspace.dependency-not-in-edit-mode", 220| | description: { 221| 0| $0 <<< "dependency" <<< { "'\($0.dependencyName)'" } <<< "not in edit mode" 222| | }) 223| | 224| | /// The name of the dependency being unedited. 225| | public let dependencyName: String 226| | } 227| | 228| | /// The diagnostic triggered when the edit operation fails because the branch 229| | /// to be created already exists. 230| | public struct BranchAlreadyExists: DiagnosticData, Swift.Error { 231| | public static var id = DiagnosticID( 232| | type: BranchAlreadyExists.self, 233| | name: "org.swift.diags.workspace.branch-already-exists", 234| | description: { 235| 0| $0 <<< "branch" <<< { "'\($0.branch)'" } <<< "already exists" 236| | }) 237| | 238| | /// The branch to create. 239| | public let branch: String 240| | } 241| | 242| | /// The diagnostic triggered when the edit operation fails because the specified 243| | /// revision does not exist. 244| | public struct RevisionDoesNotExist: DiagnosticData, Swift.Error { 245| | public static var id = DiagnosticID( 246| | type: RevisionDoesNotExist.self, 247| | name: "org.swift.diags.workspace.revision-does-not-exist", 248| | description: { 249| 0| $0 <<< "revision" <<< { "'\($0.revision)'" } <<< "does not exist" 250| | }) 251| | 252| | /// The revision requested. 253| | public let revision: String 254| | } 255| | 256| | /// The diagnostic triggered when the root package has a newer tools version than the installed tools. 257| | public struct RequireNewerTools: DiagnosticData, Swift.Error { 258| | public static var id = DiagnosticID( 259| | type: RequireNewerTools.self, 260| | name: "org.swift.diags.workspace.\(RequireNewerTools.self)", 261| 0| description: { 262| 0| $0 <<< "package at" <<< { "'\($0.packagePath.pathString)'" } 263| 0| $0 <<< "is using Swift tools version" <<< { $0.packageToolsVersion.description } 264| 0| $0 <<< "but the installed version is" <<< { "\($0.installedToolsVersion.description)" } 265| 0| }) 266| | 267| | /// The path of the package. 268| | public let packagePath: AbsolutePath 269| | 270| | /// The installed tools version. 271| | public let installedToolsVersion: ToolsVersion 272| | 273| | /// The tools version of the package. 274| | public let packageToolsVersion: ToolsVersion 275| | } 276| | 277| | /// The diagnostic triggered when the root package has an unsupported tools version. 278| | public struct UnsupportedToolsVersion: DiagnosticData, Swift.Error { 279| | public static var id = DiagnosticID( 280| | type: UnsupportedToolsVersion.self, 281| | name: "org.swift.diags.workspace.\(UnsupportedToolsVersion.self)", 282| 0| description: { 283| 0| $0 <<< "package at" <<< { "'\($0.packagePath.pathString)'" } 284| 0| $0 <<< "is using Swift tools version" <<< { $0.packageToolsVersion.description } 285| 0| $0 <<< "which is no longer supported; use" <<< { $0.minimumRequiredToolsVersion.description } 286| 0| $0 <<< "or newer instead" 287| 0| }) 288| | 289| | /// The path of the package. 290| | public let packagePath: AbsolutePath 291| | 292| | /// The tools version required by the package. 293| | public let minimumRequiredToolsVersion: ToolsVersion 294| | 295| | /// The current tools version. 296| | public let packageToolsVersion: ToolsVersion 297| | } 298| | 299| | /// The diagnostic triggered when the package at the edit destination is not the 300| | /// one user is trying to edit. 301| | public struct MismatchingDestinationPackage: DiagnosticData, Swift.Error { 302| | public static var id = DiagnosticID( 303| | type: MismatchingDestinationPackage.self, 304| | name: "org.swift.diags.workspace.mismatching-destination-package", 305| 0| description: { 306| 0| $0 <<< "package at" <<< { "'\($0.editPath)'" } 307| 0| $0 <<< "is" <<< { $0.destinationPackage ?? "" } 308| 0| $0 <<< "but was expecting" <<< { $0.expectedPackage } 309| 0| }) 310| | 311| | /// The path to be edited to. 312| | public let editPath: AbsolutePath 313| | 314| | /// The package to edit. 315| | public let expectedPackage: String 316| | 317| | /// The package found at the edit location. 318| | public let destinationPackage: String? 319| | } 320| | 321| | //MARK: - Warnings 322| | 323| | /// The diagnostic triggered when a checked-out dependency is missing 324| | /// from the file-system. 325| | public struct CheckedOutDependencyMissing: DiagnosticData, Swift.Error { 326| | public static var id = DiagnosticID( 327| | type: CheckedOutDependencyMissing.self, 328| | name: "org.swift.diags.workspace.checked-out-dependency-missing", 329| | defaultBehavior: .warning, 330| 0| description: { 331| 0| $0 <<< "dependency" <<< { "'\($0.packageName)'" } <<< "is missing;" 332| 0| $0 <<< "cloning again" 333| 0| }) 334| | 335| | /// The package name of the dependency. 336| | public let packageName: String 337| | } 338| | 339| | /// The diagnostic triggered when an edited dependency is missing 340| | /// from the file-system. 341| | public struct EditedDependencyMissing: DiagnosticData, Swift.Error { 342| | public static var id = DiagnosticID( 343| | type: EditedDependencyMissing.self, 344| | name: "org.swift.diags.workspace.edited-dependency-missing", 345| | defaultBehavior: .warning, 346| 0| description: { 347| 0| $0 <<< "dependency" <<< { "'\($0.packageName)'" } <<< "was being edited but is missing;" 348| 0| $0 <<< "falling back to original checkout" 349| 0| }) 350| | 351| | /// The package name of the dependency. 352| | public let packageName: String 353| | } 354| | 355| | /// The diagnostic triggered when a dependency is edited from a revision 356| | /// but the dependency already exists at the target location. 357| | public struct EditRevisionNotUsed: DiagnosticData, Swift.Error { 358| | public static var id = DiagnosticID( 359| | type: EditRevisionNotUsed.self, 360| | name: "org.swift.diags.workspace.edit-revision-not-used", 361| | defaultBehavior: .warning, 362| 0| description: { 363| 0| $0 <<< "dependency" <<< { "'\($0.packageName)'" } <<< "already exists at the edit destination;" 364| 0| $0 <<< "not using revision" <<< { "'\($0.revisionIdentifier)'" } 365| 0| }) 366| | 367| | /// The package name of the dependency. 368| | public let packageName: String 369| | 370| | /// The edit revision. 371| | public let revisionIdentifier: String 372| | } 373| | 374| | /// The diagnostic triggered when a dependency is edited with a branch 375| | /// but the dependency already exists at the target location. 376| | public struct EditBranchNotCheckedOut: DiagnosticData, Swift.Error { 377| | public static var id = DiagnosticID( 378| | type: EditBranchNotCheckedOut.self, 379| | name: "org.swift.diags.workspace.edit-branch-not-used", 380| | defaultBehavior: .warning, 381| 0| description: { 382| 0| $0 <<< "dependency" <<< { "'\($0.packageName)'" } <<< "already exists at the edit destination;" 383| 0| $0 <<< "not checking-out branch" <<< { "'\($0.branchName)'" } 384| 0| }) 385| | 386| | /// The package name of the dependency. 387| | public let packageName: String 388| | 389| | /// The branch name 390| | public let branchName: String 391| | } 392| | 393| | public struct ResolverDurationNote: DiagnosticData { 394| | public static let id = DiagnosticID( 395| | type: ResolverDurationNote.self, 396| | name: "\(ResolverDurationNote.self)", 397| | defaultBehavior: .note, 398| | description: { 399| 0| $0 <<< "Completed resolution in" <<< { String(format: "%.2f", $0.duration) + "s" } 400| | } 401| | ) 402| | 403| | public let duration: Double 404| | 405| 0| public init(_ duration: Double) { 406| 0| self.duration = duration 407| 0| } 408| | } 409| | 410| | public struct PD3DeprecatedDiagnostic: DiagnosticData { 411| | public static let id = DiagnosticID( 412| | type: PD3DeprecatedDiagnostic.self, 413| | name: "org.swift.diags.workspace.\(PD3DeprecatedDiagnostic.self)", 414| | defaultBehavior: .warning, 415| 0| description: { 416| 0| $0 <<< "PackageDescription API v3 is deprecated and will be removed in the future;" 417| 0| $0 <<< "used by package(s):" <<< { $0.manifests.joined(separator: ", ") } 418| 0| } 419| | ) 420| | 421| | let manifests: [String] 422| | } 423| | 424| | public struct OutdatedResolvedFile: DiagnosticData { 425| | public static let id = DiagnosticID( 426| | type: OutdatedResolvedFile.self, 427| | name: "org.swift.diags.workspace.\(OutdatedResolvedFile.self)", 428| | defaultBehavior: .error, 429| 0| description: { 430| 0| $0 <<< "the Package.resolved file is most likely severely out-of-date and is preventing correct resolution;" 431| 0| $0 <<< "delete the resolved file and try again" 432| 0| } 433| | ) 434| | } 435| | 436| | public struct RequiresResolution: DiagnosticData { 437| | public static let id = DiagnosticID( 438| | type: RequiresResolution.self, 439| | name: "org.swift.diags.workspace.\(RequiresResolution.self)", 440| | defaultBehavior: .error, 441| | description: { 442| | $0 <<< "cannot update Package.resolved file because automatic resolution is disabled" 443| | } 444| | ) 445| | } 446| | 447| | public struct DuplicateRoots: DiagnosticData { 448| | public static let id = DiagnosticID( 449| | type: DuplicateRoots.self, 450| | name: "org.swift.diags.workspace.\(DuplicateRoots.self)", 451| | description: { 452| 0| $0 <<< "found multiple top-level packages named" <<< { "'" + $0.name + "'" } 453| | } 454| | ) 455| | 456| | let name: String 457| | } 458| | 459| | public struct MalformedPackageResolved: Swift.Error, CustomStringConvertible { 460| 0| public var description: String { 461| 0| return "Package.resolved file is corrupted or malformed; fix or delete the file to continue" 462| 0| } 463| | } 464| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/InitPackage.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import PackageModel 13| | 14| |/// Create an initial template package. 15| |public final class InitPackage { 16| | /// The tool version to be used for new packages. 17| | public static let newPackageToolsVersion = ToolsVersion(version: "5.0.0") 18| | 19| | /// Represents a package type for the purposes of initialization. 20| | public enum PackageType: String, CustomStringConvertible { 21| | case empty = "empty" 22| | case library = "library" 23| | case executable = "executable" 24| | case systemModule = "system-module" 25| | 26| 0| public var description: String { 27| 0| return rawValue 28| 0| } 29| | } 30| | 31| | /// A block that will be called to report progress during package creation 32| | public var progressReporter: ((String) -> Void)? 33| | 34| | /// Where to create the new package 35| | let destinationPath: AbsolutePath 36| | 37| | /// The type of package to create. 38| | let packageType: PackageType 39| | 40| | /// The name of the package to create. 41| | let pkgname: String 42| | 43| | /// The name of the target to create. 44| | var moduleName: String 45| | 46| | /// The name of the type to create (within the package). 47| 0| var typeName: String { 48| 0| return moduleName 49| 0| } 50| | 51| | /// Create an instance that can create a package with given arguments. 52| 0| public init(name: String, destinationPath: AbsolutePath, packageType: PackageType) throws { 53| 0| self.packageType = packageType 54| 0| self.destinationPath = destinationPath 55| 0| self.pkgname = name 56| 0| self.moduleName = name.spm_mangledToC99ExtendedIdentifier() 57| 0| } 58| | 59| | /// Actually creates the new package at the destinationPath 60| 0| public func writePackageStructure() throws { 61| 0| progressReporter?("Creating \(packageType) package: \(pkgname)") 62| 0| 63| 0| // FIXME: We should form everything we want to write, then validate that 64| 0| // none of it exists, and then act. 65| 0| try writeManifestFile() 66| 0| try writeREADMEFile() 67| 0| try writeGitIgnore() 68| 0| try writeSources() 69| 0| try writeModuleMap() 70| 0| try writeTests() 71| 0| } 72| | 73| 0| private func writePackageFile(_ path: AbsolutePath, body: (OutputByteStream) -> Void) throws { 74| 0| progressReporter?("Creating \(path.relative(to: destinationPath))") 75| 0| try localFileSystem.writeFileContents(path, body: body) 76| 0| } 77| | 78| 0| private func writeManifestFile() throws { 79| 0| let manifest = destinationPath.appending(component: Manifest.filename) 80| 0| guard exists(manifest) == false else { 81| 0| throw InitError.manifestAlreadyExists 82| 0| } 83| 0| 84| 0| try writePackageFile(manifest) { stream in 85| 0| stream <<< """ 86| 0| // The swift-tools-version declares the minimum version of Swift required to build this package. 87| 0| 88| 0| import PackageDescription 89| 0| 90| 0| let package = Package( 91| 0| 92| 0| """ 93| 0| 94| 0| var pkgParams = [String]() 95| 0| pkgParams.append(""" 96| 0| name: "\(pkgname)" 97| 0| """) 98| 0| 99| 0| if packageType == .library { 100| 0| pkgParams.append(""" 101| 0| products: [ 102| 0| // Products define the executables and libraries produced by a package, and make them visible to other packages. 103| 0| .library( 104| 0| name: "\(pkgname)", 105| 0| targets: ["\(pkgname)"]), 106| 0| ] 107| 0| """) 108| 0| } 109| 0| 110| 0| pkgParams.append(""" 111| 0| dependencies: [ 112| 0| // Dependencies declare other packages that this package depends on. 113| 0| // .package(url: /* package url */, from: "1.0.0"), 114| 0| ] 115| 0| """) 116| 0| 117| 0| if packageType == .library || packageType == .executable { 118| 0| pkgParams.append(""" 119| 0| targets: [ 120| 0| // Targets are the basic building blocks of a package. A target can define a module or a test suite. 121| 0| // Targets can depend on other targets in this package, and on products in packages which this package depends on. 122| 0| .target( 123| 0| name: "\(pkgname)", 124| 0| dependencies: []), 125| 0| .testTarget( 126| 0| name: "\(pkgname)Tests", 127| 0| dependencies: ["\(pkgname)"]), 128| 0| ] 129| 0| """) 130| 0| } 131| 0| 132| 0| stream <<< pkgParams.joined(separator: ",\n") <<< "\n)\n" 133| 0| } 134| 0| 135| 0| // Create a tools version with current version but with patch set to zero. 136| 0| // We do this to avoid adding unnecessary constraints to patch versions, if 137| 0| // the package really needs it, they should add it manually. 138| 0| let version = InitPackage.newPackageToolsVersion.zeroedPatch 139| 0| 140| 0| // Write the current tools version. 141| 0| try writeToolsVersion( 142| 0| at: manifest.parentDirectory, version: version, fs: localFileSystem) 143| 0| } 144| | 145| 0| private func writeREADMEFile() throws { 146| 0| let readme = destinationPath.appending(component: "README.md") 147| 0| guard exists(readme) == false else { 148| 0| return 149| 0| } 150| 0| 151| 0| try writePackageFile(readme) { stream in 152| 0| stream <<< """ 153| 0| # \(pkgname) 154| 0| 155| 0| A description of this package. 156| 0| 157| 0| """ 158| 0| } 159| 0| } 160| | 161| 0| private func writeGitIgnore() throws { 162| 0| let gitignore = destinationPath.appending(component: ".gitignore") 163| 0| guard exists(gitignore) == false else { 164| 0| return 165| 0| } 166| 0| 167| 0| try writePackageFile(gitignore) { stream in 168| 0| stream <<< """ 169| 0| .DS_Store 170| 0| /.build 171| 0| /Packages 172| 0| /*.xcodeproj 173| 0| 174| 0| """ 175| 0| } 176| 0| } 177| | 178| 0| private func writeSources() throws { 179| 0| if packageType == .systemModule { 180| 0| return 181| 0| } 182| 0| let sources = destinationPath.appending(component: "Sources") 183| 0| guard exists(sources) == false else { 184| 0| return 185| 0| } 186| 0| progressReporter?("Creating \(sources.relative(to: destinationPath))/") 187| 0| try makeDirectories(sources) 188| 0| 189| 0| if packageType == .empty { 190| 0| return 191| 0| } 192| 0| 193| 0| let moduleDir = sources.appending(component: "\(pkgname)") 194| 0| try makeDirectories(moduleDir) 195| 0| 196| 0| let sourceFileName = (packageType == .executable) ? "main.swift" : "\(typeName).swift" 197| 0| let sourceFile = moduleDir.appending(RelativePath(sourceFileName)) 198| 0| 199| 0| try writePackageFile(sourceFile) { stream in 200| 0| switch packageType { 201| 0| case .library: 202| 0| stream <<< """ 203| 0| struct \(typeName) { 204| 0| var text = "Hello, World!" 205| 0| } 206| 0| 207| 0| """ 208| 0| case .executable: 209| 0| stream <<< """ 210| 0| print("Hello, world!") 211| 0| 212| 0| """ 213| 0| case .systemModule, .empty: 214| 0| fatalError("invalid") 215| 0| } 216| 0| } 217| 0| } 218| | 219| 0| private func writeModuleMap() throws { 220| 0| if packageType != .systemModule { 221| 0| return 222| 0| } 223| 0| let modulemap = destinationPath.appending(component: "module.modulemap") 224| 0| guard exists(modulemap) == false else { 225| 0| return 226| 0| } 227| 0| 228| 0| try writePackageFile(modulemap) { stream in 229| 0| stream <<< """ 230| 0| module \(moduleName) [system] { 231| 0| header "/usr/include/\(moduleName).h" 232| 0| link "\(moduleName)" 233| 0| export * 234| 0| } 235| 0| 236| 0| """ 237| 0| } 238| 0| } 239| | 240| 0| private func writeTests() throws { 241| 0| if packageType == .systemModule { 242| 0| return 243| 0| } 244| 0| let tests = destinationPath.appending(component: "Tests") 245| 0| guard exists(tests) == false else { 246| 0| return 247| 0| } 248| 0| progressReporter?("Creating \(tests.relative(to: destinationPath))/") 249| 0| try makeDirectories(tests) 250| 0| 251| 0| switch packageType { 252| 0| case .systemModule, .empty: break 253| 0| case .library, .executable: 254| 0| try writeLinuxMain(testsPath: tests) 255| 0| try writeTestFileStubs(testsPath: tests) 256| 0| } 257| 0| } 258| | 259| 0| private func writeLinuxMain(testsPath: AbsolutePath) throws { 260| 0| try writePackageFile(testsPath.appending(component: "LinuxMain.swift")) { stream in 261| 0| stream <<< """ 262| 0| import XCTest 263| 0| 264| 0| import \(moduleName)Tests 265| 0| 266| 0| var tests = [XCTestCaseEntry]() 267| 0| tests += \(moduleName)Tests.allTests() 268| 0| XCTMain(tests) 269| 0| 270| 0| """ 271| 0| } 272| 0| } 273| | 274| 0| private func writeLibraryTestsFile(_ path: AbsolutePath) throws { 275| 0| try writePackageFile(path) { stream in 276| 0| stream <<< """ 277| 0| import XCTest 278| 0| @testable import \(moduleName) 279| 0| 280| 0| final class \(moduleName)Tests: XCTestCase { 281| 0| func testExample() { 282| 0| // This is an example of a functional test case. 283| 0| // Use XCTAssert and related functions to verify your tests produce the correct 284| 0| // results. 285| 0| XCTAssertEqual(\(typeName)().text, "Hello, World!") 286| 0| } 287| 0| 288| 0| static var allTests = [ 289| 0| ("testExample", testExample), 290| 0| ] 291| 0| } 292| 0| 293| 0| """ 294| 0| } 295| 0| } 296| | 297| 0| private func writeExecutableTestsFile(_ path: AbsolutePath) throws { 298| 0| try writePackageFile(path) { stream in 299| 0| stream <<< """ 300| 0| import XCTest 301| 0| import class Foundation.Bundle 302| 0| 303| 0| final class \(moduleName)Tests: XCTestCase { 304| 0| func testExample() throws { 305| 0| // This is an example of a functional test case. 306| 0| // Use XCTAssert and related functions to verify your tests produce the correct 307| 0| // results. 308| 0| 309| 0| // Some of the APIs that we use below are available in macOS 10.13 and above. 310| 0| guard #available(macOS 10.13, *) else { 311| 0| return 312| 0| } 313| 0| 314| 0| let fooBinary = productsDirectory.appendingPathComponent("\(pkgname)") 315| 0| 316| 0| let process = Process() 317| 0| process.executableURL = fooBinary 318| 0| 319| 0| let pipe = Pipe() 320| 0| process.standardOutput = pipe 321| 0| 322| 0| try process.run() 323| 0| process.waitUntilExit() 324| 0| 325| 0| let data = pipe.fileHandleForReading.readDataToEndOfFile() 326| 0| let output = String(data: data, encoding: .utf8) 327| 0| 328| 0| XCTAssertEqual(output, "Hello, world!\\n") 329| 0| } 330| 0| 331| 0| /// Returns path to the built products directory. 332| 0| var productsDirectory: URL { 333| 0| #if os(macOS) 334| 0| for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { 335| 0| return bundle.bundleURL.deletingLastPathComponent() 336| 0| } 337| 0| fatalError("couldn't find the products directory") 338| 0| #else 339| 0| return Bundle.main.bundleURL 340| 0| #endif 341| 0| } 342| 0| 343| 0| static var allTests = [ 344| 0| ("testExample", testExample), 345| 0| ] 346| 0| } 347| 0| 348| 0| """ 349| 0| } 350| 0| } 351| | 352| 0| private func writeTestFileStubs(testsPath: AbsolutePath) throws { 353| 0| let testModule = testsPath.appending(RelativePath(pkgname + Target.testModuleNameSuffix)) 354| 0| progressReporter?("Creating \(testModule.relative(to: destinationPath))/") 355| 0| try makeDirectories(testModule) 356| 0| 357| 0| let testClassFile = testModule.appending(RelativePath("\(moduleName)Tests.swift")) 358| 0| switch packageType { 359| 0| case .systemModule, .empty: break 360| 0| case .library: 361| 0| try writeLibraryTestsFile(testClassFile) 362| 0| case .executable: 363| 0| try writeExecutableTestsFile(testClassFile) 364| 0| } 365| 0| 366| 0| try writePackageFile(testModule.appending(component: "XCTestManifests.swift")) { stream in 367| 0| stream <<< """ 368| 0| import XCTest 369| 0| 370| 0| #if !canImport(ObjectiveC) 371| 0| public func allTests() -> [XCTestCaseEntry] { 372| 0| return [ 373| 0| testCase(\(moduleName)Tests.allTests), 374| 0| ] 375| 0| } 376| 0| #endif 377| 0| 378| 0| """ 379| 0| } 380| 0| } 381| | 382| |} 383| | 384| |// Private helpers 385| | 386| |private enum InitError: Swift.Error { 387| | case manifestAlreadyExists 388| |} 389| | 390| |extension InitError: CustomStringConvertible { 391| 0| var description: String { 392| 0| switch self { 393| 0| case .manifestAlreadyExists: 394| 0| return "a manifest file already exists in this directory" 395| 0| } 396| 0| } 397| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/ManagedDependency.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import PackageGraph 13| |import PackageModel 14| |import SourceControl 15| |import SPMUtility 16| | 17| |/// An individual managed dependency. 18| |/// 19| |/// Each dependency will have a checkout containing the sources at a 20| |/// particular revision, and may have an associated version. 21| |public final class ManagedDependency: JSONMappable, JSONSerializable, CustomStringConvertible { 22| | 23| | /// Represents the state of the managed dependency. 24| | public enum State: Equatable, CustomStringConvertible { 25| | 26| | /// The dependency is a managed checkout. 27| | case checkout(CheckoutState) 28| | 29| | /// The dependency is in edited state. 30| | /// 31| | /// If the path is non-nil, the dependency is managed by a user and is 32| | /// located at the path. In other words, this dependency is being used 33| | /// for top of the tree style development. 34| | case edited(AbsolutePath?) 35| | 36| | // The dependency is a local package. 37| | case local 38| | 39| | /// Returns true if state is checkout. 40| 0| var isCheckout: Bool { 41| 0| if case .checkout = self { return true } 42| 0| return false 43| 0| } 44| | 45| 0| public var description: String { 46| 0| switch self { 47| 0| case .checkout(let checkout): 48| 0| return "\(checkout)" 49| 0| case .edited: 50| 0| return "edited" 51| 0| case .local: 52| 0| return "local" 53| 0| } 54| 0| } 55| | } 56| | 57| | /// The package reference. 58| | public let packageRef: PackageReference 59| | 60| | /// The state of the managed dependency. 61| | public let state: State 62| | 63| | /// The checked out path of the dependency on disk, relative to the workspace checkouts path. 64| | public let subpath: RelativePath 65| | 66| | /// A dependency which in editable state is based on a dependency from 67| | /// which it edited from. 68| | /// 69| | /// This information is useful so it can be restored when users 70| | /// unedit a package. 71| | var basedOn: ManagedDependency? 72| | 73| | init( 74| | packageRef: PackageReference, 75| | subpath: RelativePath, 76| | checkoutState: CheckoutState 77| 0| ) { 78| 0| self.packageRef = packageRef 79| 0| self.state = .checkout(checkoutState) 80| 0| self.basedOn = nil 81| 0| self.subpath = subpath 82| 0| } 83| | 84| | /// Create a dependency present locally on the filesystem. 85| | static func local( 86| | packageRef: PackageReference 87| 0| ) -> ManagedDependency { 88| 0| return ManagedDependency( 89| 0| packageRef: packageRef, 90| 0| state: .local, 91| 0| // FIXME: This is just a fake entry, we should fix it. 92| 0| subpath: RelativePath(packageRef.identity), 93| 0| basedOn: nil 94| 0| ) 95| 0| } 96| | 97| | private init( 98| | packageRef: PackageReference, 99| | state: State, 100| | subpath: RelativePath, 101| | basedOn: ManagedDependency? 102| 0| ) { 103| 0| self.packageRef = packageRef 104| 0| self.subpath = subpath 105| 0| self.basedOn = basedOn 106| 0| self.state = state 107| 0| } 108| | 109| | private init( 110| | basedOn dependency: ManagedDependency, 111| | subpath: RelativePath, 112| | unmanagedPath: AbsolutePath? 113| 0| ) { 114| 0| assert(dependency.state.isCheckout) 115| 0| self.basedOn = dependency 116| 0| self.packageRef = dependency.packageRef 117| 0| self.subpath = subpath 118| 0| self.state = .edited(unmanagedPath) 119| 0| } 120| | 121| | /// Create an editable managed dependency based on a dependency which 122| | /// was *not* in edit state. 123| | /// 124| | /// - Parameters: 125| | /// - subpath: The subpath inside the editables directory. 126| | /// - unmanagedPath: A custom absolute path instead of the subpath. 127| 0| func editedDependency(subpath: RelativePath, unmanagedPath: AbsolutePath?) -> ManagedDependency { 128| 0| return ManagedDependency(basedOn: self, subpath: subpath, unmanagedPath: unmanagedPath) 129| 0| } 130| | 131| 0| public init(json: JSON) throws { 132| 0| self.packageRef = try json.get("packageRef") 133| 0| self.subpath = try RelativePath(json.get("subpath")) 134| 0| self.basedOn = json.get("basedOn") 135| 0| self.state = try json.get("state") 136| 0| } 137| | 138| 0| public func toJSON() -> JSON { 139| 0| return .init([ 140| 0| "packageRef": packageRef.toJSON(), 141| 0| "subpath": subpath, 142| 0| "basedOn": basedOn.toJSON(), 143| 0| "state": state, 144| 0| ]) 145| 0| } 146| | 147| 0| public var description: String { 148| 0| return "" 149| 0| } 150| |} 151| | 152| |extension ManagedDependency.State: JSONMappable, JSONSerializable { 153| 0| public func toJSON() -> JSON { 154| 0| switch self { 155| 0| case .checkout(let checkoutState): 156| 0| return .init([ 157| 0| "name": "checkout", 158| 0| "checkoutState": checkoutState, 159| 0| ]) 160| 0| case .edited(let path): 161| 0| return .init([ 162| 0| "name": "edited", 163| 0| "path": path.toJSON(), 164| 0| ]) 165| 0| case .local: 166| 0| return .init([ 167| 0| "name": "local", 168| 0| ]) 169| 0| } 170| 0| } 171| | 172| 0| public init(json: JSON) throws { 173| 0| let name: String = try json.get("name") 174| 0| switch name { 175| 0| case "checkout": 176| 0| self = try .checkout(json.get("checkoutState")) 177| 0| case "edited": 178| 0| let path: String? = json.get("path") 179| 0| self = .edited(path.map({AbsolutePath($0)})) 180| 0| case "local": 181| 0| self = .local 182| 0| default: 183| 0| throw JSON.MapError.custom(key: nil, message: "Invalid state \(name)") 184| 0| } 185| 0| } 186| |} 187| | 188| |/// Represents a collection of managed dependency which are persisted on disk. 189| |public final class ManagedDependencies: SimplePersistanceProtocol { 190| | 191| | enum Error: Swift.Error, CustomStringConvertible { 192| | case dependencyNotFound(name: String) 193| | 194| 0| var description: String { 195| 0| switch self { 196| 0| case .dependencyNotFound(let name): 197| 0| return "Could not find dependency '\(name)'" 198| 0| } 199| 0| } 200| | } 201| | 202| | /// The schema version of the resolved file. 203| | /// 204| | /// * 2: Package identity. 205| | /// * 1: Initial version. 206| | static let schemaVersion: Int = 2 207| | 208| | /// The current state of managed dependencies. 209| | /// 210| | /// Key -> package URL. 211| | private var dependencyMap: [String: ManagedDependency] 212| | 213| | /// Path to the state file. 214| | let statePath: AbsolutePath 215| | 216| | /// persistence helper 217| | let persistence: SimplePersistence 218| | 219| 0| init(dataPath: AbsolutePath, fileSystem: FileSystem) { 220| 0| let statePath = dataPath.appending(component: "dependencies-state.json") 221| 0| 222| 0| self.dependencyMap = [:] 223| 0| self.statePath = statePath 224| 0| self.persistence = SimplePersistence( 225| 0| fileSystem: fileSystem, 226| 0| schemaVersion: ManagedDependencies.schemaVersion, 227| 0| statePath: statePath) 228| 0| 229| 0| // Load the state from disk, if possible. 230| 0| // 231| 0| // If the disk operation here fails, we ignore the error here. 232| 0| // This means if managed dependencies data is corrupted or out of date, 233| 0| // clients will not see the old data and managed dependencies will be 234| 0| // reset. However there could be other errors, like permission issues, 235| 0| // these errors will also be ignored but will surface when clients try 236| 0| // to save the state. 237| 0| do { 238| 0| try self.persistence.restoreState(self) 239| 0| } catch { 240| 0| // FIXME: We should emit a warning here using the diagnostic engine. 241| 0| print("\(error)") 242| 0| } 243| 0| } 244| | 245| | public subscript(forURL url: String) -> ManagedDependency? { 246| 0| get { 247| 0| return dependencyMap[url] 248| 0| } 249| 0| set { 250| 0| dependencyMap[url] = newValue 251| 0| } 252| | } 253| | 254| | /// Returns the dependency given a name or identity. 255| 0| func dependency(forNameOrIdentity nameOrIdentity: String) throws -> ManagedDependency { 256| 0| for value in values { 257| 0| if value.packageRef.name == nameOrIdentity { 258| 0| return value 259| 0| } else if value.packageRef.identity == nameOrIdentity.lowercased() { 260| 0| return value 261| 0| } 262| 0| } 263| 0| throw Error.dependencyNotFound(name: nameOrIdentity) 264| 0| } 265| | 266| 0| func dependency(forIdentity identity: String) -> ManagedDependency? { 267| 0| return values.first(where: { $0.packageRef.identity == identity }) 268| 0| } 269| | 270| 0| func reset() throws { 271| 0| dependencyMap = [:] 272| 0| try saveState() 273| 0| } 274| | 275| 0| func saveState() throws { 276| 0| try self.persistence.saveState(self) 277| 0| } 278| | 279| | /// Returns true if the state file exists on the filesystem. 280| 0| public func stateFileExists() -> Bool { 281| 0| return persistence.stateFileExists() 282| 0| } 283| | 284| 0| public var values: AnySequence { 285| 0| return AnySequence(dependencyMap.values) 286| 0| } 287| | 288| 0| public func restore(from json: JSON) throws { 289| 0| self.dependencyMap = try Dictionary(items: 290| 0| json.get("dependencies").map({ ($0.packageRef.path, $0) }) 291| 0| ) 292| 0| } 293| | 294| 0| public func toJSON() -> JSON { 295| 0| return JSON([ 296| 0| "dependencies": values.toJSON(), 297| 0| ]) 298| 0| } 299| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/PinsStore.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import SourceControl 14| |import PackageModel 15| |import PackageGraph 16| | 17| |public final class PinsStore { 18| | public struct Pin { 19| | /// The package reference of the pinned dependency. 20| | public let packageRef: PackageReference 21| | 22| | /// The pinned state. 23| | public let state: CheckoutState 24| | 25| | init( 26| | packageRef: PackageReference, 27| | state: CheckoutState 28| 0| ) { 29| 0| self.packageRef = packageRef 30| 0| self.state = state 31| 0| } 32| | } 33| | 34| | /// The schema version of the resolved file. 35| | /// 36| | /// * 1: Initial version. 37| | static let schemaVersion: Int = 1 38| | 39| | /// The path to the pins file. 40| | fileprivate let pinsFile: AbsolutePath 41| | 42| | /// The filesystem to manage the pin file on. 43| | fileprivate var fileSystem: FileSystem 44| | 45| | /// The pins map. 46| | /// 47| | /// Key -> Package Identity. 48| | fileprivate(set) var pinsMap: [String: Pin] 49| | 50| | /// The current pins. 51| 0| public var pins: AnySequence { 52| 0| return AnySequence(pinsMap.values) 53| 0| } 54| | 55| | fileprivate let persistence: SimplePersistence 56| | 57| | /// Create a new pins store. 58| | /// 59| | /// - Parameters: 60| | /// - pinsFile: Path to the pins file. 61| | /// - fileSystem: The filesystem to manage the pin file on. 62| 0| public init(pinsFile: AbsolutePath, fileSystem: FileSystem) throws { 63| 0| self.pinsFile = pinsFile 64| 0| self.fileSystem = fileSystem 65| 0| self.persistence = SimplePersistence( 66| 0| fileSystem: fileSystem, 67| 0| schemaVersion: PinsStore.schemaVersion, 68| 0| statePath: pinsFile, 69| 0| prettyPrint: true) 70| 0| pinsMap = [:] 71| 0| do { 72| 0| _ = try self.persistence.restoreState(self) 73| 0| } catch SimplePersistence.Error.restoreFailure { 74| 0| throw WorkspaceDiagnostics.MalformedPackageResolved() 75| 0| } 76| 0| } 77| | 78| | /// Pin a repository at a version. 79| | /// 80| | /// This method does not automatically write to state file. 81| | /// 82| | /// - Parameters: 83| | /// - packageRef: The package reference to pin. 84| | /// - state: The state to pin at. 85| | public func pin( 86| | packageRef: PackageReference, 87| | state: CheckoutState 88| 0| ) { 89| 0| pinsMap[packageRef.identity] = Pin( 90| 0| packageRef: packageRef, 91| 0| state: state 92| 0| ) 93| 0| } 94| | 95| | /// Add a pin. 96| | /// 97| | /// This will replace any previous pin with same package name. 98| 0| public func add(_ pin: Pin) { 99| 0| pinsMap[pin.packageRef.identity] = pin 100| 0| } 101| | 102| | /// Pin a managed dependency at its checkout state. 103| | /// 104| | /// This method does nothing if the dependency is in edited state. 105| 0| func pin(_ dependency: ManagedDependency) { 106| 0| 107| 0| // Get the checkout state. 108| 0| let checkoutState: CheckoutState 109| 0| switch dependency.state { 110| 0| case .checkout(let state): 111| 0| checkoutState = state 112| 0| case .edited, .local: 113| 0| return 114| 0| } 115| 0| 116| 0| self.pin( 117| 0| packageRef: dependency.packageRef, 118| 0| state: checkoutState) 119| 0| } 120| | 121| | /// Unpin all of the currently pinnned dependencies. 122| | /// 123| | /// This method does not automatically write to state file. 124| 0| public func unpinAll() { 125| 0| // Reset the pins map. 126| 0| pinsMap = [:] 127| 0| } 128| | 129| | /// Creates constraints based on the pins in the store. 130| 0| public func createConstraints() -> [RepositoryPackageConstraint] { 131| 0| return pins.map({ pin in 132| 0| return RepositoryPackageConstraint( 133| 0| container: pin.packageRef, requirement: pin.state.requirement()) 134| 0| }) 135| 0| } 136| |} 137| | 138| |/// Persistence. 139| |extension PinsStore: SimplePersistanceProtocol { 140| | 141| 0| public func saveState() throws { 142| 0| if pinsMap.isEmpty { 143| 0| // Remove the pins file if there are zero pins to save. 144| 0| // 145| 0| // This can happen if all dependencies are path-based or edited 146| 0| // dependencies. 147| 0| return try fileSystem.removeFileTree(pinsFile) 148| 0| } 149| 0| 150| 0| try self.persistence.saveState(self) 151| 0| } 152| | 153| 0| public func restore(from json: JSON) throws { 154| 0| self.pinsMap = try Dictionary(items: json.get("pins").map({ ($0.packageRef.identity, $0) })) 155| 0| } 156| | 157| | /// Saves the current state of pins. 158| 0| public func toJSON() -> JSON { 159| 0| return JSON([ 160| 0| "pins": pins.sorted(by: { $0.packageRef.identity < $1.packageRef.identity }).toJSON(), 161| 0| ]) 162| 0| } 163| |} 164| | 165| |// JSON. 166| |extension PinsStore.Pin: JSONMappable, JSONSerializable, Equatable { 167| | /// Create an instance from JSON data. 168| 0| public init(json: JSON) throws { 169| 0| let name: String? = json.get("package") 170| 0| let url: String = try json.get("repositoryURL") 171| 0| let ref = PackageReference(identity: PackageReference.computeIdentity(packageURL: url), path: url) 172| 0| self.packageRef = name.flatMap(ref.with(newName:)) ?? ref 173| 0| self.state = try json.get("state") 174| 0| } 175| | 176| | /// Convert the pin to JSON. 177| 0| public func toJSON() -> JSON { 178| 0| return .init([ 179| 0| "package": packageRef.name.toJSON(), 180| 0| "repositoryURL": packageRef.path, 181| 0| "state": state, 182| 0| ]) 183| 0| } 184| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/ToolsVersionWriter.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import PackageLoading 14| |import SPMUtility 15| | 16| |/// Write the given tools version at the given path. 17| |/// 18| |/// - Parameters: 19| |/// - path: The path of the package. 20| |/// - version: The version to write. 21| 0|public func writeToolsVersion(at path: AbsolutePath, version: ToolsVersion, fs: FileSystem) throws { 22| 0| let file = path.appending(component: Manifest.filename) 23| 0| assert(fs.isFile(file), "Tools version file not present") 24| 0| 25| 0| // Get the current contents of the file. 26| 0| let contents = try fs.readFileContents(file) 27| 0| 28| 0| let stream = BufferedOutputByteStream() 29| 0| // Write out the tools version. 30| 0| stream <<< "// swift-tools-version:" <<< Format.asJSON(version.major) <<< "." <<< Format.asJSON(version.minor) 31| 0| // Write patch version only if its not zero. 32| 0| if version.patch != 0 { 33| 0| stream <<< "." <<< Format.asJSON(version.patch) 34| 0| } 35| 0| stream <<< "\n" 36| 0| // Append the file contents except for version specifier line. 37| 0| stream <<< ToolsVersionLoader.split(contents).rest 38| 0| 39| 0| try fs.writeFileContents(file, bytes: stream.bytes) 40| 0|} 41| | 42| |extension ToolsVersion { 43| | 44| | /// Returns the tools version with zeroed patch number. 45| 0| public var zeroedPatch: ToolsVersion { 46| 0| return ToolsVersion(version: Version(major, minor, 0)) 47| 0| } 48| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/UserToolchain.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import POSIX 12| | 13| |import Basic 14| |import Build 15| |import PackageLoading 16| |import protocol Build.Toolchain 17| |import SPMUtility 18| | 19| |#if os(macOS) 20| |private let whichArgs: [String] = ["xcrun", "--find"] 21| |#else 22| |private let whichArgs = ["which"] 23| |#endif 24| | 25| |/// Concrete object for manifest resource provider. 26| |public struct UserManifestResources: ManifestResourceProvider { 27| | public let swiftCompiler: AbsolutePath 28| | public let libDir: AbsolutePath 29| | public let sdkRoot: AbsolutePath? 30| | 31| | public init( 32| | swiftCompiler: AbsolutePath, 33| | libDir: AbsolutePath, 34| | sdkRoot: AbsolutePath? = nil 35| 0| ) { 36| 0| self.swiftCompiler = swiftCompiler 37| 0| self.libDir = libDir 38| 0| self.sdkRoot = sdkRoot 39| 0| } 40| |} 41| | 42| |// FIXME: This is messy and needs a redesign. 43| |public final class UserToolchain: Toolchain { 44| | 45| | /// The manifest resource provider. 46| | public let manifestResources: ManifestResourceProvider 47| | 48| | /// Path of the `swiftc` compiler. 49| | public let swiftCompiler: AbsolutePath 50| | 51| | public let extraCCFlags: [String] 52| | 53| | public let extraSwiftCFlags: [String] 54| | 55| 0| public var extraCPPFlags: [String] { 56| 0| return destination.extraCPPFlags 57| 0| } 58| | 59| | /// Path of the `swift` interpreter. 60| 0| public var swiftInterpreter: AbsolutePath { 61| 0| return swiftCompiler.parentDirectory.appending(component: "swift") 62| 0| } 63| | 64| | /// Path to the xctest utility. 65| | /// 66| | /// This is only present on macOS. 67| | public let xctest: AbsolutePath? 68| | 69| | /// Path to llbuild. 70| | public let llbuild: AbsolutePath 71| | 72| | /// The compilation destination object. 73| | public let destination: Destination 74| | 75| | /// Search paths from the PATH environment variable. 76| | let envSearchPaths: [AbsolutePath] 77| | 78| | /// Returns the runtime library for the given sanitizer. 79| 0| public func runtimeLibrary(for sanitizer: Sanitizer) throws -> AbsolutePath { 80| 0| // FIXME: This is only for SwiftPM development time support. It is OK 81| 0| // for now but we shouldn't need to resolve the symlink. We need to lay 82| 0| // down symlinks to runtimes in our fake toolchain as part of the 83| 0| // bootstrap script. 84| 0| let swiftCompiler = resolveSymlinks(self.swiftCompiler) 85| 0| 86| 0| let runtime = swiftCompiler.appending( 87| 0| RelativePath("../../lib/swift/clang/lib/darwin/libclang_rt.\(sanitizer.shortName)_osx_dynamic.dylib")) 88| 0| 89| 0| // Ensure that the runtime is present. 90| 0| guard localFileSystem.exists(runtime) else { 91| 0| throw InvalidToolchainDiagnostic("Missing runtime for \(sanitizer) sanitizer") 92| 0| } 93| 0| 94| 0| return runtime 95| 0| } 96| | 97| | /// Determines the Swift compiler paths for compilation and manifest parsing. 98| 0| private static func determineSwiftCompilers(binDir: AbsolutePath, lookup: (String) -> AbsolutePath?) throws -> (compile: AbsolutePath, manifest: AbsolutePath) { 99| 0| func validateCompiler(at path: AbsolutePath?) throws { 100| 0| guard let path = path else { return } 101| 0| guard localFileSystem.isExecutableFile(path) else { 102| 0| throw InvalidToolchainDiagnostic("could not find the `swiftc` at expected path \(path)") 103| 0| } 104| 0| } 105| 0| 106| 0| // Get overrides. 107| 0| let SWIFT_EXEC_MANIFEST = lookup("SWIFT_EXEC_MANIFEST") 108| 0| let SWIFT_EXEC = lookup("SWIFT_EXEC") 109| 0| 110| 0| // Validate the overrides. 111| 0| try validateCompiler(at: SWIFT_EXEC) 112| 0| try validateCompiler(at: SWIFT_EXEC_MANIFEST) 113| 0| 114| 0| // We require there is at least one valid swift compiler, either in the 115| 0| // bin dir or SWIFT_EXEC. 116| 0| let resolvedBinDirCompiler: AbsolutePath 117| 0| let binDirCompiler = binDir.appending(component: "swiftc") 118| 0| if localFileSystem.isExecutableFile(binDirCompiler) { 119| 0| resolvedBinDirCompiler = binDirCompiler 120| 0| } else if let SWIFT_EXEC = SWIFT_EXEC { 121| 0| resolvedBinDirCompiler = SWIFT_EXEC 122| 0| } else { 123| 0| throw InvalidToolchainDiagnostic("could not find the `swiftc` at expected path \(binDirCompiler)") 124| 0| } 125| 0| 126| 0| // The compiler for compilation tasks is SWIFT_EXEC or the bin dir compiler. 127| 0| // The compiler for manifest is either SWIFT_EXEC_MANIFEST or the bin dir compiler. 128| 0| return (SWIFT_EXEC ?? resolvedBinDirCompiler, SWIFT_EXEC_MANIFEST ?? resolvedBinDirCompiler) 129| 0| } 130| | 131| 0| private static func lookup(variable: String, searchPaths: [AbsolutePath]) -> AbsolutePath? { 132| 0| return lookupExecutablePath(filename: getenv(variable), searchPaths: searchPaths) 133| 0| } 134| | 135| | /// Environment to use when looking up tools. 136| | private let processEnvironment: [String: String] 137| | 138| | /// Returns the path to clang compiler tool. 139| 0| public func getClangCompiler() throws -> AbsolutePath { 140| 0| // Check if we already computed. 141| 0| if let clang = _clangCompiler { 142| 0| return clang 143| 0| } 144| 0| 145| 0| // Check in the environment variable first. 146| 0| if let toolPath = UserToolchain.lookup(variable: "CC", searchPaths: envSearchPaths) { 147| 0| _clangCompiler = toolPath 148| 0| return toolPath 149| 0| } 150| 0| 151| 0| // Otherwise, lookup the tool on the system. 152| 0| let arguments = whichArgs + ["clang"] 153| 0| let foundPath = try Process.checkNonZeroExit(arguments: arguments, environment: processEnvironment).spm_chomp() 154| 0| guard !foundPath.isEmpty else { 155| 0| throw InvalidToolchainDiagnostic("could not find clang") 156| 0| } 157| 0| let toolPath = try AbsolutePath(validating: foundPath) 158| 0| 159| 0| // If we found clang using xcrun, assume the vendor is Apple. 160| 0| // FIXME: This might not be the best way to determine this. 161| 0| #if os(macOS) 162| 0| __isClangCompilerVendorApple = true 163| 0| #endif 164| 0| 165| 0| _clangCompiler = toolPath 166| 0| return toolPath 167| 0| } 168| | private var _clangCompiler: AbsolutePath? 169| | private var __isClangCompilerVendorApple: Bool? 170| | 171| 0| public func _isClangCompilerVendorApple() throws -> Bool? { 172| 0| // The boolean gets computed as a side-effect of lookup for clang compiler. 173| 0| _ = try getClangCompiler() 174| 0| return __isClangCompilerVendorApple 175| 0| } 176| | 177| | /// Returns the path to llvm-cov tool. 178| 0| public func getLLVMCov() throws -> AbsolutePath { 179| 0| let toolPath = destination.binDir.appending(component: "llvm-cov") 180| 0| guard localFileSystem.isExecutableFile(toolPath) else { 181| 0| throw InvalidToolchainDiagnostic("could not find llvm-cov at expected path \(toolPath)") 182| 0| } 183| 0| return toolPath 184| 0| } 185| | 186| | /// Returns the path to llvm-prof tool. 187| 0| public func getLLVMProf() throws -> AbsolutePath { 188| 0| let toolPath = destination.binDir.appending(component: "llvm-profdata") 189| 0| guard localFileSystem.isExecutableFile(toolPath) else { 190| 0| throw InvalidToolchainDiagnostic("could not find llvm-profdata at expected path \(toolPath)") 191| 0| } 192| 0| return toolPath 193| 0| } 194| | 195| 0| public init(destination: Destination, environment: [String: String] = Process.env) throws { 196| 0| self.destination = destination 197| 0| self.processEnvironment = environment 198| 0| 199| 0| // Get the search paths from PATH. 200| 0| let searchPaths = getEnvSearchPaths( 201| 0| pathString: getenv("PATH"), currentWorkingDirectory: localFileSystem.currentWorkingDirectory) 202| 0| 203| 0| self.envSearchPaths = searchPaths 204| 0| 205| 0| // Get the binDir from destination. 206| 0| let binDir = destination.binDir 207| 0| 208| 0| let swiftCompilers = try UserToolchain.determineSwiftCompilers(binDir: binDir, lookup: { UserToolchain.lookup(variable: $0, searchPaths: searchPaths) }) 209| 0| self.swiftCompiler = swiftCompilers.compile 210| 0| 211| 0| // Look for llbuild in bin dir. 212| 0| llbuild = binDir.appending(component: "swift-build-tool") 213| 0| guard localFileSystem.exists(llbuild) else { 214| 0| throw InvalidToolchainDiagnostic("could not find `llbuild` at expected path \(llbuild)") 215| 0| } 216| 0| 217| 0| 218| 0| // We require xctest to exist on macOS. 219| 0| #if os(macOS) 220| 0| // FIXME: We should have some general utility to find tools. 221| 0| let xctestFindArgs = ["xcrun", "--sdk", "macosx", "--find", "xctest"] 222| 0| self.xctest = try AbsolutePath(validating: Process.checkNonZeroExit(arguments: xctestFindArgs, environment: environment).spm_chomp()) 223| 0| #else 224| 0| self.xctest = nil 225| 0| #endif 226| 0| 227| 0| self.extraSwiftCFlags = [ 228| 0| "-sdk", destination.sdk.pathString 229| 0| ] + destination.extraSwiftCFlags 230| 0| 231| 0| self.extraCCFlags = [ 232| 0| destination.target.isDarwin() ? "-isysroot" : "--sysroot", destination.sdk.pathString 233| 0| ] + destination.extraCCFlags 234| 0| 235| 0| // Compute the path of directory containing the PackageDescription libraries. 236| 0| var pdLibDir = binDir.parentDirectory.appending(components: "lib", "swift", "pm") 237| 0| 238| 0| // Look for an override in the env. 239| 0| if let pdLibDirEnvStr = getenv("SWIFTPM_PD_LIBS") { 240| 0| // We pick the first path which exists in a colon seperated list. 241| 0| let paths = pdLibDirEnvStr.split(separator: ":").map(String.init) 242| 0| for pathString in paths { 243| 0| if let path = try? AbsolutePath(validating: pathString), localFileSystem.exists(path) { 244| 0| pdLibDir = path 245| 0| break 246| 0| } 247| 0| } 248| 0| } 249| 0| 250| 0| manifestResources = UserManifestResources( 251| 0| swiftCompiler: swiftCompilers.manifest, 252| 0| libDir: pdLibDir, 253| 0| sdkRoot: self.destination.sdk 254| 0| ) 255| 0| } 256| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Workspace/Workspace.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import Foundation 13| |import PackageLoading 14| |import PackageModel 15| |import PackageGraph 16| |import SourceControl 17| |import SPMUtility 18| | 19| |/// The delegate interface used by the workspace to report status information. 20| |public protocol WorkspaceDelegate: class { 21| | 22| | /// The workspace has started fetching this repository. 23| | func fetchingWillBegin(repository: String) 24| | 25| | /// The workspace has finished fetching this repository. 26| | func fetchingDidFinish(repository: String, diagnostic: Diagnostic?) 27| | 28| | /// The workspace has started updating this repository. 29| | func repositoryWillUpdate(_ repository: String) 30| | 31| | /// The workspace has finished updating this repository. 32| | func repositoryDidUpdate(_ repository: String) 33| | 34| | /// The workspace has finished updating and all the dependencies are already up-to-date. 35| | func dependenciesUpToDate() 36| | 37| | /// The workspace has started cloning this repository. 38| | func cloning(repository: String) 39| | 40| | /// The workspace is checking out a repository. 41| | func checkingOut(repository: String, atReference reference: String, to path: AbsolutePath) 42| | 43| | /// The workspace is removing this repository because it is no longer needed. 44| | func removing(repository: String) 45| | 46| | /// Called when the resolver is about to be run. 47| | func willResolveDependencies() 48| |} 49| | 50| |public extension WorkspaceDelegate { 51| 0| func checkingOut(repository: String, atReference: String, to path: AbsolutePath) {} 52| 0| func repositoryWillUpdate(_ repository: String) {} 53| 0| func repositoryDidUpdate(_ repository: String) {} 54| 0| func willResolveDependencies() {} 55| 0| func dependenciesUpToDate() {} 56| |} 57| | 58| |private class WorkspaceResolverDelegate: DependencyResolverDelegate { 59| | typealias Identifier = RepositoryPackageContainer.Identifier 60| |} 61| | 62| |private class WorkspaceRepositoryManagerDelegate: RepositoryManagerDelegate { 63| | unowned let workspaceDelegate: WorkspaceDelegate 64| | 65| 0| init(workspaceDelegate: WorkspaceDelegate) { 66| 0| self.workspaceDelegate = workspaceDelegate 67| 0| } 68| | 69| 0| func fetchingWillBegin(handle: RepositoryManager.RepositoryHandle) { 70| 0| workspaceDelegate.fetchingWillBegin(repository: handle.repository.url) 71| 0| } 72| | 73| 0| func fetchingDidFinish(handle: RepositoryManager.RepositoryHandle, error: Swift.Error?) { 74| 0| let diagnostic: Diagnostic? = error.flatMap({ 75| 0| let engine = DiagnosticsEngine() 76| 0| engine.emit($0) 77| 0| return engine.diagnostics.first 78| 0| }) 79| 0| workspaceDelegate.fetchingDidFinish(repository: handle.repository.url, diagnostic: diagnostic) 80| 0| } 81| | 82| 0| func handleWillUpdate(handle: RepositoryManager.RepositoryHandle) { 83| 0| workspaceDelegate.repositoryWillUpdate(handle.repository.url) 84| 0| } 85| | 86| 0| func handleDidUpdate(handle: RepositoryManager.RepositoryHandle) { 87| 0| workspaceDelegate.repositoryDidUpdate(handle.repository.url) 88| 0| } 89| |} 90| | 91| |fileprivate enum PackageResolver { 92| | typealias _PubgrubResolver = PubgrubDependencyResolver 93| | typealias _DependencyResolver = DependencyResolver 94| | 95| | case pubgrub(_PubgrubResolver) 96| | case legacy(_DependencyResolver) 97| | 98| | typealias Identifier = PackageReference 99| | typealias Constraint = PackageContainerConstraint 100| | 101| 0| func resolve(constraints: [Constraint], pins: [Constraint]) throws -> [(container: Identifier, binding: BoundVersion)] { 102| 0| switch self { 103| 0| case .pubgrub(let resolver): 104| 0| return try resolver.solve(constraints: constraints, pins: pins) 105| 0| case .legacy(let resolver): 106| 0| return try resolver.resolve(constraints: constraints, pins: pins) 107| 0| } 108| 0| } 109| | 110| 0| func resolve(dependencies: [Constraint], pins: [Constraint]) -> _DependencyResolver.Result { 111| 0| switch self { 112| 0| case .pubgrub(let resolver): 113| 0| return resolver.solve(dependencies: dependencies, pins: pins) 114| 0| case .legacy(let resolver): 115| 0| return resolver.resolve(dependencies: dependencies, pins: pins) 116| 0| } 117| 0| } 118| |} 119| | 120| |/// A workspace represents the state of a working project directory. 121| |/// 122| |/// The workspace is responsible for managing the persistent working state of a 123| |/// project directory (e.g., the active set of checked out repositories) and for 124| |/// coordinating the changes to that state. 125| |/// 126| |/// This class glues together the basic facilities provided by the dependency 127| |/// resolution, source control, and package graph loading subsystems into a 128| |/// cohesive interface for exposing the high-level operations for the package 129| |/// manager to maintain working package directories. 130| |/// 131| |/// This class does *not* support concurrent operations. 132| |public class Workspace { 133| | /// A struct representing all the current manifests (root + external) in a package graph. 134| | struct DependencyManifests { 135| | /// The package graph root. 136| | let root: PackageGraphRoot 137| | 138| | /// The dependency manifests in the transitive closure of root manifest. 139| | private let dependencies: [(manifest: Manifest, dependency: ManagedDependency)] 140| | 141| | let workspace: Workspace 142| | 143| 0| fileprivate init(root: PackageGraphRoot, dependencies: [(Manifest, ManagedDependency)], workspace: Workspace) { 144| 0| self.root = root 145| 0| self.dependencies = dependencies 146| 0| self.workspace = workspace 147| 0| } 148| | 149| | /// Find a manifest given its name. 150| 0| func lookup(manifest name: String) -> Manifest? { 151| 0| return dependencies.first(where: { $0.manifest.name == name })?.manifest 152| 0| } 153| | 154| | /// Returns all manifests contained in DependencyManifests. 155| 0| func allManifests() -> [Manifest] { 156| 0| return dependencies.map({ $0.manifest }) 157| 0| } 158| | 159| | /// Computes the identities which are declared in the manifests but aren't present in dependencies. 160| 0| func missingPackageURLs() -> Set { 161| 0| return computePackageURLs().missing 162| 0| } 163| | 164| 0| func computePackageURLs() -> (required: Set, missing: Set) { 165| 0| let manifestsMap = Dictionary(items: 166| 0| root.manifests.map({ ($0.name.lowercased(), $0) }) + 167| 0| dependencies.map({ (PackageReference.computeIdentity(packageURL: $0.manifest.url), $0.manifest) })) 168| 0| 169| 0| let inputIdentities = root.manifests.map({ 170| 0| PackageReference(identity: $0.name.lowercased(), path: $0.url) 171| 0| }) + root.dependencies.map({ 172| 0| let url = workspace.config.mirroredURL(forURL: $0.url) 173| 0| let identity = PackageReference.computeIdentity(packageURL: url) 174| 0| return PackageReference(identity: identity, path: url) 175| 0| }) 176| 0| 177| 0| var requiredIdentities = transitiveClosure(inputIdentities) { identity in 178| 0| guard let manifest = manifestsMap[identity.identity] else { return [] } 179| 0| return manifest.dependencies.map({ 180| 0| let url = workspace.config.mirroredURL(forURL: $0.url) 181| 0| let identity = PackageReference.computeIdentity(packageURL: url) 182| 0| return PackageReference(identity: identity, path: url) 183| 0| }) 184| 0| } 185| 0| requiredIdentities.formUnion(inputIdentities) 186| 0| 187| 0| let availableIdentities: Set = Set(manifestsMap.map({ 188| 0| let url = workspace.config.mirroredURL(forURL: $0.1.url) 189| 0| return PackageReference(identity: $0.key, path: url) 190| 0| })) 191| 0| // We should never have loaded a manifest we don't need. 192| 0| assert(availableIdentities.isSubset(of: requiredIdentities), "\(availableIdentities) | \(requiredIdentities)") 193| 0| // These are the missing package identities. 194| 0| let missingIdentities = requiredIdentities.subtracting(availableIdentities) 195| 0| 196| 0| return (requiredIdentities, missingIdentities) 197| 0| } 198| | 199| | /// Returns constraints of the dependencies, including edited package constraints. 200| 0| fileprivate func dependencyConstraints() -> [RepositoryPackageConstraint] { 201| 0| var allConstraints = [RepositoryPackageConstraint]() 202| 0| 203| 0| for (externalManifest, managedDependency) in dependencies { 204| 0| 205| 0| switch managedDependency.state { 206| 0| case .edited: 207| 0| // FIXME: We shouldn't need to construct a new package reference object here. 208| 0| // We should get the correct one from managed dependency object. 209| 0| let ref = PackageReference( 210| 0| identity: managedDependency.packageRef.identity, 211| 0| path: managedDependency.packageRef.path, 212| 0| isLocal: true 213| 0| ) 214| 0| // Add an unversioned constraint if the dependency is in edited state. 215| 0| let constraint = RepositoryPackageConstraint( 216| 0| container: ref, 217| 0| requirement: .unversioned) 218| 0| allConstraints.append(constraint) 219| 0| 220| 0| case .checkout, .local: 221| 0| // For checkouts, add all the constraints in the manifest. 222| 0| allConstraints += externalManifest.dependencyConstraints(config: workspace.config) 223| 0| } 224| 0| } 225| 0| return allConstraints 226| 0| } 227| | 228| | // FIXME: @testable(internal) 229| | /// Returns a list of constraints for all 'edited' package. 230| 0| func editedPackagesConstraints() -> [RepositoryPackageConstraint] { 231| 0| var constraints = [RepositoryPackageConstraint]() 232| 0| 233| 0| for (_, managedDependency) in dependencies { 234| 0| switch managedDependency.state { 235| 0| case .checkout, .local: continue 236| 0| case .edited: break 237| 0| } 238| 0| // FIXME: We shouldn't need to construct a new package reference object here. 239| 0| // We should get the correct one from managed dependency object. 240| 0| let ref = PackageReference( 241| 0| identity: managedDependency.packageRef.identity, 242| 0| path: workspace.path(for: managedDependency).pathString, 243| 0| isLocal: true 244| 0| ) 245| 0| let constraint = RepositoryPackageConstraint( 246| 0| container: ref, 247| 0| requirement: .unversioned) 248| 0| constraints.append(constraint) 249| 0| } 250| 0| return constraints 251| 0| } 252| | } 253| | 254| | /// The delegate interface. 255| | public let delegate: WorkspaceDelegate? 256| | 257| | /// The path of the workspace data. 258| | public let dataPath: AbsolutePath 259| | 260| | /// The swiftpm config. 261| | fileprivate let config: SwiftPMConfig 262| | 263| | /// The current state of managed dependencies. 264| | public let managedDependencies: ManagedDependencies 265| | 266| | /// The Pins store. The pins file will be created when first pin is added to pins store. 267| | public let pinsStore: LoadableResult 268| | 269| | /// The path for working repository clones (checkouts). 270| | public let checkoutsPath: AbsolutePath 271| | 272| | /// The path where packages which are put in edit mode are checked out. 273| | public let editablesPath: AbsolutePath 274| | 275| | /// The file system on which the workspace will operate. 276| | fileprivate var fileSystem: FileSystem 277| | 278| | /// The manifest loader to use. 279| | fileprivate let manifestLoader: ManifestLoaderProtocol 280| | 281| | /// The tools version currently in use. 282| | fileprivate let currentToolsVersion: ToolsVersion 283| | 284| | /// The manifest loader to use. 285| | fileprivate let toolsVersionLoader: ToolsVersionLoaderProtocol 286| | 287| | /// The repository manager. 288| | fileprivate let repositoryManager: RepositoryManager 289| | 290| | /// The package container provider. 291| | fileprivate let containerProvider: RepositoryPackageContainerProvider 292| | 293| | /// Enable prefetching containers in resolver. 294| | fileprivate let isResolverPrefetchingEnabled: Bool 295| | 296| | /// Enable the new Pubgrub dependency resolver. 297| | fileprivate let enablePubgrubResolver: Bool 298| | 299| | /// Skip updating containers while fetching them. 300| | fileprivate let skipUpdate: Bool 301| | 302| | /// Typealias for dependency resolver we use in the workspace. 303| | fileprivate typealias PackageDependencyResolver = DependencyResolver 304| | fileprivate typealias PubgrubResolver = PubgrubDependencyResolver 305| | 306| | /// Create a new package workspace. 307| | /// 308| | /// This will automatically load the persisted state for the package, if 309| | /// present. If the state isn't present then a default state will be 310| | /// constructed. 311| | /// 312| | /// - Parameters: 313| | /// - dataPath: The path for the workspace data files. 314| | /// - editablesPath: The path where editable packages should be placed. 315| | /// - pinsFile: The path to pins file. If pins file is not present, it will be created. 316| | /// - manifestLoader: The manifest loader. 317| | /// - fileSystem: The file system to operate on. 318| | /// - repositoryProvider: The repository provider to use in repository manager. 319| | /// - Throws: If the state was present, but could not be loaded. 320| | public init( 321| | dataPath: AbsolutePath, 322| | editablesPath: AbsolutePath, 323| | pinsFile: AbsolutePath, 324| | manifestLoader: ManifestLoaderProtocol, 325| | currentToolsVersion: ToolsVersion = ToolsVersion.currentToolsVersion, 326| | toolsVersionLoader: ToolsVersionLoaderProtocol = ToolsVersionLoader(), 327| | delegate: WorkspaceDelegate? = nil, 328| | config: SwiftPMConfig = SwiftPMConfig(), 329| | fileSystem: FileSystem = localFileSystem, 330| | repositoryProvider: RepositoryProvider = GitRepositoryProvider(), 331| | isResolverPrefetchingEnabled: Bool = false, 332| | enablePubgrubResolver: Bool = false, 333| | skipUpdate: Bool = false 334| 0| ) { 335| 0| self.delegate = delegate 336| 0| self.dataPath = dataPath 337| 0| self.config = config 338| 0| self.editablesPath = editablesPath 339| 0| self.manifestLoader = manifestLoader 340| 0| self.currentToolsVersion = currentToolsVersion 341| 0| self.toolsVersionLoader = toolsVersionLoader 342| 0| self.isResolverPrefetchingEnabled = isResolverPrefetchingEnabled 343| 0| self.enablePubgrubResolver = enablePubgrubResolver 344| 0| self.skipUpdate = skipUpdate 345| 0| 346| 0| let repositoriesPath = self.dataPath.appending(component: "repositories") 347| 0| self.repositoryManager = RepositoryManager( 348| 0| path: repositoriesPath, 349| 0| provider: repositoryProvider, 350| 0| delegate: delegate.map(WorkspaceRepositoryManagerDelegate.init(workspaceDelegate:)), 351| 0| fileSystem: fileSystem) 352| 0| self.checkoutsPath = self.dataPath.appending(component: "checkouts") 353| 0| self.containerProvider = RepositoryPackageContainerProvider( 354| 0| repositoryManager: repositoryManager, 355| 0| config: self.config, 356| 0| manifestLoader: manifestLoader, 357| 0| toolsVersionLoader: toolsVersionLoader 358| 0| ) 359| 0| self.fileSystem = fileSystem 360| 0| 361| 0| self.pinsStore = LoadableResult { 362| 0| try PinsStore(pinsFile: pinsFile, fileSystem: fileSystem) 363| 0| } 364| 0| self.managedDependencies = ManagedDependencies(dataPath: dataPath, fileSystem: fileSystem) 365| 0| } 366| | 367| | /// A convenience method for creating a workspace for the given root 368| | /// package path. 369| | /// 370| | /// The root package path is used to compute the build directory and other 371| | /// default paths. 372| | public static func create( 373| | forRootPackage packagePath: AbsolutePath, 374| | manifestLoader: ManifestLoaderProtocol 375| 0| ) -> Workspace { 376| 0| return Workspace( 377| 0| dataPath: packagePath.appending(component: ".build"), 378| 0| editablesPath: packagePath.appending(component: "Packages"), 379| 0| pinsFile: packagePath.appending(component: "Package.resolved"), 380| 0| manifestLoader: manifestLoader 381| 0| ) 382| 0| } 383| |} 384| | 385| |// MARK: - Public API 386| | 387| |extension Workspace { 388| | 389| | /// Puts a dependency in edit mode creating a checkout in editables directory. 390| | /// 391| | /// - Parameters: 392| | /// - packageName: The name of the package to edit. 393| | /// - path: If provided, creates or uses the checkout at this location. 394| | /// - revision: If provided, the revision at which the dependency 395| | /// should be checked out to otherwise current revision. 396| | /// - checkoutBranch: If provided, a new branch with this name will be 397| | /// created from the revision provided. 398| | /// - diagnostics: The diagnostics engine that reports errors, warnings 399| | /// and notes. 400| | public func edit( 401| | packageName: String, 402| | path: AbsolutePath? = nil, 403| | revision: Revision? = nil, 404| | checkoutBranch: String? = nil, 405| | diagnostics: DiagnosticsEngine 406| 0| ) { 407| 0| do { 408| 0| try _edit( 409| 0| packageName: packageName, 410| 0| path: path, 411| 0| revision: revision, 412| 0| checkoutBranch: checkoutBranch, 413| 0| diagnostics: diagnostics) 414| 0| } catch { 415| 0| diagnostics.emit(error) 416| 0| } 417| 0| } 418| | 419| | /// Ends the edit mode of an edited dependency. 420| | /// 421| | /// This will re-resolve the dependencies after ending edit as the original 422| | /// checkout may be outdated. 423| | /// 424| | /// - Parameters: 425| | /// - packageName: The name of the package to edit. 426| | /// - forceRemove: If true, the dependency will be unedited even if has unpushed 427| | /// or uncommited changes. Otherwise will throw respective errors. 428| | /// - root: The workspace root. This is used to resolve the dependencies post unediting. 429| | /// - diagnostics: The diagnostics engine that reports errors, warnings 430| | /// and notes. 431| | public func unedit( 432| | packageName: String, 433| | forceRemove: Bool, 434| | root: PackageGraphRootInput, 435| | diagnostics: DiagnosticsEngine 436| 0| ) throws { 437| 0| let dependency = try managedDependencies.dependency(forNameOrIdentity: packageName) 438| 0| try unedit(dependency: dependency, forceRemove: forceRemove, root: root, diagnostics: diagnostics) 439| 0| } 440| | 441| | /// Resolve a package at the given state. 442| | /// 443| | /// Only one of version, branch and revision will be used and in the same 444| | /// order. If none of these is provided, the dependency will be pinned at 445| | /// the current checkout state. 446| | /// 447| | /// - Parameters: 448| | /// - packageName: The name of the package which is being resolved. 449| | /// - root: The workspace's root input. 450| | /// - version: The version to pin at. 451| | /// - branch: The branch to pin at. 452| | /// - revision: The revision to pin at. 453| | /// - diagnostics: The diagnostics engine that reports errors, warnings 454| | /// and notes. 455| | public func resolve( 456| | packageName: String, 457| | root: PackageGraphRootInput, 458| | version: Version? = nil, 459| | branch: String? = nil, 460| | revision: String? = nil, 461| | diagnostics: DiagnosticsEngine 462| 0| ) { 463| 0| // Look up the dependency and check if we can pin it. 464| 0| guard let dependency = diagnostics.wrap({ try managedDependencies.dependency(forNameOrIdentity: packageName) }) else { 465| 0| return 466| 0| } 467| 0| guard let currentState = checkoutState(for: dependency, diagnostics: diagnostics) else { 468| 0| return 469| 0| } 470| 0| 471| 0| // Compute the custom or extra constraint we need to impose. 472| 0| let requirement: PackageRequirement 473| 0| if let version = version { 474| 0| requirement = .versionSet(.exact(version)) 475| 0| } else if let branch = branch { 476| 0| requirement = .revision(branch) 477| 0| } else if let revision = revision { 478| 0| requirement = .revision(revision) 479| 0| } else { 480| 0| requirement = currentState.requirement() 481| 0| } 482| 0| let constraint = RepositoryPackageConstraint( 483| 0| container: dependency.packageRef, requirement: requirement) 484| 0| 485| 0| // Run the resolution. 486| 0| _resolve(root: root, extraConstraints: [constraint], diagnostics: diagnostics) 487| 0| } 488| | 489| | /// Cleans the build artefacts from workspace data. 490| | /// 491| | /// - Parameters: 492| | /// - diagnostics: The diagnostics engine that reports errors, warnings 493| | /// and notes. 494| 0| public func clean(with diagnostics: DiagnosticsEngine) { 495| 0| 496| 0| // These are the things we don't want to remove while cleaning. 497| 0| let protectedAssets = Set([ 498| 0| repositoryManager.path, 499| 0| checkoutsPath, 500| 0| managedDependencies.statePath, 501| 0| ].map({ path in 502| 0| // Assert that these are present inside data directory. 503| 0| assert(path.parentDirectory == dataPath) 504| 0| return path.basename 505| 0| })) 506| 0| 507| 0| // If we have no data yet, we're done. 508| 0| guard fileSystem.exists(dataPath) else { 509| 0| return 510| 0| } 511| 0| 512| 0| guard let contents = diagnostics.wrap({ try fileSystem.getDirectoryContents(dataPath) }) else { 513| 0| return 514| 0| } 515| 0| 516| 0| // Remove all but protected paths. 517| 0| let contentsToRemove = Set(contents).subtracting(protectedAssets) 518| 0| for name in contentsToRemove { 519| 0| try? fileSystem.removeFileTree(dataPath.appending(RelativePath(name))) 520| 0| } 521| 0| } 522| | 523| | /// Resets the entire workspace by removing the data directory. 524| | /// 525| | /// - Parameters: 526| | /// - diagnostics: The diagnostics engine that reports errors, warnings 527| | /// and notes. 528| 0| public func reset(with diagnostics: DiagnosticsEngine) { 529| 0| let removed = diagnostics.wrap({ 530| 0| try fileSystem.chmod(.userWritable, path: checkoutsPath, options: [.recursive, .onlyFiles]) 531| 0| // Reset manaked dependencies. 532| 0| try managedDependencies.reset() 533| 0| }) 534| 0| 535| 0| guard removed else { return } 536| 0| 537| 0| repositoryManager.reset() 538| 0| try? fileSystem.removeFileTree(dataPath) 539| 0| } 540| | 541| | /// Updates the current dependencies. 542| | /// 543| | /// - Parameters: 544| | /// - diagnostics: The diagnostics engine that reports errors, warnings 545| | /// and notes. 546| | public func updateDependencies( 547| | root: PackageGraphRootInput, 548| | diagnostics: DiagnosticsEngine 549| 0| ) { 550| 0| // Create cache directories. 551| 0| createCacheDirectories(with: diagnostics) 552| 0| 553| 0| // Load the config. 554| 0| diagnostics.wrap { try config.load() } 555| 0| 556| 0| // Load the root manifests and currently checked out manifests. 557| 0| let rootManifests = loadRootManifests(packages: root.packages, diagnostics: diagnostics) 558| 0| 559| 0| // Load the current manifests. 560| 0| let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests) 561| 0| let currentManifests = loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 562| 0| 563| 0| // Abort if we're unable to load the pinsStore or have any diagnostics. 564| 0| guard let pinsStore = diagnostics.wrap({ try self.pinsStore.load() }) else { 565| 0| return 566| 0| } 567| 0| 568| 0| // Ensure we don't have any error at this point. 569| 0| guard !diagnostics.hasErrors else { return } 570| 0| 571| 0| // Add unversioned constraints for edited packages. 572| 0| var updateConstraints = currentManifests.editedPackagesConstraints() 573| 0| 574| 0| // Create constraints based on root manifest and pins for the update resolution. 575| 0| updateConstraints += graphRoot.constraints(config: config) 576| 0| 577| 0| // Record the start time of dependency resolution. 578| 0| let resolutionStartTime = Date() 579| 0| 580| 0| // Resolve the dependencies. 581| 0| let updateResults = resolveDependencies(dependencies: updateConstraints, diagnostics: diagnostics) 582| 0| guard !diagnostics.hasErrors else { return } 583| 0| 584| 0| // Emit the time taken to perform dependency resolution. 585| 0| let resolutionDuration = Date().timeIntervalSince(resolutionStartTime) 586| 0| diagnostics.emit(data: WorkspaceDiagnostics.ResolverDurationNote(resolutionDuration)) 587| 0| 588| 0| // Update the checkouts based on new dependency resolution. 589| 0| updateCheckouts(root: graphRoot, updateResults: updateResults, updateBranches: true, diagnostics: diagnostics) 590| 0| 591| 0| // Load the updated manifests. 592| 0| let updatedDependencyManifests = loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 593| 0| 594| 0| guard !diagnostics.hasErrors else { return } 595| 0| 596| 0| // Update the pins store. 597| 0| return pinAll( 598| 0| dependencyManifests: updatedDependencyManifests, 599| 0| pinsStore: pinsStore, 600| 0| diagnostics: diagnostics) 601| 0| } 602| | 603| | /// Fetch and load the complete package at the given path. 604| | /// 605| | /// This will implicitly cause any dependencies not yet present in the 606| | /// working checkouts to be resolved, cloned, and checked out. 607| | /// 608| | /// - Returns: The loaded package graph. 609| | @discardableResult 610| | public func loadPackageGraph( 611| | root: PackageGraphRootInput, 612| | createMultipleTestProducts: Bool = false, 613| | createREPLProduct: Bool = false, 614| | forceResolvedVersions: Bool = false, 615| | diagnostics: DiagnosticsEngine 616| 0| ) -> PackageGraph { 617| 0| 618| 0| // Perform dependency resolution, if required. 619| 0| let manifests: DependencyManifests 620| 0| if forceResolvedVersions { 621| 0| manifests = self._resolveToResolvedVersion(root: root, diagnostics: diagnostics) 622| 0| } else { 623| 0| manifests = self._resolve(root: root, diagnostics: diagnostics) 624| 0| } 625| 0| let externalManifests = manifests.allManifests() 626| 0| 627| 0| // Load the graph. 628| 0| return PackageGraphLoader().load( 629| 0| root: manifests.root, 630| 0| config: config, 631| 0| externalManifests: externalManifests, 632| 0| requiredDependencies: manifests.computePackageURLs().required, 633| 0| diagnostics: diagnostics, 634| 0| fileSystem: fileSystem, 635| 0| shouldCreateMultipleTestProducts: createMultipleTestProducts, 636| 0| createREPLProduct: createREPLProduct 637| 0| ) 638| 0| } 639| | 640| | @discardableResult 641| | public func loadPackageGraph( 642| | root: AbsolutePath, 643| | diagnostics: DiagnosticsEngine 644| 0| ) -> PackageGraph { 645| 0| return self.loadPackageGraph( 646| 0| root: PackageGraphRootInput(packages: [root]), 647| 0| diagnostics: diagnostics 648| 0| ) 649| 0| } 650| | 651| | /// Perform dependency resolution if needed. 652| | /// 653| | /// This method will perform dependency resolution based on the root 654| | /// manifests and pins file. Pins are respected as long as they are 655| | /// satisfied by the root manifest closure requirements. Any outdated 656| | /// checkout will be restored according to its pin. 657| | public func resolve( 658| | root: PackageGraphRootInput, 659| | diagnostics: DiagnosticsEngine 660| 0| ) { 661| 0| _resolve(root: root, diagnostics: diagnostics) 662| 0| } 663| | 664| | /// Loads and returns manifests at the given paths. 665| | public func loadRootManifests( 666| | packages: [AbsolutePath], 667| | diagnostics: DiagnosticsEngine 668| 0| ) -> [Manifest] { 669| 0| let rootManifests = packages.compactMap({ package -> Manifest? in 670| 0| loadManifest(packagePath: package, url: package.pathString, diagnostics: diagnostics) 671| 0| }) 672| 0| 673| 0| // Check for duplicate root packages. 674| 0| let duplicateRoots = rootManifests.spm_findDuplicateElements(by: \.name) 675| 0| if !duplicateRoots.isEmpty { 676| 0| diagnostics.emit(data: WorkspaceDiagnostics.DuplicateRoots(name: duplicateRoots[0][0].name)) 677| 0| return [] 678| 0| } 679| 0| 680| 0| return rootManifests 681| 0| } 682| |} 683| | 684| |// MARK: - Editing Functions 685| | 686| |extension Workspace { 687| | 688| | func checkoutState( 689| | for dependency: ManagedDependency, 690| | diagnostics: DiagnosticsEngine 691| 0| ) -> CheckoutState? { 692| 0| let name = dependency.packageRef.name ?? dependency.packageRef.identity 693| 0| switch dependency.state { 694| 0| case .checkout(let checkoutState): 695| 0| return checkoutState 696| 0| case .edited: 697| 0| diagnostics.emit(WorkspaceDiagnostics.DependencyAlreadyInEditMode(dependencyName: name)) 698| 0| case .local: 699| 0| diagnostics.emit(WorkspaceDiagnostics.LocalDependencyEdited(dependencyName: name)) 700| 0| } 701| 0| return nil 702| 0| } 703| | 704| | /// Edit implementation. 705| | fileprivate func _edit( 706| | packageName: String, 707| | path: AbsolutePath? = nil, 708| | revision: Revision? = nil, 709| | checkoutBranch: String? = nil, 710| | diagnostics: DiagnosticsEngine 711| 0| ) throws { 712| 0| // Look up the dependency and check if we can edit it. 713| 0| let dependency = try managedDependencies.dependency(forNameOrIdentity: packageName) 714| 0| 715| 0| guard let checkoutState = checkoutState(for: dependency, diagnostics: diagnostics) else { 716| 0| return 717| 0| } 718| 0| 719| 0| // If a path is provided then we use it as destination. If not, we 720| 0| // use the folder with packageName inside editablesPath. 721| 0| let destination = path ?? editablesPath.appending(component: packageName) 722| 0| 723| 0| // If there is something present at the destination, we confirm it has 724| 0| // a valid manifest with name same as the package we are trying to edit. 725| 0| if fileSystem.exists(destination) { 726| 0| let manifest = loadManifest( 727| 0| packagePath: destination, url: dependency.packageRef.repository.url, diagnostics: diagnostics) 728| 0| 729| 0| guard manifest?.name == packageName else { 730| 0| let error = WorkspaceDiagnostics.MismatchingDestinationPackage( 731| 0| editPath: destination, 732| 0| expectedPackage: packageName, 733| 0| destinationPackage: manifest?.name) 734| 0| return diagnostics.emit(error) 735| 0| } 736| 0| 737| 0| // Emit warnings for branch and revision, if they're present. 738| 0| if let checkoutBranch = checkoutBranch { 739| 0| diagnostics.emit(WorkspaceDiagnostics.EditBranchNotCheckedOut( 740| 0| packageName: packageName, 741| 0| branchName: checkoutBranch)) 742| 0| } 743| 0| if let revision = revision { 744| 0| diagnostics.emit(WorkspaceDiagnostics.EditRevisionNotUsed( 745| 0| packageName: packageName, 746| 0| revisionIdentifier: revision.identifier)) 747| 0| } 748| 0| } else { 749| 0| // Otherwise, create a checkout at the destination from our repository store. 750| 0| // 751| 0| // Get handle to the repository. 752| 0| let handle = try await { 753| 0| repositoryManager.lookup(repository: dependency.packageRef.repository, skipUpdate: true, completion: $0) 754| 0| } 755| 0| let repo = try handle.open() 756| 0| 757| 0| // Do preliminary checks on branch and revision, if provided. 758| 0| if let branch = checkoutBranch, repo.exists(revision: Revision(identifier: branch)) { 759| 0| throw WorkspaceDiagnostics.BranchAlreadyExists(branch: branch) 760| 0| } 761| 0| if let revision = revision, !repo.exists(revision: revision) { 762| 0| throw WorkspaceDiagnostics.RevisionDoesNotExist(revision: revision.identifier) 763| 0| } 764| 0| 765| 0| try handle.cloneCheckout(to: destination, editable: true) 766| 0| let workingRepo = try repositoryManager.provider.openCheckout(at: destination) 767| 0| try workingRepo.checkout(revision: revision ?? checkoutState.revision) 768| 0| 769| 0| // Checkout to the new branch if provided. 770| 0| if let branch = checkoutBranch { 771| 0| try workingRepo.checkout(newBranch: branch) 772| 0| } 773| 0| } 774| 0| 775| 0| // For unmanaged dependencies, create the symlink under editables dir. 776| 0| if let path = path { 777| 0| try fileSystem.createDirectory(editablesPath) 778| 0| // FIXME: We need this to work with InMem file system too. 779| 0| if !(fileSystem is InMemoryFileSystem) { 780| 0| let symLinkPath = editablesPath.appending(component: packageName) 781| 0| 782| 0| // Cleanup any existing symlink. 783| 0| if fileSystem.isSymlink(symLinkPath) { 784| 0| try fileSystem.removeFileTree(symLinkPath) 785| 0| } 786| 0| 787| 0| // FIXME: We should probably just warn in case we fail to create 788| 0| // this symlink, which could happen if there is some non-symlink 789| 0| // entry at this location. 790| 0| try createSymlink(symLinkPath, pointingAt: path, relative: false) 791| 0| } 792| 0| } 793| 0| 794| 0| // Remove the existing checkout. 795| 0| do { 796| 0| let oldCheckoutPath = checkoutsPath.appending(dependency.subpath) 797| 0| try fileSystem.chmod(.userWritable, path: oldCheckoutPath, options: [.recursive, .onlyFiles]) 798| 0| try fileSystem.removeFileTree(oldCheckoutPath) 799| 0| } 800| 0| 801| 0| // Save the new state. 802| 0| let url = dependency.packageRef.path 803| 0| managedDependencies[forURL: url] = dependency.editedDependency( 804| 0| subpath: RelativePath(packageName), unmanagedPath: path) 805| 0| try managedDependencies.saveState() 806| 0| } 807| | 808| | /// Unedit a managed dependency. See public API unedit(packageName:forceRemove:). 809| | fileprivate func unedit( 810| | dependency: ManagedDependency, 811| | forceRemove: Bool, 812| | root: PackageGraphRootInput? = nil, 813| | diagnostics: DiagnosticsEngine 814| 0| ) throws { 815| 0| 816| 0| // Compute if we need to force remove. 817| 0| var forceRemove = forceRemove 818| 0| 819| 0| switch dependency.state { 820| 0| // If the dependency isn't in edit mode, we can't unedit it. 821| 0| case .checkout, .local: 822| 0| throw WorkspaceDiagnostics.DependencyNotInEditMode(dependencyName: dependency.packageRef.identity) 823| 0| 824| 0| case .edited(let path): 825| 0| if path != nil { 826| 0| // Set force remove to true for unmanaged dependencies. Note that 827| 0| // this only removes the symlink under the editable directory and 828| 0| // not the actual unmanaged package. 829| 0| forceRemove = true 830| 0| } 831| 0| } 832| 0| 833| 0| // Form the edit working repo path. 834| 0| let path = editablesPath.appending(dependency.subpath) 835| 0| // Check for uncommited and unpushed changes if force removal is off. 836| 0| if !forceRemove { 837| 0| let workingRepo = try repositoryManager.provider.openCheckout(at: path) 838| 0| guard !workingRepo.hasUncommittedChanges() else { 839| 0| throw WorkspaceDiagnostics.UncommitedChanges(repositoryPath: path) 840| 0| } 841| 0| guard try !workingRepo.hasUnpushedCommits() else { 842| 0| throw WorkspaceDiagnostics.UnpushedChanges(repositoryPath: path) 843| 0| } 844| 0| } 845| 0| // Remove the editable checkout from disk. 846| 0| if fileSystem.exists(path) { 847| 0| try fileSystem.removeFileTree(path) 848| 0| } 849| 0| // If this was the last editable dependency, remove the editables directory too. 850| 0| if fileSystem.exists(editablesPath), try fileSystem.getDirectoryContents(editablesPath).isEmpty { 851| 0| try fileSystem.removeFileTree(editablesPath) 852| 0| } 853| 0| 854| 0| if let checkoutState = dependency.basedOn?.checkoutState { 855| 0| // Restore the original checkout. 856| 0| // 857| 0| // The clone method will automatically update the managed dependency state. 858| 0| _ = try clone(package: dependency.packageRef, at: checkoutState) 859| 0| } else { 860| 0| // The original dependency was removed, update the managed dependency state. 861| 0| managedDependencies[forURL: dependency.packageRef.path] = nil 862| 0| try managedDependencies.saveState() 863| 0| } 864| 0| 865| 0| // Resolve the dependencies if workspace root is provided. We do this to 866| 0| // ensure the unedited version of this dependency is resolved properly. 867| 0| if let root = root { 868| 0| resolve(root: root, diagnostics: diagnostics) 869| 0| } 870| 0| } 871| | 872| |} 873| | 874| |// MARK: - Pinning Functions 875| | 876| |extension Workspace { 877| | 878| | /// Pins all of the current managed dependencies at their checkout state. 879| | fileprivate func pinAll( 880| | dependencyManifests: DependencyManifests, 881| | pinsStore: PinsStore, 882| | diagnostics: DiagnosticsEngine 883| 0| ) { 884| 0| // Reset the pinsStore and start pinning the required dependencies. 885| 0| pinsStore.unpinAll() 886| 0| 887| 0| let requiredURLs = dependencyManifests.computePackageURLs().required 888| 0| 889| 0| for dependency in managedDependencies.values { 890| 0| if requiredURLs.contains(where: { $0.path == dependency.packageRef.path }) { 891| 0| pinsStore.pin(dependency) 892| 0| } 893| 0| } 894| 0| diagnostics.wrap({ try pinsStore.saveState() }) 895| 0| } 896| |} 897| | 898| |// MARK: - Utility Functions 899| | 900| |extension Workspace { 901| | 902| | /// Create the cache directories. 903| 0| fileprivate func createCacheDirectories(with diagnostics: DiagnosticsEngine) { 904| 0| do { 905| 0| try fileSystem.createDirectory(repositoryManager.path, recursive: true) 906| 0| try fileSystem.createDirectory(checkoutsPath, recursive: true) 907| 0| } catch { 908| 0| diagnostics.emit(error) 909| 0| } 910| 0| } 911| | 912| | /// Returns the location of the dependency. 913| | /// 914| | /// Checkout dependencies will return the subpath inside `checkoutsPath` and 915| | /// edited dependencies will either return a subpath inside `editablesPath` or 916| | /// a custom path. 917| 0| public func path(for dependency: ManagedDependency) -> AbsolutePath { 918| 0| switch dependency.state { 919| 0| case .checkout: 920| 0| return checkoutsPath.appending(dependency.subpath) 921| 0| case .edited(let path): 922| 0| return path ?? editablesPath.appending(dependency.subpath) 923| 0| case .local: 924| 0| return AbsolutePath(dependency.packageRef.path) 925| 0| } 926| 0| } 927| | 928| | /// Returns manifest interpreter flags for a package. 929| 0| public func interpreterFlags(for packagePath: AbsolutePath) -> [String] { 930| 0| // We ignore all failures here and return empty array. 931| 0| guard let manifestLoader = self.manifestLoader as? ManifestLoader, 932| 0| let toolsVersion = try? toolsVersionLoader.load(at: packagePath, fileSystem: fileSystem), 933| 0| currentToolsVersion >= toolsVersion, 934| 0| toolsVersion >= ToolsVersion.minimumRequired else { 935| 0| return [] 936| 0| } 937| 0| return manifestLoader.interpreterFlags(for: toolsVersion.manifestVersion) 938| 0| } 939| | 940| | /// Load the manifests for the current dependency tree. 941| | /// 942| | /// This will load the manifests for the root package as well as all the 943| | /// current dependencies from the working checkouts. 944| | // @testable internal 945| | func loadDependencyManifests( 946| | root: PackageGraphRoot, 947| | diagnostics: DiagnosticsEngine 948| 0| ) -> DependencyManifests { 949| 0| 950| 0| // Remove any managed dependency which has become a root. 951| 0| for dependency in managedDependencies.values { 952| 0| if root.packageRefs.contains(dependency.packageRef) { 953| 0| diagnostics.wrap { 954| 0| try self.remove(package: dependency.packageRef) 955| 0| } 956| 0| } 957| 0| } 958| 0| 959| 0| // Try to load current managed dependencies, or emit and return. 960| 0| fixManagedDependencies(with: diagnostics) 961| 0| guard !diagnostics.hasErrors else { 962| 0| return DependencyManifests(root: root, dependencies: [], workspace: self) 963| 0| } 964| 0| 965| 0| let rootDependencyManifests: [Manifest] = root.dependencies.compactMap({ 966| 0| let url = config.mirroredURL(forURL: $0.url) 967| 0| return loadManifest(forURL: url, diagnostics: diagnostics) 968| 0| }) 969| 0| let inputManifests = root.manifests + rootDependencyManifests 970| 0| 971| 0| // Map of loaded manifests. We do this to avoid reloading the shared nodes. 972| 0| var loadedManifests = [String: Manifest]() 973| 0| 974| 0| // Compute the transitive closure of available dependencies. 975| 0| let allManifests = try! topologicalSort(inputManifests.map({ KeyedPair($0, key: $0.name) })) { node in 976| 0| return node.item.dependencies.compactMap({ dependency in 977| 0| let url = config.mirroredURL(forURL: dependency.url) 978| 0| let manifest = loadedManifests[url] ?? loadManifest(forURL: url, diagnostics: diagnostics) 979| 0| loadedManifests[url] = manifest 980| 0| return manifest.flatMap({ KeyedPair($0, key: $0.name) }) 981| 0| }) 982| 0| } 983| 0| 984| 0| let allDependencyManifests = allManifests.map({ $0.item }).filter({ !root.manifests.contains($0) }) 985| 0| let deps = allDependencyManifests.map({ ($0, managedDependencies[forURL: $0.url]!) }) 986| 0| 987| 0| return DependencyManifests(root: root, dependencies: deps, workspace: self) 988| 0| } 989| | 990| | 991| | /// Loads the given manifest, if it is present in the managed dependencies. 992| 0| fileprivate func loadManifest(forURL packageURL: String, diagnostics: DiagnosticsEngine) -> Manifest? { 993| 0| // Check if this dependency is available. 994| 0| guard let managedDependency = managedDependencies[forURL: packageURL] else { 995| 0| return nil 996| 0| } 997| 0| 998| 0| // The version, if known. 999| 0| let version: Version? 1000| 0| switch managedDependency.state { 1001| 0| case .checkout(let checkoutState): 1002| 0| version = checkoutState.version 1003| 0| case .edited, .local: 1004| 0| version = nil 1005| 0| } 1006| 0| 1007| 0| // Get the path of the package. 1008| 0| let packagePath = path(for: managedDependency) 1009| 0| 1010| 0| // Load and return the manifest. 1011| 0| return loadManifest( 1012| 0| packagePath: packagePath, 1013| 0| url: managedDependency.packageRef.path, 1014| 0| version: version, 1015| 0| diagnostics: diagnostics 1016| 0| ) 1017| 0| } 1018| | 1019| | /// Load the manifest at a given path. 1020| | /// 1021| | /// This is just a helper wrapper to the manifest loader. 1022| | fileprivate func loadManifest( 1023| | packagePath: AbsolutePath, 1024| | url: String, 1025| | version: Version? = nil, 1026| | diagnostics: DiagnosticsEngine 1027| 0| ) -> Manifest? { 1028| 0| return diagnostics.wrap(with: PackageLocation.Local(packagePath: packagePath), { 1029| 0| // Load the tools version for the package. 1030| 0| let toolsVersion = try toolsVersionLoader.load( 1031| 0| at: packagePath, fileSystem: fileSystem) 1032| 0| 1033| 0| // Make sure the package has the right minimum tools version. 1034| 0| guard toolsVersion >= ToolsVersion.minimumRequired else { 1035| 0| throw WorkspaceDiagnostics.UnsupportedToolsVersion( 1036| 0| packagePath: packagePath, 1037| 0| minimumRequiredToolsVersion: .minimumRequired, 1038| 0| packageToolsVersion: toolsVersion 1039| 0| ) 1040| 0| } 1041| 0| 1042| 0| // Make sure the package isn't newer than the current tools version. 1043| 0| guard currentToolsVersion >= toolsVersion else { 1044| 0| throw WorkspaceDiagnostics.RequireNewerTools( 1045| 0| packagePath: packagePath, 1046| 0| installedToolsVersion: currentToolsVersion, 1047| 0| packageToolsVersion: toolsVersion 1048| 0| ) 1049| 0| } 1050| 0| 1051| 0| // Load the manifest. 1052| 0| // FIXME: We should have a cache for this. 1053| 0| return try manifestLoader.load( 1054| 0| package: packagePath, 1055| 0| baseURL: url, 1056| 0| version: version, 1057| 0| manifestVersion: toolsVersion.manifestVersion, 1058| 0| diagnostics: diagnostics 1059| 0| ) 1060| 0| }) 1061| 0| } 1062| |} 1063| | 1064| |// MARK: - Dependency Management 1065| | 1066| |extension Workspace { 1067| | 1068| | /// Resolves the dependencies according to the entries present in the Package.resolved file. 1069| | /// 1070| | /// This method bypasses the dependency resolution and resolves dependencies 1071| | /// according to the information in the resolved file. 1072| | public func resolveToResolvedVersion( 1073| | root: PackageGraphRootInput, 1074| | diagnostics: DiagnosticsEngine 1075| 0| ) { 1076| 0| _resolveToResolvedVersion(root: root, diagnostics: diagnostics) 1077| 0| } 1078| | 1079| | /// Resolves the dependencies according to the entries present in the Package.resolved file. 1080| | /// 1081| | /// This method bypasses the dependency resolution and resolves dependencies 1082| | /// according to the information in the resolved file. 1083| | @discardableResult 1084| | fileprivate func _resolveToResolvedVersion( 1085| | root: PackageGraphRootInput, 1086| | diagnostics: DiagnosticsEngine 1087| 0| ) -> DependencyManifests { 1088| 0| // Ensure the cache path exists. 1089| 0| createCacheDirectories(with: diagnostics) 1090| 0| 1091| 0| // Load the config. 1092| 0| diagnostics.wrap { try config.load() } 1093| 0| 1094| 0| let rootManifests = loadRootManifests(packages: root.packages, diagnostics: diagnostics) 1095| 0| let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests) 1096| 0| 1097| 0| // Load the pins store or abort now. 1098| 0| guard let pinsStore = diagnostics.wrap({ try self.pinsStore.load() }), !diagnostics.hasErrors else { 1099| 0| return loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 1100| 0| } 1101| 0| 1102| 0| // Request all the containers to fetch them in parallel. 1103| 0| // 1104| 0| // We just request the packages here, repository manager will 1105| 0| // automatically manage the parallelism. 1106| 0| let pins = pinsStore.pins.map({ $0 }) 1107| 0| DispatchQueue.concurrentPerform(iterations: pins.count) { idx in 1108| 0| _ = try? await { 1109| 0| containerProvider.getContainer(for: pins[idx].packageRef, skipUpdate: true, completion: $0) 1110| 0| } 1111| 0| } 1112| 0| 1113| 0| // Compute the pins that we need to actually clone. 1114| 0| // 1115| 0| // We require cloning if there is no checkout or if the checkout doesn't 1116| 0| // match with the pin. 1117| 0| let requiredPins = pins.filter({ pin in 1118| 0| guard let dependency = managedDependencies[forURL: pin.packageRef.path] else { 1119| 0| return true 1120| 0| } 1121| 0| switch dependency.state { 1122| 0| case .checkout(let checkoutState): 1123| 0| return pin.state != checkoutState 1124| 0| case .edited, .local: 1125| 0| return true 1126| 0| } 1127| 0| }) 1128| 0| 1129| 0| // Clone the required pins. 1130| 0| for pin in requiredPins { 1131| 0| diagnostics.wrap { 1132| 0| _ = try self.clone(package: pin.packageRef, at: pin.state) 1133| 0| } 1134| 0| } 1135| 0| 1136| 0| let currentManifests = loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 1137| 0| 1138| 0| // Check if a new resolution is required. 1139| 0| let dependencies = 1140| 0| graphRoot.constraints(config: config) + 1141| 0| // Include constraints from the manifests in the graph root. 1142| 0| graphRoot.manifests.flatMap({ $0.dependencyConstraints(config: config) }) + 1143| 0| currentManifests.dependencyConstraints() 1144| 0| 1145| 0| let result = isResolutionRequired(root: graphRoot, dependencies: dependencies, pinsStore: pinsStore) 1146| 0| if result.resolve { 1147| 0| diagnostics.emit(data: WorkspaceDiagnostics.RequiresResolution()) 1148| 0| } 1149| 0| 1150| 0| return currentManifests 1151| 0| } 1152| | 1153| | /// Implementation of resolve(root:diagnostics:). 1154| | /// 1155| | /// The extra constraints will be added to the main requirements. 1156| | /// It is useful in situations where a requirement is being 1157| | /// imposed outside of manifest and pins file. E.g., when using a command 1158| | /// like `$ swift package resolve foo --version 1.0.0`. 1159| | @discardableResult 1160| | fileprivate func _resolve( 1161| | root: PackageGraphRootInput, 1162| | extraConstraints: [RepositoryPackageConstraint] = [], 1163| | diagnostics: DiagnosticsEngine, 1164| | retryOnPackagePathMismatch: Bool = true 1165| 0| ) -> DependencyManifests { 1166| 0| 1167| 0| // Ensure the cache path exists and validate that edited dependencies. 1168| 0| createCacheDirectories(with: diagnostics) 1169| 0| 1170| 0| // Load the config. 1171| 0| diagnostics.wrap { try config.load() } 1172| 0| 1173| 0| // Load the root manifests and currently checked out manifests. 1174| 0| let rootManifests = loadRootManifests(packages: root.packages, diagnostics: diagnostics) 1175| 0| 1176| 0| // Load the current manifests. 1177| 0| let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests) 1178| 0| let currentManifests = loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 1179| 0| guard !diagnostics.hasErrors else { 1180| 0| return currentManifests 1181| 0| } 1182| 0| 1183| 0| validatePinsStore(dependencyManifests: currentManifests, diagnostics: diagnostics) 1184| 0| 1185| 0| // Abort if pinsStore is unloadable or if diagnostics has errors. 1186| 0| guard !diagnostics.hasErrors, let pinsStore = diagnostics.wrap({ try pinsStore.load() }) else { 1187| 0| return currentManifests 1188| 0| } 1189| 0| 1190| 0| // Compute the missing package identities. 1191| 0| let missingPackageURLs = currentManifests.missingPackageURLs() 1192| 0| 1193| 0| // The pins to use in case we need to run the resolution. 1194| 0| var validPins = pinsStore.createConstraints() 1195| 0| 1196| 0| // Compute if we need to run the resolver. We always run the resolver if 1197| 0| // there are extra constraints. 1198| 0| if missingPackageURLs.isEmpty { 1199| 0| // Use root constraints, dependency manifest constraints and extra 1200| 0| // constraints to compute if a new resolution is required. 1201| 0| let dependencies = 1202| 0| graphRoot.constraints(config: config) + 1203| 0| // Include constraints from the manifests in the graph root. 1204| 0| graphRoot.manifests.flatMap({ $0.dependencyConstraints(config: config) }) + 1205| 0| currentManifests.dependencyConstraints() + 1206| 0| extraConstraints 1207| 0| 1208| 0| let result = isResolutionRequired(root: graphRoot, dependencies: dependencies, pinsStore: pinsStore) 1209| 0| 1210| 0| // If we don't need resolution and there are no extra constraints, 1211| 0| // just validate pinsStore and return. 1212| 0| if !result.resolve && extraConstraints.isEmpty { 1213| 0| return currentManifests 1214| 0| } 1215| 0| 1216| 0| validPins = result.validPins 1217| 0| } 1218| 0| 1219| 0| // Inform delegate that we will resolve dependencies now. 1220| 0| delegate?.willResolveDependencies() 1221| 0| 1222| 0| // Create the constraints. 1223| 0| var constraints = [RepositoryPackageConstraint]() 1224| 0| constraints += currentManifests.editedPackagesConstraints() 1225| 0| constraints += graphRoot.constraints(config: config) + extraConstraints 1226| 0| 1227| 0| // Record the start time of dependency resolution. 1228| 0| let resolutionStartTime = Date() 1229| 0| 1230| 0| // Perform dependency resolution. 1231| 0| let resolverDiagnostics = DiagnosticsEngine() 1232| 0| let resolver = createResolver() 1233| 0| var result = resolveDependencies( 1234| 0| resolver: resolver, dependencies: constraints, pins: validPins, diagnostics: resolverDiagnostics) 1235| 0| 1236| 0| // If we fail, we just try again without any pins because the pins might 1237| 0| // be completely incompatible. 1238| 0| // 1239| 0| // FIXME: We should only do this if resolver emits "unresolvable" error. 1240| 0| if resolverDiagnostics.hasErrors { 1241| 0| // If there are no pins, merge diagnostics and return now. 1242| 0| if validPins.isEmpty { 1243| 0| diagnostics.merge(resolverDiagnostics) 1244| 0| return currentManifests 1245| 0| } 1246| 0| 1247| 0| // Run using the same resolver so we don't re-add the containers, we already have. 1248| 0| result = resolveDependencies(resolver: resolver, dependencies: constraints, diagnostics: diagnostics) 1249| 0| guard !diagnostics.hasErrors else { 1250| 0| return currentManifests 1251| 0| } 1252| 0| } 1253| 0| 1254| 0| // Emit the time taken to perform dependency resolution. 1255| 0| let resolutionDuration = Date().timeIntervalSince(resolutionStartTime) 1256| 0| diagnostics.emit(data: WorkspaceDiagnostics.ResolverDurationNote(resolutionDuration)) 1257| 0| 1258| 0| // Update the checkouts with dependency resolution result. 1259| 0| updateCheckouts(root: graphRoot, updateResults: result, diagnostics: diagnostics) 1260| 0| guard !diagnostics.hasErrors else { 1261| 0| return currentManifests 1262| 0| } 1263| 0| 1264| 0| // Update the pinsStore. 1265| 0| let updatedDependencyManifests = loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) 1266| 0| 1267| 0| // If we still have required URLs, we probably cloned a wrong URL for 1268| 0| // some package dependency. 1269| 0| // 1270| 0| // This would usually happen when we're resolving from scratch and the 1271| 0| // resolved file has an outdated entry for a transitive dependency whose 1272| 0| // URL was changed. For e.g., the resolved file could refer to a dependency 1273| 0| // through a ssh url but its new reference is now changed to http. 1274| 0| if !updatedDependencyManifests.computePackageURLs().missing.isEmpty { 1275| 0| // Retry resolution which will most likely resolve correctly now since 1276| 0| // we have the manifest files of all the dependencies. 1277| 0| if retryOnPackagePathMismatch { 1278| 0| // We still have something that is required. Retry! 1279| 0| return self._resolve( 1280| 0| root: root, 1281| 0| extraConstraints: extraConstraints, 1282| 0| diagnostics: diagnostics, 1283| 0| retryOnPackagePathMismatch: false 1284| 0| ) 1285| 0| } else { 1286| 0| // If we weren't able to resolve properly even after a retry, it 1287| 0| // could mean that the dependency at fault has a different 1288| 0| // version of the manifest file which contains dependencies that 1289| 0| // have also changed their package references. 1290| 0| // FIXME: Emit diagnostic here. 1291| 0| diagnostics.emit(data: WorkspaceDiagnostics.OutdatedResolvedFile()) 1292| 0| return updatedDependencyManifests 1293| 0| } 1294| 0| } 1295| 0| 1296| 0| self.pinAll(dependencyManifests: updatedDependencyManifests, pinsStore: pinsStore, diagnostics: diagnostics) 1297| 0| 1298| 0| return updatedDependencyManifests 1299| 0| } 1300| | 1301| | /// Computes if dependency resolution is required based on input constraints and pins. 1302| | /// 1303| | /// - Returns: A tuple with two elements. 1304| | /// resolve: If resolution is required. 1305| | /// validPins: The pins which are still valid. 1306| | // @testable internal 1307| | func isResolutionRequired( 1308| | root: PackageGraphRoot, 1309| | dependencies: [RepositoryPackageConstraint], 1310| | pinsStore: PinsStore 1311| 0| ) -> (resolve: Bool, validPins: [RepositoryPackageConstraint]) { 1312| 0| 1313| 0| // Create pinned constraints. 1314| 0| let pinConstraints = pinsStore.createConstraints() 1315| 0| 1316| 0| // Create a constraint set to check constraints are mergable. 1317| 0| var constraintSet = PackageContainerConstraintSet() 1318| 0| 1319| 0| // The input dependencies should be mergable, otherwise we have bigger problems. 1320| 0| for constraint in dependencies { 1321| 0| if let mergedSet = constraintSet.merging(constraint) { 1322| 0| constraintSet = mergedSet 1323| 0| } else { 1324| 0| return (true, pinConstraints) 1325| 0| } 1326| 0| } 1327| 0| 1328| 0| // Merge all the pin constraints. 1329| 0| for pin in pinConstraints { 1330| 0| if let mergedSet = constraintSet.merging(pin) { 1331| 0| constraintSet = mergedSet 1332| 0| } 1333| 0| } 1334| 0| 1335| 0| // Compute the valid pins, i.e., the pins which are still valid in the 1336| 0| // final merged set. 1337| 0| let validPins = pinConstraints.filter({ 1338| 0| $0.requirement == constraintSet[$0.identifier] 1339| 0| }) 1340| 0| 1341| 0| // Otherwise, check checkouts and pins. 1342| 0| for constraint in constraintSet { 1343| 0| let url = constraint.key.path 1344| 0| let dependency = managedDependencies[forURL: url] 1345| 0| 1346| 0| switch dependency?.state { 1347| 0| case let .checkout(dependencyState)?: 1348| 0| // If this constraint is not same as the checkout state, we need to re-resolve. 1349| 0| if constraint.value != dependencyState.requirement() { 1350| 0| return (true, validPins) 1351| 0| } 1352| 0| 1353| 0| // Ensure that the pin is not out of sync. 1354| 0| if dependencyState != pinsStore.pinsMap[constraint.key.identity]?.state { 1355| 0| return (true, validPins) 1356| 0| } 1357| 0| 1358| 0| case .local?: 1359| 0| switch constraint.value { 1360| 0| case .versionSet, .revision: 1361| 0| // We have a local package but the requirement is now different. 1362| 0| return (true, validPins) 1363| 0| case .unversioned: 1364| 0| break 1365| 0| } 1366| 0| 1367| 0| case .edited?: 1368| 0| continue 1369| 0| 1370| 0| case nil: 1371| 0| // Ignore root packages. 1372| 0| if root.packageRefs.contains(constraint.key) { 1373| 0| continue 1374| 0| } 1375| 0| // We don't have a checkout. 1376| 0| return (true, validPins) 1377| 0| } 1378| 0| } 1379| 0| 1380| 0| return (false, []) 1381| 0| } 1382| | 1383| | /// Validates that each checked out managed dependency has an entry in pinsStore. 1384| 0| private func validatePinsStore(dependencyManifests: DependencyManifests, diagnostics: DiagnosticsEngine) { 1385| 0| guard let pinsStore = diagnostics.wrap({ try pinsStore.load() }) else { 1386| 0| return 1387| 0| } 1388| 0| 1389| 0| let pins = pinsStore.pinsMap.keys 1390| 0| let requiredURLs = dependencyManifests.computePackageURLs().required 1391| 0| 1392| 0| for dependency in managedDependencies.values { 1393| 0| switch dependency.state { 1394| 0| case .checkout: break 1395| 0| case .edited, .local: continue 1396| 0| } 1397| 0| 1398| 0| let identity = dependency.packageRef.identity 1399| 0| 1400| 0| if requiredURLs.contains(where: { $0.path == dependency.packageRef.path }) { 1401| 0| // If required identity contains this dependency, it should be in the pins store. 1402| 0| if let pin = pinsStore.pinsMap[identity], pin.packageRef.path == dependency.packageRef.path { 1403| 0| continue 1404| 0| } 1405| 0| } else if !pins.contains(identity) { 1406| 0| // Otherwise, it should *not* be in the pins store. 1407| 0| continue 1408| 0| } 1409| 0| 1410| 0| return self.pinAll(dependencyManifests: dependencyManifests, pinsStore: pinsStore, diagnostics: diagnostics) 1411| 0| } 1412| 0| } 1413| | 1414| | /// This enum represents state of an external package. 1415| | fileprivate enum PackageStateChange: Equatable, CustomStringConvertible { 1416| | 1417| | /// The requirement imposed by the the state. 1418| | enum Requirement: Equatable, CustomStringConvertible { 1419| | /// A version requirement. 1420| | case version(Version) 1421| | 1422| | /// A revision requirement. 1423| | case revision(Revision, branch: String?) 1424| | 1425| | case unversioned 1426| | 1427| 0| var description: String { 1428| 0| switch self { 1429| 0| case .version(let version): 1430| 0| return "requirement(\(version))" 1431| 0| case .revision(let revision, let branch): 1432| 0| return "requirement(\(revision) \(branch ?? ""))" 1433| 0| case .unversioned: 1434| 0| return "requirement(unversioned)" 1435| 0| } 1436| 0| } 1437| | } 1438| | 1439| | /// The package is added. 1440| | case added(Requirement) 1441| | 1442| | /// The package is removed. 1443| | case removed 1444| | 1445| | /// The package is unchanged. 1446| | case unchanged 1447| | 1448| | /// The package is updated. 1449| | case updated(Requirement) 1450| | 1451| 0| var description: String { 1452| 0| switch self { 1453| 0| case .added(let requirement): 1454| 0| return "added(\(requirement))" 1455| 0| case .removed: 1456| 0| return "removed" 1457| 0| case .unchanged: 1458| 0| return "unchanged" 1459| 0| case .updated(let requirement): 1460| 0| return "updated(\(requirement))" 1461| 0| } 1462| 0| } 1463| | 1464| | } 1465| | 1466| | /// Computes states of the packages based on last stored state. 1467| | fileprivate func computePackageStateChanges( 1468| | root: PackageGraphRoot, 1469| | resolvedDependencies: [(PackageReference, BoundVersion)], 1470| | updateBranches: Bool 1471| 0| ) throws -> [(PackageReference, PackageStateChange)] { 1472| 0| // Load pins store and managed dependendencies. 1473| 0| let pinsStore = try self.pinsStore.load() 1474| 0| var packageStateChanges: [String: (PackageReference, PackageStateChange)] = [:] 1475| 0| 1476| 0| // Set the states from resolved dependencies results. 1477| 0| for (packageRef, binding) in resolvedDependencies { 1478| 0| // Get the existing managed dependency for this package ref, if any. 1479| 0| let currentDependency: ManagedDependency? 1480| 0| if let existingDependency = managedDependencies[forURL: packageRef.path] { 1481| 0| currentDependency = existingDependency 1482| 0| } else { 1483| 0| // Check if this is a edited dependency. 1484| 0| // 1485| 0| // This is a little bit ugly but can probably be cleaned up by 1486| 0| // putting information in the PackageReference type. We change 1487| 0| // the package reference for edited packages which causes the 1488| 0| // original checkout in somewhat of a dangling state when computing 1489| 0| // the state changes this method. We basically need to ensure that 1490| 0| // the edited checkout is unchanged. 1491| 0| if let editedDependency = managedDependencies.values.first(where: { 1492| 0| guard $0.basedOn != nil else { return false } 1493| 0| return path(for: $0).pathString == packageRef.path 1494| 0| }) { 1495| 0| currentDependency = editedDependency 1496| 0| let originalReference = editedDependency.basedOn!.packageRef 1497| 0| packageStateChanges[originalReference.path] = (originalReference, .unchanged) 1498| 0| } else { 1499| 0| currentDependency = nil 1500| 0| } 1501| 0| } 1502| 0| 1503| 0| switch binding { 1504| 0| case .excluded: 1505| 0| fatalError("Unexpected excluded binding") 1506| 0| 1507| 0| case .unversioned: 1508| 0| // Ignore the root packages. 1509| 0| if root.packageRefs.contains(packageRef) { 1510| 0| continue 1511| 0| } 1512| 0| 1513| 0| if let currentDependency = currentDependency { 1514| 0| switch currentDependency.state { 1515| 0| case .local, .edited: 1516| 0| packageStateChanges[packageRef.path] = (packageRef, .unchanged) 1517| 0| case .checkout: 1518| 0| packageStateChanges[packageRef.path] = (packageRef, .updated(.unversioned)) 1519| 0| } 1520| 0| } else { 1521| 0| packageStateChanges[packageRef.path] = (packageRef, .added(.unversioned)) 1522| 0| } 1523| 0| 1524| 0| case .revision(let identifier): 1525| 0| // Get the latest revision from the container. 1526| 0| let container = try await { 1527| 0| containerProvider.getContainer(for: packageRef, skipUpdate: true, completion: $0) 1528| 0| } as! RepositoryPackageContainer 1529| 0| var revision = try container.getRevision(forIdentifier: identifier) 1530| 0| let branch = identifier == revision.identifier ? nil : identifier 1531| 0| 1532| 0| // If we have a branch and we shouldn't be updating the 1533| 0| // branches, use the revision from pin instead (if present). 1534| 0| if branch != nil { 1535| 0| if let pin = pinsStore.pins.first(where: { $0.packageRef == packageRef }), 1536| 0| !updateBranches, 1537| 0| pin.state.branch == branch { 1538| 0| revision = pin.state.revision 1539| 0| } 1540| 0| } 1541| 0| 1542| 0| // First check if we have this dependency. 1543| 0| if let currentDependency = currentDependency { 1544| 0| // If current state and new state are equal, we don't need 1545| 0| // to do anything. 1546| 0| let newState = CheckoutState(revision: revision, branch: branch) 1547| 0| if case .checkout(let checkoutState) = currentDependency.state, checkoutState == newState { 1548| 0| packageStateChanges[packageRef.path] = (packageRef, .unchanged) 1549| 0| } else { 1550| 0| // Otherwise, we need to update this dependency to this revision. 1551| 0| packageStateChanges[packageRef.path] = (packageRef, .updated(.revision(revision, branch: branch))) 1552| 0| } 1553| 0| } else { 1554| 0| packageStateChanges[packageRef.path] = (packageRef, .added(.revision(revision, branch: branch))) 1555| 0| } 1556| 0| 1557| 0| case .version(let version): 1558| 0| if let currentDependency = currentDependency { 1559| 0| if case .checkout(let checkoutState) = currentDependency.state, checkoutState.version == version { 1560| 0| packageStateChanges[packageRef.path] = (packageRef, .unchanged) 1561| 0| } else { 1562| 0| packageStateChanges[packageRef.path] = (packageRef, .updated(.version(version))) 1563| 0| } 1564| 0| } else { 1565| 0| packageStateChanges[packageRef.path] = (packageRef, .added(.version(version))) 1566| 0| } 1567| 0| } 1568| 0| } 1569| 0| // Set the state of any old package that might have been removed. 1570| 0| let dependencies = managedDependencies.values 1571| 0| for packageRef in dependencies.lazy.map({ $0.packageRef }) where packageStateChanges[packageRef.path] == nil { 1572| 0| packageStateChanges[packageRef.path] = (packageRef, .removed) 1573| 0| } 1574| 0| 1575| 0| return Array(packageStateChanges.values) 1576| 0| } 1577| | 1578| | /// Creates resolver for the workspace. 1579| 0| fileprivate func createResolver() -> PackageResolver { 1580| 0| let resolverDelegate = WorkspaceResolverDelegate() 1581| 0| if enablePubgrubResolver { 1582| 0| let resolver = PubgrubResolver(containerProvider, resolverDelegate, 1583| 0| skipUpdate: skipUpdate) 1584| 0| return .pubgrub(resolver) 1585| 0| } else { 1586| 0| let resolver = DependencyResolver(containerProvider, resolverDelegate, 1587| 0| isPrefetchingEnabled: isResolverPrefetchingEnabled, 1588| 0| skipUpdate: skipUpdate) 1589| 0| return .legacy(resolver) 1590| 0| } 1591| 0| } 1592| | 1593| | /// Runs the dependency resolver based on constraints provided and returns the results. 1594| | fileprivate func resolveDependencies( 1595| | resolver: PackageResolver? = nil, 1596| | dependencies: [RepositoryPackageConstraint], 1597| | pins: [RepositoryPackageConstraint] = [], 1598| | diagnostics: DiagnosticsEngine 1599| 0| ) -> [(container: WorkspaceResolverDelegate.Identifier, binding: BoundVersion)] { 1600| 0| let resolver = resolver ?? createResolver() 1601| 0| 1602| 0| let result = resolver.resolve(dependencies: dependencies, pins: pins) 1603| 0| 1604| 0| // Take an action based on the result. 1605| 0| switch result { 1606| 0| case .success(let bindings): 1607| 0| return bindings 1608| 0| 1609| 0| case .unsatisfiable(let dependencies, let pins): 1610| 0| diagnostics.emit(data: ResolverDiagnostics.Unsatisfiable(dependencies: dependencies, pins: pins)) 1611| 0| return [] 1612| 0| 1613| 0| case .error(let error): 1614| 0| switch error { 1615| 0| // Emit proper error if we were not able to parse some manifest during dependency resolution. 1616| 0| case let error as RepositoryPackageContainer.GetDependenciesErrorWrapper: 1617| 0| let location = PackageLocation.Remote(url: error.containerIdentifier, reference: error.reference) 1618| 0| diagnostics.emit(error.underlyingError, location: location) 1619| 0| 1620| 0| default: 1621| 0| diagnostics.emit(error) 1622| 0| } 1623| 0| 1624| 0| return [] 1625| 0| } 1626| 0| } 1627| | 1628| | /// Validates that all the edited dependencies are still present in the file system. 1629| | /// If some checkout dependency is reomved form the file system, clone it again. 1630| | /// If some edited dependency is removed from the file system, mark it as unedited and 1631| | /// fallback on the original checkout. 1632| 0| fileprivate func fixManagedDependencies(with diagnostics: DiagnosticsEngine) { 1633| 0| 1634| 0| // Reset managed dependencies if the state file was removed during the lifetime of the Workspace object. 1635| 0| if managedDependencies.values.contains(where: { _ in true }) && !managedDependencies.stateFileExists() { 1636| 0| try? managedDependencies.reset() 1637| 0| } 1638| 0| 1639| 0| for dependency in managedDependencies.values { 1640| 0| diagnostics.wrap { 1641| 0| 1642| 0| // If the dependency is present, we're done. 1643| 0| let dependencyPath = path(for: dependency) 1644| 0| guard !fileSystem.isDirectory(dependencyPath) else { return } 1645| 0| 1646| 0| switch dependency.state { 1647| 0| case .checkout(let checkoutState): 1648| 0| // If some checkout dependency has been removed, clone it again. 1649| 0| _ = try clone(package: dependency.packageRef, at: checkoutState) 1650| 0| diagnostics.emit(WorkspaceDiagnostics.CheckedOutDependencyMissing(packageName: dependency.packageRef.identity)) 1651| 0| 1652| 0| case .edited: 1653| 0| // If some edited dependency has been removed, mark it as unedited. 1654| 0| // 1655| 0| // Note: We don't resolve the dependencies when unediting 1656| 0| // here because we expect this method to be called as part 1657| 0| // of some other resolve operation (i.e. resolve, update, etc). 1658| 0| try unedit(dependency: dependency, forceRemove: true, diagnostics: diagnostics) 1659| 0| 1660| 0| diagnostics.emit(WorkspaceDiagnostics.EditedDependencyMissing(packageName: dependency.packageRef.identity)) 1661| 0| 1662| 0| case .local: 1663| 0| managedDependencies[forURL: dependency.packageRef.path] = nil 1664| 0| try managedDependencies.saveState() 1665| 0| } 1666| 0| } 1667| 0| } 1668| 0| } 1669| |} 1670| | 1671| |// MARK: - Repository Management 1672| | 1673| |extension Workspace { 1674| | 1675| | /// Updates the current working checkouts i.e. clone or remove based on the 1676| | /// provided dependency resolution result. 1677| | /// 1678| | /// - Parameters: 1679| | /// - updateResults: The updated results from dependency resolution. 1680| | /// - diagnostics: The diagnostics engine that reports errors, warnings 1681| | /// and notes. 1682| | /// - updateBranches: If the branches should be updated in case they're pinned. 1683| | fileprivate func updateCheckouts( 1684| | root: PackageGraphRoot, 1685| | updateResults: [(PackageReference, BoundVersion)], 1686| | updateBranches: Bool = false, 1687| | diagnostics: DiagnosticsEngine 1688| 0| ) { 1689| 0| // Get the update package states from resolved results. 1690| 0| guard let packageStateChanges = diagnostics.wrap({ 1691| 0| try computePackageStateChanges(root: root, resolvedDependencies: updateResults, updateBranches: updateBranches) 1692| 0| }) else { 1693| 0| return 1694| 0| } 1695| 0| 1696| 0| // First remove the checkouts that are no longer required. 1697| 0| for (packageRef, state) in packageStateChanges { 1698| 0| diagnostics.wrap { 1699| 0| switch state { 1700| 0| case .added, .updated, .unchanged: break 1701| 0| case .removed: 1702| 0| try remove(package: packageRef) 1703| 0| } 1704| 0| } 1705| 0| } 1706| 0| 1707| 0| // Update or clone new packages. 1708| 0| for (packageRef, state) in packageStateChanges { 1709| 0| diagnostics.wrap { 1710| 0| switch state { 1711| 0| case .added(let requirement): 1712| 0| _ = try clone(package: packageRef, requirement: requirement) 1713| 0| case .updated(let requirement): 1714| 0| _ = try clone(package: packageRef, requirement: requirement) 1715| 0| case .removed, .unchanged: break 1716| 0| } 1717| 0| } 1718| 0| } 1719| 0| 1720| 0| // Inform the delegate if nothing was updated. 1721| 0| if packageStateChanges.filter({ $0.1 == .unchanged }).count == packageStateChanges.count { 1722| 0| delegate?.dependenciesUpToDate() 1723| 0| } 1724| 0| } 1725| | 1726| | /// Fetch a given `repository` and create a local checkout for it. 1727| | /// 1728| | /// This will first clone the repository into the canonical repositories 1729| | /// location, if necessary, and then check it out from there. 1730| | /// 1731| | /// - Returns: The path of the local repository. 1732| | /// - Throws: If the operation could not be satisfied. 1733| 0| private func fetch(package: PackageReference) throws -> AbsolutePath { 1734| 0| // If we already have it, fetch to update the repo from its remote. 1735| 0| if let dependency = managedDependencies[forURL: package.path] { 1736| 0| let path = checkoutsPath.appending(dependency.subpath) 1737| 0| 1738| 0| // Make sure the directory is not missing (we will have to clone again 1739| 0| // if not). 1740| 0| fetch: if fileSystem.isDirectory(path) { 1741| 0| // Fetch the checkout in case there are updates available. 1742| 0| let workingRepo = try repositoryManager.provider.openCheckout(at: path) 1743| 0| 1744| 0| // Ensure that the alternative object store is still valid. 1745| 0| // 1746| 0| // This can become invalid if the build directory is moved. 1747| 0| guard workingRepo.isAlternateObjectStoreValid() else { 1748| 0| break fetch 1749| 0| } 1750| 0| 1751| 0| // The fetch operation may update contents of the checkout, so 1752| 0| // we need do mutable-immutable dance. 1753| 0| try fileSystem.chmod(.userWritable, path: path, options: [.recursive, .onlyFiles]) 1754| 0| try workingRepo.fetch() 1755| 0| try? fileSystem.chmod(.userUnWritable, path: path, options: [.recursive, .onlyFiles]) 1756| 0| 1757| 0| return path 1758| 0| } 1759| 0| } 1760| 0| 1761| 0| // If not, we need to get the repository from the checkouts. 1762| 0| let handle = try await { 1763| 0| repositoryManager.lookup(repository: package.repository, skipUpdate: true, completion: $0) 1764| 0| } 1765| 0| 1766| 0| // Clone the repository into the checkouts. 1767| 0| let path = checkoutsPath.appending(component: package.repository.basename) 1768| 0| 1769| 0| try fileSystem.chmod(.userWritable, path: path, options: [.recursive, .onlyFiles]) 1770| 0| try fileSystem.removeFileTree(path) 1771| 0| 1772| 0| // Inform the delegate that we're starting cloning. 1773| 0| delegate?.cloning(repository: handle.repository.url) 1774| 0| try handle.cloneCheckout(to: path, editable: false) 1775| 0| 1776| 0| return path 1777| 0| } 1778| | 1779| | // FIXME: @testable internal 1780| | // 1781| | /// Create a local clone of the given `repository` checked out to `version`. 1782| | /// 1783| | /// If an existing clone is present, the repository will be reset to the 1784| | /// requested revision, if necessary. 1785| | /// 1786| | /// - Parameters: 1787| | /// - package: The package to clone. 1788| | /// - checkoutState: The state to check out. 1789| | /// - Returns: The path of the local repository. 1790| | /// - Throws: If the operation could not be satisfied. 1791| | func clone( 1792| | package: PackageReference, 1793| | at checkoutState: CheckoutState 1794| 0| ) throws -> AbsolutePath { 1795| 0| // Get the repository. 1796| 0| let path = try fetch(package: package) 1797| 0| 1798| 0| // Check out the given revision. 1799| 0| let workingRepo = try repositoryManager.provider.openCheckout(at: path) 1800| 0| 1801| 0| // Inform the delegate. 1802| 0| delegate?.checkingOut(repository: package.repository.url, atReference: checkoutState.description, to: path) 1803| 0| 1804| 0| // Do mutable-immutable dance because checkout operation modifies the disk state. 1805| 0| try fileSystem.chmod(.userWritable, path: path, options: [.recursive, .onlyFiles]) 1806| 0| try workingRepo.checkout(revision: checkoutState.revision) 1807| 0| try? fileSystem.chmod(.userUnWritable, path: path, options: [.recursive, .onlyFiles]) 1808| 0| 1809| 0| // Write the state record. 1810| 0| managedDependencies[forURL: package.path] = ManagedDependency( 1811| 0| packageRef: package, 1812| 0| subpath: path.relative(to: checkoutsPath), 1813| 0| checkoutState: checkoutState) 1814| 0| try managedDependencies.saveState() 1815| 0| 1816| 0| return path 1817| 0| } 1818| | 1819| | private func clone( 1820| | package: PackageReference, 1821| | requirement: PackageStateChange.Requirement 1822| 0| ) throws -> AbsolutePath { 1823| 0| let checkoutState: CheckoutState 1824| 0| 1825| 0| switch requirement { 1826| 0| case .version(let version): 1827| 0| // FIXME: We need to get the revision here, and we don't have a 1828| 0| // way to get it back out of the resolver which is very 1829| 0| // annoying. Maybe we should make an SPI on the provider for 1830| 0| // this? 1831| 0| let container = try await { containerProvider.getContainer(for: package, skipUpdate: true, completion: $0) } as! RepositoryPackageContainer 1832| 0| let tag = container.getTag(for: version)! 1833| 0| let revision = try container.getRevision(forTag: tag) 1834| 0| checkoutState = CheckoutState(revision: revision, version: version) 1835| 0| 1836| 0| case .revision(let revision, let branch): 1837| 0| checkoutState = CheckoutState(revision: revision, branch: branch) 1838| 0| 1839| 0| case .unversioned: 1840| 0| managedDependencies[forURL: package.path] = ManagedDependency.local(packageRef: package) 1841| 0| try managedDependencies.saveState() 1842| 0| return AbsolutePath(package.path) 1843| 0| } 1844| 0| 1845| 0| return try self.clone(package: package, at: checkoutState) 1846| 0| } 1847| | 1848| | /// Removes the clone and checkout of the provided specifier. 1849| 0| fileprivate func remove(package: PackageReference) throws { 1850| 0| 1851| 0| guard let dependency = managedDependencies[forURL: package.path] else { 1852| 0| fatalError("This should never happen, trying to remove \(package.identity) which isn't in workspace") 1853| 0| } 1854| 0| 1855| 0| // We only need to update the managed dependency structure to "remove" 1856| 0| // a local package. 1857| 0| // 1858| 0| // Note that we don't actually remove a local package from disk. 1859| 0| switch dependency.state { 1860| 0| case .local: 1861| 0| managedDependencies[forURL: package.path] = nil 1862| 0| try managedDependencies.saveState() 1863| 0| return 1864| 0| case .checkout, .edited: 1865| 0| break 1866| 0| } 1867| 0| 1868| 0| // Inform the delegate. 1869| 0| delegate?.removing(repository: dependency.packageRef.repository.url) 1870| 0| 1871| 0| // Compute the dependency which we need to remove. 1872| 0| let dependencyToRemove: ManagedDependency 1873| 0| 1874| 0| if let basedOn = dependency.basedOn { 1875| 0| // Remove the underlying dependency for edited packages. 1876| 0| dependencyToRemove = basedOn 1877| 0| dependency.basedOn = nil 1878| 0| managedDependencies[forURL: dependency.packageRef.path] = dependency 1879| 0| } else { 1880| 0| dependencyToRemove = dependency 1881| 0| managedDependencies[forURL: dependencyToRemove.packageRef.path] = nil 1882| 0| } 1883| 0| 1884| 0| // Remove the checkout. 1885| 0| let dependencyPath = checkoutsPath.appending(dependencyToRemove.subpath) 1886| 0| let checkedOutRepo = try repositoryManager.provider.openCheckout(at: dependencyPath) 1887| 0| guard !checkedOutRepo.hasUncommittedChanges() else { 1888| 0| throw WorkspaceDiagnostics.UncommitedChanges(repositoryPath: dependencyPath) 1889| 0| } 1890| 0| 1891| 0| try fileSystem.chmod(.userWritable, path: dependencyPath, options: [.recursive, .onlyFiles]) 1892| 0| try fileSystem.removeFileTree(dependencyPath) 1893| 0| 1894| 0| // Remove the clone. 1895| 0| try repositoryManager.remove(repository: dependencyToRemove.packageRef.repository) 1896| 0| 1897| 0| // Save the state. 1898| 0| try managedDependencies.saveState() 1899| 0| } 1900| |} 1901| | 1902| |/// A result which can be loaded. 1903| |/// 1904| |/// It is useful for objects that holds a state on disk and needs to be 1905| |/// loaded frequently. 1906| |public final class LoadableResult { 1907| | 1908| | /// The constructor closure for the value. 1909| | private let construct: () throws -> Value 1910| | 1911| | /// Create a loadable result. 1912| 0| public init(_ construct: @escaping () throws -> Value) { 1913| 0| self.construct = construct 1914| 0| } 1915| | 1916| | /// Load and return the result. 1917| 0| public func loadResult() -> Result { 1918| 0| return Result(anyError: { 1919| 0| try self.construct() 1920| 0| }) 1921| 0| } 1922| | 1923| | /// Load and return the value. 1924| 0| public func load() throws -> Value { 1925| 0| return try loadResult().dematerialize() 1926| 0| } 1927| |} <<<<<< EOF # path=Build.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/BuildDelegate.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import SPMLLBuild 14| |import Dispatch 15| | 16| |/// Diagnostic error when a llbuild command encounters an error. 17| |struct LLBuildCommandErrorDiagnostic: DiagnosticData { 18| | static let id = DiagnosticID( 19| | type: LLBuildCommandErrorDiagnostic.self, 20| | name: "org.swift.diags.llbuild-command-error", 21| | defaultBehavior: .error, 22| 0| description: { $0 <<< { $0.message } } 23| | ) 24| | 25| | let message: String 26| |} 27| | 28| |/// Diagnostic warning when a llbuild command encounters a warning. 29| |struct LLBuildCommandWarningDiagnostic: DiagnosticData { 30| | static let id = DiagnosticID( 31| | type: LLBuildCommandWarningDiagnostic.self, 32| | name: "org.swift.diags.llbuild-command-warning", 33| | defaultBehavior: .warning, 34| 0| description: { $0 <<< { $0.message } } 35| | ) 36| | 37| | let message: String 38| |} 39| | 40| |/// Diagnostic note when a llbuild command encounters a warning. 41| |struct LLBuildCommandNoteDiagnostic: DiagnosticData { 42| | static let id = DiagnosticID( 43| | type: LLBuildCommandNoteDiagnostic.self, 44| | name: "org.swift.diags.llbuild-command-note", 45| | defaultBehavior: .note, 46| 0| description: { $0 <<< { $0.message } } 47| | ) 48| | 49| | let message: String 50| |} 51| | 52| |/// Diagnostic error when llbuild detects a cycle. 53| |struct LLBuildCycleErrorDiagnostic: DiagnosticData { 54| | static let id = DiagnosticID( 55| | type: LLBuildCycleErrorDiagnostic.self, 56| | name: "org.swift.diags.llbuild-cycle", 57| | defaultBehavior: .error, 58| 0| description: { 59| 0| $0 <<< "build cycle detected: " 60| 0| $0 <<< { $0.rules.map({ $0.key }).joined(separator: ", ") } 61| 0| } 62| | ) 63| | 64| | let rules: [BuildKey] 65| |} 66| | 67| |/// Diagnostic error from llbuild 68| |struct LLBuildErrorDiagnostic: DiagnosticData { 69| | static let id = DiagnosticID( 70| | type: LLBuildErrorDiagnostic.self, 71| | name: "org.swift.diags.llbuild-error", 72| | defaultBehavior: .error, 73| | description: { 74| 0| $0 <<< { $0.message } 75| | } 76| | ) 77| | 78| | let message: String 79| |} 80| | 81| |/// Diagnostic warning from llbuild 82| |struct LLBuildWarningDiagnostic: DiagnosticData { 83| | static let id = DiagnosticID( 84| | type: LLBuildWarningDiagnostic.self, 85| | name: "org.swift.diags.llbuild-warning", 86| | defaultBehavior: .warning, 87| | description: { 88| 0| $0 <<< { $0.message } 89| | } 90| | ) 91| | 92| | let message: String 93| |} 94| | 95| |/// Diagnostic note from llbuild 96| |struct LLBuildNoteDiagnostic: DiagnosticData { 97| | static let id = DiagnosticID( 98| | type: LLBuildNoteDiagnostic.self, 99| | name: "org.swift.diags.llbuild-note", 100| | defaultBehavior: .note, 101| | description: { 102| 0| $0 <<< { $0.message } 103| | } 104| | ) 105| | 106| | let message: String 107| |} 108| | 109| |/// Missing inptus from LLBuild 110| |struct LLBuildMissingInputs: DiagnosticData { 111| | static let id = DiagnosticID( 112| | type: LLBuildMissingInputs.self, 113| | name: "org.swift.diags.llbuild-missing-inputs", 114| | defaultBehavior: .error, 115| 0| description: { 116| 0| $0 <<< "couldn't build " 117| 0| $0 <<< { $0.output.key } 118| 0| $0 <<< " because of missing inputs: " 119| 0| $0 <<< { $0.inputs.map({ $0.key }).joined(separator: ", ") } 120| 0| } 121| | ) 122| | 123| | let output: BuildKey 124| | let inputs: [BuildKey] 125| |} 126| | 127| |/// Multiple producers from LLBuild 128| |struct LLBuildMultipleProducers: DiagnosticData { 129| | static let id = DiagnosticID( 130| | type: LLBuildMultipleProducers.self, 131| | name: "org.swift.diags.llbuild-multiple-producers", 132| | defaultBehavior: .error, 133| 0| description: { 134| 0| $0 <<< "couldn't build " 135| 0| $0 <<< { $0.output.key } 136| 0| $0 <<< " because of multiple producers: " 137| 0| $0 <<< { $0.commands.map({ $0.description }).joined(separator: ", ") } 138| 0| } 139| | ) 140| | 141| | let output: BuildKey 142| | let commands: [SPMLLBuild.Command] 143| |} 144| | 145| |/// Command error from LLBuild 146| |struct LLBuildCommandError: DiagnosticData { 147| | static let id = DiagnosticID( 148| | type: LLBuildCommandError.self, 149| | name: "org.swift.diags.llbuild-command-error", 150| | defaultBehavior: .error, 151| 0| description: { 152| 0| $0 <<< "command " 153| 0| $0 <<< { $0.command.description } 154| 0| $0 <<< " failed: " 155| 0| $0 <<< { $0.message } 156| 0| } 157| | ) 158| | 159| | let command: SPMLLBuild.Command 160| | let message: String 161| |} 162| | 163| |extension SPMLLBuild.Diagnostic: DiagnosticDataConvertible { 164| 0| public var diagnosticData: DiagnosticData { 165| 0| switch kind { 166| 0| case .error: return LLBuildErrorDiagnostic(message: message) 167| 0| case .warning: return LLBuildWarningDiagnostic(message: message) 168| 0| case .note: return LLBuildNoteDiagnostic(message: message) 169| 0| } 170| 0| } 171| |} 172| | 173| |private let newLineByte: UInt8 = 10 174| |public final class BuildDelegate: BuildSystemDelegate { 175| | // Track counts of commands based on their CommandStatusKind 176| | private struct CommandCounter { 177| | var scanningCount = 0 178| | var upToDateCount = 0 179| | var completedCount = 0 180| | var startedCount = 0 181| | 182| 0| var estimatedMaximum: Int { 183| 0| return completedCount + scanningCount - upToDateCount 184| 0| } 185| | 186| 0| mutating func update(command: SPMLLBuild.Command, kind: CommandStatusKind) { 187| 0| guard command.shouldShowStatus else { return } 188| 0| 189| 0| switch kind { 190| 0| case .isScanning: 191| 0| scanningCount += 1 192| 0| case .isUpToDate: 193| 0| scanningCount -= 1 194| 0| upToDateCount += 1 195| 0| completedCount += 1 196| 0| case .isComplete: 197| 0| scanningCount -= 1 198| 0| completedCount += 1 199| 0| } 200| 0| } 201| | } 202| | 203| | private let diagnostics: DiagnosticsEngine 204| | public var outputStream: ThreadSafeOutputByteStream 205| | public var progressAnimation: ProgressAnimationProtocol 206| | public var isVerbose: Bool = false 207| | public var onCommmandFailure: (() -> Void)? 208| | private var commandCounter = CommandCounter() 209| | private let queue = DispatchQueue(label: "org.swift.swiftpm.build-delegate") 210| | 211| | public init( 212| | diagnostics: DiagnosticsEngine, 213| | outputStream: OutputByteStream, 214| | progressAnimation: ProgressAnimationProtocol 215| 0| ) { 216| 0| self.diagnostics = diagnostics 217| 0| // FIXME: Implement a class convenience initializer that does this once they are supported 218| 0| // https://forums.swift.org/t/allow-self-x-in-class-convenience-initializers/15924 219| 0| self.outputStream = outputStream as? ThreadSafeOutputByteStream ?? ThreadSafeOutputByteStream(outputStream) 220| 0| self.progressAnimation = progressAnimation 221| 0| } 222| | 223| 0| public var fs: SPMLLBuild.FileSystem? { 224| 0| return nil 225| 0| } 226| | 227| 0| public func lookupTool(_ name: String) -> Tool? { 228| 0| return nil 229| 0| } 230| | 231| 0| public func hadCommandFailure() { 232| 0| onCommmandFailure?() 233| 0| } 234| | 235| 0| public func handleDiagnostic(_ diagnostic: SPMLLBuild.Diagnostic) { 236| 0| diagnostics.emit(diagnostic) 237| 0| } 238| | 239| 0| public func commandStatusChanged(_ command: SPMLLBuild.Command, kind: CommandStatusKind) { 240| 0| queue.sync { 241| 0| commandCounter.update(command: command, kind: kind) 242| 0| } 243| 0| } 244| | 245| 0| public func commandPreparing(_ command: SPMLLBuild.Command) { 246| 0| } 247| | 248| 0| public func commandStarted(_ command: SPMLLBuild.Command) { 249| 0| guard command.shouldShowStatus else { return } 250| 0| 251| 0| queue.sync { 252| 0| commandCounter.startedCount += 1 253| 0| 254| 0| if isVerbose { 255| 0| outputStream <<< command.verboseDescription <<< "\n" 256| 0| outputStream.flush() 257| 0| } else { 258| 0| progressAnimation.update( 259| 0| step: commandCounter.startedCount, 260| 0| total: commandCounter.estimatedMaximum, 261| 0| text: command.description) 262| 0| } 263| 0| } 264| 0| } 265| | 266| 0| public func shouldCommandStart(_ command: SPMLLBuild.Command) -> Bool { 267| 0| return true 268| 0| } 269| | 270| 0| public func commandFinished(_ command: SPMLLBuild.Command, result: CommandResult) { 271| 0| } 272| | 273| 0| public func commandHadError(_ command: SPMLLBuild.Command, message: String) { 274| 0| diagnostics.emit(data: LLBuildCommandErrorDiagnostic(message: message)) 275| 0| } 276| | 277| 0| public func commandHadNote(_ command: SPMLLBuild.Command, message: String) { 278| 0| diagnostics.emit(data: LLBuildCommandNoteDiagnostic(message: message)) 279| 0| } 280| | 281| 0| public func commandHadWarning(_ command: SPMLLBuild.Command, message: String) { 282| 0| diagnostics.emit(data: LLBuildCommandWarningDiagnostic(message: message)) 283| 0| } 284| | 285| | public func commandCannotBuildOutputDueToMissingInputs( 286| | _ command: SPMLLBuild.Command, 287| | output: BuildKey, 288| | inputs: [BuildKey] 289| 0| ) { 290| 0| diagnostics.emit(data: LLBuildMissingInputs(output: output, inputs: inputs)) 291| 0| } 292| | 293| 0| public func cannotBuildNodeDueToMultipleProducers(output: BuildKey, commands: [SPMLLBuild.Command]) { 294| 0| diagnostics.emit(data: LLBuildMultipleProducers(output: output, commands: commands)) 295| 0| } 296| | 297| 0| public func commandProcessStarted(_ command: SPMLLBuild.Command, process: ProcessHandle) { 298| 0| } 299| | 300| 0| public func commandProcessHadError(_ command: SPMLLBuild.Command, process: ProcessHandle, message: String) { 301| 0| diagnostics.emit(data: LLBuildCommandError(command: command, message: message)) 302| 0| } 303| | 304| 0| public func commandProcessHadOutput(_ command: SPMLLBuild.Command, process: ProcessHandle, data: [UInt8]) { 305| 0| progressAnimation.clear() 306| 0| outputStream <<< data 307| 0| outputStream.flush() 308| 0| } 309| | 310| | public func commandProcessFinished( 311| | _ command: SPMLLBuild.Command, 312| | process: ProcessHandle, 313| | result: CommandExtendedResult 314| 0| ) { 315| 0| } 316| | 317| 0| public func cycleDetected(rules: [BuildKey]) { 318| 0| diagnostics.emit(data: LLBuildCycleErrorDiagnostic(rules: rules)) 319| 0| } 320| | 321| 0| public func shouldResolveCycle(rules: [BuildKey], candidate: BuildKey, action: CycleAction) -> Bool { 322| 0| return false 323| 0| } 324| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/BuildPlan.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright 2015 - 2016 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import PackageModel 14| |import PackageGraph 15| |import PackageLoading 16| |import func POSIX.getenv 17| | 18| |public struct BuildParameters { 19| | 20| | /// Mode for the indexing-while-building feature. 21| | public enum IndexStoreMode: Equatable { 22| | /// Index store should be enabled. 23| | case on 24| | /// Index store should be disabled. 25| | case off 26| | /// Index store should be enabled in debug configuration. 27| | case auto 28| | } 29| | 30| | // FIXME: Error handling. 31| | // 32| | /// Path to the module cache directory to use for SwiftPM's own tests. 33| | public static let swiftpmTestCache = resolveSymlinks(try! determineTempDirectory()).appending(component: "org.swift.swiftpm.tests-3") 34| | 35| | /// Returns the directory to be used for module cache. 36| 0| fileprivate var moduleCache: AbsolutePath { 37| 0| let base: AbsolutePath 38| 0| // FIXME: We use this hack to let swiftpm's functional test use shared 39| 0| // cache so it doesn't become painfully slow. 40| 0| if getenv("IS_SWIFTPM_TEST") != nil { 41| 0| base = BuildParameters.swiftpmTestCache 42| 0| } else { 43| 0| base = buildPath 44| 0| } 45| 0| return base.appending(component: "ModuleCache") 46| 0| } 47| | 48| | /// The path to the data directory. 49| | public let dataPath: AbsolutePath 50| | 51| | /// The build configuration. 52| | public let configuration: BuildConfiguration 53| | 54| | /// The path to the build directory (inside the data directory). 55| 0| public var buildPath: AbsolutePath { 56| 0| return dataPath.appending(component: configuration.dirname) 57| 0| } 58| | 59| | /// The path to the index store directory. 60| 0| public var indexStore: AbsolutePath { 61| 0| assert(indexStoreMode != .off, "index store is disabled") 62| 0| return buildPath.appending(components: "index", "store") 63| 0| } 64| | 65| | /// The path to the code coverage directory. 66| 0| public var codeCovPath: AbsolutePath { 67| 0| return buildPath.appending(component: "codecov") 68| 0| } 69| | 70| | /// The path to the code coverage profdata file. 71| 0| public var codeCovDataFile: AbsolutePath { 72| 0| return codeCovPath.appending(component: "default.profdata") 73| 0| } 74| | 75| | /// The toolchain. 76| | public let toolchain: Toolchain 77| | 78| | /// Destination triple. 79| | public let triple: Triple 80| | 81| | /// Extra build flags. 82| | public let flags: BuildFlags 83| | 84| | /// Extra flags to pass to Swift compiler. 85| 0| public var swiftCompilerFlags: [String] { 86| 0| var flags = self.flags.cCompilerFlags.flatMap({ ["-Xcc", $0] }) 87| 0| flags += self.flags.swiftCompilerFlags 88| 0| flags += verbosity.ccArgs 89| 0| return flags 90| 0| } 91| | 92| | /// Extra flags to pass to linker. 93| 0| public var linkerFlags: [String] { 94| 0| // Arguments that can be passed directly to the Swift compiler and 95| 0| // doesn't require -Xlinker prefix. 96| 0| // 97| 0| // We do this to avoid sending flags like linker search path at the end 98| 0| // of the search list. 99| 0| let directSwiftLinkerArgs = ["-L"] 100| 0| 101| 0| var flags: [String] = [] 102| 0| var it = self.flags.linkerFlags.makeIterator() 103| 0| while let flag = it.next() { 104| 0| if directSwiftLinkerArgs.contains(flag) { 105| 0| // `-L ` variant. 106| 0| flags.append(flag) 107| 0| guard let nextFlag = it.next() else { 108| 0| // We expected a flag but don't have one. 109| 0| continue 110| 0| } 111| 0| flags.append(nextFlag) 112| 0| } else if directSwiftLinkerArgs.contains(where: { flag.hasPrefix($0) }) { 113| 0| // `-L` variant. 114| 0| flags.append(flag) 115| 0| } else { 116| 0| flags += ["-Xlinker", flag] 117| 0| } 118| 0| } 119| 0| return flags 120| 0| } 121| | 122| | /// The tools version to use. 123| | public let toolsVersion: ToolsVersion 124| | 125| | /// If should link the Swift stdlib statically. 126| | public let shouldLinkStaticSwiftStdlib: Bool 127| | 128| | /// Which compiler sanitizers should be enabled 129| | public let sanitizers: EnabledSanitizers 130| | 131| | /// If should enable llbuild manifest caching. 132| | public let shouldEnableManifestCaching: Bool 133| | 134| | /// The mode to use for indexing-while-building feature. 135| | public let indexStoreMode: IndexStoreMode 136| | 137| | /// Whether to enable code coverage. 138| | public let enableCodeCoverage: Bool 139| | 140| | /// Whether to enable generation of `.swiftinterface` files alongside 141| | /// `.swiftmodule`s. 142| | public let enableParseableModuleInterfaces: Bool 143| | 144| | /// Checks if stdout stream is tty. 145| 0| fileprivate let isTTY: Bool = { 146| 0| guard let stream = stdoutStream.stream as? LocalFileOutputByteStream else { 147| 0| return false 148| 0| } 149| 0| return TerminalController.isTTY(stream) 150| 0| }() 151| | 152| 0| public var regenerateManifestToken: AbsolutePath { 153| 0| return dataPath.appending(components: "..", "regenerate-token") 154| 0| } 155| | 156| 0| public var llbuildManifest: AbsolutePath { 157| 0| return dataPath.appending(components: "..", configuration.dirname + ".yaml") 158| 0| } 159| | 160| | public init( 161| | dataPath: AbsolutePath, 162| | configuration: BuildConfiguration, 163| | toolchain: Toolchain, 164| | destinationTriple: Triple = Triple.hostTriple, 165| | flags: BuildFlags, 166| | toolsVersion: ToolsVersion = ToolsVersion.currentToolsVersion, 167| | shouldLinkStaticSwiftStdlib: Bool = false, 168| | shouldEnableManifestCaching: Bool = false, 169| | sanitizers: EnabledSanitizers = EnabledSanitizers(), 170| | enableCodeCoverage: Bool = false, 171| | indexStoreMode: IndexStoreMode = .auto, 172| | enableParseableModuleInterfaces: Bool = false 173| 0| ) { 174| 0| self.dataPath = dataPath 175| 0| self.configuration = configuration 176| 0| self.toolchain = toolchain 177| 0| self.triple = destinationTriple 178| 0| self.flags = flags 179| 0| self.toolsVersion = toolsVersion 180| 0| self.shouldLinkStaticSwiftStdlib = shouldLinkStaticSwiftStdlib 181| 0| self.shouldEnableManifestCaching = shouldEnableManifestCaching 182| 0| self.sanitizers = sanitizers 183| 0| self.enableCodeCoverage = enableCodeCoverage 184| 0| self.indexStoreMode = indexStoreMode 185| 0| self.enableParseableModuleInterfaces = enableParseableModuleInterfaces 186| 0| } 187| | 188| | /// Returns the compiler arguments for the index store, if enabled. 189| 0| fileprivate var indexStoreArguments: [String] { 190| 0| let addIndexStoreArguments: Bool 191| 0| switch indexStoreMode { 192| 0| case .on: 193| 0| addIndexStoreArguments = true 194| 0| case .off: 195| 0| addIndexStoreArguments = false 196| 0| case .auto: 197| 0| addIndexStoreArguments = configuration == .debug 198| 0| } 199| 0| 200| 0| if addIndexStoreArguments { 201| 0| return ["-index-store-path", indexStore.pathString] 202| 0| } 203| 0| return [] 204| 0| } 205| | 206| | /// Computes the target triple arguments for a given resolved target. 207| 0| fileprivate func targetTripleArgs(for target: ResolvedTarget) -> [String] { 208| 0| var args = ["-target"] 209| 0| // Compute the triple string for Darwin platform using the platform version. 210| 0| if triple.isDarwin() { 211| 0| guard let macOSSupportedPlatform = target.underlyingTarget.getSupportedPlatform(for: .macOS) else { 212| 0| fatalError("the target \(target) doesn't support building for macOS") 213| 0| } 214| 0| args += [triple.tripleString(forPlatformVersion: macOSSupportedPlatform.version.versionString)] 215| 0| } else { 216| 0| args += [triple.tripleString] 217| 0| } 218| 0| return args 219| 0| } 220| | 221| | /// The current platform we're building for. 222| 0| var currentPlatform: PackageModel.Platform { 223| 0| if self.triple.isDarwin() { 224| 0| return .macOS 225| 0| } else { 226| 0| return .linux 227| 0| } 228| 0| } 229| | 230| | /// Returns the scoped view of build settings for a given target. 231| 0| fileprivate func createScope(for target: ResolvedTarget) -> BuildSettings.Scope { 232| 0| return BuildSettings.Scope(target.underlyingTarget.buildSettings, boundCondition: (currentPlatform, configuration)) 233| 0| } 234| |} 235| | 236| |/// A target description which can either be for a Swift or Clang target. 237| |public enum TargetBuildDescription { 238| | 239| | /// Swift target description. 240| | case swift(SwiftTargetBuildDescription) 241| | 242| | /// Clang target description. 243| | case clang(ClangTargetBuildDescription) 244| | 245| | /// The objects in this target. 246| 0| var objects: [AbsolutePath] { 247| 0| switch self { 248| 0| case .swift(let target): 249| 0| return target.objects 250| 0| case .clang(let target): 251| 0| return target.objects 252| 0| } 253| 0| } 254| |} 255| | 256| |/// Target description for a Clang target i.e. C language family target. 257| |public final class ClangTargetBuildDescription { 258| | 259| | /// The target described by this target. 260| | public let target: ResolvedTarget 261| | 262| | /// The underlying clang target. 263| 0| public var clangTarget: ClangTarget { 264| 0| return target.underlyingTarget as! ClangTarget 265| 0| } 266| | 267| | /// The build parameters. 268| | let buildParameters: BuildParameters 269| | 270| | /// The modulemap file for this target, if any. 271| | private(set) var moduleMap: AbsolutePath? 272| | 273| | /// Path to the temporary directory for this target. 274| 0| var tempsPath: AbsolutePath { 275| 0| return buildParameters.buildPath.appending(component: target.c99name + ".build") 276| 0| } 277| | 278| | /// The objects in this target. 279| 0| var objects: [AbsolutePath] { 280| 0| return compilePaths().map({ $0.object }) 281| 0| } 282| | 283| | /// Any addition flags to be added. These flags are expected to be computed during build planning. 284| | fileprivate var additionalFlags: [String] = [] 285| | 286| | /// The filesystem to operate on. 287| | let fileSystem: FileSystem 288| | 289| | /// If this target is a test target. 290| 0| public var isTestTarget: Bool { 291| 0| return target.type == .test 292| 0| } 293| | 294| | /// Create a new target description with target and build parameters. 295| 0| init(target: ResolvedTarget, buildParameters: BuildParameters, fileSystem: FileSystem = localFileSystem) throws { 296| 0| assert(target.underlyingTarget is ClangTarget, "underlying target type mismatch \(target)") 297| 0| self.fileSystem = fileSystem 298| 0| self.target = target 299| 0| self.buildParameters = buildParameters 300| 0| // Try computing modulemap path for a C library. 301| 0| if target.type == .library { 302| 0| self.moduleMap = try computeModulemapPath() 303| 0| } 304| 0| } 305| | 306| | /// An array of tuple containing filename, source, object and dependency path for each of the source in this target. 307| | public func compilePaths() 308| | -> [(filename: RelativePath, source: AbsolutePath, object: AbsolutePath, deps: AbsolutePath)] 309| 0| { 310| 0| return target.sources.relativePaths.map({ source in 311| 0| let path = target.sources.root.appending(source) 312| 0| let object = tempsPath.appending(RelativePath("\(source.pathString).o")) 313| 0| let deps = tempsPath.appending(RelativePath("\(source.pathString).d")) 314| 0| return (source, path, object, deps) 315| 0| }) 316| 0| } 317| | 318| | /// Builds up basic compilation arguments for this target. 319| 0| public func basicArguments() -> [String] { 320| 0| var args = [String]() 321| 0| // Only enable ARC on macOS. 322| 0| if buildParameters.triple.isDarwin() { 323| 0| args += ["-fobjc-arc"] 324| 0| } 325| 0| args += buildParameters.targetTripleArgs(for: target) 326| 0| args += buildParameters.toolchain.extraCCFlags 327| 0| args += optimizationArguments 328| 0| args += activeCompilationConditions 329| 0| args += ["-fblocks"] 330| 0| 331| 0| // Enable index store, if appropriate. 332| 0| // 333| 0| // This feature is not widely available in OSS clang. So, we only enable 334| 0| // index store for Apple's clang or if explicitly asked to. 335| 0| if Process.env.keys.contains("SWIFTPM_ENABLE_CLANG_INDEX_STORE") { 336| 0| args += buildParameters.indexStoreArguments 337| 0| } else if buildParameters.triple.isDarwin(), (try? buildParameters.toolchain._isClangCompilerVendorApple()) == true { 338| 0| args += buildParameters.indexStoreArguments 339| 0| } 340| 0| 341| 0| if !buildParameters.triple.isWindows() { 342| 0| // Using modules currently conflicts with the Windows SDKs. 343| 0| args += ["-fmodules", "-fmodule-name=" + target.c99name] 344| 0| } 345| 0| args += ["-I", clangTarget.includeDir.pathString] 346| 0| args += additionalFlags 347| 0| if !buildParameters.triple.isWindows() { 348| 0| args += moduleCacheArgs 349| 0| } 350| 0| args += buildParameters.sanitizers.compileCFlags() 351| 0| 352| 0| // Add agruments from declared build settings. 353| 0| args += self.buildSettingsFlags() 354| 0| 355| 0| // User arguments (from -Xcc and -Xcxx below) should follow generated arguments to allow user overrides 356| 0| args += buildParameters.flags.cCompilerFlags 357| 0| 358| 0| // Add extra C++ flags if this target contains C++ files. 359| 0| if clangTarget.isCXX { 360| 0| args += self.buildParameters.flags.cxxCompilerFlags 361| 0| } 362| 0| return args 363| 0| } 364| | 365| | /// Returns the build flags from the declared build settings. 366| 0| private func buildSettingsFlags() -> [String] { 367| 0| let scope = buildParameters.createScope(for: target) 368| 0| var flags: [String] = [] 369| 0| 370| 0| // C defines. 371| 0| let cDefines = scope.evaluate(.GCC_PREPROCESSOR_DEFINITIONS) 372| 0| flags += cDefines.map({ "-D" + $0 }) 373| 0| 374| 0| // Header search paths. 375| 0| let headerSearchPaths = scope.evaluate(.HEADER_SEARCH_PATHS) 376| 0| flags += headerSearchPaths.map({ 377| 0| "-I\(target.sources.root.appending(RelativePath($0)).pathString)" 378| 0| }) 379| 0| 380| 0| // Frameworks. 381| 0| let frameworks = scope.evaluate(.LINK_FRAMEWORKS) 382| 0| flags += frameworks.flatMap({ ["-framework", $0] }) 383| 0| 384| 0| // Other C flags. 385| 0| flags += scope.evaluate(.OTHER_CFLAGS) 386| 0| 387| 0| // Other CXX flags. 388| 0| flags += scope.evaluate(.OTHER_CPLUSPLUSFLAGS) 389| 0| 390| 0| return flags 391| 0| } 392| | 393| | /// Optimization arguments according to the build configuration. 394| 0| private var optimizationArguments: [String] { 395| 0| switch buildParameters.configuration { 396| 0| case .debug: 397| 0| if buildParameters.triple.isWindows() { 398| 0| return ["-g", "-gcodeview", "-O0"] 399| 0| } else { 400| 0| return ["-g", "-O0"] 401| 0| } 402| 0| case .release: 403| 0| return ["-O2"] 404| 0| } 405| 0| } 406| | 407| | /// A list of compilation conditions to enable for conditional compilation expressions. 408| 0| private var activeCompilationConditions: [String] { 409| 0| var compilationConditions = ["-DSWIFT_PACKAGE=1"] 410| 0| 411| 0| switch buildParameters.configuration { 412| 0| case .debug: 413| 0| compilationConditions += ["-DDEBUG=1"] 414| 0| case .release: 415| 0| break 416| 0| } 417| 0| 418| 0| return compilationConditions 419| 0| } 420| | 421| | 422| | /// Helper function to compute the modulemap path. 423| | /// 424| | /// This function either returns path to user provided modulemap or tries to automatically generates it. 425| 0| private func computeModulemapPath() throws -> AbsolutePath { 426| 0| // If user provided the modulemap, we're done. 427| 0| if fileSystem.isFile(clangTarget.moduleMapPath) { 428| 0| return clangTarget.moduleMapPath 429| 0| } else { 430| 0| // Otherwise try to generate one. 431| 0| var moduleMapGenerator = ModuleMapGenerator(for: clangTarget, fileSystem: fileSystem) 432| 0| // FIXME: We should probably only warn if we're unable to generate the modulemap 433| 0| // because the clang target is still a valid, it just can't be imported from Swift targets. 434| 0| try moduleMapGenerator.generateModuleMap(inDir: tempsPath) 435| 0| return tempsPath.appending(component: moduleMapFilename) 436| 0| } 437| 0| } 438| | 439| | /// Module cache arguments. 440| 0| private var moduleCacheArgs: [String] { 441| 0| return ["-fmodules-cache-path=\(buildParameters.moduleCache.pathString)"] 442| 0| } 443| |} 444| | 445| |/// Target description for a Swift target. 446| |public final class SwiftTargetBuildDescription { 447| | 448| | /// The target described by this target. 449| | public let target: ResolvedTarget 450| | 451| | /// The build parameters. 452| | let buildParameters: BuildParameters 453| | 454| | /// Path to the temporary directory for this target. 455| 0| var tempsPath: AbsolutePath { 456| 0| return buildParameters.buildPath.appending(component: target.c99name + ".build") 457| 0| } 458| | 459| | /// The objects in this target. 460| 0| var objects: [AbsolutePath] { 461| 0| return target.sources.relativePaths.map({ tempsPath.appending(RelativePath("\($0.pathString).o")) }) 462| 0| } 463| | 464| | /// The path to the swiftmodule file after compilation. 465| 0| var moduleOutputPath: AbsolutePath { 466| 0| return buildParameters.buildPath.appending(component: target.c99name + ".swiftmodule") 467| 0| } 468| | 469| | /// The path to the swifinterface file after compilation. 470| 0| var parseableModuleInterfaceOutputPath: AbsolutePath { 471| 0| return buildParameters.buildPath.appending(component: target.c99name + ".swiftinterface") 472| 0| } 473| | 474| | /// Any addition flags to be added. These flags are expected to be computed during build planning. 475| | fileprivate var additionalFlags: [String] = [] 476| | 477| | /// The swift version for this target. 478| 0| var swiftVersion: SwiftLanguageVersion { 479| 0| return (target.underlyingTarget as! SwiftTarget).swiftVersion 480| 0| } 481| | 482| | /// If this target is a test target. 483| | public let isTestTarget: Bool 484| | 485| | /// Create a new target description with target and build parameters. 486| 0| init(target: ResolvedTarget, buildParameters: BuildParameters, isTestTarget: Bool? = nil) { 487| 0| assert(target.underlyingTarget is SwiftTarget, "underlying target type mismatch \(target)") 488| 0| self.target = target 489| 0| self.buildParameters = buildParameters 490| 0| // Unless mentioned explicitly, use the target type to determine if this is a test target. 491| 0| self.isTestTarget = isTestTarget ?? (target.type == .test) 492| 0| } 493| | 494| | /// The arguments needed to compile this target. 495| 0| public func compileArguments() -> [String] { 496| 0| var args = [String]() 497| 0| args += buildParameters.targetTripleArgs(for: target) 498| 0| args += ["-swift-version", swiftVersion.rawValue] 499| 0| 500| 0| // Enable batch mode in debug mode. 501| 0| // 502| 0| // Technically, it should be enabled whenever WMO is off but we 503| 0| // don't currently make that distinction in SwiftPM 504| 0| switch buildParameters.configuration { 505| 0| case .debug: 506| 0| args += ["-enable-batch-mode"] 507| 0| case .release: break 508| 0| } 509| 0| 510| 0| args += buildParameters.indexStoreArguments 511| 0| args += buildParameters.toolchain.extraSwiftCFlags 512| 0| args += optimizationArguments 513| 0| args += ["-j\(SwiftCompilerTool.numThreads)"] 514| 0| args += activeCompilationConditions 515| 0| args += additionalFlags 516| 0| args += moduleCacheArgs 517| 0| args += buildParameters.sanitizers.compileSwiftFlags() 518| 0| 519| 0| // Add arguments needed for code coverage if it is enabled. 520| 0| if buildParameters.enableCodeCoverage { 521| 0| args += ["-profile-coverage-mapping", "-profile-generate"] 522| 0| } 523| 0| 524| 0| // Add arguments to colorize output if stdout is tty 525| 0| if buildParameters.isTTY { 526| 0| args += ["-Xfrontend", "-color-diagnostics"] 527| 0| } 528| 0| 529| 0| // Add the output for the `.swiftinterface`, if requested. 530| 0| if buildParameters.enableParseableModuleInterfaces { 531| 0| args += ["-emit-parseable-module-interface-path", parseableModuleInterfaceOutputPath.pathString] 532| 0| } 533| 0| 534| 0| // Add agruments from declared build settings. 535| 0| args += self.buildSettingsFlags() 536| 0| 537| 0| // User arguments (from -Xswiftc) should follow generated arguments to allow user overrides 538| 0| args += buildParameters.swiftCompilerFlags 539| 0| return args 540| 0| } 541| | 542| | /// Returns the build flags from the declared build settings. 543| 0| private func buildSettingsFlags() -> [String] { 544| 0| let scope = buildParameters.createScope(for: target) 545| 0| var flags: [String] = [] 546| 0| 547| 0| // Swift defines. 548| 0| let swiftDefines = scope.evaluate(.SWIFT_ACTIVE_COMPILATION_CONDITIONS) 549| 0| flags += swiftDefines.map({ "-D" + $0 }) 550| 0| 551| 0| // Frameworks. 552| 0| let frameworks = scope.evaluate(.LINK_FRAMEWORKS) 553| 0| flags += frameworks.flatMap({ ["-framework", $0] }) 554| 0| 555| 0| // Other Swift flags. 556| 0| flags += scope.evaluate(.OTHER_SWIFT_FLAGS) 557| 0| 558| 0| // Add C flags by prefixing them with -Xcc. 559| 0| // 560| 0| // C defines. 561| 0| let cDefines = scope.evaluate(.GCC_PREPROCESSOR_DEFINITIONS) 562| 0| flags += cDefines.flatMap({ ["-Xcc", "-D" + $0] }) 563| 0| 564| 0| // Header search paths. 565| 0| let headerSearchPaths = scope.evaluate(.HEADER_SEARCH_PATHS) 566| 0| flags += headerSearchPaths.flatMap({ path -> [String] in 567| 0| return ["-Xcc", "-I\(target.sources.root.appending(RelativePath(path)).pathString)"] 568| 0| }) 569| 0| 570| 0| // Other C flags. 571| 0| flags += scope.evaluate(.OTHER_CFLAGS).flatMap({ ["-Xcc", $0] }) 572| 0| 573| 0| return flags 574| 0| } 575| | 576| | /// A list of compilation conditions to enable for conditional compilation expressions. 577| 0| private var activeCompilationConditions: [String] { 578| 0| var compilationConditions = ["-DSWIFT_PACKAGE"] 579| 0| 580| 0| switch buildParameters.configuration { 581| 0| case .debug: 582| 0| compilationConditions += ["-DDEBUG"] 583| 0| case .release: 584| 0| break 585| 0| } 586| 0| 587| 0| return compilationConditions 588| 0| } 589| | 590| | /// Optimization arguments according to the build configuration. 591| 0| private var optimizationArguments: [String] { 592| 0| switch buildParameters.configuration { 593| 0| case .debug: 594| 0| return ["-Onone", "-g", "-enable-testing"] 595| 0| case .release: 596| 0| return ["-O"] 597| 0| } 598| 0| } 599| | 600| | /// Module cache arguments. 601| 0| private var moduleCacheArgs: [String] { 602| 0| return ["-module-cache-path", buildParameters.moduleCache.pathString] 603| 0| } 604| |} 605| | 606| |/// The build description for a product. 607| |public final class ProductBuildDescription { 608| | 609| | /// The reference to the product. 610| | public let product: ResolvedProduct 611| | 612| | /// The build parameters. 613| | let buildParameters: BuildParameters 614| | 615| | /// The path to the product binary produced. 616| 0| public var binary: AbsolutePath { 617| 0| return buildParameters.buildPath.appending(outname) 618| 0| } 619| | 620| | /// The output name of the product. 621| 0| public var outname: RelativePath { 622| 0| let name = product.name 623| 0| 624| 0| switch product.type { 625| 0| case .executable: 626| 0| if buildParameters.triple.isWindows() { 627| 0| return RelativePath("\(name).exe") 628| 0| } else { 629| 0| return RelativePath(name) 630| 0| } 631| 0| case .library(.static): 632| 0| return RelativePath("lib\(name).a") 633| 0| case .library(.dynamic): 634| 0| return RelativePath("lib\(name)\(self.buildParameters.triple.dynamicLibraryExtension)") 635| 0| case .library(.automatic): 636| 0| fatalError() 637| 0| case .test: 638| 0| let base = "\(name).xctest" 639| 0| if buildParameters.triple.isDarwin() { 640| 0| return RelativePath("\(base)/Contents/MacOS/\(name)") 641| 0| } else { 642| 0| return RelativePath(base) 643| 0| } 644| 0| } 645| 0| } 646| | 647| | /// The objects in this product. 648| | /// 649| | // Computed during build planning. 650| | fileprivate(set) var objects = SortedArray() 651| | 652| | /// The dynamic libraries this product needs to link with. 653| | // Computed during build planning. 654| | fileprivate(set) var dylibs: [ProductBuildDescription] = [] 655| | 656| | /// Any additional flags to be added. These flags are expected to be computed during build planning. 657| | fileprivate var additionalFlags: [String] = [] 658| | 659| | /// The list of targets that are going to be linked statically in this product. 660| | fileprivate var staticTargets: [ResolvedTarget] = [] 661| | 662| | /// Path to the temporary directory for this product. 663| 0| var tempsPath: AbsolutePath { 664| 0| return buildParameters.buildPath.appending(component: product.name + ".product") 665| 0| } 666| | 667| | /// Path to the link filelist file. 668| 0| var linkFileListPath: AbsolutePath { 669| 0| return tempsPath.appending(component: "Objects.LinkFileList") 670| 0| } 671| | 672| | /// Create a build description for a product. 673| 0| init(product: ResolvedProduct, buildParameters: BuildParameters) { 674| 0| assert(product.type != .library(.automatic), "Automatic type libraries should not be described.") 675| 0| self.product = product 676| 0| self.buildParameters = buildParameters 677| 0| } 678| | 679| | /// Strips the arguments which should *never* be passed to Swift compiler 680| | /// when we're linking the product. 681| | /// 682| | /// We might want to get rid of this method once Swift driver can strip the 683| | /// flags itself, . 684| 0| private func stripInvalidArguments(_ args: [String]) -> [String] { 685| 0| let invalidArguments: Set = ["-wmo", "-whole-module-optimization"] 686| 0| return args.filter({ !invalidArguments.contains($0) }) 687| 0| } 688| | 689| | /// The arguments to link and create this product. 690| 0| public func linkArguments() -> [String] { 691| 0| var args = [buildParameters.toolchain.swiftCompiler.pathString] 692| 0| args += buildParameters.toolchain.extraSwiftCFlags 693| 0| args += buildParameters.sanitizers.linkSwiftFlags() 694| 0| args += additionalFlags 695| 0| 696| 0| if buildParameters.configuration == .debug { 697| 0| if buildParameters.triple.isWindows() { 698| 0| args += ["-Xlinker","-debug"] 699| 0| } else { 700| 0| args += ["-g"] 701| 0| } 702| 0| } 703| 0| args += ["-L", buildParameters.buildPath.pathString] 704| 0| args += ["-o", binary.pathString] 705| 0| args += ["-module-name", product.name.spm_mangledToC99ExtendedIdentifier()] 706| 0| args += dylibs.map({ "-l" + $0.product.name }) 707| 0| 708| 0| // Add arguements needed for code coverage if it is enabled. 709| 0| if buildParameters.enableCodeCoverage { 710| 0| args += ["-profile-coverage-mapping", "-profile-generate"] 711| 0| } 712| 0| 713| 0| switch product.type { 714| 0| case .library(.automatic): 715| 0| fatalError() 716| 0| case .library(.static): 717| 0| // No arguments for static libraries. 718| 0| return [] 719| 0| case .test: 720| 0| // Test products are bundle on macOS, executable on linux. 721| 0| if buildParameters.triple.isDarwin() { 722| 0| args += ["-Xlinker", "-bundle"] 723| 0| } else { 724| 0| args += ["-emit-executable"] 725| 0| } 726| 0| case .library(.dynamic): 727| 0| args += ["-emit-library"] 728| 0| case .executable: 729| 0| // Link the Swift stdlib statically if requested. 730| 0| if buildParameters.shouldLinkStaticSwiftStdlib { 731| 0| // FIXME: This does not work for linux yet (SR-648). 732| 0| if !buildParameters.triple.isLinux() { 733| 0| args += ["-static-stdlib"] 734| 0| } 735| 0| } 736| 0| args += ["-emit-executable"] 737| 0| } 738| 0| 739| 0| // On linux, set rpath such that dynamic libraries are looked up 740| 0| // adjacent to the product. This happens by default on macOS. 741| 0| if buildParameters.triple.isLinux() { 742| 0| args += ["-Xlinker", "-rpath=$ORIGIN"] 743| 0| } 744| 0| args += ["@\(linkFileListPath.pathString)"] 745| 0| 746| 0| // Embed the swift stdlib library path inside tests and executables on Darwin. 747| 0| switch product.type { 748| 0| case .library: break 749| 0| case .test, .executable: 750| 0| if buildParameters.triple.isDarwin() { 751| 0| let stdlib = buildParameters.toolchain.macosSwiftStdlib 752| 0| args += ["-Xlinker", "-rpath", "-Xlinker", stdlib.pathString] 753| 0| } 754| 0| } 755| 0| 756| 0| // Add agruments from declared build settings. 757| 0| args += self.buildSettingsFlags() 758| 0| 759| 0| // User arguments (from -Xlinker and -Xswiftc) should follow generated arguments to allow user overrides 760| 0| args += buildParameters.linkerFlags 761| 0| args += stripInvalidArguments(buildParameters.swiftCompilerFlags) 762| 0| return args 763| 0| } 764| | 765| | /// Writes link filelist to the filesystem. 766| 0| func writeLinkFilelist(_ fs: FileSystem) throws { 767| 0| let stream = BufferedOutputByteStream() 768| 0| 769| 0| for object in objects { 770| 0| stream <<< object.pathString.spm_shellEscaped() <<< "\n" 771| 0| } 772| 0| 773| 0| try fs.createDirectory(linkFileListPath.parentDirectory, recursive: true) 774| 0| try fs.writeFileContents(linkFileListPath, bytes: stream.bytes) 775| 0| } 776| | 777| | /// Returns the build flags from the declared build settings. 778| 0| private func buildSettingsFlags() -> [String] { 779| 0| var flags: [String] = [] 780| 0| 781| 0| // Linked libraries. 782| 0| let libraries = OrderedSet(staticTargets.reduce([]) { 783| 0| $0 + buildParameters.createScope(for: $1).evaluate(.LINK_LIBRARIES) 784| 0| }) 785| 0| flags += libraries.map({ "-l" + $0 }) 786| 0| 787| 0| // Linked frameworks. 788| 0| let frameworks = OrderedSet(staticTargets.reduce([]) { 789| 0| $0 + buildParameters.createScope(for: $1).evaluate(.LINK_FRAMEWORKS) 790| 0| }) 791| 0| flags += frameworks.flatMap({ ["-framework", $0] }) 792| 0| 793| 0| // Other linker flags. 794| 0| for target in staticTargets { 795| 0| let scope = buildParameters.createScope(for: target) 796| 0| flags += scope.evaluate(.OTHER_LDFLAGS) 797| 0| } 798| 0| 799| 0| return flags 800| 0| } 801| |} 802| | 803| |/// A build plan for a package graph. 804| |public class BuildPlan { 805| | 806| | public enum Error: Swift.Error, CustomStringConvertible, Equatable { 807| | /// The linux main file is missing. 808| | case missingLinuxMain 809| | 810| | /// There is no buildable target in the graph. 811| | case noBuildableTarget 812| | 813| 0| public var description: String { 814| 0| switch self { 815| 0| case .missingLinuxMain: 816| 0| return "missing LinuxMain.swift file in the Tests directory" 817| 0| case .noBuildableTarget: 818| 0| return "the package does not contain a buildable target" 819| 0| } 820| 0| } 821| | } 822| | 823| | /// The build parameters. 824| | public let buildParameters: BuildParameters 825| | 826| | /// The package graph. 827| | public let graph: PackageGraph 828| | 829| | /// The target build description map. 830| | public let targetMap: [ResolvedTarget: TargetBuildDescription] 831| | 832| | /// The product build description map. 833| | public let productMap: [ResolvedProduct: ProductBuildDescription] 834| | 835| | /// The build targets. 836| 0| public var targets: AnySequence { 837| 0| return AnySequence(targetMap.values) 838| 0| } 839| | 840| | /// The products in this plan. 841| 0| public var buildProducts: AnySequence { 842| 0| return AnySequence(productMap.values) 843| 0| } 844| | 845| | /// The filesystem to operate on. 846| | let fileSystem: FileSystem 847| | 848| | /// Diagnostics Engine to emit diagnostics 849| | let diagnostics: DiagnosticsEngine 850| | 851| | /// Create a build plan with build parameters and a package graph. 852| | public init( 853| | buildParameters: BuildParameters, 854| | graph: PackageGraph, 855| | diagnostics: DiagnosticsEngine, 856| | fileSystem: FileSystem = localFileSystem 857| 0| ) throws { 858| 0| self.buildParameters = buildParameters 859| 0| self.graph = graph 860| 0| self.diagnostics = diagnostics 861| 0| self.fileSystem = fileSystem 862| 0| 863| 0| // Create build target description for each target which we need to plan. 864| 0| var targetMap = [ResolvedTarget: TargetBuildDescription]() 865| 0| for target in graph.allTargets { 866| 0| 867| 0| // Validate the product dependencies of this target. 868| 0| for dependency in target.dependencies { 869| 0| switch dependency { 870| 0| case .target: break 871| 0| case .product(let product): 872| 0| if buildParameters.triple.isDarwin() { 873| 0| BuildPlan.validateDeploymentVersionOfProductDependency( 874| 0| product, forTarget: target, diagnostics: diagnostics) 875| 0| } 876| 0| } 877| 0| } 878| 0| 879| 0| switch target.underlyingTarget { 880| 0| case is SwiftTarget: 881| 0| targetMap[target] = .swift(SwiftTargetBuildDescription(target: target, buildParameters: buildParameters)) 882| 0| case is ClangTarget: 883| 0| targetMap[target] = try .clang(ClangTargetBuildDescription( 884| 0| target: target, 885| 0| buildParameters: buildParameters, 886| 0| fileSystem: fileSystem)) 887| 0| case is SystemLibraryTarget: 888| 0| break 889| 0| default: 890| 0| fatalError("unhandled \(target.underlyingTarget)") 891| 0| } 892| 0| } 893| 0| 894| 0| /// Ensure we have at least one buildable target. 895| 0| guard !targetMap.isEmpty else { 896| 0| throw Error.noBuildableTarget 897| 0| } 898| 0| 899| 0| // Abort now if we have any diagnostics at this point. 900| 0| guard !diagnostics.hasErrors else { 901| 0| throw Diagnostics.fatalError 902| 0| } 903| 0| 904| 0| if buildParameters.triple.isLinux() { 905| 0| // FIXME: Create a target for LinuxMain file on linux. 906| 0| // This will go away once it is possible to auto detect tests. 907| 0| let testProducts = graph.allProducts.filter({ $0.type == .test }) 908| 0| 909| 0| for product in testProducts { 910| 0| guard let linuxMainTarget = product.linuxMainTarget else { 911| 0| throw Error.missingLinuxMain 912| 0| } 913| 0| let target = SwiftTargetBuildDescription( 914| 0| target: linuxMainTarget, buildParameters: buildParameters, isTestTarget: true) 915| 0| targetMap[linuxMainTarget] = .swift(target) 916| 0| } 917| 0| } 918| 0| 919| 0| var productMap: [ResolvedProduct: ProductBuildDescription] = [:] 920| 0| // Create product description for each product we have in the package graph except 921| 0| // for automatic libraries because they don't produce any output. 922| 0| for product in graph.allProducts where product.type != .library(.automatic) { 923| 0| productMap[product] = ProductBuildDescription( 924| 0| product: product, buildParameters: buildParameters) 925| 0| } 926| 0| 927| 0| self.productMap = productMap 928| 0| self.targetMap = targetMap 929| 0| // Finally plan these targets. 930| 0| try plan() 931| 0| } 932| | 933| | static func validateDeploymentVersionOfProductDependency( 934| | _ product: ResolvedProduct, 935| | forTarget target: ResolvedTarget, 936| | diagnostics: DiagnosticsEngine 937| 0| ) { 938| 0| // Get the first target as supported platforms are on the top-level. 939| 0| // This will need to become a bit complicated once we have target-level platform support. 940| 0| let productTarget = product.underlyingProduct.targets[0] 941| 0| 942| 0| guard let productPlatform = productTarget.getSupportedPlatform(for: .macOS) else { 943| 0| fatalError("Expected supported platform macOS in product target \(productTarget)") 944| 0| } 945| 0| guard let targetPlatform = target.underlyingTarget.getSupportedPlatform(for: .macOS) else { 946| 0| fatalError("Expected supported platform macOS in target \(target)") 947| 0| } 948| 0| 949| 0| // Check if the version requirement is satisfied. 950| 0| // 951| 0| // If the product's platform version is greater than ours, then it is incompatible. 952| 0| if productPlatform.version > targetPlatform.version { 953| 0| diagnostics.emit(data: ProductRequiresHigherPlatformVersion(product: product.name, platform: productPlatform)) 954| 0| } 955| 0| } 956| | 957| | /// Plan the targets and products. 958| 0| private func plan() throws { 959| 0| // Plan targets. 960| 0| for buildTarget in targets { 961| 0| switch buildTarget { 962| 0| case .swift(let target): 963| 0| try plan(swiftTarget: target) 964| 0| case .clang(let target): 965| 0| plan(clangTarget: target) 966| 0| } 967| 0| } 968| 0| 969| 0| // Plan products. 970| 0| for buildProduct in buildProducts { 971| 0| try plan(buildProduct) 972| 0| } 973| 0| // FIXME: We need to find out if any product has a target on which it depends 974| 0| // both static and dynamically and then issue a suitable diagnostic or auto 975| 0| // handle that situation. 976| 0| } 977| | 978| | /// Plan a product. 979| 0| private func plan(_ buildProduct: ProductBuildDescription) throws { 980| 0| // Compute the product's dependency. 981| 0| let dependencies = computeDependencies(of: buildProduct.product) 982| 0| 983| 0| // Add flags for system targets. 984| 0| for systemModule in dependencies.systemModules { 985| 0| guard case let target as SystemLibraryTarget = systemModule.underlyingTarget else { 986| 0| fatalError("This should not be possible.") 987| 0| } 988| 0| // Add pkgConfig libs arguments. 989| 0| buildProduct.additionalFlags += pkgConfig(for: target).libs 990| 0| } 991| 0| 992| 0| // Link C++ if needed. 993| 0| // Note: This will come from build settings in future. 994| 0| for target in dependencies.staticTargets { 995| 0| if case let target as ClangTarget = target.underlyingTarget, target.isCXX { 996| 0| buildProduct.additionalFlags += self.buildParameters.toolchain.extraCPPFlags 997| 0| break 998| 0| } 999| 0| } 1000| 0| 1001| 0| buildProduct.staticTargets = dependencies.staticTargets 1002| 0| buildProduct.dylibs = dependencies.dylibs.map({ productMap[$0]! }) 1003| 0| buildProduct.objects += dependencies.staticTargets.flatMap({ targetMap[$0]!.objects }) 1004| 0| 1005| 0| // Write the link filelist file. 1006| 0| // 1007| 0| // FIXME: We should write this as a custom llbuild task once we adopt it 1008| 0| // as a library. 1009| 0| try buildProduct.writeLinkFilelist(fileSystem) 1010| 0| } 1011| | 1012| | /// Computes the dependencies of a product. 1013| | private func computeDependencies( 1014| | of product: ResolvedProduct 1015| | ) -> ( 1016| | dylibs: [ResolvedProduct], 1017| | staticTargets: [ResolvedTarget], 1018| | systemModules: [ResolvedTarget] 1019| 0| ) { 1020| 0| 1021| 0| // Sort the product targets in topological order. 1022| 0| let nodes = product.targets.map(ResolvedTarget.Dependency.target) 1023| 0| let allTargets = try! topologicalSort(nodes, successors: { dependency in 1024| 0| switch dependency { 1025| 0| // Include all the depenencies of a target. 1026| 0| case .target(let target): 1027| 0| return target.dependencies 1028| 0| 1029| 0| // For a product dependency, we only include its content only if we 1030| 0| // need to statically link it. 1031| 0| case .product(let product): 1032| 0| switch product.type { 1033| 0| case .library(.automatic), .library(.static): 1034| 0| return product.targets.map(ResolvedTarget.Dependency.target) 1035| 0| case .library(.dynamic), .test, .executable: 1036| 0| return [] 1037| 0| } 1038| 0| } 1039| 0| }) 1040| 0| 1041| 0| // Create empty arrays to collect our results. 1042| 0| var linkLibraries = [ResolvedProduct]() 1043| 0| var staticTargets = [ResolvedTarget]() 1044| 0| var systemModules = [ResolvedTarget]() 1045| 0| 1046| 0| for dependency in allTargets { 1047| 0| switch dependency { 1048| 0| case .target(let target): 1049| 0| switch target.type { 1050| 0| // Include executable and tests only if they're top level contents 1051| 0| // of the product. Otherwise they are just build time dependency. 1052| 0| case .executable, .test: 1053| 0| if product.targets.contains(target) { 1054| 0| staticTargets.append(target) 1055| 0| } 1056| 0| // Library targets should always be included. 1057| 0| case .library: 1058| 0| staticTargets.append(target) 1059| 0| // Add system target targets to system targets array. 1060| 0| case .systemModule: 1061| 0| systemModules.append(target) 1062| 0| } 1063| 0| 1064| 0| case .product(let product): 1065| 0| // Add the dynamic products to array of libraries to link. 1066| 0| if product.type == .library(.dynamic) { 1067| 0| linkLibraries.append(product) 1068| 0| } 1069| 0| } 1070| 0| } 1071| 0| 1072| 0| if buildParameters.triple.isLinux() { 1073| 0| if product.type == .test { 1074| 0| product.linuxMainTarget.map({ staticTargets.append($0) }) 1075| 0| } 1076| 0| } 1077| 0| 1078| 0| return (linkLibraries, staticTargets, systemModules) 1079| 0| } 1080| | 1081| | /// Plan a Clang target. 1082| 0| private func plan(clangTarget: ClangTargetBuildDescription) { 1083| 0| for dependency in clangTarget.target.recursiveDependencies() { 1084| 0| switch dependency.underlyingTarget { 1085| 0| case let target as ClangTarget where target.type == .library: 1086| 0| // Setup search paths for C dependencies: 1087| 0| clangTarget.additionalFlags += ["-I", target.includeDir.pathString] 1088| 0| case let target as SystemLibraryTarget: 1089| 0| clangTarget.additionalFlags += ["-fmodule-map-file=\(target.moduleMapPath.pathString)"] 1090| 0| clangTarget.additionalFlags += pkgConfig(for: target).cFlags 1091| 0| default: continue 1092| 0| } 1093| 0| } 1094| 0| } 1095| | 1096| | /// Plan a Swift target. 1097| 0| private func plan(swiftTarget: SwiftTargetBuildDescription) throws { 1098| 0| // We need to iterate recursive dependencies because Swift compiler needs to see all the targets a target 1099| 0| // depends on. 1100| 0| for dependency in swiftTarget.target.recursiveDependencies() { 1101| 0| switch dependency.underlyingTarget { 1102| 0| case let underlyingTarget as ClangTarget where underlyingTarget.type == .library: 1103| 0| guard case let .clang(target)? = targetMap[dependency] else { 1104| 0| fatalError("unexpected clang target \(underlyingTarget)") 1105| 0| } 1106| 0| // Add the path to modulemap of the dependency. Currently we require that all Clang targets have a 1107| 0| // modulemap but we may want to remove that requirement since it is valid for a target to exist without 1108| 0| // one. However, in that case it will not be importable in Swift targets. We may want to emit a warning 1109| 0| // in that case from here. 1110| 0| guard let moduleMap = target.moduleMap else { break } 1111| 0| swiftTarget.additionalFlags += [ 1112| 0| "-Xcc", "-fmodule-map-file=\(moduleMap.pathString)", 1113| 0| "-I", target.clangTarget.includeDir.pathString, 1114| 0| ] 1115| 0| case let target as SystemLibraryTarget: 1116| 0| swiftTarget.additionalFlags += ["-Xcc", "-fmodule-map-file=\(target.moduleMapPath.pathString)"] 1117| 0| swiftTarget.additionalFlags += pkgConfig(for: target).cFlags 1118| 0| default: break 1119| 0| } 1120| 0| } 1121| 0| } 1122| | 1123| | /// Creates arguments required to launch the Swift REPL that will allow 1124| | /// importing the modules in the package graph. 1125| 0| public func createREPLArguments() -> [String] { 1126| 0| let buildPath = buildParameters.buildPath.pathString 1127| 0| var arguments = ["-I" + buildPath, "-L" + buildPath] 1128| 0| 1129| 0| // Link the special REPL product that contains all of the library targets. 1130| 0| let replProductName = graph.rootPackages[0].manifest.name + Product.replProductSuffix 1131| 0| arguments.append("-l" + replProductName) 1132| 0| 1133| 0| // The graph should have the REPL product. 1134| 0| assert(graph.allProducts.first(where: { $0.name == replProductName }) != nil) 1135| 0| 1136| 0| // Add the search path to the directory containing the modulemap file. 1137| 0| for target in targets { 1138| 0| switch target { 1139| 0| case .swift: break 1140| 0| case .clang(let targetDescription): 1141| 0| if let includeDir = targetDescription.moduleMap?.parentDirectory { 1142| 0| arguments += ["-I\(includeDir.pathString)"] 1143| 0| } 1144| 0| } 1145| 0| } 1146| 0| 1147| 0| // Add search paths from the system library targets. 1148| 0| for target in graph.reachableTargets { 1149| 0| if let systemLib = target.underlyingTarget as? SystemLibraryTarget { 1150| 0| arguments += self.pkgConfig(for: systemLib).cFlags 1151| 0| } 1152| 0| } 1153| 0| 1154| 0| return arguments 1155| 0| } 1156| | 1157| | /// Get pkgConfig arguments for a system library target. 1158| 0| private func pkgConfig(for target: SystemLibraryTarget) -> (cFlags: [String], libs: [String]) { 1159| 0| // If we already have these flags, we're done. 1160| 0| if let flags = pkgConfigCache[target] { 1161| 0| return flags 1162| 0| } 1163| 0| // Otherwise, get the result and cache it. 1164| 0| guard let result = pkgConfigArgs(for: target, diagnostics: diagnostics) else { 1165| 0| pkgConfigCache[target] = ([], []) 1166| 0| return pkgConfigCache[target]! 1167| 0| } 1168| 0| // If there is no pc file on system and we have an available provider, emit a warning. 1169| 0| if let provider = result.provider, result.couldNotFindConfigFile { 1170| 0| diagnostics.emit(data: PkgConfigHintDiagnostic(pkgConfigName: result.pkgConfigName, installText: provider.installText)) 1171| 0| } else if let error = result.error { 1172| 0| diagnostics.emit( 1173| 0| data: PkgConfigGenericDiagnostic(error: "\(error)"), 1174| 0| location: PkgConfigDiagnosticLocation(pcFile: result.pkgConfigName, target: target.name)) 1175| 0| } 1176| 0| pkgConfigCache[target] = (result.cFlags, result.libs) 1177| 0| return pkgConfigCache[target]! 1178| 0| } 1179| | 1180| | /// Cache for pkgConfig flags. 1181| | private var pkgConfigCache = [SystemLibraryTarget: (cFlags: [String], libs: [String])]() 1182| |} 1183| | 1184| |struct ProductRequiresHigherPlatformVersion: DiagnosticData { 1185| | static let id = DiagnosticID( 1186| | type: ProductRequiresHigherPlatformVersion.self, 1187| | name: "org.swift.diags.\(ProductRequiresHigherPlatformVersion.self)", 1188| | defaultBehavior: .error, 1189| 0| description: { 1190| 0| $0 <<< "the product" <<< { "'\($0.product)'" } 1191| 0| $0 <<< "requires minimum platform version" <<< { $0.platform.version.versionString } 1192| 0| $0 <<< "for" <<< { $0.platform.platform.name } <<< "platform" 1193| 0| }) 1194| | 1195| | public let product: String 1196| | public let platform: SupportedPlatform 1197| | 1198| 0| init(product: String, platform: SupportedPlatform) { 1199| 0| self.product = product 1200| 0| self.platform = platform 1201| 0| } 1202| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/Command.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| | 13| |/// A command represents an atomic unit of build system work. 14| |struct Command { 15| | /// A unique name for the command. This need not match any of the outputs 16| | /// of the tool, but it does define the stable identifier that is used to 17| | /// match up incremental build records. 18| | let name: String 19| | 20| | /// A configured tool instance for the command. 21| | /// FIXME: Clean up the names here; tool, command, task, etc. 22| | let tool: ToolProtocol 23| |} 24| | 25| |/// A target is a grouping of commands that should be built together for a 26| |/// particular purpose. 27| |struct Target { 28| | /// A unique name for the target. These should be names that have meaning 29| | /// to a client wanting to control the build. 30| | let name: String 31| | 32| | /// A list of outputs that represent the target. 33| | var outputs: SortedArray 34| | 35| | /// A list of commands the target requires. A command may be 36| | /// in multiple targets, or might not be in any target at all. 37| | var cmds: SortedArray 38| | 39| 0| init(name: String) { 40| 0| self.name = name 41| 0| self.outputs = SortedArray(areInIncreasingOrder: <) 42| 0| self.cmds = SortedArray(areInIncreasingOrder: <) 43| 0| } 44| |} 45| | 46| |extension Command { 47| 0| static func < (lhs: Command, rhs: Command) -> Bool { 48| 0| return lhs.name < rhs.name 49| 0| } 50| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/Sanitizers.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Basic 12| |import SPMUtility 13| | 14| |/// Available runtime sanitizers. 15| |public enum Sanitizer: String { 16| | case address 17| | case thread 18| | case undefined 19| | 20| | /// Return an established short name for a sanitizer, e.g. "asan". 21| 0| public var shortName: String { 22| 0| switch self { 23| 0| case .address: return "asan" 24| 0| case .thread: return "tsan" 25| 0| case .undefined: return "ubsan" 26| 0| } 27| 0| } 28| |} 29| | 30| |/// A set of enabled runtime sanitizers. 31| |public struct EnabledSanitizers { 32| | /// A set of enabled sanitizers. 33| | public let sanitizers: Set 34| | 35| 0| public init(_ sanitizers: Set = []) { 36| 0| // FIXME: We need to throw from here if given sanitizers can't be 37| 0| // enabled. For e.g., it is illegal to enable thread and address 38| 0| // sanitizers together. 39| 0| self.sanitizers = sanitizers 40| 0| } 41| | 42| | /// Sanitization flags for the C family compiler (C/C++). 43| 0| public func compileCFlags() -> [String] { 44| 0| return sanitizers.map({ "-fsanitize=\($0.rawValue)" }) 45| 0| } 46| | 47| | /// Sanitization flags for the Swift compiler. 48| 0| public func compileSwiftFlags() -> [String] { 49| 0| return sanitizers.map({ "-sanitize=\($0.rawValue)" }) 50| 0| } 51| | 52| | /// Sanitization flags for the Swift linker and compiler are the same so far. 53| 0| public func linkSwiftFlags() -> [String] { 54| 0| return compileSwiftFlags() 55| 0| } 56| | 57| 0| public var isEmpty: Bool { 58| 0| return sanitizers.isEmpty 59| 0| } 60| |} 61| | 62| |extension Sanitizer: StringEnumArgument { 63| | public static let completion: ShellCompletion = .values([ 64| | (address.rawValue, "enable Address sanitizer"), 65| | (thread.rawValue, "enable Thread sanitizer"), 66| | (undefined.rawValue, "enable Undefined Behavior sanitizer") 67| | ]) 68| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/SwiftCompilerOutputParser.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2019 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |import Foundation 12| |import Basic 13| | 14| |/// Represents a message output by the Swift compiler in JSON output mode. 15| |struct SwiftCompilerMessage { 16| | enum Kind { 17| | struct Output { 18| | let type: String 19| | let path: String 20| | } 21| | 22| | struct CommandInfo { 23| | let inputs: [String] 24| | let outputs: [Output] 25| | } 26| | 27| | struct OutputInfo { 28| | let output: String? 29| | } 30| | 31| | case began(CommandInfo) 32| | case skipped(CommandInfo) 33| | case finished(OutputInfo) 34| | case signalled(OutputInfo) 35| | } 36| | 37| | let name: String 38| | let kind: Kind 39| |} 40| | 41| |/// Protocol for the parser delegate to get notified of parsing events. 42| |protocol SwiftCompilerOutputParserDelegate: class { 43| | /// Called for each message parsed. 44| | func swiftCompilerDidOutputMessage(_ message: SwiftCompilerMessage) 45| | 46| | /// Called on an un-expected parsing error. No more events will be received after that. 47| | func swiftCompilerOutputParserDidFail(withError error: Error) 48| |} 49| | 50| |/// Parser for the Swift compiler JSON output mode. 51| |final class SwiftCompilerOutputParser { 52| | 53| | /// State of the parser state machine. 54| | private enum State { 55| | case parsingMessageSize 56| | case parsingMessage(size: Int) 57| | case parsingNewlineAfterMessage 58| | } 59| | 60| | /// Delegate to notify of parsing events. 61| | public var delegate: SwiftCompilerOutputParserDelegate 62| | 63| | /// Buffer containing the bytes until a full message can be parsed. 64| | private var buffer: [UInt8] = [] 65| | 66| | /// The parser's state machine current state. 67| | private var state: State = .parsingMessageSize 68| | 69| | /// Boolean indicating if the parser has encountered an un-expected parsing error. 70| | private var hasFailed = false 71| | 72| | /// The JSON decoder to parse messages. 73| | private let decoder = JSONDecoder() 74| | 75| | /// Initializes the parser with a delegate to notify of parsing events. 76| 0| init(delegate: SwiftCompilerOutputParserDelegate) { 77| 0| self.delegate = delegate 78| 0| } 79| | 80| | /// Parse the next bytes of the Swift compiler JSON output. 81| | /// - Note: If a parsing error is encountered, the delegate will be notified and the parser won't accept any further 82| | /// input. 83| 0| func parse(bytes: C) where C: Collection, C.Element == UInt8 { 84| 0| guard !hasFailed else { return } 85| 0| 86| 0| do { 87| 0| try parseImpl(bytes: bytes) 88| 0| } catch { 89| 0| hasFailed = true 90| 0| delegate.swiftCompilerOutputParserDidFail(withError: error) 91| 0| } 92| 0| } 93| |} 94| | 95| |private extension SwiftCompilerOutputParser { 96| | 97| | /// Error corresponding to invalid Swift compiler output. 98| | struct ParsingError: LocalizedError { 99| | /// Text describing the specific reason for the parsing failure. 100| | let reason: String 101| | 102| 0| var errorDescription: String? { 103| 0| return reason 104| 0| } 105| | } 106| | 107| | /// Throwing implementation of the parse function. 108| 0| func parseImpl(bytes: C) throws where C: Collection, C.Element == UInt8 { 109| 0| switch state { 110| 0| case .parsingMessageSize: 111| 0| if let newlineIndex = bytes.index(of: newline) { 112| 0| buffer.append(contentsOf: bytes[.. SwiftCompilerMessage { 162| 0| let data = Data(bytes: buffer) 163| 0| buffer.removeAll() 164| 0| state = .parsingNewlineAfterMessage 165| 0| 166| 0| do { 167| 0| return try decoder.decode(SwiftCompilerMessage.self, from: data) 168| 0| } catch { 169| 0| throw ParsingError(reason: "unexpected JSON message") 170| 0| } 171| 0| } 172| |} 173| | 174| |extension SwiftCompilerMessage: Decodable, Equatable { 175| | enum CodingKeys: CodingKey { 176| | case pid 177| | case name 178| | } 179| | 180| 0| init(from decoder: Decoder) throws { 181| 0| let container = try decoder.container(keyedBy: CodingKeys.self) 182| 0| name = try container.decode(String.self, forKey: .name) 183| 0| kind = try Kind(from: decoder) 184| 0| } 185| |} 186| | 187| |extension SwiftCompilerMessage.Kind: Decodable, Equatable { 188| | enum CodingKeys: CodingKey { 189| | case kind 190| | } 191| | 192| 0| init(from decoder: Decoder) throws { 193| 0| let container = try decoder.container(keyedBy: CodingKeys.self) 194| 0| let kind = try container.decode(String.self, forKey: .kind) 195| 0| switch kind { 196| 0| case "began": 197| 0| self = try .began(CommandInfo(from: decoder)) 198| 0| case "skipped": 199| 0| self = try .skipped(CommandInfo(from: decoder)) 200| 0| case "finished": 201| 0| self = try .finished(OutputInfo(from: decoder)) 202| 0| case "signalled": 203| 0| self = try .signalled(OutputInfo(from: decoder)) 204| 0| default: 205| 0| throw DecodingError.dataCorruptedError(forKey: .kind, in: container, debugDescription: "invalid kind") 206| 0| } 207| 0| } 208| |} 209| | 210| |extension SwiftCompilerMessage.Kind.Output: Decodable, Equatable {} 211| |extension SwiftCompilerMessage.Kind.CommandInfo: Decodable, Equatable {} 212| |extension SwiftCompilerMessage.Kind.OutputInfo: Decodable, Equatable {} 213| | 214| |private let newline = UInt8(ascii: "\n") /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/ToolProtocol.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| |import SPMUtility 14| |import class Foundation.ProcessInfo 15| | 16| |/// Describes a tool which can be understood by llbuild's BuildSystem library. 17| |protocol ToolProtocol { 18| | /// The list of inputs to declare. 19| | var inputs: [String] { get } 20| | 21| | /// The list of outputs to declare. 22| | var outputs: [String] { get } 23| | 24| | /// Write a description of the tool to the given output `stream`. 25| | /// 26| | /// This should append JSON or YAML content; if it is YAML it should be indented by 4 spaces. 27| | func append(to stream: OutputByteStream) 28| |} 29| | 30| |struct PhonyTool: ToolProtocol { 31| | let inputs: [String] 32| | let outputs: [String] 33| | 34| 0| func append(to stream: OutputByteStream) { 35| 0| stream <<< " tool: phony\n" 36| 0| stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n" 37| 0| stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n" 38| 0| } 39| |} 40| | 41| |struct ShellTool: ToolProtocol { 42| | let description: String 43| | let inputs: [String] 44| | let outputs: [String] 45| | let args: [String] 46| | let allowMissingInputs: Bool 47| | 48| 0| func append(to stream: OutputByteStream) { 49| 0| stream <<< " tool: shell\n" 50| 0| stream <<< " description: " <<< Format.asJSON(description) <<< "\n" 51| 0| stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n" 52| 0| stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n" 53| 0| 54| 0| // If one argument is specified we assume pre-escaped and have llbuild 55| 0| // execute it passed through to the shell. 56| 0| if let arg = self.args.spm_only { 57| 0| stream <<< " args: " <<< Format.asJSON(arg) <<< "\n" 58| 0| } else { 59| 0| stream <<< " args: " <<< Format.asJSON(args) <<< "\n" 60| 0| } 61| 0| if allowMissingInputs { 62| 0| stream <<< " allow-missing-inputs: " <<< Format.asJSON(true) <<< "\n" 63| 0| } 64| 0| } 65| |} 66| | 67| |struct ClangTool: ToolProtocol { 68| | let desc: String 69| | let inputs: [String] 70| | let outputs: [String] 71| | let args: [String] 72| | let deps: String? 73| | 74| 0| func append(to stream: OutputByteStream) { 75| 0| stream <<< " tool: clang\n" 76| 0| stream <<< " description: " <<< Format.asJSON(desc) <<< "\n" 77| 0| stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n" 78| 0| stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n" 79| 0| stream <<< " args: " <<< Format.asJSON(args) <<< "\n" 80| 0| if let deps = deps { 81| 0| stream <<< " deps: " <<< Format.asJSON(deps) <<< "\n" 82| 0| } 83| 0| } 84| |} 85| | 86| |struct ArchiveTool: ToolProtocol { 87| | let inputs: [String] 88| | let outputs: [String] 89| | 90| 0| func append(to stream: OutputByteStream) { 91| 0| stream <<< " tool: archive\n" 92| 0| stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n" 93| 0| stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n" 94| 0| } 95| |} 96| | 97| |/// Swift compiler llbuild tool. 98| |struct SwiftCompilerTool: ToolProtocol { 99| | 100| | /// Inputs to the tool. 101| | let inputs: [String] 102| | 103| | /// Outputs produced by the tool. 104| 0| var outputs: [String] { 105| 0| return target.objects.map({ $0.pathString }) + [target.moduleOutputPath.pathString] 106| 0| } 107| | 108| | /// The underlying Swift build target. 109| | let target: SwiftTargetBuildDescription 110| | 111| | static let numThreads = ProcessInfo.processInfo.activeProcessorCount 112| | 113| 0| init(target: SwiftTargetBuildDescription, inputs: [String]) { 114| 0| self.target = target 115| 0| self.inputs = inputs 116| 0| } 117| | 118| 0| func append(to stream: OutputByteStream) { 119| 0| stream <<< " tool: swift-compiler\n" 120| 0| stream <<< " executable: " 121| 0| <<< Format.asJSON(target.buildParameters.toolchain.swiftCompiler.pathString) <<< "\n" 122| 0| stream <<< " module-name: " 123| 0| <<< Format.asJSON(target.target.c99name) <<< "\n" 124| 0| stream <<< " module-output-path: " 125| 0| <<< Format.asJSON(target.moduleOutputPath.pathString) <<< "\n" 126| 0| stream <<< " inputs: " 127| 0| <<< Format.asJSON(inputs) <<< "\n" 128| 0| stream <<< " outputs: " 129| 0| <<< Format.asJSON(outputs) <<< "\n" 130| 0| stream <<< " import-paths: " 131| 0| <<< Format.asJSON([target.buildParameters.buildPath.pathString]) <<< "\n" 132| 0| stream <<< " temps-path: " 133| 0| <<< Format.asJSON(target.tempsPath.pathString) <<< "\n" 134| 0| stream <<< " objects: " 135| 0| <<< Format.asJSON(target.objects.map{$0.pathString}) <<< "\n" 136| 0| stream <<< " other-args: " 137| 0| <<< Format.asJSON(target.compileArguments()) <<< "\n" 138| 0| stream <<< " sources: " 139| 0| <<< Format.asJSON(target.target.sources.paths.map{$0.pathString}) <<< "\n" 140| 0| stream <<< " is-library: " 141| 0| <<< Format.asJSON(target.target.type == .library || target.target.type == .test) <<< "\n" 142| 0| stream <<< " enable-whole-module-optimization: " 143| 0| <<< Format.asJSON(target.buildParameters.configuration == .release) <<< "\n" 144| 0| stream <<< " num-threads: " 145| 0| <<< Format.asJSON("\(SwiftCompilerTool.numThreads)") <<< "\n" 146| 0| } 147| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/Toolchain.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageModel 13| | 14| |public protocol Toolchain { 15| | /// Path of the `swiftc` compiler. 16| | var swiftCompiler: AbsolutePath { get } 17| | 18| | /// Path containing the macOS Swift stdlib. 19| | var macosSwiftStdlib: AbsolutePath { get } 20| | 21| | /// Path of the `clang` compiler. 22| | func getClangCompiler() throws -> AbsolutePath 23| | 24| | // FIXME: This is a temporary API until index store is widely available in 25| | // the OSS clang compiler. This API should not used for any other purpose. 26| | /// Returns true if clang compiler's vendor is Apple and nil if unknown. 27| | func _isClangCompilerVendorApple() throws -> Bool? 28| | 29| | /// Additional flags to be passed to the C compiler. 30| | var extraCCFlags: [String] { get } 31| | 32| | /// Additional flags to be passed to the Swift compiler. 33| | var extraSwiftCFlags: [String] { get } 34| | 35| | /// Additional flags to be passed when compiling with C++. 36| | var extraCPPFlags: [String] { get } 37| |} 38| | 39| |extension Toolchain { 40| 0| public func _isClangCompilerVendorApple() throws -> Bool? { 41| 0| return nil 42| 0| } 43| | 44| 0| public var macosSwiftStdlib: AbsolutePath { 45| 0| return resolveSymlinks(swiftCompiler).appending(RelativePath("../../lib/swift/macosx")) 46| 0| } 47| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/Triple.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | */ 10| | 11| |/// Triple - Helper class for working with Destination.target values 12| |/// 13| |/// Used for parsing values such as x86_64-apple-macosx10.10 into 14| |/// set of enums. For os/arch/abi based conditions in build plan. 15| |/// 16| |/// @see Destination.target 17| |/// @see https://github.com/apple/swift-llvm/blob/stable/include/llvm/ADT/Triple.h 18| |/// 19| |public struct Triple { 20| | public let tripleString: String 21| | 22| | public let arch: Arch 23| | public let vendor: Vendor 24| | public let os: OS 25| | public let abi: ABI 26| | 27| | public enum Error: Swift.Error { 28| | case badFormat 29| | case unknownArch 30| | case unknownOS 31| | } 32| | 33| | public enum Arch: String { 34| | case x86_64 35| | case i686 36| | case powerpc64le 37| | case s390x 38| | case aarch64 39| | case armv7 40| | case arm 41| | } 42| | 43| | public enum Vendor: String { 44| | case unknown 45| | case apple 46| | } 47| | 48| | public enum OS: String { 49| | case darwin 50| | case macOS = "macosx" 51| | case linux 52| | case windows 53| | 54| | fileprivate static let allKnown:[OS] = [ 55| | .darwin, 56| | .macOS, 57| | .linux, 58| | .windows 59| | ] 60| | } 61| | 62| | public enum ABI: String { 63| | case unknown 64| | case android = "androideabi" 65| | } 66| | 67| 0| public init(_ string: String) throws { 68| 0| let components = string.split(separator: "-").map(String.init) 69| 0| 70| 0| guard components.count == 3 || components.count == 4 else { 71| 0| throw Error.badFormat 72| 0| } 73| 0| 74| 0| guard let arch = Arch(rawValue: components[0]) else { 75| 0| throw Error.unknownArch 76| 0| } 77| 0| 78| 0| let vendor = Vendor(rawValue: components[1]) ?? .unknown 79| 0| 80| 0| guard let os = Triple.parseOS(components[2]) else { 81| 0| throw Error.unknownOS 82| 0| } 83| 0| 84| 0| let abiString = components.count > 3 ? components[3] : nil 85| 0| let abi = abiString.flatMap(ABI.init) 86| 0| 87| 0| self.tripleString = string 88| 0| self.arch = arch 89| 0| self.vendor = vendor 90| 0| self.os = os 91| 0| self.abi = abi ?? .unknown 92| 0| } 93| | 94| 0| fileprivate static func parseOS(_ string: String) -> OS? { 95| 0| for candidate in OS.allKnown { 96| 0| if string.hasPrefix(candidate.rawValue) { 97| 0| return candidate 98| 0| } 99| 0| } 100| 0| 101| 0| return nil 102| 0| } 103| | 104| 0| public func isDarwin() -> Bool { 105| 0| return vendor == .apple || os == .macOS || os == .darwin 106| 0| } 107| | 108| 0| public func isLinux() -> Bool { 109| 0| return os == .linux 110| 0| } 111| | 112| 0| public func isWindows() -> Bool { 113| 0| return os == .windows 114| 0| } 115| | 116| | /// Returns the triple string for the given platform version. 117| | /// 118| | /// This is currently meant for Apple platforms only. 119| 0| public func tripleString(forPlatformVersion version: String) -> String { 120| 0| precondition(isDarwin()) 121| 0| return self.tripleString + version 122| 0| } 123| | 124| | public static let macOS = try! Triple("x86_64-apple-macosx") 125| | public static let x86_64Linux = try! Triple("x86_64-unknown-linux") 126| | public static let i686Linux = try! Triple("i686-unknown-linux") 127| | public static let ppc64leLinux = try! Triple("powerpc64le-unknown-linux") 128| | public static let s390xLinux = try! Triple("s390x-unknown-linux") 129| | public static let arm64Linux = try! Triple("aarch64-unknown-linux") 130| | public static let armLinux = try! Triple("armv7-unknown-linux-gnueabihf") 131| | public static let android = try! Triple("armv7-unknown-linux-androideabi") 132| | public static let windows = try! Triple("x86_64-unknown-windows-msvc") 133| | 134| | #if os(macOS) 135| | public static let hostTriple: Triple = .macOS 136| | #elseif os(Windows) 137| | public static let hostTriple: Triple = .windows 138| | #elseif os(Linux) 139| | #if arch(x86_64) 140| | public static let hostTriple: Triple = .x86_64Linux 141| | #elseif arch(i386) 142| | public static let hostTriple: Triple = .i686Linux 143| | #elseif arch(powerpc64le) 144| | public static let hostTriple: Triple = .ppc64leLinux 145| | #elseif arch(s390x) 146| | public static let hostTriple: Triple = .s390xLinux 147| | #elseif arch(arm64) 148| | public static let hostTriple: Triple = .arm64Linux 149| | #elseif arch(arm) 150| | public static let hostTriple: Triple = .armLinux 151| | #endif 152| | #endif 153| |} 154| | 155| |extension Triple { 156| | /// The file extension for dynamic libraries (eg. `.dll`, `.so`, or `.dylib`) 157| 0| public var dynamicLibraryExtension: String { 158| 0| switch os { 159| 0| case .darwin, .macOS: 160| 0| return ".dylib" 161| 0| case .linux: 162| 0| return ".so" 163| 0| case .windows: 164| 0| return ".dll" 165| 0| } 166| 0| } 167| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Build/llbuild.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright 2015 - 2016 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import SPMUtility 13| |import PackageModel 14| |import PackageGraph 15| | 16| |/// llbuild manifest file generator for a build plan. 17| |public struct LLBuildManifestGenerator { 18| | 19| | /// The name of the llbuild target that builds all products and targets (excluding tests). 20| | public static let llbuildMainTargetName = "main" 21| | 22| | /// The name of the llbuild target that builds all products and targets (including tests). 23| | public static let llbuildTestTargetName = "test" 24| | 25| | /// The build plan to work on. 26| | public let plan: BuildPlan 27| | 28| | /// The manifest client name. 29| | public let client: String 30| | 31| | /// Path to the resolved file. 32| | let resolvedFile: AbsolutePath 33| | 34| | /// Create a new generator with a build plan. 35| 0| public init(_ plan: BuildPlan, client: String, resolvedFile: AbsolutePath) { 36| 0| self.plan = plan 37| 0| self.client = client 38| 0| self.resolvedFile = resolvedFile 39| 0| } 40| | 41| | /// A structure for targets in the manifest. 42| | private struct Targets { 43| | 44| | /// Main target. 45| | private(set) var main = Target(name: LLBuildManifestGenerator.llbuildMainTargetName) 46| | 47| | /// Test target. 48| | private(set) var test = Target(name: LLBuildManifestGenerator.llbuildTestTargetName) 49| | 50| | /// All targets. 51| 0| var allTargets: [Target] { 52| 0| return [main, test] + otherTargets.sorted(by: { $0.name < $1.name }) 53| 0| } 54| | 55| | /// All commands. 56| | private(set) var allCommands = SortedArray(areInIncreasingOrder: <) 57| | 58| | /// Other targets. 59| | private var otherTargets: [Target] = [] 60| | 61| | /// Append a command. 62| 0| mutating func append(_ target: Target, buildByDefault: Bool, isTest: Bool) { 63| 0| // Create a phony command with a virtual output node that represents the target. 64| 0| let virtualNodeName = "<\(target.name)>" 65| 0| let phonyTool = PhonyTool(inputs: target.outputs.values, outputs: [virtualNodeName]) 66| 0| let phonyCommand = Command(name: "", tool: phonyTool) 67| 0| 68| 0| // Use the phony command as dependency. 69| 0| var newTarget = target 70| 0| newTarget.outputs.insert(virtualNodeName) 71| 0| newTarget.cmds.insert(phonyCommand) 72| 0| otherTargets.append(newTarget) 73| 0| 74| 0| if buildByDefault { 75| 0| if !isTest { 76| 0| main.outputs += newTarget.outputs 77| 0| main.cmds += newTarget.cmds 78| 0| } 79| 0| 80| 0| // Always build everything for the test target. 81| 0| test.outputs += newTarget.outputs 82| 0| test.cmds += newTarget.cmds 83| 0| } 84| 0| 85| 0| allCommands += newTarget.cmds 86| 0| } 87| | } 88| | 89| | /// Generate manifest at the given path. 90| 0| public func generateManifest(at path: AbsolutePath) throws { 91| 0| var targets = Targets() 92| 0| 93| 0| // Create commands for all target description in the plan. 94| 0| for (target, description) in plan.targetMap { 95| 0| switch description { 96| 0| case .swift(let description): 97| 0| // Only build targets by default if they are reachabe from a root target. 98| 0| targets.append(createSwiftCompileTarget(description), 99| 0| buildByDefault: plan.graph.isInRootPackages(target), 100| 0| isTest: description.isTestTarget) 101| 0| case .clang(let description): 102| 0| targets.append(try createClangCompileTarget(description), 103| 0| buildByDefault: plan.graph.isInRootPackages(target), 104| 0| isTest: description.isTestTarget) 105| 0| } 106| 0| } 107| 0| 108| 0| // Create command for all products in the plan. 109| 0| for (product, description) in plan.productMap { 110| 0| // Only build products by default if they are reachabe from a root target. 111| 0| targets.append(createProductTarget(description), 112| 0| buildByDefault: plan.graph.reachableProducts.contains(product), 113| 0| isTest: product.type == .test) 114| 0| } 115| 0| 116| 0| // Write the manifest. 117| 0| let stream = BufferedOutputByteStream() 118| 0| stream <<< """ 119| 0| client: 120| 0| name: \(client) 121| 0| tools: {} 122| 0| targets:\n 123| 0| """ 124| 0| for target in targets.allTargets { 125| 0| stream <<< " " <<< Format.asJSON(target.name) 126| 0| stream <<< ": " <<< Format.asJSON(target.outputs.values) <<< "\n" 127| 0| } 128| 0| 129| 0| stream <<< "default: " <<< Format.asJSON(targets.main.name) <<< "\n" 130| 0| 131| 0| stream <<< "commands: \n" 132| 0| for command in targets.allCommands.sorted(by: { $0.name < $1.name }) { 133| 0| stream <<< " " <<< Format.asJSON(command.name) <<< ":\n" 134| 0| command.tool.append(to: stream) 135| 0| stream <<< "\n" 136| 0| } 137| 0| 138| 0| try localFileSystem.writeFileContents(path, bytes: stream.bytes) 139| 0| } 140| | 141| | /// Create a llbuild target for a product description. 142| 0| private func createProductTarget(_ buildProduct: ProductBuildDescription) -> Target { 143| 0| let tool: ToolProtocol 144| 0| // Create archive tool for static library and shell tool for rest of the products. 145| 0| if buildProduct.product.type == .library(.static) { 146| 0| tool = ArchiveTool( 147| 0| inputs: buildProduct.objects.map({ $0.pathString }), 148| 0| outputs: [buildProduct.binary.pathString]) 149| 0| } else { 150| 0| let inputs = buildProduct.objects + buildProduct.dylibs.map({ $0.binary }) 151| 0| tool = ShellTool( 152| 0| description: "Linking \(buildProduct.binary.prettyPath())", 153| 0| inputs: inputs.map({ $0.pathString }), 154| 0| outputs: [buildProduct.binary.pathString], 155| 0| args: buildProduct.linkArguments(), 156| 0| allowMissingInputs: false 157| 0| ) 158| 0| } 159| 0| 160| 0| let buildConfig = plan.buildParameters.configuration.dirname 161| 0| var target = Target(name: buildProduct.product.getLLBuildTargetName(config: buildConfig)) 162| 0| target.outputs.insert(contentsOf: tool.outputs) 163| 0| target.cmds.insert(Command(name: buildProduct.product.getCommandName(config: buildConfig), tool: tool)) 164| 0| return target 165| 0| } 166| | 167| | /// Create a llbuild target for a Swift target description. 168| 0| private func createSwiftCompileTarget(_ target: SwiftTargetBuildDescription) -> Target { 169| 0| // Compute inital inputs. 170| 0| var inputs = SortedArray() 171| 0| inputs += target.target.sources.paths.map({ $0.pathString }) 172| 0| 173| 0| func addStaticTargetInputs(_ target: ResolvedTarget) { 174| 0| // Ignore C Modules. 175| 0| if target.underlyingTarget is SystemLibraryTarget { return } 176| 0| switch plan.targetMap[target] { 177| 0| case .swift(let target)?: 178| 0| inputs.insert(target.moduleOutputPath.pathString) 179| 0| case .clang(let target)?: 180| 0| inputs += target.objects.map({ $0.pathString }) 181| 0| case nil: 182| 0| fatalError("unexpected: target \(target) not in target map \(plan.targetMap)") 183| 0| } 184| 0| } 185| 0| 186| 0| for dependency in target.target.dependencies { 187| 0| switch dependency { 188| 0| case .target(let target): 189| 0| addStaticTargetInputs(target) 190| 0| 191| 0| case .product(let product): 192| 0| switch product.type { 193| 0| case .executable, .library(.dynamic): 194| 0| // Establish a dependency on binary of the product. 195| 0| inputs += [plan.productMap[product]!.binary.pathString] 196| 0| 197| 0| // For automatic and static libraries, add their targets as static input. 198| 0| case .library(.automatic), .library(.static): 199| 0| for target in product.targets { 200| 0| addStaticTargetInputs(target) 201| 0| } 202| 0| case .test: 203| 0| break 204| 0| } 205| 0| } 206| 0| } 207| 0| 208| 0| let buildConfig = plan.buildParameters.configuration.dirname 209| 0| var buildTarget = Target(name: target.target.getLLBuildTargetName(config: buildConfig)) 210| 0| // The target only cares about the module output. 211| 0| buildTarget.outputs.insert(target.moduleOutputPath.pathString) 212| 0| let tool = SwiftCompilerTool(target: target, inputs: inputs.values) 213| 0| buildTarget.cmds.insert(Command(name: target.target.getCommandName(config: buildConfig), tool: tool)) 214| 0| return buildTarget 215| 0| } 216| | 217| | /// Create a llbuild target for a Clang target description. 218| 0| private func createClangCompileTarget(_ target: ClangTargetBuildDescription) throws -> Target { 219| 0| 220| 0| let standards = [ 221| 0| (target.clangTarget.cxxLanguageStandard, SupportedLanguageExtension.cppExtensions), 222| 0| (target.clangTarget.cLanguageStandard, SupportedLanguageExtension.cExtensions), 223| 0| ] 224| 0| 225| 0| let commands: [Command] = try target.compilePaths().map({ path in 226| 0| var args = target.basicArguments() 227| 0| args += ["-MD", "-MT", "dependencies", "-MF", path.deps.pathString] 228| 0| 229| 0| // Add language standard flag if needed. 230| 0| if let ext = path.source.extension { 231| 0| for (standard, validExtensions) in standards { 232| 0| if let languageStandard = standard, validExtensions.contains(ext) { 233| 0| args += ["-std=\(languageStandard)"] 234| 0| } 235| 0| } 236| 0| } 237| 0| 238| 0| args += ["-c", path.source.pathString, "-o", path.object.pathString] 239| 0| let clang = ClangTool( 240| 0| desc: "Compiling \(target.target.name) \(path.filename.pathString)", 241| 0| //FIXME: Should we add build time dependency on dependent targets? 242| 0| inputs: [path.source.pathString], 243| 0| outputs: [path.object.pathString], 244| 0| args: [try plan.buildParameters.toolchain.getClangCompiler().pathString] + args, 245| 0| deps: path.deps.pathString) 246| 0| return Command(name: path.object.pathString, tool: clang) 247| 0| }) 248| 0| 249| 0| // For Clang, the target requires all command outputs. 250| 0| var buildTarget = Target(name: target.target.getLLBuildTargetName(config: plan.buildParameters.configuration.dirname)) 251| 0| buildTarget.outputs.insert(contentsOf: commands.flatMap({ $0.tool.outputs })) 252| 0| buildTarget.cmds += commands 253| 0| return buildTarget 254| 0| } 255| |} 256| | 257| |extension ResolvedTarget { 258| 0| public func getCommandName(config: String) -> String { 259| 0| return "C." + getLLBuildTargetName(config: config) 260| 0| } 261| | 262| 0| public func getLLBuildTargetName(config: String) -> String { 263| 0| return "\(name)-\(config).module" 264| 0| } 265| |} 266| | 267| |extension ResolvedProduct { 268| 0| public func getLLBuildTargetName(config: String) -> String { 269| 0| switch type { 270| 0| case .library(.dynamic): 271| 0| return "\(name)-\(config).dylib" 272| 0| case .test: 273| 0| return "\(name)-\(config).test" 274| 0| case .library(.static): 275| 0| return "\(name)-\(config).a" 276| 0| case .library(.automatic): 277| 0| fatalError() 278| 0| case .executable: 279| 0| return "\(name)-\(config).exe" 280| 0| } 281| 0| } 282| | 283| 0| public func getCommandName(config: String) -> String { 284| 0| return "C." + getLLBuildTargetName(config: config) 285| 0| } 286| |} <<<<<< EOF # path=Logger.framework.coverage.txt 1| |import Foundation 2| | 3| |public struct Logger { 4| | 5| | public static var standard = Logger(outputFile: stdout) 6| | public static var error = Logger(outputFile: stderr) 7| | 8| | // MARK: - Logging 9| | 10| | var outputFile: UnsafeMutablePointer 11| | var outputHandler: (_: UnsafePointer, _: UnsafeMutablePointer) -> Int32 = fputs 12| | 13| 0| public init(outputFile: UnsafeMutablePointer) { 14| 0| self.outputFile = outputFile 15| 0| } 16| | 17| 0| public func log(_ messages: [String]) { 18| 0| messages.forEach(log) 19| 0| } 20| | 21| 0| public func log(_ message: String = "") { 22| 0| _ = outputHandler(indentation + message + .newLine, outputFile) 23| 0| } 24| | 25| | // MARK: - Integration 26| | 27| | public var indentationLevel = 0 28| | public var indentationStep = 2 29| | 30| 0| public mutating func indent(number: Int = 1) { 31| 0| indentationLevel = max(0, indentationLevel + 1 * number) 32| 0| } 33| | 34| 0| public mutating func outdent(number: Int = 1) { 35| 0| indentationLevel = max(0, indentationLevel - 1 * number) 36| 0| } 37| | 38| 0| var indentation: String { 39| 0| return Array(repeating: " ", count: indentationLevel * indentationStep).joined() 40| 0| } 41| | 42| |} 43| | 44| |// MARK: - String helper 45| | 46| |extension String { 47| | static let newLine = "\n" 48| |} <<<<<< EOF # path=llvmSupport.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Allocator.cpp: 1| |//===--- Allocator.cpp - Simple memory allocation abstraction -------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the BumpPtrAllocator interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/Allocator.h" 15| |#include "llvm/Support/Compiler.h" 16| |#include "llvm/Support/DataTypes.h" 17| |#include "llvm/Support/Memory.h" 18| |#include "llvm/Support/Recycler.h" 19| |#include "llvm/Support/raw_ostream.h" 20| |#include 21| | 22| |namespace llvm { 23| | 24| |namespace detail { 25| | 26| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 27| 0| size_t TotalMemory) { 28| 0| errs() << "\nNumber of memory regions: " << NumSlabs << '\n' 29| 0| << "Bytes used: " << BytesAllocated << '\n' 30| 0| << "Bytes allocated: " << TotalMemory << '\n' 31| 0| << "Bytes wasted: " << (TotalMemory - BytesAllocated) 32| 0| << " (includes alignment, etc)\n"; 33| 0|} 34| | 35| |} // End namespace detail. 36| | 37| |void PrintRecyclerStats(size_t Size, 38| | size_t Align, 39| 0| size_t FreeListSize) { 40| 0| errs() << "Recycler element size: " << Size << '\n' 41| 0| << "Recycler element alignment: " << Align << '\n' 42| 0| << "Number of elements free for recycling: " << FreeListSize << '\n'; 43| 0|} 44| | 45| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Atomic.cpp: 1| |//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements atomic operations. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/Atomic.h" 15| |#include "llvm/Config/llvm-config.h" 16| | 17| |using namespace llvm; 18| | 19| |#if defined(_MSC_VER) 20| |#include 21| |#include 22| |#undef MemoryFence 23| |#endif 24| | 25| |#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) 26| |#define GNU_ATOMICS 27| |#endif 28| | 29| 0|void sys::MemoryFence() { 30| |#if LLVM_HAS_ATOMICS == 0 31| | return; 32| |#else 33| |# if defined(GNU_ATOMICS) 34| 0| __sync_synchronize(); 35| |# elif defined(_MSC_VER) 36| | MemoryBarrier(); 37| |# else 38| |# error No memory fence implementation for your platform! 39| |# endif 40| |#endif 41| 0|} 42| | 43| |sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, 44| | sys::cas_flag new_value, 45| 0| sys::cas_flag old_value) { 46| |#if LLVM_HAS_ATOMICS == 0 47| | sys::cas_flag result = *ptr; 48| | if (result == old_value) 49| | *ptr = new_value; 50| | return result; 51| |#elif defined(GNU_ATOMICS) 52| | return __sync_val_compare_and_swap(ptr, old_value, new_value); 53| |#elif defined(_MSC_VER) 54| | return InterlockedCompareExchange(ptr, new_value, old_value); 55| |#else 56| |# error No compare-and-swap implementation for your platform! 57| |#endif 58| |} 59| | 60| 0|sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { 61| |#if LLVM_HAS_ATOMICS == 0 62| | ++(*ptr); 63| | return *ptr; 64| |#elif defined(GNU_ATOMICS) 65| | return __sync_add_and_fetch(ptr, 1); 66| |#elif defined(_MSC_VER) 67| | return InterlockedIncrement(ptr); 68| |#else 69| |# error No atomic increment implementation for your platform! 70| |#endif 71| |} 72| | 73| 0|sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { 74| |#if LLVM_HAS_ATOMICS == 0 75| | --(*ptr); 76| | return *ptr; 77| |#elif defined(GNU_ATOMICS) 78| | return __sync_sub_and_fetch(ptr, 1); 79| |#elif defined(_MSC_VER) 80| | return InterlockedDecrement(ptr); 81| |#else 82| |# error No atomic decrement implementation for your platform! 83| |#endif 84| |} 85| | 86| 0|sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { 87| |#if LLVM_HAS_ATOMICS == 0 88| | *ptr += val; 89| | return *ptr; 90| |#elif defined(GNU_ATOMICS) 91| | return __sync_add_and_fetch(ptr, val); 92| |#elif defined(_MSC_VER) 93| | return InterlockedExchangeAdd(ptr, val) + val; 94| |#else 95| |# error No atomic add implementation for your platform! 96| |#endif 97| |} 98| | 99| 0|sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { 100| 0| sys::cas_flag original, result; 101| 0| do { 102| 0| original = *ptr; 103| 0| result = original * val; 104| 0| } while (sys::CompareAndSwap(ptr, result, original) != original); 105| 0| 106| 0| return result; 107| 0|} 108| | 109| 0|sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { 110| 0| sys::cas_flag original, result; 111| 0| do { 112| 0| original = *ptr; 113| 0| result = original / val; 114| 0| } while (sys::CompareAndSwap(ptr, result, original) != original); 115| 0| 116| 0| return result; 117| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/ConvertUTF.c: 1| |/*===--- ConvertUTF.c - Universal Character Names conversions ---------------=== 2| | * 3| | * The LLVM Compiler Infrastructure 4| | * 5| | * This file is distributed under the University of Illinois Open Source 6| | * License. See LICENSE.TXT for details. 7| | * 8| | *===------------------------------------------------------------------------=*/ 9| |/* 10| | * Copyright 2001-2004 Unicode, Inc. 11| | * 12| | * Disclaimer 13| | * 14| | * This source code is provided as is by Unicode, Inc. No claims are 15| | * made as to fitness for any particular purpose. No warranties of any 16| | * kind are expressed or implied. The recipient agrees to determine 17| | * applicability of information provided. If this file has been 18| | * purchased on magnetic or optical media from Unicode, Inc., the 19| | * sole remedy for any claim will be exchange of defective media 20| | * within 90 days of receipt. 21| | * 22| | * Limitations on Rights to Redistribute This Code 23| | * 24| | * Unicode, Inc. hereby grants the right to freely use the information 25| | * supplied in this file in the creation of products supporting the 26| | * Unicode Standard, and to make copies of this file in any form 27| | * for internal or external distribution as long as this notice 28| | * remains attached. 29| | */ 30| | 31| |/* --------------------------------------------------------------------- 32| | 33| | Conversions between UTF32, UTF-16, and UTF-8. Source code file. 34| | Author: Mark E. Davis, 1994. 35| | Rev History: Rick McGowan, fixes & updates May 2001. 36| | Sept 2001: fixed const & error conditions per 37| | mods suggested by S. Parent & A. Lillich. 38| | June 2002: Tim Dodd added detection and handling of incomplete 39| | source sequences, enhanced error detection, added casts 40| | to eliminate compiler warnings. 41| | July 2003: slight mods to back out aggressive FFFE detection. 42| | Jan 2004: updated switches in from-UTF8 conversions. 43| | Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. 44| | 45| | See the header file "ConvertUTF.h" for complete documentation. 46| | 47| |------------------------------------------------------------------------ */ 48| | 49| | 50| |#include "llvm/Support/ConvertUTF.h" 51| |#ifdef CVTUTF_DEBUG 52| |#include 53| |#endif 54| |#include 55| | 56| |static const int halfShift = 10; /* used for shifting by 10 bits */ 57| | 58| |static const UTF32 halfBase = 0x0010000UL; 59| |static const UTF32 halfMask = 0x3FFUL; 60| | 61| 0|#define UNI_SUR_HIGH_START (UTF32)0xD800 62| 0|#define UNI_SUR_HIGH_END (UTF32)0xDBFF 63| 0|#define UNI_SUR_LOW_START (UTF32)0xDC00 64| 0|#define UNI_SUR_LOW_END (UTF32)0xDFFF 65| 0|#define false 0 66| 0|#define true 1 67| | 68| |/* --------------------------------------------------------------------- */ 69| | 70| |/* 71| | * Index into the table below with the first byte of a UTF-8 sequence to 72| | * get the number of trailing bytes that are supposed to follow it. 73| | * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is 74| | * left as-is for anyone who may want to do such conversion, which was 75| | * allowed in earlier algorithms. 76| | */ 77| |static const char trailingBytesForUTF8[256] = { 78| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 79| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 80| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 81| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 82| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 83| | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 84| | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 85| | 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 86| |}; 87| | 88| |/* 89| | * Magic values subtracted from a buffer value during UTF8 conversion. 90| | * This table contains as many values as there might be trailing bytes 91| | * in a UTF-8 sequence. 92| | */ 93| |static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 94| | 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; 95| | 96| |/* 97| | * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed 98| | * into the first byte, depending on how many bytes follow. There are 99| | * as many entries in this table as there are UTF-8 sequence types. 100| | * (I.e., one byte sequence, two byte... etc.). Remember that sequencs 101| | * for *legal* UTF-8 will be 4 or fewer bytes total. 102| | */ 103| |static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 104| | 105| |/* --------------------------------------------------------------------- */ 106| | 107| |/* The interface converts a whole buffer to avoid function-call overhead. 108| | * Constants have been gathered. Loops & conditionals have been removed as 109| | * much as possible for efficiency, in favor of drop-through switches. 110| | * (See "Note A" at the bottom of the file for equivalent code.) 111| | * If your compiler supports it, the "isLegalUTF8" call can be turned 112| | * into an inline function. 113| | */ 114| | 115| | 116| |/* --------------------------------------------------------------------- */ 117| | 118| |ConversionResult ConvertUTF32toUTF16 ( 119| | const UTF32** sourceStart, const UTF32* sourceEnd, 120| 0| UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { 121| 0| ConversionResult result = conversionOK; 122| 0| const UTF32* source = *sourceStart; 123| 0| UTF16* target = *targetStart; 124| 0| while (source < sourceEnd) { 125| 0| UTF32 ch; 126| 0| if (target >= targetEnd) { 127| 0| result = targetExhausted; break; 128| 0| } 129| 0| ch = *source++; 130| 0| if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ 131| 0| /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ 132| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { 133| 0| if (flags == strictConversion) { 134| 0| --source; /* return to the illegal value itself */ 135| 0| result = sourceIllegal; 136| 0| break; 137| 0| } else { 138| 0| *target++ = UNI_REPLACEMENT_CHAR; 139| 0| } 140| 0| } else { 141| 0| *target++ = (UTF16)ch; /* normal case */ 142| 0| } 143| 0| } else if (ch > UNI_MAX_LEGAL_UTF32) { 144| 0| if (flags == strictConversion) { 145| 0| result = sourceIllegal; 146| 0| } else { 147| 0| *target++ = UNI_REPLACEMENT_CHAR; 148| 0| } 149| 0| } else { 150| 0| /* target is a character in range 0xFFFF - 0x10FFFF. */ 151| 0| if (target + 1 >= targetEnd) { 152| 0| --source; /* Back up source pointer! */ 153| 0| result = targetExhausted; break; 154| 0| } 155| 0| ch -= halfBase; 156| 0| *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); 157| 0| *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); 158| 0| } 159| 0| } 160| 0| *sourceStart = source; 161| 0| *targetStart = target; 162| 0| return result; 163| 0|} 164| | 165| |/* --------------------------------------------------------------------- */ 166| | 167| |ConversionResult ConvertUTF16toUTF32 ( 168| | const UTF16** sourceStart, const UTF16* sourceEnd, 169| 0| UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { 170| 0| ConversionResult result = conversionOK; 171| 0| const UTF16* source = *sourceStart; 172| 0| UTF32* target = *targetStart; 173| 0| UTF32 ch, ch2; 174| 0| while (source < sourceEnd) { 175| 0| const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ 176| 0| ch = *source++; 177| 0| /* If we have a surrogate pair, convert to UTF32 first. */ 178| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { 179| 0| /* If the 16 bits following the high surrogate are in the source buffer... */ 180| 0| if (source < sourceEnd) { 181| 0| ch2 = *source; 182| 0| /* If it's a low surrogate, convert to UTF32. */ 183| 0| if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { 184| 0| ch = ((ch - UNI_SUR_HIGH_START) << halfShift) 185| 0| + (ch2 - UNI_SUR_LOW_START) + halfBase; 186| 0| ++source; 187| 0| } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ 188| 0| --source; /* return to the illegal value itself */ 189| 0| result = sourceIllegal; 190| 0| break; 191| 0| } 192| 0| } else { /* We don't have the 16 bits following the high surrogate. */ 193| 0| --source; /* return to the high surrogate */ 194| 0| result = sourceExhausted; 195| 0| break; 196| 0| } 197| 0| } else if (flags == strictConversion) { 198| 0| /* UTF-16 surrogate values are illegal in UTF-32 */ 199| 0| if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { 200| 0| --source; /* return to the illegal value itself */ 201| 0| result = sourceIllegal; 202| 0| break; 203| 0| } 204| 0| } 205| 0| if (target >= targetEnd) { 206| 0| source = oldSource; /* Back up source pointer! */ 207| 0| result = targetExhausted; break; 208| 0| } 209| 0| *target++ = ch; 210| 0| } 211| 0| *sourceStart = source; 212| 0| *targetStart = target; 213| |#ifdef CVTUTF_DEBUG 214| |if (result == sourceIllegal) { 215| | fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); 216| | fflush(stderr); 217| |} 218| |#endif 219| | return result; 220| 0|} 221| |ConversionResult ConvertUTF16toUTF8 ( 222| | const UTF16** sourceStart, const UTF16* sourceEnd, 223| 0| UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { 224| 0| ConversionResult result = conversionOK; 225| 0| const UTF16* source = *sourceStart; 226| 0| UTF8* target = *targetStart; 227| 0| while (source < sourceEnd) { 228| 0| UTF32 ch; 229| 0| unsigned short bytesToWrite = 0; 230| 0| const UTF32 byteMask = 0xBF; 231| 0| const UTF32 byteMark = 0x80; 232| 0| const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ 233| 0| ch = *source++; 234| 0| /* If we have a surrogate pair, convert to UTF32 first. */ 235| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { 236| 0| /* If the 16 bits following the high surrogate are in the source buffer... */ 237| 0| if (source < sourceEnd) { 238| 0| UTF32 ch2 = *source; 239| 0| /* If it's a low surrogate, convert to UTF32. */ 240| 0| if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { 241| 0| ch = ((ch - UNI_SUR_HIGH_START) << halfShift) 242| 0| + (ch2 - UNI_SUR_LOW_START) + halfBase; 243| 0| ++source; 244| 0| } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ 245| 0| --source; /* return to the illegal value itself */ 246| 0| result = sourceIllegal; 247| 0| break; 248| 0| } 249| 0| } else { /* We don't have the 16 bits following the high surrogate. */ 250| 0| --source; /* return to the high surrogate */ 251| 0| result = sourceExhausted; 252| 0| break; 253| 0| } 254| 0| } else if (flags == strictConversion) { 255| 0| /* UTF-16 surrogate values are illegal in UTF-32 */ 256| 0| if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { 257| 0| --source; /* return to the illegal value itself */ 258| 0| result = sourceIllegal; 259| 0| break; 260| 0| } 261| 0| } 262| 0| /* Figure out how many bytes the result will require */ 263| 0| if (ch < (UTF32)0x80) { bytesToWrite = 1; 264| 0| } else if (ch < (UTF32)0x800) { bytesToWrite = 2; 265| 0| } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; 266| 0| } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; 267| 0| } else { bytesToWrite = 3; 268| 0| ch = UNI_REPLACEMENT_CHAR; 269| 0| } 270| 0| 271| 0| target += bytesToWrite; 272| 0| if (target > targetEnd) { 273| 0| source = oldSource; /* Back up source pointer! */ 274| 0| target -= bytesToWrite; result = targetExhausted; break; 275| 0| } 276| 0| switch (bytesToWrite) { /* note: everything falls through. */ 277| 0| case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 278| 0| case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 279| 0| case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 280| 0| case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); 281| 0| } 282| 0| target += bytesToWrite; 283| 0| } 284| 0| *sourceStart = source; 285| 0| *targetStart = target; 286| 0| return result; 287| 0|} 288| | 289| |/* --------------------------------------------------------------------- */ 290| | 291| |ConversionResult ConvertUTF32toUTF8 ( 292| | const UTF32** sourceStart, const UTF32* sourceEnd, 293| 0| UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { 294| 0| ConversionResult result = conversionOK; 295| 0| const UTF32* source = *sourceStart; 296| 0| UTF8* target = *targetStart; 297| 0| while (source < sourceEnd) { 298| 0| UTF32 ch; 299| 0| unsigned short bytesToWrite = 0; 300| 0| const UTF32 byteMask = 0xBF; 301| 0| const UTF32 byteMark = 0x80; 302| 0| ch = *source++; 303| 0| if (flags == strictConversion ) { 304| 0| /* UTF-16 surrogate values are illegal in UTF-32 */ 305| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { 306| 0| --source; /* return to the illegal value itself */ 307| 0| result = sourceIllegal; 308| 0| break; 309| 0| } 310| 0| } 311| 0| /* 312| 0| * Figure out how many bytes the result will require. Turn any 313| 0| * illegally large UTF32 things (> Plane 17) into replacement chars. 314| 0| */ 315| 0| if (ch < (UTF32)0x80) { bytesToWrite = 1; 316| 0| } else if (ch < (UTF32)0x800) { bytesToWrite = 2; 317| 0| } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; 318| 0| } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; 319| 0| } else { bytesToWrite = 3; 320| 0| ch = UNI_REPLACEMENT_CHAR; 321| 0| result = sourceIllegal; 322| 0| } 323| 0| 324| 0| target += bytesToWrite; 325| 0| if (target > targetEnd) { 326| 0| --source; /* Back up source pointer! */ 327| 0| target -= bytesToWrite; result = targetExhausted; break; 328| 0| } 329| 0| switch (bytesToWrite) { /* note: everything falls through. */ 330| 0| case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 331| 0| case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 332| 0| case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; 333| 0| case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); 334| 0| } 335| 0| target += bytesToWrite; 336| 0| } 337| 0| *sourceStart = source; 338| 0| *targetStart = target; 339| 0| return result; 340| 0|} 341| | 342| |/* --------------------------------------------------------------------- */ 343| | 344| |/* 345| | * Utility routine to tell whether a sequence of bytes is legal UTF-8. 346| | * This must be called with the length pre-determined by the first byte. 347| | * If not calling this from ConvertUTF8to*, then the length can be set by: 348| | * length = trailingBytesForUTF8[*source]+1; 349| | * and the sequence is illegal right away if there aren't that many bytes 350| | * available. 351| | * If presented with a length > 4, this returns false. The Unicode 352| | * definition of UTF-8 goes up to 4-byte sequences. 353| | */ 354| | 355| 0|static Boolean isLegalUTF8(const UTF8 *source, int length) { 356| 0| UTF8 a; 357| 0| const UTF8 *srcptr = source+length; 358| 0| switch (length) { 359| 0| default: return false; 360| 0| /* Everything else falls through when "true"... */ 361| 0| case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; 362| 0| case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; 363| 0| case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; 364| 0| 365| 0| switch (*source) { 366| 0| /* no fall-through in this inner switch */ 367| 0| case 0xE0: if (a < 0xA0) return false; break; 368| 0| case 0xED: if (a > 0x9F) return false; break; 369| 0| case 0xF0: if (a < 0x90) return false; break; 370| 0| case 0xF4: if (a > 0x8F) return false; break; 371| 0| default: if (a < 0x80) return false; 372| 0| } 373| 0| 374| 0| case 1: if (*source >= 0x80 && *source < 0xC2) return false; 375| 0| } 376| 0| if (*source > 0xF4) return false; 377| 0| return true; 378| 0|} 379| | 380| |/* --------------------------------------------------------------------- */ 381| | 382| |/* 383| | * Exported function to return whether a UTF-8 sequence is legal or not. 384| | * This is not used here; it's just exported. 385| | */ 386| 0|Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { 387| 0| int length = trailingBytesForUTF8[*source]+1; 388| 0| if (length > sourceEnd - source) { 389| 0| return false; 390| 0| } 391| 0| return isLegalUTF8(source, length); 392| 0|} 393| | 394| |/* --------------------------------------------------------------------- */ 395| | 396| |static unsigned 397| |findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source, 398| 0| const UTF8 *sourceEnd) { 399| 0| UTF8 b1, b2, b3; 400| 0| 401| 0| assert(!isLegalUTF8Sequence(source, sourceEnd)); 402| 0| 403| 0| /* 404| 0| * Unicode 6.3.0, D93b: 405| 0| * 406| 0| * Maximal subpart of an ill-formed subsequence: The longest code unit 407| 0| * subsequence starting at an unconvertible offset that is either: 408| 0| * a. the initial subsequence of a well-formed code unit sequence, or 409| 0| * b. a subsequence of length one. 410| 0| */ 411| 0| 412| 0| if (source == sourceEnd) 413| 0| return 0; 414| 0| 415| 0| /* 416| 0| * Perform case analysis. See Unicode 6.3.0, Table 3-7. Well-Formed UTF-8 417| 0| * Byte Sequences. 418| 0| */ 419| 0| 420| 0| b1 = *source; 421| 0| ++source; 422| 0| if (b1 >= 0xC2 && b1 <= 0xDF) { 423| 0| /* 424| 0| * First byte is valid, but we know that this code unit sequence is 425| 0| * invalid, so the maximal subpart has to end after the first byte. 426| 0| */ 427| 0| return 1; 428| 0| } 429| 0| 430| 0| if (source == sourceEnd) 431| 0| return 1; 432| 0| 433| 0| b2 = *source; 434| 0| ++source; 435| 0| 436| 0| if (b1 == 0xE0) { 437| 0| return (b2 >= 0xA0 && b2 <= 0xBF) ? 2 : 1; 438| 0| } 439| 0| if (b1 >= 0xE1 && b1 <= 0xEC) { 440| 0| return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1; 441| 0| } 442| 0| if (b1 == 0xED) { 443| 0| return (b2 >= 0x80 && b2 <= 0x9F) ? 2 : 1; 444| 0| } 445| 0| if (b1 >= 0xEE && b1 <= 0xEF) { 446| 0| return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1; 447| 0| } 448| 0| if (b1 == 0xF0) { 449| 0| if (b2 >= 0x90 && b2 <= 0xBF) { 450| 0| if (source == sourceEnd) 451| 0| return 2; 452| 0| 453| 0| b3 = *source; 454| 0| return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; 455| 0| } 456| 0| return 1; 457| 0| } 458| 0| if (b1 >= 0xF1 && b1 <= 0xF3) { 459| 0| if (b2 >= 0x80 && b2 <= 0xBF) { 460| 0| if (source == sourceEnd) 461| 0| return 2; 462| 0| 463| 0| b3 = *source; 464| 0| return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; 465| 0| } 466| 0| return 1; 467| 0| } 468| 0| if (b1 == 0xF4) { 469| 0| if (b2 >= 0x80 && b2 <= 0x8F) { 470| 0| if (source == sourceEnd) 471| 0| return 2; 472| 0| 473| 0| b3 = *source; 474| 0| return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; 475| 0| } 476| 0| return 1; 477| 0| } 478| 0| 479| 0| assert((b1 >= 0x80 && b1 <= 0xC1) || b1 >= 0xF5); 480| 0| /* 481| 0| * There are no valid sequences that start with these bytes. Maximal subpart 482| 0| * is defined to have length 1 in these cases. 483| 0| */ 484| 0| return 1; 485| 0|} 486| | 487| |/* --------------------------------------------------------------------- */ 488| | 489| |/* 490| | * Exported function to return the total number of bytes in a codepoint 491| | * represented in UTF-8, given the value of the first byte. 492| | */ 493| 0|unsigned getNumBytesForUTF8(UTF8 first) { 494| 0| return trailingBytesForUTF8[first] + 1; 495| 0|} 496| | 497| |/* --------------------------------------------------------------------- */ 498| | 499| |/* 500| | * Exported function to return whether a UTF-8 string is legal or not. 501| | * This is not used here; it's just exported. 502| | */ 503| 0|Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) { 504| 0| while (*source != sourceEnd) { 505| 0| int length = trailingBytesForUTF8[**source] + 1; 506| 0| if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) 507| 0| return false; 508| 0| *source += length; 509| 0| } 510| 0| return true; 511| 0|} 512| | 513| |/* --------------------------------------------------------------------- */ 514| | 515| |ConversionResult ConvertUTF8toUTF16 ( 516| | const UTF8** sourceStart, const UTF8* sourceEnd, 517| 0| UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { 518| 0| ConversionResult result = conversionOK; 519| 0| const UTF8* source = *sourceStart; 520| 0| UTF16* target = *targetStart; 521| 0| while (source < sourceEnd) { 522| 0| UTF32 ch = 0; 523| 0| unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; 524| 0| if (extraBytesToRead >= sourceEnd - source) { 525| 0| result = sourceExhausted; break; 526| 0| } 527| 0| /* Do this check whether lenient or strict */ 528| 0| if (!isLegalUTF8(source, extraBytesToRead+1)) { 529| 0| result = sourceIllegal; 530| 0| break; 531| 0| } 532| 0| /* 533| 0| * The cases all fall through. See "Note A" below. 534| 0| */ 535| 0| switch (extraBytesToRead) { 536| 0| case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ 537| 0| case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ 538| 0| case 3: ch += *source++; ch <<= 6; 539| 0| case 2: ch += *source++; ch <<= 6; 540| 0| case 1: ch += *source++; ch <<= 6; 541| 0| case 0: ch += *source++; 542| 0| } 543| 0| ch -= offsetsFromUTF8[extraBytesToRead]; 544| 0| 545| 0| if (target >= targetEnd) { 546| 0| source -= (extraBytesToRead+1); /* Back up source pointer! */ 547| 0| result = targetExhausted; break; 548| 0| } 549| 0| if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ 550| 0| /* UTF-16 surrogate values are illegal in UTF-32 */ 551| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { 552| 0| if (flags == strictConversion) { 553| 0| source -= (extraBytesToRead+1); /* return to the illegal value itself */ 554| 0| result = sourceIllegal; 555| 0| break; 556| 0| } else { 557| 0| *target++ = UNI_REPLACEMENT_CHAR; 558| 0| } 559| 0| } else { 560| 0| *target++ = (UTF16)ch; /* normal case */ 561| 0| } 562| 0| } else if (ch > UNI_MAX_UTF16) { 563| 0| if (flags == strictConversion) { 564| 0| result = sourceIllegal; 565| 0| source -= (extraBytesToRead+1); /* return to the start */ 566| 0| break; /* Bail out; shouldn't continue */ 567| 0| } else { 568| 0| *target++ = UNI_REPLACEMENT_CHAR; 569| 0| } 570| 0| } else { 571| 0| /* target is a character in range 0xFFFF - 0x10FFFF. */ 572| 0| if (target + 1 >= targetEnd) { 573| 0| source -= (extraBytesToRead+1); /* Back up source pointer! */ 574| 0| result = targetExhausted; break; 575| 0| } 576| 0| ch -= halfBase; 577| 0| *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); 578| 0| *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); 579| 0| } 580| 0| } 581| 0| *sourceStart = source; 582| 0| *targetStart = target; 583| 0| return result; 584| 0|} 585| | 586| |/* --------------------------------------------------------------------- */ 587| | 588| |static ConversionResult ConvertUTF8toUTF32Impl( 589| | const UTF8** sourceStart, const UTF8* sourceEnd, 590| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags, 591| 0| Boolean InputIsPartial) { 592| 0| ConversionResult result = conversionOK; 593| 0| const UTF8* source = *sourceStart; 594| 0| UTF32* target = *targetStart; 595| 0| while (source < sourceEnd) { 596| 0| UTF32 ch = 0; 597| 0| unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; 598| 0| if (extraBytesToRead >= sourceEnd - source) { 599| 0| if (flags == strictConversion || InputIsPartial) { 600| 0| result = sourceExhausted; 601| 0| break; 602| 0| } else { 603| 0| result = sourceIllegal; 604| 0| 605| 0| /* 606| 0| * Replace the maximal subpart of ill-formed sequence with 607| 0| * replacement character. 608| 0| */ 609| 0| source += findMaximalSubpartOfIllFormedUTF8Sequence(source, 610| 0| sourceEnd); 611| 0| *target++ = UNI_REPLACEMENT_CHAR; 612| 0| continue; 613| 0| } 614| 0| } 615| 0| if (target >= targetEnd) { 616| 0| result = targetExhausted; break; 617| 0| } 618| 0| 619| 0| /* Do this check whether lenient or strict */ 620| 0| if (!isLegalUTF8(source, extraBytesToRead+1)) { 621| 0| result = sourceIllegal; 622| 0| if (flags == strictConversion) { 623| 0| /* Abort conversion. */ 624| 0| break; 625| 0| } else { 626| 0| /* 627| 0| * Replace the maximal subpart of ill-formed sequence with 628| 0| * replacement character. 629| 0| */ 630| 0| source += findMaximalSubpartOfIllFormedUTF8Sequence(source, 631| 0| sourceEnd); 632| 0| *target++ = UNI_REPLACEMENT_CHAR; 633| 0| continue; 634| 0| } 635| 0| } 636| 0| /* 637| 0| * The cases all fall through. See "Note A" below. 638| 0| */ 639| 0| switch (extraBytesToRead) { 640| 0| case 5: ch += *source++; ch <<= 6; 641| 0| case 4: ch += *source++; ch <<= 6; 642| 0| case 3: ch += *source++; ch <<= 6; 643| 0| case 2: ch += *source++; ch <<= 6; 644| 0| case 1: ch += *source++; ch <<= 6; 645| 0| case 0: ch += *source++; 646| 0| } 647| 0| ch -= offsetsFromUTF8[extraBytesToRead]; 648| 0| 649| 0| if (ch <= UNI_MAX_LEGAL_UTF32) { 650| 0| /* 651| 0| * UTF-16 surrogate values are illegal in UTF-32, and anything 652| 0| * over Plane 17 (> 0x10FFFF) is illegal. 653| 0| */ 654| 0| if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { 655| 0| if (flags == strictConversion) { 656| 0| source -= (extraBytesToRead+1); /* return to the illegal value itself */ 657| 0| result = sourceIllegal; 658| 0| break; 659| 0| } else { 660| 0| *target++ = UNI_REPLACEMENT_CHAR; 661| 0| } 662| 0| } else { 663| 0| *target++ = ch; 664| 0| } 665| 0| } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ 666| 0| result = sourceIllegal; 667| 0| *target++ = UNI_REPLACEMENT_CHAR; 668| 0| } 669| 0| } 670| 0| *sourceStart = source; 671| 0| *targetStart = target; 672| 0| return result; 673| 0|} 674| | 675| |ConversionResult ConvertUTF8toUTF32Partial(const UTF8 **sourceStart, 676| | const UTF8 *sourceEnd, 677| | UTF32 **targetStart, 678| | UTF32 *targetEnd, 679| 0| ConversionFlags flags) { 680| 0| return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd, 681| 0| flags, /*InputIsPartial=*/true); 682| 0|} 683| | 684| |ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, 685| | const UTF8 *sourceEnd, UTF32 **targetStart, 686| 0| UTF32 *targetEnd, ConversionFlags flags) { 687| 0| return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd, 688| 0| flags, /*InputIsPartial=*/false); 689| 0|} 690| | 691| |/* --------------------------------------------------------------------- 692| | 693| | Note A. 694| | The fall-through switches in UTF-8 reading code save a 695| | temp variable, some decrements & conditionals. The switches 696| | are equivalent to the following loop: 697| | { 698| | int tmpBytesToRead = extraBytesToRead+1; 699| | do { 700| | ch += *source++; 701| | --tmpBytesToRead; 702| | if (tmpBytesToRead) ch <<= 6; 703| | } while (tmpBytesToRead > 0); 704| | } 705| | In UTF-8 writing code, the switches on "bytesToWrite" are 706| | similarly unrolled loops. 707| | 708| | --------------------------------------------------------------------- */ /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/ConvertUTFWrapper.cpp: 1| |//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----=== 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#include "llvm/Support/ConvertUTF.h" 11| |#include "llvm/Support/SwapByteOrder.h" 12| |#include 13| |#include 14| | 15| |namespace llvm { 16| | 17| |bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, 18| 0| char *&ResultPtr, const UTF8 *&ErrorPtr) { 19| 0| assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4); 20| 0| ConversionResult result = conversionOK; 21| 0| // Copy the character span over. 22| 0| if (WideCharWidth == 1) { 23| 0| const UTF8 *Pos = reinterpret_cast(Source.begin()); 24| 0| if (!isLegalUTF8String(&Pos, reinterpret_cast(Source.end()))) { 25| 0| result = sourceIllegal; 26| 0| ErrorPtr = Pos; 27| 0| } else { 28| 0| memcpy(ResultPtr, Source.data(), Source.size()); 29| 0| ResultPtr += Source.size(); 30| 0| } 31| 0| } else if (WideCharWidth == 2) { 32| 0| const UTF8 *sourceStart = (const UTF8*)Source.data(); 33| 0| // FIXME: Make the type of the result buffer correct instead of 34| 0| // using reinterpret_cast. 35| 0| UTF16 *targetStart = reinterpret_cast(ResultPtr); 36| 0| ConversionFlags flags = strictConversion; 37| 0| result = ConvertUTF8toUTF16( 38| 0| &sourceStart, sourceStart + Source.size(), 39| 0| &targetStart, targetStart + 2*Source.size(), flags); 40| 0| if (result == conversionOK) 41| 0| ResultPtr = reinterpret_cast(targetStart); 42| 0| else 43| 0| ErrorPtr = sourceStart; 44| 0| } else if (WideCharWidth == 4) { 45| 0| const UTF8 *sourceStart = (const UTF8*)Source.data(); 46| 0| // FIXME: Make the type of the result buffer correct instead of 47| 0| // using reinterpret_cast. 48| 0| UTF32 *targetStart = reinterpret_cast(ResultPtr); 49| 0| ConversionFlags flags = strictConversion; 50| 0| result = ConvertUTF8toUTF32( 51| 0| &sourceStart, sourceStart + Source.size(), 52| 0| &targetStart, targetStart + 4*Source.size(), flags); 53| 0| if (result == conversionOK) 54| 0| ResultPtr = reinterpret_cast(targetStart); 55| 0| else 56| 0| ErrorPtr = sourceStart; 57| 0| } 58| 0| assert((result != targetExhausted) 59| 0| && "ConvertUTF8toUTFXX exhausted target buffer"); 60| 0| return result == conversionOK; 61| 0|} 62| | 63| 0|bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) { 64| 0| const UTF32 *SourceStart = &Source; 65| 0| const UTF32 *SourceEnd = SourceStart + 1; 66| 0| UTF8 *TargetStart = reinterpret_cast(ResultPtr); 67| 0| UTF8 *TargetEnd = TargetStart + 4; 68| 0| ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd, 69| 0| &TargetStart, TargetEnd, 70| 0| strictConversion); 71| 0| if (CR != conversionOK) 72| 0| return false; 73| 0| 74| 0| ResultPtr = reinterpret_cast(TargetStart); 75| 0| return true; 76| 0|} 77| | 78| 0|bool hasUTF16ByteOrderMark(ArrayRef S) { 79| 0| return (S.size() >= 2 && 80| 0| ((S[0] == '\xff' && S[1] == '\xfe') || 81| 0| (S[0] == '\xfe' && S[1] == '\xff'))); 82| 0|} 83| | 84| 0|bool convertUTF16ToUTF8String(ArrayRef SrcBytes, std::string &Out) { 85| 0| assert(Out.empty()); 86| 0| 87| 0| // Error out on an uneven byte count. 88| 0| if (SrcBytes.size() % 2) 89| 0| return false; 90| 0| 91| 0| // Avoid OOB by returning early on empty input. 92| 0| if (SrcBytes.empty()) 93| 0| return true; 94| 0| 95| 0| const UTF16 *Src = reinterpret_cast(SrcBytes.begin()); 96| 0| const UTF16 *SrcEnd = reinterpret_cast(SrcBytes.end()); 97| 0| 98| 0| // Byteswap if necessary. 99| 0| std::vector ByteSwapped; 100| 0| if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) { 101| 0| ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd); 102| 0| for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I) 103| 0| ByteSwapped[I] = llvm::sys::SwapByteOrder_16(ByteSwapped[I]); 104| 0| Src = &ByteSwapped[0]; 105| 0| SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1; 106| 0| } 107| 0| 108| 0| // Skip the BOM for conversion. 109| 0| if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) 110| 0| Src++; 111| 0| 112| 0| // Just allocate enough space up front. We'll shrink it later. Allocate 113| 0| // enough that we can fit a null terminator without reallocating. 114| 0| Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); 115| 0| UTF8 *Dst = reinterpret_cast(&Out[0]); 116| 0| UTF8 *DstEnd = Dst + Out.size(); 117| 0| 118| 0| ConversionResult CR = 119| 0| ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); 120| 0| assert(CR != targetExhausted); 121| 0| 122| 0| if (CR != conversionOK) { 123| 0| Out.clear(); 124| 0| return false; 125| 0| } 126| 0| 127| 0| Out.resize(reinterpret_cast(Dst) - &Out[0]); 128| 0| Out.push_back(0); 129| 0| Out.pop_back(); 130| 0| return true; 131| 0|} 132| | 133| |bool convertUTF8ToUTF16String(StringRef SrcUTF8, 134| 0| SmallVectorImpl &DstUTF16) { 135| 0| assert(DstUTF16.empty()); 136| 0| 137| 0| // Avoid OOB by returning early on empty input. 138| 0| if (SrcUTF8.empty()) { 139| 0| DstUTF16.push_back(0); 140| 0| DstUTF16.pop_back(); 141| 0| return true; 142| 0| } 143| 0| 144| 0| const UTF8 *Src = reinterpret_cast(SrcUTF8.begin()); 145| 0| const UTF8 *SrcEnd = reinterpret_cast(SrcUTF8.end()); 146| 0| 147| 0| // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding 148| 0| // as UTF-16 should always require the same amount or less code units than the 149| 0| // UTF-8 encoding. Allocate one extra byte for the null terminator though, 150| 0| // so that someone calling DstUTF16.data() gets a null terminated string. 151| 0| // We resize down later so we don't have to worry that this over allocates. 152| 0| DstUTF16.resize(SrcUTF8.size()+1); 153| 0| UTF16 *Dst = &DstUTF16[0]; 154| 0| UTF16 *DstEnd = Dst + DstUTF16.size(); 155| 0| 156| 0| ConversionResult CR = 157| 0| ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion); 158| 0| assert(CR != targetExhausted); 159| 0| 160| 0| if (CR != conversionOK) { 161| 0| DstUTF16.clear(); 162| 0| return false; 163| 0| } 164| 0| 165| 0| DstUTF16.resize(Dst - &DstUTF16[0]); 166| 0| DstUTF16.push_back(0); 167| 0| DstUTF16.pop_back(); 168| 0| return true; 169| 0|} 170| | 171| |} // end namespace llvm 172| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Debug.cpp: 1| |//===-- Debug.cpp - An easy way to add debug output to your code ----------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements a handy way of adding debugging information to your 11| |// code, without it being enabled all of the time, and without having to add 12| |// command line options to enable it. 13| |// 14| |// In particular, just wrap your code with the DEBUG() macro, and it will be 15| |// enabled automatically if you specify '-debug' on the command-line. 16| |// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify 17| |// that your debug code belongs to class "foo". Then, on the command line, you 18| |// can specify '-debug-only=foo' to enable JUST the debug information for the 19| |// foo class. 20| |// 21| |// When compiling without assertions, the -debug-* options and all code in 22| |// DEBUG() statements disappears, so it does not affect the runtime of the code. 23| |// 24| |//===----------------------------------------------------------------------===// 25| | 26| |#include "llvm/Support/Debug.h" 27| |//#include "llvm/Support/CommandLine.h" 28| |#include "llvm/Support/ManagedStatic.h" 29| |#include "llvm/Support/Signals.h" 30| |#include "llvm/Support/circular_raw_ostream.h" 31| | 32| |#include 33| | 34| |#undef isCurrentDebugType 35| |#undef setCurrentDebugType 36| | 37| |using namespace llvm; 38| | 39| |// Even though LLVM might be built with NDEBUG, define symbols that the code 40| |// built without NDEBUG can depend on via the llvm/Support/Debug.h header. 41| |namespace llvm { 42| |/// Exported boolean set by the -debug option. 43| |bool DebugFlag = false; 44| | 45| |static ManagedStatic> CurrentDebugType; 46| | 47| |/// Return true if the specified string is the debug type 48| |/// specified on the command line, or if none was specified on the command line 49| |/// with the -debug-only=X option. 50| 0|bool isCurrentDebugType(const char *DebugType) { 51| 0| if (CurrentDebugType->empty()) 52| 0| return true; 53| 0| // see if DebugType is in list. Note: do not use find() as that forces us to 54| 0| // unnecessarily create an std::string instance. 55| 0| for (auto d : *CurrentDebugType) { 56| 0| if (d == DebugType) 57| 0| return true; 58| 0| } 59| 0| return false; 60| 0|} 61| | 62| |/// Set the current debug type, as if the -debug-only=X 63| |/// option were specified. Note that DebugFlag also needs to be set to true for 64| |/// debug output to be produced. 65| |/// 66| 0|void setCurrentDebugType(const char *Type) { 67| 0| CurrentDebugType->clear(); 68| 0| CurrentDebugType->push_back(Type); 69| 0|} 70| | 71| |} // namespace llvm 72| | 73| |// All Debug.h functionality is a no-op in NDEBUG mode. 74| |#ifndef NDEBUG 75| | 76| |// -debug - Command line option to enable the DEBUG statements in the passes. 77| |// This flag may only be enabled in debug builds. 78| |//static bool Debug = false; 79| | 80| |// -debug-buffer-size - Buffer the last N characters of debug output 81| |//until program termination. 82| |static unsigned DebugBufferSize = 0; 83| | 84| |namespace { 85| | 86| |struct DebugOnlyOpt { 87| 0| void operator=(const std::string &Val) const { 88| 0| if (Val.empty()) 89| 0| return; 90| 0| DebugFlag = true; 91| 0| CurrentDebugType->push_back(Val); 92| 0| } 93| |}; 94| | 95| |} 96| | 97| |//static DebugOnlyOpt DebugOnlyOptLoc; 98| | 99| |//static DebugOnlyOpt DebugOnly; 100| | 101| |// Signal handlers - dump debug output on termination. 102| 0|static void debug_user_sig_handler(void *Cookie) { 103| 0| // This is a bit sneaky. Since this is under #ifndef NDEBUG, we 104| 0| // know that debug mode is enabled and dbgs() really is a 105| 0| // circular_raw_ostream. If NDEBUG is defined, then dbgs() == 106| 0| // errs() but this will never be invoked. 107| 0| llvm::circular_raw_ostream *dbgout = 108| 0| static_cast(&llvm::dbgs()); 109| 0| dbgout->flushBufferWithBanner(); 110| 0|} 111| | 112| |/// dbgs - Return a circular-buffered debug stream. 113| 0|raw_ostream &llvm::dbgs() { 114| 0| // Do one-time initialization in a thread-safe way. 115| 0| static struct dbgstream { 116| 0| circular_raw_ostream strm; 117| 0| 118| 0| dbgstream() : 119| 0| strm(errs(), "*** Debug Log Output ***\n", 120| 0| (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) { 121| 0| if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0) 122| 0| // TODO: Add a handler for SIGUSER1-type signals so the user can 123| 0| // force a debug dump. 124| 0| sys::AddSignalHandler(&debug_user_sig_handler, nullptr); 125| 0| // Otherwise we've already set the debug stream buffer size to 126| 0| // zero, disabling buffering so it will output directly to errs(). 127| 0| } 128| 0| } thestrm; 129| 0| 130| 0| return thestrm.strm; 131| 0|} 132| | 133| |#else 134| |// Avoid "has no symbols" warning. 135| |namespace llvm { 136| | /// dbgs - Return errs(). 137| | raw_ostream &dbgs() { 138| | return errs(); 139| | } 140| |} 141| | 142| |#endif 143| | 144| |/// EnableDebugBuffering - Turn on signal handler installation. 145| |/// 146| |bool llvm::EnableDebugBuffering = false; /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Errno.cpp: 1| |//===- Errno.cpp - errno support --------------------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the errno wrappers. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/Errno.h" 15| |#include "llvm/Config/config.h" // Get autoconf configuration settings 16| |#include "llvm/Support/raw_ostream.h" 17| |#include 18| | 19| |#if HAVE_ERRNO_H 20| |#include 21| |#endif 22| | 23| |//===----------------------------------------------------------------------===// 24| |//=== WARNING: Implementation here must contain only TRULY operating system 25| |//=== independent code. 26| |//===----------------------------------------------------------------------===// 27| | 28| |namespace llvm { 29| |namespace sys { 30| | 31| |#if HAVE_ERRNO_H 32| 0|std::string StrError() { 33| 0| return StrError(errno); 34| 0|} 35| |#endif // HAVE_ERRNO_H 36| | 37| 0|std::string StrError(int errnum) { 38| 0| std::string str; 39| 0| if (errnum == 0) 40| 0| return str; 41| 0|#if defined(HAVE_STRERROR_R) || HAVE_DECL_STRERROR_S 42| 0| const int MaxErrStrLen = 2000; 43| 0| char buffer[MaxErrStrLen]; 44| 0| buffer[0] = '\0'; 45| 0|#endif 46| 0| 47| 0|#ifdef HAVE_STRERROR_R 48| 0| // strerror_r is thread-safe. 49| |#if defined(__GLIBC__) && defined(_GNU_SOURCE) 50| | // glibc defines its own incompatible version of strerror_r 51| | // which may not use the buffer supplied. 52| | str = strerror_r(errnum, buffer, MaxErrStrLen - 1); 53| |#else 54| | strerror_r(errnum, buffer, MaxErrStrLen - 1); 55| 0| str = buffer; 56| 0|#endif 57| |#elif HAVE_DECL_STRERROR_S // "Windows Secure API" 58| | strerror_s(buffer, MaxErrStrLen - 1, errnum); 59| | str = buffer; 60| |#elif defined(HAVE_STRERROR) 61| | // Copy the thread un-safe result of strerror into 62| | // the buffer as fast as possible to minimize impact 63| | // of collision of strerror in multiple threads. 64| | str = strerror(errnum); 65| |#else 66| | // Strange that this system doesn't even have strerror 67| | // but, oh well, just use a generic message 68| | raw_string_ostream stream(str); 69| | stream << "Error #" << errnum; 70| | stream.flush(); 71| |#endif 72| | return str; 73| 0|} 74| | 75| |} // namespace sys 76| |} // namespace llvm /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/ErrorHandling.cpp: 1| |//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include "llvm/ADT/SmallVector.h" 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/Config/config.h" 19| |#include "llvm/Support/Debug.h" 20| |#include "llvm/Support/Errc.h" 21| |#include "llvm/Support/ManagedStatic.h" 22| |#include "llvm/Support/Mutex.h" 23| |#include "llvm/Support/MutexGuard.h" 24| |#include "llvm/Support/Signals.h" 25| |#include "llvm/Support/Threading.h" 26| |#include "llvm/Support/WindowsError.h" 27| |#include "llvm/Support/raw_ostream.h" 28| |#include 29| |#include 30| | 31| |#if defined(HAVE_UNISTD_H) 32| |# include 33| |#endif 34| |#if defined(_MSC_VER) 35| |# include 36| |# include 37| |#endif 38| | 39| |typedef void (*LLVMFatalErrorHandler)(const char *Reason); 40| | 41| |using namespace llvm; 42| | 43| |static fatal_error_handler_t ErrorHandler = nullptr; 44| |static void *ErrorHandlerUserData = nullptr; 45| | 46| |static ManagedStatic ErrorHandlerMutex; 47| | 48| |void llvm::install_fatal_error_handler(fatal_error_handler_t handler, 49| 0| void *user_data) { 50| 0| llvm::MutexGuard Lock(*ErrorHandlerMutex); 51| 0| assert(!ErrorHandler && "Error handler already registered!\n"); 52| 0| ErrorHandler = handler; 53| 0| ErrorHandlerUserData = user_data; 54| 0|} 55| | 56| 0|void llvm::remove_fatal_error_handler() { 57| 0| llvm::MutexGuard Lock(*ErrorHandlerMutex); 58| 0| ErrorHandler = nullptr; 59| 0| ErrorHandlerUserData = nullptr; 60| 0|} 61| | 62| 0|void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) { 63| 0| report_fatal_error(Twine(Reason), GenCrashDiag); 64| 0|} 65| | 66| 0|void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) { 67| 0| report_fatal_error(Twine(Reason), GenCrashDiag); 68| 0|} 69| | 70| 0|void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) { 71| 0| report_fatal_error(Twine(Reason), GenCrashDiag); 72| 0|} 73| | 74| 0|void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { 75| 0| llvm::fatal_error_handler_t handler = nullptr; 76| 0| void* handlerData = nullptr; 77| 0| { 78| 0| // Only acquire the mutex while reading the handler, so as not to invoke a 79| 0| // user-supplied callback under a lock. 80| 0| llvm::MutexGuard Lock(*ErrorHandlerMutex); 81| 0| handler = ErrorHandler; 82| 0| handlerData = ErrorHandlerUserData; 83| 0| } 84| 0| 85| 0| if (handler) { 86| 0| handler(handlerData, Reason.str(), GenCrashDiag); 87| 0| } else { 88| 0| // Blast the result out to stderr. We don't try hard to make sure this 89| 0| // succeeds (e.g. handling EINTR) and we can't use errs() here because 90| 0| // raw ostreams can call report_fatal_error. 91| 0| SmallVector Buffer; 92| 0| raw_svector_ostream OS(Buffer); 93| 0| OS << "LLVM ERROR: " << Reason << "\n"; 94| 0| StringRef MessageStr = OS.str(); 95| 0| ssize_t written = ::write(2, MessageStr.data(), MessageStr.size()); 96| 0| (void)written; // If something went wrong, we deliberately just give up. 97| 0| } 98| 0| 99| 0| // If we reached here, we are failing ungracefully. Run the interrupt handlers 100| 0| // to make sure any special cleanups get done, in particular that we remove 101| 0| // files registered with RemoveFileOnSignal. 102| 0| sys::RunInterruptHandlers(); 103| 0| 104| 0| exit(1); 105| 0|} 106| | 107| |void llvm::llvm_unreachable_internal(const char *msg, const char *file, 108| 0| unsigned line) { 109| 0| // This code intentionally doesn't call the ErrorHandler callback, because 110| 0| // llvm_unreachable is intended to be used to indicate "impossible" 111| 0| // situations, and not legitimate runtime errors. 112| 0| if (msg) 113| 0| dbgs() << msg << "\n"; 114| 0| dbgs() << "UNREACHABLE executed"; 115| 0| if (file) 116| 0| dbgs() << " at " << file << ":" << line; 117| 0| dbgs() << "!\n"; 118| 0| abort(); 119| 0|#ifdef LLVM_BUILTIN_UNREACHABLE 120| 0| // Windows systems and possibly others don't declare abort() to be noreturn, 121| 0| // so use the unreachable builtin to avoid a Clang self-host warning. 122| 0| LLVM_BUILTIN_UNREACHABLE; 123| 0|#endif 124| 0|} 125| | 126| |static void bindingsErrorHandler(void *user_data, const std::string& reason, 127| 0| bool gen_crash_diag) { 128| 0| LLVMFatalErrorHandler handler = 129| 0| LLVM_EXTENSION reinterpret_cast(user_data); 130| 0| handler(reason.c_str()); 131| 0|} 132| | 133| 0|void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) { 134| 0| install_fatal_error_handler(bindingsErrorHandler, 135| 0| LLVM_EXTENSION reinterpret_cast(Handler)); 136| 0|} 137| | 138| 0|void LLVMResetFatalErrorHandler() { 139| 0| remove_fatal_error_handler(); 140| 0|} 141| | 142| |#ifdef LLVM_ON_WIN32 143| | 144| |#include 145| | 146| |// I'd rather not double the line count of the following. 147| |#define MAP_ERR_TO_COND(x, y) \ 148| | case x: \ 149| | return make_error_code(errc::y) 150| | 151| |std::error_code llvm::mapWindowsError(unsigned EV) { 152| | switch (EV) { 153| | MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied); 154| | MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists); 155| | MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device); 156| | MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long); 157| | MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy); 158| | MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy); 159| | MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied); 160| | MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error); 161| | MAP_ERR_TO_COND(ERROR_CANTREAD, io_error); 162| | MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error); 163| | MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied); 164| | MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device); 165| | MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy); 166| | MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty); 167| | MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument); 168| | MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device); 169| | MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists); 170| | MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory); 171| | MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device); 172| | MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied); 173| | MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device); 174| | MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported); 175| | MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument); 176| | MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument); 177| | MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available); 178| | MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available); 179| | MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument); 180| | MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied); 181| | MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory); 182| | MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again); 183| | MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error); 184| | MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy); 185| | MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory); 186| | MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory); 187| | MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory); 188| | MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error); 189| | MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again); 190| | MAP_ERR_TO_COND(ERROR_SEEK, io_error); 191| | MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied); 192| | MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open); 193| | MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error); 194| | MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied); 195| | MAP_ERR_TO_COND(WSAEACCES, permission_denied); 196| | MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor); 197| | MAP_ERR_TO_COND(WSAEFAULT, bad_address); 198| | MAP_ERR_TO_COND(WSAEINTR, interrupted); 199| | MAP_ERR_TO_COND(WSAEINVAL, invalid_argument); 200| | MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open); 201| | MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long); 202| | default: 203| | return std::error_code(EV, std::system_category()); 204| | } 205| |} 206| | 207| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/FileUtilities.cpp: 1| |//===- Support/FileUtilities.cpp - File System Utilities ------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements a family of utility functions which are useful for doing 11| |// various things with files. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "llvm/Support/FileUtilities.h" 16| |#include "llvm/ADT/SmallString.h" 17| |#include "llvm/Support/MemoryBuffer.h" 18| |#include "llvm/Support/Path.h" 19| |#include "llvm/Support/raw_ostream.h" 20| |#include 21| |#include 22| |#include 23| |#include 24| |using namespace llvm; 25| | 26| 0|static bool isSignedChar(char C) { 27| 0| return (C == '+' || C == '-'); 28| 0|} 29| | 30| 0|static bool isExponentChar(char C) { 31| 0| switch (C) { 32| 0| case 'D': // Strange exponential notation. 33| 0| case 'd': // Strange exponential notation. 34| 0| case 'e': 35| 0| case 'E': return true; 36| 0| default: return false; 37| 0| } 38| 0|} 39| | 40| 0|static bool isNumberChar(char C) { 41| 0| switch (C) { 42| 0| case '0': case '1': case '2': case '3': case '4': 43| 0| case '5': case '6': case '7': case '8': case '9': 44| 0| case '.': return true; 45| 0| default: return isSignedChar(C) || isExponentChar(C); 46| 0| } 47| 0|} 48| | 49| 0|static const char *BackupNumber(const char *Pos, const char *FirstChar) { 50| 0| // If we didn't stop in the middle of a number, don't backup. 51| 0| if (!isNumberChar(*Pos)) return Pos; 52| 0| 53| 0| // Otherwise, return to the start of the number. 54| 0| bool HasPeriod = false; 55| 0| while (Pos > FirstChar && isNumberChar(Pos[-1])) { 56| 0| // Backup over at most one period. 57| 0| if (Pos[-1] == '.') { 58| 0| if (HasPeriod) 59| 0| break; 60| 0| HasPeriod = true; 61| 0| } 62| 0| 63| 0| --Pos; 64| 0| if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExponentChar(Pos[-1])) 65| 0| break; 66| 0| } 67| 0| return Pos; 68| 0|} 69| | 70| |/// EndOfNumber - Return the first character that is not part of the specified 71| |/// number. This assumes that the buffer is null terminated, so it won't fall 72| |/// off the end. 73| 0|static const char *EndOfNumber(const char *Pos) { 74| 0| while (isNumberChar(*Pos)) 75| 0| ++Pos; 76| 0| return Pos; 77| 0|} 78| | 79| |/// CompareNumbers - compare two numbers, returning true if they are different. 80| |static bool CompareNumbers(const char *&F1P, const char *&F2P, 81| | const char *F1End, const char *F2End, 82| | double AbsTolerance, double RelTolerance, 83| 0| std::string *ErrorMsg) { 84| 0| const char *F1NumEnd, *F2NumEnd; 85| 0| double V1 = 0.0, V2 = 0.0; 86| 0| 87| 0| // If one of the positions is at a space and the other isn't, chomp up 'til 88| 0| // the end of the space. 89| 0| while (isspace(static_cast(*F1P)) && F1P != F1End) 90| 0| ++F1P; 91| 0| while (isspace(static_cast(*F2P)) && F2P != F2End) 92| 0| ++F2P; 93| 0| 94| 0| // If we stop on numbers, compare their difference. 95| 0| if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) { 96| 0| // The diff failed. 97| 0| F1NumEnd = F1P; 98| 0| F2NumEnd = F2P; 99| 0| } else { 100| 0| // Note that some ugliness is built into this to permit support for numbers 101| 0| // that use "D" or "d" as their exponential marker, e.g. "1.234D45". This 102| 0| // occurs in 200.sixtrack in spec2k. 103| 0| V1 = strtod(F1P, const_cast(&F1NumEnd)); 104| 0| V2 = strtod(F2P, const_cast(&F2NumEnd)); 105| 0| 106| 0| if (*F1NumEnd == 'D' || *F1NumEnd == 'd') { 107| 0| // Copy string into tmp buffer to replace the 'D' with an 'e'. 108| 0| SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1); 109| 0| // Strange exponential notation! 110| 0| StrTmp[static_cast(F1NumEnd-F1P)] = 'e'; 111| 0| 112| 0| V1 = strtod(&StrTmp[0], const_cast(&F1NumEnd)); 113| 0| F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]); 114| 0| } 115| 0| 116| 0| if (*F2NumEnd == 'D' || *F2NumEnd == 'd') { 117| 0| // Copy string into tmp buffer to replace the 'D' with an 'e'. 118| 0| SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1); 119| 0| // Strange exponential notation! 120| 0| StrTmp[static_cast(F2NumEnd-F2P)] = 'e'; 121| 0| 122| 0| V2 = strtod(&StrTmp[0], const_cast(&F2NumEnd)); 123| 0| F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]); 124| 0| } 125| 0| } 126| 0| 127| 0| if (F1NumEnd == F1P || F2NumEnd == F2P) { 128| 0| if (ErrorMsg) { 129| 0| *ErrorMsg = "FP Comparison failed, not a numeric difference between '"; 130| 0| *ErrorMsg += F1P[0]; 131| 0| *ErrorMsg += "' and '"; 132| 0| *ErrorMsg += F2P[0]; 133| 0| *ErrorMsg += "'"; 134| 0| } 135| 0| return true; 136| 0| } 137| 0| 138| 0| // Check to see if these are inside the absolute tolerance 139| 0| if (AbsTolerance < std::abs(V1-V2)) { 140| 0| // Nope, check the relative tolerance... 141| 0| double Diff; 142| 0| if (V2) 143| 0| Diff = std::abs(V1/V2 - 1.0); 144| 0| else if (V1) 145| 0| Diff = std::abs(V2/V1 - 1.0); 146| 0| else 147| 0| Diff = 0; // Both zero. 148| 0| if (Diff > RelTolerance) { 149| 0| if (ErrorMsg) { 150| 0| raw_string_ostream(*ErrorMsg) 151| 0| << "Compared: " << V1 << " and " << V2 << '\n' 152| 0| << "abs. diff = " << std::abs(V1-V2) << " rel.diff = " << Diff << '\n' 153| 0| << "Out of tolerance: rel/abs: " << RelTolerance << '/' 154| 0| << AbsTolerance; 155| 0| } 156| 0| return true; 157| 0| } 158| 0| } 159| 0| 160| 0| // Otherwise, advance our read pointers to the end of the numbers. 161| 0| F1P = F1NumEnd; F2P = F2NumEnd; 162| 0| return false; 163| 0|} 164| | 165| |/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the 166| |/// files match, 1 if they are different, and 2 if there is a file error. This 167| |/// function differs from DiffFiles in that you can specify an absolete and 168| |/// relative FP error that is allowed to exist. If you specify a string to fill 169| |/// in for the error option, it will set the string to an error message if an 170| |/// error occurs, allowing the caller to distinguish between a failed diff and a 171| |/// file system error. 172| |/// 173| |int llvm::DiffFilesWithTolerance(StringRef NameA, 174| | StringRef NameB, 175| | double AbsTol, double RelTol, 176| 0| std::string *Error) { 177| 0| // Now its safe to mmap the files into memory because both files 178| 0| // have a non-zero size. 179| 0| ErrorOr> F1OrErr = MemoryBuffer::getFile(NameA); 180| 0| if (std::error_code EC = F1OrErr.getError()) { 181| 0| if (Error) 182| 0| *Error = EC.message(); 183| 0| return 2; 184| 0| } 185| 0| MemoryBuffer &F1 = *F1OrErr.get(); 186| 0| 187| 0| ErrorOr> F2OrErr = MemoryBuffer::getFile(NameB); 188| 0| if (std::error_code EC = F2OrErr.getError()) { 189| 0| if (Error) 190| 0| *Error = EC.message(); 191| 0| return 2; 192| 0| } 193| 0| MemoryBuffer &F2 = *F2OrErr.get(); 194| 0| 195| 0| // Okay, now that we opened the files, scan them for the first difference. 196| 0| const char *File1Start = F1.getBufferStart(); 197| 0| const char *File2Start = F2.getBufferStart(); 198| 0| const char *File1End = F1.getBufferEnd(); 199| 0| const char *File2End = F2.getBufferEnd(); 200| 0| const char *F1P = File1Start; 201| 0| const char *F2P = File2Start; 202| 0| uint64_t A_size = F1.getBufferSize(); 203| 0| uint64_t B_size = F2.getBufferSize(); 204| 0| 205| 0| // Are the buffers identical? Common case: Handle this efficiently. 206| 0| if (A_size == B_size && 207| 0| std::memcmp(File1Start, File2Start, A_size) == 0) 208| 0| return 0; 209| 0| 210| 0| // Otherwise, we are done a tolerances are set. 211| 0| if (AbsTol == 0 && RelTol == 0) { 212| 0| if (Error) 213| 0| *Error = "Files differ without tolerance allowance"; 214| 0| return 1; // Files different! 215| 0| } 216| 0| 217| 0| bool CompareFailed = false; 218| 0| while (1) { 219| 0| // Scan for the end of file or next difference. 220| 0| while (F1P < File1End && F2P < File2End && *F1P == *F2P) 221| 0| ++F1P, ++F2P; 222| 0| 223| 0| if (F1P >= File1End || F2P >= File2End) break; 224| 0| 225| 0| // Okay, we must have found a difference. Backup to the start of the 226| 0| // current number each stream is at so that we can compare from the 227| 0| // beginning. 228| 0| F1P = BackupNumber(F1P, File1Start); 229| 0| F2P = BackupNumber(F2P, File2Start); 230| 0| 231| 0| // Now that we are at the start of the numbers, compare them, exiting if 232| 0| // they don't match. 233| 0| if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) { 234| 0| CompareFailed = true; 235| 0| break; 236| 0| } 237| 0| } 238| 0| 239| 0| // Okay, we reached the end of file. If both files are at the end, we 240| 0| // succeeded. 241| 0| bool F1AtEnd = F1P >= File1End; 242| 0| bool F2AtEnd = F2P >= File2End; 243| 0| if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) { 244| 0| // Else, we might have run off the end due to a number: backup and retry. 245| 0| if (F1AtEnd && isNumberChar(F1P[-1])) --F1P; 246| 0| if (F2AtEnd && isNumberChar(F2P[-1])) --F2P; 247| 0| F1P = BackupNumber(F1P, File1Start); 248| 0| F2P = BackupNumber(F2P, File2Start); 249| 0| 250| 0| // Now that we are at the start of the numbers, compare them, exiting if 251| 0| // they don't match. 252| 0| if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) 253| 0| CompareFailed = true; 254| 0| 255| 0| // If we found the end, we succeeded. 256| 0| if (F1P < File1End || F2P < File2End) 257| 0| CompareFailed = true; 258| 0| } 259| 0| 260| 0| return CompareFailed; 261| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Hashing.cpp: 1| |//===-------------- lib/Support/Hashing.cpp -------------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides implementation bits for the LLVM common hashing 11| |// infrastructure. Documentation and most of the other information is in the 12| |// header file. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#include "llvm/ADT/Hashing.h" 17| | 18| |using namespace llvm; 19| | 20| |// Provide a definition and static initializer for the fixed seed. This 21| |// initializer should always be zero to ensure its value can never appear to be 22| |// non-zero, even during dynamic initialization. 23| |size_t llvm::hashing::detail::fixed_seed_override = 0; 24| | 25| |// Implement the function for forced setting of the fixed seed. 26| |// FIXME: Use atomic operations here so that there is no data race. 27| 0|void llvm::set_fixed_execution_hash_seed(size_t fixed_value) { 28| 0| hashing::detail::fixed_seed_override = fixed_value; 29| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/IntrusiveRefCntPtr.cpp: 1| |//== IntrusiveRefCntPtr.cpp - Smart Refcounting Pointer ----------*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#include "llvm/ADT/IntrusiveRefCntPtr.h" 11| | 12| |using namespace llvm; 13| | 14| 0|void RefCountedBaseVPTR::anchor() { } /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Locale.cpp: 1| |#include "llvm/Support/Locale.h" 2| |#include "llvm/Support/Unicode.h" 3| | 4| |namespace llvm { 5| |namespace sys { 6| |namespace locale { 7| | 8| 0|int columnWidth(StringRef Text) { 9| |#if LLVM_ON_WIN32 10| | return Text.size(); 11| |#else 12| | return llvm::sys::unicode::columnWidthUTF8(Text); 13| 0|#endif 14| 0|} 15| | 16| 0|bool isPrint(int UCS) { 17| |#if LLVM_ON_WIN32 18| | // Restrict characters that we'll try to print to the the lower part of ASCII 19| | // except for the control characters (0x20 - 0x7E). In general one can not 20| | // reliably output code points U+0080 and higher using narrow character C/C++ 21| | // output functions in Windows, because the meaning of the upper 128 codes is 22| | // determined by the active code page in the console. 23| | return ' ' <= UCS && UCS <= '~'; 24| |#else 25| | return llvm::sys::unicode::isPrintable(UCS); 26| 0|#endif 27| 0|} 28| | 29| |} // namespace locale 30| |} // namespace sys 31| |} // namespace llvm /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/ManagedStatic.cpp: 1| |//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the ManagedStatic class and llvm_shutdown(). 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/ManagedStatic.h" 15| |#include "llvm/Config/config.h" 16| |#include "llvm/Support/Atomic.h" 17| |#include "llvm/Support/Mutex.h" 18| |#include "llvm/Support/MutexGuard.h" 19| |#include 20| |using namespace llvm; 21| | 22| |static const ManagedStaticBase *StaticList = nullptr; 23| | 24| 0|static sys::Mutex& getManagedStaticMutex() { 25| 0| // We need to use a function local static here, since this can get called 26| 0| // during a static constructor and we need to guarantee that it's initialized 27| 0| // correctly. 28| 0| static sys::Mutex ManagedStaticMutex; 29| 0| return ManagedStaticMutex; 30| 0|} 31| | 32| |void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 33| 0| void (*Deleter)(void*)) const { 34| 0| assert(Creator); 35| 0| if (llvm_is_multithreaded()) { 36| 0| MutexGuard Lock(getManagedStaticMutex()); 37| 0| 38| 0| if (!Ptr) { 39| 0| void* tmp = Creator(); 40| 0| 41| 0| TsanHappensBefore(this); 42| 0| sys::MemoryFence(); 43| 0| 44| 0| // This write is racy against the first read in the ManagedStatic 45| 0| // accessors. The race is benign because it does a second read after a 46| 0| // memory fence, at which point it isn't possible to get a partial value. 47| 0| TsanIgnoreWritesBegin(); 48| 0| Ptr = tmp; 49| 0| TsanIgnoreWritesEnd(); 50| 0| DeleterFn = Deleter; 51| 0| 52| 0| // Add to list of managed statics. 53| 0| Next = StaticList; 54| 0| StaticList = this; 55| 0| } 56| 0| } else { 57| 0| assert(!Ptr && !DeleterFn && !Next && 58| 0| "Partially initialized ManagedStatic!?"); 59| 0| Ptr = Creator(); 60| 0| DeleterFn = Deleter; 61| 0| 62| 0| // Add to list of managed statics. 63| 0| Next = StaticList; 64| 0| StaticList = this; 65| 0| } 66| 0|} 67| | 68| 0|void ManagedStaticBase::destroy() const { 69| 0| assert(DeleterFn && "ManagedStatic not initialized correctly!"); 70| 0| assert(StaticList == this && 71| 0| "Not destroyed in reverse order of construction?"); 72| 0| // Unlink from list. 73| 0| StaticList = Next; 74| 0| Next = nullptr; 75| 0| 76| 0| // Destroy memory. 77| 0| DeleterFn(Ptr); 78| 0| 79| 0| // Cleanup. 80| 0| Ptr = nullptr; 81| 0| DeleterFn = nullptr; 82| 0|} 83| | 84| |/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 85| 0|void llvm::llvm_shutdown() { 86| 0| MutexGuard Lock(getManagedStaticMutex()); 87| 0| 88| 0| while (StaticList) 89| 0| StaticList->destroy(); 90| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/MemoryBuffer.cpp: 1| |//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the MemoryBuffer interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/MemoryBuffer.h" 15| |#include "llvm/ADT/SmallString.h" 16| |#include "llvm/Config/config.h" 17| |#include "llvm/Support/Errc.h" 18| |#include "llvm/Support/Errno.h" 19| |#include "llvm/Support/FileSystem.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/Path.h" 22| |#include "llvm/Support/Process.h" 23| |#include "llvm/Support/Program.h" 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| |#include 31| |#if !defined(_MSC_VER) && !defined(__MINGW32__) 32| |#include 33| |#else 34| |#include 35| |#endif 36| |using namespace llvm; 37| | 38| |//===----------------------------------------------------------------------===// 39| |// MemoryBuffer implementation itself. 40| |//===----------------------------------------------------------------------===// 41| | 42| 0|MemoryBuffer::~MemoryBuffer() { } 43| | 44| |/// init - Initialize this MemoryBuffer as a reference to externally allocated 45| |/// memory, memory that we know is already null terminated. 46| |void MemoryBuffer::init(const char *BufStart, const char *BufEnd, 47| 0| bool RequiresNullTerminator) { 48| 0| assert((!RequiresNullTerminator || BufEnd[0] == 0) && 49| 0| "Buffer is not null terminated!"); 50| 0| BufferStart = BufStart; 51| 0| BufferEnd = BufEnd; 52| 0|} 53| | 54| |//===----------------------------------------------------------------------===// 55| |// MemoryBufferMem implementation. 56| |//===----------------------------------------------------------------------===// 57| | 58| |/// CopyStringRef - Copies contents of a StringRef into a block of memory and 59| |/// null-terminates it. 60| 0|static void CopyStringRef(char *Memory, StringRef Data) { 61| 0| memcpy(Memory, Data.data(), Data.size()); 62| 0| Memory[Data.size()] = 0; // Null terminate string. 63| 0|} 64| | 65| |namespace { 66| |struct NamedBufferAlloc { 67| | const Twine &Name; 68| 0| NamedBufferAlloc(const Twine &Name) : Name(Name) {} 69| |}; 70| |} 71| | 72| 0|void *operator new(size_t N, const NamedBufferAlloc &Alloc) { 73| 0| SmallString<256> NameBuf; 74| 0| StringRef NameRef = Alloc.Name.toStringRef(NameBuf); 75| 0| 76| 0| char *Mem = static_cast(operator new(N + NameRef.size() + 1)); 77| 0| CopyStringRef(Mem + N, NameRef); 78| 0| return Mem; 79| 0|} 80| | 81| |namespace { 82| |/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. 83| |class MemoryBufferMem : public MemoryBuffer { 84| |public: 85| 0| MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) { 86| 0| init(InputData.begin(), InputData.end(), RequiresNullTerminator); 87| 0| } 88| | 89| 0| const char *getBufferIdentifier() const override { 90| 0| // The name is stored after the class itself. 91| 0| return reinterpret_cast(this + 1); 92| 0| } 93| | 94| 0| BufferKind getBufferKind() const override { 95| 0| return MemoryBuffer_Malloc; 96| 0| } 97| |}; 98| |} 99| | 100| |static ErrorOr> 101| |getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, 102| | uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize); 103| | 104| |std::unique_ptr 105| |MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, 106| 0| bool RequiresNullTerminator) { 107| 0| auto *Ret = new (NamedBufferAlloc(BufferName)) 108| 0| MemoryBufferMem(InputData, RequiresNullTerminator); 109| 0| return std::unique_ptr(Ret); 110| 0|} 111| | 112| |std::unique_ptr 113| 0|MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) { 114| 0| return std::unique_ptr(getMemBuffer( 115| 0| Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator)); 116| 0|} 117| | 118| |std::unique_ptr 119| 0|MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) { 120| 0| std::unique_ptr Buf = 121| 0| getNewUninitMemBuffer(InputData.size(), BufferName); 122| 0| if (!Buf) 123| 0| return nullptr; 124| 0| memcpy(const_cast(Buf->getBufferStart()), InputData.data(), 125| 0| InputData.size()); 126| 0| return Buf; 127| 0|} 128| | 129| |std::unique_ptr 130| 0|MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) { 131| 0| // Allocate space for the MemoryBuffer, the data and the name. It is important 132| 0| // that MemoryBuffer and data are aligned so PointerIntPair works with them. 133| 0| // TODO: Is 16-byte alignment enough? We copy small object files with large 134| 0| // alignment expectations into this buffer. 135| 0| SmallString<256> NameBuf; 136| 0| StringRef NameRef = BufferName.toStringRef(NameBuf); 137| 0| size_t AlignedStringLen = 138| 0| RoundUpToAlignment(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16); 139| 0| size_t RealLen = AlignedStringLen + Size + 1; 140| 0| char *Mem = static_cast(operator new(RealLen, std::nothrow)); 141| 0| if (!Mem) 142| 0| return nullptr; 143| 0| 144| 0| // The name is stored after the class itself. 145| 0| CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef); 146| 0| 147| 0| // The buffer begins after the name and must be aligned. 148| 0| char *Buf = Mem + AlignedStringLen; 149| 0| Buf[Size] = 0; // Null terminate buffer. 150| 0| 151| 0| auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); 152| 0| return std::unique_ptr(Ret); 153| 0|} 154| | 155| |std::unique_ptr 156| 0|MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { 157| 0| std::unique_ptr SB = getNewUninitMemBuffer(Size, BufferName); 158| 0| if (!SB) 159| 0| return nullptr; 160| 0| memset(const_cast(SB->getBufferStart()), 0, Size); 161| 0| return SB; 162| 0|} 163| | 164| |ErrorOr> 165| 0|MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize) { 166| 0| SmallString<256> NameBuf; 167| 0| StringRef NameRef = Filename.toStringRef(NameBuf); 168| 0| 169| 0| if (NameRef == "-") 170| 0| return getSTDIN(); 171| 0| return getFile(Filename, FileSize); 172| 0|} 173| | 174| |ErrorOr> 175| |MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, 176| 0| uint64_t Offset) { 177| 0| return getFileAux(FilePath, -1, MapSize, Offset, false, false); 178| 0|} 179| | 180| | 181| |//===----------------------------------------------------------------------===// 182| |// MemoryBuffer::getFile implementation. 183| |//===----------------------------------------------------------------------===// 184| | 185| |namespace { 186| |/// \brief Memory maps a file descriptor using sys::fs::mapped_file_region. 187| |/// 188| |/// This handles converting the offset into a legal offset on the platform. 189| |class MemoryBufferMMapFile : public MemoryBuffer { 190| | sys::fs::mapped_file_region MFR; 191| | 192| 0| static uint64_t getLegalMapOffset(uint64_t Offset) { 193| 0| return Offset & ~(sys::fs::mapped_file_region::alignment() - 1); 194| 0| } 195| | 196| 0| static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) { 197| 0| return Len + (Offset - getLegalMapOffset(Offset)); 198| 0| } 199| | 200| 0| const char *getStart(uint64_t Len, uint64_t Offset) { 201| 0| return MFR.const_data() + (Offset - getLegalMapOffset(Offset)); 202| 0| } 203| | 204| |public: 205| | MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len, 206| | uint64_t Offset, std::error_code &EC) 207| | : MFR(FD, sys::fs::mapped_file_region::readonly, 208| 0| getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) { 209| 0| if (!EC) { 210| 0| const char *Start = getStart(Len, Offset); 211| 0| init(Start, Start + Len, RequiresNullTerminator); 212| 0| } 213| 0| } 214| | 215| 0| const char *getBufferIdentifier() const override { 216| 0| // The name is stored after the class itself. 217| 0| return reinterpret_cast(this + 1); 218| 0| } 219| | 220| 0| BufferKind getBufferKind() const override { 221| 0| return MemoryBuffer_MMap; 222| 0| } 223| |}; 224| |} 225| | 226| |static ErrorOr> 227| 0|getMemoryBufferForStream(int FD, const Twine &BufferName) { 228| 0| const ssize_t ChunkSize = 4096*4; 229| 0| SmallString Buffer; 230| 0| ssize_t ReadBytes; 231| 0| // Read into Buffer until we hit EOF. 232| 0| do { 233| 0| Buffer.reserve(Buffer.size() + ChunkSize); 234| 0| ReadBytes = read(FD, Buffer.end(), ChunkSize); 235| 0| if (ReadBytes == -1) { 236| 0| if (errno == EINTR) continue; 237| 0| return std::error_code(errno, std::generic_category()); 238| 0| } 239| 0| Buffer.set_size(Buffer.size() + ReadBytes); 240| 0| } while (ReadBytes != 0); 241| 0| 242| 0| return MemoryBuffer::getMemBufferCopy(Buffer, BufferName); 243| 0|} 244| | 245| | 246| |ErrorOr> 247| |MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize, 248| 0| bool RequiresNullTerminator, bool IsVolatileSize) { 249| 0| return getFileAux(Filename, FileSize, FileSize, 0, 250| 0| RequiresNullTerminator, IsVolatileSize); 251| 0|} 252| | 253| |static ErrorOr> 254| |getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, 255| | uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, 256| | bool IsVolatileSize); 257| | 258| |static ErrorOr> 259| |getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, 260| 0| uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) { 261| 0| int FD; 262| 0| std::error_code EC = sys::fs::openFileForRead(Filename, FD); 263| 0| if (EC) 264| 0| return EC; 265| 0| 266| 0| ErrorOr> Ret = 267| 0| getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset, 268| 0| RequiresNullTerminator, IsVolatileSize); 269| 0| close(FD); 270| 0| return Ret; 271| 0|} 272| | 273| |static bool shouldUseMmap(int FD, 274| | size_t FileSize, 275| | size_t MapSize, 276| | off_t Offset, 277| | bool RequiresNullTerminator, 278| | int PageSize, 279| 0| bool IsVolatileSize) { 280| 0| // mmap may leave the buffer without null terminator if the file size changed 281| 0| // by the time the last page is mapped in, so avoid it if the file size is 282| 0| // likely to change. 283| 0| if (IsVolatileSize) 284| 0| return false; 285| 0| 286| 0| // We don't use mmap for small files because this can severely fragment our 287| 0| // address space. 288| 0| if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize) 289| 0| return false; 290| 0| 291| 0| if (!RequiresNullTerminator) 292| 0| return true; 293| 0| 294| 0| 295| 0| // If we don't know the file size, use fstat to find out. fstat on an open 296| 0| // file descriptor is cheaper than stat on a random path. 297| 0| // FIXME: this chunk of code is duplicated, but it avoids a fstat when 298| 0| // RequiresNullTerminator = false and MapSize != -1. 299| 0| if (FileSize == size_t(-1)) { 300| 0| sys::fs::file_status Status; 301| 0| if (sys::fs::status(FD, Status)) 302| 0| return false; 303| 0| FileSize = Status.getSize(); 304| 0| } 305| 0| 306| 0| // If we need a null terminator and the end of the map is inside the file, 307| 0| // we cannot use mmap. 308| 0| size_t End = Offset + MapSize; 309| 0| assert(End <= FileSize); 310| 0| if (End != FileSize) 311| 0| return false; 312| 0| 313| 0| // Don't try to map files that are exactly a multiple of the system page size 314| 0| // if we need a null terminator. 315| 0| if ((FileSize & (PageSize -1)) == 0) 316| 0| return false; 317| 0| 318| |#if defined(__CYGWIN__) 319| | // Don't try to map files that are exactly a multiple of the physical page size 320| | // if we need a null terminator. 321| | // FIXME: We should reorganize again getPageSize() on Win32. 322| | if ((FileSize & (4096 - 1)) == 0) 323| | return false; 324| |#endif 325| | 326| 0| return true; 327| 0|} 328| | 329| |static ErrorOr> 330| |getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, 331| | uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, 332| 0| bool IsVolatileSize) { 333| 0| static int PageSize = sys::Process::getPageSize(); 334| 0| 335| 0| // Default is to map the full file. 336| 0| if (MapSize == uint64_t(-1)) { 337| 0| // If we don't know the file size, use fstat to find out. fstat on an open 338| 0| // file descriptor is cheaper than stat on a random path. 339| 0| if (FileSize == uint64_t(-1)) { 340| 0| sys::fs::file_status Status; 341| 0| std::error_code EC = sys::fs::status(FD, Status); 342| 0| if (EC) 343| 0| return EC; 344| 0| 345| 0| // If this not a file or a block device (e.g. it's a named pipe 346| 0| // or character device), we can't trust the size. Create the memory 347| 0| // buffer by copying off the stream. 348| 0| sys::fs::file_type Type = Status.type(); 349| 0| if (Type != sys::fs::file_type::regular_file && 350| 0| Type != sys::fs::file_type::block_file) 351| 0| return getMemoryBufferForStream(FD, Filename); 352| 0| 353| 0| FileSize = Status.getSize(); 354| 0| } 355| 0| MapSize = FileSize; 356| 0| } 357| 0| 358| 0| if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, 359| 0| PageSize, IsVolatileSize)) { 360| 0| std::error_code EC; 361| 0| std::unique_ptr Result( 362| 0| new (NamedBufferAlloc(Filename)) 363| 0| MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC)); 364| 0| if (!EC) 365| 0| return std::move(Result); 366| 0| } 367| 0| 368| 0| std::unique_ptr Buf = 369| 0| MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); 370| 0| if (!Buf) { 371| 0| // Failed to create a buffer. The only way it can fail is if 372| 0| // new(std::nothrow) returns 0. 373| 0| return make_error_code(errc::not_enough_memory); 374| 0| } 375| 0| 376| 0| char *BufPtr = const_cast(Buf->getBufferStart()); 377| 0| 378| 0| size_t BytesLeft = MapSize; 379| |#ifndef HAVE_PREAD 380| | if (lseek(FD, Offset, SEEK_SET) == -1) 381| | return std::error_code(errno, std::generic_category()); 382| |#endif 383| | 384| 0| while (BytesLeft) { 385| 0|#ifdef HAVE_PREAD 386| 0| ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset); 387| |#else 388| | ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); 389| |#endif 390| 0| if (NumRead == -1) { 391| 0| if (errno == EINTR) 392| 0| continue; 393| 0| // Error while reading. 394| 0| return std::error_code(errno, std::generic_category()); 395| 0| } 396| 0| if (NumRead == 0) { 397| 0| memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer. 398| 0| break; 399| 0| } 400| 0| BytesLeft -= NumRead; 401| 0| BufPtr += NumRead; 402| 0| } 403| 0| 404| 0| return std::move(Buf); 405| 0|} 406| | 407| |ErrorOr> 408| |MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, 409| 0| bool RequiresNullTerminator, bool IsVolatileSize) { 410| 0| return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, 411| 0| RequiresNullTerminator, IsVolatileSize); 412| 0|} 413| | 414| |ErrorOr> 415| |MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, 416| 0| int64_t Offset) { 417| 0| assert(MapSize != uint64_t(-1)); 418| 0| return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, 419| 0| /*IsVolatileSize*/ false); 420| 0|} 421| | 422| 0|ErrorOr> MemoryBuffer::getSTDIN() { 423| 0| // Read in all of the data from stdin, we cannot mmap stdin. 424| 0| // 425| 0| // FIXME: That isn't necessarily true, we should try to mmap stdin and 426| 0| // fallback if it fails. 427| 0| sys::ChangeStdinToBinary(); 428| 0| 429| 0| return getMemoryBufferForStream(0, ""); 430| 0|} 431| | 432| 0|MemoryBufferRef MemoryBuffer::getMemBufferRef() const { 433| 0| StringRef Data = getBuffer(); 434| 0| StringRef Identifier = getBufferIdentifier(); 435| 0| return MemoryBufferRef(Data, Identifier); 436| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Mutex.cpp: 1| |//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the llvm::sys::Mutex class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Config/config.h" 15| |#include "llvm/Support/Mutex.h" 16| | 17| |//===----------------------------------------------------------------------===// 18| |//=== WARNING: Implementation here must contain only TRULY operating system 19| |//=== independent code. 20| |//===----------------------------------------------------------------------===// 21| | 22| |#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 23| |// Define all methods as no-ops if threading is explicitly disabled 24| |namespace llvm { 25| |using namespace sys; 26| |MutexImpl::MutexImpl( bool recursive) { } 27| |MutexImpl::~MutexImpl() { } 28| |bool MutexImpl::acquire() { return true; } 29| |bool MutexImpl::release() { return true; } 30| |bool MutexImpl::tryacquire() { return true; } 31| |} 32| |#else 33| | 34| |#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) 35| | 36| |#include 37| |#include 38| |#include 39| | 40| |namespace llvm { 41| |using namespace sys; 42| | 43| |// Construct a Mutex using pthread calls 44| |MutexImpl::MutexImpl( bool recursive) 45| | : data_(nullptr) 46| 0|{ 47| 0| // Declare the pthread_mutex data structures 48| 0| pthread_mutex_t* mutex = 49| 0| static_cast(malloc(sizeof(pthread_mutex_t))); 50| 0| pthread_mutexattr_t attr; 51| 0| 52| 0| // Initialize the mutex attributes 53| 0| // FIXME: We silence analyzer warnings about errorcode, but should probably 54| 0| // be doing something more sensible at runtime with the checks (abort?). 55| 0| int errorcode = pthread_mutexattr_init(&attr); 56| 0| assert(errorcode == 0); (void)errorcode; 57| 0| 58| 0| // Initialize the mutex as a recursive mutex, if requested, or normal 59| 0| // otherwise. 60| 0| int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); 61| 0| errorcode = pthread_mutexattr_settype(&attr, kind); 62| 0| assert(errorcode == 0); (void)errorcode; 63| 0| 64| 0| // Initialize the mutex 65| 0| errorcode = pthread_mutex_init(mutex, &attr); 66| 0| assert(errorcode == 0); (void)errorcode; 67| 0| 68| 0| // Destroy the attributes 69| 0| errorcode = pthread_mutexattr_destroy(&attr); 70| 0| assert(errorcode == 0); (void)errorcode; 71| 0| 72| 0| // Assign the data member 73| 0| data_ = mutex; 74| 0|} 75| | 76| |// Destruct a Mutex 77| |MutexImpl::~MutexImpl() 78| 0|{ 79| 0| pthread_mutex_t* mutex = static_cast(data_); 80| 0| assert(mutex != nullptr); 81| 0| pthread_mutex_destroy(mutex); 82| 0| free(mutex); 83| 0|} 84| | 85| |bool 86| |MutexImpl::acquire() 87| 0|{ 88| 0| pthread_mutex_t* mutex = static_cast(data_); 89| 0| assert(mutex != nullptr); 90| 0| 91| 0| int errorcode = pthread_mutex_lock(mutex); 92| 0| return errorcode == 0; 93| 0|} 94| | 95| |bool 96| |MutexImpl::release() 97| 0|{ 98| 0| pthread_mutex_t* mutex = static_cast(data_); 99| 0| assert(mutex != nullptr); 100| 0| 101| 0| int errorcode = pthread_mutex_unlock(mutex); 102| 0| return errorcode == 0; 103| 0|} 104| | 105| |bool 106| |MutexImpl::tryacquire() 107| 0|{ 108| 0| pthread_mutex_t* mutex = static_cast(data_); 109| 0| assert(mutex != nullptr); 110| 0| 111| 0| int errorcode = pthread_mutex_trylock(mutex); 112| 0| return errorcode == 0; 113| 0|} 114| | 115| |} 116| | 117| |#elif defined(LLVM_ON_UNIX) 118| |#include "Unix/Mutex.inc" 119| |#elif defined( LLVM_ON_WIN32) 120| |#include "Windows/Mutex.inc" 121| |#else 122| |#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp 123| |#endif 124| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Path.cpp: 1| |//===-- Path.cpp - Implement OS Path Concept ------------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the operating system Path API. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/COFF.h" 15| |#include "llvm/Support/Endian.h" 16| |#include "llvm/Support/Errc.h" 17| |#include "llvm/Support/ErrorHandling.h" 18| |#include "llvm/Support/FileSystem.h" 19| |#include "llvm/Support/Path.h" 20| |#include "llvm/Support/Process.h" 21| |#include 22| |#include 23| |#include 24| |#include 25| | 26| |#if !defined(_MSC_VER) && !defined(__MINGW32__) 27| |#include 28| |#else 29| |#include 30| |#endif 31| | 32| |using namespace llvm; 33| |using namespace llvm::support::endian; 34| | 35| |namespace { 36| | using llvm::StringRef; 37| | using llvm::sys::path::is_separator; 38| | 39| |#ifdef LLVM_ON_WIN32 40| | const char *separators = "\\/"; 41| | const char preferred_separator = '\\'; 42| |#else 43| | const char separators = '/'; 44| | const char preferred_separator = '/'; 45| |#endif 46| | 47| 0| StringRef find_first_component(StringRef path) { 48| 0| // Look for this first component in the following order. 49| 0| // * empty (in this case we return an empty string) 50| 0| // * either C: or {//,\\}net. 51| 0| // * {/,\} 52| 0| // * {file,directory}name 53| 0| 54| 0| if (path.empty()) 55| 0| return path; 56| 0| 57| |#ifdef LLVM_ON_WIN32 58| | // C: 59| | if (path.size() >= 2 && std::isalpha(static_cast(path[0])) && 60| | path[1] == ':') 61| | return path.substr(0, 2); 62| |#endif 63| | 64| 0| // //net 65| 0| if ((path.size() > 2) && 66| 0| is_separator(path[0]) && 67| 0| path[0] == path[1] && 68| 0| !is_separator(path[2])) { 69| 0| // Find the next directory separator. 70| 0| size_t end = path.find_first_of(separators, 2); 71| 0| return path.substr(0, end); 72| 0| } 73| 0| 74| 0| // {/,\} 75| 0| if (is_separator(path[0])) 76| 0| return path.substr(0, 1); 77| 0| 78| 0| // * {file,directory}name 79| 0| size_t end = path.find_first_of(separators); 80| 0| return path.substr(0, end); 81| 0| } 82| | 83| 0| size_t filename_pos(StringRef str) { 84| 0| if (str.size() == 2 && 85| 0| is_separator(str[0]) && 86| 0| str[0] == str[1]) 87| 0| return 0; 88| 0| 89| 0| if (str.size() > 0 && is_separator(str[str.size() - 1])) 90| 0| return str.size() - 1; 91| 0| 92| 0| size_t pos = str.find_last_of(separators, str.size() - 1); 93| 0| 94| |#ifdef LLVM_ON_WIN32 95| | if (pos == StringRef::npos) 96| | pos = str.find_last_of(':', str.size() - 2); 97| |#endif 98| | 99| 0| if (pos == StringRef::npos || 100| 0| (pos == 1 && is_separator(str[0]))) 101| 0| return 0; 102| 0| 103| 0| return pos + 1; 104| 0| } 105| | 106| 0| size_t root_dir_start(StringRef str) { 107| 0| // case "c:/" 108| |#ifdef LLVM_ON_WIN32 109| | if (str.size() > 2 && 110| | str[1] == ':' && 111| | is_separator(str[2])) 112| | return 2; 113| |#endif 114| | 115| 0| // case "//" 116| 0| if (str.size() == 2 && 117| 0| is_separator(str[0]) && 118| 0| str[0] == str[1]) 119| 0| return StringRef::npos; 120| 0| 121| 0| // case "//net" 122| 0| if (str.size() > 3 && 123| 0| is_separator(str[0]) && 124| 0| str[0] == str[1] && 125| 0| !is_separator(str[2])) { 126| 0| return str.find_first_of(separators, 2); 127| 0| } 128| 0| 129| 0| // case "/" 130| 0| if (str.size() > 0 && is_separator(str[0])) 131| 0| return 0; 132| 0| 133| 0| return StringRef::npos; 134| 0| } 135| | 136| 0| size_t parent_path_end(StringRef path) { 137| 0| size_t end_pos = filename_pos(path); 138| 0| 139| 0| bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]); 140| 0| 141| 0| // Skip separators except for root dir. 142| 0| size_t root_dir_pos = root_dir_start(path.substr(0, end_pos)); 143| 0| 144| 0| while(end_pos > 0 && 145| 0| (end_pos - 1) != root_dir_pos && 146| 0| is_separator(path[end_pos - 1])) 147| 0| --end_pos; 148| 0| 149| 0| if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) 150| 0| return StringRef::npos; 151| 0| 152| 0| return end_pos; 153| 0| } 154| |} // end unnamed namespace 155| | 156| |enum FSEntity { 157| | FS_Dir, 158| | FS_File, 159| | FS_Name 160| |}; 161| | 162| |static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, 163| | SmallVectorImpl &ResultPath, 164| | bool MakeAbsolute, unsigned Mode, 165| 0| FSEntity Type) { 166| 0| SmallString<128> ModelStorage; 167| 0| Model.toVector(ModelStorage); 168| 0| 169| 0| if (MakeAbsolute) { 170| 0| // Make model absolute by prepending a temp directory if it's not already. 171| 0| if (!sys::path::is_absolute(Twine(ModelStorage))) { 172| 0| SmallString<128> TDir; 173| 0| sys::path::system_temp_directory(true, TDir); 174| 0| sys::path::append(TDir, Twine(ModelStorage)); 175| 0| ModelStorage.swap(TDir); 176| 0| } 177| 0| } 178| 0| 179| 0| // From here on, DO NOT modify model. It may be needed if the randomly chosen 180| 0| // path already exists. 181| 0| ResultPath = ModelStorage; 182| 0| // Null terminate. 183| 0| ResultPath.push_back(0); 184| 0| ResultPath.pop_back(); 185| 0| 186| 0|retry_random_path: 187| 0| // Replace '%' with random chars. 188| 0| for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { 189| 0| if (ModelStorage[i] == '%') 190| 0| ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; 191| 0| } 192| 0| 193| 0| // Try to open + create the file. 194| 0| switch (Type) { 195| 0| case FS_File: { 196| 0| if (std::error_code EC = 197| 0| sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD, 198| 0| sys::fs::F_RW | sys::fs::F_Excl, Mode)) { 199| 0| if (EC == errc::file_exists) 200| 0| goto retry_random_path; 201| 0| return EC; 202| 0| } 203| 0| 204| 0| return std::error_code(); 205| 0| } 206| 0| 207| 0| case FS_Name: { 208| 0| std::error_code EC = 209| 0| sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); 210| 0| if (EC == errc::no_such_file_or_directory) 211| 0| return std::error_code(); 212| 0| if (EC) 213| 0| return EC; 214| 0| goto retry_random_path; 215| 0| } 216| 0| 217| 0| case FS_Dir: { 218| 0| if (std::error_code EC = 219| 0| sys::fs::create_directory(ResultPath.begin(), false)) { 220| 0| if (EC == errc::file_exists) 221| 0| goto retry_random_path; 222| 0| return EC; 223| 0| } 224| 0| return std::error_code(); 225| 0| } 226| 0| } 227| 0| llvm_unreachable("Invalid Type"); 228| 0|} 229| | 230| |namespace llvm { 231| |namespace sys { 232| |namespace path { 233| | 234| 0|const_iterator begin(StringRef path) { 235| 0| const_iterator i; 236| 0| i.Path = path; 237| 0| i.Component = find_first_component(path); 238| 0| i.Position = 0; 239| 0| return i; 240| 0|} 241| | 242| 0|const_iterator end(StringRef path) { 243| 0| const_iterator i; 244| 0| i.Path = path; 245| 0| i.Position = path.size(); 246| 0| return i; 247| 0|} 248| | 249| 0|const_iterator &const_iterator::operator++() { 250| 0| assert(Position < Path.size() && "Tried to increment past end!"); 251| 0| 252| 0| // Increment Position to past the current component 253| 0| Position += Component.size(); 254| 0| 255| 0| // Check for end. 256| 0| if (Position == Path.size()) { 257| 0| Component = StringRef(); 258| 0| return *this; 259| 0| } 260| 0| 261| 0| // Both POSIX and Windows treat paths that begin with exactly two separators 262| 0| // specially. 263| 0| bool was_net = Component.size() > 2 && 264| 0| is_separator(Component[0]) && 265| 0| Component[1] == Component[0] && 266| 0| !is_separator(Component[2]); 267| 0| 268| 0| // Handle separators. 269| 0| if (is_separator(Path[Position])) { 270| 0| // Root dir. 271| 0| if (was_net 272| |#ifdef LLVM_ON_WIN32 273| | // c:/ 274| | || Component.endswith(":") 275| |#endif 276| 0| ) { 277| 0| Component = Path.substr(Position, 1); 278| 0| return *this; 279| 0| } 280| 0| 281| 0| // Skip extra separators. 282| 0| while (Position != Path.size() && 283| 0| is_separator(Path[Position])) { 284| 0| ++Position; 285| 0| } 286| 0| 287| 0| // Treat trailing '/' as a '.'. 288| 0| if (Position == Path.size()) { 289| 0| --Position; 290| 0| Component = "."; 291| 0| return *this; 292| 0| } 293| 0| } 294| 0| 295| 0| // Find next component. 296| 0| size_t end_pos = Path.find_first_of(separators, Position); 297| 0| Component = Path.slice(Position, end_pos); 298| 0| 299| 0| return *this; 300| 0|} 301| | 302| 0|bool const_iterator::operator==(const const_iterator &RHS) const { 303| 0| return Path.begin() == RHS.Path.begin() && Position == RHS.Position; 304| 0|} 305| | 306| 0|ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { 307| 0| return Position - RHS.Position; 308| 0|} 309| | 310| 0|reverse_iterator rbegin(StringRef Path) { 311| 0| reverse_iterator I; 312| 0| I.Path = Path; 313| 0| I.Position = Path.size(); 314| 0| return ++I; 315| 0|} 316| | 317| 0|reverse_iterator rend(StringRef Path) { 318| 0| reverse_iterator I; 319| 0| I.Path = Path; 320| 0| I.Component = Path.substr(0, 0); 321| 0| I.Position = 0; 322| 0| return I; 323| 0|} 324| | 325| 0|reverse_iterator &reverse_iterator::operator++() { 326| 0| // If we're at the end and the previous char was a '/', return '.' unless 327| 0| // we are the root path. 328| 0| size_t root_dir_pos = root_dir_start(Path); 329| 0| if (Position == Path.size() && 330| 0| Path.size() > root_dir_pos + 1 && 331| 0| is_separator(Path[Position - 1])) { 332| 0| --Position; 333| 0| Component = "."; 334| 0| return *this; 335| 0| } 336| 0| 337| 0| // Skip separators unless it's the root directory. 338| 0| size_t end_pos = Position; 339| 0| 340| 0| while(end_pos > 0 && 341| 0| (end_pos - 1) != root_dir_pos && 342| 0| is_separator(Path[end_pos - 1])) 343| 0| --end_pos; 344| 0| 345| 0| // Find next separator. 346| 0| size_t start_pos = filename_pos(Path.substr(0, end_pos)); 347| 0| Component = Path.slice(start_pos, end_pos); 348| 0| Position = start_pos; 349| 0| return *this; 350| 0|} 351| | 352| 0|bool reverse_iterator::operator==(const reverse_iterator &RHS) const { 353| 0| return Path.begin() == RHS.Path.begin() && Component == RHS.Component && 354| 0| Position == RHS.Position; 355| 0|} 356| | 357| 0|StringRef root_path(StringRef path) { 358| 0| const_iterator b = begin(path), 359| 0| pos = b, 360| 0| e = end(path); 361| 0| if (b != e) { 362| 0| bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 363| 0| bool has_drive = 364| |#ifdef LLVM_ON_WIN32 365| | b->endswith(":"); 366| |#else 367| | false; 368| 0|#endif 369| 0| 370| 0| if (has_net || has_drive) { 371| 0| if ((++pos != e) && is_separator((*pos)[0])) { 372| 0| // {C:/,//net/}, so get the first two components. 373| 0| return path.substr(0, b->size() + pos->size()); 374| 0| } else { 375| 0| // just {C:,//net}, return the first component. 376| 0| return *b; 377| 0| } 378| 0| } 379| 0| 380| 0| // POSIX style root directory. 381| 0| if (is_separator((*b)[0])) { 382| 0| return *b; 383| 0| } 384| 0| } 385| 0| 386| 0| return StringRef(); 387| 0|} 388| | 389| 0|StringRef root_name(StringRef path) { 390| 0| const_iterator b = begin(path), 391| 0| e = end(path); 392| 0| if (b != e) { 393| 0| bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 394| 0| bool has_drive = 395| |#ifdef LLVM_ON_WIN32 396| | b->endswith(":"); 397| |#else 398| | false; 399| 0|#endif 400| 0| 401| 0| if (has_net || has_drive) { 402| 0| // just {C:,//net}, return the first component. 403| 0| return *b; 404| 0| } 405| 0| } 406| 0| 407| 0| // No path or no name. 408| 0| return StringRef(); 409| 0|} 410| | 411| 0|StringRef root_directory(StringRef path) { 412| 0| const_iterator b = begin(path), 413| 0| pos = b, 414| 0| e = end(path); 415| 0| if (b != e) { 416| 0| bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 417| 0| bool has_drive = 418| |#ifdef LLVM_ON_WIN32 419| | b->endswith(":"); 420| |#else 421| | false; 422| 0|#endif 423| 0| 424| 0| if ((has_net || has_drive) && 425| 0| // {C:,//net}, skip to the next component. 426| 0| (++pos != e) && is_separator((*pos)[0])) { 427| 0| return *pos; 428| 0| } 429| 0| 430| 0| // POSIX style root directory. 431| 0| if (!has_net && is_separator((*b)[0])) { 432| 0| return *b; 433| 0| } 434| 0| } 435| 0| 436| 0| // No path or no root. 437| 0| return StringRef(); 438| 0|} 439| | 440| 0|StringRef relative_path(StringRef path) { 441| 0| StringRef root = root_path(path); 442| 0| return path.substr(root.size()); 443| 0|} 444| | 445| |void append(SmallVectorImpl &path, const Twine &a, 446| | const Twine &b, 447| | const Twine &c, 448| 0| const Twine &d) { 449| 0| SmallString<32> a_storage; 450| 0| SmallString<32> b_storage; 451| 0| SmallString<32> c_storage; 452| 0| SmallString<32> d_storage; 453| 0| 454| 0| SmallVector components; 455| 0| if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage)); 456| 0| if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage)); 457| 0| if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); 458| 0| if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); 459| 0| 460| 0| for (SmallVectorImpl::const_iterator i = components.begin(), 461| 0| e = components.end(); 462| 0| i != e; ++i) { 463| 0| bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); 464| 0| bool component_has_sep = !i->empty() && is_separator((*i)[0]); 465| 0| bool is_root_name = has_root_name(*i); 466| 0| 467| 0| if (path_has_sep) { 468| 0| // Strip separators from beginning of component. 469| 0| size_t loc = i->find_first_not_of(separators); 470| 0| StringRef c = i->substr(loc); 471| 0| 472| 0| // Append it. 473| 0| path.append(c.begin(), c.end()); 474| 0| continue; 475| 0| } 476| 0| 477| 0| if (!component_has_sep && !(path.empty() || is_root_name)) { 478| 0| // Add a separator. 479| 0| path.push_back(preferred_separator); 480| 0| } 481| 0| 482| 0| path.append(i->begin(), i->end()); 483| 0| } 484| 0|} 485| | 486| |void append(SmallVectorImpl &path, 487| 0| const_iterator begin, const_iterator end) { 488| 0| for (; begin != end; ++begin) 489| 0| path::append(path, *begin); 490| 0|} 491| | 492| 0|StringRef parent_path(StringRef path) { 493| 0| size_t end_pos = parent_path_end(path); 494| 0| if (end_pos == StringRef::npos) 495| 0| return StringRef(); 496| 0| else 497| 0| return path.substr(0, end_pos); 498| 0|} 499| | 500| 0|void remove_filename(SmallVectorImpl &path) { 501| 0| size_t end_pos = parent_path_end(StringRef(path.begin(), path.size())); 502| 0| if (end_pos != StringRef::npos) 503| 0| path.set_size(end_pos); 504| 0|} 505| | 506| 0|void replace_extension(SmallVectorImpl &path, const Twine &extension) { 507| 0| StringRef p(path.begin(), path.size()); 508| 0| SmallString<32> ext_storage; 509| 0| StringRef ext = extension.toStringRef(ext_storage); 510| 0| 511| 0| // Erase existing extension. 512| 0| size_t pos = p.find_last_of('.'); 513| 0| if (pos != StringRef::npos && pos >= filename_pos(p)) 514| 0| path.set_size(pos); 515| 0| 516| 0| // Append '.' if needed. 517| 0| if (ext.size() > 0 && ext[0] != '.') 518| 0| path.push_back('.'); 519| 0| 520| 0| // Append extension. 521| 0| path.append(ext.begin(), ext.end()); 522| 0|} 523| | 524| 0|void native(const Twine &path, SmallVectorImpl &result) { 525| 0| assert((!path.isSingleStringRef() || 526| 0| path.getSingleStringRef().data() != result.data()) && 527| 0| "path and result are not allowed to overlap!"); 528| 0| // Clear result. 529| 0| result.clear(); 530| 0| path.toVector(result); 531| 0| native(result); 532| 0|} 533| | 534| 0|void native(SmallVectorImpl &Path) { 535| |#ifdef LLVM_ON_WIN32 536| | std::replace(Path.begin(), Path.end(), '/', '\\'); 537| |#else 538| 0| for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { 539| 0| if (*PI == '\\') { 540| 0| auto PN = PI + 1; 541| 0| if (PN < PE && *PN == '\\') 542| 0| ++PI; // increment once, the for loop will move over the escaped slash 543| 0| else 544| 0| *PI = '/'; 545| 0| } 546| 0| } 547| 0|#endif 548| 0|} 549| | 550| 0|StringRef filename(StringRef path) { 551| 0| return *rbegin(path); 552| 0|} 553| | 554| 0|StringRef stem(StringRef path) { 555| 0| StringRef fname = filename(path); 556| 0| size_t pos = fname.find_last_of('.'); 557| 0| if (pos == StringRef::npos) 558| 0| return fname; 559| 0| else 560| 0| if ((fname.size() == 1 && fname == ".") || 561| 0| (fname.size() == 2 && fname == "..")) 562| 0| return fname; 563| 0| else 564| 0| return fname.substr(0, pos); 565| 0|} 566| | 567| 0|StringRef extension(StringRef path) { 568| 0| StringRef fname = filename(path); 569| 0| size_t pos = fname.find_last_of('.'); 570| 0| if (pos == StringRef::npos) 571| 0| return StringRef(); 572| 0| else 573| 0| if ((fname.size() == 1 && fname == ".") || 574| 0| (fname.size() == 2 && fname == "..")) 575| 0| return StringRef(); 576| 0| else 577| 0| return fname.substr(pos); 578| 0|} 579| | 580| 0|bool is_separator(char value) { 581| 0| switch(value) { 582| |#ifdef LLVM_ON_WIN32 583| | case '\\': // fall through 584| |#endif 585| 0| case '/': return true; 586| 0| default: return false; 587| 0| } 588| 0|} 589| | 590| |static const char preferred_separator_string[] = { preferred_separator, '\0' }; 591| | 592| 0|StringRef get_separator() { 593| 0| return preferred_separator_string; 594| 0|} 595| | 596| 0|bool has_root_name(const Twine &path) { 597| 0| SmallString<128> path_storage; 598| 0| StringRef p = path.toStringRef(path_storage); 599| 0| 600| 0| return !root_name(p).empty(); 601| 0|} 602| | 603| 0|bool has_root_directory(const Twine &path) { 604| 0| SmallString<128> path_storage; 605| 0| StringRef p = path.toStringRef(path_storage); 606| 0| 607| 0| return !root_directory(p).empty(); 608| 0|} 609| | 610| 0|bool has_root_path(const Twine &path) { 611| 0| SmallString<128> path_storage; 612| 0| StringRef p = path.toStringRef(path_storage); 613| 0| 614| 0| return !root_path(p).empty(); 615| 0|} 616| | 617| 0|bool has_relative_path(const Twine &path) { 618| 0| SmallString<128> path_storage; 619| 0| StringRef p = path.toStringRef(path_storage); 620| 0| 621| 0| return !relative_path(p).empty(); 622| 0|} 623| | 624| 0|bool has_filename(const Twine &path) { 625| 0| SmallString<128> path_storage; 626| 0| StringRef p = path.toStringRef(path_storage); 627| 0| 628| 0| return !filename(p).empty(); 629| 0|} 630| | 631| 0|bool has_parent_path(const Twine &path) { 632| 0| SmallString<128> path_storage; 633| 0| StringRef p = path.toStringRef(path_storage); 634| 0| 635| 0| return !parent_path(p).empty(); 636| 0|} 637| | 638| 0|bool has_stem(const Twine &path) { 639| 0| SmallString<128> path_storage; 640| 0| StringRef p = path.toStringRef(path_storage); 641| 0| 642| 0| return !stem(p).empty(); 643| 0|} 644| | 645| 0|bool has_extension(const Twine &path) { 646| 0| SmallString<128> path_storage; 647| 0| StringRef p = path.toStringRef(path_storage); 648| 0| 649| 0| return !extension(p).empty(); 650| 0|} 651| | 652| 0|bool is_absolute(const Twine &path) { 653| 0| SmallString<128> path_storage; 654| 0| StringRef p = path.toStringRef(path_storage); 655| 0| 656| 0| bool rootDir = has_root_directory(p), 657| |#ifdef LLVM_ON_WIN32 658| | rootName = has_root_name(p); 659| |#else 660| | rootName = true; 661| 0|#endif 662| 0| 663| 0| return rootDir && rootName; 664| 0|} 665| | 666| 0|bool is_relative(const Twine &path) { 667| 0| return !is_absolute(path); 668| 0|} 669| | 670| |} // end namespace path 671| | 672| |namespace fs { 673| | 674| 0|std::error_code getUniqueID(const Twine Path, UniqueID &Result) { 675| 0| file_status Status; 676| 0| std::error_code EC = status(Path, Status); 677| 0| if (EC) 678| 0| return EC; 679| 0| Result = Status.getUniqueID(); 680| 0| return std::error_code(); 681| 0|} 682| | 683| |std::error_code createUniqueFile(const Twine &Model, int &ResultFd, 684| | SmallVectorImpl &ResultPath, 685| 0| unsigned Mode) { 686| 0| return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); 687| 0|} 688| | 689| |std::error_code createUniqueFile(const Twine &Model, 690| 0| SmallVectorImpl &ResultPath) { 691| 0| int Dummy; 692| 0| return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name); 693| 0|} 694| | 695| |static std::error_code 696| |createTemporaryFile(const Twine &Model, int &ResultFD, 697| 0| llvm::SmallVectorImpl &ResultPath, FSEntity Type) { 698| 0| SmallString<128> Storage; 699| 0| StringRef P = Model.toNullTerminatedStringRef(Storage); 700| 0| assert(P.find_first_of(separators) == StringRef::npos && 701| 0| "Model must be a simple filename."); 702| 0| // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. 703| 0| return createUniqueEntity(P.begin(), ResultFD, ResultPath, 704| 0| true, owner_read | owner_write, Type); 705| 0|} 706| | 707| |static std::error_code 708| |createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, 709| 0| llvm::SmallVectorImpl &ResultPath, FSEntity Type) { 710| 0| const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; 711| 0| return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, 712| 0| Type); 713| 0|} 714| | 715| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 716| | int &ResultFD, 717| 0| SmallVectorImpl &ResultPath) { 718| 0| return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File); 719| 0|} 720| | 721| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 722| 0| SmallVectorImpl &ResultPath) { 723| 0| int Dummy; 724| 0| return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name); 725| 0|} 726| | 727| | 728| |// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly 729| |// for consistency. We should try using mkdtemp. 730| |std::error_code createUniqueDirectory(const Twine &Prefix, 731| 0| SmallVectorImpl &ResultPath) { 732| 0| int Dummy; 733| 0| return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, 734| 0| true, 0, FS_Dir); 735| 0|} 736| | 737| 0|std::error_code make_absolute(SmallVectorImpl &path) { 738| 0| StringRef p(path.data(), path.size()); 739| 0| 740| 0| bool rootDirectory = path::has_root_directory(p), 741| |#ifdef LLVM_ON_WIN32 742| | rootName = path::has_root_name(p); 743| |#else 744| | rootName = true; 745| 0|#endif 746| 0| 747| 0| // Already absolute. 748| 0| if (rootName && rootDirectory) 749| 0| return std::error_code(); 750| 0| 751| 0| // All of the following conditions will need the current directory. 752| 0| SmallString<128> current_dir; 753| 0| if (std::error_code ec = current_path(current_dir)) 754| 0| return ec; 755| 0| 756| 0| // Relative path. Prepend the current directory. 757| 0| if (!rootName && !rootDirectory) { 758| 0| // Append path to the current directory. 759| 0| path::append(current_dir, p); 760| 0| // Set path to the result. 761| 0| path.swap(current_dir); 762| 0| return std::error_code(); 763| 0| } 764| 0| 765| 0| if (!rootName && rootDirectory) { 766| 0| StringRef cdrn = path::root_name(current_dir); 767| 0| SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); 768| 0| path::append(curDirRootName, p); 769| 0| // Set path to the result. 770| 0| path.swap(curDirRootName); 771| 0| return std::error_code(); 772| 0| } 773| 0| 774| 0| if (rootName && !rootDirectory) { 775| 0| StringRef pRootName = path::root_name(p); 776| 0| StringRef bRootDirectory = path::root_directory(current_dir); 777| 0| StringRef bRelativePath = path::relative_path(current_dir); 778| 0| StringRef pRelativePath = path::relative_path(p); 779| 0| 780| 0| SmallString<128> res; 781| 0| path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); 782| 0| path.swap(res); 783| 0| return std::error_code(); 784| 0| } 785| 0| 786| 0| llvm_unreachable("All rootName and rootDirectory combinations should have " 787| 0| "occurred above!"); 788| 0|} 789| | 790| 0|std::error_code create_directories(const Twine &Path, bool IgnoreExisting) { 791| 0| SmallString<128> PathStorage; 792| 0| StringRef P = Path.toStringRef(PathStorage); 793| 0| 794| 0| // Be optimistic and try to create the directory 795| 0| std::error_code EC = create_directory(P, IgnoreExisting); 796| 0| // If we succeeded, or had any error other than the parent not existing, just 797| 0| // return it. 798| 0| if (EC != errc::no_such_file_or_directory) 799| 0| return EC; 800| 0| 801| 0| // We failed because of a no_such_file_or_directory, try to create the 802| 0| // parent. 803| 0| StringRef Parent = path::parent_path(P); 804| 0| if (Parent.empty()) 805| 0| return EC; 806| 0| 807| 0| if ((EC = create_directories(Parent))) 808| 0| return EC; 809| 0| 810| 0| return create_directory(P, IgnoreExisting); 811| 0|} 812| | 813| 0|std::error_code copy_file(const Twine &From, const Twine &To) { 814| 0| int ReadFD, WriteFD; 815| 0| if (std::error_code EC = openFileForRead(From, ReadFD)) 816| 0| return EC; 817| 0| if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) { 818| 0| close(ReadFD); 819| 0| return EC; 820| 0| } 821| 0| 822| 0| const size_t BufSize = 4096; 823| 0| char *Buf = new char[BufSize]; 824| 0| int BytesRead = 0, BytesWritten = 0; 825| 0| for (;;) { 826| 0| BytesRead = read(ReadFD, Buf, BufSize); 827| 0| if (BytesRead <= 0) 828| 0| break; 829| 0| while (BytesRead) { 830| 0| BytesWritten = write(WriteFD, Buf, BytesRead); 831| 0| if (BytesWritten < 0) 832| 0| break; 833| 0| BytesRead -= BytesWritten; 834| 0| } 835| 0| if (BytesWritten < 0) 836| 0| break; 837| 0| } 838| 0| close(ReadFD); 839| 0| close(WriteFD); 840| 0| delete[] Buf; 841| 0| 842| 0| if (BytesRead < 0 || BytesWritten < 0) 843| 0| return std::error_code(errno, std::generic_category()); 844| 0| return std::error_code(); 845| 0|} 846| | 847| 0|bool exists(file_status status) { 848| 0| return status_known(status) && status.type() != file_type::file_not_found; 849| 0|} 850| | 851| 0|bool status_known(file_status s) { 852| 0| return s.type() != file_type::status_error; 853| 0|} 854| | 855| 0|bool is_directory(file_status status) { 856| 0| return status.type() == file_type::directory_file; 857| 0|} 858| | 859| 0|std::error_code is_directory(const Twine &path, bool &result) { 860| 0| file_status st; 861| 0| if (std::error_code ec = status(path, st)) 862| 0| return ec; 863| 0| result = is_directory(st); 864| 0| return std::error_code(); 865| 0|} 866| | 867| 0|bool is_regular_file(file_status status) { 868| 0| return status.type() == file_type::regular_file; 869| 0|} 870| | 871| 0|std::error_code is_regular_file(const Twine &path, bool &result) { 872| 0| file_status st; 873| 0| if (std::error_code ec = status(path, st)) 874| 0| return ec; 875| 0| result = is_regular_file(st); 876| 0| return std::error_code(); 877| 0|} 878| | 879| 0|bool is_other(file_status status) { 880| 0| return exists(status) && 881| 0| !is_regular_file(status) && 882| 0| !is_directory(status); 883| 0|} 884| | 885| 0|std::error_code is_other(const Twine &Path, bool &Result) { 886| 0| file_status FileStatus; 887| 0| if (std::error_code EC = status(Path, FileStatus)) 888| 0| return EC; 889| 0| Result = is_other(FileStatus); 890| 0| return std::error_code(); 891| 0|} 892| | 893| 0|void directory_entry::replace_filename(const Twine &filename, file_status st) { 894| 0| SmallString<128> path(Path.begin(), Path.end()); 895| 0| path::remove_filename(path); 896| 0| path::append(path, filename); 897| 0| Path = path.str(); 898| 0| Status = st; 899| 0|} 900| | 901| |/// @brief Identify the magic in magic. 902| 0|file_magic identify_magic(StringRef Magic) { 903| 0| if (Magic.size() < 4) 904| 0| return file_magic::unknown; 905| 0| switch ((unsigned char)Magic[0]) { 906| 0| case 0x00: { 907| 0| // COFF bigobj or short import library file 908| 0| if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && 909| 0| Magic[3] == (char)0xff) { 910| 0| size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic); 911| 0| if (Magic.size() < MinSize) 912| 0| return file_magic::coff_import_library; 913| 0| 914| 0| int BigObjVersion = read16le( 915| 0| Magic.data() + offsetof(COFF::BigObjHeader, Version)); 916| 0| if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion) 917| 0| return file_magic::coff_import_library; 918| 0| 919| 0| const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID); 920| 0| if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0) 921| 0| return file_magic::coff_import_library; 922| 0| return file_magic::coff_object; 923| 0| } 924| 0| // Windows resource file 925| 0| const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' }; 926| 0| if (Magic.size() >= sizeof(Expected) && 927| 0| memcmp(Magic.data(), Expected, sizeof(Expected)) == 0) 928| 0| return file_magic::windows_resource; 929| 0| // 0x0000 = COFF unknown machine type 930| 0| if (Magic[1] == 0) 931| 0| return file_magic::coff_object; 932| 0| break; 933| 0| } 934| 0| case 0xDE: // 0x0B17C0DE = BC wraper 935| 0| if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 && 936| 0| Magic[3] == (char)0x0B) 937| 0| return file_magic::bitcode; 938| 0| break; 939| 0| case 'B': 940| 0| if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE) 941| 0| return file_magic::bitcode; 942| 0| break; 943| 0| case '!': 944| 0| if (Magic.size() >= 8) 945| 0| if (memcmp(Magic.data(),"!\n",8) == 0) 946| 0| return file_magic::archive; 947| 0| break; 948| 0| 949| 0| case '\177': 950| 0| if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' && 951| 0| Magic[3] == 'F') { 952| 0| bool Data2MSB = Magic[5] == 2; 953| 0| unsigned high = Data2MSB ? 16 : 17; 954| 0| unsigned low = Data2MSB ? 17 : 16; 955| 0| if (Magic[high] == 0) 956| 0| switch (Magic[low]) { 957| 0| default: return file_magic::elf; 958| 0| case 1: return file_magic::elf_relocatable; 959| 0| case 2: return file_magic::elf_executable; 960| 0| case 3: return file_magic::elf_shared_object; 961| 0| case 4: return file_magic::elf_core; 962| 0| } 963| 0| else 964| 0| // It's still some type of ELF file. 965| 0| return file_magic::elf; 966| 0| } 967| 0| break; 968| 0| 969| 0| case 0xCA: 970| 0| if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) && 971| 0| Magic[3] == char(0xBE)) { 972| 0| // This is complicated by an overlap with Java class files. 973| 0| // See the Mach-O section in /usr/share/file/magic for details. 974| 0| if (Magic.size() >= 8 && Magic[7] < 43) 975| 0| return file_magic::macho_universal_binary; 976| 0| } 977| 0| break; 978| 0| 979| 0| // The two magic numbers for mach-o are: 980| 0| // 0xfeedface - 32-bit mach-o 981| 0| // 0xfeedfacf - 64-bit mach-o 982| 0| case 0xFE: 983| 0| case 0xCE: 984| 0| case 0xCF: { 985| 0| uint16_t type = 0; 986| 0| if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) && 987| 0| Magic[2] == char(0xFA) && 988| 0| (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) { 989| 0| /* Native endian */ 990| 0| if (Magic.size() >= 16) type = Magic[14] << 8 | Magic[15]; 991| 0| } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) && 992| 0| Magic[1] == char(0xFA) && Magic[2] == char(0xED) && 993| 0| Magic[3] == char(0xFE)) { 994| 0| /* Reverse endian */ 995| 0| if (Magic.size() >= 14) type = Magic[13] << 8 | Magic[12]; 996| 0| } 997| 0| switch (type) { 998| 0| default: break; 999| 0| case 1: return file_magic::macho_object; 1000| 0| case 2: return file_magic::macho_executable; 1001| 0| case 3: return file_magic::macho_fixed_virtual_memory_shared_lib; 1002| 0| case 4: return file_magic::macho_core; 1003| 0| case 5: return file_magic::macho_preload_executable; 1004| 0| case 6: return file_magic::macho_dynamically_linked_shared_lib; 1005| 0| case 7: return file_magic::macho_dynamic_linker; 1006| 0| case 8: return file_magic::macho_bundle; 1007| 0| case 9: return file_magic::macho_dynamically_linked_shared_lib_stub; 1008| 0| case 10: return file_magic::macho_dsym_companion; 1009| 0| case 11: return file_magic::macho_kext_bundle; 1010| 0| } 1011| 0| break; 1012| 0| } 1013| 0| case 0xF0: // PowerPC Windows 1014| 0| case 0x83: // Alpha 32-bit 1015| 0| case 0x84: // Alpha 64-bit 1016| 0| case 0x66: // MPS R4000 Windows 1017| 0| case 0x50: // mc68K 1018| 0| case 0x4c: // 80386 Windows 1019| 0| case 0xc4: // ARMNT Windows 1020| 0| if (Magic[1] == 0x01) 1021| 0| return file_magic::coff_object; 1022| 0| [[clang::fallthrough]]; 1023| 0| 1024| 0| case 0x90: // PA-RISC Windows 1025| 0| case 0x68: // mc68K Windows 1026| 0| if (Magic[1] == 0x02) 1027| 0| return file_magic::coff_object; 1028| 0| break; 1029| 0| 1030| 0| case 'M': // Possible MS-DOS stub on Windows PE file 1031| 0| if (Magic[1] == 'Z') { 1032| 0| uint32_t off = read32le(Magic.data() + 0x3c); 1033| 0| // PE/COFF file, either EXE or DLL. 1034| 0| if (off < Magic.size() && 1035| 0| memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0) 1036| 0| return file_magic::pecoff_executable; 1037| 0| } 1038| 0| break; 1039| 0| 1040| 0| case 0x64: // x86-64 Windows. 1041| 0| if (Magic[1] == char(0x86)) 1042| 0| return file_magic::coff_object; 1043| 0| break; 1044| 0| 1045| 0| default: 1046| 0| break; 1047| 0| } 1048| 0| return file_magic::unknown; 1049| 0|} 1050| | 1051| 0|std::error_code identify_magic(const Twine &Path, file_magic &Result) { 1052| 0| int FD; 1053| 0| if (std::error_code EC = openFileForRead(Path, FD)) 1054| 0| return EC; 1055| 0| 1056| 0| char Buffer[32]; 1057| 0| int Length = read(FD, Buffer, sizeof(Buffer)); 1058| 0| if (close(FD) != 0 || Length < 0) 1059| 0| return std::error_code(errno, std::generic_category()); 1060| 0| 1061| 0| Result = identify_magic(StringRef(Buffer, Length)); 1062| 0| return std::error_code(); 1063| 0|} 1064| | 1065| 0|std::error_code directory_entry::status(file_status &result) const { 1066| 0| return fs::status(Path, result); 1067| 0|} 1068| | 1069| |} // end namespace fs 1070| |} // end namespace sys 1071| |} // end namespace llvm 1072| | 1073| |// Include the truly platform-specific parts. 1074| |#if defined(LLVM_ON_UNIX) 1075| |#include "Unix/Path.inc" 1076| |#endif 1077| |#if defined(LLVM_ON_WIN32) 1078| |#include "Windows/Path.inc" 1079| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Process.cpp: 1| |//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the operating system Process concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/ADT/StringExtras.h" 15| |#include "llvm/Config/config.h" 16| |#include "llvm/Support/ErrorHandling.h" 17| |#include "llvm/Support/FileSystem.h" 18| |#include "llvm/Support/Process.h" 19| |#include "llvm/Support/Program.h" 20| | 21| |using namespace llvm; 22| |using namespace sys; 23| | 24| |//===----------------------------------------------------------------------===// 25| |//=== WARNING: Implementation here must contain only TRULY operating system 26| |//=== independent code. 27| |//===----------------------------------------------------------------------===// 28| | 29| |/// \brief A helper function to compute the elapsed wall-time since the program 30| |/// started. 31| |/// 32| |/// Note that this routine actually computes the elapsed wall time since the 33| |/// first time it was called. However, we arrange to have it called during the 34| |/// startup of the process to get approximately correct results. 35| 2|static TimeValue getElapsedWallTime() { 36| 2| static TimeValue &StartTime = *new TimeValue(TimeValue::now()); 37| 2| return TimeValue::now() - StartTime; 38| 2|} 39| | 40| |/// \brief A special global variable to ensure we call \c getElapsedWallTime 41| |/// during global initialization of the program. 42| |/// 43| |/// Note that this variable is never referenced elsewhere. Doing so could 44| |/// create race conditions during program startup or shutdown. 45| |static volatile TimeValue DummyTimeValue = getElapsedWallTime(); 46| | 47| |Optional Process::FindInEnvPath(const std::string& EnvName, 48| | const std::string& FileName) 49| 0|{ 50| 0| Optional FoundPath; 51| 0| Optional OptPath = Process::GetEnv(EnvName); 52| 0| if (!OptPath.hasValue()) 53| 0| return FoundPath; 54| 0| 55| 0| const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'}; 56| 0| SmallVector Dirs; 57| 0| SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr); 58| 0| 59| 0| for (const auto &Dir : Dirs) { 60| 0| if (Dir.empty()) 61| 0| continue; 62| 0| 63| 0| SmallString<128> FilePath(Dir); 64| 0| path::append(FilePath, FileName); 65| 0| if (fs::exists(Twine(FilePath))) { 66| 0| FoundPath = FilePath.str(); 67| 0| break; 68| 0| } 69| 0| } 70| 0| 71| 0| return FoundPath; 72| 0|} 73| | 74| | 75| |#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" 76| | 77| |#define ALLCOLORS(FGBG,BOLD) {\ 78| | COLOR(FGBG, "0", BOLD),\ 79| | COLOR(FGBG, "1", BOLD),\ 80| | COLOR(FGBG, "2", BOLD),\ 81| | COLOR(FGBG, "3", BOLD),\ 82| | COLOR(FGBG, "4", BOLD),\ 83| | COLOR(FGBG, "5", BOLD),\ 84| | COLOR(FGBG, "6", BOLD),\ 85| | COLOR(FGBG, "7", BOLD)\ 86| | } 87| | 88| |static const char colorcodes[2][2][8][10] = { 89| | { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, 90| | { ALLCOLORS("4",""), ALLCOLORS("4","1;") } 91| |}; 92| | 93| |// Include the platform-specific parts of this class. 94| |#ifdef LLVM_ON_UNIX 95| |#include "Unix/Process.inc" 96| |#endif 97| |#ifdef LLVM_ON_WIN32 98| |#include "Windows/Process.inc" 99| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Program.cpp: 1| |//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the operating system Program concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/Program.h" 15| |#include "llvm/Config/config.h" 16| |#include 17| |using namespace llvm; 18| |using namespace sys; 19| | 20| |//===----------------------------------------------------------------------===// 21| |//=== WARNING: Implementation here must contain only TRULY operating system 22| |//=== independent code. 23| |//===----------------------------------------------------------------------===// 24| | 25| |static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, 26| | const char **env, const StringRef **Redirects, 27| | unsigned memoryLimit, std::string *ErrMsg); 28| | 29| |int sys::ExecuteAndWait(StringRef Program, const char **args, const char **envp, 30| | const StringRef **redirects, unsigned secondsToWait, 31| | unsigned memoryLimit, std::string *ErrMsg, 32| 0| bool *ExecutionFailed) { 33| 0| ProcessInfo PI; 34| 0| if (Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) { 35| 0| if (ExecutionFailed) 36| 0| *ExecutionFailed = false; 37| 0| ProcessInfo Result = Wait( 38| 0| PI, secondsToWait, /*WaitUntilTerminates=*/secondsToWait == 0, ErrMsg); 39| 0| return Result.ReturnCode; 40| 0| } 41| 0| 42| 0| if (ExecutionFailed) 43| 0| *ExecutionFailed = true; 44| 0| 45| 0| return -1; 46| 0|} 47| | 48| |ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **args, 49| | const char **envp, const StringRef **redirects, 50| | unsigned memoryLimit, std::string *ErrMsg, 51| 0| bool *ExecutionFailed) { 52| 0| ProcessInfo PI; 53| 0| if (ExecutionFailed) 54| 0| *ExecutionFailed = false; 55| 0| if (!Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) 56| 0| if (ExecutionFailed) 57| 0| *ExecutionFailed = true; 58| 0| 59| 0| return PI; 60| 0|} 61| | 62| |// Include the platform-specific parts of this class. 63| |#ifdef LLVM_ON_UNIX 64| |#include "Unix/Program.inc" 65| |#endif 66| |#ifdef LLVM_ON_WIN32 67| |#include "Windows/Program.inc" 68| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/SmallPtrSet.cpp: 1| |//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the SmallPtrSet class. See SmallPtrSet.h for an 11| |// overview of the algorithm. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "llvm/ADT/SmallPtrSet.h" 16| |#include "llvm/ADT/DenseMapInfo.h" 17| |#include "llvm/Support/MathExtras.h" 18| |#include 19| |#include 20| | 21| |using namespace llvm; 22| | 23| 0|void SmallPtrSetImplBase::shrink_and_clear() { 24| 0| assert(!isSmall() && "Can't shrink a small set!"); 25| 0| free(CurArray); 26| 0| 27| 0| // Reduce the number of buckets. 28| 0| CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32; 29| 0| NumElements = NumTombstones = 0; 30| 0| 31| 0| // Install the new array. Clear all the buckets to empty. 32| 0| CurArray = (const void**)malloc(sizeof(void*) * CurArraySize); 33| 0| assert(CurArray && "Failed to allocate memory?"); 34| 0| memset(CurArray, -1, CurArraySize*sizeof(void*)); 35| 0|} 36| | 37| |std::pair 38| 0|SmallPtrSetImplBase::insert_imp(const void *Ptr) { 39| 0| if (isSmall()) { 40| 0| // Check to see if it is already in the set. 41| 0| for (const void **APtr = SmallArray, **E = SmallArray+NumElements; 42| 0| APtr != E; ++APtr) 43| 0| if (*APtr == Ptr) 44| 0| return std::make_pair(APtr, false); 45| 0| 46| 0| // Nope, there isn't. If we stay small, just 'pushback' now. 47| 0| if (NumElements < CurArraySize) { 48| 0| SmallArray[NumElements++] = Ptr; 49| 0| return std::make_pair(SmallArray + (NumElements - 1), true); 50| 0| } 51| 0| // Otherwise, hit the big set case, which will call grow. 52| 0| } 53| 0| 54| 0| if (LLVM_UNLIKELY(NumElements * 4 >= CurArraySize * 3)) { 55| 0| // If more than 3/4 of the array is full, grow. 56| 0| Grow(CurArraySize < 64 ? 128 : CurArraySize*2); 57| 0| } else if (LLVM_UNLIKELY(CurArraySize - (NumElements + NumTombstones) < 58| 0| CurArraySize / 8)) { 59| 0| // If fewer of 1/8 of the array is empty (meaning that many are filled with 60| 0| // tombstones), rehash. 61| 0| Grow(CurArraySize); 62| 0| } 63| 0| 64| 0| // Okay, we know we have space. Find a hash bucket. 65| 0| const void **Bucket = const_cast(FindBucketFor(Ptr)); 66| 0| if (*Bucket == Ptr) 67| 0| return std::make_pair(Bucket, false); // Already inserted, good. 68| 0| 69| 0| // Otherwise, insert it! 70| 0| if (*Bucket == getTombstoneMarker()) 71| 0| --NumTombstones; 72| 0| *Bucket = Ptr; 73| 0| ++NumElements; // Track density. 74| 0| return std::make_pair(Bucket, true); 75| 0|} 76| | 77| 0|bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { 78| 0| if (isSmall()) { 79| 0| // Check to see if it is in the set. 80| 0| for (const void **APtr = SmallArray, **E = SmallArray+NumElements; 81| 0| APtr != E; ++APtr) 82| 0| if (*APtr == Ptr) { 83| 0| // If it is in the set, replace this element. 84| 0| *APtr = E[-1]; 85| 0| E[-1] = getEmptyMarker(); 86| 0| --NumElements; 87| 0| return true; 88| 0| } 89| 0| 90| 0| return false; 91| 0| } 92| 0| 93| 0| // Okay, we know we have space. Find a hash bucket. 94| 0| void **Bucket = const_cast(FindBucketFor(Ptr)); 95| 0| if (*Bucket != Ptr) return false; // Not in the set? 96| 0| 97| 0| // Set this as a tombstone. 98| 0| *Bucket = getTombstoneMarker(); 99| 0| --NumElements; 100| 0| ++NumTombstones; 101| 0| return true; 102| 0|} 103| | 104| 0|const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const { 105| 0| unsigned Bucket = DenseMapInfo::getHashValue(Ptr) & (CurArraySize-1); 106| 0| unsigned ArraySize = CurArraySize; 107| 0| unsigned ProbeAmt = 1; 108| 0| const void *const *Array = CurArray; 109| 0| const void *const *Tombstone = nullptr; 110| 0| while (1) { 111| 0| // If we found an empty bucket, the pointer doesn't exist in the set. 112| 0| // Return a tombstone if we've seen one so far, or the empty bucket if 113| 0| // not. 114| 0| if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker())) 115| 0| return Tombstone ? Tombstone : Array+Bucket; 116| 0| 117| 0| // Found Ptr's bucket? 118| 0| if (LLVM_LIKELY(Array[Bucket] == Ptr)) 119| 0| return Array+Bucket; 120| 0| 121| 0| // If this is a tombstone, remember it. If Ptr ends up not in the set, we 122| 0| // prefer to return it than something that would require more probing. 123| 0| if (Array[Bucket] == getTombstoneMarker() && !Tombstone) 124| 0| Tombstone = Array+Bucket; // Remember the first tombstone found. 125| 0| 126| 0| // It's a hash collision or a tombstone. Reprobe. 127| 0| Bucket = (Bucket + ProbeAmt++) & (ArraySize-1); 128| 0| } 129| 0|} 130| | 131| |/// Grow - Allocate a larger backing store for the buckets and move it over. 132| |/// 133| 0|void SmallPtrSetImplBase::Grow(unsigned NewSize) { 134| 0| // Allocate at twice as many buckets, but at least 128. 135| 0| unsigned OldSize = CurArraySize; 136| 0| 137| 0| const void **OldBuckets = CurArray; 138| 0| bool WasSmall = isSmall(); 139| 0| 140| 0| // Install the new array. Clear all the buckets to empty. 141| 0| CurArray = (const void**)malloc(sizeof(void*) * NewSize); 142| 0| assert(CurArray && "Failed to allocate memory?"); 143| 0| CurArraySize = NewSize; 144| 0| memset(CurArray, -1, NewSize*sizeof(void*)); 145| 0| 146| 0| // Copy over all the elements. 147| 0| if (WasSmall) { 148| 0| // Small sets store their elements in order. 149| 0| for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements; 150| 0| BucketPtr != E; ++BucketPtr) { 151| 0| const void *Elt = *BucketPtr; 152| 0| *const_cast(FindBucketFor(Elt)) = const_cast(Elt); 153| 0| } 154| 0| } else { 155| 0| // Copy over all valid entries. 156| 0| for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize; 157| 0| BucketPtr != E; ++BucketPtr) { 158| 0| // Copy over the element if it is valid. 159| 0| const void *Elt = *BucketPtr; 160| 0| if (Elt != getTombstoneMarker() && Elt != getEmptyMarker()) 161| 0| *const_cast(FindBucketFor(Elt)) = const_cast(Elt); 162| 0| } 163| 0| 164| 0| free(OldBuckets); 165| 0| NumTombstones = 0; 166| 0| } 167| 0|} 168| | 169| |SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, 170| 0| const SmallPtrSetImplBase& that) { 171| 0| SmallArray = SmallStorage; 172| 0| 173| 0| // If we're becoming small, prepare to insert into our stack space 174| 0| if (that.isSmall()) { 175| 0| CurArray = SmallArray; 176| 0| // Otherwise, allocate new heap space (unless we were the same size) 177| 0| } else { 178| 0| CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize); 179| 0| assert(CurArray && "Failed to allocate memory?"); 180| 0| } 181| 0| 182| 0| // Copy over the new array size 183| 0| CurArraySize = that.CurArraySize; 184| 0| 185| 0| // Copy over the contents from the other set 186| 0| memcpy(CurArray, that.CurArray, sizeof(void*)*CurArraySize); 187| 0| 188| 0| NumElements = that.NumElements; 189| 0| NumTombstones = that.NumTombstones; 190| 0|} 191| | 192| |SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, 193| | unsigned SmallSize, 194| 0| SmallPtrSetImplBase &&that) { 195| 0| SmallArray = SmallStorage; 196| 0| 197| 0| // Copy over the basic members. 198| 0| CurArraySize = that.CurArraySize; 199| 0| NumElements = that.NumElements; 200| 0| NumTombstones = that.NumTombstones; 201| 0| 202| 0| // When small, just copy into our small buffer. 203| 0| if (that.isSmall()) { 204| 0| CurArray = SmallArray; 205| 0| memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize); 206| 0| } else { 207| 0| // Otherwise, we steal the large memory allocation and no copy is needed. 208| 0| CurArray = that.CurArray; 209| 0| that.CurArray = that.SmallArray; 210| 0| } 211| 0| 212| 0| // Make the "that" object small and empty. 213| 0| that.CurArraySize = SmallSize; 214| 0| assert(that.CurArray == that.SmallArray); 215| 0| that.NumElements = 0; 216| 0| that.NumTombstones = 0; 217| 0|} 218| | 219| |/// CopyFrom - implement operator= from a smallptrset that has the same pointer 220| |/// type, but may have a different small size. 221| 0|void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) { 222| 0| assert(&RHS != this && "Self-copy should be handled by the caller."); 223| 0| 224| 0| if (isSmall() && RHS.isSmall()) 225| 0| assert(CurArraySize == RHS.CurArraySize && 226| 0| "Cannot assign sets with different small sizes"); 227| 0| 228| 0| // If we're becoming small, prepare to insert into our stack space 229| 0| if (RHS.isSmall()) { 230| 0| if (!isSmall()) 231| 0| free(CurArray); 232| 0| CurArray = SmallArray; 233| 0| // Otherwise, allocate new heap space (unless we were the same size) 234| 0| } else if (CurArraySize != RHS.CurArraySize) { 235| 0| if (isSmall()) 236| 0| CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize); 237| 0| else { 238| 0| const void **T = (const void**)realloc(CurArray, 239| 0| sizeof(void*) * RHS.CurArraySize); 240| 0| if (!T) 241| 0| free(CurArray); 242| 0| CurArray = T; 243| 0| } 244| 0| assert(CurArray && "Failed to allocate memory?"); 245| 0| } 246| 0| 247| 0| // Copy over the new array size 248| 0| CurArraySize = RHS.CurArraySize; 249| 0| 250| 0| // Copy over the contents from the other set 251| 0| if (CurArray) 252| 0| memcpy(CurArray, RHS.CurArray, sizeof(void*)*CurArraySize); 253| 0| 254| 0| NumElements = RHS.NumElements; 255| 0| NumTombstones = RHS.NumTombstones; 256| 0|} 257| | 258| |void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize, 259| 0| SmallPtrSetImplBase &&RHS) { 260| 0| assert(&RHS != this && "Self-move should be handled by the caller."); 261| 0| 262| 0| if (!isSmall()) 263| 0| free(CurArray); 264| 0| 265| 0| if (RHS.isSmall()) { 266| 0| // Copy a small RHS rather than moving. 267| 0| CurArray = SmallArray; 268| 0| memcpy(CurArray, RHS.CurArray, sizeof(void*)*RHS.CurArraySize); 269| 0| } else { 270| 0| CurArray = RHS.CurArray; 271| 0| RHS.CurArray = RHS.SmallArray; 272| 0| } 273| 0| 274| 0| // Copy the rest of the trivial members. 275| 0| CurArraySize = RHS.CurArraySize; 276| 0| NumElements = RHS.NumElements; 277| 0| NumTombstones = RHS.NumTombstones; 278| 0| 279| 0| // Make the RHS small and empty. 280| 0| RHS.CurArraySize = SmallSize; 281| 0| assert(RHS.CurArray == RHS.SmallArray); 282| 0| RHS.NumElements = 0; 283| 0| RHS.NumTombstones = 0; 284| 0|} 285| | 286| 0|void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) { 287| 0| if (this == &RHS) return; 288| 0| 289| 0| // We can only avoid copying elements if neither set is small. 290| 0| if (!this->isSmall() && !RHS.isSmall()) { 291| 0| std::swap(this->CurArray, RHS.CurArray); 292| 0| std::swap(this->CurArraySize, RHS.CurArraySize); 293| 0| std::swap(this->NumElements, RHS.NumElements); 294| 0| std::swap(this->NumTombstones, RHS.NumTombstones); 295| 0| return; 296| 0| } 297| 0| 298| 0| // FIXME: From here on we assume that both sets have the same small size. 299| 0| 300| 0| // If only RHS is small, copy the small elements into LHS and move the pointer 301| 0| // from LHS to RHS. 302| 0| if (!this->isSmall() && RHS.isSmall()) { 303| 0| std::copy(RHS.SmallArray, RHS.SmallArray+RHS.CurArraySize, 304| 0| this->SmallArray); 305| 0| std::swap(this->NumElements, RHS.NumElements); 306| 0| std::swap(this->CurArraySize, RHS.CurArraySize); 307| 0| RHS.CurArray = this->CurArray; 308| 0| RHS.NumTombstones = this->NumTombstones; 309| 0| this->CurArray = this->SmallArray; 310| 0| this->NumTombstones = 0; 311| 0| return; 312| 0| } 313| 0| 314| 0| // If only LHS is small, copy the small elements into RHS and move the pointer 315| 0| // from RHS to LHS. 316| 0| if (this->isSmall() && !RHS.isSmall()) { 317| 0| std::copy(this->SmallArray, this->SmallArray+this->CurArraySize, 318| 0| RHS.SmallArray); 319| 0| std::swap(RHS.NumElements, this->NumElements); 320| 0| std::swap(RHS.CurArraySize, this->CurArraySize); 321| 0| this->CurArray = RHS.CurArray; 322| 0| this->NumTombstones = RHS.NumTombstones; 323| 0| RHS.CurArray = RHS.SmallArray; 324| 0| RHS.NumTombstones = 0; 325| 0| return; 326| 0| } 327| 0| 328| 0| // Both a small, just swap the small elements. 329| 0| assert(this->isSmall() && RHS.isSmall()); 330| 0| assert(this->CurArraySize == RHS.CurArraySize); 331| 0| std::swap_ranges(this->SmallArray, this->SmallArray+this->CurArraySize, 332| 0| RHS.SmallArray); 333| 0| std::swap(this->NumElements, RHS.NumElements); 334| 0|} 335| | 336| 0|SmallPtrSetImplBase::~SmallPtrSetImplBase() { 337| 0| if (!isSmall()) 338| 0| free(CurArray); 339| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/SmallVector.cpp: 1| |//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/ADT/SmallVector.h" 15| |using namespace llvm; 16| | 17| |/// grow_pod - This is an implementation of the grow() method which only works 18| |/// on POD-like datatypes and is out of line to reduce code duplication. 19| |void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSizeInBytes, 20| 0| size_t TSize) { 21| 0| size_t CurSizeBytes = size_in_bytes(); 22| 0| size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow. 23| 0| if (NewCapacityInBytes < MinSizeInBytes) 24| 0| NewCapacityInBytes = MinSizeInBytes; 25| 0| 26| 0| void *NewElts; 27| 0| if (BeginX == FirstEl) { 28| 0| NewElts = malloc(NewCapacityInBytes); 29| 0| 30| 0| // Copy the elements over. No need to run dtors on PODs. 31| 0| memcpy(NewElts, this->BeginX, CurSizeBytes); 32| 0| } else { 33| 0| // If this wasn't grown from the inline copy, grow the allocated space. 34| 0| NewElts = realloc(this->BeginX, NewCapacityInBytes); 35| 0| } 36| 0| 37| 0| this->EndX = (char*)NewElts+CurSizeBytes; 38| 0| this->BeginX = NewElts; 39| 0| this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; 40| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/SourceMgr.cpp: 1| |//===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the SourceMgr class. This class is used as a simple 11| |// substrate for diagnostics, #include handling, and other low level things for 12| |// simple parsers. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#include "llvm/Support/SourceMgr.h" 17| |#include "llvm/ADT/SmallString.h" 18| |#include "llvm/ADT/Twine.h" 19| |#include "llvm/Support/Locale.h" 20| |#include "llvm/Support/MemoryBuffer.h" 21| |#include "llvm/Support/Path.h" 22| |#include "llvm/Support/raw_ostream.h" 23| |#include 24| |using namespace llvm; 25| | 26| |static const size_t TabStop = 8; 27| | 28| |namespace { 29| | struct LineNoCacheTy { 30| | unsigned LastQueryBufferID; 31| | const char *LastQuery; 32| | unsigned LineNoOfQuery; 33| | }; 34| |} 35| | 36| 0|static LineNoCacheTy *getCache(void *Ptr) { 37| 0| return (LineNoCacheTy*)Ptr; 38| 0|} 39| | 40| | 41| 0|SourceMgr::~SourceMgr() { 42| 0| // Delete the line # cache if allocated. 43| 0| if (LineNoCacheTy *Cache = getCache(LineNoCache)) 44| 0| delete Cache; 45| 0|} 46| | 47| |unsigned SourceMgr::AddIncludeFile(const std::string &Filename, 48| | SMLoc IncludeLoc, 49| 0| std::string &IncludedFile) { 50| 0| IncludedFile = Filename; 51| 0| ErrorOr> NewBufOrErr = 52| 0| MemoryBuffer::getFile(IncludedFile); 53| 0| 54| 0| // If the file didn't exist directly, see if it's in an include path. 55| 0| for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr; 56| 0| ++i) { 57| 0| IncludedFile = 58| 0| IncludeDirectories[i] + sys::path::get_separator().data() + Filename; 59| 0| NewBufOrErr = MemoryBuffer::getFile(IncludedFile); 60| 0| } 61| 0| 62| 0| if (!NewBufOrErr) 63| 0| return 0; 64| 0| 65| 0| return AddNewSourceBuffer(std::move(*NewBufOrErr), IncludeLoc); 66| 0|} 67| | 68| 0|unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { 69| 0| for (unsigned i = 0, e = Buffers.size(); i != e; ++i) 70| 0| if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() && 71| 0| // Use <= here so that a pointer to the null at the end of the buffer 72| 0| // is included as part of the buffer. 73| 0| Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd()) 74| 0| return i + 1; 75| 0| return 0; 76| 0|} 77| | 78| |std::pair 79| 0|SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const { 80| 0| if (!BufferID) 81| 0| BufferID = FindBufferContainingLoc(Loc); 82| 0| assert(BufferID && "Invalid Location!"); 83| 0| 84| 0| const MemoryBuffer *Buff = getMemoryBuffer(BufferID); 85| 0| 86| 0| // Count the number of \n's between the start of the file and the specified 87| 0| // location. 88| 0| unsigned LineNo = 1; 89| 0| 90| 0| const char *BufStart = Buff->getBufferStart(); 91| 0| const char *Ptr = BufStart; 92| 0| 93| 0| // If we have a line number cache, and if the query is to a later point in the 94| 0| // same file, start searching from the last query location. This optimizes 95| 0| // for the case when multiple diagnostics come out of one file in order. 96| 0| if (LineNoCacheTy *Cache = getCache(LineNoCache)) 97| 0| if (Cache->LastQueryBufferID == BufferID && 98| 0| Cache->LastQuery <= Loc.getPointer()) { 99| 0| Ptr = Cache->LastQuery; 100| 0| LineNo = Cache->LineNoOfQuery; 101| 0| } 102| 0| 103| 0| // Scan for the location being queried, keeping track of the number of lines 104| 0| // we see. 105| 0| for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) 106| 0| if (*Ptr == '\n') ++LineNo; 107| 0| 108| 0| // Allocate the line number cache if it doesn't exist. 109| 0| if (!LineNoCache) 110| 0| LineNoCache = new LineNoCacheTy(); 111| 0| 112| 0| // Update the line # cache. 113| 0| LineNoCacheTy &Cache = *getCache(LineNoCache); 114| 0| Cache.LastQueryBufferID = BufferID; 115| 0| Cache.LastQuery = Ptr; 116| 0| Cache.LineNoOfQuery = LineNo; 117| 0| 118| 0| size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r"); 119| 0| if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0; 120| 0| return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs); 121| 0|} 122| | 123| 0|void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const { 124| 0| if (IncludeLoc == SMLoc()) return; // Top of stack. 125| 0| 126| 0| unsigned CurBuf = FindBufferContainingLoc(IncludeLoc); 127| 0| assert(CurBuf && "Invalid or unspecified location!"); 128| 0| 129| 0| PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); 130| 0| 131| 0| OS << "Included from " 132| 0| << getBufferInfo(CurBuf).Buffer->getBufferIdentifier() 133| 0| << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n"; 134| 0|} 135| | 136| | 137| |SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, 138| | const Twine &Msg, 139| | ArrayRef Ranges, 140| 0| ArrayRef FixIts) const { 141| 0| 142| 0| // First thing to do: find the current buffer containing the specified 143| 0| // location to pull out the source line. 144| 0| SmallVector, 4> ColRanges; 145| 0| std::pair LineAndCol; 146| 0| const char *BufferID = ""; 147| 0| std::string LineStr; 148| 0| 149| 0| if (Loc.isValid()) { 150| 0| unsigned CurBuf = FindBufferContainingLoc(Loc); 151| 0| assert(CurBuf && "Invalid or unspecified location!"); 152| 0| 153| 0| const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf); 154| 0| BufferID = CurMB->getBufferIdentifier(); 155| 0| 156| 0| // Scan backward to find the start of the line. 157| 0| const char *LineStart = Loc.getPointer(); 158| 0| const char *BufStart = CurMB->getBufferStart(); 159| 0| while (LineStart != BufStart && LineStart[-1] != '\n' && 160| 0| LineStart[-1] != '\r') 161| 0| --LineStart; 162| 0| 163| 0| // Get the end of the line. 164| 0| const char *LineEnd = Loc.getPointer(); 165| 0| const char *BufEnd = CurMB->getBufferEnd(); 166| 0| while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r') 167| 0| ++LineEnd; 168| 0| LineStr = std::string(LineStart, LineEnd); 169| 0| 170| 0| // Convert any ranges to column ranges that only intersect the line of the 171| 0| // location. 172| 0| for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { 173| 0| SMRange R = Ranges[i]; 174| 0| if (!R.isValid()) continue; 175| 0| 176| 0| // If the line doesn't contain any part of the range, then ignore it. 177| 0| if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart) 178| 0| continue; 179| 0| 180| 0| // Ignore pieces of the range that go onto other lines. 181| 0| if (R.Start.getPointer() < LineStart) 182| 0| R.Start = SMLoc::getFromPointer(LineStart); 183| 0| if (R.End.getPointer() > LineEnd) 184| 0| R.End = SMLoc::getFromPointer(LineEnd); 185| 0| 186| 0| // Translate from SMLoc ranges to column ranges. 187| 0| // FIXME: Handle multibyte characters. 188| 0| ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart, 189| 0| R.End.getPointer()-LineStart)); 190| 0| } 191| 0| 192| 0| LineAndCol = getLineAndColumn(Loc, CurBuf); 193| 0| } 194| 0| 195| 0| return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first, 196| 0| LineAndCol.second-1, Kind, Msg.str(), 197| 0| LineStr, ColRanges, FixIts); 198| 0|} 199| | 200| |void SourceMgr::PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, 201| 0| bool ShowColors) const { 202| 0| // Report the message with the diagnostic handler if present. 203| 0| if (DiagHandler) { 204| 0| DiagHandler(Diagnostic, DiagContext); 205| 0| return; 206| 0| } 207| 0| 208| 0| if (Diagnostic.getLoc().isValid()) { 209| 0| unsigned CurBuf = FindBufferContainingLoc(Diagnostic.getLoc()); 210| 0| assert(CurBuf && "Invalid or unspecified location!"); 211| 0| PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); 212| 0| } 213| 0| 214| 0| Diagnostic.print(nullptr, OS, ShowColors); 215| 0|} 216| | 217| |void SourceMgr::PrintMessage(raw_ostream &OS, SMLoc Loc, 218| | SourceMgr::DiagKind Kind, 219| | const Twine &Msg, ArrayRef Ranges, 220| 0| ArrayRef FixIts, bool ShowColors) const { 221| 0| PrintMessage(OS, GetMessage(Loc, Kind, Msg, Ranges, FixIts), ShowColors); 222| 0|} 223| | 224| |void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, 225| | const Twine &Msg, ArrayRef Ranges, 226| 0| ArrayRef FixIts, bool ShowColors) const { 227| 0| PrintMessage(llvm::errs(), Loc, Kind, Msg, Ranges, FixIts, ShowColors); 228| 0|} 229| | 230| |//===----------------------------------------------------------------------===// 231| |// SMDiagnostic Implementation 232| |//===----------------------------------------------------------------------===// 233| | 234| |SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 235| | int Line, int Col, SourceMgr::DiagKind Kind, 236| | StringRef Msg, StringRef LineStr, 237| | ArrayRef > Ranges, 238| | ArrayRef Hints) 239| | : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind), 240| | Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()), 241| 0| FixIts(Hints.begin(), Hints.end()) { 242| 0| std::sort(FixIts.begin(), FixIts.end()); 243| 0|} 244| | 245| |static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, 246| 0| ArrayRef FixIts, ArrayRef SourceLine){ 247| 0| if (FixIts.empty()) 248| 0| return; 249| 0| 250| 0| const char *LineStart = SourceLine.begin(); 251| 0| const char *LineEnd = SourceLine.end(); 252| 0| 253| 0| size_t PrevHintEndCol = 0; 254| 0| 255| 0| for (ArrayRef::iterator I = FixIts.begin(), E = FixIts.end(); 256| 0| I != E; ++I) { 257| 0| // If the fixit contains a newline or tab, ignore it. 258| 0| if (I->getText().find_first_of("\n\r\t") != StringRef::npos) 259| 0| continue; 260| 0| 261| 0| SMRange R = I->getRange(); 262| 0| 263| 0| // If the line doesn't contain any part of the range, then ignore it. 264| 0| if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart) 265| 0| continue; 266| 0| 267| 0| // Translate from SMLoc to column. 268| 0| // Ignore pieces of the range that go onto other lines. 269| 0| // FIXME: Handle multibyte characters in the source line. 270| 0| unsigned FirstCol; 271| 0| if (R.Start.getPointer() < LineStart) 272| 0| FirstCol = 0; 273| 0| else 274| 0| FirstCol = R.Start.getPointer() - LineStart; 275| 0| 276| 0| // If we inserted a long previous hint, push this one forwards, and add 277| 0| // an extra space to show that this is not part of the previous 278| 0| // completion. This is sort of the best we can do when two hints appear 279| 0| // to overlap. 280| 0| // 281| 0| // Note that if this hint is located immediately after the previous 282| 0| // hint, no space will be added, since the location is more important. 283| 0| unsigned HintCol = FirstCol; 284| 0| if (HintCol < PrevHintEndCol) 285| 0| HintCol = PrevHintEndCol + 1; 286| 0| 287| 0| // FIXME: This assertion is intended to catch unintended use of multibyte 288| 0| // characters in fixits. If we decide to do this, we'll have to track 289| 0| // separate byte widths for the source and fixit lines. 290| 0| assert((size_t)llvm::sys::locale::columnWidth(I->getText()) == 291| 0| I->getText().size()); 292| 0| 293| 0| // This relies on one byte per column in our fixit hints. 294| 0| unsigned LastColumnModified = HintCol + I->getText().size(); 295| 0| if (LastColumnModified > FixItLine.size()) 296| 0| FixItLine.resize(LastColumnModified, ' '); 297| 0| 298| 0| std::copy(I->getText().begin(), I->getText().end(), 299| 0| FixItLine.begin() + HintCol); 300| 0| 301| 0| PrevHintEndCol = LastColumnModified; 302| 0| 303| 0| // For replacements, mark the removal range with '~'. 304| 0| // FIXME: Handle multibyte characters in the source line. 305| 0| unsigned LastCol; 306| 0| if (R.End.getPointer() >= LineEnd) 307| 0| LastCol = LineEnd - LineStart; 308| 0| else 309| 0| LastCol = R.End.getPointer() - LineStart; 310| 0| 311| 0| std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~'); 312| 0| } 313| 0|} 314| | 315| 0|static void printSourceLine(raw_ostream &S, StringRef LineContents) { 316| 0| // Print out the source line one character at a time, so we can expand tabs. 317| 0| for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) { 318| 0| if (LineContents[i] != '\t') { 319| 0| S << LineContents[i]; 320| 0| ++OutCol; 321| 0| continue; 322| 0| } 323| 0| 324| 0| // If we have a tab, emit at least one space, then round up to 8 columns. 325| 0| do { 326| 0| S << ' '; 327| 0| ++OutCol; 328| 0| } while ((OutCol % TabStop) != 0); 329| 0| } 330| 0| S << '\n'; 331| 0|} 332| | 333| 0|static bool isNonASCII(char c) { 334| 0| return c & 0x80; 335| 0|} 336| | 337| |void SMDiagnostic::print(const char *ProgName, raw_ostream &S, 338| 0| bool ShowColors) const { 339| 0| // Display colors only if OS supports colors. 340| 0| ShowColors &= S.has_colors(); 341| 0| 342| 0| if (ShowColors) 343| 0| S.changeColor(raw_ostream::SAVEDCOLOR, true); 344| 0| 345| 0| if (ProgName && ProgName[0]) 346| 0| S << ProgName << ": "; 347| 0| 348| 0| if (!Filename.empty()) { 349| 0| if (Filename == "-") 350| 0| S << ""; 351| 0| else 352| 0| S << Filename; 353| 0| 354| 0| if (LineNo != -1) { 355| 0| S << ':' << LineNo; 356| 0| if (ColumnNo != -1) 357| 0| S << ':' << (ColumnNo+1); 358| 0| } 359| 0| S << ": "; 360| 0| } 361| 0| 362| 0| switch (Kind) { 363| 0| case SourceMgr::DK_Error: 364| 0| if (ShowColors) 365| 0| S.changeColor(raw_ostream::RED, true); 366| 0| S << "error: "; 367| 0| break; 368| 0| case SourceMgr::DK_Warning: 369| 0| if (ShowColors) 370| 0| S.changeColor(raw_ostream::MAGENTA, true); 371| 0| S << "warning: "; 372| 0| break; 373| 0| case SourceMgr::DK_Note: 374| 0| if (ShowColors) 375| 0| S.changeColor(raw_ostream::BLACK, true); 376| 0| S << "note: "; 377| 0| break; 378| 0| } 379| 0| 380| 0| if (ShowColors) { 381| 0| S.resetColor(); 382| 0| S.changeColor(raw_ostream::SAVEDCOLOR, true); 383| 0| } 384| 0| 385| 0| S << Message << '\n'; 386| 0| 387| 0| if (ShowColors) 388| 0| S.resetColor(); 389| 0| 390| 0| if (LineNo == -1 || ColumnNo == -1) 391| 0| return; 392| 0| 393| 0| // FIXME: If there are multibyte or multi-column characters in the source, all 394| 0| // our ranges will be wrong. To do this properly, we'll need a byte-to-column 395| 0| // map like Clang's TextDiagnostic. For now, we'll just handle tabs by 396| 0| // expanding them later, and bail out rather than show incorrect ranges and 397| 0| // misaligned fixits for any other odd characters. 398| 0| if (std::find_if(LineContents.begin(), LineContents.end(), isNonASCII) != 399| 0| LineContents.end()) { 400| 0| printSourceLine(S, LineContents); 401| 0| return; 402| 0| } 403| 0| size_t NumColumns = LineContents.size(); 404| 0| 405| 0| // Build the line with the caret and ranges. 406| 0| std::string CaretLine(NumColumns+1, ' '); 407| 0| 408| 0| // Expand any ranges. 409| 0| for (unsigned r = 0, e = Ranges.size(); r != e; ++r) { 410| 0| std::pair R = Ranges[r]; 411| 0| std::fill(&CaretLine[R.first], 412| 0| &CaretLine[std::min((size_t)R.second, CaretLine.size())], 413| 0| '~'); 414| 0| } 415| 0| 416| 0| // Add any fix-its. 417| 0| // FIXME: Find the beginning of the line properly for multibyte characters. 418| 0| std::string FixItInsertionLine; 419| 0| buildFixItLine(CaretLine, FixItInsertionLine, FixIts, 420| 0| makeArrayRef(Loc.getPointer() - ColumnNo, 421| 0| LineContents.size())); 422| 0| 423| 0| // Finally, plop on the caret. 424| 0| if (unsigned(ColumnNo) <= NumColumns) 425| 0| CaretLine[ColumnNo] = '^'; 426| 0| else 427| 0| CaretLine[NumColumns] = '^'; 428| 0| 429| 0| // ... and remove trailing whitespace so the output doesn't wrap for it. We 430| 0| // know that the line isn't completely empty because it has the caret in it at 431| 0| // least. 432| 0| CaretLine.erase(CaretLine.find_last_not_of(' ')+1); 433| 0| 434| 0| printSourceLine(S, LineContents); 435| 0| 436| 0| if (ShowColors) 437| 0| S.changeColor(raw_ostream::GREEN, true); 438| 0| 439| 0| // Print out the caret line, matching tabs in the source line. 440| 0| for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) { 441| 0| if (i >= LineContents.size() || LineContents[i] != '\t') { 442| 0| S << CaretLine[i]; 443| 0| ++OutCol; 444| 0| continue; 445| 0| } 446| 0| 447| 0| // Okay, we have a tab. Insert the appropriate number of characters. 448| 0| do { 449| 0| S << CaretLine[i]; 450| 0| ++OutCol; 451| 0| } while ((OutCol % TabStop) != 0); 452| 0| } 453| 0| S << '\n'; 454| 0| 455| 0| if (ShowColors) 456| 0| S.resetColor(); 457| 0| 458| 0| // Print out the replacement line, matching tabs in the source line. 459| 0| if (FixItInsertionLine.empty()) 460| 0| return; 461| 0| 462| 0| for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) { 463| 0| if (i >= LineContents.size() || LineContents[i] != '\t') { 464| 0| S << FixItInsertionLine[i]; 465| 0| ++OutCol; 466| 0| continue; 467| 0| } 468| 0| 469| 0| // Okay, we have a tab. Insert the appropriate number of characters. 470| 0| do { 471| 0| S << FixItInsertionLine[i]; 472| 0| // FIXME: This is trying not to break up replacements, but then to re-sync 473| 0| // with the tabs between replacements. This will fail, though, if two 474| 0| // fix-it replacements are exactly adjacent, or if a fix-it contains a 475| 0| // space. Really we should be precomputing column widths, which we'll 476| 0| // need anyway for multibyte chars. 477| 0| if (FixItInsertionLine[i] != ' ') 478| 0| ++i; 479| 0| ++OutCol; 480| 0| } while (((OutCol % TabStop) != 0) && i != e); 481| 0| } 482| 0| S << '\n'; 483| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/StringExtras.cpp: 1| |//===-- StringExtras.cpp - Implement the StringExtras header --------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the StringExtras.h header 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/ADT/SmallVector.h" 15| |#include "llvm/ADT/STLExtras.h" 16| |#include "llvm/ADT/StringExtras.h" 17| |using namespace llvm; 18| | 19| |/// StrInStrNoCase - Portable version of strcasestr. Locates the first 20| |/// occurrence of string 's1' in string 's2', ignoring case. Returns 21| |/// the offset of s2 in s1 or npos if s2 cannot be found. 22| 0|StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) { 23| 0| size_t N = s2.size(), M = s1.size(); 24| 0| if (N > M) 25| 0| return StringRef::npos; 26| 0| for (size_t i = 0, e = M - N + 1; i != e; ++i) 27| 0| if (s1.substr(i, N).equals_lower(s2)) 28| 0| return i; 29| 0| return StringRef::npos; 30| 0|} 31| | 32| |/// getToken - This function extracts one token from source, ignoring any 33| |/// leading characters that appear in the Delimiters string, and ending the 34| |/// token at any of the characters that appear in the Delimiters string. If 35| |/// there are no tokens in the source string, an empty string is returned. 36| |/// The function returns a pair containing the extracted token and the 37| |/// remaining tail string. 38| |std::pair llvm::getToken(StringRef Source, 39| 0| StringRef Delimiters) { 40| 0| // Figure out where the token starts. 41| 0| StringRef::size_type Start = Source.find_first_not_of(Delimiters); 42| 0| 43| 0| // Find the next occurrence of the delimiter. 44| 0| StringRef::size_type End = Source.find_first_of(Delimiters, Start); 45| 0| 46| 0| return std::make_pair(Source.slice(Start, End), Source.substr(End)); 47| 0|} 48| | 49| |/// SplitString - Split up the specified string according to the specified 50| |/// delimiters, appending the result fragments to the output list. 51| |void llvm::SplitString(StringRef Source, 52| | SmallVectorImpl &OutFragments, 53| 0| StringRef Delimiters) { 54| 0| std::pair S = getToken(Source, Delimiters); 55| 0| while (!S.first.empty()) { 56| 0| OutFragments.push_back(S.first); 57| 0| S = getToken(S.second, Delimiters); 58| 0| } 59| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/StringMap.cpp: 1| |//===--- StringMap.cpp - String Hash table map implementation -------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/ADT/StringMap.h" 15| |#include "llvm/ADT/StringExtras.h" 16| |#include "llvm/Support/Compiler.h" 17| |#include 18| |using namespace llvm; 19| | 20| 0|StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { 21| 0| ItemSize = itemSize; 22| 0| 23| 0| // If a size is specified, initialize the table with that many buckets. 24| 0| if (InitSize) { 25| 0| init(InitSize); 26| 0| return; 27| 0| } 28| 0| 29| 0| // Otherwise, initialize it with zero buckets to avoid the allocation. 30| 0| TheTable = nullptr; 31| 0| NumBuckets = 0; 32| 0| NumItems = 0; 33| 0| NumTombstones = 0; 34| 0|} 35| | 36| 0|void StringMapImpl::init(unsigned InitSize) { 37| 0| assert((InitSize & (InitSize-1)) == 0 && 38| 0| "Init Size must be a power of 2 or zero!"); 39| 0| NumBuckets = InitSize ? InitSize : 16; 40| 0| NumItems = 0; 41| 0| NumTombstones = 0; 42| 0| 43| 0| TheTable = (StringMapEntryBase **)calloc(NumBuckets+1, 44| 0| sizeof(StringMapEntryBase **) + 45| 0| sizeof(unsigned)); 46| 0| 47| 0| // Allocate one extra bucket, set it to look filled so the iterators stop at 48| 0| // end. 49| 0| TheTable[NumBuckets] = (StringMapEntryBase*)2; 50| 0|} 51| | 52| | 53| |/// LookupBucketFor - Look up the bucket that the specified string should end 54| |/// up in. If it already exists as a key in the map, the Item pointer for the 55| |/// specified bucket will be non-null. Otherwise, it will be null. In either 56| |/// case, the FullHashValue field of the bucket will be set to the hash value 57| |/// of the string. 58| 0|unsigned StringMapImpl::LookupBucketFor(StringRef Name) { 59| 0| unsigned HTSize = NumBuckets; 60| 0| if (HTSize == 0) { // Hash table unallocated so far? 61| 0| init(16); 62| 0| HTSize = NumBuckets; 63| 0| } 64| 0| unsigned FullHashValue = HashString(Name); 65| 0| unsigned BucketNo = FullHashValue & (HTSize-1); 66| 0| unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); 67| 0| 68| 0| unsigned ProbeAmt = 1; 69| 0| int FirstTombstone = -1; 70| 0| while (1) { 71| 0| StringMapEntryBase *BucketItem = TheTable[BucketNo]; 72| 0| // If we found an empty bucket, this key isn't in the table yet, return it. 73| 0| if (LLVM_LIKELY(!BucketItem)) { 74| 0| // If we found a tombstone, we want to reuse the tombstone instead of an 75| 0| // empty bucket. This reduces probing. 76| 0| if (FirstTombstone != -1) { 77| 0| HashTable[FirstTombstone] = FullHashValue; 78| 0| return FirstTombstone; 79| 0| } 80| 0| 81| 0| HashTable[BucketNo] = FullHashValue; 82| 0| return BucketNo; 83| 0| } 84| 0| 85| 0| if (BucketItem == getTombstoneVal()) { 86| 0| // Skip over tombstones. However, remember the first one we see. 87| 0| if (FirstTombstone == -1) FirstTombstone = BucketNo; 88| 0| } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { 89| 0| // If the full hash value matches, check deeply for a match. The common 90| 0| // case here is that we are only looking at the buckets (for item info 91| 0| // being non-null and for the full hash value) not at the items. This 92| 0| // is important for cache locality. 93| 0| 94| 0| // Do the comparison like this because Name isn't necessarily 95| 0| // null-terminated! 96| 0| char *ItemStr = (char*)BucketItem+ItemSize; 97| 0| if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) { 98| 0| // We found a match! 99| 0| return BucketNo; 100| 0| } 101| 0| } 102| 0| 103| 0| // Okay, we didn't find the item. Probe to the next bucket. 104| 0| BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); 105| 0| 106| 0| // Use quadratic probing, it has fewer clumping artifacts than linear 107| 0| // probing and has good cache behavior in the common case. 108| 0| ++ProbeAmt; 109| 0| } 110| 0|} 111| | 112| | 113| |/// FindKey - Look up the bucket that contains the specified key. If it exists 114| |/// in the map, return the bucket number of the key. Otherwise return -1. 115| |/// This does not modify the map. 116| 0|int StringMapImpl::FindKey(StringRef Key) const { 117| 0| unsigned HTSize = NumBuckets; 118| 0| if (HTSize == 0) return -1; // Really empty table? 119| 0| unsigned FullHashValue = HashString(Key); 120| 0| unsigned BucketNo = FullHashValue & (HTSize-1); 121| 0| unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); 122| 0| 123| 0| unsigned ProbeAmt = 1; 124| 0| while (1) { 125| 0| StringMapEntryBase *BucketItem = TheTable[BucketNo]; 126| 0| // If we found an empty bucket, this key isn't in the table yet, return. 127| 0| if (LLVM_LIKELY(!BucketItem)) 128| 0| return -1; 129| 0| 130| 0| if (BucketItem == getTombstoneVal()) { 131| 0| // Ignore tombstones. 132| 0| } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { 133| 0| // If the full hash value matches, check deeply for a match. The common 134| 0| // case here is that we are only looking at the buckets (for item info 135| 0| // being non-null and for the full hash value) not at the items. This 136| 0| // is important for cache locality. 137| 0| 138| 0| // Do the comparison like this because NameStart isn't necessarily 139| 0| // null-terminated! 140| 0| char *ItemStr = (char*)BucketItem+ItemSize; 141| 0| if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) { 142| 0| // We found a match! 143| 0| return BucketNo; 144| 0| } 145| 0| } 146| 0| 147| 0| // Okay, we didn't find the item. Probe to the next bucket. 148| 0| BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); 149| 0| 150| 0| // Use quadratic probing, it has fewer clumping artifacts than linear 151| 0| // probing and has good cache behavior in the common case. 152| 0| ++ProbeAmt; 153| 0| } 154| 0|} 155| | 156| |/// RemoveKey - Remove the specified StringMapEntry from the table, but do not 157| |/// delete it. This aborts if the value isn't in the table. 158| 0|void StringMapImpl::RemoveKey(StringMapEntryBase *V) { 159| 0| const char *VStr = (char*)V + ItemSize; 160| 0| StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength())); 161| 0| (void)V2; 162| 0| assert(V == V2 && "Didn't find key?"); 163| 0|} 164| | 165| |/// RemoveKey - Remove the StringMapEntry for the specified key from the 166| |/// table, returning it. If the key is not in the table, this returns null. 167| 0|StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { 168| 0| int Bucket = FindKey(Key); 169| 0| if (Bucket == -1) return nullptr; 170| 0| 171| 0| StringMapEntryBase *Result = TheTable[Bucket]; 172| 0| TheTable[Bucket] = getTombstoneVal(); 173| 0| --NumItems; 174| 0| ++NumTombstones; 175| 0| assert(NumItems + NumTombstones <= NumBuckets); 176| 0| 177| 0| return Result; 178| 0|} 179| | 180| | 181| | 182| |/// RehashTable - Grow the table, redistributing values into the buckets with 183| |/// the appropriate mod-of-hashtable-size. 184| 0|unsigned StringMapImpl::RehashTable(unsigned BucketNo) { 185| 0| unsigned NewSize; 186| 0| unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); 187| 0| 188| 0| // If the hash table is now more than 3/4 full, or if fewer than 1/8 of 189| 0| // the buckets are empty (meaning that many are filled with tombstones), 190| 0| // grow/rehash the table. 191| 0| if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) { 192| 0| NewSize = NumBuckets*2; 193| 0| } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <= 194| 0| NumBuckets / 8)) { 195| 0| NewSize = NumBuckets; 196| 0| } else { 197| 0| return BucketNo; 198| 0| } 199| 0| 200| 0| unsigned NewBucketNo = BucketNo; 201| 0| // Allocate one extra bucket which will always be non-empty. This allows the 202| 0| // iterators to stop at end. 203| 0| StringMapEntryBase **NewTableArray = 204| 0| (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) + 205| 0| sizeof(unsigned)); 206| 0| unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1); 207| 0| NewTableArray[NewSize] = (StringMapEntryBase*)2; 208| 0| 209| 0| // Rehash all the items into their new buckets. Luckily :) we already have 210| 0| // the hash values available, so we don't have to rehash any strings. 211| 0| for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 212| 0| StringMapEntryBase *Bucket = TheTable[I]; 213| 0| if (Bucket && Bucket != getTombstoneVal()) { 214| 0| // Fast case, bucket available. 215| 0| unsigned FullHash = HashTable[I]; 216| 0| unsigned NewBucket = FullHash & (NewSize-1); 217| 0| if (!NewTableArray[NewBucket]) { 218| 0| NewTableArray[FullHash & (NewSize-1)] = Bucket; 219| 0| NewHashArray[FullHash & (NewSize-1)] = FullHash; 220| 0| if (I == BucketNo) 221| 0| NewBucketNo = NewBucket; 222| 0| continue; 223| 0| } 224| 0| 225| 0| // Otherwise probe for a spot. 226| 0| unsigned ProbeSize = 1; 227| 0| do { 228| 0| NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); 229| 0| } while (NewTableArray[NewBucket]); 230| 0| 231| 0| // Finally found a slot. Fill it in. 232| 0| NewTableArray[NewBucket] = Bucket; 233| 0| NewHashArray[NewBucket] = FullHash; 234| 0| if (I == BucketNo) 235| 0| NewBucketNo = NewBucket; 236| 0| } 237| 0| } 238| 0| 239| 0| free(TheTable); 240| 0| 241| 0| TheTable = NewTableArray; 242| 0| NumBuckets = NewSize; 243| 0| NumTombstones = 0; 244| 0| return NewBucketNo; 245| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/StringRef.cpp: 1| |//===-- StringRef.cpp - Lightweight String References ---------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#include "llvm/ADT/StringRef.h" 11| |#include "llvm/ADT/Hashing.h" 12| |#include "llvm/ADT/edit_distance.h" 13| |#include 14| |#include 15| | 16| |using namespace llvm; 17| | 18| |// MSVC emits references to this into the translation units which reference it. 19| |#ifndef _MSC_VER 20| |const size_t StringRef::npos; 21| |#endif 22| | 23| 0|static char ascii_tolower(char x) { 24| 0| if (x >= 'A' && x <= 'Z') 25| 0| return x - 'A' + 'a'; 26| 0| return x; 27| 0|} 28| | 29| 0|static char ascii_toupper(char x) { 30| 0| if (x >= 'a' && x <= 'z') 31| 0| return x - 'a' + 'A'; 32| 0| return x; 33| 0|} 34| | 35| 0|static bool ascii_isdigit(char x) { 36| 0| return x >= '0' && x <= '9'; 37| 0|} 38| | 39| |// strncasecmp() is not available on non-POSIX systems, so define an 40| |// alternative function here. 41| 0|static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) { 42| 0| for (size_t I = 0; I < Length; ++I) { 43| 0| unsigned char LHC = ascii_tolower(LHS[I]); 44| 0| unsigned char RHC = ascii_tolower(RHS[I]); 45| 0| if (LHC != RHC) 46| 0| return LHC < RHC ? -1 : 1; 47| 0| } 48| 0| return 0; 49| 0|} 50| | 51| |/// compare_lower - Compare strings, ignoring case. 52| 0|int StringRef::compare_lower(StringRef RHS) const { 53| 0| if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length))) 54| 0| return Res; 55| 0| if (Length == RHS.Length) 56| 0| return 0; 57| 0| return Length < RHS.Length ? -1 : 1; 58| 0|} 59| | 60| |/// Check if this string starts with the given \p Prefix, ignoring case. 61| 0|bool StringRef::startswith_lower(StringRef Prefix) const { 62| 0| return Length >= Prefix.Length && 63| 0| ascii_strncasecmp(Data, Prefix.Data, Prefix.Length) == 0; 64| 0|} 65| | 66| |/// Check if this string ends with the given \p Suffix, ignoring case. 67| 0|bool StringRef::endswith_lower(StringRef Suffix) const { 68| 0| return Length >= Suffix.Length && 69| 0| ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 70| 0|} 71| | 72| |/// compare_numeric - Compare strings, handle embedded numbers. 73| 0|int StringRef::compare_numeric(StringRef RHS) const { 74| 0| for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { 75| 0| // Check for sequences of digits. 76| 0| if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { 77| 0| // The longer sequence of numbers is considered larger. 78| 0| // This doesn't really handle prefixed zeros well. 79| 0| size_t J; 80| 0| for (J = I + 1; J != E + 1; ++J) { 81| 0| bool ld = J < Length && ascii_isdigit(Data[J]); 82| 0| bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]); 83| 0| if (ld != rd) 84| 0| return rd ? -1 : 1; 85| 0| if (!rd) 86| 0| break; 87| 0| } 88| 0| // The two number sequences have the same length (J-I), just memcmp them. 89| 0| if (int Res = compareMemory(Data + I, RHS.Data + I, J - I)) 90| 0| return Res < 0 ? -1 : 1; 91| 0| // Identical number sequences, continue search after the numbers. 92| 0| I = J - 1; 93| 0| continue; 94| 0| } 95| 0| if (Data[I] != RHS.Data[I]) 96| 0| return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1; 97| 0| } 98| 0| if (Length == RHS.Length) 99| 0| return 0; 100| 0| return Length < RHS.Length ? -1 : 1; 101| 0|} 102| | 103| |// Compute the edit distance between the two given strings. 104| |unsigned StringRef::edit_distance(llvm::StringRef Other, 105| | bool AllowReplacements, 106| 0| unsigned MaxEditDistance) const { 107| 0| return llvm::ComputeEditDistance( 108| 0| makeArrayRef(data(), size()), 109| 0| makeArrayRef(Other.data(), Other.size()), 110| 0| AllowReplacements, MaxEditDistance); 111| 0|} 112| | 113| |//===----------------------------------------------------------------------===// 114| |// String Operations 115| |//===----------------------------------------------------------------------===// 116| | 117| 0|std::string StringRef::lower() const { 118| 0| std::string Result(size(), char()); 119| 0| for (size_type i = 0, e = size(); i != e; ++i) { 120| 0| Result[i] = ascii_tolower(Data[i]); 121| 0| } 122| 0| return Result; 123| 0|} 124| | 125| 0|std::string StringRef::upper() const { 126| 0| std::string Result(size(), char()); 127| 0| for (size_type i = 0, e = size(); i != e; ++i) { 128| 0| Result[i] = ascii_toupper(Data[i]); 129| 0| } 130| 0| return Result; 131| 0|} 132| | 133| |//===----------------------------------------------------------------------===// 134| |// String Searching 135| |//===----------------------------------------------------------------------===// 136| | 137| | 138| |/// find - Search for the first string \arg Str in the string. 139| |/// 140| |/// \return - The index of the first occurrence of \arg Str, or npos if not 141| |/// found. 142| 0|size_t StringRef::find(StringRef Str, size_t From) const { 143| 0| size_t N = Str.size(); 144| 0| if (N > Length) 145| 0| return npos; 146| 0| 147| 0| // For short haystacks or unsupported needles fall back to the naive algorithm 148| 0| if (Length < 16 || N > 255 || N == 0) { 149| 0| for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i) 150| 0| if (substr(i, N).equals(Str)) 151| 0| return i; 152| 0| return npos; 153| 0| } 154| 0| 155| 0| if (From >= Length) 156| 0| return npos; 157| 0| 158| 0| // Build the bad char heuristic table, with uint8_t to reduce cache thrashing. 159| 0| uint8_t BadCharSkip[256]; 160| 0| std::memset(BadCharSkip, N, 256); 161| 0| for (unsigned i = 0; i != N-1; ++i) 162| 0| BadCharSkip[(uint8_t)Str[i]] = N-1-i; 163| 0| 164| 0| unsigned Len = Length-From, Pos = From; 165| 0| while (Len >= N) { 166| 0| if (substr(Pos, N).equals(Str)) // See if this is the correct substring. 167| 0| return Pos; 168| 0| 169| 0| // Otherwise skip the appropriate number of bytes. 170| 0| uint8_t Skip = BadCharSkip[(uint8_t)(*this)[Pos+N-1]]; 171| 0| Len -= Skip; 172| 0| Pos += Skip; 173| 0| } 174| 0| 175| 0| return npos; 176| 0|} 177| | 178| |/// rfind - Search for the last string \arg Str in the string. 179| |/// 180| |/// \return - The index of the last occurrence of \arg Str, or npos if not 181| |/// found. 182| 0|size_t StringRef::rfind(StringRef Str) const { 183| 0| size_t N = Str.size(); 184| 0| if (N > Length) 185| 0| return npos; 186| 0| for (size_t i = Length - N + 1, e = 0; i != e;) { 187| 0| --i; 188| 0| if (substr(i, N).equals(Str)) 189| 0| return i; 190| 0| } 191| 0| return npos; 192| 0|} 193| | 194| |/// find_first_of - Find the first character in the string that is in \arg 195| |/// Chars, or npos if not found. 196| |/// 197| |/// Note: O(size() + Chars.size()) 198| |StringRef::size_type StringRef::find_first_of(StringRef Chars, 199| 0| size_t From) const { 200| 0| std::bitset<1 << CHAR_BIT> CharBits; 201| 0| for (size_type i = 0; i != Chars.size(); ++i) 202| 0| CharBits.set((unsigned char)Chars[i]); 203| 0| 204| 0| for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 205| 0| if (CharBits.test((unsigned char)Data[i])) 206| 0| return i; 207| 0| return npos; 208| 0|} 209| | 210| |/// find_first_not_of - Find the first character in the string that is not 211| |/// \arg C or npos if not found. 212| 0|StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { 213| 0| for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 214| 0| if (Data[i] != C) 215| 0| return i; 216| 0| return npos; 217| 0|} 218| | 219| |/// find_first_not_of - Find the first character in the string that is not 220| |/// in the string \arg Chars, or npos if not found. 221| |/// 222| |/// Note: O(size() + Chars.size()) 223| |StringRef::size_type StringRef::find_first_not_of(StringRef Chars, 224| 0| size_t From) const { 225| 0| std::bitset<1 << CHAR_BIT> CharBits; 226| 0| for (size_type i = 0; i != Chars.size(); ++i) 227| 0| CharBits.set((unsigned char)Chars[i]); 228| 0| 229| 0| for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 230| 0| if (!CharBits.test((unsigned char)Data[i])) 231| 0| return i; 232| 0| return npos; 233| 0|} 234| | 235| |/// find_last_of - Find the last character in the string that is in \arg C, 236| |/// or npos if not found. 237| |/// 238| |/// Note: O(size() + Chars.size()) 239| |StringRef::size_type StringRef::find_last_of(StringRef Chars, 240| 0| size_t From) const { 241| 0| std::bitset<1 << CHAR_BIT> CharBits; 242| 0| for (size_type i = 0; i != Chars.size(); ++i) 243| 0| CharBits.set((unsigned char)Chars[i]); 244| 0| 245| 0| for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) 246| 0| if (CharBits.test((unsigned char)Data[i])) 247| 0| return i; 248| 0| return npos; 249| 0|} 250| | 251| |/// find_last_not_of - Find the last character in the string that is not 252| |/// \arg C, or npos if not found. 253| 0|StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const { 254| 0| for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) 255| 0| if (Data[i] != C) 256| 0| return i; 257| 0| return npos; 258| 0|} 259| | 260| |/// find_last_not_of - Find the last character in the string that is not in 261| |/// \arg Chars, or npos if not found. 262| |/// 263| |/// Note: O(size() + Chars.size()) 264| |StringRef::size_type StringRef::find_last_not_of(StringRef Chars, 265| 0| size_t From) const { 266| 0| std::bitset<1 << CHAR_BIT> CharBits; 267| 0| for (size_type i = 0, e = Chars.size(); i != e; ++i) 268| 0| CharBits.set((unsigned char)Chars[i]); 269| 0| 270| 0| for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) 271| 0| if (!CharBits.test((unsigned char)Data[i])) 272| 0| return i; 273| 0| return npos; 274| 0|} 275| | 276| |void StringRef::split(SmallVectorImpl &A, 277| | StringRef Separators, int MaxSplit, 278| 0| bool KeepEmpty) const { 279| 0| StringRef rest = *this; 280| 0| 281| 0| // rest.data() is used to distinguish cases like "a," that splits into 282| 0| // "a" + "" and "a" that splits into "a" + 0. 283| 0| for (int splits = 0; 284| 0| rest.data() != nullptr && (MaxSplit < 0 || splits < MaxSplit); 285| 0| ++splits) { 286| 0| std::pair p = rest.split(Separators); 287| 0| 288| 0| if (KeepEmpty || p.first.size() != 0) 289| 0| A.push_back(p.first); 290| 0| rest = p.second; 291| 0| } 292| 0| // If we have a tail left, add it. 293| 0| if (rest.data() != nullptr && (rest.size() != 0 || KeepEmpty)) 294| 0| A.push_back(rest); 295| 0|} 296| | 297| |//===----------------------------------------------------------------------===// 298| |// Helpful Algorithms 299| |//===----------------------------------------------------------------------===// 300| | 301| |/// count - Return the number of non-overlapped occurrences of \arg Str in 302| |/// the string. 303| 0|size_t StringRef::count(StringRef Str) const { 304| 0| size_t Count = 0; 305| 0| size_t N = Str.size(); 306| 0| if (N > Length) 307| 0| return 0; 308| 0| for (size_t i = 0, e = Length - N + 1; i != e; ++i) 309| 0| if (substr(i, N).equals(Str)) 310| 0| ++Count; 311| 0| return Count; 312| 0|} 313| | 314| 0|static unsigned GetAutoSenseRadix(StringRef &Str) { 315| 0| if (Str.startswith("0x")) { 316| 0| Str = Str.substr(2); 317| 0| return 16; 318| 0| } 319| 0| 320| 0| if (Str.startswith("0b")) { 321| 0| Str = Str.substr(2); 322| 0| return 2; 323| 0| } 324| 0| 325| 0| if (Str.startswith("0o")) { 326| 0| Str = Str.substr(2); 327| 0| return 8; 328| 0| } 329| 0| 330| 0| if (Str.startswith("0")) 331| 0| return 8; 332| 0| 333| 0| return 10; 334| 0|} 335| | 336| | 337| |/// GetAsUnsignedInteger - Workhorse method that converts a integer character 338| |/// sequence of radix up to 36 to an unsigned long long value. 339| |bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, 340| 0| unsigned long long &Result) { 341| 0| // Autosense radix if not specified. 342| 0| if (Radix == 0) 343| 0| Radix = GetAutoSenseRadix(Str); 344| 0| 345| 0| // Empty strings (after the radix autosense) are invalid. 346| 0| if (Str.empty()) return true; 347| 0| 348| 0| // Parse all the bytes of the string given this radix. Watch for overflow. 349| 0| Result = 0; 350| 0| while (!Str.empty()) { 351| 0| unsigned CharVal; 352| 0| if (Str[0] >= '0' && Str[0] <= '9') 353| 0| CharVal = Str[0]-'0'; 354| 0| else if (Str[0] >= 'a' && Str[0] <= 'z') 355| 0| CharVal = Str[0]-'a'+10; 356| 0| else if (Str[0] >= 'A' && Str[0] <= 'Z') 357| 0| CharVal = Str[0]-'A'+10; 358| 0| else 359| 0| return true; 360| 0| 361| 0| // If the parsed value is larger than the integer radix, the string is 362| 0| // invalid. 363| 0| if (CharVal >= Radix) 364| 0| return true; 365| 0| 366| 0| // Add in this character. 367| 0| unsigned long long PrevResult = Result; 368| 0| Result = Result*Radix+CharVal; 369| 0| 370| 0| // Check for overflow by shifting back and seeing if bits were lost. 371| 0| if (Result/Radix < PrevResult) 372| 0| return true; 373| 0| 374| 0| Str = Str.substr(1); 375| 0| } 376| 0| 377| 0| return false; 378| 0|} 379| | 380| |bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, 381| 0| long long &Result) { 382| 0| unsigned long long ULLVal; 383| 0| 384| 0| // Handle positive strings first. 385| 0| if (Str.empty() || Str.front() != '-') { 386| 0| if (getAsUnsignedInteger(Str, Radix, ULLVal) || 387| 0| // Check for value so large it overflows a signed value. 388| 0| (long long)ULLVal < 0) 389| 0| return true; 390| 0| Result = ULLVal; 391| 0| return false; 392| 0| } 393| 0| 394| 0| // Get the positive part of the value. 395| 0| if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) || 396| 0| // Reject values so large they'd overflow as negative signed, but allow 397| 0| // "-0". This negates the unsigned so that the negative isn't undefined 398| 0| // on signed overflow. 399| 0| (long long)-ULLVal > 0) 400| 0| return true; 401| 0| 402| 0| Result = -ULLVal; 403| 0| return false; 404| 0|} 405| | 406| | 407| |// Implementation of StringRef hashing. 408| 0|hash_code llvm::hash_value(StringRef S) { 409| 0| return hash_combine_range(S.begin(), S.end()); 410| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Threading.cpp: 1| |//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines helper functions for running LLVM in a multi-threaded 11| |// environment. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "llvm/Support/Threading.h" 16| |#include "llvm/Config/config.h" 17| |#include "llvm/Support/Atomic.h" 18| |#include "llvm/Support/Mutex.h" 19| |#include 20| | 21| |using namespace llvm; 22| | 23| 0|bool llvm::llvm_is_multithreaded() { 24| 0|#if LLVM_ENABLE_THREADS != 0 25| 0| return true; 26| |#else 27| | return false; 28| |#endif 29| |} 30| | 31| |#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) 32| |#include 33| | 34| |struct ThreadInfo { 35| | void (*UserFn)(void *); 36| | void *UserData; 37| |}; 38| 0|static void *ExecuteOnThread_Dispatch(void *Arg) { 39| 0| ThreadInfo *TI = reinterpret_cast(Arg); 40| 0| TI->UserFn(TI->UserData); 41| 0| return nullptr; 42| 0|} 43| | 44| |void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 45| 0| unsigned RequestedStackSize) { 46| 0| ThreadInfo Info = { Fn, UserData }; 47| 0| pthread_attr_t Attr; 48| 0| pthread_t Thread; 49| 0| 50| 0| // Construct the attributes object. 51| 0| if (::pthread_attr_init(&Attr) != 0) 52| 0| return; 53| 0| 54| 0| // Set the requested stack size, if given. 55| 0| if (RequestedStackSize != 0) { 56| 0| if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) 57| 0| goto error; 58| 0| } 59| 0| 60| 0| // Construct and execute the thread. 61| 0| if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) 62| 0| goto error; 63| 0| 64| 0| // Wait for the thread and clean up. 65| 0| ::pthread_join(Thread, nullptr); 66| 0| 67| 0| error: 68| 0| ::pthread_attr_destroy(&Attr); 69| 0|} 70| |#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32) 71| |#include "Windows/WindowsSupport.h" 72| |#include 73| | 74| |struct ThreadInfo { 75| | void (*func)(void*); 76| | void *param; 77| |}; 78| | 79| |static unsigned __stdcall ThreadCallback(void *param) { 80| | struct ThreadInfo *info = reinterpret_cast(param); 81| | info->func(info->param); 82| | 83| | return 0; 84| |} 85| | 86| |void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 87| | unsigned RequestedStackSize) { 88| | struct ThreadInfo param = { Fn, UserData }; 89| | 90| | HANDLE hThread = (HANDLE)::_beginthreadex(NULL, 91| | RequestedStackSize, ThreadCallback, 92| | ¶m, 0, NULL); 93| | 94| | if (hThread) { 95| | // We actually don't care whether the wait succeeds or fails, in 96| | // the same way we don't care whether the pthread_join call succeeds 97| | // or fails. There's not much we could do if this were to fail. But 98| | // on success, this call will wait until the thread finishes executing 99| | // before returning. 100| | (void)::WaitForSingleObject(hThread, INFINITE); 101| | ::CloseHandle(hThread); 102| | } 103| |} 104| |#else 105| |// Support for non-Win32, non-pthread implementation. 106| |void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 107| | unsigned RequestedStackSize) { 108| | (void) RequestedStackSize; 109| | Fn(UserData); 110| |} 111| | 112| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/TimeValue.cpp: 1| |//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the operating system TimeValue concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/TimeValue.h" 15| |#include "llvm/Config/config.h" 16| | 17| |namespace llvm { 18| |using namespace sys; 19| | 20| |const TimeValue::SecondsType 21| | TimeValue::PosixZeroTimeSeconds = -946684800; 22| |const TimeValue::SecondsType 23| | TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; 24| | 25| |void 26| 8|TimeValue::normalize( void ) { 27| 8| if ( nanos_ >= NANOSECONDS_PER_SECOND ) { 28| 0| do { 29| 0| seconds_++; 30| 0| nanos_ -= NANOSECONDS_PER_SECOND; 31| 0| } while ( nanos_ >= NANOSECONDS_PER_SECOND ); 32| 8| } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) { 33| 0| do { 34| 0| seconds_--; 35| 0| nanos_ += NANOSECONDS_PER_SECOND; 36| 0| } while (nanos_ <= -NANOSECONDS_PER_SECOND); 37| 0| } 38| 8| 39| 8| if (seconds_ >= 1 && nanos_ < 0) { 40| 0| seconds_--; 41| 0| nanos_ += NANOSECONDS_PER_SECOND; 42| 8| } else if (seconds_ < 0 && nanos_ > 0) { 43| 0| seconds_++; 44| 0| nanos_ -= NANOSECONDS_PER_SECOND; 45| 0| } 46| 8|} 47| | 48| |} 49| | 50| |/// Include the platform-specific portion of TimeValue class 51| |#ifdef LLVM_ON_UNIX 52| |#include "Unix/TimeValue.inc" 53| |#endif 54| |#ifdef LLVM_ON_WIN32 55| |#include "Windows/TimeValue.inc" 56| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Twine.cpp: 1| |//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#include "llvm/ADT/Twine.h" 11| |#include "llvm/ADT/SmallString.h" 12| |#include "llvm/Support/Debug.h" 13| |#include "llvm/Support/raw_ostream.h" 14| |using namespace llvm; 15| | 16| 0|std::string Twine::str() const { 17| 0| // If we're storing only a std::string, just return it. 18| 0| if (LHSKind == StdStringKind && RHSKind == EmptyKind) 19| 0| return *LHS.stdString; 20| 0| 21| 0| // Otherwise, flatten and copy the contents first. 22| 0| SmallString<256> Vec; 23| 0| return toStringRef(Vec).str(); 24| 0|} 25| | 26| 0|void Twine::toVector(SmallVectorImpl &Out) const { 27| 0| raw_svector_ostream OS(Out); 28| 0| print(OS); 29| 0|} 30| | 31| 0|StringRef Twine::toStringRef(SmallVectorImpl &Out) const { 32| 0| if (isSingleStringRef()) 33| 0| return getSingleStringRef(); 34| 0| toVector(Out); 35| 0| return StringRef(Out.data(), Out.size()); 36| 0|} 37| | 38| 0|StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl &Out) const { 39| 0| if (isUnary()) { 40| 0| switch (getLHSKind()) { 41| 0| case CStringKind: 42| 0| // Already null terminated, yay! 43| 0| return StringRef(LHS.cString); 44| 0| case StdStringKind: { 45| 0| const std::string *str = LHS.stdString; 46| 0| return StringRef(str->c_str(), str->size()); 47| 0| } 48| 0| default: 49| 0| break; 50| 0| } 51| 0| } 52| 0| toVector(Out); 53| 0| Out.push_back(0); 54| 0| Out.pop_back(); 55| 0| return StringRef(Out.data(), Out.size()); 56| 0|} 57| | 58| |void Twine::printOneChild(raw_ostream &OS, Child Ptr, 59| 0| NodeKind Kind) const { 60| 0| switch (Kind) { 61| 0| case Twine::NullKind: break; 62| 0| case Twine::EmptyKind: break; 63| 0| case Twine::TwineKind: 64| 0| Ptr.twine->print(OS); 65| 0| break; 66| 0| case Twine::CStringKind: 67| 0| OS << Ptr.cString; 68| 0| break; 69| 0| case Twine::StdStringKind: 70| 0| OS << *Ptr.stdString; 71| 0| break; 72| 0| case Twine::StringRefKind: 73| 0| OS << *Ptr.stringRef; 74| 0| break; 75| 0| case Twine::CharKind: 76| 0| OS << Ptr.character; 77| 0| break; 78| 0| case Twine::DecUIKind: 79| 0| OS << Ptr.decUI; 80| 0| break; 81| 0| case Twine::DecIKind: 82| 0| OS << Ptr.decI; 83| 0| break; 84| 0| case Twine::DecULKind: 85| 0| OS << *Ptr.decUL; 86| 0| break; 87| 0| case Twine::DecLKind: 88| 0| OS << *Ptr.decL; 89| 0| break; 90| 0| case Twine::DecULLKind: 91| 0| OS << *Ptr.decULL; 92| 0| break; 93| 0| case Twine::DecLLKind: 94| 0| OS << *Ptr.decLL; 95| 0| break; 96| 0| case Twine::UHexKind: 97| 0| OS.write_hex(*Ptr.uHex); 98| 0| break; 99| 0| } 100| 0|} 101| | 102| |void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr, 103| 0| NodeKind Kind) const { 104| 0| switch (Kind) { 105| 0| case Twine::NullKind: 106| 0| OS << "null"; break; 107| 0| case Twine::EmptyKind: 108| 0| OS << "empty"; break; 109| 0| case Twine::TwineKind: 110| 0| OS << "rope:"; 111| 0| Ptr.twine->printRepr(OS); 112| 0| break; 113| 0| case Twine::CStringKind: 114| 0| OS << "cstring:\"" 115| 0| << Ptr.cString << "\""; 116| 0| break; 117| 0| case Twine::StdStringKind: 118| 0| OS << "std::string:\"" 119| 0| << Ptr.stdString << "\""; 120| 0| break; 121| 0| case Twine::StringRefKind: 122| 0| OS << "stringref:\"" 123| 0| << Ptr.stringRef << "\""; 124| 0| break; 125| 0| case Twine::CharKind: 126| 0| OS << "char:\"" << Ptr.character << "\""; 127| 0| break; 128| 0| case Twine::DecUIKind: 129| 0| OS << "decUI:\"" << Ptr.decUI << "\""; 130| 0| break; 131| 0| case Twine::DecIKind: 132| 0| OS << "decI:\"" << Ptr.decI << "\""; 133| 0| break; 134| 0| case Twine::DecULKind: 135| 0| OS << "decUL:\"" << *Ptr.decUL << "\""; 136| 0| break; 137| 0| case Twine::DecLKind: 138| 0| OS << "decL:\"" << *Ptr.decL << "\""; 139| 0| break; 140| 0| case Twine::DecULLKind: 141| 0| OS << "decULL:\"" << *Ptr.decULL << "\""; 142| 0| break; 143| 0| case Twine::DecLLKind: 144| 0| OS << "decLL:\"" << *Ptr.decLL << "\""; 145| 0| break; 146| 0| case Twine::UHexKind: 147| 0| OS << "uhex:\"" << Ptr.uHex << "\""; 148| 0| break; 149| 0| } 150| 0|} 151| | 152| 0|void Twine::print(raw_ostream &OS) const { 153| 0| printOneChild(OS, LHS, getLHSKind()); 154| 0| printOneChild(OS, RHS, getRHSKind()); 155| 0|} 156| | 157| 0|void Twine::printRepr(raw_ostream &OS) const { 158| 0| OS << "(Twine "; 159| 0| printOneChildRepr(OS, LHS, getLHSKind()); 160| 0| OS << " "; 161| 0| printOneChildRepr(OS, RHS, getRHSKind()); 162| 0| OS << ")"; 163| 0|} 164| | 165| 0|void Twine::dump() const { 166| 0| print(dbgs()); 167| 0|} 168| | 169| 0|void Twine::dumpRepr() const { 170| 0| printRepr(dbgs()); 171| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unicode.cpp: 1| |//===- llvm/Support/Unicode.cpp - Unicode character properties -*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements functions that allow querying certain properties of 11| |// Unicode characters. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "llvm/Support/Unicode.h" 16| |#include "llvm/Support/ConvertUTF.h" 17| |#include "llvm/Support/UnicodeCharRanges.h" 18| | 19| |namespace llvm { 20| |namespace sys { 21| |namespace unicode { 22| | 23| 0|bool isPrintable(int UCS) { 24| 0| // Sorted list of non-overlapping intervals of code points that are not 25| 0| // supposed to be printable. 26| 0| static const UnicodeCharRange NonPrintableRanges[] = { 27| 0| { 0x0000, 0x001F }, { 0x007F, 0x009F }, { 0x034F, 0x034F }, 28| 0| { 0x0378, 0x0379 }, { 0x037F, 0x0383 }, { 0x038B, 0x038B }, 29| 0| { 0x038D, 0x038D }, { 0x03A2, 0x03A2 }, { 0x0528, 0x0530 }, 30| 0| { 0x0557, 0x0558 }, { 0x0560, 0x0560 }, { 0x0588, 0x0588 }, 31| 0| { 0x058B, 0x058E }, { 0x0590, 0x0590 }, { 0x05C8, 0x05CF }, 32| 0| { 0x05EB, 0x05EF }, { 0x05F5, 0x0605 }, { 0x061C, 0x061D }, 33| 0| { 0x06DD, 0x06DD }, { 0x070E, 0x070F }, { 0x074B, 0x074C }, 34| 0| { 0x07B2, 0x07BF }, { 0x07FB, 0x07FF }, { 0x082E, 0x082F }, 35| 0| { 0x083F, 0x083F }, { 0x085C, 0x085D }, { 0x085F, 0x089F }, 36| 0| { 0x08A1, 0x08A1 }, { 0x08AD, 0x08E3 }, { 0x08FF, 0x08FF }, 37| 0| { 0x0978, 0x0978 }, { 0x0980, 0x0980 }, { 0x0984, 0x0984 }, 38| 0| { 0x098D, 0x098E }, { 0x0991, 0x0992 }, { 0x09A9, 0x09A9 }, 39| 0| { 0x09B1, 0x09B1 }, { 0x09B3, 0x09B5 }, { 0x09BA, 0x09BB }, 40| 0| { 0x09C5, 0x09C6 }, { 0x09C9, 0x09CA }, { 0x09CF, 0x09D6 }, 41| 0| { 0x09D8, 0x09DB }, { 0x09DE, 0x09DE }, { 0x09E4, 0x09E5 }, 42| 0| { 0x09FC, 0x0A00 }, { 0x0A04, 0x0A04 }, { 0x0A0B, 0x0A0E }, 43| 0| { 0x0A11, 0x0A12 }, { 0x0A29, 0x0A29 }, { 0x0A31, 0x0A31 }, 44| 0| { 0x0A34, 0x0A34 }, { 0x0A37, 0x0A37 }, { 0x0A3A, 0x0A3B }, 45| 0| { 0x0A3D, 0x0A3D }, { 0x0A43, 0x0A46 }, { 0x0A49, 0x0A4A }, 46| 0| { 0x0A4E, 0x0A50 }, { 0x0A52, 0x0A58 }, { 0x0A5D, 0x0A5D }, 47| 0| { 0x0A5F, 0x0A65 }, { 0x0A76, 0x0A80 }, { 0x0A84, 0x0A84 }, 48| 0| { 0x0A8E, 0x0A8E }, { 0x0A92, 0x0A92 }, { 0x0AA9, 0x0AA9 }, 49| 0| { 0x0AB1, 0x0AB1 }, { 0x0AB4, 0x0AB4 }, { 0x0ABA, 0x0ABB }, 50| 0| { 0x0AC6, 0x0AC6 }, { 0x0ACA, 0x0ACA }, { 0x0ACE, 0x0ACF }, 51| 0| { 0x0AD1, 0x0ADF }, { 0x0AE4, 0x0AE5 }, { 0x0AF2, 0x0B00 }, 52| 0| { 0x0B04, 0x0B04 }, { 0x0B0D, 0x0B0E }, { 0x0B11, 0x0B12 }, 53| 0| { 0x0B29, 0x0B29 }, { 0x0B31, 0x0B31 }, { 0x0B34, 0x0B34 }, 54| 0| { 0x0B3A, 0x0B3B }, { 0x0B45, 0x0B46 }, { 0x0B49, 0x0B4A }, 55| 0| { 0x0B4E, 0x0B55 }, { 0x0B58, 0x0B5B }, { 0x0B5E, 0x0B5E }, 56| 0| { 0x0B64, 0x0B65 }, { 0x0B78, 0x0B81 }, { 0x0B84, 0x0B84 }, 57| 0| { 0x0B8B, 0x0B8D }, { 0x0B91, 0x0B91 }, { 0x0B96, 0x0B98 }, 58| 0| { 0x0B9B, 0x0B9B }, { 0x0B9D, 0x0B9D }, { 0x0BA0, 0x0BA2 }, 59| 0| { 0x0BA5, 0x0BA7 }, { 0x0BAB, 0x0BAD }, { 0x0BBA, 0x0BBD }, 60| 0| { 0x0BC3, 0x0BC5 }, { 0x0BC9, 0x0BC9 }, { 0x0BCE, 0x0BCF }, 61| 0| { 0x0BD1, 0x0BD6 }, { 0x0BD8, 0x0BE5 }, { 0x0BFB, 0x0C00 }, 62| 0| { 0x0C04, 0x0C04 }, { 0x0C0D, 0x0C0D }, { 0x0C11, 0x0C11 }, 63| 0| { 0x0C29, 0x0C29 }, { 0x0C34, 0x0C34 }, { 0x0C3A, 0x0C3C }, 64| 0| { 0x0C45, 0x0C45 }, { 0x0C49, 0x0C49 }, { 0x0C4E, 0x0C54 }, 65| 0| { 0x0C57, 0x0C57 }, { 0x0C5A, 0x0C5F }, { 0x0C64, 0x0C65 }, 66| 0| { 0x0C70, 0x0C77 }, { 0x0C80, 0x0C81 }, { 0x0C84, 0x0C84 }, 67| 0| { 0x0C8D, 0x0C8D }, { 0x0C91, 0x0C91 }, { 0x0CA9, 0x0CA9 }, 68| 0| { 0x0CB4, 0x0CB4 }, { 0x0CBA, 0x0CBB }, { 0x0CC5, 0x0CC5 }, 69| 0| { 0x0CC9, 0x0CC9 }, { 0x0CCE, 0x0CD4 }, { 0x0CD7, 0x0CDD }, 70| 0| { 0x0CDF, 0x0CDF }, { 0x0CE4, 0x0CE5 }, { 0x0CF0, 0x0CF0 }, 71| 0| { 0x0CF3, 0x0D01 }, { 0x0D04, 0x0D04 }, { 0x0D0D, 0x0D0D }, 72| 0| { 0x0D11, 0x0D11 }, { 0x0D3B, 0x0D3C }, { 0x0D45, 0x0D45 }, 73| 0| { 0x0D49, 0x0D49 }, { 0x0D4F, 0x0D56 }, { 0x0D58, 0x0D5F }, 74| 0| { 0x0D64, 0x0D65 }, { 0x0D76, 0x0D78 }, { 0x0D80, 0x0D81 }, 75| 0| { 0x0D84, 0x0D84 }, { 0x0D97, 0x0D99 }, { 0x0DB2, 0x0DB2 }, 76| 0| { 0x0DBC, 0x0DBC }, { 0x0DBE, 0x0DBF }, { 0x0DC7, 0x0DC9 }, 77| 0| { 0x0DCB, 0x0DCE }, { 0x0DD5, 0x0DD5 }, { 0x0DD7, 0x0DD7 }, 78| 0| { 0x0DE0, 0x0DF1 }, { 0x0DF5, 0x0E00 }, { 0x0E3B, 0x0E3E }, 79| 0| { 0x0E5C, 0x0E80 }, { 0x0E83, 0x0E83 }, { 0x0E85, 0x0E86 }, 80| 0| { 0x0E89, 0x0E89 }, { 0x0E8B, 0x0E8C }, { 0x0E8E, 0x0E93 }, 81| 0| { 0x0E98, 0x0E98 }, { 0x0EA0, 0x0EA0 }, { 0x0EA4, 0x0EA4 }, 82| 0| { 0x0EA6, 0x0EA6 }, { 0x0EA8, 0x0EA9 }, { 0x0EAC, 0x0EAC }, 83| 0| { 0x0EBA, 0x0EBA }, { 0x0EBE, 0x0EBF }, { 0x0EC5, 0x0EC5 }, 84| 0| { 0x0EC7, 0x0EC7 }, { 0x0ECE, 0x0ECF }, { 0x0EDA, 0x0EDB }, 85| 0| { 0x0EE0, 0x0EFF }, { 0x0F48, 0x0F48 }, { 0x0F6D, 0x0F70 }, 86| 0| { 0x0F98, 0x0F98 }, { 0x0FBD, 0x0FBD }, { 0x0FCD, 0x0FCD }, 87| 0| { 0x0FDB, 0x0FFF }, { 0x10C6, 0x10C6 }, { 0x10C8, 0x10CC }, 88| 0| { 0x10CE, 0x10CF }, { 0x115F, 0x1160 }, { 0x1249, 0x1249 }, 89| 0| { 0x124E, 0x124F }, { 0x1257, 0x1257 }, { 0x1259, 0x1259 }, 90| 0| { 0x125E, 0x125F }, { 0x1289, 0x1289 }, { 0x128E, 0x128F }, 91| 0| { 0x12B1, 0x12B1 }, { 0x12B6, 0x12B7 }, { 0x12BF, 0x12BF }, 92| 0| { 0x12C1, 0x12C1 }, { 0x12C6, 0x12C7 }, { 0x12D7, 0x12D7 }, 93| 0| { 0x1311, 0x1311 }, { 0x1316, 0x1317 }, { 0x135B, 0x135C }, 94| 0| { 0x137D, 0x137F }, { 0x139A, 0x139F }, { 0x13F5, 0x13FF }, 95| 0| { 0x169D, 0x169F }, { 0x16F1, 0x16FF }, { 0x170D, 0x170D }, 96| 0| { 0x1715, 0x171F }, { 0x1737, 0x173F }, { 0x1754, 0x175F }, 97| 0| { 0x176D, 0x176D }, { 0x1771, 0x1771 }, { 0x1774, 0x177F }, 98| 0| { 0x17B4, 0x17B5 }, { 0x17DE, 0x17DF }, { 0x17EA, 0x17EF }, 99| 0| { 0x17FA, 0x17FF }, { 0x180B, 0x180D }, { 0x180F, 0x180F }, 100| 0| { 0x181A, 0x181F }, { 0x1878, 0x187F }, { 0x18AB, 0x18AF }, 101| 0| { 0x18F6, 0x18FF }, { 0x191D, 0x191F }, { 0x192C, 0x192F }, 102| 0| { 0x193C, 0x193F }, { 0x1941, 0x1943 }, { 0x196E, 0x196F }, 103| 0| { 0x1975, 0x197F }, { 0x19AC, 0x19AF }, { 0x19CA, 0x19CF }, 104| 0| { 0x19DB, 0x19DD }, { 0x1A1C, 0x1A1D }, { 0x1A5F, 0x1A5F }, 105| 0| { 0x1A7D, 0x1A7E }, { 0x1A8A, 0x1A8F }, { 0x1A9A, 0x1A9F }, 106| 0| { 0x1AAE, 0x1AFF }, { 0x1B4C, 0x1B4F }, { 0x1B7D, 0x1B7F }, 107| 0| { 0x1BF4, 0x1BFB }, { 0x1C38, 0x1C3A }, { 0x1C4A, 0x1C4C }, 108| 0| { 0x1C80, 0x1CBF }, { 0x1CC8, 0x1CCF }, { 0x1CF7, 0x1CFF }, 109| 0| { 0x1DE7, 0x1DFB }, { 0x1F16, 0x1F17 }, { 0x1F1E, 0x1F1F }, 110| 0| { 0x1F46, 0x1F47 }, { 0x1F4E, 0x1F4F }, { 0x1F58, 0x1F58 }, 111| 0| { 0x1F5A, 0x1F5A }, { 0x1F5C, 0x1F5C }, { 0x1F5E, 0x1F5E }, 112| 0| { 0x1F7E, 0x1F7F }, { 0x1FB5, 0x1FB5 }, { 0x1FC5, 0x1FC5 }, 113| 0| { 0x1FD4, 0x1FD5 }, { 0x1FDC, 0x1FDC }, { 0x1FF0, 0x1FF1 }, 114| 0| { 0x1FF5, 0x1FF5 }, { 0x1FFF, 0x1FFF }, { 0x200B, 0x200F }, 115| 0| { 0x202A, 0x202E }, { 0x2060, 0x206F }, { 0x2072, 0x2073 }, 116| 0| { 0x208F, 0x208F }, { 0x209D, 0x209F }, { 0x20BB, 0x20CF }, 117| 0| { 0x20F1, 0x20FF }, { 0x218A, 0x218F }, { 0x23F4, 0x23FF }, 118| 0| { 0x2427, 0x243F }, { 0x244B, 0x245F }, { 0x2700, 0x2700 }, 119| 0| { 0x2B4D, 0x2B4F }, { 0x2B5A, 0x2BFF }, { 0x2C2F, 0x2C2F }, 120| 0| { 0x2C5F, 0x2C5F }, { 0x2CF4, 0x2CF8 }, { 0x2D26, 0x2D26 }, 121| 0| { 0x2D28, 0x2D2C }, { 0x2D2E, 0x2D2F }, { 0x2D68, 0x2D6E }, 122| 0| { 0x2D71, 0x2D7E }, { 0x2D97, 0x2D9F }, { 0x2DA7, 0x2DA7 }, 123| 0| { 0x2DAF, 0x2DAF }, { 0x2DB7, 0x2DB7 }, { 0x2DBF, 0x2DBF }, 124| 0| { 0x2DC7, 0x2DC7 }, { 0x2DCF, 0x2DCF }, { 0x2DD7, 0x2DD7 }, 125| 0| { 0x2DDF, 0x2DDF }, { 0x2E3C, 0x2E7F }, { 0x2E9A, 0x2E9A }, 126| 0| { 0x2EF4, 0x2EFF }, { 0x2FD6, 0x2FEF }, { 0x2FFC, 0x2FFF }, 127| 0| { 0x3040, 0x3040 }, { 0x3097, 0x3098 }, { 0x3100, 0x3104 }, 128| 0| { 0x312E, 0x3130 }, { 0x3164, 0x3164 }, { 0x318F, 0x318F }, 129| 0| { 0x31BB, 0x31BF }, { 0x31E4, 0x31EF }, { 0x321F, 0x321F }, 130| 0| { 0x32FF, 0x32FF }, { 0x4DB6, 0x4DBF }, { 0x9FCD, 0x9FFF }, 131| 0| { 0xA48D, 0xA48F }, { 0xA4C7, 0xA4CF }, { 0xA62C, 0xA63F }, 132| 0| { 0xA698, 0xA69E }, { 0xA6F8, 0xA6FF }, { 0xA78F, 0xA78F }, 133| 0| { 0xA794, 0xA79F }, { 0xA7AB, 0xA7F7 }, { 0xA82C, 0xA82F }, 134| 0| { 0xA83A, 0xA83F }, { 0xA878, 0xA87F }, { 0xA8C5, 0xA8CD }, 135| 0| { 0xA8DA, 0xA8DF }, { 0xA8FC, 0xA8FF }, { 0xA954, 0xA95E }, 136| 0| { 0xA97D, 0xA97F }, { 0xA9CE, 0xA9CE }, { 0xA9DA, 0xA9DD }, 137| 0| { 0xA9E0, 0xA9FF }, { 0xAA37, 0xAA3F }, { 0xAA4E, 0xAA4F }, 138| 0| { 0xAA5A, 0xAA5B }, { 0xAA7C, 0xAA7F }, { 0xAAC3, 0xAADA }, 139| 0| { 0xAAF7, 0xAB00 }, { 0xAB07, 0xAB08 }, { 0xAB0F, 0xAB10 }, 140| 0| { 0xAB17, 0xAB1F }, { 0xAB27, 0xAB27 }, { 0xAB2F, 0xABBF }, 141| 0| { 0xABEE, 0xABEF }, { 0xABFA, 0xABFF }, { 0xD7A4, 0xD7AF }, 142| 0| { 0xD7C7, 0xD7CA }, { 0xD7FC, 0xDFFF }, { 0xFA6E, 0xFA6F }, 143| 0| { 0xFADA, 0xFAFF }, { 0xFB07, 0xFB12 }, { 0xFB18, 0xFB1C }, 144| 0| { 0xFB37, 0xFB37 }, { 0xFB3D, 0xFB3D }, { 0xFB3F, 0xFB3F }, 145| 0| { 0xFB42, 0xFB42 }, { 0xFB45, 0xFB45 }, { 0xFBC2, 0xFBD2 }, 146| 0| { 0xFD40, 0xFD4F }, { 0xFD90, 0xFD91 }, { 0xFDC8, 0xFDEF }, 147| 0| { 0xFDFE, 0xFE0F }, { 0xFE1A, 0xFE1F }, { 0xFE27, 0xFE2F }, 148| 0| { 0xFE53, 0xFE53 }, { 0xFE67, 0xFE67 }, { 0xFE6C, 0xFE6F }, 149| 0| { 0xFE75, 0xFE75 }, { 0xFEFD, 0xFEFF }, { 0xFF00, 0xFF00 }, 150| 0| { 0xFFA0, 0xFFA0 }, { 0xFFBF, 0xFFC1 }, { 0xFFC8, 0xFFC9 }, 151| 0| { 0xFFD0, 0xFFD1 }, { 0xFFD8, 0xFFD9 }, { 0xFFDD, 0xFFDF }, 152| 0| { 0xFFE7, 0xFFE7 }, { 0xFFEF, 0xFFFB }, { 0xFFFE, 0xFFFF }, 153| 0| { 0x1000C, 0x1000C }, { 0x10027, 0x10027 }, { 0x1003B, 0x1003B }, 154| 0| { 0x1003E, 0x1003E }, { 0x1004E, 0x1004F }, { 0x1005E, 0x1007F }, 155| 0| { 0x100FB, 0x100FF }, { 0x10103, 0x10106 }, { 0x10134, 0x10136 }, 156| 0| { 0x1018B, 0x1018F }, { 0x1019C, 0x101CF }, { 0x101FE, 0x1027F }, 157| 0| { 0x1029D, 0x1029F }, { 0x102D1, 0x102FF }, { 0x1031F, 0x1031F }, 158| 0| { 0x10324, 0x1032F }, { 0x1034B, 0x1037F }, { 0x1039E, 0x1039E }, 159| 0| { 0x103C4, 0x103C7 }, { 0x103D6, 0x103FF }, { 0x1049E, 0x1049F }, 160| 0| { 0x104AA, 0x107FF }, { 0x10806, 0x10807 }, { 0x10809, 0x10809 }, 161| 0| { 0x10836, 0x10836 }, { 0x10839, 0x1083B }, { 0x1083D, 0x1083E }, 162| 0| { 0x10856, 0x10856 }, { 0x10860, 0x108FF }, { 0x1091C, 0x1091E }, 163| 0| { 0x1093A, 0x1093E }, { 0x10940, 0x1097F }, { 0x109B8, 0x109BD }, 164| 0| { 0x109C0, 0x109FF }, { 0x10A04, 0x10A04 }, { 0x10A07, 0x10A0B }, 165| 0| { 0x10A14, 0x10A14 }, { 0x10A18, 0x10A18 }, { 0x10A34, 0x10A37 }, 166| 0| { 0x10A3B, 0x10A3E }, { 0x10A48, 0x10A4F }, { 0x10A59, 0x10A5F }, 167| 0| { 0x10A80, 0x10AFF }, { 0x10B36, 0x10B38 }, { 0x10B56, 0x10B57 }, 168| 0| { 0x10B73, 0x10B77 }, { 0x10B80, 0x10BFF }, { 0x10C49, 0x10E5F }, 169| 0| { 0x10E7F, 0x10FFF }, { 0x1104E, 0x11051 }, { 0x11070, 0x1107F }, 170| 0| { 0x110BD, 0x110BD }, { 0x110C2, 0x110CF }, { 0x110E9, 0x110EF }, 171| 0| { 0x110FA, 0x110FF }, { 0x11135, 0x11135 }, { 0x11144, 0x1117F }, 172| 0| { 0x111C9, 0x111CF }, { 0x111DA, 0x1167F }, { 0x116B8, 0x116BF }, 173| 0| { 0x116CA, 0x11FFF }, { 0x1236F, 0x123FF }, { 0x12463, 0x1246F }, 174| 0| { 0x12474, 0x12FFF }, { 0x1342F, 0x167FF }, { 0x16A39, 0x16EFF }, 175| 0| { 0x16F45, 0x16F4F }, { 0x16F7F, 0x16F8E }, { 0x16FA0, 0x1AFFF }, 176| 0| { 0x1B002, 0x1CFFF }, { 0x1D0F6, 0x1D0FF }, { 0x1D127, 0x1D128 }, 177| 0| { 0x1D173, 0x1D17A }, { 0x1D1DE, 0x1D1FF }, { 0x1D246, 0x1D2FF }, 178| 0| { 0x1D357, 0x1D35F }, { 0x1D372, 0x1D3FF }, { 0x1D455, 0x1D455 }, 179| 0| { 0x1D49D, 0x1D49D }, { 0x1D4A0, 0x1D4A1 }, { 0x1D4A3, 0x1D4A4 }, 180| 0| { 0x1D4A7, 0x1D4A8 }, { 0x1D4AD, 0x1D4AD }, { 0x1D4BA, 0x1D4BA }, 181| 0| { 0x1D4BC, 0x1D4BC }, { 0x1D4C4, 0x1D4C4 }, { 0x1D506, 0x1D506 }, 182| 0| { 0x1D50B, 0x1D50C }, { 0x1D515, 0x1D515 }, { 0x1D51D, 0x1D51D }, 183| 0| { 0x1D53A, 0x1D53A }, { 0x1D53F, 0x1D53F }, { 0x1D545, 0x1D545 }, 184| 0| { 0x1D547, 0x1D549 }, { 0x1D551, 0x1D551 }, { 0x1D6A6, 0x1D6A7 }, 185| 0| { 0x1D7CC, 0x1D7CD }, { 0x1D800, 0x1EDFF }, { 0x1EE04, 0x1EE04 }, 186| 0| { 0x1EE20, 0x1EE20 }, { 0x1EE23, 0x1EE23 }, { 0x1EE25, 0x1EE26 }, 187| 0| { 0x1EE28, 0x1EE28 }, { 0x1EE33, 0x1EE33 }, { 0x1EE38, 0x1EE38 }, 188| 0| { 0x1EE3A, 0x1EE3A }, { 0x1EE3C, 0x1EE41 }, { 0x1EE43, 0x1EE46 }, 189| 0| { 0x1EE48, 0x1EE48 }, { 0x1EE4A, 0x1EE4A }, { 0x1EE4C, 0x1EE4C }, 190| 0| { 0x1EE50, 0x1EE50 }, { 0x1EE53, 0x1EE53 }, { 0x1EE55, 0x1EE56 }, 191| 0| { 0x1EE58, 0x1EE58 }, { 0x1EE5A, 0x1EE5A }, { 0x1EE5C, 0x1EE5C }, 192| 0| { 0x1EE5E, 0x1EE5E }, { 0x1EE60, 0x1EE60 }, { 0x1EE63, 0x1EE63 }, 193| 0| { 0x1EE65, 0x1EE66 }, { 0x1EE6B, 0x1EE6B }, { 0x1EE73, 0x1EE73 }, 194| 0| { 0x1EE78, 0x1EE78 }, { 0x1EE7D, 0x1EE7D }, { 0x1EE7F, 0x1EE7F }, 195| 0| { 0x1EE8A, 0x1EE8A }, { 0x1EE9C, 0x1EEA0 }, { 0x1EEA4, 0x1EEA4 }, 196| 0| { 0x1EEAA, 0x1EEAA }, { 0x1EEBC, 0x1EEEF }, { 0x1EEF2, 0x1EFFF }, 197| 0| { 0x1F02C, 0x1F02F }, { 0x1F094, 0x1F09F }, { 0x1F0AF, 0x1F0B0 }, 198| 0| { 0x1F0BF, 0x1F0C0 }, { 0x1F0D0, 0x1F0D0 }, { 0x1F0E0, 0x1F0FF }, 199| 0| { 0x1F10B, 0x1F10F }, { 0x1F12F, 0x1F12F }, { 0x1F16C, 0x1F16F }, 200| 0| { 0x1F19B, 0x1F1E5 }, { 0x1F203, 0x1F20F }, { 0x1F23B, 0x1F23F }, 201| 0| { 0x1F249, 0x1F24F }, { 0x1F252, 0x1F2FF }, { 0x1F321, 0x1F32F }, 202| 0| { 0x1F336, 0x1F336 }, { 0x1F37D, 0x1F37F }, { 0x1F394, 0x1F39F }, 203| 0| { 0x1F3C5, 0x1F3C5 }, { 0x1F3CB, 0x1F3DF }, { 0x1F3F1, 0x1F3FF }, 204| 0| { 0x1F43F, 0x1F43F }, { 0x1F441, 0x1F441 }, { 0x1F4F8, 0x1F4F8 }, 205| 0| { 0x1F4FD, 0x1F4FF }, { 0x1F53E, 0x1F53F }, { 0x1F544, 0x1F54F }, 206| 0| { 0x1F568, 0x1F5FA }, { 0x1F641, 0x1F644 }, { 0x1F650, 0x1F67F }, 207| 0| { 0x1F6C6, 0x1F6FF }, { 0x1F774, 0x1FFFF }, { 0x2A6D7, 0x2A6FF }, 208| 0| { 0x2B735, 0x2B73F }, { 0x2B81E, 0x2F7FF }, { 0x2FA1E, 0xF0000 }, 209| 0| { 0xFFFFE, 0xFFFFF }, { 0x10FFFE, 0x10FFFF } 210| 0| }; 211| 0| static const UnicodeCharSet NonPrintables(NonPrintableRanges); 212| 0| 213| 0| return UCS >= 0 && UCS <= 0x10FFFF && !NonPrintables.contains(UCS); 214| 0|} 215| | 216| |/// Gets the number of positions a character is likely to occupy when output 217| |/// on a terminal ("character width"). This depends on the implementation of the 218| |/// terminal, and there's no standard definition of character width. 219| |/// The implementation defines it in a way that is expected to be compatible 220| |/// with a generic Unicode-capable terminal. 221| |/// \return Character width: 222| |/// * ErrorNonPrintableCharacter (-1) for non-printable characters (as 223| |/// identified by isPrintable); 224| |/// * 0 for non-spacing and enclosing combining marks; 225| |/// * 2 for CJK characters excluding halfwidth forms; 226| |/// * 1 for all remaining characters. 227| |static inline int charWidth(int UCS) 228| 0|{ 229| 0| if (!isPrintable(UCS)) 230| 0| return ErrorNonPrintableCharacter; 231| 0| 232| 0| // Sorted list of non-spacing and enclosing combining mark intervals as 233| 0| // defined in "3.6 Combination" of 234| 0| // http://www.unicode.org/versions/Unicode6.2.0/UnicodeStandard-6.2.pdf 235| 0| static const UnicodeCharRange CombiningCharacterRanges[] = { 236| 0| { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD }, 237| 0| { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 }, 238| 0| { 0x05C7, 0x05C7 }, { 0x0610, 0x061A }, { 0x064B, 0x065F }, 239| 0| { 0x0670, 0x0670 }, { 0x06D6, 0x06DC }, { 0x06DF, 0x06E4 }, 240| 0| { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x0711, 0x0711 }, 241| 0| { 0x0730, 0x074A }, { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, 242| 0| { 0x0816, 0x0819 }, { 0x081B, 0x0823 }, { 0x0825, 0x0827 }, 243| 0| { 0x0829, 0x082D }, { 0x0859, 0x085B }, { 0x08E4, 0x08FE }, 244| 0| { 0x0900, 0x0902 }, { 0x093A, 0x093A }, { 0x093C, 0x093C }, 245| 0| { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0957 }, 246| 0| { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, 247| 0| { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, 248| 0| { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, 249| 0| { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A51, 0x0A51 }, 250| 0| { 0x0A70, 0x0A71 }, { 0x0A75, 0x0A75 }, { 0x0A81, 0x0A82 }, 251| 0| { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, 252| 0| { 0x0ACD, 0x0ACD }, { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, 253| 0| { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B44 }, 254| 0| { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B62, 0x0B63 }, 255| 0| { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, 256| 0| { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, 257| 0| { 0x0C55, 0x0C56 }, { 0x0C62, 0x0C63 }, { 0x0CBC, 0x0CBC }, 258| 0| { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, 259| 0| { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D44 }, { 0x0D4D, 0x0D4D }, 260| 0| { 0x0D62, 0x0D63 }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, 261| 0| { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, 262| 0| { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, 263| 0| { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, 264| 0| { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, 265| 0| { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, 266| 0| { 0x0F8D, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, 267| 0| { 0x102D, 0x1030 }, { 0x1032, 0x1037 }, { 0x1039, 0x103A }, 268| 0| { 0x103D, 0x103E }, { 0x1058, 0x1059 }, { 0x105E, 0x1060 }, 269| 0| { 0x1071, 0x1074 }, { 0x1082, 0x1082 }, { 0x1085, 0x1086 }, 270| 0| { 0x108D, 0x108D }, { 0x109D, 0x109D }, { 0x135D, 0x135F }, 271| 0| { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, 272| 0| { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, 273| 0| { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, 274| 0| { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, 275| 0| { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, 276| 0| { 0x1A17, 0x1A18 }, { 0x1A56, 0x1A56 }, { 0x1A58, 0x1A5E }, 277| 0| { 0x1A60, 0x1A60 }, { 0x1A62, 0x1A62 }, { 0x1A65, 0x1A6C }, 278| 0| { 0x1A73, 0x1A7C }, { 0x1A7F, 0x1A7F }, { 0x1B00, 0x1B03 }, 279| 0| { 0x1B34, 0x1B34 }, { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, 280| 0| { 0x1B42, 0x1B42 }, { 0x1B6B, 0x1B73 }, { 0x1B80, 0x1B81 }, 281| 0| { 0x1BA2, 0x1BA5 }, { 0x1BA8, 0x1BA9 }, { 0x1BAB, 0x1BAB }, 282| 0| { 0x1BE6, 0x1BE6 }, { 0x1BE8, 0x1BE9 }, { 0x1BED, 0x1BED }, 283| 0| { 0x1BEF, 0x1BF1 }, { 0x1C2C, 0x1C33 }, { 0x1C36, 0x1C37 }, 284| 0| { 0x1CD0, 0x1CD2 }, { 0x1CD4, 0x1CE0 }, { 0x1CE2, 0x1CE8 }, 285| 0| { 0x1CED, 0x1CED }, { 0x1CF4, 0x1CF4 }, { 0x1DC0, 0x1DE6 }, 286| 0| { 0x1DFC, 0x1DFF }, { 0x20D0, 0x20F0 }, { 0x2CEF, 0x2CF1 }, 287| 0| { 0x2D7F, 0x2D7F }, { 0x2DE0, 0x2DFF }, { 0x302A, 0x302D }, 288| 0| { 0x3099, 0x309A }, { 0xA66F, 0xA672 }, { 0xA674, 0xA67D }, 289| 0| { 0xA69F, 0xA69F }, { 0xA6F0, 0xA6F1 }, { 0xA802, 0xA802 }, 290| 0| { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, { 0xA825, 0xA826 }, 291| 0| { 0xA8C4, 0xA8C4 }, { 0xA8E0, 0xA8F1 }, { 0xA926, 0xA92D }, 292| 0| { 0xA947, 0xA951 }, { 0xA980, 0xA982 }, { 0xA9B3, 0xA9B3 }, 293| 0| { 0xA9B6, 0xA9B9 }, { 0xA9BC, 0xA9BC }, { 0xAA29, 0xAA2E }, 294| 0| { 0xAA31, 0xAA32 }, { 0xAA35, 0xAA36 }, { 0xAA43, 0xAA43 }, 295| 0| { 0xAA4C, 0xAA4C }, { 0xAAB0, 0xAAB0 }, { 0xAAB2, 0xAAB4 }, 296| 0| { 0xAAB7, 0xAAB8 }, { 0xAABE, 0xAABF }, { 0xAAC1, 0xAAC1 }, 297| 0| { 0xAAEC, 0xAAED }, { 0xAAF6, 0xAAF6 }, { 0xABE5, 0xABE5 }, 298| 0| { 0xABE8, 0xABE8 }, { 0xABED, 0xABED }, { 0xFB1E, 0xFB1E }, 299| 0| { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE26 }, { 0x101FD, 0x101FD }, 300| 0| { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, 301| 0| { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x11001, 0x11001 }, 302| 0| { 0x11038, 0x11046 }, { 0x11080, 0x11081 }, { 0x110B3, 0x110B6 }, 303| 0| { 0x110B9, 0x110BA }, { 0x11100, 0x11102 }, { 0x11127, 0x1112B }, 304| 0| { 0x1112D, 0x11134 }, { 0x11180, 0x11181 }, { 0x111B6, 0x111BE }, 305| 0| { 0x116AB, 0x116AB }, { 0x116AD, 0x116AD }, { 0x116B0, 0x116B5 }, 306| 0| { 0x116B7, 0x116B7 }, { 0x16F8F, 0x16F92 }, { 0x1D167, 0x1D169 }, 307| 0| { 0x1D17B, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, 308| 0| { 0x1D242, 0x1D244 }, { 0xE0100, 0xE01EF }, 309| 0| }; 310| 0| static const UnicodeCharSet CombiningCharacters(CombiningCharacterRanges); 311| 0| 312| 0| if (CombiningCharacters.contains(UCS)) 313| 0| return 0; 314| 0| 315| 0| static const UnicodeCharRange DoubleWidthCharacterRanges[] = { 316| 0| // Hangul Jamo 317| 0| { 0x1100, 0x11FF }, 318| 0| // Deprecated fullwidth angle brackets 319| 0| { 0x2329, 0x232A }, 320| 0| // CJK Misc, CJK Unified Ideographs, Yijing Hexagrams, Yi 321| 0| // excluding U+303F (IDEOGRAPHIC HALF FILL SPACE) 322| 0| { 0x2E80, 0x303E }, { 0x3040, 0xA4CF }, 323| 0| // Hangul 324| 0| { 0xAC00, 0xD7A3 }, { 0xD7B0, 0xD7C6 }, { 0xD7CB, 0xD7FB }, 325| 0| // CJK Unified Ideographs 326| 0| { 0xF900, 0xFAFF }, 327| 0| // Vertical forms 328| 0| { 0xFE10, 0xFE19 }, 329| 0| // CJK Compatibility Forms + Small Form Variants 330| 0| { 0xFE30, 0xFE6F }, 331| 0| // Fullwidth forms 332| 0| { 0xFF01, 0xFF60 }, { 0xFFE0, 0xFFE6 }, 333| 0| // CJK Unified Ideographs 334| 0| { 0x20000, 0x2A6DF }, { 0x2A700, 0x2B81F }, { 0x2F800, 0x2FA1F } 335| 0| }; 336| 0| static const UnicodeCharSet DoubleWidthCharacters(DoubleWidthCharacterRanges); 337| 0| 338| 0| if (DoubleWidthCharacters.contains(UCS)) 339| 0| return 2; 340| 0| return 1; 341| 0|} 342| | 343| 0|int columnWidthUTF8(StringRef Text) { 344| 0| unsigned ColumnWidth = 0; 345| 0| unsigned Length; 346| 0| for (size_t i = 0, e = Text.size(); i < e; i += Length) { 347| 0| Length = getNumBytesForUTF8(Text[i]); 348| 0| if (Length <= 0 || i + Length > Text.size()) 349| 0| return ErrorInvalidUTF8; 350| 0| UTF32 buf[1]; 351| 0| const UTF8 *Start = reinterpret_cast(Text.data() + i); 352| 0| UTF32 *Target = &buf[0]; 353| 0| if (conversionOK != ConvertUTF8toUTF32(&Start, Start + Length, &Target, 354| 0| Target + 1, strictConversion)) 355| 0| return ErrorInvalidUTF8; 356| 0| int Width = charWidth(buf[0]); 357| 0| if (Width < 0) 358| 0| return ErrorNonPrintableCharacter; 359| 0| ColumnWidth += Width; 360| 0| } 361| 0| return ColumnWidth; 362| 0|} 363| | 364| |} // namespace unicode 365| |} // namespace sys 366| |} // namespace llvm 367| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Memory.inc: 1| |//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines some functions for various memory management utilities. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "Unix.h" 15| |#include "llvm/Support/DataTypes.h" 16| |#include "llvm/Support/ErrorHandling.h" 17| |#include "llvm/Support/Process.h" 18| | 19| |#ifdef HAVE_SYS_MMAN_H 20| |#include 21| |#endif 22| | 23| |#ifdef __APPLE__ 24| |#include 25| |#endif 26| | 27| |#if defined(__mips__) 28| |# if defined(__OpenBSD__) 29| |# include 30| |# else 31| |# include 32| |# endif 33| |#endif 34| | 35| |#ifdef __APPLE__ 36| |extern "C" void sys_icache_invalidate(const void *Addr, size_t len); 37| |#else 38| |extern "C" void __clear_cache(void *, void*); 39| |#endif 40| | 41| |namespace { 42| | 43| 0|int getPosixProtectionFlags(unsigned Flags) { 44| 0| switch (Flags) { 45| 0| case llvm::sys::Memory::MF_READ: 46| 0| return PROT_READ; 47| 0| case llvm::sys::Memory::MF_WRITE: 48| 0| return PROT_WRITE; 49| 0| case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE: 50| 0| return PROT_READ | PROT_WRITE; 51| 0| case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: 52| 0| return PROT_READ | PROT_EXEC; 53| 0| case llvm::sys::Memory::MF_READ | 54| 0| llvm::sys::Memory::MF_WRITE | 55| 0| llvm::sys::Memory::MF_EXEC: 56| 0| return PROT_READ | PROT_WRITE | PROT_EXEC; 57| 0| case llvm::sys::Memory::MF_EXEC: 58| |#if defined(__FreeBSD__) 59| | // On PowerPC, having an executable page that has no read permission 60| | // can have unintended consequences. The function InvalidateInstruction- 61| | // Cache uses instructions dcbf and icbi, both of which are treated by 62| | // the processor as loads. If the page has no read permissions, 63| | // executing these instructions will result in a segmentation fault. 64| | // Somehow, this problem is not present on Linux, but it does happen 65| | // on FreeBSD. 66| | return PROT_READ | PROT_EXEC; 67| |#else 68| | return PROT_EXEC; 69| 0|#endif 70| 0| default: 71| 0| llvm_unreachable("Illegal memory protection flag specified!"); 72| 0| } 73| 0| // Provide a default return value as required by some compilers. 74| 0| return PROT_NONE; 75| 0|} 76| | 77| |} // namespace 78| | 79| |namespace llvm { 80| |namespace sys { 81| | 82| |MemoryBlock 83| |Memory::allocateMappedMemory(size_t NumBytes, 84| | const MemoryBlock *const NearBlock, 85| | unsigned PFlags, 86| 0| std::error_code &EC) { 87| 0| EC = std::error_code(); 88| 0| if (NumBytes == 0) 89| 0| return MemoryBlock(); 90| 0| 91| 0| static const size_t PageSize = Process::getPageSize(); 92| 0| const size_t NumPages = (NumBytes+PageSize-1)/PageSize; 93| 0| 94| 0| int fd = -1; 95| |#ifdef NEED_DEV_ZERO_FOR_MMAP 96| | static int zero_fd = open("/dev/zero", O_RDWR); 97| | if (zero_fd == -1) { 98| | EC = std::error_code(errno, std::generic_category()); 99| | return MemoryBlock(); 100| | } 101| | fd = zero_fd; 102| |#endif 103| | 104| 0| int MMFlags = MAP_PRIVATE | 105| |#ifdef HAVE_MMAP_ANONYMOUS 106| | MAP_ANONYMOUS 107| |#else 108| | MAP_ANON 109| 0|#endif 110| 0| ; // Ends statement above 111| 0| 112| 0| int Protect = getPosixProtectionFlags(PFlags); 113| 0| 114| 0| // Use any near hint and the page size to set a page-aligned starting address 115| 0| uintptr_t Start = NearBlock ? reinterpret_cast(NearBlock->base()) + 116| 0| NearBlock->size() : 0; 117| 0| if (Start && Start % PageSize) 118| 0| Start += PageSize - Start % PageSize; 119| 0| 120| 0| void *Addr = ::mmap(reinterpret_cast(Start), PageSize*NumPages, 121| 0| Protect, MMFlags, fd, 0); 122| 0| if (Addr == MAP_FAILED) { 123| 0| if (NearBlock) //Try again without a near hint 124| 0| return allocateMappedMemory(NumBytes, nullptr, PFlags, EC); 125| 0| 126| 0| EC = std::error_code(errno, std::generic_category()); 127| 0| return MemoryBlock(); 128| 0| } 129| 0| 130| 0| MemoryBlock Result; 131| 0| Result.Address = Addr; 132| 0| Result.Size = NumPages*PageSize; 133| 0| 134| 0| if (PFlags & MF_EXEC) 135| 0| Memory::InvalidateInstructionCache(Result.Address, Result.Size); 136| 0| 137| 0| return Result; 138| 0|} 139| | 140| |std::error_code 141| 0|Memory::releaseMappedMemory(MemoryBlock &M) { 142| 0| if (M.Address == nullptr || M.Size == 0) 143| 0| return std::error_code(); 144| 0| 145| 0| if (0 != ::munmap(M.Address, M.Size)) 146| 0| return std::error_code(errno, std::generic_category()); 147| 0| 148| 0| M.Address = nullptr; 149| 0| M.Size = 0; 150| 0| 151| 0| return std::error_code(); 152| 0|} 153| | 154| |std::error_code 155| 0|Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { 156| 0| if (M.Address == nullptr || M.Size == 0) 157| 0| return std::error_code(); 158| 0| 159| 0| if (!Flags) 160| 0| return std::error_code(EINVAL, std::generic_category()); 161| 0| 162| 0| int Protect = getPosixProtectionFlags(Flags); 163| 0| 164| 0| int Result = ::mprotect(M.Address, M.Size, Protect); 165| 0| if (Result != 0) 166| 0| return std::error_code(errno, std::generic_category()); 167| 0| 168| 0| if (Flags & MF_EXEC) 169| 0| Memory::InvalidateInstructionCache(M.Address, M.Size); 170| 0| 171| 0| return std::error_code(); 172| 0|} 173| | 174| |/// AllocateRWX - Allocate a slab of memory with read/write/execute 175| |/// permissions. This is typically used for JIT applications where we want 176| |/// to emit code to the memory then jump to it. Getting this type of memory 177| |/// is very OS specific. 178| |/// 179| |MemoryBlock 180| |Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, 181| 0| std::string *ErrMsg) { 182| 0| if (NumBytes == 0) return MemoryBlock(); 183| 0| 184| 0| size_t PageSize = Process::getPageSize(); 185| 0| size_t NumPages = (NumBytes+PageSize-1)/PageSize; 186| 0| 187| 0| int fd = -1; 188| |#ifdef NEED_DEV_ZERO_FOR_MMAP 189| | static int zero_fd = open("/dev/zero", O_RDWR); 190| | if (zero_fd == -1) { 191| | MakeErrMsg(ErrMsg, "Can't open /dev/zero device"); 192| | return MemoryBlock(); 193| | } 194| | fd = zero_fd; 195| |#endif 196| | 197| 0| int flags = MAP_PRIVATE | 198| |#ifdef HAVE_MMAP_ANONYMOUS 199| | MAP_ANONYMOUS 200| |#else 201| | MAP_ANON 202| 0|#endif 203| 0| ; 204| 0| 205| 0| void* start = NearBlock ? (unsigned char*)NearBlock->base() + 206| 0| NearBlock->size() : nullptr; 207| 0| 208| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 209| | void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC, 210| | flags, fd, 0); 211| |#else 212| | void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, 213| 0| flags, fd, 0); 214| 0|#endif 215| 0| if (pa == MAP_FAILED) { 216| 0| if (NearBlock) //Try again without a near hint 217| 0| return AllocateRWX(NumBytes, nullptr); 218| 0| 219| 0| MakeErrMsg(ErrMsg, "Can't allocate RWX Memory"); 220| 0| return MemoryBlock(); 221| 0| } 222| 0| 223| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 224| | kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa, 225| | (vm_size_t)(PageSize*NumPages), 0, 226| | VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); 227| | if (KERN_SUCCESS != kr) { 228| | MakeErrMsg(ErrMsg, "vm_protect max RX failed"); 229| | return MemoryBlock(); 230| | } 231| | 232| | kr = vm_protect(mach_task_self(), (vm_address_t)pa, 233| | (vm_size_t)(PageSize*NumPages), 0, 234| | VM_PROT_READ | VM_PROT_WRITE); 235| | if (KERN_SUCCESS != kr) { 236| | MakeErrMsg(ErrMsg, "vm_protect RW failed"); 237| | return MemoryBlock(); 238| | } 239| |#endif 240| | 241| 0| MemoryBlock result; 242| 0| result.Address = pa; 243| 0| result.Size = NumPages*PageSize; 244| 0| 245| 0| return result; 246| 0|} 247| | 248| 0|bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { 249| 0| if (M.Address == nullptr || M.Size == 0) return false; 250| 0| if (0 != ::munmap(M.Address, M.Size)) 251| 0| return MakeErrMsg(ErrMsg, "Can't release RWX Memory"); 252| 0| return false; 253| 0|} 254| | 255| 0|bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { 256| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 257| | if (M.Address == 0 || M.Size == 0) return false; 258| | Memory::InvalidateInstructionCache(M.Address, M.Size); 259| | kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, 260| | (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE); 261| | return KERN_SUCCESS == kr; 262| |#else 263| | return true; 264| 0|#endif 265| 0|} 266| | 267| 0|bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { 268| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 269| | if (M.Address == 0 || M.Size == 0) return false; 270| | Memory::InvalidateInstructionCache(M.Address, M.Size); 271| | kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, 272| | (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); 273| | return KERN_SUCCESS == kr; 274| |#elif defined(__arm__) || defined(__aarch64__) 275| | Memory::InvalidateInstructionCache(M.Address, M.Size); 276| | return true; 277| |#else 278| | return true; 279| 0|#endif 280| 0|} 281| | 282| 0|bool Memory::setRangeWritable(const void *Addr, size_t Size) { 283| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 284| | kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, 285| | (vm_size_t)Size, 0, 286| | VM_PROT_READ | VM_PROT_WRITE); 287| | return KERN_SUCCESS == kr; 288| |#else 289| | return true; 290| 0|#endif 291| 0|} 292| | 293| 0|bool Memory::setRangeExecutable(const void *Addr, size_t Size) { 294| |#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 295| | kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, 296| | (vm_size_t)Size, 0, 297| | VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); 298| | return KERN_SUCCESS == kr; 299| |#else 300| | return true; 301| 0|#endif 302| 0|} 303| | 304| |/// InvalidateInstructionCache - Before the JIT can run a block of code 305| |/// that has been emitted it must invalidate the instruction cache on some 306| |/// platforms. 307| |void Memory::InvalidateInstructionCache(const void *Addr, 308| 0| size_t Len) { 309| 0| 310| 0|// icache invalidation for PPC and ARM. 311| 0|#if defined(__APPLE__) 312| 0| 313| |# if (defined(__POWERPC__) || defined (__ppc__) || \ 314| | defined(_POWER) || defined(_ARCH_PPC) || defined(__arm__) || \ 315| | defined(__arm64__)) 316| | sys_icache_invalidate(const_cast(Addr), Len); 317| |# endif 318| | 319| |#else 320| | 321| |# if (defined(__POWERPC__) || defined (__ppc__) || \ 322| | defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) 323| | const size_t LineSize = 32; 324| | 325| | const intptr_t Mask = ~(LineSize - 1); 326| | const intptr_t StartLine = ((intptr_t) Addr) & Mask; 327| | const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; 328| | 329| | for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) 330| | asm volatile("dcbf 0, %0" : : "r"(Line)); 331| | asm volatile("sync"); 332| | 333| | for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) 334| | asm volatile("icbi 0, %0" : : "r"(Line)); 335| | asm volatile("isync"); 336| |# elif (defined(__arm__) || defined(__aarch64__) || defined(__mips__)) && \ 337| | defined(__GNUC__) 338| | // FIXME: Can we safely always call this for __GNUC__ everywhere? 339| | const char *Start = static_cast(Addr); 340| | const char *End = Start + Len; 341| | __clear_cache(const_cast(Start), const_cast(End)); 342| |# endif 343| | 344| |#endif // end apple 345| | 346| 0| ValgrindDiscardTranslations(Addr, Len); 347| 0|} 348| | 349| |} // namespace sys 350| |} // namespace llvm /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Path.inc: 1| |//===- llvm/Support/Unix/Path.inc - Unix Path Implementation ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the Unix specific implementation of the Path API. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |//===----------------------------------------------------------------------===// 15| |//=== WARNING: Implementation here must contain only generic UNIX code that 16| |//=== is guaranteed to work on *all* UNIX variants. 17| |//===----------------------------------------------------------------------===// 18| | 19| |#include "Unix.h" 20| |#include 21| |#include 22| |#if HAVE_SYS_STAT_H 23| |#include 24| |#endif 25| |#if HAVE_FCNTL_H 26| |#include 27| |#endif 28| |#ifdef HAVE_SYS_MMAN_H 29| |#include 30| |#endif 31| |#if HAVE_DIRENT_H 32| |# include 33| 0|# define NAMLEN(dirent) strlen((dirent)->d_name) 34| |#else 35| |# define dirent direct 36| |# define NAMLEN(dirent) (dirent)->d_namlen 37| |# if HAVE_SYS_NDIR_H 38| |# include 39| |# endif 40| |# if HAVE_SYS_DIR_H 41| |# include 42| |# endif 43| |# if HAVE_NDIR_H 44| |# include 45| |# endif 46| |#endif 47| | 48| |#ifdef __APPLE__ 49| |#include 50| |#endif 51| | 52| |// Both stdio.h and cstdio are included via different pathes and 53| |// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros 54| |// either. 55| |#undef ferror 56| |#undef feof 57| | 58| |// For GNU Hurd 59| |#if defined(__GNU__) && !defined(PATH_MAX) 60| |# define PATH_MAX 4096 61| |#endif 62| | 63| |using namespace llvm; 64| | 65| |namespace llvm { 66| |namespace sys { 67| |namespace fs { 68| |#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 69| | defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ 70| | defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) 71| |static int 72| |test_dir(char ret[PATH_MAX], const char *dir, const char *bin) 73| |{ 74| | struct stat sb; 75| | char fullpath[PATH_MAX]; 76| | 77| | snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); 78| | if (realpath(fullpath, ret) == NULL) 79| | return (1); 80| | if (stat(fullpath, &sb) != 0) 81| | return (1); 82| | 83| | return (0); 84| |} 85| | 86| |static char * 87| |getprogpath(char ret[PATH_MAX], const char *bin) 88| |{ 89| | char *pv, *s, *t; 90| | 91| | /* First approach: absolute path. */ 92| | if (bin[0] == '/') { 93| | if (test_dir(ret, "/", bin) == 0) 94| | return (ret); 95| | return (NULL); 96| | } 97| | 98| | /* Second approach: relative path. */ 99| | if (strchr(bin, '/') != NULL) { 100| | char cwd[PATH_MAX]; 101| | if (getcwd(cwd, PATH_MAX) == NULL) 102| | return (NULL); 103| | if (test_dir(ret, cwd, bin) == 0) 104| | return (ret); 105| | return (NULL); 106| | } 107| | 108| | /* Third approach: $PATH */ 109| | if ((pv = getenv("PATH")) == NULL) 110| | return (NULL); 111| | s = pv = strdup(pv); 112| | if (pv == NULL) 113| | return (NULL); 114| | while ((t = strsep(&s, ":")) != NULL) { 115| | if (test_dir(ret, t, bin) == 0) { 116| | free(pv); 117| | return (ret); 118| | } 119| | } 120| | free(pv); 121| | return (NULL); 122| |} 123| |#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 124| | 125| |/// GetMainExecutable - Return the path to the main executable, given the 126| |/// value of argv[0] from program startup. 127| 0|std::string getMainExecutable(const char *argv0, void *MainAddr) { 128| 0|#if defined(__APPLE__) 129| 0| // On OS X the executable path is saved to the stack by dyld. Reading it 130| 0| // from there is much faster than calling dladdr, especially for large 131| 0| // binaries with symbols. 132| 0| char exe_path[MAXPATHLEN]; 133| 0| uint32_t size = sizeof(exe_path); 134| 0| if (_NSGetExecutablePath(exe_path, &size) == 0) { 135| 0| char link_path[MAXPATHLEN]; 136| 0| if (realpath(exe_path, link_path)) 137| 0| return link_path; 138| 0| } 139| |#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 140| | defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \ 141| | defined(__FreeBSD_kernel__) 142| | char exe_path[PATH_MAX]; 143| | 144| | if (getprogpath(exe_path, argv0) != NULL) 145| | return exe_path; 146| |#elif defined(__linux__) || defined(__CYGWIN__) 147| | char exe_path[MAXPATHLEN]; 148| | StringRef aPath("/proc/self/exe"); 149| | if (sys::fs::exists(aPath)) { 150| | // /proc is not always mounted under Linux (chroot for example). 151| | ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 152| | if (len >= 0) 153| | return std::string(exe_path, len); 154| | } else { 155| | // Fall back to the classical detection. 156| | if (getprogpath(exe_path, argv0) != NULL) 157| | return exe_path; 158| | } 159| |#elif defined(HAVE_DLFCN_H) 160| | // Use dladdr to get executable path if available. 161| | Dl_info DLInfo; 162| | int err = dladdr(MainAddr, &DLInfo); 163| | if (err == 0) 164| | return ""; 165| | 166| | // If the filename is a symlink, we need to resolve and return the location of 167| | // the actual executable. 168| | char link_path[MAXPATHLEN]; 169| | if (realpath(DLInfo.dli_fname, link_path)) 170| | return link_path; 171| |#else 172| |#error GetMainExecutable is not implemented on this host yet. 173| |#endif 174| 0| return ""; 175| 0|} 176| | 177| 0|TimeValue file_status::getLastModificationTime() const { 178| 0| TimeValue Ret; 179| 0| Ret.fromEpochTime(fs_st_mtime); 180| 0| return Ret; 181| 0|} 182| | 183| 0|UniqueID file_status::getUniqueID() const { 184| 0| return UniqueID(fs_st_dev, fs_st_ino); 185| 0|} 186| | 187| 0|std::error_code current_path(SmallVectorImpl &result) { 188| 0| result.clear(); 189| 0| 190| 0| const char *pwd = ::getenv("PWD"); 191| 0| llvm::sys::fs::file_status PWDStatus, DotStatus; 192| 0| if (pwd && llvm::sys::path::is_absolute(pwd) && 193| 0| !llvm::sys::fs::status(pwd, PWDStatus) && 194| 0| !llvm::sys::fs::status(".", DotStatus) && 195| 0| PWDStatus.getUniqueID() == DotStatus.getUniqueID()) { 196| 0| result.append(pwd, pwd + strlen(pwd)); 197| 0| return std::error_code(); 198| 0| } 199| 0| 200| 0|#ifdef MAXPATHLEN 201| 0| result.reserve(MAXPATHLEN); 202| |#else 203| |// For GNU Hurd 204| | result.reserve(1024); 205| |#endif 206| | 207| 0| while (true) { 208| 0| if (::getcwd(result.data(), result.capacity()) == nullptr) { 209| 0| // See if there was a real error. 210| 0| if (errno != ENOMEM) 211| 0| return std::error_code(errno, std::generic_category()); 212| 0| // Otherwise there just wasn't enough space. 213| 0| result.reserve(result.capacity() * 2); 214| 0| } else 215| 0| break; 216| 0| } 217| 0| 218| 0| result.set_size(strlen(result.data())); 219| 0| return std::error_code(); 220| 0|} 221| | 222| 0|std::error_code create_directory(const Twine &path, bool IgnoreExisting) { 223| 0| SmallString<128> path_storage; 224| 0| StringRef p = path.toNullTerminatedStringRef(path_storage); 225| 0| 226| 0| if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { 227| 0| if (errno != EEXIST || !IgnoreExisting) 228| 0| return std::error_code(errno, std::generic_category()); 229| 0| } 230| 0| 231| 0| return std::error_code(); 232| 0|} 233| | 234| |// Note that we are using symbolic link because hard links are not supported by 235| |// all filesystems (SMB doesn't). 236| 0|std::error_code create_link(const Twine &to, const Twine &from) { 237| 0| // Get arguments. 238| 0| SmallString<128> from_storage; 239| 0| SmallString<128> to_storage; 240| 0| StringRef f = from.toNullTerminatedStringRef(from_storage); 241| 0| StringRef t = to.toNullTerminatedStringRef(to_storage); 242| 0| 243| 0| if (::symlink(t.begin(), f.begin()) == -1) 244| 0| return std::error_code(errno, std::generic_category()); 245| 0| 246| 0| return std::error_code(); 247| 0|} 248| | 249| 0|std::error_code remove(const Twine &path, bool IgnoreNonExisting) { 250| 0| SmallString<128> path_storage; 251| 0| StringRef p = path.toNullTerminatedStringRef(path_storage); 252| 0| 253| 0| struct stat buf; 254| 0| if (lstat(p.begin(), &buf) != 0) { 255| 0| if (errno != ENOENT || !IgnoreNonExisting) 256| 0| return std::error_code(errno, std::generic_category()); 257| 0| return std::error_code(); 258| 0| } 259| 0| 260| 0| // Note: this check catches strange situations. In all cases, LLVM should 261| 0| // only be involved in the creation and deletion of regular files. This 262| 0| // check ensures that what we're trying to erase is a regular file. It 263| 0| // effectively prevents LLVM from erasing things like /dev/null, any block 264| 0| // special file, or other things that aren't "regular" files. 265| 0| if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode)) 266| 0| return make_error_code(errc::operation_not_permitted); 267| 0| 268| 0| if (::remove(p.begin()) == -1) { 269| 0| if (errno != ENOENT || !IgnoreNonExisting) 270| 0| return std::error_code(errno, std::generic_category()); 271| 0| } 272| 0| 273| 0| return std::error_code(); 274| 0|} 275| | 276| 0|std::error_code rename(const Twine &from, const Twine &to) { 277| 0| // Get arguments. 278| 0| SmallString<128> from_storage; 279| 0| SmallString<128> to_storage; 280| 0| StringRef f = from.toNullTerminatedStringRef(from_storage); 281| 0| StringRef t = to.toNullTerminatedStringRef(to_storage); 282| 0| 283| 0| if (::rename(f.begin(), t.begin()) == -1) 284| 0| return std::error_code(errno, std::generic_category()); 285| 0| 286| 0| return std::error_code(); 287| 0|} 288| | 289| 0|std::error_code resize_file(int FD, uint64_t Size) { 290| 0| if (::ftruncate(FD, Size) == -1) 291| 0| return std::error_code(errno, std::generic_category()); 292| 0| 293| 0| return std::error_code(); 294| 0|} 295| | 296| 0|static int convertAccessMode(AccessMode Mode) { 297| 0| switch (Mode) { 298| 0| case AccessMode::Exist: 299| 0| return F_OK; 300| 0| case AccessMode::Write: 301| 0| return W_OK; 302| 0| case AccessMode::Execute: 303| 0| return R_OK | X_OK; // scripts also need R_OK. 304| 0| } 305| 0| llvm_unreachable("invalid enum"); 306| 0|} 307| | 308| 0|std::error_code access(const Twine &Path, AccessMode Mode) { 309| 0| SmallString<128> PathStorage; 310| 0| StringRef P = Path.toNullTerminatedStringRef(PathStorage); 311| 0| 312| 0| if (::access(P.begin(), convertAccessMode(Mode)) == -1) 313| 0| return std::error_code(errno, std::generic_category()); 314| 0| 315| 0| if (Mode == AccessMode::Execute) { 316| 0| // Don't say that directories are executable. 317| 0| struct stat buf; 318| 0| if (0 != stat(P.begin(), &buf)) 319| 0| return errc::permission_denied; 320| 0| if (!S_ISREG(buf.st_mode)) 321| 0| return errc::permission_denied; 322| 0| } 323| 0| 324| 0| return std::error_code(); 325| 0|} 326| | 327| 0|bool equivalent(file_status A, file_status B) { 328| 0| assert(status_known(A) && status_known(B)); 329| 0| return A.fs_st_dev == B.fs_st_dev && 330| 0| A.fs_st_ino == B.fs_st_ino; 331| 0|} 332| | 333| 0|std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 334| 0| file_status fsA, fsB; 335| 0| if (std::error_code ec = status(A, fsA)) 336| 0| return ec; 337| 0| if (std::error_code ec = status(B, fsB)) 338| 0| return ec; 339| 0| result = equivalent(fsA, fsB); 340| 0| return std::error_code(); 341| 0|} 342| | 343| |static std::error_code fillStatus(int StatRet, const struct stat &Status, 344| 0| file_status &Result) { 345| 0| if (StatRet != 0) { 346| 0| std::error_code ec(errno, std::generic_category()); 347| 0| if (ec == errc::no_such_file_or_directory) 348| 0| Result = file_status(file_type::file_not_found); 349| 0| else 350| 0| Result = file_status(file_type::status_error); 351| 0| return ec; 352| 0| } 353| 0| 354| 0| file_type Type = file_type::type_unknown; 355| 0| 356| 0| if (S_ISDIR(Status.st_mode)) 357| 0| Type = file_type::directory_file; 358| 0| else if (S_ISREG(Status.st_mode)) 359| 0| Type = file_type::regular_file; 360| 0| else if (S_ISBLK(Status.st_mode)) 361| 0| Type = file_type::block_file; 362| 0| else if (S_ISCHR(Status.st_mode)) 363| 0| Type = file_type::character_file; 364| 0| else if (S_ISFIFO(Status.st_mode)) 365| 0| Type = file_type::fifo_file; 366| 0| else if (S_ISSOCK(Status.st_mode)) 367| 0| Type = file_type::socket_file; 368| 0| 369| 0| perms Perms = static_cast(Status.st_mode); 370| 0| Result = 371| 0| file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime, 372| 0| Status.st_uid, Status.st_gid, Status.st_size); 373| 0| 374| 0| return std::error_code(); 375| 0|} 376| | 377| 0|std::error_code status(const Twine &Path, file_status &Result) { 378| 0| SmallString<128> PathStorage; 379| 0| StringRef P = Path.toNullTerminatedStringRef(PathStorage); 380| 0| 381| 0| struct stat Status; 382| 0| int StatRet = ::stat(P.begin(), &Status); 383| 0| return fillStatus(StatRet, Status, Result); 384| 0|} 385| | 386| 0|std::error_code status(int FD, file_status &Result) { 387| 0| struct stat Status; 388| 0| int StatRet = ::fstat(FD, &Status); 389| 0| return fillStatus(StatRet, Status, Result); 390| 0|} 391| | 392| 0|std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { 393| |#if defined(HAVE_FUTIMENS) 394| | timespec Times[2]; 395| | Times[0].tv_sec = Time.toEpochTime(); 396| | Times[0].tv_nsec = 0; 397| | Times[1] = Times[0]; 398| | if (::futimens(FD, Times)) 399| | return std::error_code(errno, std::generic_category()); 400| | return std::error_code(); 401| |#elif defined(HAVE_FUTIMES) 402| | timeval Times[2]; 403| 0| Times[0].tv_sec = Time.toEpochTime(); 404| 0| Times[0].tv_usec = 0; 405| 0| Times[1] = Times[0]; 406| 0| if (::futimes(FD, Times)) 407| 0| return std::error_code(errno, std::generic_category()); 408| 0| return std::error_code(); 409| |#else 410| |#warning Missing futimes() and futimens() 411| | return make_error_code(errc::function_not_supported); 412| |#endif 413| |} 414| | 415| |std::error_code mapped_file_region::init(int FD, uint64_t Offset, 416| 0| mapmode Mode) { 417| 0| assert(Size != 0); 418| 0| 419| 0| int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 420| 0| int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 421| 0| Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 422| 0| if (Mapping == MAP_FAILED) 423| 0| return std::error_code(errno, std::generic_category()); 424| 0| return std::error_code(); 425| 0|} 426| | 427| |mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, 428| | uint64_t offset, std::error_code &ec) 429| 0| : Size(length), Mapping() { 430| 0| // Make sure that the requested size fits within SIZE_T. 431| 0| if (length > std::numeric_limits::max()) { 432| 0| ec = make_error_code(errc::invalid_argument); 433| 0| return; 434| 0| } 435| 0| 436| 0| ec = init(fd, offset, mode); 437| 0| if (ec) 438| 0| Mapping = nullptr; 439| 0|} 440| | 441| 0|mapped_file_region::~mapped_file_region() { 442| 0| if (Mapping) 443| 0| ::munmap(Mapping, Size); 444| 0|} 445| | 446| 0|uint64_t mapped_file_region::size() const { 447| 0| assert(Mapping && "Mapping failed but used anyway!"); 448| 0| return Size; 449| 0|} 450| | 451| 0|char *mapped_file_region::data() const { 452| 0| assert(Mapping && "Mapping failed but used anyway!"); 453| 0| return reinterpret_cast(Mapping); 454| 0|} 455| | 456| 0|const char *mapped_file_region::const_data() const { 457| 0| assert(Mapping && "Mapping failed but used anyway!"); 458| 0| return reinterpret_cast(Mapping); 459| 0|} 460| | 461| 0|int mapped_file_region::alignment() { 462| 0| return Process::getPageSize(); 463| 0|} 464| | 465| |std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 466| 0| StringRef path){ 467| 0| SmallString<128> path_null(path); 468| 0| DIR *directory = ::opendir(path_null.c_str()); 469| 0| if (!directory) 470| 0| return std::error_code(errno, std::generic_category()); 471| 0| 472| 0| it.IterationHandle = reinterpret_cast(directory); 473| 0| // Add something for replace_filename to replace. 474| 0| path::append(path_null, "."); 475| 0| it.CurrentEntry = directory_entry(path_null.str()); 476| 0| return directory_iterator_increment(it); 477| 0|} 478| | 479| 0|std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 480| 0| if (it.IterationHandle) 481| 0| ::closedir(reinterpret_cast(it.IterationHandle)); 482| 0| it.IterationHandle = 0; 483| 0| it.CurrentEntry = directory_entry(); 484| 0| return std::error_code(); 485| 0|} 486| | 487| 0|std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { 488| 0| errno = 0; 489| 0| dirent *cur_dir = ::readdir(reinterpret_cast(it.IterationHandle)); 490| 0| if (cur_dir == nullptr && errno != 0) { 491| 0| return std::error_code(errno, std::generic_category()); 492| 0| } else if (cur_dir != nullptr) { 493| 0| StringRef name(cur_dir->d_name, NAMLEN(cur_dir)); 494| 0| if ((name.size() == 1 && name[0] == '.') || 495| 0| (name.size() == 2 && name[0] == '.' && name[1] == '.')) 496| 0| return directory_iterator_increment(it); 497| 0| it.CurrentEntry.replace_filename(name); 498| 0| } else 499| 0| return directory_iterator_destruct(it); 500| 0| 501| 0| return std::error_code(); 502| 0|} 503| | 504| 0|std::error_code openFileForRead(const Twine &Name, int &ResultFD) { 505| 0| SmallString<128> Storage; 506| 0| StringRef P = Name.toNullTerminatedStringRef(Storage); 507| 0| while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) { 508| 0| if (errno != EINTR) 509| 0| return std::error_code(errno, std::generic_category()); 510| 0| } 511| 0| return std::error_code(); 512| 0|} 513| | 514| |std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 515| 0| sys::fs::OpenFlags Flags, unsigned Mode) { 516| 0| // Verify that we don't have both "append" and "excl". 517| 0| assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && 518| 0| "Cannot specify both 'excl' and 'append' file creation flags!"); 519| 0| 520| 0| int OpenFlags = O_CREAT; 521| 0| 522| 0| if (Flags & F_RW) 523| 0| OpenFlags |= O_RDWR; 524| 0| else 525| 0| OpenFlags |= O_WRONLY; 526| 0| 527| 0| if (Flags & F_Append) 528| 0| OpenFlags |= O_APPEND; 529| 0| else 530| 0| OpenFlags |= O_TRUNC; 531| 0| 532| 0| if (Flags & F_Excl) 533| 0| OpenFlags |= O_EXCL; 534| 0| 535| 0| SmallString<128> Storage; 536| 0| StringRef P = Name.toNullTerminatedStringRef(Storage); 537| 0| while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) { 538| 0| if (errno != EINTR) 539| 0| return std::error_code(errno, std::generic_category()); 540| 0| } 541| 0| return std::error_code(); 542| 0|} 543| | 544| |} // end namespace fs 545| | 546| |namespace path { 547| | 548| 0|bool home_directory(SmallVectorImpl &result) { 549| 0| if (char *RequestedDir = getenv("HOME")) { 550| 0| result.clear(); 551| 0| result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 552| 0| return true; 553| 0| } 554| 0| 555| 0| return false; 556| 0|} 557| | 558| 0|static const char *getEnvTempDir() { 559| 0| // Check whether the temporary directory is specified by an environment 560| 0| // variable. 561| 0| const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 562| 0| for (const char *Env : EnvironmentVariables) { 563| 0| if (const char *Dir = std::getenv(Env)) 564| 0| return Dir; 565| 0| } 566| 0| 567| 0| return nullptr; 568| 0|} 569| | 570| 0|static const char *getDefaultTempDir(bool ErasedOnReboot) { 571| 0|#ifdef P_tmpdir 572| 0| if ((bool)P_tmpdir) 573| 0| return P_tmpdir; 574| 0|#endif 575| 0| 576| 0| if (ErasedOnReboot) 577| 0| return "/tmp"; 578| 0| return "/var/tmp"; 579| 0|} 580| | 581| 0|void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl &Result) { 582| 0| Result.clear(); 583| 0| 584| 0| if (ErasedOnReboot) { 585| 0| // There is no env variable for the cache directory. 586| 0| if (const char *RequestedDir = getEnvTempDir()) { 587| 0| Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 588| 0| return; 589| 0| } 590| 0| } 591| 0| 592| 0|#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 593| 0| // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 594| 0| // macros defined in on darwin >= 9 595| 0| int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR 596| 0| : _CS_DARWIN_USER_CACHE_DIR; 597| 0| size_t ConfLen = confstr(ConfName, nullptr, 0); 598| 0| if (ConfLen > 0) { 599| 0| do { 600| 0| Result.resize(ConfLen); 601| 0| ConfLen = confstr(ConfName, Result.data(), Result.size()); 602| 0| } while (ConfLen > 0 && ConfLen != Result.size()); 603| 0| 604| 0| if (ConfLen > 0) { 605| 0| assert(Result.back() == 0); 606| 0| Result.pop_back(); 607| 0| return; 608| 0| } 609| 0| 610| 0| Result.clear(); 611| 0| } 612| 0|#endif 613| 0| 614| 0| const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 615| 0| Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 616| 0|} 617| | 618| |} // end namespace path 619| | 620| |} // end namespace sys 621| |} // end namespace llvm /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Process.inc: 1| |//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides the generic Unix implementation of the Process class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "Unix.h" 15| |#include "llvm/ADT/Hashing.h" 16| |#include "llvm/ADT/StringRef.h" 17| |#include "llvm/Support/ManagedStatic.h" 18| |#include "llvm/Support/Mutex.h" 19| |#include "llvm/Support/MutexGuard.h" 20| |#include "llvm/Support/TimeValue.h" 21| |#if HAVE_FCNTL_H 22| |#include 23| |#endif 24| |#ifdef HAVE_SYS_TIME_H 25| |#include 26| |#endif 27| |#ifdef HAVE_SYS_RESOURCE_H 28| |#include 29| |#endif 30| |#ifdef HAVE_SYS_STAT_H 31| |#include 32| |#endif 33| |#if HAVE_SIGNAL_H 34| |#include 35| |#endif 36| |// DragonFlyBSD, FreeBSD, OpenBSD, and Bitrig have deprecated for 37| |// instead. Unix.h includes this for us already. 38| |#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \ 39| | !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__Bitrig__) 40| |#include 41| |#endif 42| |#if defined(HAVE_MALLCTL) 43| |#include 44| |#endif 45| |#ifdef HAVE_MALLOC_MALLOC_H 46| |#include 47| |#endif 48| |#ifdef HAVE_SYS_IOCTL_H 49| |# include 50| |#endif 51| |#ifdef HAVE_TERMIOS_H 52| |# include 53| |#endif 54| | 55| |//===----------------------------------------------------------------------===// 56| |//=== WARNING: Implementation here must contain only generic UNIX code that 57| |//=== is guaranteed to work on *all* UNIX variants. 58| |//===----------------------------------------------------------------------===// 59| | 60| |using namespace llvm; 61| |using namespace sys; 62| | 63| 0|static std::pair getRUsageTimes() { 64| 0|#if defined(HAVE_GETRUSAGE) 65| 0| struct rusage RU; 66| 0| ::getrusage(RUSAGE_SELF, &RU); 67| 0| return std::make_pair( 68| 0| TimeValue( 69| 0| static_cast(RU.ru_utime.tv_sec), 70| 0| static_cast( 71| 0| RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), 72| 0| TimeValue( 73| 0| static_cast(RU.ru_stime.tv_sec), 74| 0| static_cast( 75| 0| RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); 76| |#else 77| |#warning Cannot get usage times on this platform 78| | return std::make_pair(TimeValue(), TimeValue()); 79| |#endif 80| |} 81| | 82| |// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and 83| |// offset in mmap(3) should be aligned to the AllocationGranularity. 84| 0|unsigned Process::getPageSize() { 85| 0|#if defined(HAVE_GETPAGESIZE) 86| 0| static const int page_size = ::getpagesize(); 87| |#elif defined(HAVE_SYSCONF) 88| | static long page_size = ::sysconf(_SC_PAGE_SIZE); 89| |#else 90| |#warning Cannot get the page size on this machine 91| |#endif 92| | return static_cast(page_size); 93| 0|} 94| | 95| 0|size_t Process::GetMallocUsage() { 96| |#if defined(HAVE_MALLINFO) 97| | struct mallinfo mi; 98| | mi = ::mallinfo(); 99| | return mi.uordblks; 100| |#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) 101| | malloc_statistics_t Stats; 102| 0| malloc_zone_statistics(malloc_default_zone(), &Stats); 103| 0| return Stats.size_in_use; // darwin 104| |#elif defined(HAVE_MALLCTL) 105| | size_t alloc, sz; 106| | sz = sizeof(size_t); 107| | if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0) 108| | return alloc; 109| | return 0; 110| |#elif defined(HAVE_SBRK) 111| | // Note this is only an approximation and more closely resembles 112| | // the value returned by mallinfo in the arena field. 113| | static char *StartOfMemory = reinterpret_cast(::sbrk(0)); 114| | char *EndOfMemory = (char*)sbrk(0); 115| | if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1)) 116| | return EndOfMemory - StartOfMemory; 117| | return 0; 118| |#else 119| |#warning Cannot get malloc info on this platform 120| | return 0; 121| |#endif 122| |} 123| | 124| |void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, 125| 0| TimeValue &sys_time) { 126| 0| elapsed = TimeValue::now(); 127| 0| std::tie(user_time, sys_time) = getRUsageTimes(); 128| 0|} 129| | 130| |#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__) 131| |#include 132| |#endif 133| | 134| |// Some LLVM programs such as bugpoint produce core files as a normal part of 135| |// their operation. To prevent the disk from filling up, this function 136| |// does what's necessary to prevent their generation. 137| 0|void Process::PreventCoreFiles() { 138| 0|#if HAVE_SETRLIMIT 139| 0| struct rlimit rlim; 140| 0| rlim.rlim_cur = rlim.rlim_max = 0; 141| 0| setrlimit(RLIMIT_CORE, &rlim); 142| 0|#endif 143| 0| 144| 0|#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__) 145| 0| // Disable crash reporting on Mac OS X 10.0-10.4 146| 0| 147| 0| // get information about the original set of exception ports for the task 148| 0| mach_msg_type_number_t Count = 0; 149| 0| exception_mask_t OriginalMasks[EXC_TYPES_COUNT]; 150| 0| exception_port_t OriginalPorts[EXC_TYPES_COUNT]; 151| 0| exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT]; 152| 0| thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT]; 153| 0| kern_return_t err = 154| 0| task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks, 155| 0| &Count, OriginalPorts, OriginalBehaviors, 156| 0| OriginalFlavors); 157| 0| if (err == KERN_SUCCESS) { 158| 0| // replace each with MACH_PORT_NULL. 159| 0| for (unsigned i = 0; i != Count; ++i) 160| 0| task_set_exception_ports(mach_task_self(), OriginalMasks[i], 161| 0| MACH_PORT_NULL, OriginalBehaviors[i], 162| 0| OriginalFlavors[i]); 163| 0| } 164| 0| 165| 0| // Disable crash reporting on Mac OS X 10.5 166| 0| signal(SIGABRT, _exit); 167| 0| signal(SIGILL, _exit); 168| 0| signal(SIGFPE, _exit); 169| 0| signal(SIGSEGV, _exit); 170| 0| signal(SIGBUS, _exit); 171| 0|#endif 172| 0|} 173| | 174| 0|Optional Process::GetEnv(StringRef Name) { 175| 0| std::string NameStr = Name.str(); 176| 0| const char *Val = ::getenv(NameStr.c_str()); 177| 0| if (!Val) 178| 0| return None; 179| 0| return std::string(Val); 180| 0|} 181| | 182| |std::error_code 183| |Process::GetArgumentVector(SmallVectorImpl &ArgsOut, 184| | ArrayRef ArgsIn, 185| 0| SpecificBumpPtrAllocator &) { 186| 0| ArgsOut.append(ArgsIn.begin(), ArgsIn.end()); 187| 0| 188| 0| return std::error_code(); 189| 0|} 190| | 191| |namespace { 192| |class FDCloser { 193| |public: 194| 0| FDCloser(int &FD) : FD(FD), KeepOpen(false) {} 195| 0| void keepOpen() { KeepOpen = true; } 196| 0| ~FDCloser() { 197| 0| if (!KeepOpen && FD >= 0) 198| 0| ::close(FD); 199| 0| } 200| | 201| |private: 202| | FDCloser(const FDCloser &) = delete; 203| | void operator=(const FDCloser &) = delete; 204| | 205| | int &FD; 206| | bool KeepOpen; 207| |}; 208| |} 209| | 210| 0|std::error_code Process::FixupStandardFileDescriptors() { 211| 0| int NullFD = -1; 212| 0| FDCloser FDC(NullFD); 213| 0| const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; 214| 0| for (int StandardFD : StandardFDs) { 215| 0| struct stat st; 216| 0| errno = 0; 217| 0| while (fstat(StandardFD, &st) < 0) { 218| 0| assert(errno && "expected errno to be set if fstat failed!"); 219| 0| // fstat should return EBADF if the file descriptor is closed. 220| 0| if (errno == EBADF) 221| 0| break; 222| 0| // retry fstat if we got EINTR, otherwise bubble up the failure. 223| 0| if (errno != EINTR) 224| 0| return std::error_code(errno, std::generic_category()); 225| 0| } 226| 0| // if fstat succeeds, move on to the next FD. 227| 0| if (!errno) 228| 0| continue; 229| 0| assert(errno == EBADF && "expected errno to have EBADF at this point!"); 230| 0| 231| 0| if (NullFD < 0) { 232| 0| while ((NullFD = open("/dev/null", O_RDWR)) < 0) { 233| 0| if (errno == EINTR) 234| 0| continue; 235| 0| return std::error_code(errno, std::generic_category()); 236| 0| } 237| 0| } 238| 0| 239| 0| if (NullFD == StandardFD) 240| 0| FDC.keepOpen(); 241| 0| else if (dup2(NullFD, StandardFD) < 0) 242| 0| return std::error_code(errno, std::generic_category()); 243| 0| } 244| 0| return std::error_code(); 245| 0|} 246| | 247| 0|std::error_code Process::SafelyCloseFileDescriptor(int FD) { 248| 0| // Create a signal set filled with *all* signals. 249| 0| sigset_t FullSet; 250| 0| if (sigfillset(&FullSet) < 0) 251| 0| return std::error_code(errno, std::generic_category()); 252| 0| // Atomically swap our current signal mask with a full mask. 253| 0| sigset_t SavedSet; 254| 0|#if LLVM_ENABLE_THREADS 255| 0| if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) 256| 0| return std::error_code(EC, std::generic_category()); 257| |#else 258| | if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0) 259| | return std::error_code(errno, std::generic_category()); 260| |#endif 261| | // Attempt to close the file descriptor. 262| 0| // We need to save the error, if one occurs, because our subsequent call to 263| 0| // pthread_sigmask might tamper with errno. 264| 0| int ErrnoFromClose = 0; 265| 0| if (::close(FD) < 0) 266| 0| ErrnoFromClose = errno; 267| 0| // Restore the signal mask back to what we saved earlier. 268| 0| int EC = 0; 269| 0|#if LLVM_ENABLE_THREADS 270| 0| EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr); 271| |#else 272| | if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0) 273| | EC = errno; 274| |#endif 275| | // The error code from close takes precedence over the one from 276| 0| // pthread_sigmask. 277| 0| if (ErrnoFromClose) 278| 0| return std::error_code(ErrnoFromClose, std::generic_category()); 279| 0| return std::error_code(EC, std::generic_category()); 280| 0|} 281| | 282| 0|bool Process::StandardInIsUserInput() { 283| 0| return FileDescriptorIsDisplayed(STDIN_FILENO); 284| 0|} 285| | 286| 0|bool Process::StandardOutIsDisplayed() { 287| 0| return FileDescriptorIsDisplayed(STDOUT_FILENO); 288| 0|} 289| | 290| 0|bool Process::StandardErrIsDisplayed() { 291| 0| return FileDescriptorIsDisplayed(STDERR_FILENO); 292| 0|} 293| | 294| 0|bool Process::FileDescriptorIsDisplayed(int fd) { 295| 0|#if HAVE_ISATTY 296| 0| return isatty(fd); 297| |#else 298| | // If we don't have isatty, just return false. 299| | return false; 300| |#endif 301| |} 302| | 303| 0|static unsigned getColumns(int FileID) { 304| 0| // If COLUMNS is defined in the environment, wrap to that many columns. 305| 0| if (const char *ColumnsStr = std::getenv("COLUMNS")) { 306| 0| int Columns = std::atoi(ColumnsStr); 307| 0| if (Columns > 0) 308| 0| return Columns; 309| 0| } 310| 0| 311| 0| unsigned Columns = 0; 312| 0| 313| 0|#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) 314| 0| // Try to determine the width of the terminal. 315| 0| struct winsize ws; 316| 0| if (ioctl(FileID, TIOCGWINSZ, &ws) == 0) 317| 0| Columns = ws.ws_col; 318| 0|#endif 319| 0| 320| 0| return Columns; 321| 0|} 322| | 323| 0|unsigned Process::StandardOutColumns() { 324| 0| if (!StandardOutIsDisplayed()) 325| 0| return 0; 326| 0| 327| 0| return getColumns(1); 328| 0|} 329| | 330| 0|unsigned Process::StandardErrColumns() { 331| 0| if (!StandardErrIsDisplayed()) 332| 0| return 0; 333| 0| 334| 0| return getColumns(2); 335| 0|} 336| | 337| |#ifdef HAVE_TERMINFO 338| |// We manually declare these extern functions because finding the correct 339| |// headers from various terminfo, curses, or other sources is harder than 340| |// writing their specs down. 341| |extern "C" int setupterm(char *term, int filedes, int *errret); 342| |extern "C" struct term *set_curterm(struct term *termp); 343| |extern "C" int del_curterm(struct term *termp); 344| |extern "C" int tigetnum(char *capname); 345| |#endif 346| | 347| |#ifdef HAVE_TERMINFO 348| |static ManagedStatic TermColorMutex; 349| |#endif 350| | 351| 0|static bool terminalHasColors(int fd) { 352| 0|#ifdef HAVE_TERMINFO 353| 0| // First, acquire a global lock because these C routines are thread hostile. 354| 0| MutexGuard G(*TermColorMutex); 355| 0| 356| 0| int errret = 0; 357| 0| if (setupterm((char *)nullptr, fd, &errret) != 0) 358| 0| // Regardless of why, if we can't get terminfo, we shouldn't try to print 359| 0| // colors. 360| 0| return false; 361| 0| 362| 0| // Test whether the terminal as set up supports color output. How to do this 363| 0| // isn't entirely obvious. We can use the curses routine 'has_colors' but it 364| 0| // would be nice to avoid a dependency on curses proper when we can make do 365| 0| // with a minimal terminfo parsing library. Also, we don't really care whether 366| 0| // the terminal supports the curses-specific color changing routines, merely 367| 0| // if it will interpret ANSI color escape codes in a reasonable way. Thus, the 368| 0| // strategy here is just to query the baseline colors capability and if it 369| 0| // supports colors at all to assume it will translate the escape codes into 370| 0| // whatever range of colors it does support. We can add more detailed tests 371| 0| // here if users report them as necessary. 372| 0| // 373| 0| // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if 374| 0| // the terminfo says that no colors are supported. 375| 0| bool HasColors = tigetnum(const_cast("colors")) > 0; 376| 0| 377| 0| // Now extract the structure allocated by setupterm and free its memory 378| 0| // through a really silly dance. 379| 0| struct term *termp = set_curterm((struct term *)nullptr); 380| 0| (void)del_curterm(termp); // Drop any errors here. 381| 0| 382| 0| // Return true if we found a color capabilities for the current terminal. 383| 0| if (HasColors) 384| 0| return true; 385| 0|#endif 386| 0| 387| 0| // Otherwise, be conservative. 388| 0| return false; 389| 0|} 390| | 391| 0|bool Process::FileDescriptorHasColors(int fd) { 392| 0| // A file descriptor has colors if it is displayed and the terminal has 393| 0| // colors. 394| 0| return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd); 395| 0|} 396| | 397| 0|bool Process::StandardOutHasColors() { 398| 0| return FileDescriptorHasColors(STDOUT_FILENO); 399| 0|} 400| | 401| 0|bool Process::StandardErrHasColors() { 402| 0| return FileDescriptorHasColors(STDERR_FILENO); 403| 0|} 404| | 405| 0|void Process::UseANSIEscapeCodes(bool /*enable*/) { 406| 0| // No effect. 407| 0|} 408| | 409| 0|bool Process::ColorNeedsFlush() { 410| 0| // No, we use ANSI escape sequences. 411| 0| return false; 412| 0|} 413| | 414| 0|const char *Process::OutputColor(char code, bool bold, bool bg) { 415| 0| return colorcodes[bg?1:0][bold?1:0][code&7]; 416| 0|} 417| | 418| 0|const char *Process::OutputBold(bool bg) { 419| 0| return "\033[1m"; 420| 0|} 421| | 422| 0|const char *Process::OutputReverse() { 423| 0| return "\033[7m"; 424| 0|} 425| | 426| 0|const char *Process::ResetColor() { 427| 0| return "\033[0m"; 428| 0|} 429| | 430| |#if !defined(HAVE_DECL_ARC4RANDOM) || !HAVE_DECL_ARC4RANDOM 431| |static unsigned GetRandomNumberSeed() { 432| | // Attempt to get the initial seed from /dev/urandom, if possible. 433| | if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) { 434| | unsigned seed; 435| | int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource); 436| | ::fclose(RandomSource); 437| | 438| | // Return the seed if the read was successful. 439| | if (count == 1) 440| | return seed; 441| | } 442| | 443| | // Otherwise, swizzle the current time and the process ID to form a reasonable 444| | // seed. 445| | TimeValue Now = TimeValue::now(); 446| | return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); 447| |} 448| |#endif 449| | 450| 0|unsigned llvm::sys::Process::GetRandomNumber() { 451| 0|#if defined(HAVE_DECL_ARC4RANDOM) && HAVE_DECL_ARC4RANDOM 452| 0| return arc4random(); 453| |#else 454| | static int x = (::srand(GetRandomNumberSeed()), 0); 455| | (void)x; 456| | return ::rand(); 457| |#endif 458| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Program.inc: 1| |//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the Unix specific portion of the Program class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |//===----------------------------------------------------------------------===// 15| |//=== WARNING: Implementation here must contain only generic UNIX code that 16| |//=== is guaranteed to work on *all* UNIX variants. 17| |//===----------------------------------------------------------------------===// 18| | 19| |#include "Unix.h" 20| |#include "llvm/ADT/StringExtras.h" 21| |#include "llvm/Support/Compiler.h" 22| |#include "llvm/Support/FileSystem.h" 23| |#include "llvm/Support/raw_ostream.h" 24| |#include 25| |#if HAVE_SYS_STAT_H 26| |#include 27| |#endif 28| |#if HAVE_SYS_RESOURCE_H 29| |#include 30| |#endif 31| |#if HAVE_SIGNAL_H 32| |#include 33| |#endif 34| |#if HAVE_FCNTL_H 35| |#include 36| |#endif 37| |#if HAVE_UNISTD_H 38| |#include 39| |#endif 40| |#ifdef HAVE_POSIX_SPAWN 41| |#ifdef __sun__ 42| |#define _RESTRICT_KYWD 43| |#endif 44| |#include 45| | 46| |#if defined(__APPLE__) 47| |#include 48| |#endif 49| | 50| |#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) 51| |#define USE_NSGETENVIRON 1 52| |#else 53| |#define USE_NSGETENVIRON 0 54| |#endif 55| | 56| |#if !USE_NSGETENVIRON 57| | extern char **environ; 58| |#else 59| |#include // _NSGetEnviron 60| |#endif 61| |#endif 62| | 63| |namespace llvm { 64| | 65| |using namespace sys; 66| | 67| 0|ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {} 68| | 69| |ErrorOr sys::findProgramByName(StringRef Name, 70| 0| ArrayRef Paths) { 71| 0| assert(!Name.empty() && "Must have a name!"); 72| 0| // Use the given path verbatim if it contains any slashes; this matches 73| 0| // the behavior of sh(1) and friends. 74| 0| if (Name.find('/') != StringRef::npos) 75| 0| return std::string(Name); 76| 0| 77| 0| SmallVector EnvironmentPaths; 78| 0| if (Paths.empty()) 79| 0| if (const char *PathEnv = std::getenv("PATH")) { 80| 0| SplitString(PathEnv, EnvironmentPaths, ":"); 81| 0| Paths = EnvironmentPaths; 82| 0| } 83| 0| 84| 0| for (auto Path : Paths) { 85| 0| if (Path.empty()) 86| 0| continue; 87| 0| 88| 0| // Check to see if this first directory contains the executable... 89| 0| SmallString<128> FilePath(Path); 90| 0| sys::path::append(FilePath, Name); 91| 0| if (sys::fs::can_execute(FilePath.c_str())) 92| 0| return std::string(FilePath.str()); // Found the executable! 93| 0| } 94| 0| return std::errc::no_such_file_or_directory; 95| 0|} 96| | 97| 0|static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { 98| 0| if (!Path) // Noop 99| 0| return false; 100| 0| std::string File; 101| 0| if (Path->empty()) 102| 0| // Redirect empty paths to /dev/null 103| 0| File = "/dev/null"; 104| 0| else 105| 0| File = *Path; 106| 0| 107| 0| // Open the file 108| 0| int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); 109| 0| if (InFD == -1) { 110| 0| MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " 111| 0| + (FD == 0 ? "input" : "output")); 112| 0| return true; 113| 0| } 114| 0| 115| 0| // Install it as the requested FD 116| 0| if (dup2(InFD, FD) == -1) { 117| 0| MakeErrMsg(ErrMsg, "Cannot dup2"); 118| 0| close(InFD); 119| 0| return true; 120| 0| } 121| 0| close(InFD); // Close the original FD 122| 0| return false; 123| 0|} 124| | 125| |#ifdef HAVE_POSIX_SPAWN 126| |static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg, 127| 0| posix_spawn_file_actions_t *FileActions) { 128| 0| if (!Path) // Noop 129| 0| return false; 130| 0| const char *File; 131| 0| if (Path->empty()) 132| 0| // Redirect empty paths to /dev/null 133| 0| File = "/dev/null"; 134| 0| else 135| 0| File = Path->c_str(); 136| 0| 137| 0| if (int Err = posix_spawn_file_actions_addopen( 138| 0| FileActions, FD, File, 139| 0| FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) 140| 0| return MakeErrMsg(ErrMsg, "Cannot dup2", Err); 141| 0| return false; 142| 0|} 143| |#endif 144| | 145| 0|static void TimeOutHandler(int Sig) { 146| 0|} 147| | 148| |static void SetMemoryLimits (unsigned size) 149| 0|{ 150| 0|#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT 151| 0| struct rlimit r; 152| 0| __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; 153| 0| 154| 0| // Heap size 155| 0| getrlimit (RLIMIT_DATA, &r); 156| 0| r.rlim_cur = limit; 157| 0| setrlimit (RLIMIT_DATA, &r); 158| 0|#ifdef RLIMIT_RSS 159| 0| // Resident set size. 160| 0| getrlimit (RLIMIT_RSS, &r); 161| 0| r.rlim_cur = limit; 162| 0| setrlimit (RLIMIT_RSS, &r); 163| 0|#endif 164| 0|#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. 165| 0| // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb 166| 0| // of virtual memory for shadow memory mapping. 167| 0|#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD 168| 0| // Virtual memory. 169| 0| getrlimit (RLIMIT_AS, &r); 170| 0| r.rlim_cur = limit; 171| 0| setrlimit (RLIMIT_AS, &r); 172| 0|#endif 173| 0|#endif 174| 0|#endif 175| 0|} 176| | 177| |} 178| | 179| |static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, 180| | const char **envp, const StringRef **redirects, 181| 0| unsigned memoryLimit, std::string *ErrMsg) { 182| 0| if (!llvm::sys::fs::exists(Program)) { 183| 0| if (ErrMsg) 184| 0| *ErrMsg = std::string("Executable \"") + Program.str() + 185| 0| std::string("\" doesn't exist!"); 186| 0| return false; 187| 0| } 188| 0| 189| 0| // If this OS has posix_spawn and there is no memory limit being implied, use 190| 0| // posix_spawn. It is more efficient than fork/exec. 191| 0|#ifdef HAVE_POSIX_SPAWN 192| 0| if (memoryLimit == 0) { 193| 0| posix_spawn_file_actions_t FileActionsStore; 194| 0| posix_spawn_file_actions_t *FileActions = nullptr; 195| 0| 196| 0| // If we call posix_spawn_file_actions_addopen we have to make sure the 197| 0| // c strings we pass to it stay alive until the call to posix_spawn, 198| 0| // so we copy any StringRefs into this variable. 199| 0| std::string RedirectsStorage[3]; 200| 0| 201| 0| if (redirects) { 202| 0| std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr}; 203| 0| for (int I = 0; I < 3; ++I) { 204| 0| if (redirects[I]) { 205| 0| RedirectsStorage[I] = *redirects[I]; 206| 0| RedirectsStr[I] = &RedirectsStorage[I]; 207| 0| } 208| 0| } 209| 0| 210| 0| FileActions = &FileActionsStore; 211| 0| posix_spawn_file_actions_init(FileActions); 212| 0| 213| 0| // Redirect stdin/stdout. 214| 0| if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) || 215| 0| RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions)) 216| 0| return false; 217| 0| if (redirects[1] == nullptr || redirects[2] == nullptr || 218| 0| *redirects[1] != *redirects[2]) { 219| 0| // Just redirect stderr 220| 0| if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions)) 221| 0| return false; 222| 0| } else { 223| 0| // If stdout and stderr should go to the same place, redirect stderr 224| 0| // to the FD already open for stdout. 225| 0| if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2)) 226| 0| return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); 227| 0| } 228| 0| } 229| 0| 230| 0| if (!envp) 231| |#if !USE_NSGETENVIRON 232| | envp = const_cast(environ); 233| |#else 234| | // environ is missing in dylibs. 235| 0| envp = const_cast(*_NSGetEnviron()); 236| 0|#endif 237| 0| 238| 0| // Explicitly initialized to prevent what appears to be a valgrind false 239| 0| // positive. 240| 0| pid_t PID = 0; 241| 0| int Err = posix_spawn(&PID, Program.str().c_str(), FileActions, 242| 0| /*attrp*/nullptr, const_cast(args), 243| 0| const_cast(envp)); 244| 0| 245| 0| if (FileActions) 246| 0| posix_spawn_file_actions_destroy(FileActions); 247| 0| 248| 0| if (Err) 249| 0| return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); 250| 0| 251| 0| PI.Pid = PID; 252| 0| 253| 0| return true; 254| 0| } 255| 0|#endif 256| 0| 257| 0| // Create a child process. 258| 0| int child = fork(); 259| 0| switch (child) { 260| 0| // An error occurred: Return to the caller. 261| 0| case -1: 262| 0| MakeErrMsg(ErrMsg, "Couldn't fork"); 263| 0| return false; 264| 0| 265| 0| // Child process: Execute the program. 266| 0| case 0: { 267| 0| // Redirect file descriptors... 268| 0| if (redirects) { 269| 0| // Redirect stdin 270| 0| if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } 271| 0| // Redirect stdout 272| 0| if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } 273| 0| if (redirects[1] && redirects[2] && 274| 0| *(redirects[1]) == *(redirects[2])) { 275| 0| // If stdout and stderr should go to the same place, redirect stderr 276| 0| // to the FD already open for stdout. 277| 0| if (-1 == dup2(1,2)) { 278| 0| MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); 279| 0| return false; 280| 0| } 281| 0| } else { 282| 0| // Just redirect stderr 283| 0| if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } 284| 0| } 285| 0| } 286| 0| 287| 0| // Set memory limits 288| 0| if (memoryLimit!=0) { 289| 0| SetMemoryLimits(memoryLimit); 290| 0| } 291| 0| 292| 0| // Execute! 293| 0| std::string PathStr = Program; 294| 0| if (envp != nullptr) 295| 0| execve(PathStr.c_str(), 296| 0| const_cast(args), 297| 0| const_cast(envp)); 298| 0| else 299| 0| execv(PathStr.c_str(), 300| 0| const_cast(args)); 301| 0| // If the execve() failed, we should exit. Follow Unix protocol and 302| 0| // return 127 if the executable was not found, and 126 otherwise. 303| 0| // Use _exit rather than exit so that atexit functions and static 304| 0| // object destructors cloned from the parent process aren't 305| 0| // redundantly run, and so that any data buffered in stdio buffers 306| 0| // cloned from the parent aren't redundantly written out. 307| 0| _exit(errno == ENOENT ? 127 : 126); 308| 0| } 309| 0| 310| 0| // Parent process: Break out of the switch to do our processing. 311| 0| default: 312| 0| break; 313| 0| } 314| 0| 315| 0| PI.Pid = child; 316| 0| 317| 0| return true; 318| 0|} 319| | 320| |namespace llvm { 321| | 322| |ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, 323| 0| bool WaitUntilTerminates, std::string *ErrMsg) { 324| 0|#ifdef HAVE_SYS_WAIT_H 325| 0| struct sigaction Act, Old; 326| 0| assert(PI.Pid && "invalid pid to wait on, process not started?"); 327| 0| 328| 0| int WaitPidOptions = 0; 329| 0| pid_t ChildPid = PI.Pid; 330| 0| if (WaitUntilTerminates) { 331| 0| SecondsToWait = 0; 332| 0| } else if (SecondsToWait) { 333| 0| // Install a timeout handler. The handler itself does nothing, but the 334| 0| // simple fact of having a handler at all causes the wait below to return 335| 0| // with EINTR, unlike if we used SIG_IGN. 336| 0| memset(&Act, 0, sizeof(Act)); 337| 0| Act.sa_handler = TimeOutHandler; 338| 0| sigemptyset(&Act.sa_mask); 339| 0| sigaction(SIGALRM, &Act, &Old); 340| 0| alarm(SecondsToWait); 341| 0| } else if (SecondsToWait == 0) 342| 0| WaitPidOptions = WNOHANG; 343| 0| 344| 0| // Parent process: Wait for the child process to terminate. 345| 0| int status; 346| 0| ProcessInfo WaitResult; 347| 0| 348| 0| do { 349| 0| WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions); 350| 0| } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR); 351| 0| 352| 0| if (WaitResult.Pid != PI.Pid) { 353| 0| if (WaitResult.Pid == 0) { 354| 0| // Non-blocking wait. 355| 0| return WaitResult; 356| 0| } else { 357| 0| if (SecondsToWait && errno == EINTR) { 358| 0| // Kill the child. 359| 0| kill(PI.Pid, SIGKILL); 360| 0| 361| 0| // Turn off the alarm and restore the signal handler 362| 0| alarm(0); 363| 0| sigaction(SIGALRM, &Old, nullptr); 364| 0| 365| 0| // Wait for child to die 366| 0| if (wait(&status) != ChildPid) 367| 0| MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); 368| 0| else 369| 0| MakeErrMsg(ErrMsg, "Child timed out", 0); 370| 0| 371| 0| WaitResult.ReturnCode = -2; // Timeout detected 372| 0| return WaitResult; 373| 0| } else if (errno != EINTR) { 374| 0| MakeErrMsg(ErrMsg, "Error waiting for child process"); 375| 0| WaitResult.ReturnCode = -1; 376| 0| return WaitResult; 377| 0| } 378| 0| } 379| 0| } 380| 0| 381| 0| // We exited normally without timeout, so turn off the timer. 382| 0| if (SecondsToWait && !WaitUntilTerminates) { 383| 0| alarm(0); 384| 0| sigaction(SIGALRM, &Old, nullptr); 385| 0| } 386| 0| 387| 0| // Return the proper exit status. Detect error conditions 388| 0| // so we can return -1 for them and set ErrMsg informatively. 389| 0| int result = 0; 390| 0| if (WIFEXITED(status)) { 391| 0| result = WEXITSTATUS(status); 392| 0| WaitResult.ReturnCode = result; 393| 0| 394| 0| if (result == 127) { 395| 0| if (ErrMsg) 396| 0| *ErrMsg = llvm::sys::StrError(ENOENT); 397| 0| WaitResult.ReturnCode = -1; 398| 0| return WaitResult; 399| 0| } 400| 0| if (result == 126) { 401| 0| if (ErrMsg) 402| 0| *ErrMsg = "Program could not be executed"; 403| 0| WaitResult.ReturnCode = -1; 404| 0| return WaitResult; 405| 0| } 406| 0| } else if (WIFSIGNALED(status)) { 407| 0| if (ErrMsg) { 408| 0| *ErrMsg = strsignal(WTERMSIG(status)); 409| 0|#ifdef WCOREDUMP 410| 0| if (WCOREDUMP(status)) 411| 0| *ErrMsg += " (core dumped)"; 412| 0|#endif 413| 0| } 414| 0| // Return a special value to indicate that the process received an unhandled 415| 0| // signal during execution as opposed to failing to execute. 416| 0| WaitResult.ReturnCode = -2; 417| 0| } 418| |#else 419| | if (ErrMsg) 420| | *ErrMsg = "Program::Wait is not implemented on this platform yet!"; 421| | ProcessInfo WaitResult; 422| | WaitResult.ReturnCode = -2; 423| |#endif 424| 0| return WaitResult; 425| 0|} 426| | 427| 0| std::error_code sys::ChangeStdinToBinary(){ 428| 0| // Do nothing, as Unix doesn't differentiate between text and binary. 429| 0| return std::error_code(); 430| 0|} 431| | 432| 0| std::error_code sys::ChangeStdoutToBinary(){ 433| 0| // Do nothing, as Unix doesn't differentiate between text and binary. 434| 0| return std::error_code(); 435| 0|} 436| | 437| |std::error_code 438| |llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, 439| 0| WindowsEncodingMethod Encoding /*unused*/) { 440| 0| std::error_code EC; 441| 0| llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); 442| 0| 443| 0| if (EC) 444| 0| return EC; 445| 0| 446| 0| OS << Contents; 447| 0| 448| 0| if (OS.has_error()) 449| 0| return std::make_error_code(std::errc::io_error); 450| 0| 451| 0| return EC; 452| 0|} 453| | 454| 0|bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef Args) { 455| 0| static long ArgMax = sysconf(_SC_ARG_MAX); 456| 0| 457| 0| // System says no practical limit. 458| 0| if (ArgMax == -1) 459| 0| return true; 460| 0| 461| 0| // Conservatively account for space required by environment variables. 462| 0| long HalfArgMax = ArgMax / 2; 463| 0| 464| 0| size_t ArgLength = 0; 465| 0| for (ArrayRef::iterator I = Args.begin(), E = Args.end(); 466| 0| I != E; ++I) { 467| 0| ArgLength += strlen(*I) + 1; 468| 0| if (ArgLength > size_t(HalfArgMax)) { 469| 0| return false; 470| 0| } 471| 0| } 472| 0| return true; 473| 0|} 474| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Signals.inc: 1| |//===- Signals.cpp - Generic Unix Signals Implementation -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines some helpful functions for dealing with the possibility of 11| |// Unix signals occurring while your program is running. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#include "Unix.h" 16| |#include "llvm/ADT/STLExtras.h" 17| |#include "llvm/Support/Format.h" 18| |#include "llvm/Support/FileSystem.h" 19| |#include "llvm/Support/FileUtilities.h" 20| |#include "llvm/Support/ManagedStatic.h" 21| |#include "llvm/Support/MemoryBuffer.h" 22| |#include "llvm/Support/Mutex.h" 23| |#include "llvm/Support/Program.h" 24| |#include "llvm/Support/UniqueLock.h" 25| |#include "llvm/Support/raw_ostream.h" 26| |#include 27| |#include 28| |#include 29| |#if HAVE_EXECINFO_H 30| |# include // For backtrace(). 31| |#endif 32| |#if HAVE_SIGNAL_H 33| |#include 34| |#endif 35| |#if HAVE_SYS_STAT_H 36| |#include 37| |#endif 38| |#if HAVE_CXXABI_H 39| |#include 40| |#endif 41| |#if HAVE_DLFCN_H 42| |#include 43| |#endif 44| |#if HAVE_MACH_MACH_H 45| |#include 46| |#endif 47| |#if HAVE_LINK_H 48| |#include 49| |#endif 50| | 51| |using namespace llvm; 52| | 53| |static RETSIGTYPE SignalHandler(int Sig); // defined below. 54| | 55| |static ManagedStatic > SignalsMutex; 56| | 57| |/// InterruptFunction - The function to call if ctrl-c is pressed. 58| |static void (*InterruptFunction)() = nullptr; 59| | 60| |static ManagedStatic> FilesToRemove; 61| |static ManagedStatic>> 62| | CallBacksToRun; 63| | 64| |// IntSigs - Signals that represent requested termination. There's no bug 65| |// or failure, or if there is, it's not our direct responsibility. For whatever 66| |// reason, our continued execution is no longer desirable. 67| |static const int IntSigs[] = { 68| | SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 69| |}; 70| | 71| |// KillSigs - Signals that represent that we have a bug, and our prompt 72| |// termination has been ordered. 73| |static const int KillSigs[] = { 74| | SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT 75| |#ifdef SIGSYS 76| | , SIGSYS 77| |#endif 78| |#ifdef SIGXCPU 79| | , SIGXCPU 80| |#endif 81| |#ifdef SIGXFSZ 82| | , SIGXFSZ 83| |#endif 84| |#ifdef SIGEMT 85| | , SIGEMT 86| |#endif 87| |}; 88| | 89| |static unsigned NumRegisteredSignals = 0; 90| |static struct { 91| | struct sigaction SA; 92| | int SigNo; 93| |} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])]; 94| | 95| | 96| 0|static void RegisterHandler(int Signal) { 97| 0| assert(NumRegisteredSignals < 98| 0| sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) && 99| 0| "Out of space for signal handlers!"); 100| 0| 101| 0| struct sigaction NewHandler; 102| 0| 103| 0| NewHandler.sa_handler = SignalHandler; 104| 0| NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND; 105| 0| sigemptyset(&NewHandler.sa_mask); 106| 0| 107| 0| // Install the new handler, save the old one in RegisteredSignalInfo. 108| 0| sigaction(Signal, &NewHandler, 109| 0| &RegisteredSignalInfo[NumRegisteredSignals].SA); 110| 0| RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal; 111| 0| ++NumRegisteredSignals; 112| 0|} 113| | 114| 0|static void RegisterHandlers() { 115| 0| // If the handlers are already registered, we're done. 116| 0| if (NumRegisteredSignals != 0) return; 117| 0| 118| 0| for (auto S : IntSigs) RegisterHandler(S); 119| 0| for (auto S : KillSigs) RegisterHandler(S); 120| 0|} 121| | 122| 0|static void UnregisterHandlers() { 123| 0| // Restore all of the signal handlers to how they were before we showed up. 124| 0| for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i) 125| 0| sigaction(RegisteredSignalInfo[i].SigNo, 126| 0| &RegisteredSignalInfo[i].SA, nullptr); 127| 0| NumRegisteredSignals = 0; 128| 0|} 129| | 130| | 131| |/// RemoveFilesToRemove - Process the FilesToRemove list. This function 132| |/// should be called with the SignalsMutex lock held. 133| |/// NB: This must be an async signal safe function. It cannot allocate or free 134| |/// memory, even in debug builds. 135| 0|static void RemoveFilesToRemove() { 136| 0| // We avoid iterators in case of debug iterators that allocate or release 137| 0| // memory. 138| 0| std::vector& FilesToRemoveRef = *FilesToRemove; 139| 0| for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) { 140| 0| // We rely on a std::string implementation for which repeated calls to 141| 0| // 'c_str()' don't allocate memory. We pre-call 'c_str()' on all of these 142| 0| // strings to try to ensure this is safe. 143| 0| const char *path = FilesToRemoveRef[i].c_str(); 144| 0| 145| 0| // Get the status so we can determine if it's a file or directory. If we 146| 0| // can't stat the file, ignore it. 147| 0| struct stat buf; 148| 0| if (stat(path, &buf) != 0) 149| 0| continue; 150| 0| 151| 0| // If this is not a regular file, ignore it. We want to prevent removal of 152| 0| // special files like /dev/null, even if the compiler is being run with the 153| 0| // super-user permissions. 154| 0| if (!S_ISREG(buf.st_mode)) 155| 0| continue; 156| 0| 157| 0| // Otherwise, remove the file. We ignore any errors here as there is nothing 158| 0| // else we can do. 159| 0| unlink(path); 160| 0| } 161| 0|} 162| | 163| |// SignalHandler - The signal handler that runs. 164| 0|static RETSIGTYPE SignalHandler(int Sig) { 165| 0| // Restore the signal behavior to default, so that the program actually 166| 0| // crashes when we return and the signal reissues. This also ensures that if 167| 0| // we crash in our signal handler that the program will terminate immediately 168| 0| // instead of recursing in the signal handler. 169| 0| UnregisterHandlers(); 170| 0| 171| 0| // Unmask all potentially blocked kill signals. 172| 0| sigset_t SigMask; 173| 0| sigfillset(&SigMask); 174| 0| sigprocmask(SIG_UNBLOCK, &SigMask, nullptr); 175| 0| 176| 0| { 177| 0| unique_lock> Guard(*SignalsMutex); 178| 0| RemoveFilesToRemove(); 179| 0| 180| 0| if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig) 181| 0| != std::end(IntSigs)) { 182| 0| if (InterruptFunction) { 183| 0| void (*IF)() = InterruptFunction; 184| 0| Guard.unlock(); 185| 0| InterruptFunction = nullptr; 186| 0| IF(); // run the interrupt function. 187| 0| return; 188| 0| } 189| 0| 190| 0| Guard.unlock(); 191| 0| raise(Sig); // Execute the default handler. 192| 0| return; 193| 0| } 194| 0| } 195| 0| 196| 0| // Otherwise if it is a fault (like SEGV) run any handler. 197| 0| std::vector>& CallBacksToRunRef = 198| 0| *CallBacksToRun; 199| 0| for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) 200| 0| CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); 201| 0| 202| |#ifdef __s390__ 203| | // On S/390, certain signals are delivered with PSW Address pointing to 204| | // *after* the faulting instruction. Simply returning from the signal 205| | // handler would continue execution after that point, instead of 206| | // re-raising the signal. Raise the signal manually in those cases. 207| | if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP) 208| | raise(Sig); 209| |#endif 210| |} 211| | 212| 0|void llvm::sys::RunInterruptHandlers() { 213| 0| sys::SmartScopedLock Guard(*SignalsMutex); 214| 0| RemoveFilesToRemove(); 215| 0|} 216| | 217| 0|void llvm::sys::SetInterruptFunction(void (*IF)()) { 218| 0| { 219| 0| sys::SmartScopedLock Guard(*SignalsMutex); 220| 0| InterruptFunction = IF; 221| 0| } 222| 0| RegisterHandlers(); 223| 0|} 224| | 225| |// RemoveFileOnSignal - The public API 226| |bool llvm::sys::RemoveFileOnSignal(StringRef Filename, 227| 0| std::string* ErrMsg) { 228| 0| { 229| 0| sys::SmartScopedLock Guard(*SignalsMutex); 230| 0| std::vector& FilesToRemoveRef = *FilesToRemove; 231| 0| std::string *OldPtr = 232| 0| FilesToRemoveRef.empty() ? nullptr : &FilesToRemoveRef[0]; 233| 0| FilesToRemoveRef.push_back(Filename); 234| 0| 235| 0| // We want to call 'c_str()' on every std::string in this vector so that if 236| 0| // the underlying implementation requires a re-allocation, it happens here 237| 0| // rather than inside of the signal handler. If we see the vector grow, we 238| 0| // have to call it on every entry. If it remains in place, we only need to 239| 0| // call it on the latest one. 240| 0| if (OldPtr == &FilesToRemoveRef[0]) 241| 0| FilesToRemoveRef.back().c_str(); 242| 0| else 243| 0| for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) 244| 0| FilesToRemoveRef[i].c_str(); 245| 0| } 246| 0| 247| 0| RegisterHandlers(); 248| 0| return false; 249| 0|} 250| | 251| |// DontRemoveFileOnSignal - The public API 252| 0|void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { 253| 0| sys::SmartScopedLock Guard(*SignalsMutex); 254| 0| std::vector::reverse_iterator RI = 255| 0| std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); 256| 0| std::vector::iterator I = FilesToRemove->end(); 257| 0| if (RI != FilesToRemove->rend()) 258| 0| I = FilesToRemove->erase(RI.base()-1); 259| 0| 260| 0| // We need to call c_str() on every element which would have been moved by 261| 0| // the erase. These elements, in a C++98 implementation where c_str() 262| 0| // requires a reallocation on the first call may have had the call to c_str() 263| 0| // made on insertion become invalid by being copied down an element. 264| 0| for (std::vector::iterator E = FilesToRemove->end(); I != E; ++I) 265| 0| I->c_str(); 266| 0|} 267| | 268| |/// AddSignalHandler - Add a function to be called when a signal is delivered 269| |/// to the process. The handler can have a cookie passed to it to identify 270| |/// what instance of the handler it is. 271| 0|void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 272| 0| CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 273| 0| RegisterHandlers(); 274| 0|} 275| | 276| |#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 277| | 278| |#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \ 279| | defined(__FreeBSD_kernel__) || defined(__NetBSD__)) 280| |struct DlIteratePhdrData { 281| | void **StackTrace; 282| | int depth; 283| | bool first; 284| | const char **modules; 285| | intptr_t *offsets; 286| | const char *main_exec_name; 287| |}; 288| | 289| |static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { 290| | DlIteratePhdrData *data = (DlIteratePhdrData*)arg; 291| | const char *name = data->first ? data->main_exec_name : info->dlpi_name; 292| | data->first = false; 293| | for (int i = 0; i < info->dlpi_phnum; i++) { 294| | const auto *phdr = &info->dlpi_phdr[i]; 295| | if (phdr->p_type != PT_LOAD) 296| | continue; 297| | intptr_t beg = info->dlpi_addr + phdr->p_vaddr; 298| | intptr_t end = beg + phdr->p_memsz; 299| | for (int j = 0; j < data->depth; j++) { 300| | if (data->modules[j]) 301| | continue; 302| | intptr_t addr = (intptr_t)data->StackTrace[j]; 303| | if (beg <= addr && addr < end) { 304| | data->modules[j] = name; 305| | data->offsets[j] = addr - info->dlpi_addr; 306| | } 307| | } 308| | } 309| | return 0; 310| |} 311| | 312| |static bool findModulesAndOffsets(void **StackTrace, int Depth, 313| | const char **Modules, intptr_t *Offsets, 314| | const char *MainExecutableName) { 315| | DlIteratePhdrData data = {StackTrace, Depth, true, 316| | Modules, Offsets, MainExecutableName}; 317| | dl_iterate_phdr(dl_iterate_phdr_cb, &data); 318| | return true; 319| |} 320| |#else 321| |static bool findModulesAndOffsets(void **StackTrace, int Depth, 322| | const char **Modules, intptr_t *Offsets, 323| 0| const char *MainExecutableName) { 324| 0| return false; 325| 0|} 326| |#endif 327| | 328| |static bool printSymbolizedStackTrace(void **StackTrace, int Depth, 329| 0| llvm::raw_ostream &OS) { 330| 0| // FIXME: Subtract necessary number from StackTrace entries to turn return addresses 331| 0| // into actual instruction addresses. 332| 0| // Use llvm-symbolizer tool to symbolize the stack traces. 333| 0| ErrorOr LLVMSymbolizerPathOrErr = 334| 0| sys::findProgramByName("llvm-symbolizer"); 335| 0| if (!LLVMSymbolizerPathOrErr) 336| 0| return false; 337| 0| const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; 338| 0| // We don't know argv0 or the address of main() at this point, but try 339| 0| // to guess it anyway (it's possible on some platforms). 340| 0| std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); 341| 0| if (MainExecutableName.empty() || 342| 0| MainExecutableName.find("llvm-symbolizer") != std::string::npos) 343| 0| return false; 344| 0| 345| 0| std::vector Modules(Depth, nullptr); 346| 0| std::vector Offsets(Depth, 0); 347| 0| if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), 348| 0| MainExecutableName.c_str())) 349| 0| return false; 350| 0| int InputFD; 351| 0| SmallString<32> InputFile, OutputFile; 352| 0| sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); 353| 0| sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); 354| 0| FileRemover InputRemover(InputFile.c_str()); 355| 0| FileRemover OutputRemover(OutputFile.c_str()); 356| 0| 357| 0| { 358| 0| raw_fd_ostream Input(InputFD, true); 359| 0| for (int i = 0; i < Depth; i++) { 360| 0| if (Modules[i]) 361| 0| Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; 362| 0| } 363| 0| } 364| 0| 365| 0| StringRef InputFileStr(InputFile); 366| 0| StringRef OutputFileStr(OutputFile); 367| 0| StringRef StderrFileStr; 368| 0| const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, 369| 0| &StderrFileStr}; 370| 0| const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", 371| 0| "--demangle", nullptr}; 372| 0| int RunResult = 373| 0| sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); 374| 0| if (RunResult != 0) 375| 0| return false; 376| 0| 377| 0| auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); 378| 0| if (!OutputBuf) 379| 0| return false; 380| 0| StringRef Output = OutputBuf.get()->getBuffer(); 381| 0| SmallVector Lines; 382| 0| Output.split(Lines, "\n"); 383| 0| auto CurLine = Lines.begin(); 384| 0| int frame_no = 0; 385| 0| for (int i = 0; i < Depth; i++) { 386| 0| if (!Modules[i]) { 387| 0| OS << format("#%d %p\n", frame_no++, StackTrace[i]); 388| 0| continue; 389| 0| } 390| 0| // Read pairs of lines (function name and file/line info) until we 391| 0| // encounter empty line. 392| 0| for (;;) { 393| 0| if (CurLine == Lines.end()) 394| 0| return false; 395| 0| StringRef FunctionName = *CurLine++; 396| 0| if (FunctionName.empty()) 397| 0| break; 398| 0| OS << format("#%d %p ", frame_no++, StackTrace[i]); 399| 0| if (!FunctionName.startswith("??")) 400| 0| OS << format("%s ", FunctionName.str().c_str()); 401| 0| if (CurLine == Lines.end()) 402| 0| return false; 403| 0| StringRef FileLineInfo = *CurLine++; 404| 0| if (!FileLineInfo.startswith("??")) 405| 0| OS << format("%s", FileLineInfo.str().c_str()); 406| 0| else 407| 0| OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]); 408| 0| OS << "\n"; 409| 0| } 410| 0| } 411| 0| return true; 412| 0|} 413| |#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 414| | 415| |// PrintStackTrace - In the case of a program crash or fault, print out a stack 416| |// trace so that the user has an indication of why and where we died. 417| |// 418| |// On glibc systems we have the 'backtrace' function, which works nicely, but 419| |// doesn't demangle symbols. 420| 0|void llvm::sys::PrintStackTrace(raw_ostream &OS) { 421| 0|#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 422| 0| static void* StackTrace[256]; 423| 0| // Use backtrace() to output a backtrace on Linux systems with glibc. 424| 0| int depth = backtrace(StackTrace, 425| 0| static_cast(array_lengthof(StackTrace))); 426| 0| if (printSymbolizedStackTrace(StackTrace, depth, OS)) 427| 0| return; 428| 0|#if HAVE_DLFCN_H && __GNUG__ 429| 0| int width = 0; 430| 0| for (int i = 0; i < depth; ++i) { 431| 0| Dl_info dlinfo; 432| 0| dladdr(StackTrace[i], &dlinfo); 433| 0| const char* name = strrchr(dlinfo.dli_fname, '/'); 434| 0| 435| 0| int nwidth; 436| 0| if (!name) nwidth = strlen(dlinfo.dli_fname); 437| 0| else nwidth = strlen(name) - 1; 438| 0| 439| 0| if (nwidth > width) width = nwidth; 440| 0| } 441| 0| 442| 0| for (int i = 0; i < depth; ++i) { 443| 0| Dl_info dlinfo; 444| 0| dladdr(StackTrace[i], &dlinfo); 445| 0| 446| 0| OS << format("%-2d", i); 447| 0| 448| 0| const char* name = strrchr(dlinfo.dli_fname, '/'); 449| 0| if (!name) OS << format(" %-*s", width, dlinfo.dli_fname); 450| 0| else OS << format(" %-*s", width, name+1); 451| 0| 452| 0| OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2, 453| 0| (unsigned long)StackTrace[i]); 454| 0| 455| 0| if (dlinfo.dli_sname != nullptr) { 456| 0| OS << ' '; 457| 0|# if HAVE_CXXABI_H 458| 0| int res; 459| 0| char* d = abi::__cxa_demangle(dlinfo.dli_sname, nullptr, nullptr, &res); 460| |# else 461| | char* d = NULL; 462| |# endif 463| 0| if (!d) OS << dlinfo.dli_sname; 464| 0| else OS << d; 465| 0| free(d); 466| 0| 467| 0| // FIXME: When we move to C++11, use %t length modifier. It's not in 468| 0| // C++03 and causes gcc to issue warnings. Losing the upper 32 bits of 469| 0| // the stack offset for a stack dump isn't likely to cause any problems. 470| 0| OS << format(" + %u",(unsigned)((char*)StackTrace[i]- 471| 0| (char*)dlinfo.dli_saddr)); 472| 0| } 473| 0| OS << '\n'; 474| 0| } 475| |#else 476| | backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO); 477| |#endif 478| |#endif 479| 0|} 480| | 481| 0|static void PrintStackTraceSignalHandler(void *) { 482| 0| PrintStackTrace(llvm::errs()); 483| 0|} 484| | 485| 0|void llvm::sys::DisableSystemDialogsOnCrash() {} 486| | 487| |/// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or 488| |/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 489| 0|void llvm::sys::PrintStackTraceOnErrorSignal() { 490| 0| AddSignalHandler(PrintStackTraceSignalHandler, nullptr); 491| 0| 492| |#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES) 493| | // Environment variable to disable any kind of crash dialog. 494| | if (getenv("LLVM_DISABLE_CRASH_REPORT")) { 495| | mach_port_t self = mach_task_self(); 496| | 497| | exception_mask_t mask = EXC_MASK_CRASH; 498| | 499| | kern_return_t ret = task_set_exception_ports(self, 500| | mask, 501| | MACH_PORT_NULL, 502| | EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, 503| | THREAD_STATE_NONE); 504| | (void)ret; 505| | } 506| |#endif 507| |} 508| | 509| | 510| |/***/ 511| | 512| |// On Darwin, raise sends a signal to the main thread instead of the current 513| |// thread. This has the unfortunate effect that assert() and abort() will end up 514| |// bypassing our crash recovery attempts. We work around this for anything in 515| |// the same linkage unit by just defining our own versions of the assert handler 516| |// and abort. 517| | 518| |#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES) 519| | 520| |#include 521| |#include 522| | 523| |int raise(int sig) { 524| | return pthread_kill(pthread_self(), sig); 525| |} 526| | 527| |void __assert_rtn(const char *func, 528| | const char *file, 529| | int line, 530| | const char *expr) { 531| | if (func) 532| | fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n", 533| | expr, func, file, line); 534| | else 535| | fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n", 536| | expr, file, line); 537| | abort(); 538| |} 539| | 540| |void abort() { 541| | raise(SIGABRT); 542| | usleep(1000); 543| | __builtin_trap(); 544| |} 545| | 546| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/TimeValue.inc: 1| |//===- Unix/TimeValue.cpp - Unix TimeValue Implementation -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the Unix specific portion of the TimeValue class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |//===----------------------------------------------------------------------===// 15| |//=== WARNING: Implementation here must contain only generic UNIX code that 16| |//=== is guaranteed to work on *all* UNIX variants. 17| |//===----------------------------------------------------------------------===// 18| | 19| |#include "Unix.h" 20| | 21| |namespace llvm { 22| | using namespace sys; 23| | 24| 0|std::string TimeValue::str() const { 25| 0| time_t OurTime = time_t(this->toEpochTime()); 26| 0| struct tm Storage; 27| 0| struct tm *LT = ::localtime_r(&OurTime, &Storage); 28| 0| assert(LT); 29| 0| char Buffer1[sizeof("YYYY-MM-DD HH:MM:SS")]; 30| 0| strftime(Buffer1, sizeof(Buffer1), "%Y-%m-%d %H:%M:%S", LT); 31| 0| char Buffer2[sizeof("YYYY-MM-DD HH:MM:SS.MMMUUUNNN")]; 32| 0| snprintf(Buffer2, sizeof(Buffer2), "%s.%.9u", Buffer1, this->nanoseconds()); 33| 0| return std::string(Buffer2); 34| 0|} 35| | 36| 4|TimeValue TimeValue::now() { 37| 4| struct timeval the_time; 38| 4| timerclear(&the_time); 39| 4| if (0 != ::gettimeofday(&the_time,nullptr)) { 40| 0| // This is *really* unlikely to occur because the only gettimeofday 41| 0| // errors concern the timezone parameter which we're passing in as 0. 42| 0| // In the unlikely case it does happen, just return MinTime, no error 43| 0| // message needed. 44| 0| return MinTime(); 45| 0| } 46| 4| 47| 4| return TimeValue( 48| 4| static_cast( the_time.tv_sec + 49| 4| PosixZeroTimeSeconds ), 50| 4| static_cast( the_time.tv_usec * 51| 4| NANOSECONDS_PER_MICROSECOND ) ); 52| 4|} 53| | 54| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Unix.h: 1| |//===- llvm/Support/Unix/Unix.h - Common Unix Include File -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines things specific to Unix implementations. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_LIB_SUPPORT_UNIX_UNIX_H 15| |#define LLVM_LIB_SUPPORT_UNIX_UNIX_H 16| | 17| |//===----------------------------------------------------------------------===// 18| |//=== WARNING: Implementation here must contain only generic UNIX code that 19| |//=== is guaranteed to work on all UNIX variants. 20| |//===----------------------------------------------------------------------===// 21| | 22| |#include "llvm/Config/config.h" // Get autoconf configuration settings 23| |#include "llvm/Support/Errno.h" 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| |#include 31| |#include 32| | 33| |#ifdef HAVE_UNISTD_H 34| |#include 35| |#endif 36| | 37| |#ifdef HAVE_SYS_PARAM_H 38| |#include 39| |#endif 40| | 41| |#ifdef HAVE_SYS_TIME_H 42| |# include 43| |#endif 44| |#include 45| | 46| |#ifdef HAVE_SYS_WAIT_H 47| |# include 48| |#endif 49| | 50| |#ifdef HAVE_DLFCN_H 51| |# include 52| |#endif 53| | 54| |#ifndef WEXITSTATUS 55| |# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 56| |#endif 57| | 58| |#ifndef WIFEXITED 59| |# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 60| |#endif 61| | 62| |/// This function builds an error message into \p ErrMsg using the \p prefix 63| |/// string and the Unix error number given by \p errnum. If errnum is -1, the 64| |/// default then the value of errno is used. 65| |/// @brief Make an error message 66| |/// 67| |/// If the error number can be converted to a string, it will be 68| |/// separated from prefix by ": ". 69| |static inline bool MakeErrMsg( 70| 0| std::string* ErrMsg, const std::string& prefix, int errnum = -1) { 71| 0| if (!ErrMsg) 72| 0| return true; 73| 0| if (errnum == -1) 74| 0| errnum = errno; 75| 0| *ErrMsg = prefix + ": " + llvm::sys::StrError(errnum); 76| 0| return true; 77| 0|} ------------------ | Unexecuted instantiation: Memory.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ | Unexecuted instantiation: Path.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ | Unexecuted instantiation: Process.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ | Unexecuted instantiation: Program.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ | Unexecuted instantiation: Signals.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ | Unexecuted instantiation: TimeValue.cpp:_ZL10MakeErrMsgPNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_i ------------------ 78| | 79| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/Valgrind.cpp: 1| |//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is 11| |// defined. If we have valgrind.h but valgrind isn't running, its macros are 12| |// no-ops. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#include "llvm/Support/Valgrind.h" 17| |#include "llvm/Config/config.h" 18| | 19| |#if HAVE_VALGRIND_VALGRIND_H 20| |#include 21| | 22| |static bool InitNotUnderValgrind() { 23| | return !RUNNING_ON_VALGRIND; 24| |} 25| | 26| |// This bool is negated from what we'd expect because code may run before it 27| |// gets initialized. If that happens, it will appear to be 0 (false), and we 28| |// want that to cause the rest of the code in this file to run the 29| |// Valgrind-provided macros. 30| |static const bool NotUnderValgrind = InitNotUnderValgrind(); 31| | 32| |bool llvm::sys::RunningOnValgrind() { 33| | if (NotUnderValgrind) 34| | return false; 35| | return RUNNING_ON_VALGRIND; 36| |} 37| | 38| |void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { 39| | if (NotUnderValgrind) 40| | return; 41| | 42| | VALGRIND_DISCARD_TRANSLATIONS(Addr, Len); 43| |} 44| | 45| |#else // !HAVE_VALGRIND_VALGRIND_H 46| | 47| 0|bool llvm::sys::RunningOnValgrind() { 48| 0| return false; 49| 0|} 50| | 51| 0|void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { 52| 0|} 53| | 54| |#endif // !HAVE_VALGRIND_VALGRIND_H 55| | 56| |// These functions require no implementation, tsan just looks at the arguments 57| |// they're called with. However, they are required to be weak as some other 58| |// application or library may already be providing these definitions for the 59| |// same reason we are. 60| |extern "C" { 61| |LLVM_ATTRIBUTE_WEAK void AnnotateHappensAfter(const char *file, int line, 62| | const volatile void *cv); 63| 0|void AnnotateHappensAfter(const char *file, int line, const volatile void *cv) { 64| 0|} 65| |LLVM_ATTRIBUTE_WEAK void AnnotateHappensBefore(const char *file, int line, 66| | const volatile void *cv); 67| |void AnnotateHappensBefore(const char *file, int line, 68| 0| const volatile void *cv) {} 69| |LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesBegin(const char *file, int line); 70| 0|void AnnotateIgnoreWritesBegin(const char *file, int line) {} 71| |LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line); 72| 0|void AnnotateIgnoreWritesEnd(const char *file, int line) {} 73| |} 74| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/YAMLParser.cpp: 1| |//===--- YAMLParser.cpp - Simple YAML parser ------------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements a YAML parser. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/YAMLParser.h" 15| |#include "llvm/ADT/SmallVector.h" 16| |#include "llvm/ADT/StringExtras.h" 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/ADT/ilist.h" 19| |#include "llvm/ADT/ilist_node.h" 20| |#include "llvm/Support/ErrorHandling.h" 21| |#include "llvm/Support/MemoryBuffer.h" 22| |#include "llvm/Support/SourceMgr.h" 23| |#include "llvm/Support/raw_ostream.h" 24| | 25| |using namespace llvm; 26| |using namespace yaml; 27| | 28| |enum UnicodeEncodingForm { 29| | UEF_UTF32_LE, ///< UTF-32 Little Endian 30| | UEF_UTF32_BE, ///< UTF-32 Big Endian 31| | UEF_UTF16_LE, ///< UTF-16 Little Endian 32| | UEF_UTF16_BE, ///< UTF-16 Big Endian 33| | UEF_UTF8, ///< UTF-8 or ascii. 34| | UEF_Unknown ///< Not a valid Unicode encoding. 35| |}; 36| | 37| |/// EncodingInfo - Holds the encoding type and length of the byte order mark if 38| |/// it exists. Length is in {0, 2, 3, 4}. 39| |typedef std::pair EncodingInfo; 40| | 41| |/// getUnicodeEncoding - Reads up to the first 4 bytes to determine the Unicode 42| |/// encoding form of \a Input. 43| |/// 44| |/// @param Input A string of length 0 or more. 45| |/// @returns An EncodingInfo indicating the Unicode encoding form of the input 46| |/// and how long the byte order mark is if one exists. 47| 0|static EncodingInfo getUnicodeEncoding(StringRef Input) { 48| 0| if (Input.size() == 0) 49| 0| return std::make_pair(UEF_Unknown, 0); 50| 0| 51| 0| switch (uint8_t(Input[0])) { 52| 0| case 0x00: 53| 0| if (Input.size() >= 4) { 54| 0| if ( Input[1] == 0 55| 0| && uint8_t(Input[2]) == 0xFE 56| 0| && uint8_t(Input[3]) == 0xFF) 57| 0| return std::make_pair(UEF_UTF32_BE, 4); 58| 0| if (Input[1] == 0 && Input[2] == 0 && Input[3] != 0) 59| 0| return std::make_pair(UEF_UTF32_BE, 0); 60| 0| } 61| 0| 62| 0| if (Input.size() >= 2 && Input[1] != 0) 63| 0| return std::make_pair(UEF_UTF16_BE, 0); 64| 0| return std::make_pair(UEF_Unknown, 0); 65| 0| case 0xFF: 66| 0| if ( Input.size() >= 4 67| 0| && uint8_t(Input[1]) == 0xFE 68| 0| && Input[2] == 0 69| 0| && Input[3] == 0) 70| 0| return std::make_pair(UEF_UTF32_LE, 4); 71| 0| 72| 0| if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFE) 73| 0| return std::make_pair(UEF_UTF16_LE, 2); 74| 0| return std::make_pair(UEF_Unknown, 0); 75| 0| case 0xFE: 76| 0| if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFF) 77| 0| return std::make_pair(UEF_UTF16_BE, 2); 78| 0| return std::make_pair(UEF_Unknown, 0); 79| 0| case 0xEF: 80| 0| if ( Input.size() >= 3 81| 0| && uint8_t(Input[1]) == 0xBB 82| 0| && uint8_t(Input[2]) == 0xBF) 83| 0| return std::make_pair(UEF_UTF8, 3); 84| 0| return std::make_pair(UEF_Unknown, 0); 85| 0| } 86| 0| 87| 0| // It could still be utf-32 or utf-16. 88| 0| if (Input.size() >= 4 && Input[1] == 0 && Input[2] == 0 && Input[3] == 0) 89| 0| return std::make_pair(UEF_UTF32_LE, 0); 90| 0| 91| 0| if (Input.size() >= 2 && Input[1] == 0) 92| 0| return std::make_pair(UEF_UTF16_LE, 0); 93| 0| 94| 0| return std::make_pair(UEF_UTF8, 0); 95| 0|} 96| | 97| |namespace llvm { 98| |namespace yaml { 99| |/// Pin the vtables to this file. 100| 0|void Node::anchor() {} 101| 0|void NullNode::anchor() {} 102| 0|void ScalarNode::anchor() {} 103| 0|void KeyValueNode::anchor() {} 104| 0|void MappingNode::anchor() {} 105| 0|void SequenceNode::anchor() {} 106| 0|void AliasNode::anchor() {} 107| | 108| |/// Token - A single YAML token. 109| |struct Token : ilist_node { 110| | enum TokenKind { 111| | TK_Error, // Uninitialized token. 112| | TK_StreamStart, 113| | TK_StreamEnd, 114| | TK_VersionDirective, 115| | TK_TagDirective, 116| | TK_DocumentStart, 117| | TK_DocumentEnd, 118| | TK_BlockEntry, 119| | TK_BlockEnd, 120| | TK_BlockSequenceStart, 121| | TK_BlockMappingStart, 122| | TK_FlowEntry, 123| | TK_FlowSequenceStart, 124| | TK_FlowSequenceEnd, 125| | TK_FlowMappingStart, 126| | TK_FlowMappingEnd, 127| | TK_Key, 128| | TK_Value, 129| | TK_Scalar, 130| | TK_Alias, 131| | TK_Anchor, 132| | TK_Tag 133| | } Kind; 134| | 135| | /// A string of length 0 or more whose begin() points to the logical location 136| | /// of the token in the input. 137| | StringRef Range; 138| | 139| 0| Token() : Kind(TK_Error) {} 140| |}; 141| |} 142| |} 143| | 144| |namespace llvm { 145| |template<> 146| |struct ilist_sentinel_traits { 147| 0| Token *createSentinel() const { 148| 0| return &Sentinel; 149| 0| } 150| 0| static void destroySentinel(Token*) {} 151| | 152| 0| Token *provideInitialHead() const { return createSentinel(); } 153| 0| Token *ensureHead(Token*) const { return createSentinel(); } 154| 0| static void noteHead(Token*, Token*) {} 155| | 156| |private: 157| | mutable Token Sentinel; 158| |}; 159| | 160| |template<> 161| |struct ilist_node_traits { 162| 0| Token *createNode(const Token &V) { 163| 0| return new (Alloc.Allocate()) Token(V); 164| 0| } 165| 0| static void deleteNode(Token *V) {} 166| | 167| 0| void addNodeToList(Token *) {} 168| 0| void removeNodeFromList(Token *) {} 169| | void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, 170| | ilist_iterator /*first*/, 171| 0| ilist_iterator /*last*/) {} 172| | 173| | BumpPtrAllocator Alloc; 174| |}; 175| |} 176| | 177| |typedef ilist TokenQueueT; 178| | 179| |namespace { 180| |/// @brief This struct is used to track simple keys. 181| |/// 182| |/// Simple keys are handled by creating an entry in SimpleKeys for each Token 183| |/// which could legally be the start of a simple key. When peekNext is called, 184| |/// if the Token To be returned is referenced by a SimpleKey, we continue 185| |/// tokenizing until that potential simple key has either been found to not be 186| |/// a simple key (we moved on to the next line or went further than 1024 chars). 187| |/// Or when we run into a Value, and then insert a Key token (and possibly 188| |/// others) before the SimpleKey's Tok. 189| |struct SimpleKey { 190| | TokenQueueT::iterator Tok; 191| | unsigned Column; 192| | unsigned Line; 193| | unsigned FlowLevel; 194| | bool IsRequired; 195| | 196| 0| bool operator ==(const SimpleKey &Other) { 197| 0| return Tok == Other.Tok; 198| 0| } 199| |}; 200| |} 201| | 202| |/// @brief The Unicode scalar value of a UTF-8 minimal well-formed code unit 203| |/// subsequence and the subsequence's length in code units (uint8_t). 204| |/// A length of 0 represents an error. 205| |typedef std::pair UTF8Decoded; 206| | 207| 0|static UTF8Decoded decodeUTF8(StringRef Range) { 208| 0| StringRef::iterator Position= Range.begin(); 209| 0| StringRef::iterator End = Range.end(); 210| 0| // 1 byte: [0x00, 0x7f] 211| 0| // Bit pattern: 0xxxxxxx 212| 0| if ((*Position & 0x80) == 0) { 213| 0| return std::make_pair(*Position, 1); 214| 0| } 215| 0| // 2 bytes: [0x80, 0x7ff] 216| 0| // Bit pattern: 110xxxxx 10xxxxxx 217| 0| if (Position + 1 != End && 218| 0| ((*Position & 0xE0) == 0xC0) && 219| 0| ((*(Position + 1) & 0xC0) == 0x80)) { 220| 0| uint32_t codepoint = ((*Position & 0x1F) << 6) | 221| 0| (*(Position + 1) & 0x3F); 222| 0| if (codepoint >= 0x80) 223| 0| return std::make_pair(codepoint, 2); 224| 0| } 225| 0| // 3 bytes: [0x8000, 0xffff] 226| 0| // Bit pattern: 1110xxxx 10xxxxxx 10xxxxxx 227| 0| if (Position + 2 != End && 228| 0| ((*Position & 0xF0) == 0xE0) && 229| 0| ((*(Position + 1) & 0xC0) == 0x80) && 230| 0| ((*(Position + 2) & 0xC0) == 0x80)) { 231| 0| uint32_t codepoint = ((*Position & 0x0F) << 12) | 232| 0| ((*(Position + 1) & 0x3F) << 6) | 233| 0| (*(Position + 2) & 0x3F); 234| 0| // Codepoints between 0xD800 and 0xDFFF are invalid, as 235| 0| // they are high / low surrogate halves used by UTF-16. 236| 0| if (codepoint >= 0x800 && 237| 0| (codepoint < 0xD800 || codepoint > 0xDFFF)) 238| 0| return std::make_pair(codepoint, 3); 239| 0| } 240| 0| // 4 bytes: [0x10000, 0x10FFFF] 241| 0| // Bit pattern: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 242| 0| if (Position + 3 != End && 243| 0| ((*Position & 0xF8) == 0xF0) && 244| 0| ((*(Position + 1) & 0xC0) == 0x80) && 245| 0| ((*(Position + 2) & 0xC0) == 0x80) && 246| 0| ((*(Position + 3) & 0xC0) == 0x80)) { 247| 0| uint32_t codepoint = ((*Position & 0x07) << 18) | 248| 0| ((*(Position + 1) & 0x3F) << 12) | 249| 0| ((*(Position + 2) & 0x3F) << 6) | 250| 0| (*(Position + 3) & 0x3F); 251| 0| if (codepoint >= 0x10000 && codepoint <= 0x10FFFF) 252| 0| return std::make_pair(codepoint, 4); 253| 0| } 254| 0| return std::make_pair(0, 0); 255| 0|} 256| | 257| |namespace llvm { 258| |namespace yaml { 259| |/// @brief Scans YAML tokens from a MemoryBuffer. 260| |class Scanner { 261| |public: 262| | Scanner(StringRef Input, SourceMgr &SM); 263| | Scanner(MemoryBufferRef Buffer, SourceMgr &SM_); 264| | 265| | /// @brief Parse the next token and return it without popping it. 266| | Token &peekNext(); 267| | 268| | /// @brief Parse the next token and pop it from the queue. 269| | Token getNext(); 270| | 271| | void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message, 272| 0| ArrayRef Ranges = None) { 273| 0| SM.PrintMessage(Loc, Kind, Message, Ranges); 274| 0| } 275| | 276| 0| void setError(const Twine &Message, StringRef::iterator Position) { 277| 0| if (Current >= End) 278| 0| Current = End - 1; 279| 0| 280| 0| // Don't print out more errors after the first one we encounter. The rest 281| 0| // are just the result of the first, and have no meaning. 282| 0| if (!Failed) 283| 0| printError(SMLoc::getFromPointer(Current), SourceMgr::DK_Error, Message); 284| 0| Failed = true; 285| 0| } 286| | 287| 0| void setError(const Twine &Message) { 288| 0| setError(Message, Current); 289| 0| } 290| | 291| | /// @brief Returns true if an error occurred while parsing. 292| 0| bool failed() { 293| 0| return Failed; 294| 0| } 295| | 296| |private: 297| | void init(MemoryBufferRef Buffer); 298| | 299| 0| StringRef currentInput() { 300| 0| return StringRef(Current, End - Current); 301| 0| } 302| | 303| | /// @brief Decode a UTF-8 minimal well-formed code unit subsequence starting 304| | /// at \a Position. 305| | /// 306| | /// If the UTF-8 code units starting at Position do not form a well-formed 307| | /// code unit subsequence, then the Unicode scalar value is 0, and the length 308| | /// is 0. 309| 0| UTF8Decoded decodeUTF8(StringRef::iterator Position) { 310| 0| return ::decodeUTF8(StringRef(Position, End - Position)); 311| 0| } 312| | 313| | // The following functions are based on the gramar rules in the YAML spec. The 314| | // style of the function names it meant to closely match how they are written 315| | // in the spec. The number within the [] is the number of the grammar rule in 316| | // the spec. 317| | // 318| | // See 4.2 [Production Naming Conventions] for the meaning of the prefixes. 319| | // 320| | // c- 321| | // A production starting and ending with a special character. 322| | // b- 323| | // A production matching a single line break. 324| | // nb- 325| | // A production starting and ending with a non-break character. 326| | // s- 327| | // A production starting and ending with a white space character. 328| | // ns- 329| | // A production starting and ending with a non-space character. 330| | // l- 331| | // A production matching complete line(s). 332| | 333| | /// @brief Skip a single nb-char[27] starting at Position. 334| | /// 335| | /// A nb-char is 0x9 | [0x20-0x7E] | 0x85 | [0xA0-0xD7FF] | [0xE000-0xFEFE] 336| | /// | [0xFF00-0xFFFD] | [0x10000-0x10FFFF] 337| | /// 338| | /// @returns The code unit after the nb-char, or Position if it's not an 339| | /// nb-char. 340| | StringRef::iterator skip_nb_char(StringRef::iterator Position); 341| | 342| | /// @brief Skip a single b-break[28] starting at Position. 343| | /// 344| | /// A b-break is 0xD 0xA | 0xD | 0xA 345| | /// 346| | /// @returns The code unit after the b-break, or Position if it's not a 347| | /// b-break. 348| | StringRef::iterator skip_b_break(StringRef::iterator Position); 349| | 350| | /// @brief Skip a single s-white[33] starting at Position. 351| | /// 352| | /// A s-white is 0x20 | 0x9 353| | /// 354| | /// @returns The code unit after the s-white, or Position if it's not a 355| | /// s-white. 356| | StringRef::iterator skip_s_white(StringRef::iterator Position); 357| | 358| | /// @brief Skip a single ns-char[34] starting at Position. 359| | /// 360| | /// A ns-char is nb-char - s-white 361| | /// 362| | /// @returns The code unit after the ns-char, or Position if it's not a 363| | /// ns-char. 364| | StringRef::iterator skip_ns_char(StringRef::iterator Position); 365| | 366| | typedef StringRef::iterator (Scanner::*SkipWhileFunc)(StringRef::iterator); 367| | /// @brief Skip minimal well-formed code unit subsequences until Func 368| | /// returns its input. 369| | /// 370| | /// @returns The code unit after the last minimal well-formed code unit 371| | /// subsequence that Func accepted. 372| | StringRef::iterator skip_while( SkipWhileFunc Func 373| | , StringRef::iterator Position); 374| | 375| | /// @brief Scan ns-uri-char[39]s starting at Cur. 376| | /// 377| | /// This updates Cur and Column while scanning. 378| | /// 379| | /// @returns A StringRef starting at Cur which covers the longest contiguous 380| | /// sequence of ns-uri-char. 381| | StringRef scan_ns_uri_char(); 382| | 383| | /// @brief Consume a minimal well-formed code unit subsequence starting at 384| | /// \a Cur. Return false if it is not the same Unicode scalar value as 385| | /// \a Expected. This updates \a Column. 386| | bool consume(uint32_t Expected); 387| | 388| | /// @brief Skip \a Distance UTF-8 code units. Updates \a Cur and \a Column. 389| | void skip(uint32_t Distance); 390| | 391| | /// @brief Return true if the minimal well-formed code unit subsequence at 392| | /// Pos is whitespace or a new line 393| | bool isBlankOrBreak(StringRef::iterator Position); 394| | 395| | /// @brief If IsSimpleKeyAllowed, create and push_back a new SimpleKey. 396| | void saveSimpleKeyCandidate( TokenQueueT::iterator Tok 397| | , unsigned AtColumn 398| | , bool IsRequired); 399| | 400| | /// @brief Remove simple keys that can no longer be valid simple keys. 401| | /// 402| | /// Invalid simple keys are not on the current line or are further than 1024 403| | /// columns back. 404| | void removeStaleSimpleKeyCandidates(); 405| | 406| | /// @brief Remove all simple keys on FlowLevel \a Level. 407| | void removeSimpleKeyCandidatesOnFlowLevel(unsigned Level); 408| | 409| | /// @brief Unroll indentation in \a Indents back to \a Col. Creates BlockEnd 410| | /// tokens if needed. 411| | bool unrollIndent(int ToColumn); 412| | 413| | /// @brief Increase indent to \a Col. Creates \a Kind token at \a InsertPoint 414| | /// if needed. 415| | bool rollIndent( int ToColumn 416| | , Token::TokenKind Kind 417| | , TokenQueueT::iterator InsertPoint); 418| | 419| | /// @brief Skip whitespace and comments until the start of the next token. 420| | void scanToNextToken(); 421| | 422| | /// @brief Must be the first token generated. 423| | bool scanStreamStart(); 424| | 425| | /// @brief Generate tokens needed to close out the stream. 426| | bool scanStreamEnd(); 427| | 428| | /// @brief Scan a %BLAH directive. 429| | bool scanDirective(); 430| | 431| | /// @brief Scan a ... or ---. 432| | bool scanDocumentIndicator(bool IsStart); 433| | 434| | /// @brief Scan a [ or { and generate the proper flow collection start token. 435| | bool scanFlowCollectionStart(bool IsSequence); 436| | 437| | /// @brief Scan a ] or } and generate the proper flow collection end token. 438| | bool scanFlowCollectionEnd(bool IsSequence); 439| | 440| | /// @brief Scan the , that separates entries in a flow collection. 441| | bool scanFlowEntry(); 442| | 443| | /// @brief Scan the - that starts block sequence entries. 444| | bool scanBlockEntry(); 445| | 446| | /// @brief Scan an explicit ? indicating a key. 447| | bool scanKey(); 448| | 449| | /// @brief Scan an explicit : indicating a value. 450| | bool scanValue(); 451| | 452| | /// @brief Scan a quoted scalar. 453| | bool scanFlowScalar(bool IsDoubleQuoted); 454| | 455| | /// @brief Scan an unquoted scalar. 456| | bool scanPlainScalar(); 457| | 458| | /// @brief Scan an Alias or Anchor starting with * or &. 459| | bool scanAliasOrAnchor(bool IsAlias); 460| | 461| | /// @brief Scan a block scalar starting with | or >. 462| | bool scanBlockScalar(bool IsLiteral); 463| | 464| | /// @brief Scan a tag of the form !stuff. 465| | bool scanTag(); 466| | 467| | /// @brief Dispatch to the next scanning function based on \a *Cur. 468| | bool fetchMoreTokens(); 469| | 470| | /// @brief The SourceMgr used for diagnostics and buffer management. 471| | SourceMgr &SM; 472| | 473| | /// @brief The original input. 474| | MemoryBufferRef InputBuffer; 475| | 476| | /// @brief The current position of the scanner. 477| | StringRef::iterator Current; 478| | 479| | /// @brief The end of the input (one past the last character). 480| | StringRef::iterator End; 481| | 482| | /// @brief Current YAML indentation level in spaces. 483| | int Indent; 484| | 485| | /// @brief Current column number in Unicode code points. 486| | unsigned Column; 487| | 488| | /// @brief Current line number. 489| | unsigned Line; 490| | 491| | /// @brief How deep we are in flow style containers. 0 Means at block level. 492| | unsigned FlowLevel; 493| | 494| | /// @brief Are we at the start of the stream? 495| | bool IsStartOfStream; 496| | 497| | /// @brief Can the next token be the start of a simple key? 498| | bool IsSimpleKeyAllowed; 499| | 500| | /// @brief True if an error has occurred. 501| | bool Failed; 502| | 503| | /// @brief Queue of tokens. This is required to queue up tokens while looking 504| | /// for the end of a simple key. And for cases where a single character 505| | /// can produce multiple tokens (e.g. BlockEnd). 506| | TokenQueueT TokenQueue; 507| | 508| | /// @brief Indentation levels. 509| | SmallVector Indents; 510| | 511| | /// @brief Potential simple keys. 512| | SmallVector SimpleKeys; 513| |}; 514| | 515| |} // end namespace yaml 516| |} // end namespace llvm 517| | 518| |/// encodeUTF8 - Encode \a UnicodeScalarValue in UTF-8 and append it to result. 519| |static void encodeUTF8( uint32_t UnicodeScalarValue 520| 0| , SmallVectorImpl &Result) { 521| 0| if (UnicodeScalarValue <= 0x7F) { 522| 0| Result.push_back(UnicodeScalarValue & 0x7F); 523| 0| } else if (UnicodeScalarValue <= 0x7FF) { 524| 0| uint8_t FirstByte = 0xC0 | ((UnicodeScalarValue & 0x7C0) >> 6); 525| 0| uint8_t SecondByte = 0x80 | (UnicodeScalarValue & 0x3F); 526| 0| Result.push_back(FirstByte); 527| 0| Result.push_back(SecondByte); 528| 0| } else if (UnicodeScalarValue <= 0xFFFF) { 529| 0| uint8_t FirstByte = 0xE0 | ((UnicodeScalarValue & 0xF000) >> 12); 530| 0| uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6); 531| 0| uint8_t ThirdByte = 0x80 | (UnicodeScalarValue & 0x3F); 532| 0| Result.push_back(FirstByte); 533| 0| Result.push_back(SecondByte); 534| 0| Result.push_back(ThirdByte); 535| 0| } else if (UnicodeScalarValue <= 0x10FFFF) { 536| 0| uint8_t FirstByte = 0xF0 | ((UnicodeScalarValue & 0x1F0000) >> 18); 537| 0| uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0x3F000) >> 12); 538| 0| uint8_t ThirdByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6); 539| 0| uint8_t FourthByte = 0x80 | (UnicodeScalarValue & 0x3F); 540| 0| Result.push_back(FirstByte); 541| 0| Result.push_back(SecondByte); 542| 0| Result.push_back(ThirdByte); 543| 0| Result.push_back(FourthByte); 544| 0| } 545| 0|} 546| | 547| 0|bool yaml::dumpTokens(StringRef Input, raw_ostream &OS) { 548| 0| SourceMgr SM; 549| 0| Scanner scanner(Input, SM); 550| 0| while (true) { 551| 0| Token T = scanner.getNext(); 552| 0| switch (T.Kind) { 553| 0| case Token::TK_StreamStart: 554| 0| OS << "Stream-Start: "; 555| 0| break; 556| 0| case Token::TK_StreamEnd: 557| 0| OS << "Stream-End: "; 558| 0| break; 559| 0| case Token::TK_VersionDirective: 560| 0| OS << "Version-Directive: "; 561| 0| break; 562| 0| case Token::TK_TagDirective: 563| 0| OS << "Tag-Directive: "; 564| 0| break; 565| 0| case Token::TK_DocumentStart: 566| 0| OS << "Document-Start: "; 567| 0| break; 568| 0| case Token::TK_DocumentEnd: 569| 0| OS << "Document-End: "; 570| 0| break; 571| 0| case Token::TK_BlockEntry: 572| 0| OS << "Block-Entry: "; 573| 0| break; 574| 0| case Token::TK_BlockEnd: 575| 0| OS << "Block-End: "; 576| 0| break; 577| 0| case Token::TK_BlockSequenceStart: 578| 0| OS << "Block-Sequence-Start: "; 579| 0| break; 580| 0| case Token::TK_BlockMappingStart: 581| 0| OS << "Block-Mapping-Start: "; 582| 0| break; 583| 0| case Token::TK_FlowEntry: 584| 0| OS << "Flow-Entry: "; 585| 0| break; 586| 0| case Token::TK_FlowSequenceStart: 587| 0| OS << "Flow-Sequence-Start: "; 588| 0| break; 589| 0| case Token::TK_FlowSequenceEnd: 590| 0| OS << "Flow-Sequence-End: "; 591| 0| break; 592| 0| case Token::TK_FlowMappingStart: 593| 0| OS << "Flow-Mapping-Start: "; 594| 0| break; 595| 0| case Token::TK_FlowMappingEnd: 596| 0| OS << "Flow-Mapping-End: "; 597| 0| break; 598| 0| case Token::TK_Key: 599| 0| OS << "Key: "; 600| 0| break; 601| 0| case Token::TK_Value: 602| 0| OS << "Value: "; 603| 0| break; 604| 0| case Token::TK_Scalar: 605| 0| OS << "Scalar: "; 606| 0| break; 607| 0| case Token::TK_Alias: 608| 0| OS << "Alias: "; 609| 0| break; 610| 0| case Token::TK_Anchor: 611| 0| OS << "Anchor: "; 612| 0| break; 613| 0| case Token::TK_Tag: 614| 0| OS << "Tag: "; 615| 0| break; 616| 0| case Token::TK_Error: 617| 0| break; 618| 0| } 619| 0| OS << T.Range << "\n"; 620| 0| if (T.Kind == Token::TK_StreamEnd) 621| 0| break; 622| 0| else if (T.Kind == Token::TK_Error) 623| 0| return false; 624| 0| } 625| 0| return true; 626| 0|} 627| | 628| 0|bool yaml::scanTokens(StringRef Input) { 629| 0| llvm::SourceMgr SM; 630| 0| llvm::yaml::Scanner scanner(Input, SM); 631| 0| for (;;) { 632| 0| llvm::yaml::Token T = scanner.getNext(); 633| 0| if (T.Kind == Token::TK_StreamEnd) 634| 0| break; 635| 0| else if (T.Kind == Token::TK_Error) 636| 0| return false; 637| 0| } 638| 0| return true; 639| 0|} 640| | 641| 0|std::string yaml::escape(StringRef Input) { 642| 0| std::string EscapedInput; 643| 0| for (StringRef::iterator i = Input.begin(), e = Input.end(); i != e; ++i) { 644| 0| if (*i == '\\') 645| 0| EscapedInput += "\\\\"; 646| 0| else if (*i == '"') 647| 0| EscapedInput += "\\\""; 648| 0| else if (*i == 0) 649| 0| EscapedInput += "\\0"; 650| 0| else if (*i == 0x07) 651| 0| EscapedInput += "\\a"; 652| 0| else if (*i == 0x08) 653| 0| EscapedInput += "\\b"; 654| 0| else if (*i == 0x09) 655| 0| EscapedInput += "\\t"; 656| 0| else if (*i == 0x0A) 657| 0| EscapedInput += "\\n"; 658| 0| else if (*i == 0x0B) 659| 0| EscapedInput += "\\v"; 660| 0| else if (*i == 0x0C) 661| 0| EscapedInput += "\\f"; 662| 0| else if (*i == 0x0D) 663| 0| EscapedInput += "\\r"; 664| 0| else if (*i == 0x1B) 665| 0| EscapedInput += "\\e"; 666| 0| else if ((unsigned char)*i < 0x20) { // Control characters not handled above. 667| 0| std::string HexStr = utohexstr(*i); 668| 0| EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr; 669| 0| } else if (*i & 0x80) { // UTF-8 multiple code unit subsequence. 670| 0| UTF8Decoded UnicodeScalarValue 671| 0| = decodeUTF8(StringRef(i, Input.end() - i)); 672| 0| if (UnicodeScalarValue.second == 0) { 673| 0| // Found invalid char. 674| 0| SmallString<4> Val; 675| 0| encodeUTF8(0xFFFD, Val); 676| 0| EscapedInput.insert(EscapedInput.end(), Val.begin(), Val.end()); 677| 0| // FIXME: Error reporting. 678| 0| return EscapedInput; 679| 0| } 680| 0| if (UnicodeScalarValue.first == 0x85) 681| 0| EscapedInput += "\\N"; 682| 0| else if (UnicodeScalarValue.first == 0xA0) 683| 0| EscapedInput += "\\_"; 684| 0| else if (UnicodeScalarValue.first == 0x2028) 685| 0| EscapedInput += "\\L"; 686| 0| else if (UnicodeScalarValue.first == 0x2029) 687| 0| EscapedInput += "\\P"; 688| 0| else { 689| 0| std::string HexStr = utohexstr(UnicodeScalarValue.first); 690| 0| if (HexStr.size() <= 2) 691| 0| EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr; 692| 0| else if (HexStr.size() <= 4) 693| 0| EscapedInput += "\\u" + std::string(4 - HexStr.size(), '0') + HexStr; 694| 0| else if (HexStr.size() <= 8) 695| 0| EscapedInput += "\\U" + std::string(8 - HexStr.size(), '0') + HexStr; 696| 0| } 697| 0| i += UnicodeScalarValue.second - 1; 698| 0| } else 699| 0| EscapedInput.push_back(*i); 700| 0| } 701| 0| return EscapedInput; 702| 0|} 703| | 704| 0|Scanner::Scanner(StringRef Input, SourceMgr &sm) : SM(sm) { 705| 0| init(MemoryBufferRef(Input, "YAML")); 706| 0|} 707| | 708| 0|Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_) : SM(SM_) { 709| 0| init(Buffer); 710| 0|} 711| | 712| 0|void Scanner::init(MemoryBufferRef Buffer) { 713| 0| InputBuffer = Buffer; 714| 0| Current = InputBuffer.getBufferStart(); 715| 0| End = InputBuffer.getBufferEnd(); 716| 0| Indent = -1; 717| 0| Column = 0; 718| 0| Line = 0; 719| 0| FlowLevel = 0; 720| 0| IsStartOfStream = true; 721| 0| IsSimpleKeyAllowed = true; 722| 0| Failed = false; 723| 0| std::unique_ptr InputBufferOwner = 724| 0| MemoryBuffer::getMemBuffer(Buffer); 725| 0| SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc()); 726| 0|} 727| | 728| 0|Token &Scanner::peekNext() { 729| 0| // If the current token is a possible simple key, keep parsing until we 730| 0| // can confirm. 731| 0| bool NeedMore = false; 732| 0| while (true) { 733| 0| if (TokenQueue.empty() || NeedMore) { 734| 0| if (!fetchMoreTokens()) { 735| 0| TokenQueue.clear(); 736| 0| TokenQueue.push_back(Token()); 737| 0| return TokenQueue.front(); 738| 0| } 739| 0| } 740| 0| assert(!TokenQueue.empty() && 741| 0| "fetchMoreTokens lied about getting tokens!"); 742| 0| 743| 0| removeStaleSimpleKeyCandidates(); 744| 0| SimpleKey SK; 745| 0| SK.Tok = TokenQueue.front(); 746| 0| if (std::find(SimpleKeys.begin(), SimpleKeys.end(), SK) 747| 0| == SimpleKeys.end()) 748| 0| break; 749| 0| else 750| 0| NeedMore = true; 751| 0| } 752| 0| return TokenQueue.front(); 753| 0|} 754| | 755| 0|Token Scanner::getNext() { 756| 0| Token Ret = peekNext(); 757| 0| // TokenQueue can be empty if there was an error getting the next token. 758| 0| if (!TokenQueue.empty()) 759| 0| TokenQueue.pop_front(); 760| 0| 761| 0| // There cannot be any referenced Token's if the TokenQueue is empty. So do a 762| 0| // quick deallocation of them all. 763| 0| if (TokenQueue.empty()) { 764| 0| TokenQueue.Alloc.Reset(); 765| 0| } 766| 0| 767| 0| return Ret; 768| 0|} 769| | 770| 0|StringRef::iterator Scanner::skip_nb_char(StringRef::iterator Position) { 771| 0| if (Position == End) 772| 0| return Position; 773| 0| // Check 7 bit c-printable - b-char. 774| 0| if ( *Position == 0x09 775| 0| || (*Position >= 0x20 && *Position <= 0x7E)) 776| 0| return Position + 1; 777| 0| 778| 0| // Check for valid UTF-8. 779| 0| if (uint8_t(*Position) & 0x80) { 780| 0| UTF8Decoded u8d = decodeUTF8(Position); 781| 0| if ( u8d.second != 0 782| 0| && u8d.first != 0xFEFF 783| 0| && ( u8d.first == 0x85 784| 0| || ( u8d.first >= 0xA0 785| 0| && u8d.first <= 0xD7FF) 786| 0| || ( u8d.first >= 0xE000 787| 0| && u8d.first <= 0xFFFD) 788| 0| || ( u8d.first >= 0x10000 789| 0| && u8d.first <= 0x10FFFF))) 790| 0| return Position + u8d.second; 791| 0| } 792| 0| return Position; 793| 0|} 794| | 795| 0|StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) { 796| 0| if (Position == End) 797| 0| return Position; 798| 0| if (*Position == 0x0D) { 799| 0| if (Position + 1 != End && *(Position + 1) == 0x0A) 800| 0| return Position + 2; 801| 0| return Position + 1; 802| 0| } 803| 0| 804| 0| if (*Position == 0x0A) 805| 0| return Position + 1; 806| 0| return Position; 807| 0|} 808| | 809| | 810| 0|StringRef::iterator Scanner::skip_s_white(StringRef::iterator Position) { 811| 0| if (Position == End) 812| 0| return Position; 813| 0| if (*Position == ' ' || *Position == '\t') 814| 0| return Position + 1; 815| 0| return Position; 816| 0|} 817| | 818| 0|StringRef::iterator Scanner::skip_ns_char(StringRef::iterator Position) { 819| 0| if (Position == End) 820| 0| return Position; 821| 0| if (*Position == ' ' || *Position == '\t') 822| 0| return Position; 823| 0| return skip_nb_char(Position); 824| 0|} 825| | 826| |StringRef::iterator Scanner::skip_while( SkipWhileFunc Func 827| 0| , StringRef::iterator Position) { 828| 0| while (true) { 829| 0| StringRef::iterator i = (this->*Func)(Position); 830| 0| if (i == Position) 831| 0| break; 832| 0| Position = i; 833| 0| } 834| 0| return Position; 835| 0|} 836| | 837| 0|static bool is_ns_hex_digit(const char C) { 838| 0| return (C >= '0' && C <= '9') 839| 0| || (C >= 'a' && C <= 'z') 840| 0| || (C >= 'A' && C <= 'Z'); 841| 0|} 842| | 843| 0|static bool is_ns_word_char(const char C) { 844| 0| return C == '-' 845| 0| || (C >= 'a' && C <= 'z') 846| 0| || (C >= 'A' && C <= 'Z'); 847| 0|} 848| | 849| 0|StringRef Scanner::scan_ns_uri_char() { 850| 0| StringRef::iterator Start = Current; 851| 0| while (true) { 852| 0| if (Current == End) 853| 0| break; 854| 0| if (( *Current == '%' 855| 0| && Current + 2 < End 856| 0| && is_ns_hex_digit(*(Current + 1)) 857| 0| && is_ns_hex_digit(*(Current + 2))) 858| 0| || is_ns_word_char(*Current) 859| 0| || StringRef(Current, 1).find_first_of("#;/?:@&=+$,_.!~*'()[]") 860| 0| != StringRef::npos) { 861| 0| ++Current; 862| 0| ++Column; 863| 0| } else 864| 0| break; 865| 0| } 866| 0| return StringRef(Start, Current - Start); 867| 0|} 868| | 869| 0|bool Scanner::consume(uint32_t Expected) { 870| 0| if (Expected >= 0x80) 871| 0| report_fatal_error("Not dealing with this yet"); 872| 0| if (Current == End) 873| 0| return false; 874| 0| if (uint8_t(*Current) >= 0x80) 875| 0| report_fatal_error("Not dealing with this yet"); 876| 0| if (uint8_t(*Current) == Expected) { 877| 0| ++Current; 878| 0| ++Column; 879| 0| return true; 880| 0| } 881| 0| return false; 882| 0|} 883| | 884| 0|void Scanner::skip(uint32_t Distance) { 885| 0| Current += Distance; 886| 0| Column += Distance; 887| 0| assert(Current <= End && "Skipped past the end"); 888| 0|} 889| | 890| 0|bool Scanner::isBlankOrBreak(StringRef::iterator Position) { 891| 0| if (Position == End) 892| 0| return false; 893| 0| if ( *Position == ' ' || *Position == '\t' 894| 0| || *Position == '\r' || *Position == '\n') 895| 0| return true; 896| 0| return false; 897| 0|} 898| | 899| |void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok 900| | , unsigned AtColumn 901| 0| , bool IsRequired) { 902| 0| if (IsSimpleKeyAllowed) { 903| 0| SimpleKey SK; 904| 0| SK.Tok = Tok; 905| 0| SK.Line = Line; 906| 0| SK.Column = AtColumn; 907| 0| SK.IsRequired = IsRequired; 908| 0| SK.FlowLevel = FlowLevel; 909| 0| SimpleKeys.push_back(SK); 910| 0| } 911| 0|} 912| | 913| 0|void Scanner::removeStaleSimpleKeyCandidates() { 914| 0| for (SmallVectorImpl::iterator i = SimpleKeys.begin(); 915| 0| i != SimpleKeys.end();) { 916| 0| if (i->Line != Line || i->Column + 1024 < Column) { 917| 0| if (i->IsRequired) 918| 0| setError( "Could not find expected : for simple key" 919| 0| , i->Tok->Range.begin()); 920| 0| i = SimpleKeys.erase(i); 921| 0| } else 922| 0| ++i; 923| 0| } 924| 0|} 925| | 926| 0|void Scanner::removeSimpleKeyCandidatesOnFlowLevel(unsigned Level) { 927| 0| if (!SimpleKeys.empty() && (SimpleKeys.end() - 1)->FlowLevel == Level) 928| 0| SimpleKeys.pop_back(); 929| 0|} 930| | 931| 0|bool Scanner::unrollIndent(int ToColumn) { 932| 0| Token T; 933| 0| // Indentation is ignored in flow. 934| 0| if (FlowLevel != 0) 935| 0| return true; 936| 0| 937| 0| while (Indent > ToColumn) { 938| 0| T.Kind = Token::TK_BlockEnd; 939| 0| T.Range = StringRef(Current, 1); 940| 0| TokenQueue.push_back(T); 941| 0| Indent = Indents.pop_back_val(); 942| 0| } 943| 0| 944| 0| return true; 945| 0|} 946| | 947| |bool Scanner::rollIndent( int ToColumn 948| | , Token::TokenKind Kind 949| 0| , TokenQueueT::iterator InsertPoint) { 950| 0| if (FlowLevel) 951| 0| return true; 952| 0| if (Indent < ToColumn) { 953| 0| Indents.push_back(Indent); 954| 0| Indent = ToColumn; 955| 0| 956| 0| Token T; 957| 0| T.Kind = Kind; 958| 0| T.Range = StringRef(Current, 0); 959| 0| TokenQueue.insert(InsertPoint, T); 960| 0| } 961| 0| return true; 962| 0|} 963| | 964| 0|void Scanner::scanToNextToken() { 965| 0| while (true) { 966| 0| while (*Current == ' ' || *Current == '\t') { 967| 0| skip(1); 968| 0| } 969| 0| 970| 0| // Skip comment. 971| 0| if (*Current == '#') { 972| 0| while (true) { 973| 0| // This may skip more than one byte, thus Column is only incremented 974| 0| // for code points. 975| 0| StringRef::iterator i = skip_nb_char(Current); 976| 0| if (i == Current) 977| 0| break; 978| 0| Current = i; 979| 0| ++Column; 980| 0| } 981| 0| } 982| 0| 983| 0| // Skip EOL. 984| 0| StringRef::iterator i = skip_b_break(Current); 985| 0| if (i == Current) 986| 0| break; 987| 0| Current = i; 988| 0| ++Line; 989| 0| Column = 0; 990| 0| // New lines may start a simple key. 991| 0| if (!FlowLevel) 992| 0| IsSimpleKeyAllowed = true; 993| 0| } 994| 0|} 995| | 996| 0|bool Scanner::scanStreamStart() { 997| 0| IsStartOfStream = false; 998| 0| 999| 0| EncodingInfo EI = getUnicodeEncoding(currentInput()); 1000| 0| 1001| 0| Token T; 1002| 0| T.Kind = Token::TK_StreamStart; 1003| 0| T.Range = StringRef(Current, EI.second); 1004| 0| TokenQueue.push_back(T); 1005| 0| Current += EI.second; 1006| 0| return true; 1007| 0|} 1008| | 1009| 0|bool Scanner::scanStreamEnd() { 1010| 0| // Force an ending new line if one isn't present. 1011| 0| if (Column != 0) { 1012| 0| Column = 0; 1013| 0| ++Line; 1014| 0| } 1015| 0| 1016| 0| unrollIndent(-1); 1017| 0| SimpleKeys.clear(); 1018| 0| IsSimpleKeyAllowed = false; 1019| 0| 1020| 0| Token T; 1021| 0| T.Kind = Token::TK_StreamEnd; 1022| 0| T.Range = StringRef(Current, 0); 1023| 0| TokenQueue.push_back(T); 1024| 0| return true; 1025| 0|} 1026| | 1027| 0|bool Scanner::scanDirective() { 1028| 0| // Reset the indentation level. 1029| 0| unrollIndent(-1); 1030| 0| SimpleKeys.clear(); 1031| 0| IsSimpleKeyAllowed = false; 1032| 0| 1033| 0| StringRef::iterator Start = Current; 1034| 0| consume('%'); 1035| 0| StringRef::iterator NameStart = Current; 1036| 0| Current = skip_while(&Scanner::skip_ns_char, Current); 1037| 0| StringRef Name(NameStart, Current - NameStart); 1038| 0| Current = skip_while(&Scanner::skip_s_white, Current); 1039| 0| 1040| 0| Token T; 1041| 0| if (Name == "YAML") { 1042| 0| Current = skip_while(&Scanner::skip_ns_char, Current); 1043| 0| T.Kind = Token::TK_VersionDirective; 1044| 0| T.Range = StringRef(Start, Current - Start); 1045| 0| TokenQueue.push_back(T); 1046| 0| return true; 1047| 0| } else if(Name == "TAG") { 1048| 0| Current = skip_while(&Scanner::skip_ns_char, Current); 1049| 0| Current = skip_while(&Scanner::skip_s_white, Current); 1050| 0| Current = skip_while(&Scanner::skip_ns_char, Current); 1051| 0| T.Kind = Token::TK_TagDirective; 1052| 0| T.Range = StringRef(Start, Current - Start); 1053| 0| TokenQueue.push_back(T); 1054| 0| return true; 1055| 0| } 1056| 0| return false; 1057| 0|} 1058| | 1059| 0|bool Scanner::scanDocumentIndicator(bool IsStart) { 1060| 0| unrollIndent(-1); 1061| 0| SimpleKeys.clear(); 1062| 0| IsSimpleKeyAllowed = false; 1063| 0| 1064| 0| Token T; 1065| 0| T.Kind = IsStart ? Token::TK_DocumentStart : Token::TK_DocumentEnd; 1066| 0| T.Range = StringRef(Current, 3); 1067| 0| skip(3); 1068| 0| TokenQueue.push_back(T); 1069| 0| return true; 1070| 0|} 1071| | 1072| 0|bool Scanner::scanFlowCollectionStart(bool IsSequence) { 1073| 0| Token T; 1074| 0| T.Kind = IsSequence ? Token::TK_FlowSequenceStart 1075| 0| : Token::TK_FlowMappingStart; 1076| 0| T.Range = StringRef(Current, 1); 1077| 0| skip(1); 1078| 0| TokenQueue.push_back(T); 1079| 0| 1080| 0| // [ and { may begin a simple key. 1081| 0| saveSimpleKeyCandidate(TokenQueue.back(), Column - 1, false); 1082| 0| 1083| 0| // And may also be followed by a simple key. 1084| 0| IsSimpleKeyAllowed = true; 1085| 0| ++FlowLevel; 1086| 0| return true; 1087| 0|} 1088| | 1089| 0|bool Scanner::scanFlowCollectionEnd(bool IsSequence) { 1090| 0| removeSimpleKeyCandidatesOnFlowLevel(FlowLevel); 1091| 0| IsSimpleKeyAllowed = false; 1092| 0| Token T; 1093| 0| T.Kind = IsSequence ? Token::TK_FlowSequenceEnd 1094| 0| : Token::TK_FlowMappingEnd; 1095| 0| T.Range = StringRef(Current, 1); 1096| 0| skip(1); 1097| 0| TokenQueue.push_back(T); 1098| 0| if (FlowLevel) 1099| 0| --FlowLevel; 1100| 0| return true; 1101| 0|} 1102| | 1103| 0|bool Scanner::scanFlowEntry() { 1104| 0| removeSimpleKeyCandidatesOnFlowLevel(FlowLevel); 1105| 0| IsSimpleKeyAllowed = true; 1106| 0| Token T; 1107| 0| T.Kind = Token::TK_FlowEntry; 1108| 0| T.Range = StringRef(Current, 1); 1109| 0| skip(1); 1110| 0| TokenQueue.push_back(T); 1111| 0| return true; 1112| 0|} 1113| | 1114| 0|bool Scanner::scanBlockEntry() { 1115| 0| rollIndent(Column, Token::TK_BlockSequenceStart, TokenQueue.end()); 1116| 0| removeSimpleKeyCandidatesOnFlowLevel(FlowLevel); 1117| 0| IsSimpleKeyAllowed = true; 1118| 0| Token T; 1119| 0| T.Kind = Token::TK_BlockEntry; 1120| 0| T.Range = StringRef(Current, 1); 1121| 0| skip(1); 1122| 0| TokenQueue.push_back(T); 1123| 0| return true; 1124| 0|} 1125| | 1126| 0|bool Scanner::scanKey() { 1127| 0| if (!FlowLevel) 1128| 0| rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end()); 1129| 0| 1130| 0| removeSimpleKeyCandidatesOnFlowLevel(FlowLevel); 1131| 0| IsSimpleKeyAllowed = !FlowLevel; 1132| 0| 1133| 0| Token T; 1134| 0| T.Kind = Token::TK_Key; 1135| 0| T.Range = StringRef(Current, 1); 1136| 0| skip(1); 1137| 0| TokenQueue.push_back(T); 1138| 0| return true; 1139| 0|} 1140| | 1141| 0|bool Scanner::scanValue() { 1142| 0| // If the previous token could have been a simple key, insert the key token 1143| 0| // into the token queue. 1144| 0| if (!SimpleKeys.empty()) { 1145| 0| SimpleKey SK = SimpleKeys.pop_back_val(); 1146| 0| Token T; 1147| 0| T.Kind = Token::TK_Key; 1148| 0| T.Range = SK.Tok->Range; 1149| 0| TokenQueueT::iterator i, e; 1150| 0| for (i = TokenQueue.begin(), e = TokenQueue.end(); i != e; ++i) { 1151| 0| if (i == SK.Tok) 1152| 0| break; 1153| 0| } 1154| 0| assert(i != e && "SimpleKey not in token queue!"); 1155| 0| i = TokenQueue.insert(i, T); 1156| 0| 1157| 0| // We may also need to add a Block-Mapping-Start token. 1158| 0| rollIndent(SK.Column, Token::TK_BlockMappingStart, i); 1159| 0| 1160| 0| IsSimpleKeyAllowed = false; 1161| 0| } else { 1162| 0| if (!FlowLevel) 1163| 0| rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end()); 1164| 0| IsSimpleKeyAllowed = !FlowLevel; 1165| 0| } 1166| 0| 1167| 0| Token T; 1168| 0| T.Kind = Token::TK_Value; 1169| 0| T.Range = StringRef(Current, 1); 1170| 0| skip(1); 1171| 0| TokenQueue.push_back(T); 1172| 0| return true; 1173| 0|} 1174| | 1175| |// Forbidding inlining improves performance by roughly 20%. 1176| |// FIXME: Remove once llvm optimizes this to the faster version without hints. 1177| |LLVM_ATTRIBUTE_NOINLINE static bool 1178| |wasEscaped(StringRef::iterator First, StringRef::iterator Position); 1179| | 1180| |// Returns whether a character at 'Position' was escaped with a leading '\'. 1181| |// 'First' specifies the position of the first character in the string. 1182| |static bool wasEscaped(StringRef::iterator First, 1183| 0| StringRef::iterator Position) { 1184| 0| assert(Position - 1 >= First); 1185| 0| StringRef::iterator I = Position - 1; 1186| 0| // We calculate the number of consecutive '\'s before the current position 1187| 0| // by iterating backwards through our string. 1188| 0| while (I >= First && *I == '\\') --I; 1189| 0| // (Position - 1 - I) now contains the number of '\'s before the current 1190| 0| // position. If it is odd, the character at 'Position' was escaped. 1191| 0| return (Position - 1 - I) % 2 == 1; 1192| 0|} 1193| | 1194| 0|bool Scanner::scanFlowScalar(bool IsDoubleQuoted) { 1195| 0| StringRef::iterator Start = Current; 1196| 0| unsigned ColStart = Column; 1197| 0| if (IsDoubleQuoted) { 1198| 0| do { 1199| 0| ++Current; 1200| 0| while (Current != End && *Current != '"') 1201| 0| ++Current; 1202| 0| // Repeat until the previous character was not a '\' or was an escaped 1203| 0| // backslash. 1204| 0| } while ( Current != End 1205| 0| && *(Current - 1) == '\\' 1206| 0| && wasEscaped(Start + 1, Current)); 1207| 0| } else { 1208| 0| skip(1); 1209| 0| while (true) { 1210| 0| // Skip a ' followed by another '. 1211| 0| if (Current + 1 < End && *Current == '\'' && *(Current + 1) == '\'') { 1212| 0| skip(2); 1213| 0| continue; 1214| 0| } else if (*Current == '\'') 1215| 0| break; 1216| 0| StringRef::iterator i = skip_nb_char(Current); 1217| 0| if (i == Current) { 1218| 0| i = skip_b_break(Current); 1219| 0| if (i == Current) 1220| 0| break; 1221| 0| Current = i; 1222| 0| Column = 0; 1223| 0| ++Line; 1224| 0| } else { 1225| 0| if (i == End) 1226| 0| break; 1227| 0| Current = i; 1228| 0| ++Column; 1229| 0| } 1230| 0| } 1231| 0| } 1232| 0| 1233| 0| if (Current == End) { 1234| 0| setError("Expected quote at end of scalar", Current); 1235| 0| return false; 1236| 0| } 1237| 0| 1238| 0| skip(1); // Skip ending quote. 1239| 0| Token T; 1240| 0| T.Kind = Token::TK_Scalar; 1241| 0| T.Range = StringRef(Start, Current - Start); 1242| 0| TokenQueue.push_back(T); 1243| 0| 1244| 0| saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); 1245| 0| 1246| 0| IsSimpleKeyAllowed = false; 1247| 0| 1248| 0| return true; 1249| 0|} 1250| | 1251| 0|bool Scanner::scanPlainScalar() { 1252| 0| StringRef::iterator Start = Current; 1253| 0| unsigned ColStart = Column; 1254| 0| unsigned LeadingBlanks = 0; 1255| 0| assert(Indent >= -1 && "Indent must be >= -1 !"); 1256| 0| unsigned indent = static_cast(Indent + 1); 1257| 0| while (true) { 1258| 0| if (*Current == '#') 1259| 0| break; 1260| 0| 1261| 0| while (!isBlankOrBreak(Current)) { 1262| 0| if ( FlowLevel && *Current == ':' 1263| 0| && !(isBlankOrBreak(Current + 1) || *(Current + 1) == ',')) { 1264| 0| setError("Found unexpected ':' while scanning a plain scalar", Current); 1265| 0| return false; 1266| 0| } 1267| 0| 1268| 0| // Check for the end of the plain scalar. 1269| 0| if ( (*Current == ':' && isBlankOrBreak(Current + 1)) 1270| 0| || ( FlowLevel 1271| 0| && (StringRef(Current, 1).find_first_of(",:?[]{}") 1272| 0| != StringRef::npos))) 1273| 0| break; 1274| 0| 1275| 0| StringRef::iterator i = skip_nb_char(Current); 1276| 0| if (i == Current) 1277| 0| break; 1278| 0| Current = i; 1279| 0| ++Column; 1280| 0| } 1281| 0| 1282| 0| // Are we at the end? 1283| 0| if (!isBlankOrBreak(Current)) 1284| 0| break; 1285| 0| 1286| 0| // Eat blanks. 1287| 0| StringRef::iterator Tmp = Current; 1288| 0| while (isBlankOrBreak(Tmp)) { 1289| 0| StringRef::iterator i = skip_s_white(Tmp); 1290| 0| if (i != Tmp) { 1291| 0| if (LeadingBlanks && (Column < indent) && *Tmp == '\t') { 1292| 0| setError("Found invalid tab character in indentation", Tmp); 1293| 0| return false; 1294| 0| } 1295| 0| Tmp = i; 1296| 0| ++Column; 1297| 0| } else { 1298| 0| i = skip_b_break(Tmp); 1299| 0| if (!LeadingBlanks) 1300| 0| LeadingBlanks = 1; 1301| 0| Tmp = i; 1302| 0| Column = 0; 1303| 0| ++Line; 1304| 0| } 1305| 0| } 1306| 0| 1307| 0| if (!FlowLevel && Column < indent) 1308| 0| break; 1309| 0| 1310| 0| Current = Tmp; 1311| 0| } 1312| 0| if (Start == Current) { 1313| 0| setError("Got empty plain scalar", Start); 1314| 0| return false; 1315| 0| } 1316| 0| Token T; 1317| 0| T.Kind = Token::TK_Scalar; 1318| 0| T.Range = StringRef(Start, Current - Start); 1319| 0| TokenQueue.push_back(T); 1320| 0| 1321| 0| // Plain scalars can be simple keys. 1322| 0| saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); 1323| 0| 1324| 0| IsSimpleKeyAllowed = false; 1325| 0| 1326| 0| return true; 1327| 0|} 1328| | 1329| 0|bool Scanner::scanAliasOrAnchor(bool IsAlias) { 1330| 0| StringRef::iterator Start = Current; 1331| 0| unsigned ColStart = Column; 1332| 0| skip(1); 1333| 0| while(true) { 1334| 0| if ( *Current == '[' || *Current == ']' 1335| 0| || *Current == '{' || *Current == '}' 1336| 0| || *Current == ',' 1337| 0| || *Current == ':') 1338| 0| break; 1339| 0| StringRef::iterator i = skip_ns_char(Current); 1340| 0| if (i == Current) 1341| 0| break; 1342| 0| Current = i; 1343| 0| ++Column; 1344| 0| } 1345| 0| 1346| 0| if (Start == Current) { 1347| 0| setError("Got empty alias or anchor", Start); 1348| 0| return false; 1349| 0| } 1350| 0| 1351| 0| Token T; 1352| 0| T.Kind = IsAlias ? Token::TK_Alias : Token::TK_Anchor; 1353| 0| T.Range = StringRef(Start, Current - Start); 1354| 0| TokenQueue.push_back(T); 1355| 0| 1356| 0| // Alias and anchors can be simple keys. 1357| 0| saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); 1358| 0| 1359| 0| IsSimpleKeyAllowed = false; 1360| 0| 1361| 0| return true; 1362| 0|} 1363| | 1364| 0|bool Scanner::scanBlockScalar(bool IsLiteral) { 1365| 0| StringRef::iterator Start = Current; 1366| 0| skip(1); // Eat | or > 1367| 0| while(true) { 1368| 0| StringRef::iterator i = skip_nb_char(Current); 1369| 0| if (i == Current) { 1370| 0| if (Column == 0) 1371| 0| break; 1372| 0| i = skip_b_break(Current); 1373| 0| if (i != Current) { 1374| 0| // We got a line break. 1375| 0| Column = 0; 1376| 0| ++Line; 1377| 0| Current = i; 1378| 0| continue; 1379| 0| } else { 1380| 0| // There was an error, which should already have been printed out. 1381| 0| return false; 1382| 0| } 1383| 0| } 1384| 0| Current = i; 1385| 0| ++Column; 1386| 0| } 1387| 0| 1388| 0| if (Start == Current) { 1389| 0| setError("Got empty block scalar", Start); 1390| 0| return false; 1391| 0| } 1392| 0| 1393| 0| Token T; 1394| 0| T.Kind = Token::TK_Scalar; 1395| 0| T.Range = StringRef(Start, Current - Start); 1396| 0| TokenQueue.push_back(T); 1397| 0| return true; 1398| 0|} 1399| | 1400| 0|bool Scanner::scanTag() { 1401| 0| StringRef::iterator Start = Current; 1402| 0| unsigned ColStart = Column; 1403| 0| skip(1); // Eat !. 1404| 0| if (Current == End || isBlankOrBreak(Current)); // An empty tag. 1405| 0| else if (*Current == '<') { 1406| 0| skip(1); 1407| 0| scan_ns_uri_char(); 1408| 0| if (!consume('>')) 1409| 0| return false; 1410| 0| } else { 1411| 0| // FIXME: Actually parse the c-ns-shorthand-tag rule. 1412| 0| Current = skip_while(&Scanner::skip_ns_char, Current); 1413| 0| } 1414| 0| 1415| 0| Token T; 1416| 0| T.Kind = Token::TK_Tag; 1417| 0| T.Range = StringRef(Start, Current - Start); 1418| 0| TokenQueue.push_back(T); 1419| 0| 1420| 0| // Tags can be simple keys. 1421| 0| saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); 1422| 0| 1423| 0| IsSimpleKeyAllowed = false; 1424| 0| 1425| 0| return true; 1426| 0|} 1427| | 1428| 0|bool Scanner::fetchMoreTokens() { 1429| 0| if (IsStartOfStream) 1430| 0| return scanStreamStart(); 1431| 0| 1432| 0| scanToNextToken(); 1433| 0| 1434| 0| if (Current == End) 1435| 0| return scanStreamEnd(); 1436| 0| 1437| 0| removeStaleSimpleKeyCandidates(); 1438| 0| 1439| 0| unrollIndent(Column); 1440| 0| 1441| 0| if (Column == 0 && *Current == '%') 1442| 0| return scanDirective(); 1443| 0| 1444| 0| if (Column == 0 && Current + 4 <= End 1445| 0| && *Current == '-' 1446| 0| && *(Current + 1) == '-' 1447| 0| && *(Current + 2) == '-' 1448| 0| && (Current + 3 == End || isBlankOrBreak(Current + 3))) 1449| 0| return scanDocumentIndicator(true); 1450| 0| 1451| 0| if (Column == 0 && Current + 4 <= End 1452| 0| && *Current == '.' 1453| 0| && *(Current + 1) == '.' 1454| 0| && *(Current + 2) == '.' 1455| 0| && (Current + 3 == End || isBlankOrBreak(Current + 3))) 1456| 0| return scanDocumentIndicator(false); 1457| 0| 1458| 0| if (*Current == '[') 1459| 0| return scanFlowCollectionStart(true); 1460| 0| 1461| 0| if (*Current == '{') 1462| 0| return scanFlowCollectionStart(false); 1463| 0| 1464| 0| if (*Current == ']') 1465| 0| return scanFlowCollectionEnd(true); 1466| 0| 1467| 0| if (*Current == '}') 1468| 0| return scanFlowCollectionEnd(false); 1469| 0| 1470| 0| if (*Current == ',') 1471| 0| return scanFlowEntry(); 1472| 0| 1473| 0| if (*Current == '-' && isBlankOrBreak(Current + 1)) 1474| 0| return scanBlockEntry(); 1475| 0| 1476| 0| if (*Current == '?' && (FlowLevel || isBlankOrBreak(Current + 1))) 1477| 0| return scanKey(); 1478| 0| 1479| 0| if (*Current == ':' && (FlowLevel || isBlankOrBreak(Current + 1))) 1480| 0| return scanValue(); 1481| 0| 1482| 0| if (*Current == '*') 1483| 0| return scanAliasOrAnchor(true); 1484| 0| 1485| 0| if (*Current == '&') 1486| 0| return scanAliasOrAnchor(false); 1487| 0| 1488| 0| if (*Current == '!') 1489| 0| return scanTag(); 1490| 0| 1491| 0| if (*Current == '|' && !FlowLevel) 1492| 0| return scanBlockScalar(true); 1493| 0| 1494| 0| if (*Current == '>' && !FlowLevel) 1495| 0| return scanBlockScalar(false); 1496| 0| 1497| 0| if (*Current == '\'') 1498| 0| return scanFlowScalar(false); 1499| 0| 1500| 0| if (*Current == '"') 1501| 0| return scanFlowScalar(true); 1502| 0| 1503| 0| // Get a plain scalar. 1504| 0| StringRef FirstChar(Current, 1); 1505| 0| if (!(isBlankOrBreak(Current) 1506| 0| || FirstChar.find_first_of("-?:,[]{}#&*!|>'\"%@`") != StringRef::npos) 1507| 0| || (*Current == '-' && !isBlankOrBreak(Current + 1)) 1508| 0| || (!FlowLevel && (*Current == '?' || *Current == ':') 1509| 0| && isBlankOrBreak(Current + 1)) 1510| 0| || (!FlowLevel && *Current == ':' 1511| 0| && Current + 2 < End 1512| 0| && *(Current + 1) == ':' 1513| 0| && !isBlankOrBreak(Current + 2))) 1514| 0| return scanPlainScalar(); 1515| 0| 1516| 0| setError("Unrecognized character while tokenizing."); 1517| 0| return false; 1518| 0|} 1519| | 1520| |Stream::Stream(StringRef Input, SourceMgr &SM) 1521| 0| : scanner(new Scanner(Input, SM)), CurrentDoc() {} 1522| | 1523| |Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM) 1524| 0| : scanner(new Scanner(InputBuffer, SM)), CurrentDoc() {} 1525| | 1526| 0|Stream::~Stream() {} 1527| | 1528| 0|bool Stream::failed() { return scanner->failed(); } 1529| | 1530| 0|void Stream::printError(Node *N, const Twine &Msg) { 1531| 0| scanner->printError( N->getSourceRange().Start 1532| 0| , SourceMgr::DK_Error 1533| 0| , Msg 1534| 0| , N->getSourceRange()); 1535| 0|} 1536| | 1537| 0|document_iterator Stream::begin() { 1538| 0| if (CurrentDoc) 1539| 0| report_fatal_error("Can only iterate over the stream once"); 1540| 0| 1541| 0| // Skip Stream-Start. 1542| 0| scanner->getNext(); 1543| 0| 1544| 0| CurrentDoc.reset(new Document(*this)); 1545| 0| return document_iterator(CurrentDoc); 1546| 0|} 1547| | 1548| 0|document_iterator Stream::end() { 1549| 0| return document_iterator(); 1550| 0|} 1551| | 1552| 0|void Stream::skip() { 1553| 0| for (document_iterator i = begin(), e = end(); i != e; ++i) 1554| 0| i->skip(); 1555| 0|} 1556| | 1557| |Node::Node(unsigned int Type, std::unique_ptr &D, StringRef A, 1558| | StringRef T) 1559| 0| : Doc(D), TypeID(Type), Anchor(A), Tag(T) { 1560| 0| SMLoc Start = SMLoc::getFromPointer(peekNext().Range.begin()); 1561| 0| SourceRange = SMRange(Start, Start); 1562| 0|} 1563| | 1564| 0|std::string Node::getVerbatimTag() const { 1565| 0| StringRef Raw = getRawTag(); 1566| 0| if (!Raw.empty() && Raw != "!") { 1567| 0| std::string Ret; 1568| 0| if (Raw.find_last_of('!') == 0) { 1569| 0| Ret = Doc->getTagMap().find("!")->second; 1570| 0| Ret += Raw.substr(1); 1571| 0| return Ret; 1572| 0| } else if (Raw.startswith("!!")) { 1573| 0| Ret = Doc->getTagMap().find("!!")->second; 1574| 0| Ret += Raw.substr(2); 1575| 0| return Ret; 1576| 0| } else { 1577| 0| StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1); 1578| 0| std::map::const_iterator It = 1579| 0| Doc->getTagMap().find(TagHandle); 1580| 0| if (It != Doc->getTagMap().end()) 1581| 0| Ret = It->second; 1582| 0| else { 1583| 0| Token T; 1584| 0| T.Kind = Token::TK_Tag; 1585| 0| T.Range = TagHandle; 1586| 0| setError(Twine("Unknown tag handle ") + TagHandle, T); 1587| 0| } 1588| 0| Ret += Raw.substr(Raw.find_last_of('!') + 1); 1589| 0| return Ret; 1590| 0| } 1591| 0| } 1592| 0| 1593| 0| switch (getType()) { 1594| 0| case NK_Null: 1595| 0| return "tag:yaml.org,2002:null"; 1596| 0| case NK_Scalar: 1597| 0| // TODO: Tag resolution. 1598| 0| return "tag:yaml.org,2002:str"; 1599| 0| case NK_Mapping: 1600| 0| return "tag:yaml.org,2002:map"; 1601| 0| case NK_Sequence: 1602| 0| return "tag:yaml.org,2002:seq"; 1603| 0| } 1604| 0| 1605| 0| return ""; 1606| 0|} 1607| | 1608| 0|Token &Node::peekNext() { 1609| 0| return Doc->peekNext(); 1610| 0|} 1611| | 1612| 0|Token Node::getNext() { 1613| 0| return Doc->getNext(); 1614| 0|} 1615| | 1616| 0|Node *Node::parseBlockNode() { 1617| 0| return Doc->parseBlockNode(); 1618| 0|} 1619| | 1620| 0|BumpPtrAllocator &Node::getAllocator() { 1621| 0| return Doc->NodeAllocator; 1622| 0|} 1623| | 1624| 0|void Node::setError(const Twine &Msg, Token &Tok) const { 1625| 0| Doc->setError(Msg, Tok); 1626| 0|} 1627| | 1628| 0|bool Node::failed() const { 1629| 0| return Doc->failed(); 1630| 0|} 1631| | 1632| | 1633| | 1634| 0|StringRef ScalarNode::getValue(SmallVectorImpl &Storage) const { 1635| 0| // TODO: Handle newlines properly. We need to remove leading whitespace. 1636| 0| if (Value[0] == '"') { // Double quoted. 1637| 0| // Pull off the leading and trailing "s. 1638| 0| StringRef UnquotedValue = Value.substr(1, Value.size() - 2); 1639| 0| // Search for characters that would require unescaping the value. 1640| 0| StringRef::size_type i = UnquotedValue.find_first_of("\\\r\n"); 1641| 0| if (i != StringRef::npos) 1642| 0| return unescapeDoubleQuoted(UnquotedValue, i, Storage); 1643| 0| return UnquotedValue; 1644| 0| } else if (Value[0] == '\'') { // Single quoted. 1645| 0| // Pull off the leading and trailing 's. 1646| 0| StringRef UnquotedValue = Value.substr(1, Value.size() - 2); 1647| 0| StringRef::size_type i = UnquotedValue.find('\''); 1648| 0| if (i != StringRef::npos) { 1649| 0| // We're going to need Storage. 1650| 0| Storage.clear(); 1651| 0| Storage.reserve(UnquotedValue.size()); 1652| 0| for (; i != StringRef::npos; i = UnquotedValue.find('\'')) { 1653| 0| StringRef Valid(UnquotedValue.begin(), i); 1654| 0| Storage.insert(Storage.end(), Valid.begin(), Valid.end()); 1655| 0| Storage.push_back('\''); 1656| 0| UnquotedValue = UnquotedValue.substr(i + 2); 1657| 0| } 1658| 0| Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end()); 1659| 0| return StringRef(Storage.begin(), Storage.size()); 1660| 0| } 1661| 0| return UnquotedValue; 1662| 0| } 1663| 0| // Plain or block. 1664| 0| return Value.rtrim(" "); 1665| 0|} 1666| | 1667| |StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue 1668| | , StringRef::size_type i 1669| | , SmallVectorImpl &Storage) 1670| 0| const { 1671| 0| // Use Storage to build proper value. 1672| 0| Storage.clear(); 1673| 0| Storage.reserve(UnquotedValue.size()); 1674| 0| for (; i != StringRef::npos; i = UnquotedValue.find_first_of("\\\r\n")) { 1675| 0| // Insert all previous chars into Storage. 1676| 0| StringRef Valid(UnquotedValue.begin(), i); 1677| 0| Storage.insert(Storage.end(), Valid.begin(), Valid.end()); 1678| 0| // Chop off inserted chars. 1679| 0| UnquotedValue = UnquotedValue.substr(i); 1680| 0| 1681| 0| assert(!UnquotedValue.empty() && "Can't be empty!"); 1682| 0| 1683| 0| // Parse escape or line break. 1684| 0| switch (UnquotedValue[0]) { 1685| 0| case '\r': 1686| 0| case '\n': 1687| 0| Storage.push_back('\n'); 1688| 0| if ( UnquotedValue.size() > 1 1689| 0| && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n')) 1690| 0| UnquotedValue = UnquotedValue.substr(1); 1691| 0| UnquotedValue = UnquotedValue.substr(1); 1692| 0| break; 1693| 0| default: 1694| 0| if (UnquotedValue.size() == 1) 1695| 0| // TODO: Report error. 1696| 0| break; 1697| 0| UnquotedValue = UnquotedValue.substr(1); 1698| 0| switch (UnquotedValue[0]) { 1699| 0| default: { 1700| 0| Token T; 1701| 0| T.Range = StringRef(UnquotedValue.begin(), 1); 1702| 0| setError("Unrecognized escape code!", T); 1703| 0| return ""; 1704| 0| } 1705| 0| case '\r': 1706| 0| case '\n': 1707| 0| // Remove the new line. 1708| 0| if ( UnquotedValue.size() > 1 1709| 0| && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n')) 1710| 0| UnquotedValue = UnquotedValue.substr(1); 1711| 0| // If this was just a single byte newline, it will get skipped 1712| 0| // below. 1713| 0| break; 1714| 0| case '0': 1715| 0| Storage.push_back(0x00); 1716| 0| break; 1717| 0| case 'a': 1718| 0| Storage.push_back(0x07); 1719| 0| break; 1720| 0| case 'b': 1721| 0| Storage.push_back(0x08); 1722| 0| break; 1723| 0| case 't': 1724| 0| case 0x09: 1725| 0| Storage.push_back(0x09); 1726| 0| break; 1727| 0| case 'n': 1728| 0| Storage.push_back(0x0A); 1729| 0| break; 1730| 0| case 'v': 1731| 0| Storage.push_back(0x0B); 1732| 0| break; 1733| 0| case 'f': 1734| 0| Storage.push_back(0x0C); 1735| 0| break; 1736| 0| case 'r': 1737| 0| Storage.push_back(0x0D); 1738| 0| break; 1739| 0| case 'e': 1740| 0| Storage.push_back(0x1B); 1741| 0| break; 1742| 0| case ' ': 1743| 0| Storage.push_back(0x20); 1744| 0| break; 1745| 0| case '"': 1746| 0| Storage.push_back(0x22); 1747| 0| break; 1748| 0| case '/': 1749| 0| Storage.push_back(0x2F); 1750| 0| break; 1751| 0| case '\\': 1752| 0| Storage.push_back(0x5C); 1753| 0| break; 1754| 0| case 'N': 1755| 0| encodeUTF8(0x85, Storage); 1756| 0| break; 1757| 0| case '_': 1758| 0| encodeUTF8(0xA0, Storage); 1759| 0| break; 1760| 0| case 'L': 1761| 0| encodeUTF8(0x2028, Storage); 1762| 0| break; 1763| 0| case 'P': 1764| 0| encodeUTF8(0x2029, Storage); 1765| 0| break; 1766| 0| case 'x': { 1767| 0| if (UnquotedValue.size() < 3) 1768| 0| // TODO: Report error. 1769| 0| break; 1770| 0| unsigned int UnicodeScalarValue; 1771| 0| if (UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue)) 1772| 0| // TODO: Report error. 1773| 0| UnicodeScalarValue = 0xFFFD; 1774| 0| encodeUTF8(UnicodeScalarValue, Storage); 1775| 0| UnquotedValue = UnquotedValue.substr(2); 1776| 0| break; 1777| 0| } 1778| 0| case 'u': { 1779| 0| if (UnquotedValue.size() < 5) 1780| 0| // TODO: Report error. 1781| 0| break; 1782| 0| unsigned int UnicodeScalarValue; 1783| 0| if (UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue)) 1784| 0| // TODO: Report error. 1785| 0| UnicodeScalarValue = 0xFFFD; 1786| 0| encodeUTF8(UnicodeScalarValue, Storage); 1787| 0| UnquotedValue = UnquotedValue.substr(4); 1788| 0| break; 1789| 0| } 1790| 0| case 'U': { 1791| 0| if (UnquotedValue.size() < 9) 1792| 0| // TODO: Report error. 1793| 0| break; 1794| 0| unsigned int UnicodeScalarValue; 1795| 0| if (UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue)) 1796| 0| // TODO: Report error. 1797| 0| UnicodeScalarValue = 0xFFFD; 1798| 0| encodeUTF8(UnicodeScalarValue, Storage); 1799| 0| UnquotedValue = UnquotedValue.substr(8); 1800| 0| break; 1801| 0| } 1802| 0| } 1803| 0| UnquotedValue = UnquotedValue.substr(1); 1804| 0| } 1805| 0| } 1806| 0| Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end()); 1807| 0| return StringRef(Storage.begin(), Storage.size()); 1808| 0|} 1809| | 1810| 0|Node *KeyValueNode::getKey() { 1811| 0| if (Key) 1812| 0| return Key; 1813| 0| // Handle implicit null keys. 1814| 0| { 1815| 0| Token &t = peekNext(); 1816| 0| if ( t.Kind == Token::TK_BlockEnd 1817| 0| || t.Kind == Token::TK_Value 1818| 0| || t.Kind == Token::TK_Error) { 1819| 0| return Key = new (getAllocator()) NullNode(Doc); 1820| 0| } 1821| 0| if (t.Kind == Token::TK_Key) 1822| 0| getNext(); // skip TK_Key. 1823| 0| } 1824| 0| 1825| 0| // Handle explicit null keys. 1826| 0| Token &t = peekNext(); 1827| 0| if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Value) { 1828| 0| return Key = new (getAllocator()) NullNode(Doc); 1829| 0| } 1830| 0| 1831| 0| // We've got a normal key. 1832| 0| return Key = parseBlockNode(); 1833| 0|} 1834| | 1835| 0|Node *KeyValueNode::getValue() { 1836| 0| if (Value) 1837| 0| return Value; 1838| 0| getKey()->skip(); 1839| 0| if (failed()) 1840| 0| return Value = new (getAllocator()) NullNode(Doc); 1841| 0| 1842| 0| // Handle implicit null values. 1843| 0| { 1844| 0| Token &t = peekNext(); 1845| 0| if ( t.Kind == Token::TK_BlockEnd 1846| 0| || t.Kind == Token::TK_FlowMappingEnd 1847| 0| || t.Kind == Token::TK_Key 1848| 0| || t.Kind == Token::TK_FlowEntry 1849| 0| || t.Kind == Token::TK_Error) { 1850| 0| return Value = new (getAllocator()) NullNode(Doc); 1851| 0| } 1852| 0| 1853| 0| if (t.Kind != Token::TK_Value) { 1854| 0| setError("Unexpected token in Key Value.", t); 1855| 0| return Value = new (getAllocator()) NullNode(Doc); 1856| 0| } 1857| 0| getNext(); // skip TK_Value. 1858| 0| } 1859| 0| 1860| 0| // Handle explicit null values. 1861| 0| Token &t = peekNext(); 1862| 0| if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Key) { 1863| 0| return Value = new (getAllocator()) NullNode(Doc); 1864| 0| } 1865| 0| 1866| 0| // We got a normal value. 1867| 0| return Value = parseBlockNode(); 1868| 0|} 1869| | 1870| 0|void MappingNode::increment() { 1871| 0| if (failed()) { 1872| 0| IsAtEnd = true; 1873| 0| CurrentEntry = nullptr; 1874| 0| return; 1875| 0| } 1876| 0| if (CurrentEntry) { 1877| 0| CurrentEntry->skip(); 1878| 0| if (Type == MT_Inline) { 1879| 0| IsAtEnd = true; 1880| 0| CurrentEntry = nullptr; 1881| 0| return; 1882| 0| } 1883| 0| } 1884| 0| Token T = peekNext(); 1885| 0| if (T.Kind == Token::TK_Key || T.Kind == Token::TK_Scalar) { 1886| 0| // KeyValueNode eats the TK_Key. That way it can detect null keys. 1887| 0| CurrentEntry = new (getAllocator()) KeyValueNode(Doc); 1888| 0| } else if (Type == MT_Block) { 1889| 0| switch (T.Kind) { 1890| 0| case Token::TK_BlockEnd: 1891| 0| getNext(); 1892| 0| IsAtEnd = true; 1893| 0| CurrentEntry = nullptr; 1894| 0| break; 1895| 0| default: 1896| 0| setError("Unexpected token. Expected Key or Block End", T); 1897| 0| [[clang::fallthrough]]; 1898| 0| case Token::TK_Error: 1899| 0| IsAtEnd = true; 1900| 0| CurrentEntry = nullptr; 1901| 0| } 1902| 0| } else { 1903| 0| switch (T.Kind) { 1904| 0| case Token::TK_FlowEntry: 1905| 0| // Eat the flow entry and recurse. 1906| 0| getNext(); 1907| 0| return increment(); 1908| 0| case Token::TK_FlowMappingEnd: 1909| 0| getNext(); 1910| 0| [[clang::fallthrough]]; 1911| 0| case Token::TK_Error: 1912| 0| // Set this to end iterator. 1913| 0| IsAtEnd = true; 1914| 0| CurrentEntry = nullptr; 1915| 0| break; 1916| 0| default: 1917| 0| setError( "Unexpected token. Expected Key, Flow Entry, or Flow " 1918| 0| "Mapping End." 1919| 0| , T); 1920| 0| IsAtEnd = true; 1921| 0| CurrentEntry = nullptr; 1922| 0| } 1923| 0| } 1924| 0|} 1925| | 1926| 0|void SequenceNode::increment() { 1927| 0| if (failed()) { 1928| 0| IsAtEnd = true; 1929| 0| CurrentEntry = nullptr; 1930| 0| return; 1931| 0| } 1932| 0| if (CurrentEntry) 1933| 0| CurrentEntry->skip(); 1934| 0| Token T = peekNext(); 1935| 0| if (SeqType == ST_Block) { 1936| 0| switch (T.Kind) { 1937| 0| case Token::TK_BlockEntry: 1938| 0| getNext(); 1939| 0| CurrentEntry = parseBlockNode(); 1940| 0| if (!CurrentEntry) { // An error occurred. 1941| 0| IsAtEnd = true; 1942| 0| CurrentEntry = nullptr; 1943| 0| } 1944| 0| break; 1945| 0| case Token::TK_BlockEnd: 1946| 0| getNext(); 1947| 0| IsAtEnd = true; 1948| 0| CurrentEntry = nullptr; 1949| 0| break; 1950| 0| default: 1951| 0| setError("Unexpected token. Expected Block Entry or Block End.", T); 1952| 0| [[clang::fallthrough]]; 1953| 0| case Token::TK_Error: 1954| 0| IsAtEnd = true; 1955| 0| CurrentEntry = nullptr; 1956| 0| } 1957| 0| } else if (SeqType == ST_Indentless) { 1958| 0| switch (T.Kind) { 1959| 0| case Token::TK_BlockEntry: 1960| 0| getNext(); 1961| 0| CurrentEntry = parseBlockNode(); 1962| 0| if (!CurrentEntry) { // An error occurred. 1963| 0| IsAtEnd = true; 1964| 0| CurrentEntry = nullptr; 1965| 0| } 1966| 0| break; 1967| 0| default: 1968| 0| case Token::TK_Error: 1969| 0| IsAtEnd = true; 1970| 0| CurrentEntry = nullptr; 1971| 0| } 1972| 0| } else if (SeqType == ST_Flow) { 1973| 0| switch (T.Kind) { 1974| 0| case Token::TK_FlowEntry: 1975| 0| // Eat the flow entry and recurse. 1976| 0| getNext(); 1977| 0| WasPreviousTokenFlowEntry = true; 1978| 0| return increment(); 1979| 0| case Token::TK_FlowSequenceEnd: 1980| 0| getNext(); 1981| 0| [[clang::fallthrough]]; 1982| 0| case Token::TK_Error: 1983| 0| // Set this to end iterator. 1984| 0| IsAtEnd = true; 1985| 0| CurrentEntry = nullptr; 1986| 0| break; 1987| 0| case Token::TK_StreamEnd: 1988| 0| case Token::TK_DocumentEnd: 1989| 0| case Token::TK_DocumentStart: 1990| 0| setError("Could not find closing ]!", T); 1991| 0| // Set this to end iterator. 1992| 0| IsAtEnd = true; 1993| 0| CurrentEntry = nullptr; 1994| 0| break; 1995| 0| default: 1996| 0| if (!WasPreviousTokenFlowEntry) { 1997| 0| setError("Expected , between entries!", T); 1998| 0| IsAtEnd = true; 1999| 0| CurrentEntry = nullptr; 2000| 0| break; 2001| 0| } 2002| 0| // Otherwise it must be a flow entry. 2003| 0| CurrentEntry = parseBlockNode(); 2004| 0| if (!CurrentEntry) { 2005| 0| IsAtEnd = true; 2006| 0| } 2007| 0| WasPreviousTokenFlowEntry = false; 2008| 0| break; 2009| 0| } 2010| 0| } 2011| 0|} 2012| | 2013| 0|Document::Document(Stream &S) : stream(S), Root(nullptr) { 2014| 0| // Tag maps starts with two default mappings. 2015| 0| TagMap["!"] = "!"; 2016| 0| TagMap["!!"] = "tag:yaml.org,2002:"; 2017| 0| 2018| 0| if (parseDirectives()) 2019| 0| expectToken(Token::TK_DocumentStart); 2020| 0| Token &T = peekNext(); 2021| 0| if (T.Kind == Token::TK_DocumentStart) 2022| 0| getNext(); 2023| 0|} 2024| | 2025| 0|bool Document::skip() { 2026| 0| if (stream.scanner->failed()) 2027| 0| return false; 2028| 0| if (!Root) 2029| 0| getRoot(); 2030| 0| Root->skip(); 2031| 0| Token &T = peekNext(); 2032| 0| if (T.Kind == Token::TK_StreamEnd) 2033| 0| return false; 2034| 0| if (T.Kind == Token::TK_DocumentEnd) { 2035| 0| getNext(); 2036| 0| return skip(); 2037| 0| } 2038| 0| return true; 2039| 0|} 2040| | 2041| 0|Token &Document::peekNext() { 2042| 0| return stream.scanner->peekNext(); 2043| 0|} 2044| | 2045| 0|Token Document::getNext() { 2046| 0| return stream.scanner->getNext(); 2047| 0|} 2048| | 2049| 0|void Document::setError(const Twine &Message, Token &Location) const { 2050| 0| stream.scanner->setError(Message, Location.Range.begin()); 2051| 0|} 2052| | 2053| 0|bool Document::failed() const { 2054| 0| return stream.scanner->failed(); 2055| 0|} 2056| | 2057| 0|Node *Document::parseBlockNode() { 2058| 0| Token T = peekNext(); 2059| 0| // Handle properties. 2060| 0| Token AnchorInfo; 2061| 0| Token TagInfo; 2062| 0|parse_property: 2063| 0| switch (T.Kind) { 2064| 0| case Token::TK_Alias: 2065| 0| getNext(); 2066| 0| return new (NodeAllocator) AliasNode(stream.CurrentDoc, T.Range.substr(1)); 2067| 0| case Token::TK_Anchor: 2068| 0| if (AnchorInfo.Kind == Token::TK_Anchor) { 2069| 0| setError("Already encountered an anchor for this node!", T); 2070| 0| return nullptr; 2071| 0| } 2072| 0| AnchorInfo = getNext(); // Consume TK_Anchor. 2073| 0| T = peekNext(); 2074| 0| goto parse_property; 2075| 0| case Token::TK_Tag: 2076| 0| if (TagInfo.Kind == Token::TK_Tag) { 2077| 0| setError("Already encountered a tag for this node!", T); 2078| 0| return nullptr; 2079| 0| } 2080| 0| TagInfo = getNext(); // Consume TK_Tag. 2081| 0| T = peekNext(); 2082| 0| goto parse_property; 2083| 0| default: 2084| 0| break; 2085| 0| } 2086| 0| 2087| 0| switch (T.Kind) { 2088| 0| case Token::TK_BlockEntry: 2089| 0| // We got an unindented BlockEntry sequence. This is not terminated with 2090| 0| // a BlockEnd. 2091| 0| // Don't eat the TK_BlockEntry, SequenceNode needs it. 2092| 0| return new (NodeAllocator) SequenceNode( stream.CurrentDoc 2093| 0| , AnchorInfo.Range.substr(1) 2094| 0| , TagInfo.Range 2095| 0| , SequenceNode::ST_Indentless); 2096| 0| case Token::TK_BlockSequenceStart: 2097| 0| getNext(); 2098| 0| return new (NodeAllocator) 2099| 0| SequenceNode( stream.CurrentDoc 2100| 0| , AnchorInfo.Range.substr(1) 2101| 0| , TagInfo.Range 2102| 0| , SequenceNode::ST_Block); 2103| 0| case Token::TK_BlockMappingStart: 2104| 0| getNext(); 2105| 0| return new (NodeAllocator) 2106| 0| MappingNode( stream.CurrentDoc 2107| 0| , AnchorInfo.Range.substr(1) 2108| 0| , TagInfo.Range 2109| 0| , MappingNode::MT_Block); 2110| 0| case Token::TK_FlowSequenceStart: 2111| 0| getNext(); 2112| 0| return new (NodeAllocator) 2113| 0| SequenceNode( stream.CurrentDoc 2114| 0| , AnchorInfo.Range.substr(1) 2115| 0| , TagInfo.Range 2116| 0| , SequenceNode::ST_Flow); 2117| 0| case Token::TK_FlowMappingStart: 2118| 0| getNext(); 2119| 0| return new (NodeAllocator) 2120| 0| MappingNode( stream.CurrentDoc 2121| 0| , AnchorInfo.Range.substr(1) 2122| 0| , TagInfo.Range 2123| 0| , MappingNode::MT_Flow); 2124| 0| case Token::TK_Scalar: 2125| 0| getNext(); 2126| 0| return new (NodeAllocator) 2127| 0| ScalarNode( stream.CurrentDoc 2128| 0| , AnchorInfo.Range.substr(1) 2129| 0| , TagInfo.Range 2130| 0| , T.Range); 2131| 0| case Token::TK_Key: 2132| 0| // Don't eat the TK_Key, KeyValueNode expects it. 2133| 0| return new (NodeAllocator) 2134| 0| MappingNode( stream.CurrentDoc 2135| 0| , AnchorInfo.Range.substr(1) 2136| 0| , TagInfo.Range 2137| 0| , MappingNode::MT_Inline); 2138| 0| case Token::TK_DocumentStart: 2139| 0| case Token::TK_DocumentEnd: 2140| 0| case Token::TK_StreamEnd: 2141| 0| default: 2142| 0| // TODO: Properly handle tags. "[!!str ]" should resolve to !!str "", not 2143| 0| // !!null null. 2144| 0| return new (NodeAllocator) NullNode(stream.CurrentDoc); 2145| 0| case Token::TK_Error: 2146| 0| return nullptr; 2147| 0| } 2148| 0| llvm_unreachable("Control flow shouldn't reach here."); 2149| 0| return nullptr; 2150| 0|} 2151| | 2152| 0|bool Document::parseDirectives() { 2153| 0| bool isDirective = false; 2154| 0| while (true) { 2155| 0| Token T = peekNext(); 2156| 0| if (T.Kind == Token::TK_TagDirective) { 2157| 0| parseTAGDirective(); 2158| 0| isDirective = true; 2159| 0| } else if (T.Kind == Token::TK_VersionDirective) { 2160| 0| parseYAMLDirective(); 2161| 0| isDirective = true; 2162| 0| } else 2163| 0| break; 2164| 0| } 2165| 0| return isDirective; 2166| 0|} 2167| | 2168| 0|void Document::parseYAMLDirective() { 2169| 0| getNext(); // Eat %YAML 2170| 0|} 2171| | 2172| 0|void Document::parseTAGDirective() { 2173| 0| Token Tag = getNext(); // %TAG 2174| 0| StringRef T = Tag.Range; 2175| 0| // Strip %TAG 2176| 0| T = T.substr(T.find_first_of(" \t")).ltrim(" \t"); 2177| 0| std::size_t HandleEnd = T.find_first_of(" \t"); 2178| 0| StringRef TagHandle = T.substr(0, HandleEnd); 2179| 0| StringRef TagPrefix = T.substr(HandleEnd).ltrim(" \t"); 2180| 0| TagMap[TagHandle] = TagPrefix; 2181| 0|} 2182| | 2183| 0|bool Document::expectToken(int TK) { 2184| 0| Token T = getNext(); 2185| 0| if (T.Kind != TK) { 2186| 0| setError("Unexpected token", T); 2187| 0| return false; 2188| 0| } 2189| 0| return true; 2190| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/circular_raw_ostream.cpp: 1| |//===- circular_raw_ostream.cpp - Implement circular_raw_ostream ----------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This implements support for circular buffered streams. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/circular_raw_ostream.h" 15| |#include 16| |using namespace llvm; 17| | 18| 0|void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) { 19| 0| if (BufferSize == 0) { 20| 0| TheStream->write(Ptr, Size); 21| 0| return; 22| 0| } 23| 0| 24| 0| // Write into the buffer, wrapping if necessary. 25| 0| while (Size != 0) { 26| 0| unsigned Bytes = 27| 0| std::min(unsigned(Size), unsigned(BufferSize - (Cur - BufferArray))); 28| 0| memcpy(Cur, Ptr, Bytes); 29| 0| Size -= Bytes; 30| 0| Cur += Bytes; 31| 0| if (Cur == BufferArray + BufferSize) { 32| 0| // Reset the output pointer to the start of the buffer. 33| 0| Cur = BufferArray; 34| 0| Filled = true; 35| 0| } 36| 0| } 37| 0|} 38| | 39| 0|void circular_raw_ostream::flushBufferWithBanner() { 40| 0| if (BufferSize != 0) { 41| 0| // Write out the buffer 42| 0| TheStream->write(Banner, std::strlen(Banner)); 43| 0| flushBuffer(); 44| 0| } 45| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/ArrayRef.h: 1| |//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_ARRAYREF_H 11| |#define LLVM_ADT_ARRAYREF_H 12| | 13| |#include "llvm/ADT/None.h" 14| |#include "llvm/ADT/SmallVector.h" 15| |#include 16| | 17| |namespace llvm { 18| | 19| | /// ArrayRef - Represent a constant reference to an array (0 or more elements 20| | /// consecutively in memory), i.e. a start pointer and a length. It allows 21| | /// various APIs to take consecutive elements easily and conveniently. 22| | /// 23| | /// This class does not own the underlying data, it is expected to be used in 24| | /// situations where the data resides in some other buffer, whose lifetime 25| | /// extends past that of the ArrayRef. For this reason, it is not in general 26| | /// safe to store an ArrayRef. 27| | /// 28| | /// This is intended to be trivially copyable, so it should be passed by 29| | /// value. 30| | template 31| | class ArrayRef { 32| | public: 33| | typedef const T *iterator; 34| | typedef const T *const_iterator; 35| | typedef size_t size_type; 36| | 37| | typedef std::reverse_iterator reverse_iterator; 38| | 39| | private: 40| | /// The start of the array, in an external buffer. 41| | const T *Data; 42| | 43| | /// The number of elements. 44| | size_type Length; 45| | 46| | public: 47| | /// @name Constructors 48| | /// @{ 49| | 50| | /// Construct an empty ArrayRef. 51| 0| /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} 52| | 53| | /// Construct an empty ArrayRef from None. 54| 0| /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMRangeEEC2ENS_8NoneTypeE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMFixItEEC2ENS_8NoneTypeE ------------------ 55| | 56| | /// Construct an ArrayRef from a single element. 57| | /*implicit*/ ArrayRef(const T &OneElt) 58| 0| : Data(&OneElt), Length(1) {} 59| | 60| | /// Construct an ArrayRef from a pointer and length. 61| | /*implicit*/ ArrayRef(const T *data, size_t length) 62| 0| : Data(data), Length(length) {} 63| | 64| | /// Construct an ArrayRef from a range. 65| | ArrayRef(const T *begin, const T *end) 66| | : Data(begin), Length(end - begin) {} 67| | 68| | /// Construct an ArrayRef from a SmallVector. This is templated in order to 69| | /// avoid instantiating SmallVectorTemplateCommon whenever we 70| | /// copy-construct an ArrayRef. 71| | template 72| | /*implicit*/ ArrayRef(const SmallVectorTemplateCommon &Vec) 73| 0| : Data(Vec.data()), Length(Vec.size()) { 74| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_9StringRefEEC2IvEERKNS_25SmallVectorTemplateCommonIS1_T_EE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_7SMFixItEEC2IvEERKNS_25SmallVectorTemplateCommonIS1_T_EE ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINSt3__14pairIjjEEEC2IvEERKNS_25SmallVectorTemplateCommonIS3_T_EE ------------------ 75| | 76| | /// Construct an ArrayRef from a std::vector. 77| | template 78| | /*implicit*/ ArrayRef(const std::vector &Vec) 79| | : Data(Vec.data()), Length(Vec.size()) {} 80| | 81| | /// Construct an ArrayRef from a C array. 82| | template 83| | /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) 84| 0| : Data(Arr), Length(N) {} ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_3sys16UnicodeCharRangeEEC2ILm548EEERAT__KS2_ ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_3sys16UnicodeCharRangeEEC2ILm218EEERAT__KS2_ ------------------ | Unexecuted instantiation: _ZN4llvm8ArrayRefINS_3sys16UnicodeCharRangeEEC2ILm15EEERAT__KS2_ ------------------ 85| | 86| | /// Construct an ArrayRef from a std::initializer_list. 87| | /*implicit*/ ArrayRef(const std::initializer_list &Vec) 88| | : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), 89| | Length(Vec.size()) {} 90| | 91| | /// Construct an ArrayRef from ArrayRef. This uses SFINAE to 92| | /// ensure that only ArrayRefs of pointers can be converted. 93| | template 94| | ArrayRef(const ArrayRef &A, 95| | typename std::enable_if< 96| | std::is_convertible::value>::type* = 0) 97| | : Data(A.data()), Length(A.size()) {} 98| | 99| | /// @} 100| | /// @name Simple Operations 101| | /// @{ 102| | 103| 0| iterator begin() const { return Data; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIcE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIPKcE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_7SMFixItEE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_3sys16UnicodeCharRangeEE5beginEv ------------------ 104| 0| iterator end() const { return Data + Length; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIcE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIPKcE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_7SMFixItEE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_3sys16UnicodeCharRangeEE3endEv ------------------ 105| | 106| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 107| | reverse_iterator rend() const { return reverse_iterator(begin()); } 108| | 109| | /// empty - Check if the array is empty. 110| 0| bool empty() const { return Length == 0; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIcE5emptyEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_9StringRefEE5emptyEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_7SMFixItEE5emptyEv ------------------ 111| | 112| | const T *data() const { return Data; } 113| | 114| | /// size - Get the array size. 115| 0| size_t size() const { return Length; } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIcE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_7SMRangeEE4sizeEv ------------------ 116| | 117| | /// front - Get the first element. 118| | const T &front() const { 119| | assert(!empty()); 120| | return Data[0]; 121| | } 122| | 123| | /// back - Get the last element. 124| | const T &back() const { 125| | assert(!empty()); 126| | return Data[Length-1]; 127| | } 128| | 129| | // copy - Allocate copy in Allocator and return ArrayRef to it. 130| | template ArrayRef copy(Allocator &A) { 131| | T *Buff = A.template Allocate(Length); 132| | std::copy(begin(), end(), Buff); 133| | return ArrayRef(Buff, Length); 134| | } 135| | 136| | /// equals - Check for element-wise equality. 137| | bool equals(ArrayRef RHS) const { 138| | if (Length != RHS.Length) 139| | return false; 140| | if (Length == 0) 141| | return true; 142| | return std::equal(begin(), end(), RHS.begin()); 143| | } 144| | 145| | /// slice(n) - Chop off the first N elements of the array. 146| | ArrayRef slice(unsigned N) const { 147| | assert(N <= size() && "Invalid specifier"); 148| | return ArrayRef(data()+N, size()-N); 149| | } 150| | 151| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 152| | /// elements in the array. 153| | ArrayRef slice(unsigned N, unsigned M) const { 154| | assert(N+M <= size() && "Invalid specifier"); 155| | return ArrayRef(data()+N, M); 156| | } 157| | 158| | // \brief Drop the last \p N elements of the array. 159| | ArrayRef drop_back(unsigned N = 1) const { 160| | assert(size() >= N && "Dropping more elements than exist"); 161| | return slice(0, size() - N); 162| | } 163| | 164| | /// @} 165| | /// @name Operator Overloads 166| | /// @{ 167| 0| const T &operator[](size_t Index) const { 168| 0| assert(Index < Length && "Invalid index!"); 169| 0| return Data[Index]; 170| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefIcEixEm ------------------ | Unexecuted instantiation: _ZNK4llvm8ArrayRefINS_7SMRangeEEixEm ------------------ 171| | 172| | /// @} 173| | /// @name Expensive Operations 174| | /// @{ 175| 0| std::vector vec() const { 176| 0| return std::vector(Data, Data+Length); 177| 0| } 178| | 179| | /// @} 180| | /// @name Conversion operators 181| | /// @{ 182| | operator std::vector() const { 183| | return std::vector(Data, Data+Length); 184| | } 185| | 186| | /// @} 187| | }; 188| | 189| | /// MutableArrayRef - Represent a mutable reference to an array (0 or more 190| | /// elements consecutively in memory), i.e. a start pointer and a length. It 191| | /// allows various APIs to take and modify consecutive elements easily and 192| | /// conveniently. 193| | /// 194| | /// This class does not own the underlying data, it is expected to be used in 195| | /// situations where the data resides in some other buffer, whose lifetime 196| | /// extends past that of the MutableArrayRef. For this reason, it is not in 197| | /// general safe to store a MutableArrayRef. 198| | /// 199| | /// This is intended to be trivially copyable, so it should be passed by 200| | /// value. 201| | template 202| | class MutableArrayRef : public ArrayRef { 203| | public: 204| | typedef T *iterator; 205| | 206| | typedef std::reverse_iterator reverse_iterator; 207| | 208| | /// Construct an empty MutableArrayRef. 209| | /*implicit*/ MutableArrayRef() : ArrayRef() {} 210| | 211| | /// Construct an empty MutableArrayRef from None. 212| | /*implicit*/ MutableArrayRef(NoneType) : ArrayRef() {} 213| | 214| | /// Construct an MutableArrayRef from a single element. 215| | /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef(OneElt) {} 216| | 217| | /// Construct an MutableArrayRef from a pointer and length. 218| | /*implicit*/ MutableArrayRef(T *data, size_t length) 219| | : ArrayRef(data, length) {} 220| | 221| | /// Construct an MutableArrayRef from a range. 222| | MutableArrayRef(T *begin, T *end) : ArrayRef(begin, end) {} 223| | 224| | /// Construct an MutableArrayRef from a SmallVector. 225| | /*implicit*/ MutableArrayRef(SmallVectorImpl &Vec) 226| | : ArrayRef(Vec) {} 227| | 228| | /// Construct a MutableArrayRef from a std::vector. 229| | /*implicit*/ MutableArrayRef(std::vector &Vec) 230| | : ArrayRef(Vec) {} 231| | 232| | /// Construct an MutableArrayRef from a C array. 233| | template 234| | /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) 235| | : ArrayRef(Arr) {} 236| | 237| | T *data() const { return const_cast(ArrayRef::data()); } 238| | 239| | iterator begin() const { return data(); } 240| | iterator end() const { return data() + this->size(); } 241| | 242| | reverse_iterator rbegin() const { return reverse_iterator(end()); } 243| | reverse_iterator rend() const { return reverse_iterator(begin()); } 244| | 245| | /// front - Get the first element. 246| | T &front() const { 247| | assert(!this->empty()); 248| | return data()[0]; 249| | } 250| | 251| | /// back - Get the last element. 252| | T &back() const { 253| | assert(!this->empty()); 254| | return data()[this->size()-1]; 255| | } 256| | 257| | /// slice(n) - Chop off the first N elements of the array. 258| | MutableArrayRef slice(unsigned N) const { 259| | assert(N <= this->size() && "Invalid specifier"); 260| | return MutableArrayRef(data()+N, this->size()-N); 261| | } 262| | 263| | /// slice(n, m) - Chop off the first N elements of the array, and keep M 264| | /// elements in the array. 265| | MutableArrayRef slice(unsigned N, unsigned M) const { 266| | assert(N+M <= this->size() && "Invalid specifier"); 267| | return MutableArrayRef(data()+N, M); 268| | } 269| | 270| | /// @} 271| | /// @name Operator Overloads 272| | /// @{ 273| | T &operator[](size_t Index) const { 274| | assert(Index < this->size() && "Invalid index!"); 275| | return data()[Index]; 276| | } 277| | }; 278| | 279| | /// @name ArrayRef Convenience constructors 280| | /// @{ 281| | 282| | /// Construct an ArrayRef from a single element. 283| | template 284| | ArrayRef makeArrayRef(const T &OneElt) { 285| | return OneElt; 286| | } 287| | 288| | /// Construct an ArrayRef from a pointer and length. 289| | template 290| 0| ArrayRef makeArrayRef(const T *data, size_t length) { 291| 0| return ArrayRef(data, length); 292| 0| } 293| | 294| | /// Construct an ArrayRef from a range. 295| | template 296| | ArrayRef makeArrayRef(const T *begin, const T *end) { 297| | return ArrayRef(begin, end); 298| | } 299| | 300| | /// Construct an ArrayRef from a SmallVector. 301| | template 302| | ArrayRef makeArrayRef(const SmallVectorImpl &Vec) { 303| | return Vec; 304| | } 305| | 306| | /// Construct an ArrayRef from a SmallVector. 307| | template 308| | ArrayRef makeArrayRef(const SmallVector &Vec) { 309| | return Vec; 310| | } 311| | 312| | /// Construct an ArrayRef from a std::vector. 313| | template 314| | ArrayRef makeArrayRef(const std::vector &Vec) { 315| | return Vec; 316| | } 317| | 318| | /// Construct an ArrayRef from a C array. 319| | template 320| | ArrayRef makeArrayRef(const T (&Arr)[N]) { 321| | return ArrayRef(Arr); 322| | } 323| | 324| | /// @} 325| | /// @name ArrayRef Comparison Operators 326| | /// @{ 327| | 328| | template 329| | inline bool operator==(ArrayRef LHS, ArrayRef RHS) { 330| | return LHS.equals(RHS); 331| | } 332| | 333| | template 334| | inline bool operator!=(ArrayRef LHS, ArrayRef RHS) { 335| | return !(LHS == RHS); 336| | } 337| | 338| | /// @} 339| | 340| | // ArrayRefs can be treated like a POD type. 341| | template struct isPodLike; 342| | template struct isPodLike > { 343| | static const bool value = true; 344| | }; 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/DenseMapInfo.h: 1| |//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines DenseMapInfo traits for DenseMap. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_DENSEMAPINFO_H 15| |#define LLVM_ADT_DENSEMAPINFO_H 16| | 17| |#include "llvm/Support/PointerLikeTypeTraits.h" 18| |#include "llvm/Support/type_traits.h" 19| | 20| |namespace llvm { 21| | 22| |template 23| |struct DenseMapInfo { 24| | //static inline T getEmptyKey(); 25| | //static inline T getTombstoneKey(); 26| | //static unsigned getHashValue(const T &Val); 27| | //static bool isEqual(const T &LHS, const T &RHS); 28| |}; 29| | 30| |// Provide DenseMapInfo for all pointers. 31| |template 32| |struct DenseMapInfo { 33| | static inline T* getEmptyKey() { 34| | uintptr_t Val = static_cast(-1); 35| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 36| | return reinterpret_cast(Val); 37| | } 38| | static inline T* getTombstoneKey() { 39| | uintptr_t Val = static_cast(-2); 40| | Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; 41| | return reinterpret_cast(Val); 42| | } 43| 0| static unsigned getHashValue(const T *PtrVal) { 44| 0| return (unsigned((uintptr_t)PtrVal) >> 4) ^ 45| 0| (unsigned((uintptr_t)PtrVal) >> 9); 46| 0| } 47| | static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } 48| |}; 49| | 50| |// Provide DenseMapInfo for chars. 51| |template<> struct DenseMapInfo { 52| 0| static inline char getEmptyKey() { return ~0; } 53| 0| static inline char getTombstoneKey() { return ~0 - 1; } 54| 0| static unsigned getHashValue(const char& Val) { return Val * 37U; } 55| 0| static bool isEqual(const char &LHS, const char &RHS) { 56| 0| return LHS == RHS; 57| 0| } 58| |}; 59| | 60| |// Provide DenseMapInfo for unsigned ints. 61| |template<> struct DenseMapInfo { 62| 0| static inline unsigned getEmptyKey() { return ~0U; } 63| 0| static inline unsigned getTombstoneKey() { return ~0U - 1; } 64| 0| static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } 65| 0| static bool isEqual(const unsigned& LHS, const unsigned& RHS) { 66| 0| return LHS == RHS; 67| 0| } 68| |}; 69| | 70| |// Provide DenseMapInfo for unsigned longs. 71| |template<> struct DenseMapInfo { 72| | static inline unsigned long getEmptyKey() { return ~0UL; } 73| | static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } 74| | static unsigned getHashValue(const unsigned long& Val) { 75| | return (unsigned)(Val * 37UL); 76| | } 77| | static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { 78| | return LHS == RHS; 79| | } 80| |}; 81| | 82| |// Provide DenseMapInfo for unsigned long longs. 83| |template<> struct DenseMapInfo { 84| | static inline unsigned long long getEmptyKey() { return ~0ULL; } 85| | static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } 86| | static unsigned getHashValue(const unsigned long long& Val) { 87| | return (unsigned)(Val * 37ULL); 88| | } 89| | static bool isEqual(const unsigned long long& LHS, 90| | const unsigned long long& RHS) { 91| | return LHS == RHS; 92| | } 93| |}; 94| | 95| |// Provide DenseMapInfo for ints. 96| |template<> struct DenseMapInfo { 97| 0| static inline int getEmptyKey() { return 0x7fffffff; } 98| 0| static inline int getTombstoneKey() { return -0x7fffffff - 1; } 99| 0| static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } 100| 0| static bool isEqual(const int& LHS, const int& RHS) { 101| 0| return LHS == RHS; 102| 0| } 103| |}; 104| | 105| |// Provide DenseMapInfo for longs. 106| |template<> struct DenseMapInfo { 107| 0| static inline long getEmptyKey() { 108| 0| return (1UL << (sizeof(long) * 8 - 1)) - 1UL; 109| 0| } 110| 0| static inline long getTombstoneKey() { return getEmptyKey() - 1L; } 111| 0| static unsigned getHashValue(const long& Val) { 112| 0| return (unsigned)(Val * 37UL); 113| 0| } 114| 0| static bool isEqual(const long& LHS, const long& RHS) { 115| 0| return LHS == RHS; 116| 0| } 117| |}; 118| | 119| |// Provide DenseMapInfo for long longs. 120| |template<> struct DenseMapInfo { 121| 0| static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } 122| 0| static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } 123| 0| static unsigned getHashValue(const long long& Val) { 124| 0| return (unsigned)(Val * 37ULL); 125| 0| } 126| | static bool isEqual(const long long& LHS, 127| 0| const long long& RHS) { 128| 0| return LHS == RHS; 129| 0| } 130| |}; 131| | 132| |// Provide DenseMapInfo for all pairs whose members have info. 133| |template 134| |struct DenseMapInfo > { 135| | typedef std::pair Pair; 136| | typedef DenseMapInfo FirstInfo; 137| | typedef DenseMapInfo SecondInfo; 138| | 139| | static inline Pair getEmptyKey() { 140| | return std::make_pair(FirstInfo::getEmptyKey(), 141| | SecondInfo::getEmptyKey()); 142| | } 143| | static inline Pair getTombstoneKey() { 144| | return std::make_pair(FirstInfo::getTombstoneKey(), 145| | SecondInfo::getTombstoneKey()); 146| | } 147| | static unsigned getHashValue(const Pair& PairVal) { 148| | uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 149| | | (uint64_t)SecondInfo::getHashValue(PairVal.second); 150| | key += ~(key << 32); 151| | key ^= (key >> 22); 152| | key += ~(key << 13); 153| | key ^= (key >> 8); 154| | key += (key << 3); 155| | key ^= (key >> 15); 156| | key += ~(key << 27); 157| | key ^= (key >> 31); 158| | return (unsigned)key; 159| | } 160| | static bool isEqual(const Pair &LHS, const Pair &RHS) { 161| | return FirstInfo::isEqual(LHS.first, RHS.first) && 162| | SecondInfo::isEqual(LHS.second, RHS.second); 163| | } 164| |}; 165| | 166| |} // end namespace llvm 167| | 168| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Hashing.h: 1| |//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the newly proposed standard C++ interfaces for hashing 11| |// arbitrary data and building hash functions for user-defined types. This 12| |// interface was originally proposed in N3333[1] and is currently under review 13| |// for inclusion in a future TR and/or standard. 14| |// 15| |// The primary interfaces provide are comprised of one type and three functions: 16| |// 17| |// -- 'hash_code' class is an opaque type representing the hash code for some 18| |// data. It is the intended product of hashing, and can be used to implement 19| |// hash tables, checksumming, and other common uses of hashes. It is not an 20| |// integer type (although it can be converted to one) because it is risky 21| |// to assume much about the internals of a hash_code. In particular, each 22| |// execution of the program has a high probability of producing a different 23| |// hash_code for a given input. Thus their values are not stable to save or 24| |// persist, and should only be used during the execution for the 25| |// construction of hashing datastructures. 26| |// 27| |// -- 'hash_value' is a function designed to be overloaded for each 28| |// user-defined type which wishes to be used within a hashing context. It 29| |// should be overloaded within the user-defined type's namespace and found 30| |// via ADL. Overloads for primitive types are provided by this library. 31| |// 32| |// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid 33| |// programmers in easily and intuitively combining a set of data into 34| |// a single hash_code for their object. They should only logically be used 35| |// within the implementation of a 'hash_value' routine or similar context. 36| |// 37| |// Note that 'hash_combine_range' contains very special logic for hashing 38| |// a contiguous array of integers or pointers. This logic is *extremely* fast, 39| |// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were 40| |// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys 41| |// under 32-bytes. 42| |// 43| |//===----------------------------------------------------------------------===// 44| | 45| |#ifndef LLVM_ADT_HASHING_H 46| |#define LLVM_ADT_HASHING_H 47| | 48| |#include "llvm/Support/DataTypes.h" 49| |#include "llvm/Support/Host.h" 50| |#include "llvm/Support/SwapByteOrder.h" 51| |#include "llvm/Support/type_traits.h" 52| |#include 53| |#include 54| |#include 55| |#include 56| |#include 57| | 58| |namespace llvm { 59| | 60| |/// \brief An opaque object representing a hash code. 61| |/// 62| |/// This object represents the result of hashing some entity. It is intended to 63| |/// be used to implement hashtables or other hashing-based data structures. 64| |/// While it wraps and exposes a numeric value, this value should not be 65| |/// trusted to be stable or predictable across processes or executions. 66| |/// 67| |/// In order to obtain the hash_code for an object 'x': 68| |/// \code 69| |/// using llvm::hash_value; 70| |/// llvm::hash_code code = hash_value(x); 71| |/// \endcode 72| |class hash_code { 73| | size_t value; 74| | 75| |public: 76| | /// \brief Default construct a hash_code. 77| | /// Note that this leaves the value uninitialized. 78| 0| hash_code() {} 79| | 80| | /// \brief Form a hash code directly from a numerical value. 81| 0| hash_code(size_t value) : value(value) {} 82| | 83| | /// \brief Convert the hash code to its numerical value for use. 84| | /*explicit*/ operator size_t() const { return value; } 85| | 86| 0| friend bool operator==(const hash_code &lhs, const hash_code &rhs) { 87| 0| return lhs.value == rhs.value; 88| 0| } 89| 0| friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { 90| 0| return lhs.value != rhs.value; 91| 0| } 92| | 93| | /// \brief Allow a hash_code to be directly run through hash_value. 94| | friend size_t hash_value(const hash_code &code) { return code.value; } 95| |}; 96| | 97| |/// \brief Compute a hash_code for any integer value. 98| |/// 99| |/// Note that this function is intended to compute the same hash_code for 100| |/// a particular value without regard to the pre-promotion type. This is in 101| |/// contrast to hash_combine which may produce different hash_codes for 102| |/// differing argument types even if they would implicit promote to a common 103| |/// type without changing the value. 104| |template 105| |typename std::enable_if::value, hash_code>::type 106| |hash_value(T value); 107| | 108| |/// \brief Compute a hash_code for a pointer's address. 109| |/// 110| |/// N.B.: This hashes the *address*. Not the value and not the type. 111| |template hash_code hash_value(const T *ptr); 112| | 113| |/// \brief Compute a hash_code for a pair of objects. 114| |template 115| |hash_code hash_value(const std::pair &arg); 116| | 117| |/// \brief Compute a hash_code for a standard string. 118| |template 119| |hash_code hash_value(const std::basic_string &arg); 120| | 121| | 122| |/// \brief Override the execution seed with a fixed value. 123| |/// 124| |/// This hashing library uses a per-execution seed designed to change on each 125| |/// run with high probability in order to ensure that the hash codes are not 126| |/// attackable and to ensure that output which is intended to be stable does 127| |/// not rely on the particulars of the hash codes produced. 128| |/// 129| |/// That said, there are use cases where it is important to be able to 130| |/// reproduce *exactly* a specific behavior. To that end, we provide a function 131| |/// which will forcibly set the seed to a fixed value. This must be done at the 132| |/// start of the program, before any hashes are computed. Also, it cannot be 133| |/// undone. This makes it thread-hostile and very hard to use outside of 134| |/// immediately on start of a simple program designed for reproducible 135| |/// behavior. 136| |void set_fixed_execution_hash_seed(size_t fixed_value); 137| | 138| | 139| |// All of the implementation details of actually computing the various hash 140| |// code values are held within this namespace. These routines are included in 141| |// the header file mainly to allow inlining and constant propagation. 142| |namespace hashing { 143| |namespace detail { 144| | 145| 0|inline uint64_t fetch64(const char *p) { 146| 0| uint64_t result; 147| 0| memcpy(&result, p, sizeof(result)); 148| 0| if (sys::IsBigEndianHost) 149| 0| sys::swapByteOrder(result); 150| 0| return result; 151| 0|} 152| | 153| 0|inline uint32_t fetch32(const char *p) { 154| 0| uint32_t result; 155| 0| memcpy(&result, p, sizeof(result)); 156| 0| if (sys::IsBigEndianHost) 157| 0| sys::swapByteOrder(result); 158| 0| return result; 159| 0|} 160| | 161| |/// Some primes between 2^63 and 2^64 for various uses. 162| |static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; 163| |static const uint64_t k1 = 0xb492b66fbe98f273ULL; 164| |static const uint64_t k2 = 0x9ae16a3b2f90404fULL; 165| |static const uint64_t k3 = 0xc949d7c7509e6557ULL; 166| | 167| |/// \brief Bitwise right rotate. 168| |/// Normally this will compile to a single instruction, especially if the 169| |/// shift is a manifest constant. 170| 0|inline uint64_t rotate(uint64_t val, size_t shift) { 171| 0| // Avoid shifting by 64: doing so yields an undefined result. 172| 0| return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); 173| 0|} 174| | 175| 0|inline uint64_t shift_mix(uint64_t val) { 176| 0| return val ^ (val >> 47); 177| 0|} 178| | 179| 0|inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { 180| 0| // Murmur-inspired hashing. 181| 0| const uint64_t kMul = 0x9ddfea08eb382d69ULL; 182| 0| uint64_t a = (low ^ high) * kMul; 183| 0| a ^= (a >> 47); 184| 0| uint64_t b = (high ^ a) * kMul; 185| 0| b ^= (b >> 47); 186| 0| b *= kMul; 187| 0| return b; 188| 0|} 189| | 190| 0|inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { 191| 0| uint8_t a = s[0]; 192| 0| uint8_t b = s[len >> 1]; 193| 0| uint8_t c = s[len - 1]; 194| 0| uint32_t y = static_cast(a) + (static_cast(b) << 8); 195| 0| uint32_t z = len + (static_cast(c) << 2); 196| 0| return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; 197| 0|} 198| | 199| 0|inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { 200| 0| uint64_t a = fetch32(s); 201| 0| return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); 202| 0|} 203| | 204| 0|inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { 205| 0| uint64_t a = fetch64(s); 206| 0| uint64_t b = fetch64(s + len - 8); 207| 0| return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; 208| 0|} 209| | 210| 0|inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { 211| 0| uint64_t a = fetch64(s) * k1; 212| 0| uint64_t b = fetch64(s + 8); 213| 0| uint64_t c = fetch64(s + len - 8) * k2; 214| 0| uint64_t d = fetch64(s + len - 16) * k0; 215| 0| return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, 216| 0| a + rotate(b ^ k3, 20) - c + len + seed); 217| 0|} 218| | 219| 0|inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { 220| 0| uint64_t z = fetch64(s + 24); 221| 0| uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; 222| 0| uint64_t b = rotate(a + z, 52); 223| 0| uint64_t c = rotate(a, 37); 224| 0| a += fetch64(s + 8); 225| 0| c += rotate(a, 7); 226| 0| a += fetch64(s + 16); 227| 0| uint64_t vf = a + z; 228| 0| uint64_t vs = b + rotate(a, 31) + c; 229| 0| a = fetch64(s + 16) + fetch64(s + len - 32); 230| 0| z = fetch64(s + len - 8); 231| 0| b = rotate(a + z, 52); 232| 0| c = rotate(a, 37); 233| 0| a += fetch64(s + len - 24); 234| 0| c += rotate(a, 7); 235| 0| a += fetch64(s + len - 16); 236| 0| uint64_t wf = a + z; 237| 0| uint64_t ws = b + rotate(a, 31) + c; 238| 0| uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); 239| 0| return shift_mix((seed ^ (r * k0)) + vs) * k2; 240| 0|} 241| | 242| 0|inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { 243| 0| if (length >= 4 && length <= 8) 244| 0| return hash_4to8_bytes(s, length, seed); 245| 0| if (length > 8 && length <= 16) 246| 0| return hash_9to16_bytes(s, length, seed); 247| 0| if (length > 16 && length <= 32) 248| 0| return hash_17to32_bytes(s, length, seed); 249| 0| if (length > 32) 250| 0| return hash_33to64_bytes(s, length, seed); 251| 0| if (length != 0) 252| 0| return hash_1to3_bytes(s, length, seed); 253| 0| 254| 0| return k2 ^ seed; 255| 0|} 256| | 257| |/// \brief The intermediate state used during hashing. 258| |/// Currently, the algorithm for computing hash codes is based on CityHash and 259| |/// keeps 56 bytes of arbitrary state. 260| |struct hash_state { 261| | uint64_t h0, h1, h2, h3, h4, h5, h6; 262| | 263| | /// \brief Create a new hash_state structure and initialize it based on the 264| | /// seed and the first 64-byte chunk. 265| | /// This effectively performs the initial mix. 266| 0| static hash_state create(const char *s, uint64_t seed) { 267| 0| hash_state state = { 268| 0| 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), 269| 0| seed * k1, shift_mix(seed), 0 }; 270| 0| state.h6 = hash_16_bytes(state.h4, state.h5); 271| 0| state.mix(s); 272| 0| return state; 273| 0| } 274| | 275| | /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' 276| | /// and 'b', including whatever is already in 'a' and 'b'. 277| 0| static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { 278| 0| a += fetch64(s); 279| 0| uint64_t c = fetch64(s + 24); 280| 0| b = rotate(b + a + c, 21); 281| 0| uint64_t d = a; 282| 0| a += fetch64(s + 8) + fetch64(s + 16); 283| 0| b += rotate(a, 44) + d; 284| 0| a += c; 285| 0| } 286| | 287| | /// \brief Mix in a 64-byte buffer of data. 288| | /// We mix all 64 bytes even when the chunk length is smaller, but we 289| | /// record the actual length. 290| 0| void mix(const char *s) { 291| 0| h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; 292| 0| h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; 293| 0| h0 ^= h6; 294| 0| h1 += h3 + fetch64(s + 40); 295| 0| h2 = rotate(h2 + h5, 33) * k1; 296| 0| h3 = h4 * k1; 297| 0| h4 = h0 + h5; 298| 0| mix_32_bytes(s, h3, h4); 299| 0| h5 = h2 + h6; 300| 0| h6 = h1 + fetch64(s + 16); 301| 0| mix_32_bytes(s + 32, h5, h6); 302| 0| std::swap(h2, h0); 303| 0| } 304| | 305| | /// \brief Compute the final 64-bit hash code value based on the current 306| | /// state and the length of bytes hashed. 307| 0| uint64_t finalize(size_t length) { 308| 0| return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, 309| 0| hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); 310| 0| } 311| |}; 312| | 313| | 314| |/// \brief A global, fixed seed-override variable. 315| |/// 316| |/// This variable can be set using the \see llvm::set_fixed_execution_seed 317| |/// function. See that function for details. Do not, under any circumstances, 318| |/// set or read this variable. 319| |extern size_t fixed_seed_override; 320| | 321| 0|inline size_t get_execution_seed() { 322| 0| // FIXME: This needs to be a per-execution seed. This is just a placeholder 323| 0| // implementation. Switching to a per-execution seed is likely to flush out 324| 0| // instability bugs and so will happen as its own commit. 325| 0| // 326| 0| // However, if there is a fixed seed override set the first time this is 327| 0| // called, return that instead of the per-execution seed. 328| 0| const uint64_t seed_prime = 0xff51afd7ed558ccdULL; 329| 0| static size_t seed = fixed_seed_override ? fixed_seed_override 330| 0| : (size_t)seed_prime; 331| 0| return seed; 332| 0|} 333| | 334| | 335| |/// \brief Trait to indicate whether a type's bits can be hashed directly. 336| |/// 337| |/// A type trait which is true if we want to combine values for hashing by 338| |/// reading the underlying data. It is false if values of this type must 339| |/// first be passed to hash_value, and the resulting hash_codes combined. 340| |// 341| |// FIXME: We want to replace is_integral_or_enum and is_pointer here with 342| |// a predicate which asserts that comparing the underlying storage of two 343| |// values of the type for equality is equivalent to comparing the two values 344| |// for equality. For all the platforms we care about, this holds for integers 345| |// and pointers, but there are platforms where it doesn't and we would like to 346| |// support user-defined types which happen to satisfy this property. 347| |template struct is_hashable_data 348| | : std::integral_constant::value || 349| | std::is_pointer::value) && 350| | 64 % sizeof(T) == 0)> {}; 351| | 352| |// Special case std::pair to detect when both types are viable and when there 353| |// is no alignment-derived padding in the pair. This is a bit of a lie because 354| |// std::pair isn't truly POD, but it's close enough in all reasonable 355| |// implementations for our use case of hashing the underlying data. 356| |template struct is_hashable_data > 357| | : std::integral_constant::value && 358| | is_hashable_data::value && 359| | (sizeof(T) + sizeof(U)) == 360| | sizeof(std::pair))> {}; 361| | 362| |/// \brief Helper to get the hashable data representation for a type. 363| |/// This variant is enabled when the type itself can be used. 364| |template 365| |typename std::enable_if::value, T>::type 366| |get_hashable_data(const T &value) { 367| | return value; 368| |} 369| |/// \brief Helper to get the hashable data representation for a type. 370| |/// This variant is enabled when we must first call hash_value and use the 371| |/// result as our data. 372| |template 373| |typename std::enable_if::value, size_t>::type 374| |get_hashable_data(const T &value) { 375| | using ::llvm::hash_value; 376| | return hash_value(value); 377| |} 378| | 379| |/// \brief Helper to store data from a value into a buffer and advance the 380| |/// pointer into that buffer. 381| |/// 382| |/// This routine first checks whether there is enough space in the provided 383| |/// buffer, and if not immediately returns false. If there is space, it 384| |/// copies the underlying bytes of value into the buffer, advances the 385| |/// buffer_ptr past the copied bytes, and returns true. 386| |template 387| |bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, 388| | size_t offset = 0) { 389| | size_t store_size = sizeof(value) - offset; 390| | if (buffer_ptr + store_size > buffer_end) 391| | return false; 392| | const char *value_data = reinterpret_cast(&value); 393| | memcpy(buffer_ptr, value_data + offset, store_size); 394| | buffer_ptr += store_size; 395| | return true; 396| |} 397| | 398| |/// \brief Implement the combining of integral values into a hash_code. 399| |/// 400| |/// This overload is selected when the value type of the iterator is 401| |/// integral. Rather than computing a hash_code for each object and then 402| |/// combining them, this (as an optimization) directly combines the integers. 403| |template 404| |hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { 405| | const size_t seed = get_execution_seed(); 406| | char buffer[64], *buffer_ptr = buffer; 407| | char *const buffer_end = std::end(buffer); 408| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 409| | get_hashable_data(*first))) 410| | ++first; 411| | if (first == last) 412| | return hash_short(buffer, buffer_ptr - buffer, seed); 413| | assert(buffer_ptr == buffer_end); 414| | 415| | hash_state state = state.create(buffer, seed); 416| | size_t length = 64; 417| | while (first != last) { 418| | // Fill up the buffer. We don't clear it, which re-mixes the last round 419| | // when only a partial 64-byte chunk is left. 420| | buffer_ptr = buffer; 421| | while (first != last && store_and_advance(buffer_ptr, buffer_end, 422| | get_hashable_data(*first))) 423| | ++first; 424| | 425| | // Rotate the buffer if we did a partial fill in order to simulate doing 426| | // a mix of the last 64-bytes. That is how the algorithm works when we 427| | // have a contiguous byte sequence, and we want to emulate that here. 428| | std::rotate(buffer, buffer_ptr, buffer_end); 429| | 430| | // Mix this chunk into the current state. 431| | state.mix(buffer); 432| | length += buffer_ptr - buffer; 433| | }; 434| | 435| | return state.finalize(length); 436| |} 437| | 438| |/// \brief Implement the combining of integral values into a hash_code. 439| |/// 440| |/// This overload is selected when the value type of the iterator is integral 441| |/// and when the input iterator is actually a pointer. Rather than computing 442| |/// a hash_code for each object and then combining them, this (as an 443| |/// optimization) directly combines the integers. Also, because the integers 444| |/// are stored in contiguous memory, this routine avoids copying each value 445| |/// and directly reads from the underlying memory. 446| |template 447| |typename std::enable_if::value, hash_code>::type 448| 0|hash_combine_range_impl(ValueT *first, ValueT *last) { 449| 0| const size_t seed = get_execution_seed(); 450| 0| const char *s_begin = reinterpret_cast(first); 451| 0| const char *s_end = reinterpret_cast(last); 452| 0| const size_t length = std::distance(s_begin, s_end); 453| 0| if (length <= 64) 454| 0| return hash_short(s_begin, length, seed); 455| 0| 456| 0| const char *s_aligned_end = s_begin + (length & ~63); 457| 0| hash_state state = state.create(s_begin, seed); 458| 0| s_begin += 64; 459| 0| while (s_begin != s_aligned_end) { 460| 0| state.mix(s_begin); 461| 0| s_begin += 64; 462| 0| } 463| 0| if (length & 63) 464| 0| state.mix(s_end - 64); 465| 0| 466| 0| return state.finalize(length); 467| 0|} 468| | 469| |} // namespace detail 470| |} // namespace hashing 471| | 472| | 473| |/// \brief Compute a hash_code for a sequence of values. 474| |/// 475| |/// This hashes a sequence of values. It produces the same hash_code as 476| |/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences 477| |/// and is significantly faster given pointers and types which can be hashed as 478| |/// a sequence of bytes. 479| |template 480| 0|hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { 481| 0| return ::llvm::hashing::detail::hash_combine_range_impl(first, last); 482| 0|} 483| | 484| | 485| |// Implementation details for hash_combine. 486| |namespace hashing { 487| |namespace detail { 488| | 489| |/// \brief Helper class to manage the recursive combining of hash_combine 490| |/// arguments. 491| |/// 492| |/// This class exists to manage the state and various calls involved in the 493| |/// recursive combining of arguments used in hash_combine. It is particularly 494| |/// useful at minimizing the code in the recursive calls to ease the pain 495| |/// caused by a lack of variadic functions. 496| |struct hash_combine_recursive_helper { 497| | char buffer[64]; 498| | hash_state state; 499| | const size_t seed; 500| | 501| |public: 502| | /// \brief Construct a recursive hash combining helper. 503| | /// 504| | /// This sets up the state for a recursive hash combine, including getting 505| | /// the seed and buffer setup. 506| | hash_combine_recursive_helper() 507| 0| : seed(get_execution_seed()) {} 508| | 509| | /// \brief Combine one chunk of data into the current in-flight hash. 510| | /// 511| | /// This merges one chunk of data into the hash. First it tries to buffer 512| | /// the data. If the buffer is full, it hashes the buffer into its 513| | /// hash_state, empties it, and then merges the new chunk in. This also 514| | /// handles cases where the data straddles the end of the buffer. 515| | template 516| | char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { 517| | if (!store_and_advance(buffer_ptr, buffer_end, data)) { 518| | // Check for skew which prevents the buffer from being packed, and do 519| | // a partial store into the buffer to fill it. This is only a concern 520| | // with the variadic combine because that formation can have varying 521| | // argument types. 522| | size_t partial_store_size = buffer_end - buffer_ptr; 523| | memcpy(buffer_ptr, &data, partial_store_size); 524| | 525| | // If the store fails, our buffer is full and ready to hash. We have to 526| | // either initialize the hash state (on the first full buffer) or mix 527| | // this buffer into the existing hash state. Length tracks the *hashed* 528| | // length, not the buffered length. 529| | if (length == 0) { 530| | state = state.create(buffer, seed); 531| | length = 64; 532| | } else { 533| | // Mix this chunk into the current state and bump length up by 64. 534| | state.mix(buffer); 535| | length += 64; 536| | } 537| | // Reset the buffer_ptr to the head of the buffer for the next chunk of 538| | // data. 539| | buffer_ptr = buffer; 540| | 541| | // Try again to store into the buffer -- this cannot fail as we only 542| | // store types smaller than the buffer. 543| | if (!store_and_advance(buffer_ptr, buffer_end, data, 544| | partial_store_size)) 545| | abort(); 546| | } 547| | return buffer_ptr; 548| | } 549| | 550| | /// \brief Recursive, variadic combining method. 551| | /// 552| | /// This function recurses through each argument, combining that argument 553| | /// into a single hash. 554| | template 555| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, 556| | const T &arg, const Ts &...args) { 557| | buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); 558| | 559| | // Recurse to the next argument. 560| | return combine(length, buffer_ptr, buffer_end, args...); 561| | } 562| | 563| | /// \brief Base case for recursive, variadic combining. 564| | /// 565| | /// The base case when combining arguments recursively is reached when all 566| | /// arguments have been handled. It flushes the remaining buffer and 567| | /// constructs a hash_code. 568| | hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { 569| | // Check whether the entire set of values fit in the buffer. If so, we'll 570| | // use the optimized short hashing routine and skip state entirely. 571| | if (length == 0) 572| | return hash_short(buffer, buffer_ptr - buffer, seed); 573| | 574| | // Mix the final buffer, rotating it if we did a partial fill in order to 575| | // simulate doing a mix of the last 64-bytes. That is how the algorithm 576| | // works when we have a contiguous byte sequence, and we want to emulate 577| | // that here. 578| | std::rotate(buffer, buffer_ptr, buffer_end); 579| | 580| | // Mix this chunk into the current state. 581| | state.mix(buffer); 582| | length += buffer_ptr - buffer; 583| | 584| | return state.finalize(length); 585| | } 586| |}; 587| | 588| |} // namespace detail 589| |} // namespace hashing 590| | 591| |/// \brief Combine values into a single hash_code. 592| |/// 593| |/// This routine accepts a varying number of arguments of any type. It will 594| |/// attempt to combine them into a single hash_code. For user-defined types it 595| |/// attempts to call a \see hash_value overload (via ADL) for the type. For 596| |/// integer and pointer types it directly combines their data into the 597| |/// resulting hash_code. 598| |/// 599| |/// The result is suitable for returning from a user's hash_value 600| |/// *implementation* for their user-defined type. Consumers of a type should 601| |/// *not* call this routine, they should instead call 'hash_value'. 602| |template hash_code hash_combine(const Ts &...args) { 603| | // Recursively hash each argument using a helper class. 604| | ::llvm::hashing::detail::hash_combine_recursive_helper helper; 605| | return helper.combine(0, helper.buffer, helper.buffer + 64, args...); 606| |} 607| | 608| |// Implementation details for implementations of hash_value overloads provided 609| |// here. 610| |namespace hashing { 611| |namespace detail { 612| | 613| |/// \brief Helper to hash the value of a single integer. 614| |/// 615| |/// Overloads for smaller integer types are not provided to ensure consistent 616| |/// behavior in the presence of integral promotions. Essentially, 617| |/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. 618| 0|inline hash_code hash_integer_value(uint64_t value) { 619| 0| // Similar to hash_4to8_bytes but using a seed instead of length. 620| 0| const uint64_t seed = get_execution_seed(); 621| 0| const char *s = reinterpret_cast(&value); 622| 0| const uint64_t a = fetch32(s); 623| 0| return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); 624| 0|} 625| | 626| |} // namespace detail 627| |} // namespace hashing 628| | 629| |// Declared and documented above, but defined here so that any of the hashing 630| |// infrastructure is available. 631| |template 632| |typename std::enable_if::value, hash_code>::type 633| |hash_value(T value) { 634| | return ::llvm::hashing::detail::hash_integer_value(value); 635| |} 636| | 637| |// Declared and documented above, but defined here so that any of the hashing 638| |// infrastructure is available. 639| |template hash_code hash_value(const T *ptr) { 640| | return ::llvm::hashing::detail::hash_integer_value( 641| | reinterpret_cast(ptr)); 642| |} 643| | 644| |// Declared and documented above, but defined here so that any of the hashing 645| |// infrastructure is available. 646| |template 647| |hash_code hash_value(const std::pair &arg) { 648| | return hash_combine(arg.first, arg.second); 649| |} 650| | 651| |// Declared and documented above, but defined here so that any of the hashing 652| |// infrastructure is available. 653| |template 654| |hash_code hash_value(const std::basic_string &arg) { 655| | return hash_combine_range(arg.begin(), arg.end()); 656| |} 657| | 658| |} // namespace llvm 659| | 660| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/IntrusiveRefCntPtr.h: 1| |//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines IntrusiveRefCntPtr, a template class that 11| |// implements a "smart" pointer for objects that maintain their own 12| |// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 13| |// generic base classes for objects that wish to have their lifetimes 14| |// managed using reference counting. 15| |// 16| |// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 17| |// LLVM-style casting. 18| |// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H 22| |#define LLVM_ADT_INTRUSIVEREFCNTPTR_H 23| | 24| |#include "llvm/Support/Casting.h" 25| |#include "llvm/Support/Compiler.h" 26| |#include 27| |#include 28| | 29| |namespace llvm { 30| | 31| | template 32| | class IntrusiveRefCntPtr; 33| | 34| |//===----------------------------------------------------------------------===// 35| |/// RefCountedBase - A generic base class for objects that wish to 36| |/// have their lifetimes managed using reference counts. Classes 37| |/// subclass RefCountedBase to obtain such functionality, and are 38| |/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 39| |/// which automatically handle the management of reference counts. 40| |/// Objects that subclass RefCountedBase should not be allocated on 41| |/// the stack, as invoking "delete" (which is called when the 42| |/// reference count hits 0) on such objects is an error. 43| |//===----------------------------------------------------------------------===// 44| | template 45| | class RefCountedBase { 46| | mutable unsigned ref_cnt; 47| | 48| | public: 49| | RefCountedBase() : ref_cnt(0) {} 50| | RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 51| | 52| 0| void Retain() const { ++ref_cnt; } ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail12DirIterStateEE6RetainEv ------------------ | Unexecuted instantiation: _ZNK4llvm14RefCountedBaseINS_3sys2fs6detail15RecDirIterStateEE6RetainEv ------------------ 53| 0| void Release() const { 54| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 55| 0| if (--ref_cnt == 0) delete static_cast(this); 56| 0| } 57| | }; 58| | 59| |//===----------------------------------------------------------------------===// 60| |/// RefCountedBaseVPTR - A class that has the same function as 61| |/// RefCountedBase, but with a virtual destructor. Should be used 62| |/// instead of RefCountedBase for classes that already have virtual 63| |/// methods to enforce dynamic allocation via 'new'. Classes that 64| |/// inherit from RefCountedBaseVPTR can't be allocated on stack - 65| |/// attempting to do this will produce a compile error. 66| |//===----------------------------------------------------------------------===// 67| | class RefCountedBaseVPTR { 68| | mutable unsigned ref_cnt; 69| | virtual void anchor(); 70| | 71| | protected: 72| 0| RefCountedBaseVPTR() : ref_cnt(0) {} 73| 0| RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 74| | 75| 0| virtual ~RefCountedBaseVPTR() {} 76| | 77| 0| void Retain() const { ++ref_cnt; } 78| 0| void Release() const { 79| 0| assert (ref_cnt > 0 && "Reference count is already zero."); 80| 0| if (--ref_cnt == 0) delete this; 81| 0| } 82| | 83| | template 84| | friend struct IntrusiveRefCntPtrInfo; 85| | }; 86| | 87| | 88| | template struct IntrusiveRefCntPtrInfo { 89| 0| static void retain(T *obj) { obj->Retain(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE6retainEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE6retainEPS4_ ------------------ 90| 0| static void release(T *obj) { obj->Release(); } ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail12DirIterStateEE7releaseEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm22IntrusiveRefCntPtrInfoINS_3sys2fs6detail15RecDirIterStateEE7releaseEPS4_ ------------------ 91| | }; 92| | 93| |/// \brief A thread-safe version of \c llvm::RefCountedBase. 94| |/// 95| |/// A generic base class for objects that wish to have their lifetimes managed 96| |/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to 97| |/// obtain such functionality, and are typically handled with 98| |/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the 99| |/// management of reference counts. 100| |template 101| |class ThreadSafeRefCountedBase { 102| | mutable std::atomic RefCount; 103| | 104| |protected: 105| | ThreadSafeRefCountedBase() : RefCount(0) {} 106| | 107| |public: 108| | void Retain() const { ++RefCount; } 109| | 110| | void Release() const { 111| | int NewRefCount = --RefCount; 112| | assert(NewRefCount >= 0 && "Reference count was already zero."); 113| | if (NewRefCount == 0) 114| | delete static_cast(this); 115| | } 116| |}; 117| | 118| |//===----------------------------------------------------------------------===// 119| |/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 120| |/// that assumes the wrapped object has a reference count associated 121| |/// with it that can be managed via calls to 122| |/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 123| |/// manage reference counts via the RAII idiom: upon creation of 124| |/// smart pointer the reference count of the wrapped object is 125| |/// incremented and upon destruction of the smart pointer the 126| |/// reference count is decremented. This class also safely handles 127| |/// wrapping NULL pointers. 128| |/// 129| |/// Reference counting is implemented via calls to 130| |/// Obj->Retain()/Obj->Release(). Release() is required to destroy 131| |/// the object when the reference count reaches zero. Inheriting from 132| |/// RefCountedBase/RefCountedBaseVPTR takes care of this 133| |/// automatically. 134| |//===----------------------------------------------------------------------===// 135| | template 136| | class IntrusiveRefCntPtr { 137| | T* Obj; 138| | 139| | public: 140| | typedef T element_type; 141| | 142| | explicit IntrusiveRefCntPtr() : Obj(nullptr) {} 143| | 144| | IntrusiveRefCntPtr(T* obj) : Obj(obj) { 145| | retain(); 146| | } 147| | 148| | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 149| | retain(); 150| | } 151| | 152| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 153| | S.Obj = nullptr; 154| | } 155| | 156| | template 157| | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.get()) { 158| | S.Obj = 0; 159| | } 160| | 161| | template 162| | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) 163| | : Obj(S.get()) { 164| | retain(); 165| | } 166| | 167| | IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 168| | swap(S); 169| | return *this; 170| | } 171| | 172| | ~IntrusiveRefCntPtr() { release(); } 173| | 174| | T& operator*() const { return *Obj; } 175| | 176| 0| T* operator->() const { return Obj; } 177| | 178| 0| T* get() const { return Obj; } 179| | 180| 0| explicit operator bool() const { return Obj; } 181| | 182| 0| void swap(IntrusiveRefCntPtr& other) { 183| 0| T* tmp = other.Obj; 184| 0| other.Obj = Obj; 185| 0| Obj = tmp; 186| 0| } 187| | 188| 0| void reset() { 189| 0| release(); 190| 0| Obj = nullptr; 191| 0| } 192| | 193| | void resetWithoutRelease() { 194| | Obj = 0; 195| | } 196| | 197| | private: 198| 0| void retain() { if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } 199| 0| void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); } 200| | 201| | template 202| | friend class IntrusiveRefCntPtr; 203| | }; 204| | 205| | template 206| | inline bool operator==(const IntrusiveRefCntPtr& A, 207| | const IntrusiveRefCntPtr& B) 208| 0| { 209| 0| return A.get() == B.get(); 210| 0| } 211| | 212| | template 213| | inline bool operator!=(const IntrusiveRefCntPtr& A, 214| | const IntrusiveRefCntPtr& B) 215| | { 216| | return A.get() != B.get(); 217| | } 218| | 219| | template 220| | inline bool operator==(const IntrusiveRefCntPtr& A, 221| | U* B) 222| | { 223| | return A.get() == B; 224| | } 225| | 226| | template 227| | inline bool operator!=(const IntrusiveRefCntPtr& A, 228| | U* B) 229| | { 230| | return A.get() != B; 231| | } 232| | 233| | template 234| | inline bool operator==(T* A, 235| | const IntrusiveRefCntPtr& B) 236| | { 237| | return A == B.get(); 238| | } 239| | 240| | template 241| | inline bool operator!=(T* A, 242| | const IntrusiveRefCntPtr& B) 243| | { 244| | return A != B.get(); 245| | } 246| | 247| | template 248| | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 249| | return !B; 250| | } 251| | 252| | template 253| | bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 254| | return B == A; 255| | } 256| | 257| | template 258| | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { 259| | return !(A == B); 260| | } 261| | 262| | template 263| | bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { 264| | return !(A == B); 265| | } 266| | 267| |//===----------------------------------------------------------------------===// 268| |// LLVM-style downcasting support for IntrusiveRefCntPtr objects 269| |//===----------------------------------------------------------------------===// 270| | 271| | template struct simplify_type > { 272| | typedef T* SimpleType; 273| | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr& Val) { 274| | return Val.get(); 275| | } 276| | }; 277| | 278| | template struct simplify_type > { 279| | typedef /*const*/ T* SimpleType; 280| | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { 281| | return Val.get(); 282| | } 283| | }; 284| | 285| |} // end namespace llvm 286| | 287| |#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Optional.h: 1| |//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file provides Optional, a template class modeled in the spirit of 11| |// OCaml's 'opt' variant. The idea is to strongly type whether or not 12| |// a value can be optional. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_ADT_OPTIONAL_H 17| |#define LLVM_ADT_OPTIONAL_H 18| | 19| |#include "llvm/ADT/None.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include "llvm/Support/Compiler.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |template 30| |class Optional { 31| | AlignedCharArrayUnion storage; 32| | bool hasVal; 33| |public: 34| | typedef T value_type; 35| | 36| 0| Optional(NoneType) : hasVal(false) {} 37| 0| explicit Optional() : hasVal(false) {} 38| | Optional(const T &y) : hasVal(true) { 39| | new (storage.buffer) T(y); 40| | } 41| | Optional(const Optional &O) : hasVal(O.hasVal) { 42| | if (hasVal) 43| | new (storage.buffer) T(*O); 44| | } 45| | 46| 0| Optional(T &&y) : hasVal(true) { 47| 0| new (storage.buffer) T(std::forward(y)); 48| 0| } 49| | Optional(Optional &&O) : hasVal(O) { 50| | if (O) { 51| | new (storage.buffer) T(std::move(*O)); 52| | O.reset(); 53| | } 54| | } 55| 0| Optional &operator=(T &&y) { 56| 0| if (hasVal) 57| 0| **this = std::move(y); 58| 0| else { 59| 0| new (storage.buffer) T(std::move(y)); 60| 0| hasVal = true; 61| 0| } 62| 0| return *this; 63| 0| } 64| | Optional &operator=(Optional &&O) { 65| | if (!O) 66| | reset(); 67| | else { 68| | *this = std::move(*O); 69| | O.reset(); 70| | } 71| | return *this; 72| | } 73| | 74| | /// Create a new object by constructing it in place with the given arguments. 75| | template 76| | void emplace(ArgTypes &&...Args) { 77| | reset(); 78| | hasVal = true; 79| | new (storage.buffer) T(std::forward(Args)...); 80| | } 81| | 82| | static inline Optional create(const T* y) { 83| | return y ? Optional(*y) : Optional(); 84| | } 85| | 86| | // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 87| | // could be made more efficient by passing by value, possibly unifying them 88| | // with the rvalue versions above - but this could place a different set of 89| | // requirements (notably: the existence of a default ctor) when implemented 90| | // in that way. Careful SFINAE to avoid such pitfalls would be required. 91| | Optional &operator=(const T &y) { 92| | if (hasVal) 93| | **this = y; 94| | else { 95| | new (storage.buffer) T(y); 96| | hasVal = true; 97| | } 98| | return *this; 99| | } 100| | 101| | Optional &operator=(const Optional &O) { 102| | if (!O) 103| | reset(); 104| | else 105| | *this = *O; 106| | return *this; 107| | } 108| | 109| 0| void reset() { 110| 0| if (hasVal) { 111| 0| (**this).~T(); 112| 0| hasVal = false; 113| 0| } 114| 0| } 115| | 116| 0| ~Optional() { 117| 0| reset(); 118| 0| } 119| | 120| | const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); } 121| 0| T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); } 122| | const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 123| 0| T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 124| | 125| 0| explicit operator bool() const { return hasVal; } 126| 0| bool hasValue() const { return hasVal; } 127| | const T* operator->() const { return getPointer(); } 128| | T* operator->() { return getPointer(); } 129| | const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 130| 0| T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 131| | 132| | template 133| | LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { 134| | return hasValue() ? getValue() : std::forward(value); 135| | } 136| | 137| | void unwrapIn(std::function fn) { 138| | if (hasValue()) 139| | fn(getValue()); 140| | } 141| | void unwrapIn(std::function fn) const { 142| | if (hasValue()) 143| | fn(getValue()); 144| | } 145| | 146| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 147| | T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 148| | T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 149| | 150| | template 151| | T getValueOr(U &&value) && { 152| | return hasValue() ? std::move(getValue()) : std::forward(value); 153| | } 154| |#endif 155| |}; 156| | 157| |template struct isPodLike; 158| |template struct isPodLike > { 159| | // An Optional is pod-like if T is. 160| | static const bool value = isPodLike::value; 161| |}; 162| | 163| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 164| |/// explicitly compare the underlying values and account for empty \c Optional 165| |/// objects. 166| |/// 167| |/// This routine will never be defined. It returns \c void to help diagnose 168| |/// errors at compile time. 169| |template 170| |void operator==(const Optional &X, const Optional &Y); 171| | 172| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 173| |/// explicitly compare the underlying values and account for empty \c Optional 174| |/// objects. 175| |/// 176| |/// This routine will never be defined. It returns \c void to help diagnose 177| |/// errors at compile time. 178| |template 179| |void operator!=(const Optional &X, const Optional &Y); 180| | 181| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 182| |/// explicitly compare the underlying values and account for empty \c Optional 183| |/// objects. 184| |/// 185| |/// This routine will never be defined. It returns \c void to help diagnose 186| |/// errors at compile time. 187| |template 188| |void operator<(const Optional &X, const Optional &Y); 189| | 190| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 191| |/// explicitly compare the underlying values and account for empty \c Optional 192| |/// objects. 193| |/// 194| |/// This routine will never be defined. It returns \c void to help diagnose 195| |/// errors at compile time. 196| |template 197| |void operator<=(const Optional &X, const Optional &Y); 198| | 199| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 200| |/// explicitly compare the underlying values and account for empty \c Optional 201| |/// objects. 202| |/// 203| |/// This routine will never be defined. It returns \c void to help diagnose 204| |/// errors at compile time. 205| |template 206| |void operator>=(const Optional &X, const Optional &Y); 207| | 208| |/// \brief Poison comparison between two \c Optional objects. Clients needs to 209| |/// explicitly compare the underlying values and account for empty \c Optional 210| |/// objects. 211| |/// 212| |/// This routine will never be defined. It returns \c void to help diagnose 213| |/// errors at compile time. 214| |template 215| |void operator>(const Optional &X, const Optional &Y); 216| | 217| |} // end llvm namespace 218| | 219| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/STLExtras.h: 1| |//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some templates that are useful if you are working with the 11| |// STL at all. 12| |// 13| |// No library is required when using these functions. 14| |// 15| |//===----------------------------------------------------------------------===// 16| | 17| |#ifndef LLVM_ADT_STLEXTRAS_H 18| |#define LLVM_ADT_STLEXTRAS_H 19| | 20| |#include "llvm/Support/Compiler.h" 21| |#include 22| |#include // for std::size_t 23| |#include // for qsort 24| |#include 25| |#include 26| |#include 27| |#include // for std::pair 28| | 29| |namespace llvm { 30| | 31| |//===----------------------------------------------------------------------===// 32| |// Extra additions to 33| |//===----------------------------------------------------------------------===// 34| | 35| |template 36| |struct identity : public std::unary_function { 37| | Ty &operator()(Ty &self) const { 38| | return self; 39| | } 40| | const Ty &operator()(const Ty &self) const { 41| | return self; 42| | } 43| |}; 44| | 45| |template 46| |struct less_ptr : public std::binary_function { 47| | bool operator()(const Ty* left, const Ty* right) const { 48| | return *left < *right; 49| | } 50| |}; 51| | 52| |template 53| |struct greater_ptr : public std::binary_function { 54| | bool operator()(const Ty* left, const Ty* right) const { 55| | return *right < *left; 56| | } 57| |}; 58| | 59| |/// An efficient, type-erasing, non-owning reference to a callable. This is 60| |/// intended for use as the type of a function parameter that is not used 61| |/// after the function in question returns. 62| |/// 63| |/// This class does not own the callable, so it is not in general safe to store 64| |/// a function_ref. 65| |template class function_ref; 66| | 67| |template 68| |class function_ref { 69| | Ret (*callback)(intptr_t callable, Params ...params); 70| | intptr_t callable; 71| | 72| | template 73| | static Ret callback_fn(intptr_t callable, Params ...params) { 74| | return (*reinterpret_cast(callable))( 75| | std::forward(params)...); 76| | } 77| | 78| |public: 79| | template 80| | function_ref(Callable &&callable, 81| | typename std::enable_if< 82| | !std::is_same::type, 83| | function_ref>::value>::type * = nullptr) 84| | : callback(callback_fn::type>), 85| | callable(reinterpret_cast(&callable)) {} 86| | Ret operator()(Params ...params) const { 87| | return callback(callable, std::forward(params)...); 88| | } 89| |}; 90| | 91| |// deleter - Very very very simple method that is used to invoke operator 92| |// delete on something. It is used like this: 93| |// 94| |// for_each(V.begin(), B.end(), deleter); 95| |// 96| |template 97| |inline void deleter(T *Ptr) { 98| | delete Ptr; 99| |} 100| | 101| | 102| | 103| |//===----------------------------------------------------------------------===// 104| |// Extra additions to 105| |//===----------------------------------------------------------------------===// 106| | 107| |// mapped_iterator - This is a simple iterator adapter that causes a function to 108| |// be dereferenced whenever operator* is invoked on the iterator. 109| |// 110| |template 111| |class mapped_iterator { 112| | RootIt current; 113| | UnaryFunc Fn; 114| |public: 115| | typedef typename std::iterator_traits::iterator_category 116| | iterator_category; 117| | typedef typename std::iterator_traits::difference_type 118| | difference_type; 119| | typedef typename UnaryFunc::result_type value_type; 120| | 121| | typedef void pointer; 122| | //typedef typename UnaryFunc::result_type *pointer; 123| | typedef void reference; // Can't modify value returned by fn 124| | 125| | typedef RootIt iterator_type; 126| | 127| | inline const RootIt &getCurrent() const { return current; } 128| | inline const UnaryFunc &getFunc() const { return Fn; } 129| | 130| | inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) 131| | : current(I), Fn(F) {} 132| | 133| | inline value_type operator*() const { // All this work to do this 134| | return Fn(*current); // little change 135| | } 136| | 137| | mapped_iterator &operator++() { 138| | ++current; 139| | return *this; 140| | } 141| | mapped_iterator &operator--() { 142| | --current; 143| | return *this; 144| | } 145| | mapped_iterator operator++(int) { 146| | mapped_iterator __tmp = *this; 147| | ++current; 148| | return __tmp; 149| | } 150| | mapped_iterator operator--(int) { 151| | mapped_iterator __tmp = *this; 152| | --current; 153| | return __tmp; 154| | } 155| | mapped_iterator operator+(difference_type n) const { 156| | return mapped_iterator(current + n, Fn); 157| | } 158| | mapped_iterator &operator+=(difference_type n) { 159| | current += n; 160| | return *this; 161| | } 162| | mapped_iterator operator-(difference_type n) const { 163| | return mapped_iterator(current - n, Fn); 164| | } 165| | mapped_iterator &operator-=(difference_type n) { 166| | current -= n; 167| | return *this; 168| | } 169| | reference operator[](difference_type n) const { return *(*this + n); } 170| | 171| | bool operator!=(const mapped_iterator &X) const { return !operator==(X); } 172| | bool operator==(const mapped_iterator &X) const { 173| | return current == X.current; 174| | } 175| | bool operator<(const mapped_iterator &X) const { return current < X.current; } 176| | 177| | difference_type operator-(const mapped_iterator &X) const { 178| | return current - X.current; 179| | } 180| |}; 181| | 182| |template 183| |inline mapped_iterator 184| |operator+(typename mapped_iterator::difference_type N, 185| | const mapped_iterator &X) { 186| | return mapped_iterator(X.getCurrent() - N, X.getFunc()); 187| |} 188| | 189| | 190| |// map_iterator - Provide a convenient way to create mapped_iterators, just like 191| |// make_pair is useful for creating pairs... 192| |// 193| |template 194| |inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { 195| | return mapped_iterator(I, F); 196| |} 197| | 198| |//===----------------------------------------------------------------------===// 199| |// Extra additions to 200| |//===----------------------------------------------------------------------===// 201| | 202| |/// \brief Function object to check whether the first component of a std::pair 203| |/// compares less than the first component of another std::pair. 204| |struct less_first { 205| | template bool operator()(const T &lhs, const T &rhs) const { 206| | return lhs.first < rhs.first; 207| | } 208| |}; 209| | 210| |/// \brief Function object to check whether the second component of a std::pair 211| |/// compares less than the second component of another std::pair. 212| |struct less_second { 213| | template bool operator()(const T &lhs, const T &rhs) const { 214| | return lhs.second < rhs.second; 215| | } 216| |}; 217| | 218| |// A subset of N3658. More stuff can be added as-needed. 219| | 220| |/// \brief Represents a compile-time sequence of integers. 221| |template struct integer_sequence { 222| | typedef T value_type; 223| | 224| | static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } 225| |}; 226| | 227| |/// \brief Alias for the common case of a sequence of size_ts. 228| |template 229| |struct index_sequence : integer_sequence {}; 230| | 231| |template 232| |struct build_index_impl : build_index_impl {}; 233| |template 234| |struct build_index_impl<0, I...> : index_sequence {}; 235| | 236| |/// \brief Creates a compile-time integer sequence for a parameter pack. 237| |template 238| |struct index_sequence_for : build_index_impl {}; 239| | 240| |//===----------------------------------------------------------------------===// 241| |// Extra additions for arrays 242| |//===----------------------------------------------------------------------===// 243| | 244| |/// Find the length of an array. 245| |template 246| 0|LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { 247| 0| return N; 248| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm14array_lengthofIPvLm256EEEmRAT0__T_ ------------------ | Unexecuted instantiation: _ZN4llvm14array_lengthofIKcLm81EEEmRAT0__T_ ------------------ 249| | 250| |/// Adapt std::less for array_pod_sort. 251| |template 252| |inline int array_pod_sort_comparator(const void *P1, const void *P2) { 253| | if (std::less()(*reinterpret_cast(P1), 254| | *reinterpret_cast(P2))) 255| | return -1; 256| | if (std::less()(*reinterpret_cast(P2), 257| | *reinterpret_cast(P1))) 258| | return 1; 259| | return 0; 260| |} 261| | 262| |/// get_array_pod_sort_comparator - This is an internal helper function used to 263| |/// get type deduction of T right. 264| |template 265| |inline int (*get_array_pod_sort_comparator(const T &)) 266| | (const void*, const void*) { 267| | return array_pod_sort_comparator; 268| |} 269| | 270| | 271| |/// array_pod_sort - This sorts an array with the specified start and end 272| |/// extent. This is just like std::sort, except that it calls qsort instead of 273| |/// using an inlined template. qsort is slightly slower than std::sort, but 274| |/// most sorts are not performance critical in LLVM and std::sort has to be 275| |/// template instantiated for each type, leading to significant measured code 276| |/// bloat. This function should generally be used instead of std::sort where 277| |/// possible. 278| |/// 279| |/// This function assumes that you have simple POD-like types that can be 280| |/// compared with std::less and can be moved with memcpy. If this isn't true, 281| |/// you should use std::sort. 282| |/// 283| |/// NOTE: If qsort_r were portable, we could allow a custom comparator and 284| |/// default to std::less. 285| |template 286| |inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 287| | // Don't inefficiently call qsort with one element or trigger undefined 288| | // behavior with an empty sequence. 289| | auto NElts = End - Start; 290| | if (NElts <= 1) return; 291| | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 292| |} 293| | 294| |template 295| |inline void array_pod_sort( 296| | IteratorTy Start, IteratorTy End, 297| | int (*Compare)( 298| | const typename std::iterator_traits::value_type *, 299| | const typename std::iterator_traits::value_type *)) { 300| | // Don't inefficiently call qsort with one element or trigger undefined 301| | // behavior with an empty sequence. 302| | auto NElts = End - Start; 303| | if (NElts <= 1) return; 304| | qsort(&*Start, NElts, sizeof(*Start), 305| | reinterpret_cast(Compare)); 306| |} 307| | 308| |//===----------------------------------------------------------------------===// 309| |// Extra additions to 310| |//===----------------------------------------------------------------------===// 311| | 312| |/// For a container of pointers, deletes the pointers and then clears the 313| |/// container. 314| |template 315| |void DeleteContainerPointers(Container &C) { 316| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 317| | delete *I; 318| | C.clear(); 319| |} 320| | 321| |/// In a container of pairs (usually a map) whose second element is a pointer, 322| |/// deletes the second elements and then clears the container. 323| |template 324| |void DeleteContainerSeconds(Container &C) { 325| | for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 326| | delete I->second; 327| | C.clear(); 328| |} 329| | 330| |//===----------------------------------------------------------------------===// 331| |// Extra additions to 332| |//===----------------------------------------------------------------------===// 333| | 334| |// Implement make_unique according to N3656. 335| | 336| |/// \brief Constructs a `new T()` with the given args and returns a 337| |/// `unique_ptr` which owns the object. 338| |/// 339| |/// Example: 340| |/// 341| |/// auto p = make_unique(); 342| |/// auto p = make_unique>(0, 1); 343| |template 344| |typename std::enable_if::value, std::unique_ptr>::type 345| |make_unique(Args &&... args) { 346| | return std::unique_ptr(new T(std::forward(args)...)); 347| |} 348| | 349| |/// \brief Constructs a `new T[n]` with the given args and returns a 350| |/// `unique_ptr` which owns the object. 351| |/// 352| |/// \param n size of the new array. 353| |/// 354| |/// Example: 355| |/// 356| |/// auto p = make_unique(2); // value-initializes the array with 0's. 357| |template 358| |typename std::enable_if::value && std::extent::value == 0, 359| | std::unique_ptr>::type 360| |make_unique(size_t n) { 361| | return std::unique_ptr(new typename std::remove_extent::type[n]()); 362| |} 363| | 364| |/// This function isn't used and is only here to provide better compile errors. 365| |template 366| |typename std::enable_if::value != 0>::type 367| |make_unique(Args &&...) = delete; 368| | 369| |struct FreeDeleter { 370| 0| void operator()(void* v) { 371| 0| ::free(v); 372| 0| } 373| |}; 374| | 375| |template 376| |struct pair_hash { 377| | size_t operator()(const std::pair &P) const { 378| | return std::hash()(P.first) * 31 + std::hash()(P.second); 379| | } 380| |}; 381| | 382| |/// A functor like C++14's std::less in its absence. 383| |struct less { 384| | template bool operator()(A &&a, B &&b) const { 385| | return std::forward(a) < std::forward(b); 386| | } 387| |}; 388| | 389| |/// A functor like C++14's std::equal in its absence. 390| |struct equal { 391| | template bool operator()(A &&a, B &&b) const { 392| | return std::forward(a) == std::forward(b); 393| | } 394| |}; 395| | 396| |/// Binary functor that adapts to any other binary functor after dereferencing 397| |/// operands. 398| |template struct deref { 399| | T func; 400| | // Could be further improved to cope with non-derivable functors and 401| | // non-binary functors (should be a variadic template member function 402| | // operator()). 403| | template 404| | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { 405| | assert(lhs); 406| | assert(rhs); 407| | return func(*lhs, *rhs); 408| | } 409| |}; 410| | 411| |} // End llvm namespace 412| | 413| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallPtrSet.h: 1| |//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallPtrSet class. See the doxygen comment for 11| |// SmallPtrSetImplBase for more details on the algorithm used. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_ADT_SMALLPTRSET_H 16| |#define LLVM_ADT_SMALLPTRSET_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include "llvm/Support/PointerLikeTypeTraits.h" 21| |#include 22| |#include 23| |#include 24| |#include 25| |#include 26| | 27| |namespace llvm { 28| | 29| |class SmallPtrSetIteratorImpl; 30| | 31| |/// SmallPtrSetImplBase - This is the common code shared among all the 32| |/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one 33| |/// for small and one for large sets. 34| |/// 35| |/// Small sets use an array of pointers allocated in the SmallPtrSet object, 36| |/// which is treated as a simple array of pointers. When a pointer is added to 37| |/// the set, the array is scanned to see if the element already exists, if not 38| |/// the element is 'pushed back' onto the array. If we run out of space in the 39| |/// array, we grow into the 'large set' case. SmallSet should be used when the 40| |/// sets are often small. In this case, no memory allocation is used, and only 41| |/// light-weight and cache-efficient scanning is used. 42| |/// 43| |/// Large sets use a classic exponentially-probed hash table. Empty buckets are 44| |/// represented with an illegal pointer value (-1) to allow null pointers to be 45| |/// inserted. Tombstones are represented with another illegal pointer value 46| |/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or 47| |/// more. When this happens, the table is doubled in size. 48| |/// 49| |class SmallPtrSetImplBase { 50| | friend class SmallPtrSetIteratorImpl; 51| |protected: 52| | /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. 53| | const void **SmallArray; 54| | /// CurArray - This is the current set of buckets. If equal to SmallArray, 55| | /// then the set is in 'small mode'. 56| | const void **CurArray; 57| | /// CurArraySize - The allocated size of CurArray, always a power of two. 58| | unsigned CurArraySize; 59| | 60| | // If small, this is # elts allocated consecutively 61| | unsigned NumElements; 62| | unsigned NumTombstones; 63| | 64| | // Helpers to copy and move construct a SmallPtrSet. 65| | SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that); 66| | SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize, 67| | SmallPtrSetImplBase &&that); 68| | explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) : 69| | SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { 70| | assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && 71| | "Initial size must be a power of two!"); 72| | clear(); 73| | } 74| | ~SmallPtrSetImplBase(); 75| | 76| |public: 77| | typedef unsigned size_type; 78| | bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } 79| | size_type size() const { return NumElements; } 80| | 81| | void clear() { 82| | // If the capacity of the array is huge, and the # elements used is small, 83| | // shrink the array. 84| | if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) 85| | return shrink_and_clear(); 86| | 87| | // Fill the array with empty markers. 88| | memset(CurArray, -1, CurArraySize*sizeof(void*)); 89| | NumElements = 0; 90| | NumTombstones = 0; 91| | } 92| | 93| |protected: 94| 0| static void *getTombstoneMarker() { return reinterpret_cast(-2); } 95| 0| static void *getEmptyMarker() { 96| 0| // Note that -1 is chosen to make clear() efficiently implementable with 97| 0| // memset and because it's not a valid pointer value. 98| 0| return reinterpret_cast(-1); 99| 0| } 100| | 101| | /// insert_imp - This returns true if the pointer was new to the set, false if 102| | /// it was already in the set. This is hidden from the client so that the 103| | /// derived class can check that the right type of pointer is passed in. 104| | std::pair insert_imp(const void *Ptr); 105| | 106| | /// erase_imp - If the set contains the specified pointer, remove it and 107| | /// return true, otherwise return false. This is hidden from the client so 108| | /// that the derived class can check that the right type of pointer is passed 109| | /// in. 110| | bool erase_imp(const void * Ptr); 111| | 112| 0| bool count_imp(const void * Ptr) const { 113| 0| if (isSmall()) { 114| 0| // Linear search for the item. 115| 0| for (const void *const *APtr = SmallArray, 116| 0| *const *E = SmallArray+NumElements; APtr != E; ++APtr) 117| 0| if (*APtr == Ptr) 118| 0| return true; 119| 0| return false; 120| 0| } 121| 0| 122| 0| // Big set case. 123| 0| return *FindBucketFor(Ptr) == Ptr; 124| 0| } 125| | 126| |private: 127| 0| bool isSmall() const { return CurArray == SmallArray; } 128| | 129| | const void * const *FindBucketFor(const void *Ptr) const; 130| | void shrink_and_clear(); 131| | 132| | /// Grow - Allocate a larger backing store for the buckets and move it over. 133| | void Grow(unsigned NewSize); 134| | 135| | void operator=(const SmallPtrSetImplBase &RHS) = delete; 136| |protected: 137| | /// swap - Swaps the elements of two sets. 138| | /// Note: This method assumes that both sets have the same small size. 139| | void swap(SmallPtrSetImplBase &RHS); 140| | 141| | void CopyFrom(const SmallPtrSetImplBase &RHS); 142| | void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS); 143| |}; 144| | 145| |/// SmallPtrSetIteratorImpl - This is the common base class shared between all 146| |/// instances of SmallPtrSetIterator. 147| |class SmallPtrSetIteratorImpl { 148| |protected: 149| | const void *const *Bucket; 150| | const void *const *End; 151| |public: 152| | explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) 153| 0| : Bucket(BP), End(E) { 154| 0| AdvanceIfNotValid(); 155| 0| } 156| | 157| 0| bool operator==(const SmallPtrSetIteratorImpl &RHS) const { 158| 0| return Bucket == RHS.Bucket; 159| 0| } 160| | bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { 161| | return Bucket != RHS.Bucket; 162| | } 163| | 164| |protected: 165| | /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket 166| | /// that is. This is guaranteed to stop because the end() bucket is marked 167| | /// valid. 168| | void AdvanceIfNotValid() { 169| | assert(Bucket <= End); 170| | while (Bucket != End && 171| | (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || 172| | *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) 173| | ++Bucket; 174| | } 175| |}; 176| | 177| |/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. 178| |template 179| |class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { 180| | typedef PointerLikeTypeTraits PtrTraits; 181| | 182| |public: 183| | typedef PtrTy value_type; 184| | typedef PtrTy reference; 185| | typedef PtrTy pointer; 186| | typedef std::ptrdiff_t difference_type; 187| | typedef std::forward_iterator_tag iterator_category; 188| | 189| | explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) 190| | : SmallPtrSetIteratorImpl(BP, E) {} 191| | 192| | // Most methods provided by baseclass. 193| | 194| | const PtrTy operator*() const { 195| | assert(Bucket < End); 196| | return PtrTraits::getFromVoidPointer(const_cast(*Bucket)); 197| | } 198| | 199| | inline SmallPtrSetIterator& operator++() { // Preincrement 200| | ++Bucket; 201| | AdvanceIfNotValid(); 202| | return *this; 203| | } 204| | 205| | SmallPtrSetIterator operator++(int) { // Postincrement 206| | SmallPtrSetIterator tmp = *this; ++*this; return tmp; 207| | } 208| |}; 209| | 210| |/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next 211| |/// power of two (which means N itself if N is already a power of two). 212| |template 213| |struct RoundUpToPowerOfTwo; 214| | 215| |/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a 216| |/// helper template used to implement RoundUpToPowerOfTwo. 217| |template 218| |struct RoundUpToPowerOfTwoH { 219| | enum { Val = N }; 220| |}; 221| |template 222| |struct RoundUpToPowerOfTwoH { 223| | enum { 224| | // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets 225| | // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. 226| | Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val 227| | }; 228| |}; 229| | 230| |template 231| |struct RoundUpToPowerOfTwo { 232| | enum { Val = RoundUpToPowerOfTwoH::Val }; 233| |}; 234| | 235| | 236| |/// \brief A templated base class for \c SmallPtrSet which provides the 237| |/// typesafe interface that is common across all small sizes. 238| |/// 239| |/// This is particularly useful for passing around between interface boundaries 240| |/// to avoid encoding a particular small size in the interface boundary. 241| |template 242| |class SmallPtrSetImpl : public SmallPtrSetImplBase { 243| | typedef PointerLikeTypeTraits PtrTraits; 244| | 245| | SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; 246| |protected: 247| | // Constructors that forward to the base. 248| | SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) 249| | : SmallPtrSetImplBase(SmallStorage, that) {} 250| | SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, 251| | SmallPtrSetImpl &&that) 252| | : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} 253| | explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) 254| | : SmallPtrSetImplBase(SmallStorage, SmallSize) {} 255| | 256| |public: 257| | typedef SmallPtrSetIterator iterator; 258| | typedef SmallPtrSetIterator const_iterator; 259| | 260| | /// Inserts Ptr if and only if there is no element in the container equal to 261| | /// Ptr. The bool component of the returned pair is true if and only if the 262| | /// insertion takes place, and the iterator component of the pair points to 263| | /// the element equal to Ptr. 264| | std::pair insert(PtrType Ptr) { 265| | auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); 266| | return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); 267| | } 268| | 269| | /// erase - If the set contains the specified pointer, remove it and return 270| | /// true, otherwise return false. 271| | bool erase(PtrType Ptr) { 272| | return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); 273| | } 274| | 275| | /// count - Return 1 if the specified pointer is in the set, 0 otherwise. 276| | size_type count(PtrType Ptr) const { 277| | return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; 278| | } 279| | 280| | template 281| | void insert(IterT I, IterT E) { 282| | for (; I != E; ++I) 283| | insert(*I); 284| | } 285| | 286| | inline iterator begin() const { 287| | return iterator(CurArray, CurArray+CurArraySize); 288| | } 289| | inline iterator end() const { 290| | return iterator(CurArray+CurArraySize, CurArray+CurArraySize); 291| | } 292| |}; 293| | 294| |/// SmallPtrSet - This class implements a set which is optimized for holding 295| |/// SmallSize or less elements. This internally rounds up SmallSize to the next 296| |/// power of two if it is not already a power of two. See the comments above 297| |/// SmallPtrSetImplBase for details of the algorithm. 298| |template 299| |class SmallPtrSet : public SmallPtrSetImpl { 300| | typedef SmallPtrSetImpl BaseT; 301| | 302| | // Make sure that SmallSize is a power of two, round up if not. 303| | enum { SmallSizePowTwo = RoundUpToPowerOfTwo::Val }; 304| | /// SmallStorage - Fixed size storage used in 'small mode'. 305| | const void *SmallStorage[SmallSizePowTwo]; 306| |public: 307| | SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} 308| | SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} 309| | SmallPtrSet(SmallPtrSet &&that) 310| | : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} 311| | 312| | template 313| | SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { 314| | this->insert(I, E); 315| | } 316| | 317| | SmallPtrSet & 318| | operator=(const SmallPtrSet &RHS) { 319| | if (&RHS != this) 320| | this->CopyFrom(RHS); 321| | return *this; 322| | } 323| | 324| | SmallPtrSet& 325| | operator=(SmallPtrSet &&RHS) { 326| | if (&RHS != this) 327| | this->MoveFrom(SmallSizePowTwo, std::move(RHS)); 328| | return *this; 329| | } 330| | 331| | /// swap - Swaps the elements of two sets. 332| | void swap(SmallPtrSet &RHS) { 333| | SmallPtrSetImplBase::swap(RHS); 334| | } 335| |}; 336| | 337| |} 338| | 339| |namespace std { 340| | /// Implement std::swap in terms of SmallPtrSet swap. 341| | template 342| | inline void swap(llvm::SmallPtrSet &LHS, llvm::SmallPtrSet &RHS) { 343| | LHS.swap(RHS); 344| | } 345| |} 346| | 347| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallString.h: 1| |//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallString class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLSTRING_H 15| |#define LLVM_ADT_SMALLSTRING_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| | 20| |namespace llvm { 21| | 22| |/// SmallString - A SmallString is just a SmallVector with methods and accessors 23| |/// that make it work better as a string (e.g. operator+ etc). 24| |template 25| |class SmallString : public SmallVector { 26| |public: 27| | /// Default ctor - Initialize to empty. 28| 0| SmallString() {} ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj16384EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj32EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj4EEC2Ev ------------------ 29| | 30| | /// Initialize from a StringRef. 31| 0| SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} 32| | 33| | /// Initialize with a range. 34| | template 35| 0| SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj200EEC2IPKcEET_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EEC2IPKcEET_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EEC2INSt3__111__wrap_iterIPcEEEET_S7_ ------------------ 36| | 37| | // Note that in order to add new overloads for append & assign, we have to 38| | // duplicate the inherited versions so as not to inadvertently hide them. 39| | 40| | /// @} 41| | /// @name String Assignment 42| | /// @{ 43| | 44| | /// Assign from a repeated element. 45| | void assign(size_t NumElts, char Elt) { 46| | this->SmallVectorImpl::assign(NumElts, Elt); 47| | } 48| | 49| | /// Assign from an iterator pair. 50| | template 51| | void assign(in_iter S, in_iter E) { 52| | this->clear(); 53| | SmallVectorImpl::append(S, E); 54| | } 55| | 56| | /// Assign from a StringRef. 57| | void assign(StringRef RHS) { 58| | this->clear(); 59| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 60| | } 61| | 62| | /// Assign from a SmallVector. 63| | void assign(const SmallVectorImpl &RHS) { 64| | this->clear(); 65| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 66| | } 67| | 68| | /// @} 69| | /// @name String Concatenation 70| | /// @{ 71| | 72| | /// Append from an iterator pair. 73| | template 74| | void append(in_iter S, in_iter E) { 75| | SmallVectorImpl::append(S, E); 76| | } 77| | 78| | void append(size_t NumInputs, char Elt) { 79| | SmallVectorImpl::append(NumInputs, Elt); 80| | } 81| | 82| | 83| | /// Append from a StringRef. 84| | void append(StringRef RHS) { 85| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 86| | } 87| | 88| | /// Append from a SmallVector. 89| | void append(const SmallVectorImpl &RHS) { 90| | SmallVectorImpl::append(RHS.begin(), RHS.end()); 91| | } 92| | 93| | /// @} 94| | /// @name String Comparison 95| | /// @{ 96| | 97| | /// Check for string equality. This is more efficient than compare() when 98| | /// the relative ordering of inequal strings isn't needed. 99| | bool equals(StringRef RHS) const { 100| | return str().equals(RHS); 101| | } 102| | 103| | /// Check for string equality, ignoring case. 104| | bool equals_lower(StringRef RHS) const { 105| | return str().equals_lower(RHS); 106| | } 107| | 108| | /// Compare two strings; the result is -1, 0, or 1 if this string is 109| | /// lexicographically less than, equal to, or greater than the \p RHS. 110| | int compare(StringRef RHS) const { 111| | return str().compare(RHS); 112| | } 113| | 114| | /// compare_lower - Compare two strings, ignoring case. 115| | int compare_lower(StringRef RHS) const { 116| | return str().compare_lower(RHS); 117| | } 118| | 119| | /// compare_numeric - Compare two strings, treating sequences of digits as 120| | /// numbers. 121| | int compare_numeric(StringRef RHS) const { 122| | return str().compare_numeric(RHS); 123| | } 124| | 125| | /// @} 126| | /// @name String Predicates 127| | /// @{ 128| | 129| | /// startswith - Check if this string starts with the given \p Prefix. 130| | bool startswith(StringRef Prefix) const { 131| | return str().startswith(Prefix); 132| | } 133| | 134| | /// endswith - Check if this string ends with the given \p Suffix. 135| | bool endswith(StringRef Suffix) const { 136| | return str().endswith(Suffix); 137| | } 138| | 139| | /// @} 140| | /// @name String Searching 141| | /// @{ 142| | 143| | /// find - Search for the first character \p C in the string. 144| | /// 145| | /// \return - The index of the first occurrence of \p C, or npos if not 146| | /// found. 147| | size_t find(char C, size_t From = 0) const { 148| | return str().find(C, From); 149| | } 150| | 151| | /// Search for the first string \p Str in the string. 152| | /// 153| | /// \returns The index of the first occurrence of \p Str, or npos if not 154| | /// found. 155| | size_t find(StringRef Str, size_t From = 0) const { 156| | return str().find(Str, From); 157| | } 158| | 159| | /// Search for the last character \p C in the string. 160| | /// 161| | /// \returns The index of the last occurrence of \p C, or npos if not 162| | /// found. 163| | size_t rfind(char C, size_t From = StringRef::npos) const { 164| | return str().rfind(C, From); 165| | } 166| | 167| | /// Search for the last string \p Str in the string. 168| | /// 169| | /// \returns The index of the last occurrence of \p Str, or npos if not 170| | /// found. 171| | size_t rfind(StringRef Str) const { 172| | return str().rfind(Str); 173| | } 174| | 175| | /// Find the first character in the string that is \p C, or npos if not 176| | /// found. Same as find. 177| | size_t find_first_of(char C, size_t From = 0) const { 178| | return str().find_first_of(C, From); 179| | } 180| | 181| | /// Find the first character in the string that is in \p Chars, or npos if 182| | /// not found. 183| | /// 184| | /// Complexity: O(size() + Chars.size()) 185| | size_t find_first_of(StringRef Chars, size_t From = 0) const { 186| | return str().find_first_of(Chars, From); 187| | } 188| | 189| | /// Find the first character in the string that is not \p C or npos if not 190| | /// found. 191| | size_t find_first_not_of(char C, size_t From = 0) const { 192| | return str().find_first_not_of(C, From); 193| | } 194| | 195| | /// Find the first character in the string that is not in the string 196| | /// \p Chars, or npos if not found. 197| | /// 198| | /// Complexity: O(size() + Chars.size()) 199| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const { 200| | return str().find_first_not_of(Chars, From); 201| | } 202| | 203| | /// Find the last character in the string that is \p C, or npos if not 204| | /// found. 205| | size_t find_last_of(char C, size_t From = StringRef::npos) const { 206| | return str().find_last_of(C, From); 207| | } 208| | 209| | /// Find the last character in the string that is in \p C, or npos if not 210| | /// found. 211| | /// 212| | /// Complexity: O(size() + Chars.size()) 213| | size_t find_last_of( 214| | StringRef Chars, size_t From = StringRef::npos) const { 215| | return str().find_last_of(Chars, From); 216| | } 217| | 218| | /// @} 219| | /// @name Helpful Algorithms 220| | /// @{ 221| | 222| | /// Return the number of occurrences of \p C in the string. 223| | size_t count(char C) const { 224| | return str().count(C); 225| | } 226| | 227| | /// Return the number of non-overlapped occurrences of \p Str in the 228| | /// string. 229| | size_t count(StringRef Str) const { 230| | return str().count(Str); 231| | } 232| | 233| | /// @} 234| | /// @name Substring Operations 235| | /// @{ 236| | 237| | /// Return a reference to the substring from [Start, Start + N). 238| | /// 239| | /// \param Start The index of the starting character in the substring; if 240| | /// the index is npos or greater than the length of the string then the 241| | /// empty substring will be returned. 242| | /// 243| | /// \param N The number of characters to included in the substring. If \p N 244| | /// exceeds the number of characters remaining in the string, the string 245| | /// suffix (starting with \p Start) will be returned. 246| | StringRef substr(size_t Start, size_t N = StringRef::npos) const { 247| | return str().substr(Start, N); 248| | } 249| | 250| | /// Return a reference to the substring from [Start, End). 251| | /// 252| | /// \param Start The index of the starting character in the substring; if 253| | /// the index is npos or greater than the length of the string then the 254| | /// empty substring will be returned. 255| | /// 256| | /// \param End The index following the last character to include in the 257| | /// substring. If this is npos, or less than \p Start, or exceeds the 258| | /// number of characters remaining in the string, the string suffix 259| | /// (starting with \p Start) will be returned. 260| | StringRef slice(size_t Start, size_t End) const { 261| | return str().slice(Start, End); 262| | } 263| | 264| | // Extra methods. 265| | 266| | /// Explicit conversion to StringRef. 267| 0| StringRef str() const { return StringRef(this->begin(), this->size()); } ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj128EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj16384EE3strEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj32EE3strEv ------------------ 268| | 269| | // TODO: Make this const, if it's safe... 270| 0| const char* c_str() { 271| 0| this->push_back(0); 272| 0| this->pop_back(); 273| 0| return this->data(); 274| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj128EE5c_strEv ------------------ | Unexecuted instantiation: _ZN4llvm11SmallStringILj32EE5c_strEv ------------------ 275| | 276| | /// Implicit conversion to StringRef. 277| 0| operator StringRef() const { return str(); } ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj16384EEcvNS_9StringRefEEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj128EEcvNS_9StringRefEEv ------------------ | Unexecuted instantiation: _ZNK4llvm11SmallStringILj32EEcvNS_9StringRefEEv ------------------ 278| | 279| | // Extra operators. 280| | const SmallString &operator=(StringRef RHS) { 281| | this->clear(); 282| | return *this += RHS; 283| | } 284| | 285| | SmallString &operator+=(StringRef RHS) { 286| | this->append(RHS.begin(), RHS.end()); 287| | return *this; 288| | } 289| | SmallString &operator+=(char C) { 290| | this->push_back(C); 291| | return *this; 292| | } 293| |}; 294| | 295| |} 296| | 297| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/SmallVector.h: 1| |//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the SmallVector class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_SMALLVECTOR_H 15| |#define LLVM_ADT_SMALLVECTOR_H 16| | 17| |#include "llvm/ADT/iterator_range.h" 18| |#include "llvm/Support/AlignOf.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/MathExtras.h" 21| |#include "llvm/Support/type_traits.h" 22| |#include 23| |#include 24| |#include 25| |#include 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |namespace llvm { 32| | 33| |/// This is all the non-templated stuff common to all SmallVectors. 34| |class SmallVectorBase { 35| |protected: 36| | void *BeginX, *EndX, *CapacityX; 37| | 38| |protected: 39| | SmallVectorBase(void *FirstEl, size_t Size) 40| 0| : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} 41| | 42| | /// This is an implementation of the grow() method which only works 43| | /// on POD-like data types and is out of line to reduce code duplication. 44| | void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); 45| | 46| |public: 47| | /// This returns size()*sizeof(T). 48| 0| size_t size_in_bytes() const { 49| 0| return size_t((char*)EndX - (char*)BeginX); 50| 0| } 51| | 52| | /// capacity_in_bytes - This returns capacity()*sizeof(T). 53| 0| size_t capacity_in_bytes() const { 54| 0| return size_t((char*)CapacityX - (char*)BeginX); 55| 0| } 56| | 57| 0| bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } 58| |}; 59| | 60| |template struct SmallVectorStorage; 61| | 62| |/// This is the part of SmallVectorTemplateBase which does not depend on whether 63| |/// the type T is a POD. The extra dummy template argument is used by ArrayRef 64| |/// to avoid unnecessarily requiring T to be complete. 65| |template 66| |class SmallVectorTemplateCommon : public SmallVectorBase { 67| |private: 68| | template friend struct SmallVectorStorage; 69| | 70| | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 71| | // don't want it to be automatically run, so we need to represent the space as 72| | // something else. Use an array of char of sufficient alignment. 73| | typedef llvm::AlignedCharArrayUnion U; 74| | U FirstEl; 75| | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 76| | 77| |protected: 78| 0| SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivEC2Em ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvEC2Em ------------------ 79| | 80| 0| void grow_pod(size_t MinSizeInBytes, size_t TSize) { 81| 0| SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); 82| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonItvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPKcvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE8grow_podEmm ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE8grow_podEmm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivE8grow_podEmm ------------------ 83| | 84| | /// Return true if this is a smallvector which has not had dynamic 85| | /// memory allocated for it. 86| 0| bool isSmall() const { 87| 0| return BeginX == static_cast(&FirstEl); 88| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE7isSmallEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZNK4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIivE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPvvE7isSmallEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE7isSmallEv ------------------ 89| | 90| | /// Put this vector in a state of being small. 91| 0| void resetToSmall() { 92| 0| BeginX = EndX = CapacityX = &FirstEl; 93| 0| } 94| | 95| 0| void setEnd(T *P) { this->EndX = P; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonItvE6setEndEPt ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE6setEndEPc ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE6setEndEPS1_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPKcvE6setEndEPS2_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE6setEndEPS3_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE6setEndEPS1_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE6setEndEPS4_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE6setEndEPS1_ ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE6setEndEPS2_ ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivE6setEndEPi ------------------ 96| |public: 97| | typedef size_t size_type; 98| | typedef ptrdiff_t difference_type; 99| | typedef T value_type; 100| | typedef T *iterator; 101| | typedef const T *const_iterator; 102| | 103| | typedef std::reverse_iterator const_reverse_iterator; 104| | typedef std::reverse_iterator reverse_iterator; 105| | 106| | typedef T &reference; 107| | typedef const T &const_reference; 108| | typedef T *pointer; 109| | typedef const T *const_pointer; 110| | 111| | // forward iterator creation methods. 112| 0| iterator begin() { return (iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonItvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivE5beginEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE5beginEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE5beginEv ------------------ 113| 0| const_iterator begin() const { return (const_iterator)this->BeginX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonItvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPKcvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE5beginEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPvvE5beginEv ------------------ 114| 0| iterator end() { return (iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonItvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_9StringRefEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPKcvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINSt3__14pairIPvmEEvE3endEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPvvE3endEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE3endEv ------------------ 115| 0| const_iterator end() const { return (const_iterator)this->EndX; } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonItvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPKcvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE3endEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPvvE3endEv ------------------ 116| |protected: 117| 0| iterator capacity_ptr() { return (iterator)this->CapacityX; } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIPKcvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE12capacity_ptrEv ------------------ 118| 0| const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonItvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE12capacity_ptrEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE12capacity_ptrEv ------------------ 119| |public: 120| | 121| | // reverse iterator creation methods. 122| | reverse_iterator rbegin() { return reverse_iterator(end()); } 123| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 124| | reverse_iterator rend() { return reverse_iterator(begin()); } 125| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 126| | 127| 0| size_type size() const { return end()-begin(); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonItvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPKcvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE4sizeEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIPvvE4sizeEv ------------------ 128| | size_type max_size() const { return size_type(-1) / sizeof(T); } 129| | 130| | /// Return the total number of elements in the currently allocated buffer. 131| 0| size_t capacity() const { return capacity_ptr() - begin(); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonItvE8capacityEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonIcvE8capacityEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE8capacityEv ------------------ 132| | 133| | /// Return a pointer to the vector's buffer, even if empty(). 134| 0| pointer data() { return pointer(begin()); } 135| | /// Return a pointer to the vector's buffer, even if empty(). 136| 0| const_pointer data() const { return const_pointer(begin()); } ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_9StringRefEvE4dataEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINS_7SMFixItEvE4dataEv ------------------ | Unexecuted instantiation: _ZNK4llvm25SmallVectorTemplateCommonINSt3__14pairIjjEEvE4dataEv ------------------ 137| | 138| 0| reference operator[](size_type idx) { 139| 0| assert(idx < size()); 140| 0| return begin()[idx]; 141| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonItvEixEm ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvEixEm ------------------ 142| | const_reference operator[](size_type idx) const { 143| | assert(idx < size()); 144| | return begin()[idx]; 145| | } 146| | 147| 0| reference front() { 148| 0| assert(!empty()); 149| 0| return begin()[0]; 150| 0| } 151| | const_reference front() const { 152| | assert(!empty()); 153| | return begin()[0]; 154| | } 155| | 156| 0| reference back() { 157| 0| assert(!empty()); 158| 0| return end()[-1]; 159| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIcvE4backEv ------------------ | Unexecuted instantiation: _ZN4llvm25SmallVectorTemplateCommonIivE4backEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm25SmallVectorTemplateCommonIN12_GLOBAL__N_19SimpleKeyEvE4backEv ------------------ 160| | const_reference back() const { 161| | assert(!empty()); 162| | return end()[-1]; 163| | } 164| |}; 165| | 166| |/// SmallVectorTemplateBase - This is where we put method 167| |/// implementations that are designed to work with non-POD-like T's. 168| |template 169| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 170| |protected: 171| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} 172| | 173| 0| static void destroy_range(T *S, T *E) { 174| 0| while (S != E) { 175| 0| --E; 176| 0| E->~T(); 177| 0| } 178| 0| } 179| | 180| | /// Use move-assignment to move the range [I, E) onto the 181| | /// objects starting with "Dest". This is just 's 182| | /// std::move, but not all stdlibs actually provide that. 183| | template 184| 0| static It2 move(It1 I, It1 E, It2 Dest) { 185| 0| for (; I != E; ++I, ++Dest) 186| 0| *Dest = ::std::move(*I); 187| 0| return Dest; 188| 0| } 189| | 190| | /// Use move-assignment to move the range 191| | /// [I, E) onto the objects ending at "Dest", moving objects 192| | /// in reverse order. This is just 's 193| | /// std::move_backward, but not all stdlibs actually provide that. 194| | template 195| | static It2 move_backward(It1 I, It1 E, It2 Dest) { 196| | while (I != E) 197| | *--Dest = ::std::move(*--E); 198| | return Dest; 199| | } 200| | 201| | /// Move the range [I, E) into the uninitialized memory starting with "Dest", 202| | /// constructing elements as needed. 203| | template 204| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 205| 0| for (; I != E; ++I, ++Dest) 206| 0| ::new ((void*) &*Dest) T(::std::move(*I)); 207| 0| } 208| | 209| | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", 210| | /// constructing elements as needed. 211| | template 212| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 213| 0| std::uninitialized_copy(I, E, Dest); 214| 0| } 215| | 216| | /// Grow the allocated memory (without initializing new elements), doubling 217| | /// the size of the allocated memory. Guarantees space for at least one more 218| | /// element, or MinSize more elements if specified. 219| | void grow(size_t MinSize = 0); 220| | 221| |public: 222| 0| void push_back(const T &Elt) { 223| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 224| 0| this->grow(); 225| 0| ::new ((void*) this->end()) T(Elt); 226| 0| this->setEnd(this->end()+1); 227| 0| } 228| | 229| | void push_back(T &&Elt) { 230| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 231| | this->grow(); 232| | ::new ((void*) this->end()) T(::std::move(Elt)); 233| | this->setEnd(this->end()+1); 234| | } 235| | 236| | void pop_back() { 237| | this->setEnd(this->end()-1); 238| | this->end()->~T(); 239| | } 240| |}; 241| | 242| |// Define this out-of-line to dissuade the C++ compiler from inlining it. 243| |template 244| 0|void SmallVectorTemplateBase::grow(size_t MinSize) { 245| 0| size_t CurCapacity = this->capacity(); 246| 0| size_t CurSize = this->size(); 247| 0| // Always grow, even from zero. 248| 0| size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); 249| 0| if (NewCapacity < MinSize) 250| 0| NewCapacity = MinSize; 251| 0| T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); 252| 0| 253| 0| // Move the elements over. 254| 0| this->uninitialized_move(this->begin(), this->end(), NewElts); 255| 0| 256| 0| // Destroy the original elements. 257| 0| destroy_range(this->begin(), this->end()); 258| 0| 259| 0| // If this wasn't grown from the inline copy, deallocate the old space. 260| 0| if (!this->isSmall()) 261| 0| free(this->begin()); 262| 0| 263| 0| this->setEnd(NewElts+CurSize); 264| 0| this->BeginX = NewElts; 265| 0| this->CapacityX = this->begin()+NewCapacity; 266| 0|} 267| | 268| | 269| |/// SmallVectorTemplateBase - This is where we put method 270| |/// implementations that are designed to work with POD-like T's. 271| |template 272| |class SmallVectorTemplateBase : public SmallVectorTemplateCommon { 273| |protected: 274| 0| SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIjjEELb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIiLb1EEC2Em ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EEC2Em ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EEC2Em ------------------ 275| | 276| | // No need to do a destroy loop for POD's. 277| 0| static void destroy_range(T *, T *) {} ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseItLb1EE13destroy_rangeEPtS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE13destroy_rangeEPcS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EE13destroy_rangeEPS1_S3_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIjjEELb1EE13destroy_rangeEPS3_S5_ ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EE13destroy_rangeEPS2_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIiLb1EE13destroy_rangeEPiS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE13destroy_rangeEPS1_S3_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EE13destroy_rangeEPS4_S6_ ------------------ 278| | 279| | /// Use move-assignment to move the range [I, E) onto the 280| | /// objects starting with "Dest". For PODs, this is just memcpy. 281| | template 282| 0| static It2 move(It1 I, It1 E, It2 Dest) { 283| 0| return ::std::copy(I, E, Dest); 284| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE4moveIPS1_S4_EET0_T_S6_S5_ ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EE4moveIPS2_S5_EET0_T_S7_S6_ ------------------ 285| | 286| | /// Use move-assignment to move the range [I, E) onto the objects ending at 287| | /// "Dest", moving objects in reverse order. 288| | template 289| 0| static It2 move_backward(It1 I, It1 E, It2 Dest) { 290| 0| return ::std::copy_backward(I, E, Dest); 291| 0| } 292| | 293| | /// Move the range [I, E) onto the uninitialized memory 294| | /// starting with "Dest", constructing elements into it as needed. 295| | template 296| 0| static void uninitialized_move(It1 I, It1 E, It2 Dest) { 297| 0| // Just do a copy. 298| 0| uninitialized_copy(I, E, Dest); 299| 0| } 300| | 301| | /// Copy the range [I, E) onto the uninitialized memory 302| | /// starting with "Dest", constructing elements into it as needed. 303| | template 304| 0| static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 305| 0| // Arbitrary iterator types; just use the basic implementation. 306| 0| std::uninitialized_copy(I, E, Dest); 307| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyINSt3__111__wrap_iterIPcEES5_EEvT_S7_T0_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyINSt3__113move_iteratorIPcEES5_EEvT_S7_T0_ ------------------ 308| | 309| | /// Copy the range [I, E) onto the uninitialized memory 310| | /// starting with "Dest", constructing elements into it as needed. 311| | template 312| | static void uninitialized_copy( 313| | T1 *I, T1 *E, T2 *Dest, 314| | typename std::enable_if::type, 315| 0| T2>::value>::type * = nullptr) { 316| 0| // Use memcpy for PODs iterated by pointers (which includes SmallVector 317| 0| // iterators): std::uninitialized_copy optimizes to memmove, but we can 318| 0| // use memcpy here. 319| 0| memcpy(Dest, I, (E-I)*sizeof(T)); 320| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIKccEEvPT_S5_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS8_12remove_constIS4_E4typeES6_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE18uninitialized_copyIccEEvPT_S4_PT0_PNSt3__19enable_ifIXsr3std7is_sameINS7_12remove_constIS3_E4typeES5_EE5valueEvE4typeE ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPKcLb1EE18uninitialized_copyIKS2_S2_EEvPT_S7_PT0_PNSt3__19enable_ifIXsr3std7is_sameINSA_12remove_constIS6_E4typeES8_EE5valueEvE4typeE ------------------ 321| | 322| | /// Double the size of the allocated memory, guaranteeing space for at 323| | /// least one more element or MinSize if specified. 324| 0| void grow(size_t MinSize = 0) { 325| 0| this->grow_pod(MinSize*sizeof(T), sizeof(T)); 326| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseItLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPKcLb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIjjEELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE4growEm ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EE4growEm ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIiLb1EE4growEm ------------------ 327| |public: 328| 0| void push_back(const T &Elt) { 329| 0| if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 330| 0| this->grow(); 331| 0| memcpy(this->end(), &Elt, sizeof(T)); 332| 0| this->setEnd(this->end()+1); 333| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseItLb1EE9push_backERKt ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE9push_backERKc ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINS_9StringRefELb1EE9push_backERKS1_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIjjEELb1EE9push_backERKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseINSt3__14pairIPvmEELb1EE9push_backERKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIPvLb1EE9push_backERKS1_ ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EE9push_backERKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIiLb1EE9push_backERKi ------------------ 334| | 335| 0| void pop_back() { 336| 0| this->setEnd(this->end()-1); 337| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseItLb1EE8pop_backEv ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIcLb1EE8pop_backEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm23SmallVectorTemplateBaseIN12_GLOBAL__N_19SimpleKeyELb1EE8pop_backEv ------------------ | Unexecuted instantiation: _ZN4llvm23SmallVectorTemplateBaseIiLb1EE8pop_backEv ------------------ 338| |}; 339| | 340| | 341| |/// This class consists of common code factored out of the SmallVector class to 342| |/// reduce code duplication based on the SmallVector 'N' template parameter. 343| |template 344| |class SmallVectorImpl : public SmallVectorTemplateBase::value> { 345| | typedef SmallVectorTemplateBase::value > SuperClass; 346| | 347| | SmallVectorImpl(const SmallVectorImpl&) = delete; 348| |public: 349| | typedef typename SuperClass::iterator iterator; 350| | typedef typename SuperClass::size_type size_type; 351| | 352| |protected: 353| | // Default ctor - Initialize to empty. 354| | explicit SmallVectorImpl(unsigned N) 355| 0| : SmallVectorTemplateBase::value>(N*sizeof(T)) { 356| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_9StringRefEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIjjEEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_7SMFixItEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIiEC2Ej ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm15SmallVectorImplIN12_GLOBAL__N_19SimpleKeyEEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIPvEC2Ej ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIPvmEEEC2Ej ------------------ 357| | 358| |public: 359| 0| ~SmallVectorImpl() { 360| 0| // Destroy the constructed elements in the vector. 361| 0| this->destroy_range(this->begin(), this->end()); 362| 0| 363| 0| // If this wasn't grown from the inline copy, deallocate the old space. 364| 0| if (!this->isSmall()) 365| 0| free(this->begin()); 366| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_9StringRefEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIjjEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_7SMFixItEED2Ev ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm15SmallVectorImplIN12_GLOBAL__N_19SimpleKeyEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIiED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIPvED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIPvmEEED2Ev ------------------ 367| | 368| | 369| 0| void clear() { 370| 0| this->destroy_range(this->begin(), this->end()); 371| 0| this->EndX = this->BeginX; 372| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplItE5clearEv ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE5clearEv ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_7SMFixItEE5clearEv ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINSt3__14pairIPvmEEE5clearEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm15SmallVectorImplIN12_GLOBAL__N_19SimpleKeyEE5clearEv ------------------ 373| | 374| 0| void resize(size_type N) { 375| 0| if (N < this->size()) { 376| 0| this->destroy_range(this->begin()+N, this->end()); 377| 0| this->setEnd(this->begin()+N); 378| 0| } else if (N > this->size()) { 379| 0| if (this->capacity() < N) 380| 0| this->grow(N); 381| 0| for (auto I = this->end(), E = this->begin() + N; I != E; ++I) 382| 0| new (&*I) T(); 383| 0| this->setEnd(this->begin()+N); 384| 0| } 385| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplItE6resizeEm ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6resizeEm ------------------ 386| | 387| | void resize(size_type N, const T &NV) { 388| | if (N < this->size()) { 389| | this->destroy_range(this->begin()+N, this->end()); 390| | this->setEnd(this->begin()+N); 391| | } else if (N > this->size()) { 392| | if (this->capacity() < N) 393| | this->grow(N); 394| | std::uninitialized_fill(this->end(), this->begin()+N, NV); 395| | this->setEnd(this->begin()+N); 396| | } 397| | } 398| | 399| 0| void reserve(size_type N) { 400| 0| if (this->capacity() < N) 401| 0| this->grow(N); 402| 0| } 403| | 404| 0| T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { 405| 0| T Result = ::std::move(this->back()); 406| 0| this->pop_back(); 407| 0| return Result; 408| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIiE12pop_back_valEv ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm15SmallVectorImplIN12_GLOBAL__N_19SimpleKeyEE12pop_back_valEv ------------------ 409| | 410| | void swap(SmallVectorImpl &RHS); 411| | 412| | /// Add the specified range to the end of the SmallVector. 413| | template 414| 0| void append(in_iter in_start, in_iter in_end) { 415| 0| size_type NumInputs = std::distance(in_start, in_end); 416| 0| // Grow allocated space if needed. 417| 0| if (NumInputs > size_type(this->capacity_ptr()-this->end())) 418| 0| this->grow(this->size()+NumInputs); 419| 0| 420| 0| // Copy the new elements over. 421| 0| this->uninitialized_copy(in_start, in_end, this->end()); 422| 0| this->setEnd(this->end() + NumInputs); 423| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6appendIPKcEEvT_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6appendINSt3__111__wrap_iterIPcEEEEvT_S7_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6appendIPcEEvT_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIPKcE6appendIPKS2_EEvT_S7_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplINS_7SMFixItEE6appendIPKS1_EEvT_S6_ ------------------ | Unexecuted instantiation: _ZN4llvm15SmallVectorImplIcE6appendINSt3__113move_iteratorIPcEEEEvT_S7_ ------------------ 424| | 425| | /// Add the specified range to the end of the SmallVector. 426| | void append(size_type NumInputs, const T &Elt) { 427| | // Grow allocated space if needed. 428| | if (NumInputs > size_type(this->capacity_ptr()-this->end())) 429| | this->grow(this->size()+NumInputs); 430| | 431| | // Copy the new elements over. 432| | std::uninitialized_fill_n(this->end(), NumInputs, Elt); 433| | this->setEnd(this->end() + NumInputs); 434| | } 435| | 436| | void append(std::initializer_list IL) { 437| | append(IL.begin(), IL.end()); 438| | } 439| | 440| | void assign(size_type NumElts, const T &Elt) { 441| | clear(); 442| | if (this->capacity() < NumElts) 443| | this->grow(NumElts); 444| | this->setEnd(this->begin()+NumElts); 445| | std::uninitialized_fill(this->begin(), this->end(), Elt); 446| | } 447| | 448| | void assign(std::initializer_list IL) { 449| | clear(); 450| | append(IL); 451| | } 452| | 453| 0| iterator erase(iterator I) { 454| 0| assert(I >= this->begin() && "Iterator to erase is out of bounds."); 455| 0| assert(I < this->end() && "Erasing at past-the-end iterator."); 456| 0| 457| 0| iterator N = I; 458| 0| // Shift all elts down one. 459| 0| this->move(I+1, this->end(), I); 460| 0| // Drop the last elt. 461| 0| this->pop_back(); 462| 0| return(N); 463| 0| } 464| | 465| 0| iterator erase(iterator S, iterator E) { 466| 0| assert(S >= this->begin() && "Range to erase is out of bounds."); 467| 0| assert(S <= E && "Trying to erase invalid range."); 468| 0| assert(E <= this->end() && "Trying to erase past the end."); 469| 0| 470| 0| iterator N = S; 471| 0| // Shift all elts down. 472| 0| iterator I = this->move(E, this->end(), S); 473| 0| // Drop the last elts. 474| 0| this->destroy_range(I, this->end()); 475| 0| this->setEnd(I); 476| 0| return(N); 477| 0| } 478| | 479| | iterator insert(iterator I, T &&Elt) { 480| | if (I == this->end()) { // Important special case for empty vector. 481| | this->push_back(::std::move(Elt)); 482| | return this->end()-1; 483| | } 484| | 485| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 486| | assert(I <= this->end() && "Inserting past the end of the vector."); 487| | 488| | if (this->EndX >= this->CapacityX) { 489| | size_t EltNo = I-this->begin(); 490| | this->grow(); 491| | I = this->begin()+EltNo; 492| | } 493| | 494| | ::new ((void*) this->end()) T(::std::move(this->back())); 495| | // Push everything else over. 496| | this->move_backward(I, this->end()-1, this->end()); 497| | this->setEnd(this->end()+1); 498| | 499| | // If we just moved the element we're inserting, be sure to update 500| | // the reference. 501| | T *EltPtr = &Elt; 502| | if (I <= EltPtr && EltPtr < this->EndX) 503| | ++EltPtr; 504| | 505| | *I = ::std::move(*EltPtr); 506| | return I; 507| | } 508| | 509| | iterator insert(iterator I, const T &Elt) { 510| | if (I == this->end()) { // Important special case for empty vector. 511| | this->push_back(Elt); 512| | return this->end()-1; 513| | } 514| | 515| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 516| | assert(I <= this->end() && "Inserting past the end of the vector."); 517| | 518| | if (this->EndX >= this->CapacityX) { 519| | size_t EltNo = I-this->begin(); 520| | this->grow(); 521| | I = this->begin()+EltNo; 522| | } 523| | ::new ((void*) this->end()) T(std::move(this->back())); 524| | // Push everything else over. 525| | this->move_backward(I, this->end()-1, this->end()); 526| | this->setEnd(this->end()+1); 527| | 528| | // If we just moved the element we're inserting, be sure to update 529| | // the reference. 530| | const T *EltPtr = &Elt; 531| | if (I <= EltPtr && EltPtr < this->EndX) 532| | ++EltPtr; 533| | 534| | *I = *EltPtr; 535| | return I; 536| | } 537| | 538| | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 539| | // Convert iterator to elt# to avoid invalidating iterator when we reserve() 540| | size_t InsertElt = I - this->begin(); 541| | 542| | if (I == this->end()) { // Important special case for empty vector. 543| | append(NumToInsert, Elt); 544| | return this->begin()+InsertElt; 545| | } 546| | 547| | assert(I >= this->begin() && "Insertion iterator is out of bounds."); 548| | assert(I <= this->end() && "Inserting past the end of the vector."); 549| | 550| | // Ensure there is enough space. 551| | reserve(this->size() + NumToInsert); 552| | 553| | // Uninvalidate the iterator. 554| | I = this->begin()+InsertElt; 555| | 556| | // If there are more elements between the insertion point and the end of the 557| | // range than there are being inserted, we can use a simple approach to 558| | // insertion. Since we already reserved space, we know that this won't 559| | // reallocate the vector. 560| | if (size_t(this->end()-I) >= NumToInsert) { 561| | T *OldEnd = this->end(); 562| | append(std::move_iterator(this->end() - NumToInsert), 563| | std::move_iterator(this->end())); 564| | 565| | // Copy the existing elements that get replaced. 566| | this->move_backward(I, OldEnd-NumToInsert, OldEnd); 567| | 568| | std::fill_n(I, NumToInsert, Elt); 569| | return I; 570| | } 571| | 572| | // Otherwise, we're inserting more elements than exist already, and we're 573| | // not inserting at the end. 574| | 575| | // Move over the elements that we're about to overwrite. 576| | T *OldEnd = this->end(); 577| | this->setEnd(this->end() + NumToInsert); 578| | size_t NumOverwritten = OldEnd-I; 579| | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 580| | 581| | // Replace the overwritten part. 582| | std::fill_n(I, NumOverwritten, Elt); 583| | 584| | // Insert the non-overwritten middle part. 585| | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 586| | return I; 587| | } 588| | 589| | template 590| 0| iterator insert(iterator I, ItTy From, ItTy To) { 591| 0| // Convert iterator to elt# to avoid invalidating iterator when we reserve() 592| 0| size_t InsertElt = I - this->begin(); 593| 0| 594| 0| if (I == this->end()) { // Important special case for empty vector. 595| 0| append(From, To); 596| 0| return this->begin()+InsertElt; 597| 0| } 598| 0| 599| 0| assert(I >= this->begin() && "Insertion iterator is out of bounds."); 600| 0| assert(I <= this->end() && "Inserting past the end of the vector."); 601| 0| 602| 0| size_t NumToInsert = std::distance(From, To); 603| 0| 604| 0| // Ensure there is enough space. 605| 0| reserve(this->size() + NumToInsert); 606| 0| 607| 0| // Uninvalidate the iterator. 608| 0| I = this->begin()+InsertElt; 609| 0| 610| 0| // If there are more elements between the insertion point and the end of the 611| 0| // range than there are being inserted, we can use a simple approach to 612| 0| // insertion. Since we already reserved space, we know that this won't 613| 0| // reallocate the vector. 614| 0| if (size_t(this->end()-I) >= NumToInsert) { 615| 0| T *OldEnd = this->end(); 616| 0| append(std::move_iterator(this->end() - NumToInsert), 617| 0| std::move_iterator(this->end())); 618| 0| 619| 0| // Copy the existing elements that get replaced. 620| 0| this->move_backward(I, OldEnd-NumToInsert, OldEnd); 621| 0| 622| 0| std::copy(From, To, I); 623| 0| return I; 624| 0| } 625| 0| 626| 0| // Otherwise, we're inserting more elements than exist already, and we're 627| 0| // not inserting at the end. 628| 0| 629| 0| // Move over the elements that we're about to overwrite. 630| 0| T *OldEnd = this->end(); 631| 0| this->setEnd(this->end() + NumToInsert); 632| 0| size_t NumOverwritten = OldEnd-I; 633| 0| this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); 634| 0| 635| 0| // Replace the overwritten part. 636| 0| for (T *J = I; NumOverwritten > 0; --NumOverwritten) { 637| 0| *J = *From; 638| 0| ++J; ++From; 639| 0| } 640| 0| 641| 0| // Insert the non-overwritten middle part. 642| 0| this->uninitialized_copy(From, To, OldEnd); 643| 0| return I; 644| 0| } 645| | 646| | void insert(iterator I, std::initializer_list IL) { 647| | insert(I, IL.begin(), IL.end()); 648| | } 649| | 650| | template void emplace_back(ArgTypes &&... Args) { 651| | if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) 652| | this->grow(); 653| | ::new ((void *)this->end()) T(std::forward(Args)...); 654| | this->setEnd(this->end() + 1); 655| | } 656| | 657| | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 658| | 659| | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); 660| | 661| | bool operator==(const SmallVectorImpl &RHS) const { 662| | if (this->size() != RHS.size()) return false; 663| | return std::equal(this->begin(), this->end(), RHS.begin()); 664| | } 665| | bool operator!=(const SmallVectorImpl &RHS) const { 666| | return !(*this == RHS); 667| | } 668| | 669| | bool operator<(const SmallVectorImpl &RHS) const { 670| | return std::lexicographical_compare(this->begin(), this->end(), 671| | RHS.begin(), RHS.end()); 672| | } 673| | 674| | /// Set the array size to \p N, which the current array must have enough 675| | /// capacity for. 676| | /// 677| | /// This does not construct or destroy any elements in the vector. 678| | /// 679| | /// Clients can use this in conjunction with capacity() to write past the end 680| | /// of the buffer when they know that more elements are available, and only 681| | /// update the size later. This avoids the cost of value initializing elements 682| | /// which will only be overwritten. 683| 0| void set_size(size_type N) { 684| 0| assert(N <= this->capacity()); 685| 0| this->setEnd(this->begin() + N); 686| 0| } 687| |}; 688| | 689| | 690| |template 691| 0|void SmallVectorImpl::swap(SmallVectorImpl &RHS) { 692| 0| if (this == &RHS) return; 693| 0| 694| 0| // We can only avoid copying elements if neither vector is small. 695| 0| if (!this->isSmall() && !RHS.isSmall()) { 696| 0| std::swap(this->BeginX, RHS.BeginX); 697| 0| std::swap(this->EndX, RHS.EndX); 698| 0| std::swap(this->CapacityX, RHS.CapacityX); 699| 0| return; 700| 0| } 701| 0| if (RHS.size() > this->capacity()) 702| 0| this->grow(RHS.size()); 703| 0| if (this->size() > RHS.capacity()) 704| 0| RHS.grow(this->size()); 705| 0| 706| 0| // Swap the shared elements. 707| 0| size_t NumShared = this->size(); 708| 0| if (NumShared > RHS.size()) NumShared = RHS.size(); 709| 0| for (size_type i = 0; i != NumShared; ++i) 710| 0| std::swap((*this)[i], RHS[i]); 711| 0| 712| 0| // Copy over the extra elts. 713| 0| if (this->size() > RHS.size()) { 714| 0| size_t EltDiff = this->size() - RHS.size(); 715| 0| this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 716| 0| RHS.setEnd(RHS.end()+EltDiff); 717| 0| this->destroy_range(this->begin()+NumShared, this->end()); 718| 0| this->setEnd(this->begin()+NumShared); 719| 0| } else if (RHS.size() > this->size()) { 720| 0| size_t EltDiff = RHS.size() - this->size(); 721| 0| this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 722| 0| this->setEnd(this->end() + EltDiff); 723| 0| this->destroy_range(RHS.begin()+NumShared, RHS.end()); 724| 0| RHS.setEnd(RHS.begin()+NumShared); 725| 0| } 726| 0|} 727| | 728| |template 729| |SmallVectorImpl &SmallVectorImpl:: 730| 0| operator=(const SmallVectorImpl &RHS) { 731| 0| // Avoid self-assignment. 732| 0| if (this == &RHS) return *this; 733| 0| 734| 0| // If we already have sufficient space, assign the common elements, then 735| 0| // destroy any excess. 736| 0| size_t RHSSize = RHS.size(); 737| 0| size_t CurSize = this->size(); 738| 0| if (CurSize >= RHSSize) { 739| 0| // Assign common elements. 740| 0| iterator NewEnd; 741| 0| if (RHSSize) 742| 0| NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 743| 0| else 744| 0| NewEnd = this->begin(); 745| 0| 746| 0| // Destroy excess elements. 747| 0| this->destroy_range(NewEnd, this->end()); 748| 0| 749| 0| // Trim. 750| 0| this->setEnd(NewEnd); 751| 0| return *this; 752| 0| } 753| 0| 754| 0| // If we have to grow to have enough elements, destroy the current elements. 755| 0| // This allows us to avoid copying them during the grow. 756| 0| // FIXME: don't do this if they're efficiently moveable. 757| 0| if (this->capacity() < RHSSize) { 758| 0| // Destroy current elements. 759| 0| this->destroy_range(this->begin(), this->end()); 760| 0| this->setEnd(this->begin()); 761| 0| CurSize = 0; 762| 0| this->grow(RHSSize); 763| 0| } else if (CurSize) { 764| 0| // Otherwise, use assignment for the already-constructed elements. 765| 0| std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 766| 0| } 767| 0| 768| 0| // Copy construct the new elements in place. 769| 0| this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 770| 0| this->begin()+CurSize); 771| 0| 772| 0| // Set end. 773| 0| this->setEnd(this->begin()+RHSSize); 774| 0| return *this; 775| 0|} 776| | 777| |template 778| 0|SmallVectorImpl &SmallVectorImpl::operator=(SmallVectorImpl &&RHS) { 779| 0| // Avoid self-assignment. 780| 0| if (this == &RHS) return *this; 781| 0| 782| 0| // If the RHS isn't small, clear this vector and then steal its buffer. 783| 0| if (!RHS.isSmall()) { 784| 0| this->destroy_range(this->begin(), this->end()); 785| 0| if (!this->isSmall()) free(this->begin()); 786| 0| this->BeginX = RHS.BeginX; 787| 0| this->EndX = RHS.EndX; 788| 0| this->CapacityX = RHS.CapacityX; 789| 0| RHS.resetToSmall(); 790| 0| return *this; 791| 0| } 792| 0| 793| 0| // If we already have sufficient space, assign the common elements, then 794| 0| // destroy any excess. 795| 0| size_t RHSSize = RHS.size(); 796| 0| size_t CurSize = this->size(); 797| 0| if (CurSize >= RHSSize) { 798| 0| // Assign common elements. 799| 0| iterator NewEnd = this->begin(); 800| 0| if (RHSSize) 801| 0| NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); 802| 0| 803| 0| // Destroy excess elements and trim the bounds. 804| 0| this->destroy_range(NewEnd, this->end()); 805| 0| this->setEnd(NewEnd); 806| 0| 807| 0| // Clear the RHS. 808| 0| RHS.clear(); 809| 0| 810| 0| return *this; 811| 0| } 812| 0| 813| 0| // If we have to grow to have enough elements, destroy the current elements. 814| 0| // This allows us to avoid copying them during the grow. 815| 0| // FIXME: this may not actually make any sense if we can efficiently move 816| 0| // elements. 817| 0| if (this->capacity() < RHSSize) { 818| 0| // Destroy current elements. 819| 0| this->destroy_range(this->begin(), this->end()); 820| 0| this->setEnd(this->begin()); 821| 0| CurSize = 0; 822| 0| this->grow(RHSSize); 823| 0| } else if (CurSize) { 824| 0| // Otherwise, use assignment for the already-constructed elements. 825| 0| this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); 826| 0| } 827| 0| 828| 0| // Move-construct the new elements in place. 829| 0| this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), 830| 0| this->begin()+CurSize); 831| 0| 832| 0| // Set end. 833| 0| this->setEnd(this->begin()+RHSSize); 834| 0| 835| 0| RHS.clear(); 836| 0| return *this; 837| 0|} 838| | 839| |/// Storage for the SmallVector elements which aren't contained in 840| |/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' 841| |/// element is in the base class. This is specialized for the N=1 and N=0 cases 842| |/// to avoid allocating unnecessary storage. 843| |template 844| |struct SmallVectorStorage { 845| | typename SmallVectorTemplateCommon::U InlineElts[N - 1]; 846| |}; 847| |template struct SmallVectorStorage {}; 848| |template struct SmallVectorStorage {}; 849| | 850| |/// This is a 'vector' (really, a variable-sized array), optimized 851| |/// for the case when the array is small. It contains some number of elements 852| |/// in-place, which allows it to avoid heap allocation when the actual number of 853| |/// elements is below that threshold. This allows normal "small" cases to be 854| |/// fast without losing generality for large inputs. 855| |/// 856| |/// Note that this does not attempt to be exception safe. 857| |/// 858| |template 859| |class SmallVector : public SmallVectorImpl { 860| | /// Inline space for elements which aren't stored in the base class. 861| | SmallVectorStorage Storage; 862| |public: 863| 0| SmallVector() : SmallVectorImpl(N) { 864| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj64EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj16384EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj256EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj128EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj32EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_9StringRefELj4EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_9StringRefELj8EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_9StringRefELj16EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_9StringRefELj32EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINSt3__14pairIjjEELj4EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj4EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIiLj4EEC2Ev ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvm11SmallVectorIN12_GLOBAL__N_19SimpleKeyELj4EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIPvLj4EEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINSt3__14pairIPvmEELj0EEC2Ev ------------------ 865| | 866| | explicit SmallVector(size_t Size, const T &Value = T()) 867| | : SmallVectorImpl(N) { 868| | this->assign(Size, Value); 869| | } 870| | 871| | template 872| 0| SmallVector(ItTy S, ItTy E) : SmallVectorImpl(N) { 873| 0| this->append(S, E); 874| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj200EEC2IPKcEET_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj128EEC2IPKcEET_S5_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorIcLj128EEC2INSt3__111__wrap_iterIPcEEEET_S7_ ------------------ | Unexecuted instantiation: _ZN4llvm11SmallVectorINS_7SMFixItELj4EEC2IPKS1_EET_S6_ ------------------ 875| | 876| | template 877| | explicit SmallVector(const llvm::iterator_range R) 878| | : SmallVectorImpl(N) { 879| | this->append(R.begin(), R.end()); 880| | } 881| | 882| | SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { 883| | this->assign(IL); 884| | } 885| | 886| | SmallVector(const SmallVector &RHS) : SmallVectorImpl(N) { 887| | if (!RHS.empty()) 888| | SmallVectorImpl::operator=(RHS); 889| | } 890| | 891| | const SmallVector &operator=(const SmallVector &RHS) { 892| | SmallVectorImpl::operator=(RHS); 893| | return *this; 894| | } 895| | 896| | SmallVector(SmallVector &&RHS) : SmallVectorImpl(N) { 897| | if (!RHS.empty()) 898| | SmallVectorImpl::operator=(::std::move(RHS)); 899| | } 900| | 901| | const SmallVector &operator=(SmallVector &&RHS) { 902| | SmallVectorImpl::operator=(::std::move(RHS)); 903| | return *this; 904| | } 905| | 906| | SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { 907| | if (!RHS.empty()) 908| | SmallVectorImpl::operator=(::std::move(RHS)); 909| | } 910| | 911| | const SmallVector &operator=(SmallVectorImpl &&RHS) { 912| | SmallVectorImpl::operator=(::std::move(RHS)); 913| | return *this; 914| | } 915| | 916| | const SmallVector &operator=(std::initializer_list IL) { 917| | this->assign(IL); 918| | return *this; 919| | } 920| |}; 921| | 922| |template 923| |static inline size_t capacity_in_bytes(const SmallVector &X) { 924| | return X.capacity_in_bytes(); 925| |} 926| | 927| |} // End llvm namespace 928| | 929| |namespace std { 930| | /// Implement std::swap in terms of SmallVector swap. 931| | template 932| | inline void 933| | swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { 934| | LHS.swap(RHS); 935| | } 936| | 937| | /// Implement std::swap in terms of SmallVector swap. 938| | template 939| | inline void 940| | swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { 941| | LHS.swap(RHS); 942| | } 943| |} 944| | 945| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringExtras.h: 1| |//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful when dealing with strings. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGEXTRAS_H 15| |#define LLVM_ADT_STRINGEXTRAS_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/DataTypes.h" 19| |#include 20| | 21| |namespace llvm { 22| |template class SmallVectorImpl; 23| | 24| |/// hexdigit - Return the hexadecimal character for the 25| |/// given number \p X (which should be less than 16). 26| 0|static inline char hexdigit(unsigned X, bool LowerCase = false) { 27| 0| const char HexChar = LowerCase ? 'a' : 'A'; 28| 0| return X < 10 ? '0' + X : HexChar + X - 10; 29| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL8hexdigitEjb ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL8hexdigitEjb ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL8hexdigitEjb ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL8hexdigitEjb ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL8hexdigitEjb ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL8hexdigitEjb ------------------ 30| | 31| |/// Construct a string ref from a boolean. 32| 0|static inline StringRef toStringRef(bool B) { 33| 0| return StringRef(B ? "true" : "false"); 34| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL11toStringRefEb ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL11toStringRefEb ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL11toStringRefEb ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL11toStringRefEb ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL11toStringRefEb ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL11toStringRefEb ------------------ 35| | 36| |/// Interpret the given character \p C as a hexadecimal digit and return its 37| |/// value. 38| |/// 39| |/// If \p C is not a valid hex digit, -1U is returned. 40| 0|static inline unsigned hexDigitValue(char C) { 41| 0| if (C >= '0' && C <= '9') return C-'0'; 42| 0| if (C >= 'a' && C <= 'f') return C-'a'+10U; 43| 0| if (C >= 'A' && C <= 'F') return C-'A'+10U; 44| 0| return -1U; 45| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL13hexDigitValueEc ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL13hexDigitValueEc ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL13hexDigitValueEc ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL13hexDigitValueEc ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL13hexDigitValueEc ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL13hexDigitValueEc ------------------ 46| | 47| |/// utohex_buffer - Emit the specified number into the buffer specified by 48| |/// BufferEnd, returning a pointer to the start of the string. This can be used 49| |/// like this: (note that the buffer must be large enough to handle any number): 50| |/// char Buffer[40]; 51| |/// printf("0x%s", utohex_buffer(X, Buffer+40)); 52| |/// 53| |/// This should only be used with unsigned types. 54| |/// 55| |template 56| 0|static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) { 57| 0| char *BufPtr = BufferEnd; 58| 0| *--BufPtr = 0; // Null terminate buffer. 59| 0| if (X == 0) { 60| 0| *--BufPtr = '0'; // Handle special case. 61| 0| return BufPtr; 62| 0| } 63| 0| 64| 0| while (X) { 65| 0| unsigned char Mod = static_cast(X) & 15; 66| 0| *--BufPtr = hexdigit(Mod, LowerCase); 67| 0| X >>= 4; 68| 0| } 69| 0| return BufPtr; 70| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL13utohex_bufferIyEEPcT_S1_b ------------------ 71| | 72| 0|static inline std::string utohexstr(uint64_t X, bool LowerCase = false) { 73| 0| char Buffer[17]; 74| 0| return utohex_buffer(X, Buffer+17, LowerCase); 75| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL9utohexstrEyb ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL9utohexstrEyb ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL9utohexstrEyb ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL9utohexstrEyb ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL9utohexstrEyb ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL9utohexstrEyb ------------------ 76| | 77| 0|static inline std::string utostr_32(uint32_t X, bool isNeg = false) { 78| 0| char Buffer[11]; 79| 0| char *BufPtr = Buffer+11; 80| 0| 81| 0| if (X == 0) *--BufPtr = '0'; // Handle special case... 82| 0| 83| 0| while (X) { 84| 0| *--BufPtr = '0' + char(X % 10); 85| 0| X /= 10; 86| 0| } 87| 0| 88| 0| if (isNeg) *--BufPtr = '-'; // Add negative sign... 89| 0| 90| 0| return std::string(BufPtr, Buffer+11); 91| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL9utostr_32Ejb ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL9utostr_32Ejb ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL9utostr_32Ejb ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL9utostr_32Ejb ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL9utostr_32Ejb ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL9utostr_32Ejb ------------------ 92| | 93| 0|static inline std::string utostr(uint64_t X, bool isNeg = false) { 94| 0| char Buffer[21]; 95| 0| char *BufPtr = Buffer+21; 96| 0| 97| 0| if (X == 0) *--BufPtr = '0'; // Handle special case... 98| 0| 99| 0| while (X) { 100| 0| *--BufPtr = '0' + char(X % 10); 101| 0| X /= 10; 102| 0| } 103| 0| 104| 0| if (isNeg) *--BufPtr = '-'; // Add negative sign... 105| 0| return std::string(BufPtr, Buffer+21); 106| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL6utostrEyb ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL6utostrEyb ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL6utostrEyb ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL6utostrEyb ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL6utostrEyb ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL6utostrEyb ------------------ 107| | 108| | 109| 0|static inline std::string itostr(int64_t X) { 110| 0| if (X < 0) 111| 0| return utostr(static_cast(-X), true); 112| 0| else 113| 0| return utostr(static_cast(X)); 114| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL6itostrEx ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL6itostrEx ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL6itostrEx ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL6itostrEx ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL6itostrEx ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL6itostrEx ------------------ 115| | 116| |/// StrInStrNoCase - Portable version of strcasestr. Locates the first 117| |/// occurrence of string 's1' in string 's2', ignoring case. Returns 118| |/// the offset of s2 in s1 or npos if s2 cannot be found. 119| |StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2); 120| | 121| |/// getToken - This function extracts one token from source, ignoring any 122| |/// leading characters that appear in the Delimiters string, and ending the 123| |/// token at any of the characters that appear in the Delimiters string. If 124| |/// there are no tokens in the source string, an empty string is returned. 125| |/// The function returns a pair containing the extracted token and the 126| |/// remaining tail string. 127| |std::pair getToken(StringRef Source, 128| | StringRef Delimiters = " \t\n\v\f\r"); 129| | 130| |/// SplitString - Split up the specified string according to the specified 131| |/// delimiters, appending the result fragments to the output list. 132| |void SplitString(StringRef Source, 133| | SmallVectorImpl &OutFragments, 134| | StringRef Delimiters = " \t\n\v\f\r"); 135| | 136| |/// HashString - Hash function for strings. 137| |/// 138| |/// This is the Bernstein hash function. 139| |// 140| |// FIXME: Investigate whether a modified bernstein hash function performs 141| |// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx 142| |// X*33+c -> X*33^c 143| 0|static inline unsigned HashString(StringRef Str, unsigned Result = 0) { 144| 0| for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i) 145| 0| Result = Result * 33 + (unsigned char)Str[i]; 146| 0| return Result; 147| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL10HashStringENS_9StringRefEj ------------------ 148| | 149| |/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). 150| 0|static inline StringRef getOrdinalSuffix(unsigned Val) { 151| 0| // It is critically important that we do this perfectly for 152| 0| // user-written sequences with over 100 elements. 153| 0| switch (Val % 100) { 154| 0| case 11: 155| 0| case 12: 156| 0| case 13: 157| 0| return "th"; 158| 0| default: 159| 0| switch (Val % 10) { 160| 0| case 1: return "st"; 161| 0| case 2: return "nd"; 162| 0| case 3: return "rd"; 163| 0| default: return "th"; 164| 0| } 165| 0| } 166| 0|} ------------------ | Unexecuted instantiation: Process.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ | Unexecuted instantiation: Program.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ | Unexecuted instantiation: StringExtras.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ | Unexecuted instantiation: StringMap.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ | Unexecuted instantiation: YAMLParser.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ | Unexecuted instantiation: raw_ostream.cpp:_ZN4llvmL16getOrdinalSuffixEj ------------------ 167| | 168| |template 169| |inline std::string join_impl(IteratorT Begin, IteratorT End, 170| | StringRef Separator, std::input_iterator_tag) { 171| | std::string S; 172| | if (Begin == End) 173| | return S; 174| | 175| | S += (*Begin); 176| | while (++Begin != End) { 177| | S += Separator; 178| | S += (*Begin); 179| | } 180| | return S; 181| |} 182| | 183| |template 184| |inline std::string join_impl(IteratorT Begin, IteratorT End, 185| | StringRef Separator, std::forward_iterator_tag) { 186| | std::string S; 187| | if (Begin == End) 188| | return S; 189| | 190| | size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); 191| | for (IteratorT I = Begin; I != End; ++I) 192| | Len += (*Begin).size(); 193| | S.reserve(Len); 194| | S += (*Begin); 195| | while (++Begin != End) { 196| | S += Separator; 197| | S += (*Begin); 198| | } 199| | return S; 200| |} 201| | 202| |/// Joins the strings in the range [Begin, End), adding Separator between 203| |/// the elements. 204| |template 205| |inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { 206| | typedef typename std::iterator_traits::iterator_category tag; 207| | return join_impl(Begin, End, Separator, tag()); 208| |} 209| | 210| |} // End llvm namespace 211| | 212| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringMap.h: 1| |//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the StringMap class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_ADT_STRINGMAP_H 15| |#define LLVM_ADT_STRINGMAP_H 16| | 17| |#include "llvm/ADT/StringRef.h" 18| |#include "llvm/Support/Allocator.h" 19| |#include 20| |#include 21| | 22| |namespace llvm { 23| | template 24| | class StringMapConstIterator; 25| | template 26| | class StringMapIterator; 27| | template 28| | class StringMapEntry; 29| | 30| |/// StringMapEntryBase - Shared base class of StringMapEntry instances. 31| |class StringMapEntryBase { 32| | unsigned StrLen; 33| |public: 34| 0| explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 35| | 36| 0| unsigned getKeyLength() const { return StrLen; } 37| |}; 38| | 39| |/// StringMapImpl - This is the base class of StringMap that is shared among 40| |/// all of its instantiations. 41| |class StringMapImpl { 42| |protected: 43| | // Array of NumBuckets pointers to entries, null pointers are holes. 44| | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 45| | // by an array of the actual hash values as unsigned integers. 46| | StringMapEntryBase **TheTable; 47| | unsigned NumBuckets; 48| | unsigned NumItems; 49| | unsigned NumTombstones; 50| | unsigned ItemSize; 51| |protected: 52| | explicit StringMapImpl(unsigned itemSize) 53| | : TheTable(nullptr), 54| | // Initialize the map with zero buckets to allocation. 55| 0| NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 56| | StringMapImpl(StringMapImpl &&RHS) 57| | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 58| | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 59| 0| ItemSize(RHS.ItemSize) { 60| 0| RHS.TheTable = nullptr; 61| 0| RHS.NumBuckets = 0; 62| 0| RHS.NumItems = 0; 63| 0| RHS.NumTombstones = 0; 64| 0| } 65| | 66| | StringMapImpl(unsigned InitSize, unsigned ItemSize); 67| | unsigned RehashTable(unsigned BucketNo = 0); 68| | 69| | /// LookupBucketFor - Look up the bucket that the specified string should end 70| | /// up in. If it already exists as a key in the map, the Item pointer for the 71| | /// specified bucket will be non-null. Otherwise, it will be null. In either 72| | /// case, the FullHashValue field of the bucket will be set to the hash value 73| | /// of the string. 74| | unsigned LookupBucketFor(StringRef Key); 75| | 76| | /// FindKey - Look up the bucket that contains the specified key. If it exists 77| | /// in the map, return the bucket number of the key. Otherwise return -1. 78| | /// This does not modify the map. 79| | int FindKey(StringRef Key) const; 80| | 81| | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 82| | /// delete it. This aborts if the value isn't in the table. 83| | void RemoveKey(StringMapEntryBase *V); 84| | 85| | /// RemoveKey - Remove the StringMapEntry for the specified key from the 86| | /// table, returning it. If the key is not in the table, this returns null. 87| | StringMapEntryBase *RemoveKey(StringRef Key); 88| |private: 89| | void init(unsigned Size); 90| |public: 91| 0| static StringMapEntryBase *getTombstoneVal() { 92| 0| return (StringMapEntryBase*)-1; 93| 0| } 94| | 95| 0| unsigned getNumBuckets() const { return NumBuckets; } 96| 0| unsigned getNumItems() const { return NumItems; } 97| | 98| | bool empty() const { return NumItems == 0; } 99| 0| unsigned size() const { return NumItems; } 100| | 101| 0| void swap(StringMapImpl &Other) { 102| 0| std::swap(TheTable, Other.TheTable); 103| 0| std::swap(NumBuckets, Other.NumBuckets); 104| 0| std::swap(NumItems, Other.NumItems); 105| 0| std::swap(NumTombstones, Other.NumTombstones); 106| 0| } 107| |}; 108| | 109| |/// StringMapEntry - This is used to represent one value that is inserted into 110| |/// a StringMap. It contains the Value itself and the key: the string length 111| |/// and data. 112| |template 113| |class StringMapEntry : public StringMapEntryBase { 114| | StringMapEntry(StringMapEntry &E) = delete; 115| |public: 116| | ValueTy second; 117| | 118| | explicit StringMapEntry(unsigned strLen) 119| | : StringMapEntryBase(strLen), second() {} 120| | template 121| | StringMapEntry(unsigned strLen, InitTy &&V) 122| | : StringMapEntryBase(strLen), second(std::forward(V)) {} 123| | 124| | StringRef getKey() const { 125| | return StringRef(getKeyData(), getKeyLength()); 126| | } 127| | 128| | const ValueTy &getValue() const { return second; } 129| | ValueTy &getValue() { return second; } 130| | 131| | void setValue(const ValueTy &V) { second = V; } 132| | 133| | /// getKeyData - Return the start of the string data that is the key for this 134| | /// value. The string data is always stored immediately after the 135| | /// StringMapEntry object. 136| | const char *getKeyData() const {return reinterpret_cast(this+1);} 137| | 138| | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 139| | 140| | /// Create - Create a StringMapEntry for the specified key and default 141| | /// construct the value. 142| | template 143| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, 144| | InitType &&InitVal) { 145| | unsigned KeyLength = Key.size(); 146| | 147| | // Allocate a new item with space for the string at the end and a null 148| | // terminator. 149| | unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ 150| | KeyLength+1; 151| | unsigned Alignment = alignOf(); 152| | 153| | StringMapEntry *NewItem = 154| | static_cast(Allocator.Allocate(AllocSize,Alignment)); 155| | 156| | // Default construct the value. 157| | new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); 158| | 159| | // Copy the string information. 160| | char *StrBuffer = const_cast(NewItem->getKeyData()); 161| | memcpy(StrBuffer, Key.data(), KeyLength); 162| | StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 163| | return NewItem; 164| | } 165| | 166| | template 167| | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 168| | return Create(Key, Allocator, ValueTy()); 169| | } 170| | 171| | /// Create - Create a StringMapEntry with normal malloc/free. 172| | template 173| | static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { 174| | MallocAllocator A; 175| | return Create(Key, A, std::forward(InitVal)); 176| | } 177| | 178| | static StringMapEntry *Create(StringRef Key) { 179| | return Create(Key, ValueTy()); 180| | } 181| | 182| | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 183| | /// into a StringMapEntry, return the StringMapEntry itself. 184| | static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 185| | char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); 186| | return *reinterpret_cast(Ptr); 187| | } 188| | 189| | /// Destroy - Destroy this StringMapEntry, releasing memory back to the 190| | /// specified allocator. 191| | template 192| | void Destroy(AllocatorTy &Allocator) { 193| | // Free memory referenced by the item. 194| | unsigned AllocSize = 195| | static_cast(sizeof(StringMapEntry)) + getKeyLength() + 1; 196| | this->~StringMapEntry(); 197| | Allocator.Deallocate(static_cast(this), AllocSize); 198| | } 199| | 200| | /// Destroy this object, releasing memory back to the malloc allocator. 201| | void Destroy() { 202| | MallocAllocator A; 203| | Destroy(A); 204| | } 205| |}; 206| | 207| | 208| |/// StringMap - This is an unconventional map that is specialized for handling 209| |/// keys that are "strings", which are basically ranges of bytes. This does some 210| |/// funky memory allocation and hashing things to make it extremely efficient, 211| |/// storing the string data *after* the value in the map. 212| |template 213| |class StringMap : public StringMapImpl { 214| | AllocatorTy Allocator; 215| |public: 216| | typedef StringMapEntry MapEntryTy; 217| | 218| | StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} 219| | explicit StringMap(unsigned InitialSize) 220| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} 221| | 222| | explicit StringMap(AllocatorTy A) 223| | : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} 224| | 225| | StringMap(unsigned InitialSize, AllocatorTy A) 226| | : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))), 227| | Allocator(A) {} 228| | 229| | StringMap(StringMap &&RHS) 230| | : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 231| | 232| | StringMap &operator=(StringMap RHS) { 233| | StringMapImpl::swap(RHS); 234| | std::swap(Allocator, RHS.Allocator); 235| | return *this; 236| | } 237| | 238| | // FIXME: Implement copy operations if/when they're needed. 239| | 240| | AllocatorTy &getAllocator() { return Allocator; } 241| | const AllocatorTy &getAllocator() const { return Allocator; } 242| | 243| | typedef const char* key_type; 244| | typedef ValueTy mapped_type; 245| | typedef StringMapEntry value_type; 246| | typedef size_t size_type; 247| | 248| | typedef StringMapConstIterator const_iterator; 249| | typedef StringMapIterator iterator; 250| | 251| | iterator begin() { 252| | return iterator(TheTable, NumBuckets == 0); 253| | } 254| | iterator end() { 255| | return iterator(TheTable+NumBuckets, true); 256| | } 257| | const_iterator begin() const { 258| | return const_iterator(TheTable, NumBuckets == 0); 259| | } 260| | const_iterator end() const { 261| | return const_iterator(TheTable+NumBuckets, true); 262| | } 263| | 264| | iterator find(StringRef Key) { 265| | int Bucket = FindKey(Key); 266| | if (Bucket == -1) return end(); 267| | return iterator(TheTable+Bucket, true); 268| | } 269| | 270| | const_iterator find(StringRef Key) const { 271| | int Bucket = FindKey(Key); 272| | if (Bucket == -1) return end(); 273| | return const_iterator(TheTable+Bucket, true); 274| | } 275| | 276| | /// lookup - Return the entry for the specified key, or a default 277| | /// constructed value if no such entry exists. 278| | ValueTy lookup(StringRef Key) const { 279| | const_iterator it = find(Key); 280| | if (it != end()) 281| | return it->second; 282| | return ValueTy(); 283| | } 284| | 285| | ValueTy &operator[](StringRef Key) { 286| | return insert(std::make_pair(Key, ValueTy())).first->second; 287| | } 288| | 289| | /// count - Return 1 if the element is in the map, 0 otherwise. 290| | size_type count(StringRef Key) const { 291| | return find(Key) == end() ? 0 : 1; 292| | } 293| | 294| | /// insert - Insert the specified key/value pair into the map. If the key 295| | /// already exists in the map, return false and ignore the request, otherwise 296| | /// insert it and return true. 297| | bool insert(MapEntryTy *KeyValue) { 298| | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 299| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 300| | if (Bucket && Bucket != getTombstoneVal()) 301| | return false; // Already exists in map. 302| | 303| | if (Bucket == getTombstoneVal()) 304| | --NumTombstones; 305| | Bucket = KeyValue; 306| | ++NumItems; 307| | assert(NumItems + NumTombstones <= NumBuckets); 308| | 309| | RehashTable(); 310| | return true; 311| | } 312| | 313| | /// insert - Inserts the specified key/value pair into the map if the key 314| | /// isn't already in the map. The bool component of the returned pair is true 315| | /// if and only if the insertion takes place, and the iterator component of 316| | /// the pair points to the element with key equivalent to the key of the pair. 317| | std::pair insert(std::pair KV) { 318| | unsigned BucketNo = LookupBucketFor(KV.first); 319| | StringMapEntryBase *&Bucket = TheTable[BucketNo]; 320| | if (Bucket && Bucket != getTombstoneVal()) 321| | return std::make_pair(iterator(TheTable + BucketNo, false), 322| | false); // Already exists in map. 323| | 324| | if (Bucket == getTombstoneVal()) 325| | --NumTombstones; 326| | Bucket = 327| | MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 328| | ++NumItems; 329| | assert(NumItems + NumTombstones <= NumBuckets); 330| | 331| | BucketNo = RehashTable(BucketNo); 332| | return std::make_pair(iterator(TheTable + BucketNo, false), true); 333| | } 334| | 335| | // clear - Empties out the StringMap 336| | void clear() { 337| | if (empty()) return; 338| | 339| | // Zap all values, resetting the keys back to non-present (not tombstone), 340| | // which is safe because we're removing all elements. 341| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 342| | StringMapEntryBase *&Bucket = TheTable[I]; 343| | if (Bucket && Bucket != getTombstoneVal()) { 344| | static_cast(Bucket)->Destroy(Allocator); 345| | } 346| | Bucket = nullptr; 347| | } 348| | 349| | NumItems = 0; 350| | NumTombstones = 0; 351| | } 352| | 353| | /// remove - Remove the specified key/value pair from the map, but do not 354| | /// erase it. This aborts if the key is not in the map. 355| | void remove(MapEntryTy *KeyValue) { 356| | RemoveKey(KeyValue); 357| | } 358| | 359| | void erase(iterator I) { 360| | MapEntryTy &V = *I; 361| | remove(&V); 362| | V.Destroy(Allocator); 363| | } 364| | 365| | bool erase(StringRef Key) { 366| | iterator I = find(Key); 367| | if (I == end()) return false; 368| | erase(I); 369| | return true; 370| | } 371| | 372| | ~StringMap() { 373| | // Delete all the elements in the map, but don't reset the elements 374| | // to default values. This is a copy of clear(), but avoids unnecessary 375| | // work not required in the destructor. 376| | if (!empty()) { 377| | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 378| | StringMapEntryBase *Bucket = TheTable[I]; 379| | if (Bucket && Bucket != getTombstoneVal()) { 380| | static_cast(Bucket)->Destroy(Allocator); 381| | } 382| | } 383| | } 384| | free(TheTable); 385| | } 386| |}; 387| | 388| | 389| |template 390| |class StringMapConstIterator { 391| |protected: 392| | StringMapEntryBase **Ptr; 393| |public: 394| | typedef StringMapEntry value_type; 395| | 396| | StringMapConstIterator() : Ptr(nullptr) { } 397| | 398| | explicit StringMapConstIterator(StringMapEntryBase **Bucket, 399| | bool NoAdvance = false) 400| | : Ptr(Bucket) { 401| | if (!NoAdvance) AdvancePastEmptyBuckets(); 402| | } 403| | 404| | const value_type &operator*() const { 405| | return *static_cast*>(*Ptr); 406| | } 407| | const value_type *operator->() const { 408| | return static_cast*>(*Ptr); 409| | } 410| | 411| | bool operator==(const StringMapConstIterator &RHS) const { 412| | return Ptr == RHS.Ptr; 413| | } 414| | bool operator!=(const StringMapConstIterator &RHS) const { 415| | return Ptr != RHS.Ptr; 416| | } 417| | 418| | inline StringMapConstIterator& operator++() { // Preincrement 419| | ++Ptr; 420| | AdvancePastEmptyBuckets(); 421| | return *this; 422| | } 423| | StringMapConstIterator operator++(int) { // Postincrement 424| | StringMapConstIterator tmp = *this; ++*this; return tmp; 425| | } 426| | 427| |private: 428| | void AdvancePastEmptyBuckets() { 429| | while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 430| | ++Ptr; 431| | } 432| |}; 433| | 434| |template 435| |class StringMapIterator : public StringMapConstIterator { 436| |public: 437| | StringMapIterator() {} 438| | explicit StringMapIterator(StringMapEntryBase **Bucket, 439| | bool NoAdvance = false) 440| | : StringMapConstIterator(Bucket, NoAdvance) { 441| | } 442| | StringMapEntry &operator*() const { 443| | return *static_cast*>(*this->Ptr); 444| | } 445| | StringMapEntry *operator->() const { 446| | return static_cast*>(*this->Ptr); 447| | } 448| |}; 449| | 450| |} 451| | 452| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/StringRef.h: 1| |//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_STRINGREF_H 11| |#define LLVM_ADT_STRINGREF_H 12| | 13| |#include 14| |#include 15| |#include 16| |#include 17| |#include 18| |#include 19| | 20| |namespace llvm { 21| | template 22| | class SmallVectorImpl; 23| | class hash_code; 24| | class StringRef; 25| | 26| | /// Helper functions for StringRef::getAsInteger. 27| | bool getAsUnsignedInteger(StringRef Str, unsigned Radix, 28| | unsigned long long &Result); 29| | 30| | bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); 31| | 32| | /// StringRef - Represent a constant reference to a string, i.e. a character 33| | /// array and a length, which need not be null terminated. 34| | /// 35| | /// This class does not own the string data, it is expected to be used in 36| | /// situations where the character data resides in some other buffer, whose 37| | /// lifetime extends past that of the StringRef. For this reason, it is not in 38| | /// general safe to store a StringRef. 39| | class StringRef { 40| | public: 41| | typedef const char *iterator; 42| | typedef const char *const_iterator; 43| | static const size_t npos = ~size_t(0); 44| | typedef size_t size_type; 45| | 46| | private: 47| | /// The start of the string, in an external buffer. 48| | const char *Data; 49| | 50| | /// The length of the string. 51| | size_t Length; 52| | 53| | // Workaround memcmp issue with null pointers (undefined behavior) 54| | // by providing a specialized version 55| 0| static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { 56| 0| if (Length == 0) { return 0; } 57| 0| return ::memcmp(Lhs,Rhs,Length); 58| 0| } 59| | 60| | public: 61| | /// @name Constructors 62| | /// @{ 63| | 64| | /// Construct an empty string ref. 65| 0| /*implicit*/ StringRef() : Data(nullptr), Length(0) {} 66| | 67| | /// Construct a string ref from a cstring. 68| | /*implicit*/ StringRef(const char *Str) 69| 0| : Data(Str) { 70| 0| assert(Str && "StringRef cannot be built from a NULL argument"); 71| 0| Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior 72| 0| } 73| | 74| | /// Construct a string ref from a pointer and length. 75| | /*implicit*/ StringRef(const char *data, size_t length) 76| 0| : Data(data), Length(length) { 77| 0| assert((data || length == 0) && 78| 0| "StringRef cannot be built from a NULL argument with non-null length"); 79| 0| } 80| | 81| | /// Construct a string ref from an std::string. 82| | /*implicit*/ StringRef(const std::string &Str) 83| 0| : Data(Str.data()), Length(Str.length()) {} 84| | 85| | /// @} 86| | /// @name Iterators 87| | /// @{ 88| | 89| 0| iterator begin() const { return Data; } 90| | 91| 0| iterator end() const { return Data + Length; } 92| | 93| 0| const unsigned char *bytes_begin() const { 94| 0| return reinterpret_cast(begin()); 95| 0| } 96| 0| const unsigned char *bytes_end() const { 97| 0| return reinterpret_cast(end()); 98| 0| } 99| | 100| | /// @} 101| | /// @name String Operations 102| | /// @{ 103| | 104| | /// data - Get a pointer to the start of the string (which may not be null 105| | /// terminated). 106| 0| const char *data() const { return Data; } 107| | 108| | /// empty - Check if the string is empty. 109| 0| bool empty() const { return Length == 0; } 110| | 111| | /// size - Get the string size. 112| 0| size_t size() const { return Length; } 113| | 114| | /// front - Get the first character in the string. 115| 0| char front() const { 116| 0| assert(!empty()); 117| 0| return Data[0]; 118| 0| } 119| | 120| | /// back - Get the last character in the string. 121| | char back() const { 122| | assert(!empty()); 123| | return Data[Length-1]; 124| | } 125| | 126| | // copy - Allocate copy in Allocator and return StringRef to it. 127| | template StringRef copy(Allocator &A) const { 128| | char *S = A.template Allocate(Length); 129| | std::copy(begin(), end(), S); 130| | return StringRef(S, Length); 131| | } 132| | 133| | /// equals - Check for string equality, this is more efficient than 134| | /// compare() when the relative ordering of inequal strings isn't needed. 135| 0| bool equals(StringRef RHS) const { 136| 0| return (Length == RHS.Length && 137| 0| compareMemory(Data, RHS.Data, RHS.Length) == 0); 138| 0| } 139| | 140| | /// equals_lower - Check for string equality, ignoring case. 141| 0| bool equals_lower(StringRef RHS) const { 142| 0| return Length == RHS.Length && compare_lower(RHS) == 0; 143| 0| } 144| | 145| | /// compare - Compare two strings; the result is -1, 0, or 1 if this string 146| | /// is lexicographically less than, equal to, or greater than the \p RHS. 147| 0| int compare(StringRef RHS) const { 148| 0| // Check the prefix for a mismatch. 149| 0| if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) 150| 0| return Res < 0 ? -1 : 1; 151| 0| 152| 0| // Otherwise the prefixes match, so we only need to check the lengths. 153| 0| if (Length == RHS.Length) 154| 0| return 0; 155| 0| return Length < RHS.Length ? -1 : 1; 156| 0| } 157| | 158| | /// compare_lower - Compare two strings, ignoring case. 159| | int compare_lower(StringRef RHS) const; 160| | 161| | /// compare_numeric - Compare two strings, treating sequences of digits as 162| | /// numbers. 163| | int compare_numeric(StringRef RHS) const; 164| | 165| | /// \brief Determine the edit distance between this string and another 166| | /// string. 167| | /// 168| | /// \param Other the string to compare this string against. 169| | /// 170| | /// \param AllowReplacements whether to allow character 171| | /// replacements (change one character into another) as a single 172| | /// operation, rather than as two operations (an insertion and a 173| | /// removal). 174| | /// 175| | /// \param MaxEditDistance If non-zero, the maximum edit distance that 176| | /// this routine is allowed to compute. If the edit distance will exceed 177| | /// that maximum, returns \c MaxEditDistance+1. 178| | /// 179| | /// \returns the minimum number of character insertions, removals, 180| | /// or (if \p AllowReplacements is \c true) replacements needed to 181| | /// transform one of the given strings into the other. If zero, 182| | /// the strings are identical. 183| | unsigned edit_distance(StringRef Other, bool AllowReplacements = true, 184| | unsigned MaxEditDistance = 0) const; 185| | 186| | /// str - Get the contents as an std::string. 187| 0| std::string str() const { 188| 0| if (!Data) return std::string(); 189| 0| return std::string(Data, Length); 190| 0| } 191| | 192| | /// @} 193| | /// @name Operator Overloads 194| | /// @{ 195| | 196| 0| char operator[](size_t Index) const { 197| 0| assert(Index < Length && "Invalid index!"); 198| 0| return Data[Index]; 199| 0| } 200| | 201| | /// @} 202| | /// @name Type Conversions 203| | /// @{ 204| | 205| 0| operator std::string() const { 206| 0| return str(); 207| 0| } 208| | 209| | /// @} 210| | /// @name String Predicates 211| | /// @{ 212| | 213| | /// Check if this string starts with the given \p Prefix. 214| 0| bool startswith(StringRef Prefix) const { 215| 0| return Length >= Prefix.Length && 216| 0| compareMemory(Data, Prefix.Data, Prefix.Length) == 0; 217| 0| } 218| | 219| | /// Check if this string starts with the given \p Prefix, ignoring case. 220| | bool startswith_lower(StringRef Prefix) const; 221| | 222| | /// Check if this string ends with the given \p Suffix. 223| | bool endswith(StringRef Suffix) const { 224| | return Length >= Suffix.Length && 225| | compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; 226| | } 227| | 228| | /// Check if this string ends with the given \p Suffix, ignoring case. 229| | bool endswith_lower(StringRef Suffix) const; 230| | 231| | /// @} 232| | /// @name String Searching 233| | /// @{ 234| | 235| | /// Search for the first character \p C in the string. 236| | /// 237| | /// \returns The index of the first occurrence of \p C, or npos if not 238| | /// found. 239| 0| size_t find(char C, size_t From = 0) const { 240| 0| for (size_t i = std::min(From, Length), e = Length; i != e; ++i) 241| 0| if (Data[i] == C) 242| 0| return i; 243| 0| return npos; 244| 0| } 245| | 246| | /// Search for the first string \p Str in the string. 247| | /// 248| | /// \returns The index of the first occurrence of \p Str, or npos if not 249| | /// found. 250| | size_t find(StringRef Str, size_t From = 0) const; 251| | 252| | /// Search for the last character \p C in the string. 253| | /// 254| | /// \returns The index of the last occurrence of \p C, or npos if not 255| | /// found. 256| 0| size_t rfind(char C, size_t From = npos) const { 257| 0| From = std::min(From, Length); 258| 0| size_t i = From; 259| 0| while (i != 0) { 260| 0| --i; 261| 0| if (Data[i] == C) 262| 0| return i; 263| 0| } 264| 0| return npos; 265| 0| } 266| | 267| | /// Search for the last string \p Str in the string. 268| | /// 269| | /// \returns The index of the last occurrence of \p Str, or npos if not 270| | /// found. 271| | size_t rfind(StringRef Str) const; 272| | 273| | /// Find the first character in the string that is \p C, or npos if not 274| | /// found. Same as find. 275| 0| size_t find_first_of(char C, size_t From = 0) const { 276| 0| return find(C, From); 277| 0| } 278| | 279| | /// Find the first character in the string that is in \p Chars, or npos if 280| | /// not found. 281| | /// 282| | /// Complexity: O(size() + Chars.size()) 283| | size_t find_first_of(StringRef Chars, size_t From = 0) const; 284| | 285| | /// Find the first character in the string that is not \p C or npos if not 286| | /// found. 287| | size_t find_first_not_of(char C, size_t From = 0) const; 288| | 289| | /// Find the first character in the string that is not in the string 290| | /// \p Chars, or npos if not found. 291| | /// 292| | /// Complexity: O(size() + Chars.size()) 293| | size_t find_first_not_of(StringRef Chars, size_t From = 0) const; 294| | 295| | /// Find the last character in the string that is \p C, or npos if not 296| | /// found. 297| 0| size_t find_last_of(char C, size_t From = npos) const { 298| 0| return rfind(C, From); 299| 0| } 300| | 301| | /// Find the last character in the string that is in \p C, or npos if not 302| | /// found. 303| | /// 304| | /// Complexity: O(size() + Chars.size()) 305| | size_t find_last_of(StringRef Chars, size_t From = npos) const; 306| | 307| | /// Find the last character in the string that is not \p C, or npos if not 308| | /// found. 309| | size_t find_last_not_of(char C, size_t From = npos) const; 310| | 311| | /// Find the last character in the string that is not in \p Chars, or 312| | /// npos if not found. 313| | /// 314| | /// Complexity: O(size() + Chars.size()) 315| | size_t find_last_not_of(StringRef Chars, size_t From = npos) const; 316| | 317| | /// @} 318| | /// @name Helpful Algorithms 319| | /// @{ 320| | 321| | /// Return the number of occurrences of \p C in the string. 322| 0| size_t count(char C) const { 323| 0| size_t Count = 0; 324| 0| for (size_t i = 0, e = Length; i != e; ++i) 325| 0| if (Data[i] == C) 326| 0| ++Count; 327| 0| return Count; 328| 0| } 329| | 330| | /// Return the number of non-overlapped occurrences of \p Str in 331| | /// the string. 332| | size_t count(StringRef Str) const; 333| | 334| | /// Parse the current string as an integer of the specified radix. If 335| | /// \p Radix is specified as zero, this does radix autosensing using 336| | /// extended C rules: 0 is octal, 0x is hex, 0b is binary. 337| | /// 338| | /// If the string is invalid or if only a subset of the string is valid, 339| | /// this returns true to signify the error. The string is considered 340| | /// erroneous if empty or if it overflows T. 341| | template 342| | typename std::enable_if::is_signed, bool>::type 343| | getAsInteger(unsigned Radix, T &Result) const { 344| | long long LLVal; 345| | if (getAsSignedInteger(*this, Radix, LLVal) || 346| | static_cast(LLVal) != LLVal) 347| | return true; 348| | Result = LLVal; 349| | return false; 350| | } 351| | 352| | template 353| | typename std::enable_if::is_signed, bool>::type 354| 0| getAsInteger(unsigned Radix, T &Result) const { 355| 0| unsigned long long ULLVal; 356| 0| // The additional cast to unsigned long long is required to avoid the 357| 0| // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type 358| 0| // 'unsigned __int64' when instantiating getAsInteger with T = bool. 359| 0| if (getAsUnsignedInteger(*this, Radix, ULLVal) || 360| 0| static_cast(static_cast(ULLVal)) != ULLVal) 361| 0| return true; 362| 0| Result = ULLVal; 363| 0| return false; 364| 0| } 365| | 366| | /// @} 367| | /// @name String Operations 368| | /// @{ 369| | 370| | // Convert the given ASCII string to lowercase. 371| | std::string lower() const; 372| | 373| | /// Convert the given ASCII string to uppercase. 374| | std::string upper() const; 375| | 376| | /// @} 377| | /// @name Substring Operations 378| | /// @{ 379| | 380| | /// Return a reference to the substring from [Start, Start + N). 381| | /// 382| | /// \param Start The index of the starting character in the substring; if 383| | /// the index is npos or greater than the length of the string then the 384| | /// empty substring will be returned. 385| | /// 386| | /// \param N The number of characters to included in the substring. If N 387| | /// exceeds the number of characters remaining in the string, the string 388| | /// suffix (starting with \p Start) will be returned. 389| 0| StringRef substr(size_t Start, size_t N = npos) const { 390| 0| Start = std::min(Start, Length); 391| 0| return StringRef(Data + Start, std::min(N, Length - Start)); 392| 0| } 393| | 394| | /// Return a StringRef equal to 'this' but with the first \p N elements 395| | /// dropped. 396| 0| StringRef drop_front(size_t N = 1) const { 397| 0| assert(size() >= N && "Dropping more elements than exist"); 398| 0| return substr(N); 399| 0| } 400| | 401| | /// Return a StringRef equal to 'this' but with the last \p N elements 402| | /// dropped. 403| 0| StringRef drop_back(size_t N = 1) const { 404| 0| assert(size() >= N && "Dropping more elements than exist"); 405| 0| return substr(0, size()-N); 406| 0| } 407| | 408| | /// Return a reference to the substring from [Start, End). 409| | /// 410| | /// \param Start The index of the starting character in the substring; if 411| | /// the index is npos or greater than the length of the string then the 412| | /// empty substring will be returned. 413| | /// 414| | /// \param End The index following the last character to include in the 415| | /// substring. If this is npos, or less than \p Start, or exceeds the 416| | /// number of characters remaining in the string, the string suffix 417| | /// (starting with \p Start) will be returned. 418| 0| StringRef slice(size_t Start, size_t End) const { 419| 0| Start = std::min(Start, Length); 420| 0| End = std::min(std::max(Start, End), Length); 421| 0| return StringRef(Data + Start, End - Start); 422| 0| } 423| | 424| | /// Split into two substrings around the first occurrence of a separator 425| | /// character. 426| | /// 427| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 428| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 429| | /// maximal. If \p Separator is not in the string, then the result is a 430| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 431| | /// 432| | /// \param Separator The character to split on. 433| | /// \returns The split substrings. 434| | std::pair split(char Separator) const { 435| | size_t Idx = find(Separator); 436| | if (Idx == npos) 437| | return std::make_pair(*this, StringRef()); 438| | return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 439| | } 440| | 441| | /// Split into two substrings around the first occurrence of a separator 442| | /// string. 443| | /// 444| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 445| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 446| | /// maximal. If \p Separator is not in the string, then the result is a 447| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 448| | /// 449| | /// \param Separator - The string to split on. 450| | /// \return - The split substrings. 451| 0| std::pair split(StringRef Separator) const { 452| 0| size_t Idx = find(Separator); 453| 0| if (Idx == npos) 454| 0| return std::make_pair(*this, StringRef()); 455| 0| return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); 456| 0| } 457| | 458| | /// Split into substrings around the occurrences of a separator string. 459| | /// 460| | /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most 461| | /// \p MaxSplit splits are done and consequently <= \p MaxSplit 462| | /// elements are added to A. 463| | /// If \p KeepEmpty is false, empty strings are not added to \p A. They 464| | /// still count when considering \p MaxSplit 465| | /// An useful invariant is that 466| | /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true 467| | /// 468| | /// \param A - Where to put the substrings. 469| | /// \param Separator - The string to split on. 470| | /// \param MaxSplit - The maximum number of times the string is split. 471| | /// \param KeepEmpty - True if empty substring should be added. 472| | void split(SmallVectorImpl &A, 473| | StringRef Separator, int MaxSplit = -1, 474| | bool KeepEmpty = true) const; 475| | 476| | /// Split into two substrings around the last occurrence of a separator 477| | /// character. 478| | /// 479| | /// If \p Separator is in the string, then the result is a pair (LHS, RHS) 480| | /// such that (*this == LHS + Separator + RHS) is true and RHS is 481| | /// minimal. If \p Separator is not in the string, then the result is a 482| | /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). 483| | /// 484| | /// \param Separator - The character to split on. 485| | /// \return - The split substrings. 486| 0| std::pair rsplit(char Separator) const { 487| 0| size_t Idx = rfind(Separator); 488| 0| if (Idx == npos) 489| 0| return std::make_pair(*this, StringRef()); 490| 0| return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); 491| 0| } 492| | 493| | /// Return string with consecutive characters in \p Chars starting from 494| | /// the left removed. 495| 0| StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { 496| 0| return drop_front(std::min(Length, find_first_not_of(Chars))); 497| 0| } 498| | 499| | /// Return string with consecutive characters in \p Chars starting from 500| | /// the right removed. 501| 0| StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { 502| 0| return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); 503| 0| } 504| | 505| | /// Return string with consecutive characters in \p Chars starting from 506| | /// the left and right removed. 507| 0| StringRef trim(StringRef Chars = " \t\n\v\f\r") const { 508| 0| return ltrim(Chars).rtrim(Chars); 509| 0| } 510| | 511| | /// @} 512| | }; 513| | 514| | /// @name StringRef Comparison Operators 515| | /// @{ 516| | 517| 0| inline bool operator==(StringRef LHS, StringRef RHS) { 518| 0| return LHS.equals(RHS); 519| 0| } 520| | 521| 0| inline bool operator!=(StringRef LHS, StringRef RHS) { 522| 0| return !(LHS == RHS); 523| 0| } 524| | 525| 0| inline bool operator<(StringRef LHS, StringRef RHS) { 526| 0| return LHS.compare(RHS) == -1; 527| 0| } 528| | 529| 0| inline bool operator<=(StringRef LHS, StringRef RHS) { 530| 0| return LHS.compare(RHS) != 1; 531| 0| } 532| | 533| 0| inline bool operator>(StringRef LHS, StringRef RHS) { 534| 0| return LHS.compare(RHS) == 1; 535| 0| } 536| | 537| 0| inline bool operator>=(StringRef LHS, StringRef RHS) { 538| 0| return LHS.compare(RHS) != -1; 539| 0| } 540| | 541| 0| inline std::string &operator+=(std::string &buffer, StringRef string) { 542| 0| return buffer.append(string.data(), string.size()); 543| 0| } 544| | 545| | /// @} 546| | 547| | /// \brief Compute a hash_code for a StringRef. 548| | hash_code hash_value(StringRef S); 549| | 550| | // StringRefs can be treated like a POD type. 551| | template struct isPodLike; 552| | template <> struct isPodLike { static const bool value = true; }; 553| |} 554| | 555| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/Twine.h: 1| |//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| | 10| |#ifndef LLVM_ADT_TWINE_H 11| |#define LLVM_ADT_TWINE_H 12| | 13| |#include "llvm/ADT/StringRef.h" 14| |#include "llvm/Support/DataTypes.h" 15| |#include "llvm/Support/ErrorHandling.h" 16| |#include 17| |#include 18| | 19| |namespace llvm { 20| | template 21| | class SmallVectorImpl; 22| | class StringRef; 23| | class raw_ostream; 24| | 25| | /// Twine - A lightweight data structure for efficiently representing the 26| | /// concatenation of temporary values as strings. 27| | /// 28| | /// A Twine is a kind of rope, it represents a concatenated string using a 29| | /// binary-tree, where the string is the preorder of the nodes. Since the 30| | /// Twine can be efficiently rendered into a buffer when its result is used, 31| | /// it avoids the cost of generating temporary values for intermediate string 32| | /// results -- particularly in cases when the Twine result is never 33| | /// required. By explicitly tracking the type of leaf nodes, we can also avoid 34| | /// the creation of temporary strings for conversions operations (such as 35| | /// appending an integer to a string). 36| | /// 37| | /// A Twine is not intended for use directly and should not be stored, its 38| | /// implementation relies on the ability to store pointers to temporary stack 39| | /// objects which may be deallocated at the end of a statement. Twines should 40| | /// only be used accepted as const references in arguments, when an API wishes 41| | /// to accept possibly-concatenated strings. 42| | /// 43| | /// Twines support a special 'null' value, which always concatenates to form 44| | /// itself, and renders as an empty string. This can be returned from APIs to 45| | /// effectively nullify any concatenations performed on the result. 46| | /// 47| | /// \b Implementation 48| | /// 49| | /// Given the nature of a Twine, it is not possible for the Twine's 50| | /// concatenation method to construct interior nodes; the result must be 51| | /// represented inside the returned value. For this reason a Twine object 52| | /// actually holds two values, the left- and right-hand sides of a 53| | /// concatenation. We also have nullary Twine objects, which are effectively 54| | /// sentinel values that represent empty strings. 55| | /// 56| | /// Thus, a Twine can effectively have zero, one, or two children. The \see 57| | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 58| | /// testing the number of children. 59| | /// 60| | /// We maintain a number of invariants on Twine objects (FIXME: Why): 61| | /// - Nullary twines are always represented with their Kind on the left-hand 62| | /// side, and the Empty kind on the right-hand side. 63| | /// - Unary twines are always represented with the value on the left-hand 64| | /// side, and the Empty kind on the right-hand side. 65| | /// - If a Twine has another Twine as a child, that child should always be 66| | /// binary (otherwise it could have been folded into the parent). 67| | /// 68| | /// These invariants are check by \see isValid(). 69| | /// 70| | /// \b Efficiency Considerations 71| | /// 72| | /// The Twine is designed to yield efficient and small code for common 73| | /// situations. For this reason, the concat() method is inlined so that 74| | /// concatenations of leaf nodes can be optimized into stores directly into a 75| | /// single stack allocated object. 76| | /// 77| | /// In practice, not all compilers can be trusted to optimize concat() fully, 78| | /// so we provide two additional methods (and accompanying operator+ 79| | /// overloads) to guarantee that particularly important cases (cstring plus 80| | /// StringRef) codegen as desired. 81| | class Twine { 82| | /// NodeKind - Represent the type of an argument. 83| | enum NodeKind : unsigned char { 84| | /// An empty string; the result of concatenating anything with it is also 85| | /// empty. 86| | NullKind, 87| | 88| | /// The empty string. 89| | EmptyKind, 90| | 91| | /// A pointer to a Twine instance. 92| | TwineKind, 93| | 94| | /// A pointer to a C string instance. 95| | CStringKind, 96| | 97| | /// A pointer to an std::string instance. 98| | StdStringKind, 99| | 100| | /// A pointer to a StringRef instance. 101| | StringRefKind, 102| | 103| | /// A char value reinterpreted as a pointer, to render as a character. 104| | CharKind, 105| | 106| | /// An unsigned int value reinterpreted as a pointer, to render as an 107| | /// unsigned decimal integer. 108| | DecUIKind, 109| | 110| | /// An int value reinterpreted as a pointer, to render as a signed 111| | /// decimal integer. 112| | DecIKind, 113| | 114| | /// A pointer to an unsigned long value, to render as an unsigned decimal 115| | /// integer. 116| | DecULKind, 117| | 118| | /// A pointer to a long value, to render as a signed decimal integer. 119| | DecLKind, 120| | 121| | /// A pointer to an unsigned long long value, to render as an unsigned 122| | /// decimal integer. 123| | DecULLKind, 124| | 125| | /// A pointer to a long long value, to render as a signed decimal integer. 126| | DecLLKind, 127| | 128| | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 129| | /// integer. 130| | UHexKind 131| | }; 132| | 133| | union Child 134| | { 135| | const Twine *twine; 136| | const char *cString; 137| | const std::string *stdString; 138| | const StringRef *stringRef; 139| | char character; 140| | unsigned int decUI; 141| | int decI; 142| | const unsigned long *decUL; 143| | const long *decL; 144| | const unsigned long long *decULL; 145| | const long long *decLL; 146| | const uint64_t *uHex; 147| | }; 148| | 149| | private: 150| | /// LHS - The prefix in the concatenation, which may be uninitialized for 151| | /// Null or Empty kinds. 152| | Child LHS; 153| | /// RHS - The suffix in the concatenation, which may be uninitialized for 154| | /// Null or Empty kinds. 155| | Child RHS; 156| | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 157| | NodeKind LHSKind; 158| | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). 159| | NodeKind RHSKind; 160| | 161| | private: 162| | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 163| | explicit Twine(NodeKind Kind) 164| 0| : LHSKind(Kind), RHSKind(EmptyKind) { 165| 0| assert(isNullary() && "Invalid kind!"); 166| 0| } 167| | 168| | /// Construct a binary twine. 169| | explicit Twine(const Twine &LHS, const Twine &RHS) 170| 0| : LHSKind(TwineKind), RHSKind(TwineKind) { 171| 0| this->LHS.twine = &LHS; 172| 0| this->RHS.twine = &RHS; 173| 0| assert(isValid() && "Invalid twine!"); 174| 0| } 175| | 176| | /// Construct a twine from explicit values. 177| | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) 178| 0| : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { 179| 0| assert(isValid() && "Invalid twine!"); 180| 0| } 181| | 182| | /// Since the intended use of twines is as temporary objects, assignments 183| | /// when concatenating might cause undefined behavior or stack corruptions 184| | Twine &operator=(const Twine &Other) = delete; 185| | 186| | /// isNull - Check for the null twine. 187| 0| bool isNull() const { 188| 0| return getLHSKind() == NullKind; 189| 0| } 190| | 191| | /// isEmpty - Check for the empty twine. 192| 0| bool isEmpty() const { 193| 0| return getLHSKind() == EmptyKind; 194| 0| } 195| | 196| | /// isNullary - Check if this is a nullary twine (null or empty). 197| 0| bool isNullary() const { 198| 0| return isNull() || isEmpty(); 199| 0| } 200| | 201| | /// isUnary - Check if this is a unary twine. 202| 0| bool isUnary() const { 203| 0| return getRHSKind() == EmptyKind && !isNullary(); 204| 0| } 205| | 206| | /// isBinary - Check if this is a binary twine. 207| 0| bool isBinary() const { 208| 0| return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 209| 0| } 210| | 211| | /// isValid - Check if this is a valid twine (satisfying the invariants on 212| | /// order and number of arguments). 213| 0| bool isValid() const { 214| 0| // Nullary twines always have Empty on the RHS. 215| 0| if (isNullary() && getRHSKind() != EmptyKind) 216| 0| return false; 217| 0| 218| 0| // Null should never appear on the RHS. 219| 0| if (getRHSKind() == NullKind) 220| 0| return false; 221| 0| 222| 0| // The RHS cannot be non-empty if the LHS is empty. 223| 0| if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 224| 0| return false; 225| 0| 226| 0| // A twine child should always be binary. 227| 0| if (getLHSKind() == TwineKind && 228| 0| !LHS.twine->isBinary()) 229| 0| return false; 230| 0| if (getRHSKind() == TwineKind && 231| 0| !RHS.twine->isBinary()) 232| 0| return false; 233| 0| 234| 0| return true; 235| 0| } 236| | 237| | /// getLHSKind - Get the NodeKind of the left-hand side. 238| 0| NodeKind getLHSKind() const { return LHSKind; } 239| | 240| | /// getRHSKind - Get the NodeKind of the right-hand side. 241| 0| NodeKind getRHSKind() const { return RHSKind; } 242| | 243| | /// printOneChild - Print one child from a twine. 244| | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; 245| | 246| | /// printOneChildRepr - Print the representation of one child from a twine. 247| | void printOneChildRepr(raw_ostream &OS, Child Ptr, 248| | NodeKind Kind) const; 249| | 250| | public: 251| | /// @name Constructors 252| | /// @{ 253| | 254| | /// Construct from an empty string. 255| 0| /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 256| 0| assert(isValid() && "Invalid twine!"); 257| 0| } 258| | 259| | Twine(const Twine &) = default; 260| | 261| | /// Construct from a C string. 262| | /// 263| | /// We take care here to optimize "" into the empty twine -- this will be 264| | /// optimized out for string constants. This allows Twine arguments have 265| | /// default "" values, without introducing unnecessary string constants. 266| | /*implicit*/ Twine(const char *Str) 267| 0| : RHSKind(EmptyKind) { 268| 0| if (Str[0] != '\0') { 269| 0| LHS.cString = Str; 270| 0| LHSKind = CStringKind; 271| 0| } else 272| 0| LHSKind = EmptyKind; 273| 0| 274| 0| assert(isValid() && "Invalid twine!"); 275| 0| } 276| | 277| | /// Construct from an std::string. 278| | /*implicit*/ Twine(const std::string &Str) 279| 0| : LHSKind(StdStringKind), RHSKind(EmptyKind) { 280| 0| LHS.stdString = &Str; 281| 0| assert(isValid() && "Invalid twine!"); 282| 0| } 283| | 284| | /// Construct from a StringRef. 285| | /*implicit*/ Twine(const StringRef &Str) 286| 0| : LHSKind(StringRefKind), RHSKind(EmptyKind) { 287| 0| LHS.stringRef = &Str; 288| 0| assert(isValid() && "Invalid twine!"); 289| 0| } 290| | 291| | /// Construct from a char. 292| | explicit Twine(char Val) 293| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 294| 0| LHS.character = Val; 295| 0| } 296| | 297| | /// Construct from a signed char. 298| | explicit Twine(signed char Val) 299| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 300| 0| LHS.character = static_cast(Val); 301| 0| } 302| | 303| | /// Construct from an unsigned char. 304| | explicit Twine(unsigned char Val) 305| 0| : LHSKind(CharKind), RHSKind(EmptyKind) { 306| 0| LHS.character = static_cast(Val); 307| 0| } 308| | 309| | /// Construct a twine to print \p Val as an unsigned decimal integer. 310| | explicit Twine(unsigned Val) 311| 0| : LHSKind(DecUIKind), RHSKind(EmptyKind) { 312| 0| LHS.decUI = Val; 313| 0| } 314| | 315| | /// Construct a twine to print \p Val as a signed decimal integer. 316| | explicit Twine(int Val) 317| 0| : LHSKind(DecIKind), RHSKind(EmptyKind) { 318| 0| LHS.decI = Val; 319| 0| } 320| | 321| | /// Construct a twine to print \p Val as an unsigned decimal integer. 322| | explicit Twine(const unsigned long &Val) 323| 0| : LHSKind(DecULKind), RHSKind(EmptyKind) { 324| 0| LHS.decUL = &Val; 325| 0| } 326| | 327| | /// Construct a twine to print \p Val as a signed decimal integer. 328| | explicit Twine(const long &Val) 329| 0| : LHSKind(DecLKind), RHSKind(EmptyKind) { 330| 0| LHS.decL = &Val; 331| 0| } 332| | 333| | /// Construct a twine to print \p Val as an unsigned decimal integer. 334| | explicit Twine(const unsigned long long &Val) 335| 0| : LHSKind(DecULLKind), RHSKind(EmptyKind) { 336| 0| LHS.decULL = &Val; 337| 0| } 338| | 339| | /// Construct a twine to print \p Val as a signed decimal integer. 340| | explicit Twine(const long long &Val) 341| 0| : LHSKind(DecLLKind), RHSKind(EmptyKind) { 342| 0| LHS.decLL = &Val; 343| 0| } 344| | 345| | // FIXME: Unfortunately, to make sure this is as efficient as possible we 346| | // need extra binary constructors from particular types. We can't rely on 347| | // the compiler to be smart enough to fold operator+()/concat() down to the 348| | // right thing. Yet. 349| | 350| | /// Construct as the concatenation of a C string and a StringRef. 351| | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) 352| | : LHSKind(CStringKind), RHSKind(StringRefKind) { 353| | this->LHS.cString = LHS; 354| | this->RHS.stringRef = &RHS; 355| | assert(isValid() && "Invalid twine!"); 356| | } 357| | 358| | /// Construct as the concatenation of a StringRef and a C string. 359| | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) 360| | : LHSKind(StringRefKind), RHSKind(CStringKind) { 361| | this->LHS.stringRef = &LHS; 362| | this->RHS.cString = RHS; 363| | assert(isValid() && "Invalid twine!"); 364| | } 365| | 366| | /// Create a 'null' string, which is an empty string that always 367| | /// concatenates to form another empty string. 368| 0| static Twine createNull() { 369| 0| return Twine(NullKind); 370| 0| } 371| | 372| | /// @} 373| | /// @name Numeric Conversions 374| | /// @{ 375| | 376| | // Construct a twine to print \p Val as an unsigned hexadecimal integer. 377| | static Twine utohexstr(const uint64_t &Val) { 378| | Child LHS, RHS; 379| | LHS.uHex = &Val; 380| | RHS.twine = nullptr; 381| | return Twine(LHS, UHexKind, RHS, EmptyKind); 382| | } 383| | 384| | /// @} 385| | /// @name Predicate Operations 386| | /// @{ 387| | 388| | /// isTriviallyEmpty - Check if this twine is trivially empty; a false 389| | /// return value does not necessarily mean the twine is empty. 390| 0| bool isTriviallyEmpty() const { 391| 0| return isNullary(); 392| 0| } 393| | 394| | /// isSingleStringRef - Return true if this twine can be dynamically 395| | /// accessed as a single StringRef value with getSingleStringRef(). 396| 0| bool isSingleStringRef() const { 397| 0| if (getRHSKind() != EmptyKind) return false; 398| 0| 399| 0| switch (getLHSKind()) { 400| 0| case EmptyKind: 401| 0| case CStringKind: 402| 0| case StdStringKind: 403| 0| case StringRefKind: 404| 0| return true; 405| 0| default: 406| 0| return false; 407| 0| } 408| 0| } 409| | 410| | /// @} 411| | /// @name String Operations 412| | /// @{ 413| | 414| | Twine concat(const Twine &Suffix) const; 415| | 416| | /// @} 417| | /// @name Output & Conversion. 418| | /// @{ 419| | 420| | /// str - Return the twine contents as a std::string. 421| | std::string str() const; 422| | 423| | /// toVector - Write the concatenated string into the given SmallString or 424| | /// SmallVector. 425| | void toVector(SmallVectorImpl &Out) const; 426| | 427| | /// getSingleStringRef - This returns the twine as a single StringRef. This 428| | /// method is only valid if isSingleStringRef() is true. 429| 0| StringRef getSingleStringRef() const { 430| 0| assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); 431| 0| switch (getLHSKind()) { 432| 0| default: llvm_unreachable("Out of sync with isSingleStringRef"); 433| 0| case EmptyKind: return StringRef(); 434| 0| case CStringKind: return StringRef(LHS.cString); 435| 0| case StdStringKind: return StringRef(*LHS.stdString); 436| 0| case StringRefKind: return *LHS.stringRef; 437| 0| } 438| 0| } 439| | 440| | /// toStringRef - This returns the twine as a single StringRef if it can be 441| | /// represented as such. Otherwise the twine is written into the given 442| | /// SmallVector and a StringRef to the SmallVector's data is returned. 443| | StringRef toStringRef(SmallVectorImpl &Out) const; 444| | 445| | /// toNullTerminatedStringRef - This returns the twine as a single null 446| | /// terminated StringRef if it can be represented as such. Otherwise the 447| | /// twine is written into the given SmallVector and a StringRef to the 448| | /// SmallVector's data is returned. 449| | /// 450| | /// The returned StringRef's size does not include the null terminator. 451| | StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; 452| | 453| | /// Write the concatenated string represented by this twine to the 454| | /// stream \p OS. 455| | void print(raw_ostream &OS) const; 456| | 457| | /// Dump the concatenated string represented by this twine to stderr. 458| | void dump() const; 459| | 460| | /// Write the representation of this twine to the stream \p OS. 461| | void printRepr(raw_ostream &OS) const; 462| | 463| | /// Dump the representation of this twine to stderr. 464| | void dumpRepr() const; 465| | 466| | /// @} 467| | }; 468| | 469| | /// @name Twine Inline Implementations 470| | /// @{ 471| | 472| 0| inline Twine Twine::concat(const Twine &Suffix) const { 473| 0| // Concatenation with null is null. 474| 0| if (isNull() || Suffix.isNull()) 475| 0| return Twine(NullKind); 476| 0| 477| 0| // Concatenation with empty yields the other side. 478| 0| if (isEmpty()) 479| 0| return Suffix; 480| 0| if (Suffix.isEmpty()) 481| 0| return *this; 482| 0| 483| 0| // Otherwise we need to create a new node, taking care to fold in unary 484| 0| // twines. 485| 0| Child NewLHS, NewRHS; 486| 0| NewLHS.twine = this; 487| 0| NewRHS.twine = &Suffix; 488| 0| NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 489| 0| if (isUnary()) { 490| 0| NewLHS = LHS; 491| 0| NewLHSKind = getLHSKind(); 492| 0| } 493| 0| if (Suffix.isUnary()) { 494| 0| NewRHS = Suffix.LHS; 495| 0| NewRHSKind = Suffix.getLHSKind(); 496| 0| } 497| 0| 498| 0| return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 499| 0| } 500| | 501| 0| inline Twine operator+(const Twine &LHS, const Twine &RHS) { 502| 0| return LHS.concat(RHS); 503| 0| } 504| | 505| | /// Additional overload to guarantee simplified codegen; this is equivalent to 506| | /// concat(). 507| | 508| | inline Twine operator+(const char *LHS, const StringRef &RHS) { 509| | return Twine(LHS, RHS); 510| | } 511| | 512| | /// Additional overload to guarantee simplified codegen; this is equivalent to 513| | /// concat(). 514| | 515| | inline Twine operator+(const StringRef &LHS, const char *RHS) { 516| | return Twine(LHS, RHS); 517| | } 518| | 519| 0| inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 520| 0| RHS.print(OS); 521| 0| return OS; 522| 0| } 523| | 524| | /// @} 525| |} 526| | 527| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/edit_distance.h: 1| |//===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines a Levenshtein distance function that works for any two 11| |// sequences, with each element of each sequence being analogous to a character 12| |// in a string. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_ADT_EDIT_DISTANCE_H 17| |#define LLVM_ADT_EDIT_DISTANCE_H 18| | 19| |#include "llvm/ADT/ArrayRef.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| | 25| |/// \brief Determine the edit distance between two sequences. 26| |/// 27| |/// \param FromArray the first sequence to compare. 28| |/// 29| |/// \param ToArray the second sequence to compare. 30| |/// 31| |/// \param AllowReplacements whether to allow element replacements (change one 32| |/// element into another) as a single operation, rather than as two operations 33| |/// (an insertion and a removal). 34| |/// 35| |/// \param MaxEditDistance If non-zero, the maximum edit distance that this 36| |/// routine is allowed to compute. If the edit distance will exceed that 37| |/// maximum, returns \c MaxEditDistance+1. 38| |/// 39| |/// \returns the minimum number of element insertions, removals, or (if 40| |/// \p AllowReplacements is \c true) replacements needed to transform one of 41| |/// the given sequences into the other. If zero, the sequences are identical. 42| |template 43| |unsigned ComputeEditDistance(ArrayRef FromArray, ArrayRef ToArray, 44| | bool AllowReplacements = true, 45| 0| unsigned MaxEditDistance = 0) { 46| 0| // The algorithm implemented below is the "classic" 47| 0| // dynamic-programming algorithm for computing the Levenshtein 48| 0| // distance, which is described here: 49| 0| // 50| 0| // http://en.wikipedia.org/wiki/Levenshtein_distance 51| 0| // 52| 0| // Although the algorithm is typically described using an m x n 53| 0| // array, only two rows are used at a time, so this implemenation 54| 0| // just keeps two separate vectors for those two rows. 55| 0| typename ArrayRef::size_type m = FromArray.size(); 56| 0| typename ArrayRef::size_type n = ToArray.size(); 57| 0| 58| 0| const unsigned SmallBufferSize = 64; 59| 0| unsigned SmallBuffer[SmallBufferSize]; 60| 0| std::unique_ptr Allocated; 61| 0| unsigned *Previous = SmallBuffer; 62| 0| if (2*(n + 1) > SmallBufferSize) { 63| 0| Previous = new unsigned [2*(n+1)]; 64| 0| Allocated.reset(Previous); 65| 0| } 66| 0| unsigned *Current = Previous + (n + 1); 67| 0| 68| 0| for (unsigned i = 0; i <= n; ++i) 69| 0| Previous[i] = i; 70| 0| 71| 0| for (typename ArrayRef::size_type y = 1; y <= m; ++y) { 72| 0| Current[0] = y; 73| 0| unsigned BestThisRow = Current[0]; 74| 0| 75| 0| for (typename ArrayRef::size_type x = 1; x <= n; ++x) { 76| 0| if (AllowReplacements) { 77| 0| Current[x] = std::min( 78| 0| Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), 79| 0| std::min(Current[x-1], Previous[x])+1); 80| 0| } 81| 0| else { 82| 0| if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1]; 83| 0| else Current[x] = std::min(Current[x-1], Previous[x]) + 1; 84| 0| } 85| 0| BestThisRow = std::min(BestThisRow, Current[x]); 86| 0| } 87| 0| 88| 0| if (MaxEditDistance && BestThisRow > MaxEditDistance) 89| 0| return MaxEditDistance + 1; 90| 0| 91| 0| unsigned *tmp = Current; 92| 0| Current = Previous; 93| 0| Previous = tmp; 94| 0| } 95| 0| 96| 0| unsigned Result = Previous[n]; 97| 0| return Result; 98| 0|} 99| | 100| |} // End llvm namespace 101| | 102| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/ilist.h: 1| |//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines classes to implement an intrusive doubly linked list class 11| |// (i.e. each node of the list must contain a next and previous field for the 12| |// list. 13| |// 14| |// The ilist_traits trait class is used to gain access to the next and previous 15| |// fields of the node type that the list is instantiated with. If it is not 16| |// specialized, the list defaults to using the getPrev(), getNext() method calls 17| |// to get the next and previous pointers. 18| |// 19| |// The ilist class itself, should be a plug in replacement for list, assuming 20| |// that the nodes contain next/prev pointers. This list replacement does not 21| |// provide a constant time size() method, so be careful to use empty() when you 22| |// really want to know if it's empty. 23| |// 24| |// The ilist class is implemented by allocating a 'tail' node when the list is 25| |// created (using ilist_traits<>::createSentinel()). This tail node is 26| |// absolutely required because the user must be able to compute end()-1. Because 27| |// of this, users of the direct next/prev links will see an extra link on the 28| |// end of the list, which should be ignored. 29| |// 30| |// Requirements for a user of this list: 31| |// 32| |// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize 33| |// ilist_traits to provide an alternate way of getting and setting next and 34| |// prev links. 35| |// 36| |//===----------------------------------------------------------------------===// 37| | 38| |#ifndef LLVM_ADT_ILIST_H 39| |#define LLVM_ADT_ILIST_H 40| | 41| |#include "llvm/Support/Compiler.h" 42| |#include 43| |#include 44| |#include 45| |#include 46| | 47| |namespace llvm { 48| | 49| |template class iplist; 50| |template class ilist_iterator; 51| | 52| |/// ilist_nextprev_traits - A fragment for template traits for intrusive list 53| |/// that provides default next/prev implementations for common operations. 54| |/// 55| |template 56| |struct ilist_nextprev_traits { 57| 0| static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } 58| 0| static NodeTy *getNext(NodeTy *N) { return N->getNext(); } 59| | static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } 60| | static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } 61| | 62| 0| static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } 63| 0| static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } 64| |}; 65| | 66| |template 67| |struct ilist_traits; 68| | 69| |/// ilist_sentinel_traits - A fragment for template traits for intrusive list 70| |/// that provides default sentinel implementations for common operations. 71| |/// 72| |/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation 73| |/// strategy. The sentinel is stored in the prev field of ilist's Head. 74| |/// 75| |template 76| |struct ilist_sentinel_traits { 77| | /// createSentinel - create the dynamic sentinel 78| | static NodeTy *createSentinel() { return new NodeTy(); } 79| | 80| | /// destroySentinel - deallocate the dynamic sentinel 81| | static void destroySentinel(NodeTy *N) { delete N; } 82| | 83| | /// provideInitialHead - when constructing an ilist, provide a starting 84| | /// value for its Head 85| | /// @return null node to indicate that it needs to be allocated later 86| | static NodeTy *provideInitialHead() { return nullptr; } 87| | 88| | /// ensureHead - make sure that Head is either already 89| | /// initialized or assigned a fresh sentinel 90| | /// @return the sentinel 91| | static NodeTy *ensureHead(NodeTy *&Head) { 92| | if (!Head) { 93| | Head = ilist_traits::createSentinel(); 94| | ilist_traits::noteHead(Head, Head); 95| | ilist_traits::setNext(Head, nullptr); 96| | return Head; 97| | } 98| | return ilist_traits::getPrev(Head); 99| | } 100| | 101| | /// noteHead - stash the sentinel into its default location 102| | static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) { 103| | ilist_traits::setPrev(NewHead, Sentinel); 104| | } 105| |}; 106| | 107| |/// ilist_node_traits - A fragment for template traits for intrusive list 108| |/// that provides default node related operations. 109| |/// 110| |template 111| |struct ilist_node_traits { 112| | static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } 113| | static void deleteNode(NodeTy *V) { delete V; } 114| | 115| | void addNodeToList(NodeTy *) {} 116| | void removeNodeFromList(NodeTy *) {} 117| | void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, 118| | ilist_iterator /*first*/, 119| | ilist_iterator /*last*/) {} 120| |}; 121| | 122| |/// ilist_default_traits - Default template traits for intrusive list. 123| |/// By inheriting from this, you can easily use default implementations 124| |/// for all common operations. 125| |/// 126| |template 127| |struct ilist_default_traits : public ilist_nextprev_traits, 128| | public ilist_sentinel_traits, 129| | public ilist_node_traits { 130| |}; 131| | 132| |// Template traits for intrusive list. By specializing this template class, you 133| |// can change what next/prev fields are used to store the links... 134| |template 135| |struct ilist_traits : public ilist_default_traits {}; 136| | 137| |// Const traits are the same as nonconst traits... 138| |template 139| |struct ilist_traits : public ilist_traits {}; 140| | 141| |//===----------------------------------------------------------------------===// 142| |// ilist_iterator - Iterator for intrusive list. 143| |// 144| |template 145| |class ilist_iterator 146| | : public std::iterator { 147| | 148| |public: 149| | typedef ilist_traits Traits; 150| | typedef std::iterator super; 152| | 153| | typedef typename super::value_type value_type; 154| | typedef typename super::difference_type difference_type; 155| | typedef typename super::pointer pointer; 156| | typedef typename super::reference reference; 157| |private: 158| | pointer NodePtr; 159| | 160| | // ilist_iterator is not a random-access iterator, but it has an 161| | // implicit conversion to pointer-type, which is. Declare (but 162| | // don't define) these functions as private to help catch 163| | // accidental misuse. 164| | void operator[](difference_type) const; 165| | void operator+(difference_type) const; 166| | void operator-(difference_type) const; 167| | void operator+=(difference_type) const; 168| | void operator-=(difference_type) const; 169| | template void operator<(T) const; 170| | template void operator<=(T) const; 171| | template void operator>(T) const; 172| | template void operator>=(T) const; 173| | template void operator-(T) const; 174| |public: 175| | 176| 0| ilist_iterator(pointer NP) : NodePtr(NP) {} 177| 0| ilist_iterator(reference NR) : NodePtr(&NR) {} 178| 0| ilist_iterator() : NodePtr(nullptr) {} 179| | 180| | // This is templated so that we can allow constructing a const iterator from 181| | // a nonconst iterator... 182| | template 183| | ilist_iterator(const ilist_iterator &RHS) 184| | : NodePtr(RHS.getNodePtrUnchecked()) {} 185| | 186| | // This is templated so that we can allow assigning to a const iterator from 187| | // a nonconst iterator... 188| | template 189| | const ilist_iterator &operator=(const ilist_iterator &RHS) { 190| | NodePtr = RHS.getNodePtrUnchecked(); 191| | return *this; 192| | } 193| | 194| | // Accessors... 195| | operator pointer() const { 196| | return NodePtr; 197| | } 198| | 199| 0| reference operator*() const { 200| 0| return *NodePtr; 201| 0| } 202| 0| pointer operator->() const { return &operator*(); } 203| | 204| | // Comparison operators 205| 0| bool operator==(const ilist_iterator &RHS) const { 206| 0| return NodePtr == RHS.NodePtr; 207| 0| } 208| 0| bool operator!=(const ilist_iterator &RHS) const { 209| 0| return NodePtr != RHS.NodePtr; 210| 0| } 211| | 212| | // Increment and decrement operators... 213| | ilist_iterator &operator--() { // predecrement - Back up 214| | NodePtr = Traits::getPrev(NodePtr); 215| | assert(NodePtr && "--'d off the beginning of an ilist!"); 216| | return *this; 217| | } 218| 0| ilist_iterator &operator++() { // preincrement - Advance 219| 0| NodePtr = Traits::getNext(NodePtr); 220| 0| return *this; 221| 0| } 222| | ilist_iterator operator--(int) { // postdecrement operators... 223| | ilist_iterator tmp = *this; 224| | --*this; 225| | return tmp; 226| | } 227| | ilist_iterator operator++(int) { // postincrement operators... 228| | ilist_iterator tmp = *this; 229| | ++*this; 230| | return tmp; 231| | } 232| | 233| | // Internal interface, do not use... 234| 0| pointer getNodePtrUnchecked() const { return NodePtr; } 235| |}; 236| | 237| |// These are to catch errors when people try to use them as random access 238| |// iterators. 239| |template 240| |void operator-(int, ilist_iterator) = delete; 241| |template 242| |void operator-(ilist_iterator,int) = delete; 243| | 244| |template 245| |void operator+(int, ilist_iterator) = delete; 246| |template 247| |void operator+(ilist_iterator,int) = delete; 248| | 249| |// operator!=/operator== - Allow mixed comparisons without dereferencing 250| |// the iterator, which could very likely be pointing to end(). 251| |template 252| |bool operator!=(const T* LHS, const ilist_iterator &RHS) { 253| | return LHS != RHS.getNodePtrUnchecked(); 254| |} 255| |template 256| |bool operator==(const T* LHS, const ilist_iterator &RHS) { 257| | return LHS == RHS.getNodePtrUnchecked(); 258| |} 259| |template 260| |bool operator!=(T* LHS, const ilist_iterator &RHS) { 261| | return LHS != RHS.getNodePtrUnchecked(); 262| |} 263| |template 264| |bool operator==(T* LHS, const ilist_iterator &RHS) { 265| | return LHS == RHS.getNodePtrUnchecked(); 266| |} 267| | 268| | 269| |// Allow ilist_iterators to convert into pointers to a node automatically when 270| |// used by the dyn_cast, cast, isa mechanisms... 271| | 272| |template struct simplify_type; 273| | 274| |template struct simplify_type > { 275| | typedef NodeTy* SimpleType; 276| | 277| | static SimpleType getSimplifiedValue(ilist_iterator &Node) { 278| | return &*Node; 279| | } 280| |}; 281| |template struct simplify_type > { 282| | typedef /*const*/ NodeTy* SimpleType; 283| | 284| | static SimpleType getSimplifiedValue(const ilist_iterator &Node) { 285| | return &*Node; 286| | } 287| |}; 288| | 289| | 290| |//===----------------------------------------------------------------------===// 291| |// 292| |/// iplist - The subset of list functionality that can safely be used on nodes 293| |/// of polymorphic types, i.e. a heterogeneous list with a common base class that 294| |/// holds the next/prev pointers. The only state of the list itself is a single 295| |/// pointer to the head of the list. 296| |/// 297| |/// This list can be in one of three interesting states: 298| |/// 1. The list may be completely unconstructed. In this case, the head 299| |/// pointer is null. When in this form, any query for an iterator (e.g. 300| |/// begin() or end()) causes the list to transparently change to state #2. 301| |/// 2. The list may be empty, but contain a sentinel for the end iterator. This 302| |/// sentinel is created by the Traits::createSentinel method and is a link 303| |/// in the list. When the list is empty, the pointer in the iplist points 304| |/// to the sentinel. Once the sentinel is constructed, it 305| |/// is not destroyed until the list is. 306| |/// 3. The list may contain actual objects in it, which are stored as a doubly 307| |/// linked list of nodes. One invariant of the list is that the predecessor 308| |/// of the first node in the list always points to the last node in the list, 309| |/// and the successor pointer for the sentinel (which always stays at the 310| |/// end of the list) is always null. 311| |/// 312| |template > 313| |class iplist : public Traits { 314| | mutable NodeTy *Head; 315| | 316| | // Use the prev node pointer of 'head' as the tail pointer. This is really a 317| | // circularly linked list where we snip the 'next' link from the sentinel node 318| | // back to the first node in the list (to preserve assertions about going off 319| | // the end of the list). 320| 0| NodeTy *getTail() { return this->ensureHead(Head); } 321| 0| const NodeTy *getTail() const { return this->ensureHead(Head); } 322| | void setTail(NodeTy *N) const { this->noteHead(Head, N); } 323| | 324| | /// CreateLazySentinel - This method verifies whether the sentinel for the 325| | /// list has been created and lazily makes it if not. 326| 0| void CreateLazySentinel() const { 327| 0| this->ensureHead(Head); 328| 0| } 329| | 330| | static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } 331| | static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } 332| | 333| | // No fundamental reason why iplist can't be copyable, but the default 334| | // copy/copy-assign won't do. 335| | iplist(const iplist &) = delete; 336| | void operator=(const iplist &) = delete; 337| | 338| |public: 339| | typedef NodeTy *pointer; 340| | typedef const NodeTy *const_pointer; 341| | typedef NodeTy &reference; 342| | typedef const NodeTy &const_reference; 343| | typedef NodeTy value_type; 344| | typedef ilist_iterator iterator; 345| | typedef ilist_iterator const_iterator; 346| | typedef size_t size_type; 347| | typedef ptrdiff_t difference_type; 348| | typedef std::reverse_iterator const_reverse_iterator; 349| | typedef std::reverse_iterator reverse_iterator; 350| | 351| 0| iplist() : Head(this->provideInitialHead()) {} 352| 0| ~iplist() { 353| 0| if (!Head) return; 354| 0| clear(); 355| 0| Traits::destroySentinel(getTail()); 356| 0| } 357| | 358| | // Iterator creation methods. 359| 0| iterator begin() { 360| 0| CreateLazySentinel(); 361| 0| return iterator(Head); 362| 0| } 363| | const_iterator begin() const { 364| | CreateLazySentinel(); 365| | return const_iterator(Head); 366| | } 367| 0| iterator end() { 368| 0| CreateLazySentinel(); 369| 0| return iterator(getTail()); 370| 0| } 371| | const_iterator end() const { 372| | CreateLazySentinel(); 373| | return const_iterator(getTail()); 374| | } 375| | 376| | // reverse iterator creation methods. 377| | reverse_iterator rbegin() { return reverse_iterator(end()); } 378| | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 379| | reverse_iterator rend() { return reverse_iterator(begin()); } 380| | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 381| | 382| | 383| | // Miscellaneous inspection routines. 384| | size_type max_size() const { return size_type(-1); } 385| 0| bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { 386| 0| return !Head || Head == getTail(); 387| 0| } 388| | 389| | // Front and back accessor functions... 390| 0| reference front() { 391| 0| assert(!empty() && "Called front() on empty list!"); 392| 0| return *Head; 393| 0| } 394| | const_reference front() const { 395| | assert(!empty() && "Called front() on empty list!"); 396| | return *Head; 397| | } 398| 0| reference back() { 399| 0| assert(!empty() && "Called back() on empty list!"); 400| 0| return *this->getPrev(getTail()); 401| 0| } 402| | const_reference back() const { 403| | assert(!empty() && "Called back() on empty list!"); 404| | return *this->getPrev(getTail()); 405| | } 406| | 407| | void swap(iplist &RHS) { 408| | assert(0 && "Swap does not use list traits callback correctly yet!"); 409| | std::swap(Head, RHS.Head); 410| | } 411| | 412| 0| iterator insert(iterator where, NodeTy *New) { 413| 0| NodeTy *CurNode = where.getNodePtrUnchecked(); 414| 0| NodeTy *PrevNode = this->getPrev(CurNode); 415| 0| this->setNext(New, CurNode); 416| 0| this->setPrev(New, PrevNode); 417| 0| 418| 0| if (CurNode != Head) // Is PrevNode off the beginning of the list? 419| 0| this->setNext(PrevNode, New); 420| 0| else 421| 0| Head = New; 422| 0| this->setPrev(CurNode, New); 423| 0| 424| 0| this->addNodeToList(New); // Notify traits that we added a node... 425| 0| return New; 426| 0| } 427| | 428| | iterator insertAfter(iterator where, NodeTy *New) { 429| | if (empty()) 430| | return insert(begin(), New); 431| | else 432| | return insert(++where, New); 433| | } 434| | 435| 0| NodeTy *remove(iterator &IT) { 436| 0| assert(IT != end() && "Cannot remove end of list!"); 437| 0| NodeTy *Node = &*IT; 438| 0| NodeTy *NextNode = this->getNext(Node); 439| 0| NodeTy *PrevNode = this->getPrev(Node); 440| 0| 441| 0| if (Node != Head) // Is PrevNode off the beginning of the list? 442| 0| this->setNext(PrevNode, NextNode); 443| 0| else 444| 0| Head = NextNode; 445| 0| this->setPrev(NextNode, PrevNode); 446| 0| IT = NextNode; 447| 0| this->removeNodeFromList(Node); // Notify traits that we removed a node... 448| 0| 449| 0| // Set the next/prev pointers of the current node to null. This isn't 450| 0| // strictly required, but this catches errors where a node is removed from 451| 0| // an ilist (and potentially deleted) with iterators still pointing at it. 452| 0| // When those iterators are incremented or decremented, they will assert on 453| 0| // the null next/prev pointer instead of "usually working". 454| 0| this->setNext(Node, nullptr); 455| 0| this->setPrev(Node, nullptr); 456| 0| return Node; 457| 0| } 458| | 459| | NodeTy *remove(const iterator &IT) { 460| | iterator MutIt = IT; 461| | return remove(MutIt); 462| | } 463| | 464| | // erase - remove a node from the controlled sequence... and delete it. 465| 0| iterator erase(iterator where) { 466| 0| this->deleteNode(remove(where)); 467| 0| return where; 468| 0| } 469| | 470| | /// Remove all nodes from the list like clear(), but do not call 471| | /// removeNodeFromList() or deleteNode(). 472| | /// 473| | /// This should only be used immediately before freeing nodes in bulk to 474| | /// avoid traversing the list and bringing all the nodes into cache. 475| | void clearAndLeakNodesUnsafely() { 476| | if (Head) { 477| | Head = getTail(); 478| | this->setPrev(Head, Head); 479| | } 480| | } 481| | 482| |private: 483| | // transfer - The heart of the splice function. Move linked list nodes from 484| | // [first, last) into position. 485| | // 486| | void transfer(iterator position, iplist &L2, iterator first, iterator last) { 487| | assert(first != last && "Should be checked by callers"); 488| | // Position cannot be contained in the range to be transferred. 489| | // Check for the most common mistake. 490| | assert(position != first && 491| | "Insertion point can't be one of the transferred nodes"); 492| | 493| | if (position != last) { 494| | // Note: we have to be careful about the case when we move the first node 495| | // in the list. This node is the list sentinel node and we can't move it. 496| | NodeTy *ThisSentinel = getTail(); 497| | setTail(nullptr); 498| | NodeTy *L2Sentinel = L2.getTail(); 499| | L2.setTail(nullptr); 500| | 501| | // Remove [first, last) from its old position. 502| | NodeTy *First = &*first, *Prev = this->getPrev(First); 503| | NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->getPrev(Next); 504| | if (Prev) 505| | this->setNext(Prev, Next); 506| | else 507| | L2.Head = Next; 508| | this->setPrev(Next, Prev); 509| | 510| | // Splice [first, last) into its new position. 511| | NodeTy *PosNext = position.getNodePtrUnchecked(); 512| | NodeTy *PosPrev = this->getPrev(PosNext); 513| | 514| | // Fix head of list... 515| | if (PosPrev) 516| | this->setNext(PosPrev, First); 517| | else 518| | Head = First; 519| | this->setPrev(First, PosPrev); 520| | 521| | // Fix end of list... 522| | this->setNext(Last, PosNext); 523| | this->setPrev(PosNext, Last); 524| | 525| | this->transferNodesFromList(L2, First, PosNext); 526| | 527| | // Now that everything is set, restore the pointers to the list sentinels. 528| | L2.setTail(L2Sentinel); 529| | setTail(ThisSentinel); 530| | } 531| | } 532| | 533| |public: 534| | 535| | //===----------------------------------------------------------------------=== 536| | // Functionality derived from other functions defined above... 537| | // 538| | 539| | size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { 540| | if (!Head) return 0; // Don't require construction of sentinel if empty. 541| | return std::distance(begin(), end()); 542| | } 543| | 544| 0| iterator erase(iterator first, iterator last) { 545| 0| while (first != last) 546| 0| first = erase(first); 547| 0| return last; 548| 0| } 549| | 550| 0| void clear() { if (Head) erase(begin(), end()); } 551| | 552| | // Front and back inserters... 553| | void push_front(NodeTy *val) { insert(begin(), val); } 554| | void push_back(NodeTy *val) { insert(end(), val); } 555| 0| void pop_front() { 556| 0| assert(!empty() && "pop_front() on empty list!"); 557| 0| erase(begin()); 558| 0| } 559| | void pop_back() { 560| | assert(!empty() && "pop_back() on empty list!"); 561| | iterator t = end(); erase(--t); 562| | } 563| | 564| | // Special forms of insert... 565| | template void insert(iterator where, InIt first, InIt last) { 566| | for (; first != last; ++first) insert(where, *first); 567| | } 568| | 569| | // Splice members - defined in terms of transfer... 570| | void splice(iterator where, iplist &L2) { 571| | if (!L2.empty()) 572| | transfer(where, L2, L2.begin(), L2.end()); 573| | } 574| | void splice(iterator where, iplist &L2, iterator first) { 575| | iterator last = first; ++last; 576| | if (where == first || where == last) return; // No change 577| | transfer(where, L2, first, last); 578| | } 579| | void splice(iterator where, iplist &L2, iterator first, iterator last) { 580| | if (first != last) transfer(where, L2, first, last); 581| | } 582| |}; 583| | 584| | 585| |template 586| |struct ilist : public iplist { 587| | typedef typename iplist::size_type size_type; 588| | typedef typename iplist::iterator iterator; 589| | 590| 0| ilist() {} 591| | ilist(const ilist &right) { 592| | insert(this->begin(), right.begin(), right.end()); 593| | } 594| | explicit ilist(size_type count) { 595| | insert(this->begin(), count, NodeTy()); 596| | } 597| | ilist(size_type count, const NodeTy &val) { 598| | insert(this->begin(), count, val); 599| | } 600| | template ilist(InIt first, InIt last) { 601| | insert(this->begin(), first, last); 602| | } 603| | 604| | // bring hidden functions into scope 605| | using iplist::insert; 606| | using iplist::push_front; 607| | using iplist::push_back; 608| | 609| | // Main implementation here - Insert for a node passed by value... 610| 0| iterator insert(iterator where, const NodeTy &val) { 611| 0| return insert(where, this->createNode(val)); 612| 0| } 613| | 614| | 615| | // Front and back inserters... 616| | void push_front(const NodeTy &val) { insert(this->begin(), val); } 617| 0| void push_back(const NodeTy &val) { insert(this->end(), val); } 618| | 619| | void insert(iterator where, size_type count, const NodeTy &val) { 620| | for (; count != 0; --count) insert(where, val); 621| | } 622| | 623| | // Assign special forms... 624| | void assign(size_type count, const NodeTy &val) { 625| | iterator I = this->begin(); 626| | for (; I != this->end() && count != 0; ++I, --count) 627| | *I = val; 628| | if (count != 0) 629| | insert(this->end(), val, val); 630| | else 631| | erase(I, this->end()); 632| | } 633| | template void assign(InIt first1, InIt last1) { 634| | iterator first2 = this->begin(), last2 = this->end(); 635| | for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) 636| | *first1 = *first2; 637| | if (first2 == last2) 638| | erase(first1, last1); 639| | else 640| | insert(last1, first2, last2); 641| | } 642| | 643| | 644| | // Resize members... 645| | void resize(size_type newsize, NodeTy val) { 646| | iterator i = this->begin(); 647| | size_type len = 0; 648| | for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; 649| | 650| | if (len == newsize) 651| | erase(i, this->end()); 652| | else // i == end() 653| | insert(this->end(), newsize - len, val); 654| | } 655| | void resize(size_type newsize) { resize(newsize, NodeTy()); } 656| |}; 657| | 658| |} // End llvm namespace 659| | 660| |namespace std { 661| | // Ensure that swap uses the fast list swap... 662| | template 663| | void swap(llvm::iplist &Left, llvm::iplist &Right) { 664| | Left.swap(Right); 665| | } 666| |} // End 'std' extensions... 667| | 668| |#endif // LLVM_ADT_ILIST_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/ADT/ilist_node.h: 1| |//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the ilist_node class template, which is a convenient 11| |// base class for creating classes that can be used with ilists. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_ADT_ILIST_NODE_H 16| |#define LLVM_ADT_ILIST_NODE_H 17| | 18| |namespace llvm { 19| | 20| |template 21| |struct ilist_traits; 22| | 23| |/// ilist_half_node - Base class that provides prev services for sentinels. 24| |/// 25| |template 26| |class ilist_half_node { 27| | friend struct ilist_traits; 28| | NodeTy *Prev; 29| |protected: 30| 0| NodeTy *getPrev() { return Prev; } 31| | const NodeTy *getPrev() const { return Prev; } 32| 0| void setPrev(NodeTy *P) { Prev = P; } 33| 0| ilist_half_node() : Prev(nullptr) {} 34| |}; 35| | 36| |template 37| |struct ilist_nextprev_traits; 38| | 39| |/// ilist_node - Base class that provides next/prev services for nodes 40| |/// that use ilist_nextprev_traits or ilist_default_traits. 41| |/// 42| |template 43| |class ilist_node : private ilist_half_node { 44| | friend struct ilist_nextprev_traits; 45| | friend struct ilist_traits; 46| | NodeTy *Next; 47| 0| NodeTy *getNext() { return Next; } 48| | const NodeTy *getNext() const { return Next; } 49| 0| void setNext(NodeTy *N) { Next = N; } 50| |protected: 51| 0| ilist_node() : Next(nullptr) {} 52| | 53| |public: 54| | /// @name Adjacent Node Accessors 55| | /// @{ 56| | 57| | /// \brief Get the previous node, or 0 for the list head. 58| | NodeTy *getPrevNode() { 59| | NodeTy *Prev = this->getPrev(); 60| | 61| | // Check for sentinel. 62| | if (!Prev->getNext()) 63| | return nullptr; 64| | 65| | return Prev; 66| | } 67| | 68| | /// \brief Get the previous node, or 0 for the list head. 69| | const NodeTy *getPrevNode() const { 70| | const NodeTy *Prev = this->getPrev(); 71| | 72| | // Check for sentinel. 73| | if (!Prev->getNext()) 74| | return nullptr; 75| | 76| | return Prev; 77| | } 78| | 79| | /// \brief Get the next node, or 0 for the list tail. 80| | NodeTy *getNextNode() { 81| | NodeTy *Next = getNext(); 82| | 83| | // Check for sentinel. 84| | if (!Next->getNext()) 85| | return nullptr; 86| | 87| | return Next; 88| | } 89| | 90| | /// \brief Get the next node, or 0 for the list tail. 91| | const NodeTy *getNextNode() const { 92| | const NodeTy *Next = getNext(); 93| | 94| | // Check for sentinel. 95| | if (!Next->getNext()) 96| | return nullptr; 97| | 98| | return Next; 99| | } 100| | 101| | /// @} 102| |}; 103| | 104| |} // End llvm namespace 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Allocator.h: 1| |//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// \file 10| |/// 11| |/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both 12| |/// of these conform to an LLVM "Allocator" concept which consists of an 13| |/// Allocate method accepting a size and alignment, and a Deallocate accepting 14| |/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of 15| |/// Allocate and Deallocate for setting size and alignment based on the final 16| |/// type. These overloads are typically provided by a base class template \c 17| |/// AllocatorBase. 18| |/// 19| |//===----------------------------------------------------------------------===// 20| | 21| |#ifndef LLVM_SUPPORT_ALLOCATOR_H 22| |#define LLVM_SUPPORT_ALLOCATOR_H 23| | 24| |#include "llvm/ADT/SmallVector.h" 25| |#include "llvm/Support/AlignOf.h" 26| |#include "llvm/Support/DataTypes.h" 27| |#include "llvm/Support/MathExtras.h" 28| |#include "llvm/Support/Memory.h" 29| |#include 30| |#include 31| |#include 32| |#include 33| | 34| |namespace llvm { 35| | 36| |/// \brief CRTP base class providing obvious overloads for the core \c 37| |/// Allocate() methods of LLVM-style allocators. 38| |/// 39| |/// This base class both documents the full public interface exposed by all 40| |/// LLVM-style allocators, and redirects all of the overloads to a single core 41| |/// set of methods which the derived class must define. 42| |template class AllocatorBase { 43| |public: 44| | /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method 45| | /// must be implemented by \c DerivedT. 46| 0| void *Allocate(size_t Size, size_t Alignment) { 47| 0|#ifdef __clang__ 48| 0| static_assert(static_cast( 49| 0| &AllocatorBase::Allocate) != 50| 0| static_cast( 51| 0| &DerivedT::Allocate), 52| 0| "Class derives from AllocatorBase without implementing the " 53| 0| "core Allocate(size_t, size_t) overload!"); 54| 0|#endif 55| 0| return static_cast(this)->Allocate(Size, Alignment); 56| 0| } 57| | 58| | /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this 59| | /// allocator. 60| | void Deallocate(const void *Ptr, size_t Size) { 61| |#ifdef __clang__ 62| | static_assert(static_cast( 63| | &AllocatorBase::Deallocate) != 64| | static_cast( 65| | &DerivedT::Deallocate), 66| | "Class derives from AllocatorBase without implementing the " 67| | "core Deallocate(void *) overload!"); 68| |#endif 69| | return static_cast(this)->Deallocate(Ptr, Size); 70| | } 71| | 72| | // The rest of these methods are helpers that redirect to one of the above 73| | // core methods. 74| | 75| | /// \brief Allocate space for a sequence of objects without constructing them. 76| 0| template T *Allocate(size_t Num = 1) { 77| 0| return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); 78| 0| } 79| | 80| | /// \brief Deallocate space for a sequence of objects without constructing them. 81| | template 82| | typename std::enable_if< 83| | !std::is_same::type, void>::value, void>::type 84| | Deallocate(T *Ptr, size_t Num = 1) { 85| | Deallocate(static_cast(Ptr), Num * sizeof(T)); 86| | } 87| |}; 88| | 89| |class MallocAllocator : public AllocatorBase { 90| |public: 91| 0| void Reset() {} 92| | 93| | LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, 94| 0| size_t /*Alignment*/) { 95| 0| return malloc(Size); 96| 0| } 97| | 98| | // Pull in base class overloads. 99| | using AllocatorBase::Allocate; 100| | 101| 0| void Deallocate(const void *Ptr, size_t /*Size*/) { 102| 0| free(const_cast(Ptr)); 103| 0| } 104| | 105| | // Pull in base class overloads. 106| | using AllocatorBase::Deallocate; 107| | 108| 0| void PrintStats() const {} 109| |}; 110| | 111| |namespace detail { 112| | 113| |// We call out to an external function to actually print the message as the 114| |// printing code uses Allocator.h in its implementation. 115| |void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, 116| | size_t TotalMemory); 117| |} // End namespace detail. 118| | 119| |/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. 120| |/// 121| |/// This isn't strictly a bump-pointer allocator as it uses backing slabs of 122| |/// memory rather than relying on a boundless contiguous heap. However, it has 123| |/// bump-pointer semantics in that it is a monotonically growing pool of memory 124| |/// where every allocation is found by merely allocating the next N bytes in 125| |/// the slab, or the next N bytes in the next slab. 126| |/// 127| |/// Note that this also has a threshold for forcing allocations above a certain 128| |/// size into their own slab. 129| |/// 130| |/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator 131| |/// object, which wraps malloc, to allocate memory, but it can be changed to 132| |/// use a custom allocator. 133| |template 135| |class BumpPtrAllocatorImpl 136| | : public AllocatorBase< 137| | BumpPtrAllocatorImpl> { 138| |public: 139| | static_assert(SizeThreshold <= SlabSize, 140| | "The SizeThreshold must be at most the SlabSize to ensure " 141| | "that objects larger than a slab go into their own memory " 142| | "allocation."); 143| | 144| | BumpPtrAllocatorImpl() 145| 0| : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} 146| | template 147| | BumpPtrAllocatorImpl(T &&Allocator) 148| | : CurPtr(nullptr), End(nullptr), BytesAllocated(0), 149| | Allocator(std::forward(Allocator)) {} 150| | 151| | // Manually implement a move constructor as we must clear the old allocators 152| | // slabs as a matter of correctness. 153| | BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) 154| | : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), 155| | CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), 156| | BytesAllocated(Old.BytesAllocated), 157| | Allocator(std::move(Old.Allocator)) { 158| | Old.CurPtr = Old.End = nullptr; 159| | Old.BytesAllocated = 0; 160| | Old.Slabs.clear(); 161| | Old.CustomSizedSlabs.clear(); 162| | } 163| | 164| 0| ~BumpPtrAllocatorImpl() { 165| 0| DeallocateSlabs(Slabs.begin(), Slabs.end()); 166| 0| DeallocateCustomSizedSlabs(); 167| 0| } 168| | 169| | BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { 170| | DeallocateSlabs(Slabs.begin(), Slabs.end()); 171| | DeallocateCustomSizedSlabs(); 172| | 173| | CurPtr = RHS.CurPtr; 174| | End = RHS.End; 175| | BytesAllocated = RHS.BytesAllocated; 176| | Slabs = std::move(RHS.Slabs); 177| | CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); 178| | Allocator = std::move(RHS.Allocator); 179| | 180| | RHS.CurPtr = RHS.End = nullptr; 181| | RHS.BytesAllocated = 0; 182| | RHS.Slabs.clear(); 183| | RHS.CustomSizedSlabs.clear(); 184| | return *this; 185| | } 186| | 187| | /// \brief Deallocate all but the current slab and reset the current pointer 188| | /// to the beginning of it, freeing all memory allocated so far. 189| 0| void Reset() { 190| 0| if (Slabs.empty()) 191| 0| return; 192| 0| 193| 0| // Reset the state. 194| 0| BytesAllocated = 0; 195| 0| CurPtr = (char *)Slabs.front(); 196| 0| End = CurPtr + SlabSize; 197| 0| 198| 0| // Deallocate all but the first slab, and all custome sized slabs. 199| 0| DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); 200| 0| Slabs.erase(std::next(Slabs.begin()), Slabs.end()); 201| 0| DeallocateCustomSizedSlabs(); 202| 0| CustomSizedSlabs.clear(); 203| 0| } 204| | 205| | /// \brief Allocate space at the specified alignment. 206| 0| LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { 207| 0| assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); 208| 0| 209| 0| // Keep track of how many bytes we've allocated. 210| 0| BytesAllocated += Size; 211| 0| 212| 0| size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); 213| 0| assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); 214| 0| 215| 0| // Check if we have enough space. 216| 0| if (Adjustment + Size <= size_t(End - CurPtr)) { 217| 0| char *AlignedPtr = CurPtr + Adjustment; 218| 0| CurPtr = AlignedPtr + Size; 219| 0| // Update the allocation point of this memory block in MemorySanitizer. 220| 0| // Without this, MemorySanitizer messages for values originated from here 221| 0| // will point to the allocation of the entire slab. 222| 0| __msan_allocated_memory(AlignedPtr, Size); 223| 0| return AlignedPtr; 224| 0| } 225| 0| 226| 0| // If Size is really big, allocate a separate slab for it. 227| 0| size_t PaddedSize = Size + Alignment - 1; 228| 0| if (PaddedSize > SizeThreshold) { 229| 0| void *NewSlab = Allocator.Allocate(PaddedSize, 0); 230| 0| CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); 231| 0| 232| 0| uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); 233| 0| assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); 234| 0| char *AlignedPtr = (char*)AlignedAddr; 235| 0| __msan_allocated_memory(AlignedPtr, Size); 236| 0| return AlignedPtr; 237| 0| } 238| 0| 239| 0| // Otherwise, start a new slab and try again. 240| 0| StartNewSlab(); 241| 0| uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); 242| 0| assert(AlignedAddr + Size <= (uintptr_t)End && 243| 0| "Unable to allocate memory!"); 244| 0| char *AlignedPtr = (char*)AlignedAddr; 245| 0| CurPtr = AlignedPtr + Size; 246| 0| __msan_allocated_memory(AlignedPtr, Size); 247| 0| return AlignedPtr; 248| 0| } 249| | 250| | // Pull in base class overloads. 251| | using AllocatorBase::Allocate; 252| | 253| 0| void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} 254| | 255| | // Pull in base class overloads. 256| | using AllocatorBase::Deallocate; 257| | 258| | size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } 259| | 260| | size_t getTotalMemory() const { 261| | size_t TotalMemory = 0; 262| | for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) 263| | TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); 264| | for (auto &PtrAndSize : CustomSizedSlabs) 265| | TotalMemory += PtrAndSize.second; 266| | return TotalMemory; 267| | } 268| | 269| | void PrintStats() const { 270| | detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, 271| | getTotalMemory()); 272| | } 273| | 274| |private: 275| | /// \brief The current pointer into the current slab. 276| | /// 277| | /// This points to the next free byte in the slab. 278| | char *CurPtr; 279| | 280| | /// \brief The end of the current slab. 281| | char *End; 282| | 283| | /// \brief The slabs allocated so far. 284| | SmallVector Slabs; 285| | 286| | /// \brief Custom-sized slabs allocated for too-large allocation requests. 287| | SmallVector, 0> CustomSizedSlabs; 288| | 289| | /// \brief How many bytes we've allocated. 290| | /// 291| | /// Used so that we can compute how much space was wasted. 292| | size_t BytesAllocated; 293| | 294| | /// \brief The allocator instance we use to get slabs of memory. 295| | AllocatorT Allocator; 296| | 297| 0| static size_t computeSlabSize(unsigned SlabIdx) { 298| 0| // Scale the actual allocated slab size based on the number of slabs 299| 0| // allocated. Every 128 slabs allocated, we double the allocated size to 300| 0| // reduce allocation frequency, but saturate at multiplying the slab size by 301| 0| // 2^30. 302| 0| return SlabSize * ((size_t)1 << std::min(30, SlabIdx / 128)); 303| 0| } 304| | 305| | /// \brief Allocate a new slab and move the bump pointers over into the new 306| | /// slab, modifying CurPtr and End. 307| 0| void StartNewSlab() { 308| 0| size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); 309| 0| 310| 0| void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); 311| 0| Slabs.push_back(NewSlab); 312| 0| CurPtr = (char *)(NewSlab); 313| 0| End = ((char *)NewSlab) + AllocatedSlabSize; 314| 0| } 315| | 316| | /// \brief Deallocate a sequence of slabs. 317| | void DeallocateSlabs(SmallVectorImpl::iterator I, 318| 0| SmallVectorImpl::iterator E) { 319| 0| for (; I != E; ++I) { 320| 0| size_t AllocatedSlabSize = 321| 0| computeSlabSize(std::distance(Slabs.begin(), I)); 322| 0|#ifndef NDEBUG 323| 0| // Poison the memory so stale pointers crash sooner. Note we must 324| 0| // preserve the Size and NextPtr fields at the beginning. 325| 0| if (AllocatedSlabSize != 0) { 326| 0| sys::Memory::setRangeWritable(*I, AllocatedSlabSize); 327| 0| memset(*I, 0xCD, AllocatedSlabSize); 328| 0| } 329| 0|#endif 330| 0| Allocator.Deallocate(*I, AllocatedSlabSize); 331| 0| } 332| 0| } 333| | 334| | /// \brief Deallocate all memory for custom sized slabs. 335| 0| void DeallocateCustomSizedSlabs() { 336| 0| for (auto &PtrAndSize : CustomSizedSlabs) { 337| 0| void *Ptr = PtrAndSize.first; 338| 0| size_t Size = PtrAndSize.second; 339| 0|#ifndef NDEBUG 340| 0| // Poison the memory so stale pointers crash sooner. Note we must 341| 0| // preserve the Size and NextPtr fields at the beginning. 342| 0| sys::Memory::setRangeWritable(Ptr, Size); 343| 0| memset(Ptr, 0xCD, Size); 344| 0|#endif 345| 0| Allocator.Deallocate(Ptr, Size); 346| 0| } 347| 0| } 348| | 349| | template friend class SpecificBumpPtrAllocator; 350| |}; 351| | 352| |/// \brief The standard BumpPtrAllocator which just uses the default template 353| |/// paramaters. 354| |typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; 355| | 356| |/// \brief A BumpPtrAllocator that allows only elements of a specific type to be 357| |/// allocated. 358| |/// 359| |/// This allows calling the destructor in DestroyAll() and when the allocator is 360| |/// destroyed. 361| |template class SpecificBumpPtrAllocator { 362| | BumpPtrAllocator Allocator; 363| | 364| |public: 365| | SpecificBumpPtrAllocator() : Allocator() {} 366| | SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) 367| | : Allocator(std::move(Old.Allocator)) {} 368| | ~SpecificBumpPtrAllocator() { DestroyAll(); } 369| | 370| | SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { 371| | Allocator = std::move(RHS.Allocator); 372| | return *this; 373| | } 374| | 375| | /// Call the destructor of each allocated object and deallocate all but the 376| | /// current slab and reset the current pointer to the beginning of it, freeing 377| | /// all memory allocated so far. 378| | void DestroyAll() { 379| | auto DestroyElements = [](char *Begin, char *End) { 380| | assert(Begin == (char*)alignAddr(Begin, alignOf())); 381| | for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) 382| | reinterpret_cast(Ptr)->~T(); 383| | }; 384| | 385| | for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; 386| | ++I) { 387| | size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( 388| | std::distance(Allocator.Slabs.begin(), I)); 389| | char *Begin = (char*)alignAddr(*I, alignOf()); 390| | char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr 391| | : (char *)*I + AllocatedSlabSize; 392| | 393| | DestroyElements(Begin, End); 394| | } 395| | 396| | for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { 397| | void *Ptr = PtrAndSize.first; 398| | size_t Size = PtrAndSize.second; 399| | DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); 400| | } 401| | 402| | Allocator.Reset(); 403| | } 404| | 405| | /// \brief Allocate space for an array of objects without constructing them. 406| | T *Allocate(size_t num = 1) { return Allocator.Allocate(num); } 407| |}; 408| | 409| |} // end namespace llvm 410| | 411| |template 412| |void *operator new(size_t Size, 413| | llvm::BumpPtrAllocatorImpl &Allocator) { 415| | struct S { 416| | char c; 417| | union { 418| | double D; 419| | long double LD; 420| | long long L; 421| | void *P; 422| | } x; 423| | }; 424| | return Allocator.Allocate( 425| | Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); 426| |} 427| | 428| |template 429| |void operator delete( 430| | void *, llvm::BumpPtrAllocatorImpl &) { 431| |} 432| | 433| |#endif // LLVM_SUPPORT_ALLOCATOR_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/CBindingWrapping.h: 1| |//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the wrapping macros for the C interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H 15| |#define LLVM_SUPPORT_CBINDINGWRAPPING_H 16| | 17| |#include "llvm/Support/Casting.h" 18| | 19| |#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 20| 0| inline ty *unwrap(ref P) { \ 21| 0| return reinterpret_cast(P); \ 22| 0| } \ 23| | \ 24| 0| inline ref wrap(const ty *P) { \ 25| 0| return reinterpret_cast(const_cast(P)); \ 26| 0| } 27| | 28| |#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ 29| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 30| | \ 31| | template \ 32| | inline T *unwrap(ref P) { \ 33| | return cast(unwrap(P)); \ 34| | } 35| | 36| |#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ 37| | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ 38| | \ 39| | template \ 40| | inline T *unwrap(ref P) { \ 41| | T *Q = (T*)unwrap(P); \ 42| | assert(Q && "Invalid cast!"); \ 43| | return Q; \ 44| | } 45| | 46| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/COFF.h: 1| |//===-- llvm/Support/COFF.h -------------------------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains an definitions used in Windows COFF Files. 11| |// 12| |// Structures and enums defined within this file where created using 13| |// information from Microsoft's publicly available PE/COFF format document: 14| |// 15| |// Microsoft Portable Executable and Common Object File Format Specification 16| |// Revision 8.1 - February 15, 2008 17| |// 18| |// As of 5/2/2010, hosted by Microsoft at: 19| |// http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx 20| |// 21| |//===----------------------------------------------------------------------===// 22| | 23| |#ifndef LLVM_SUPPORT_COFF_H 24| |#define LLVM_SUPPORT_COFF_H 25| | 26| |#include "llvm/Support/DataTypes.h" 27| |#include 28| |#include 29| | 30| |// Undefine the DEBUG macro which is added by SwiftPM to avoid 31| |// conflict with another "DEBUG" symbol in this file. 32| |#ifdef SWIFT_PACKAGE 33| |#undef DEBUG 34| |#endif 35| | 36| |namespace llvm { 37| |namespace COFF { 38| | 39| | // The maximum number of sections that a COFF object can have (inclusive). 40| | const int32_t MaxNumberOfSections16 = 65279; 41| | 42| | // The PE signature bytes that follows the DOS stub header. 43| | static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; 44| | 45| | static const char BigObjMagic[] = { 46| | '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b', 47| | '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8', 48| | }; 49| | 50| | // Sizes in bytes of various things in the COFF format. 51| | enum { 52| | Header16Size = 20, 53| | Header32Size = 56, 54| | NameSize = 8, 55| | Symbol16Size = 18, 56| | Symbol32Size = 20, 57| | SectionSize = 40, 58| | RelocationSize = 10 59| | }; 60| | 61| | struct header { 62| | uint16_t Machine; 63| | int32_t NumberOfSections; 64| | uint32_t TimeDateStamp; 65| | uint32_t PointerToSymbolTable; 66| | uint32_t NumberOfSymbols; 67| | uint16_t SizeOfOptionalHeader; 68| | uint16_t Characteristics; 69| | }; 70| | 71| | struct BigObjHeader { 72| | enum : uint16_t { MinBigObjectVersion = 2 }; 73| | 74| | uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). 75| | uint16_t Sig2; ///< Must be 0xFFFF. 76| | uint16_t Version; 77| | uint16_t Machine; 78| | uint32_t TimeDateStamp; 79| | uint8_t UUID[16]; 80| | uint32_t unused1; 81| | uint32_t unused2; 82| | uint32_t unused3; 83| | uint32_t unused4; 84| | uint32_t NumberOfSections; 85| | uint32_t PointerToSymbolTable; 86| | uint32_t NumberOfSymbols; 87| | }; 88| | 89| | enum MachineTypes { 90| | MT_Invalid = 0xffff, 91| | 92| | IMAGE_FILE_MACHINE_UNKNOWN = 0x0, 93| | IMAGE_FILE_MACHINE_AM33 = 0x13, 94| | IMAGE_FILE_MACHINE_AMD64 = 0x8664, 95| | IMAGE_FILE_MACHINE_ARM = 0x1C0, 96| | IMAGE_FILE_MACHINE_ARMNT = 0x1C4, 97| | IMAGE_FILE_MACHINE_EBC = 0xEBC, 98| | IMAGE_FILE_MACHINE_I386 = 0x14C, 99| | IMAGE_FILE_MACHINE_IA64 = 0x200, 100| | IMAGE_FILE_MACHINE_M32R = 0x9041, 101| | IMAGE_FILE_MACHINE_MIPS16 = 0x266, 102| | IMAGE_FILE_MACHINE_MIPSFPU = 0x366, 103| | IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466, 104| | IMAGE_FILE_MACHINE_POWERPC = 0x1F0, 105| | IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1, 106| | IMAGE_FILE_MACHINE_R4000 = 0x166, 107| | IMAGE_FILE_MACHINE_SH3 = 0x1A2, 108| | IMAGE_FILE_MACHINE_SH3DSP = 0x1A3, 109| | IMAGE_FILE_MACHINE_SH4 = 0x1A6, 110| | IMAGE_FILE_MACHINE_SH5 = 0x1A8, 111| | IMAGE_FILE_MACHINE_THUMB = 0x1C2, 112| | IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 113| | }; 114| | 115| | enum Characteristics { 116| | C_Invalid = 0, 117| | 118| | /// The file does not contain base relocations and must be loaded at its 119| | /// preferred base. If this cannot be done, the loader will error. 120| | IMAGE_FILE_RELOCS_STRIPPED = 0x0001, 121| | /// The file is valid and can be run. 122| | IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002, 123| | /// COFF line numbers have been stripped. This is deprecated and should be 124| | /// 0. 125| | IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004, 126| | /// COFF symbol table entries for local symbols have been removed. This is 127| | /// deprecated and should be 0. 128| | IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008, 129| | /// Aggressively trim working set. This is deprecated and must be 0. 130| | IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010, 131| | /// Image can handle > 2GiB addresses. 132| | IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020, 133| | /// Little endian: the LSB precedes the MSB in memory. This is deprecated 134| | /// and should be 0. 135| | IMAGE_FILE_BYTES_REVERSED_LO = 0x0080, 136| | /// Machine is based on a 32bit word architecture. 137| | IMAGE_FILE_32BIT_MACHINE = 0x0100, 138| | /// Debugging info has been removed. 139| | IMAGE_FILE_DEBUG_STRIPPED = 0x0200, 140| | /// If the image is on removable media, fully load it and copy it to swap. 141| | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400, 142| | /// If the image is on network media, fully load it and copy it to swap. 143| | IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800, 144| | /// The image file is a system file, not a user program. 145| | IMAGE_FILE_SYSTEM = 0x1000, 146| | /// The image file is a DLL. 147| | IMAGE_FILE_DLL = 0x2000, 148| | /// This file should only be run on a uniprocessor machine. 149| | IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000, 150| | /// Big endian: the MSB precedes the LSB in memory. This is deprecated 151| | /// and should be 0. 152| | IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 153| | }; 154| | 155| | struct symbol { 156| | char Name[NameSize]; 157| | uint32_t Value; 158| | int32_t SectionNumber; 159| | uint16_t Type; 160| | uint8_t StorageClass; 161| | uint8_t NumberOfAuxSymbols; 162| | }; 163| | 164| | enum SymbolFlags { 165| | SF_TypeMask = 0x0000FFFF, 166| | SF_TypeShift = 0, 167| | 168| | SF_ClassMask = 0x00FF0000, 169| | SF_ClassShift = 16, 170| | 171| | SF_WeakExternal = 0x01000000 172| | }; 173| | 174| | enum SymbolSectionNumber : int32_t { 175| | IMAGE_SYM_DEBUG = -2, 176| | IMAGE_SYM_ABSOLUTE = -1, 177| | IMAGE_SYM_UNDEFINED = 0 178| | }; 179| | 180| | /// Storage class tells where and what the symbol represents 181| | enum SymbolStorageClass { 182| | SSC_Invalid = 0xff, 183| | 184| | IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function 185| | IMAGE_SYM_CLASS_NULL = 0, ///< No symbol 186| | IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable 187| | IMAGE_SYM_CLASS_EXTERNAL = 2, ///< External symbol 188| | IMAGE_SYM_CLASS_STATIC = 3, ///< Static 189| | IMAGE_SYM_CLASS_REGISTER = 4, ///< Register variable 190| | IMAGE_SYM_CLASS_EXTERNAL_DEF = 5, ///< External definition 191| | IMAGE_SYM_CLASS_LABEL = 6, ///< Label 192| | IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7, ///< Undefined label 193| | IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8, ///< Member of structure 194| | IMAGE_SYM_CLASS_ARGUMENT = 9, ///< Function argument 195| | IMAGE_SYM_CLASS_STRUCT_TAG = 10, ///< Structure tag 196| | IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11, ///< Member of union 197| | IMAGE_SYM_CLASS_UNION_TAG = 12, ///< Union tag 198| | IMAGE_SYM_CLASS_TYPE_DEFINITION = 13, ///< Type definition 199| | IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14, ///< Undefined static 200| | IMAGE_SYM_CLASS_ENUM_TAG = 15, ///< Enumeration tag 201| | IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16, ///< Member of enumeration 202| | IMAGE_SYM_CLASS_REGISTER_PARAM = 17, ///< Register parameter 203| | IMAGE_SYM_CLASS_BIT_FIELD = 18, ///< Bit field 204| | /// ".bb" or ".eb" - beginning or end of block 205| | IMAGE_SYM_CLASS_BLOCK = 100, 206| | /// ".bf" or ".ef" - beginning or end of function 207| | IMAGE_SYM_CLASS_FUNCTION = 101, 208| | IMAGE_SYM_CLASS_END_OF_STRUCT = 102, ///< End of structure 209| | IMAGE_SYM_CLASS_FILE = 103, ///< File name 210| | /// Line number, reformatted as symbol 211| | IMAGE_SYM_CLASS_SECTION = 104, 212| | IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105, ///< Duplicate tag 213| | /// External symbol in dmert public lib 214| | IMAGE_SYM_CLASS_CLR_TOKEN = 107 215| | }; 216| | 217| | enum SymbolBaseType { 218| | IMAGE_SYM_TYPE_NULL = 0, ///< No type information or unknown base type. 219| | IMAGE_SYM_TYPE_VOID = 1, ///< Used with void pointers and functions. 220| | IMAGE_SYM_TYPE_CHAR = 2, ///< A character (signed byte). 221| | IMAGE_SYM_TYPE_SHORT = 3, ///< A 2-byte signed integer. 222| | IMAGE_SYM_TYPE_INT = 4, ///< A natural integer type on the target. 223| | IMAGE_SYM_TYPE_LONG = 5, ///< A 4-byte signed integer. 224| | IMAGE_SYM_TYPE_FLOAT = 6, ///< A 4-byte floating-point number. 225| | IMAGE_SYM_TYPE_DOUBLE = 7, ///< An 8-byte floating-point number. 226| | IMAGE_SYM_TYPE_STRUCT = 8, ///< A structure. 227| | IMAGE_SYM_TYPE_UNION = 9, ///< An union. 228| | IMAGE_SYM_TYPE_ENUM = 10, ///< An enumerated type. 229| | IMAGE_SYM_TYPE_MOE = 11, ///< A member of enumeration (a specific value). 230| | IMAGE_SYM_TYPE_BYTE = 12, ///< A byte; unsigned 1-byte integer. 231| | IMAGE_SYM_TYPE_WORD = 13, ///< A word; unsigned 2-byte integer. 232| | IMAGE_SYM_TYPE_UINT = 14, ///< An unsigned integer of natural size. 233| | IMAGE_SYM_TYPE_DWORD = 15 ///< An unsigned 4-byte integer. 234| | }; 235| | 236| | enum SymbolComplexType { 237| | IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. 238| | IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type. 239| | IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type. 240| | IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type. 241| | 242| | /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT)) 243| | SCT_COMPLEX_TYPE_SHIFT = 4 244| | }; 245| | 246| | enum AuxSymbolType { 247| | IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1 248| | }; 249| | 250| | struct section { 251| | char Name[NameSize]; 252| | uint32_t VirtualSize; 253| | uint32_t VirtualAddress; 254| | uint32_t SizeOfRawData; 255| | uint32_t PointerToRawData; 256| | uint32_t PointerToRelocations; 257| | uint32_t PointerToLineNumbers; 258| | uint16_t NumberOfRelocations; 259| | uint16_t NumberOfLineNumbers; 260| | uint32_t Characteristics; 261| | }; 262| | 263| | enum SectionCharacteristics : uint32_t { 264| | SC_Invalid = 0xffffffff, 265| | 266| | IMAGE_SCN_TYPE_NO_PAD = 0x00000008, 267| | IMAGE_SCN_CNT_CODE = 0x00000020, 268| | IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, 269| | IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, 270| | IMAGE_SCN_LNK_OTHER = 0x00000100, 271| | IMAGE_SCN_LNK_INFO = 0x00000200, 272| | IMAGE_SCN_LNK_REMOVE = 0x00000800, 273| | IMAGE_SCN_LNK_COMDAT = 0x00001000, 274| | IMAGE_SCN_GPREL = 0x00008000, 275| | IMAGE_SCN_MEM_PURGEABLE = 0x00020000, 276| | IMAGE_SCN_MEM_16BIT = 0x00020000, 277| | IMAGE_SCN_MEM_LOCKED = 0x00040000, 278| | IMAGE_SCN_MEM_PRELOAD = 0x00080000, 279| | IMAGE_SCN_ALIGN_1BYTES = 0x00100000, 280| | IMAGE_SCN_ALIGN_2BYTES = 0x00200000, 281| | IMAGE_SCN_ALIGN_4BYTES = 0x00300000, 282| | IMAGE_SCN_ALIGN_8BYTES = 0x00400000, 283| | IMAGE_SCN_ALIGN_16BYTES = 0x00500000, 284| | IMAGE_SCN_ALIGN_32BYTES = 0x00600000, 285| | IMAGE_SCN_ALIGN_64BYTES = 0x00700000, 286| | IMAGE_SCN_ALIGN_128BYTES = 0x00800000, 287| | IMAGE_SCN_ALIGN_256BYTES = 0x00900000, 288| | IMAGE_SCN_ALIGN_512BYTES = 0x00A00000, 289| | IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000, 290| | IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, 291| | IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, 292| | IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, 293| | IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, 294| | IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, 295| | IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, 296| | IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, 297| | IMAGE_SCN_MEM_SHARED = 0x10000000, 298| | IMAGE_SCN_MEM_EXECUTE = 0x20000000, 299| | IMAGE_SCN_MEM_READ = 0x40000000, 300| | IMAGE_SCN_MEM_WRITE = 0x80000000 301| | }; 302| | 303| | struct relocation { 304| | uint32_t VirtualAddress; 305| | uint32_t SymbolTableIndex; 306| | uint16_t Type; 307| | }; 308| | 309| | enum RelocationTypeI386 { 310| | IMAGE_REL_I386_ABSOLUTE = 0x0000, 311| | IMAGE_REL_I386_DIR16 = 0x0001, 312| | IMAGE_REL_I386_REL16 = 0x0002, 313| | IMAGE_REL_I386_DIR32 = 0x0006, 314| | IMAGE_REL_I386_DIR32NB = 0x0007, 315| | IMAGE_REL_I386_SEG12 = 0x0009, 316| | IMAGE_REL_I386_SECTION = 0x000A, 317| | IMAGE_REL_I386_SECREL = 0x000B, 318| | IMAGE_REL_I386_TOKEN = 0x000C, 319| | IMAGE_REL_I386_SECREL7 = 0x000D, 320| | IMAGE_REL_I386_REL32 = 0x0014 321| | }; 322| | 323| | enum RelocationTypeAMD64 { 324| | IMAGE_REL_AMD64_ABSOLUTE = 0x0000, 325| | IMAGE_REL_AMD64_ADDR64 = 0x0001, 326| | IMAGE_REL_AMD64_ADDR32 = 0x0002, 327| | IMAGE_REL_AMD64_ADDR32NB = 0x0003, 328| | IMAGE_REL_AMD64_REL32 = 0x0004, 329| | IMAGE_REL_AMD64_REL32_1 = 0x0005, 330| | IMAGE_REL_AMD64_REL32_2 = 0x0006, 331| | IMAGE_REL_AMD64_REL32_3 = 0x0007, 332| | IMAGE_REL_AMD64_REL32_4 = 0x0008, 333| | IMAGE_REL_AMD64_REL32_5 = 0x0009, 334| | IMAGE_REL_AMD64_SECTION = 0x000A, 335| | IMAGE_REL_AMD64_SECREL = 0x000B, 336| | IMAGE_REL_AMD64_SECREL7 = 0x000C, 337| | IMAGE_REL_AMD64_TOKEN = 0x000D, 338| | IMAGE_REL_AMD64_SREL32 = 0x000E, 339| | IMAGE_REL_AMD64_PAIR = 0x000F, 340| | IMAGE_REL_AMD64_SSPAN32 = 0x0010 341| | }; 342| | 343| | enum RelocationTypesARM { 344| | IMAGE_REL_ARM_ABSOLUTE = 0x0000, 345| | IMAGE_REL_ARM_ADDR32 = 0x0001, 346| | IMAGE_REL_ARM_ADDR32NB = 0x0002, 347| | IMAGE_REL_ARM_BRANCH24 = 0x0003, 348| | IMAGE_REL_ARM_BRANCH11 = 0x0004, 349| | IMAGE_REL_ARM_TOKEN = 0x0005, 350| | IMAGE_REL_ARM_BLX24 = 0x0008, 351| | IMAGE_REL_ARM_BLX11 = 0x0009, 352| | IMAGE_REL_ARM_SECTION = 0x000E, 353| | IMAGE_REL_ARM_SECREL = 0x000F, 354| | IMAGE_REL_ARM_MOV32A = 0x0010, 355| | IMAGE_REL_ARM_MOV32T = 0x0011, 356| | IMAGE_REL_ARM_BRANCH20T = 0x0012, 357| | IMAGE_REL_ARM_BRANCH24T = 0x0014, 358| | IMAGE_REL_ARM_BLX23T = 0x0015 359| | }; 360| | 361| | enum COMDATType { 362| | IMAGE_COMDAT_SELECT_NODUPLICATES = 1, 363| | IMAGE_COMDAT_SELECT_ANY, 364| | IMAGE_COMDAT_SELECT_SAME_SIZE, 365| | IMAGE_COMDAT_SELECT_EXACT_MATCH, 366| | IMAGE_COMDAT_SELECT_ASSOCIATIVE, 367| | IMAGE_COMDAT_SELECT_LARGEST, 368| | IMAGE_COMDAT_SELECT_NEWEST 369| | }; 370| | 371| | // Auxiliary Symbol Formats 372| | struct AuxiliaryFunctionDefinition { 373| | uint32_t TagIndex; 374| | uint32_t TotalSize; 375| | uint32_t PointerToLinenumber; 376| | uint32_t PointerToNextFunction; 377| | char unused[2]; 378| | }; 379| | 380| | struct AuxiliarybfAndefSymbol { 381| | uint8_t unused1[4]; 382| | uint16_t Linenumber; 383| | uint8_t unused2[6]; 384| | uint32_t PointerToNextFunction; 385| | uint8_t unused3[2]; 386| | }; 387| | 388| | struct AuxiliaryWeakExternal { 389| | uint32_t TagIndex; 390| | uint32_t Characteristics; 391| | uint8_t unused[10]; 392| | }; 393| | 394| | /// These are not documented in the spec, but are located in WinNT.h. 395| | enum WeakExternalCharacteristics { 396| | IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1, 397| | IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2, 398| | IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 399| | }; 400| | 401| | struct AuxiliarySectionDefinition { 402| | uint32_t Length; 403| | uint16_t NumberOfRelocations; 404| | uint16_t NumberOfLinenumbers; 405| | uint32_t CheckSum; 406| | uint32_t Number; 407| | uint8_t Selection; 408| | char unused; 409| | }; 410| | 411| | struct AuxiliaryCLRToken { 412| | uint8_t AuxType; 413| | uint8_t unused1; 414| | uint32_t SymbolTableIndex; 415| | char unused2[12]; 416| | }; 417| | 418| | union Auxiliary { 419| | AuxiliaryFunctionDefinition FunctionDefinition; 420| | AuxiliarybfAndefSymbol bfAndefSymbol; 421| | AuxiliaryWeakExternal WeakExternal; 422| | AuxiliarySectionDefinition SectionDefinition; 423| | }; 424| | 425| | /// @brief The Import Directory Table. 426| | /// 427| | /// There is a single array of these and one entry per imported DLL. 428| | struct ImportDirectoryTableEntry { 429| | uint32_t ImportLookupTableRVA; 430| | uint32_t TimeDateStamp; 431| | uint32_t ForwarderChain; 432| | uint32_t NameRVA; 433| | uint32_t ImportAddressTableRVA; 434| | }; 435| | 436| | /// @brief The PE32 Import Lookup Table. 437| | /// 438| | /// There is an array of these for each imported DLL. It represents either 439| | /// the ordinal to import from the target DLL, or a name to lookup and import 440| | /// from the target DLL. 441| | /// 442| | /// This also happens to be the same format used by the Import Address Table 443| | /// when it is initially written out to the image. 444| | struct ImportLookupTableEntry32 { 445| | uint32_t data; 446| | 447| | /// @brief Is this entry specified by ordinal, or name? 448| 0| bool isOrdinal() const { return data & 0x80000000; } 449| | 450| | /// @brief Get the ordinal value of this entry. isOrdinal must be true. 451| 0| uint16_t getOrdinal() const { 452| 0| assert(isOrdinal() && "ILT entry is not an ordinal!"); 453| 0| return data & 0xFFFF; 454| 0| } 455| | 456| | /// @brief Set the ordinal value and set isOrdinal to true. 457| 0| void setOrdinal(uint16_t o) { 458| 0| data = o; 459| 0| data |= 0x80000000; 460| 0| } 461| | 462| | /// @brief Get the Hint/Name entry RVA. isOrdinal must be false. 463| 0| uint32_t getHintNameRVA() const { 464| 0| assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 465| 0| return data; 466| 0| } 467| | 468| | /// @brief Set the Hint/Name entry RVA and set isOrdinal to false. 469| 0| void setHintNameRVA(uint32_t rva) { data = rva; } 470| | }; 471| | 472| | /// @brief The DOS compatible header at the front of all PEs. 473| | struct DOSHeader { 474| | uint16_t Magic; 475| | uint16_t UsedBytesInTheLastPage; 476| | uint16_t FileSizeInPages; 477| | uint16_t NumberOfRelocationItems; 478| | uint16_t HeaderSizeInParagraphs; 479| | uint16_t MinimumExtraParagraphs; 480| | uint16_t MaximumExtraParagraphs; 481| | uint16_t InitialRelativeSS; 482| | uint16_t InitialSP; 483| | uint16_t Checksum; 484| | uint16_t InitialIP; 485| | uint16_t InitialRelativeCS; 486| | uint16_t AddressOfRelocationTable; 487| | uint16_t OverlayNumber; 488| | uint16_t Reserved[4]; 489| | uint16_t OEMid; 490| | uint16_t OEMinfo; 491| | uint16_t Reserved2[10]; 492| | uint32_t AddressOfNewExeHeader; 493| | }; 494| | 495| | struct PE32Header { 496| | enum { 497| | PE32 = 0x10b, 498| | PE32_PLUS = 0x20b 499| | }; 500| | 501| | uint16_t Magic; 502| | uint8_t MajorLinkerVersion; 503| | uint8_t MinorLinkerVersion; 504| | uint32_t SizeOfCode; 505| | uint32_t SizeOfInitializedData; 506| | uint32_t SizeOfUninitializedData; 507| | uint32_t AddressOfEntryPoint; // RVA 508| | uint32_t BaseOfCode; // RVA 509| | uint32_t BaseOfData; // RVA 510| | uint32_t ImageBase; 511| | uint32_t SectionAlignment; 512| | uint32_t FileAlignment; 513| | uint16_t MajorOperatingSystemVersion; 514| | uint16_t MinorOperatingSystemVersion; 515| | uint16_t MajorImageVersion; 516| | uint16_t MinorImageVersion; 517| | uint16_t MajorSubsystemVersion; 518| | uint16_t MinorSubsystemVersion; 519| | uint32_t Win32VersionValue; 520| | uint32_t SizeOfImage; 521| | uint32_t SizeOfHeaders; 522| | uint32_t CheckSum; 523| | uint16_t Subsystem; 524| | // FIXME: This should be DllCharacteristics to match the COFF spec. 525| | uint16_t DLLCharacteristics; 526| | uint32_t SizeOfStackReserve; 527| | uint32_t SizeOfStackCommit; 528| | uint32_t SizeOfHeapReserve; 529| | uint32_t SizeOfHeapCommit; 530| | uint32_t LoaderFlags; 531| | // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec. 532| | uint32_t NumberOfRvaAndSize; 533| | }; 534| | 535| | struct DataDirectory { 536| | uint32_t RelativeVirtualAddress; 537| | uint32_t Size; 538| | }; 539| | 540| | enum DataDirectoryIndex { 541| | EXPORT_TABLE = 0, 542| | IMPORT_TABLE, 543| | RESOURCE_TABLE, 544| | EXCEPTION_TABLE, 545| | CERTIFICATE_TABLE, 546| | BASE_RELOCATION_TABLE, 547| | DEBUG, 548| | ARCHITECTURE, 549| | GLOBAL_PTR, 550| | TLS_TABLE, 551| | LOAD_CONFIG_TABLE, 552| | BOUND_IMPORT, 553| | IAT, 554| | DELAY_IMPORT_DESCRIPTOR, 555| | CLR_RUNTIME_HEADER, 556| | 557| | NUM_DATA_DIRECTORIES 558| | }; 559| | 560| | enum WindowsSubsystem { 561| | IMAGE_SUBSYSTEM_UNKNOWN = 0, ///< An unknown subsystem. 562| | IMAGE_SUBSYSTEM_NATIVE = 1, ///< Device drivers and native Windows processes 563| | IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, ///< The Windows GUI subsystem. 564| | IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, ///< The Windows character subsystem. 565| | IMAGE_SUBSYSTEM_OS2_CUI = 5, ///< The OS/2 character subsytem. 566| | IMAGE_SUBSYSTEM_POSIX_CUI = 7, ///< The POSIX character subsystem. 567| | IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, ///< Native Windows 9x driver. 568| | IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, ///< Windows CE. 569| | IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, ///< An EFI application. 570| | IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, ///< An EFI driver with boot 571| | /// services. 572| | IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, ///< An EFI driver with run-time 573| | /// services. 574| | IMAGE_SUBSYSTEM_EFI_ROM = 13, ///< An EFI ROM image. 575| | IMAGE_SUBSYSTEM_XBOX = 14, ///< XBOX. 576| | IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 ///< A BCD application. 577| | }; 578| | 579| | enum DLLCharacteristics { 580| | /// ASLR with 64 bit address space. 581| | IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, 582| | /// DLL can be relocated at load time. 583| | IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, 584| | /// Code integrity checks are enforced. 585| | IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, 586| | ///< Image is NX compatible. 587| | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, 588| | /// Isolation aware, but do not isolate the image. 589| | IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, 590| | /// Does not use structured exception handling (SEH). No SEH handler may be 591| | /// called in this image. 592| | IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, 593| | /// Do not bind the image. 594| | IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, 595| | ///< Image should execute in an AppContainer. 596| | IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, 597| | ///< A WDM driver. 598| | IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, 599| | ///< Image supports Control Flow Guard. 600| | IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, 601| | /// Terminal Server aware. 602| | IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 603| | }; 604| | 605| | enum DebugType { 606| | IMAGE_DEBUG_TYPE_UNKNOWN = 0, 607| | IMAGE_DEBUG_TYPE_COFF = 1, 608| | IMAGE_DEBUG_TYPE_CODEVIEW = 2, 609| | IMAGE_DEBUG_TYPE_FPO = 3, 610| | IMAGE_DEBUG_TYPE_MISC = 4, 611| | IMAGE_DEBUG_TYPE_EXCEPTION = 5, 612| | IMAGE_DEBUG_TYPE_FIXUP = 6, 613| | IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7, 614| | IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8, 615| | IMAGE_DEBUG_TYPE_BORLAND = 9, 616| | IMAGE_DEBUG_TYPE_CLSID = 11 617| | }; 618| | 619| | enum BaseRelocationType { 620| | IMAGE_REL_BASED_ABSOLUTE = 0, 621| | IMAGE_REL_BASED_HIGH = 1, 622| | IMAGE_REL_BASED_LOW = 2, 623| | IMAGE_REL_BASED_HIGHLOW = 3, 624| | IMAGE_REL_BASED_HIGHADJ = 4, 625| | IMAGE_REL_BASED_MIPS_JMPADDR = 5, 626| | IMAGE_REL_BASED_ARM_MOV32A = 5, 627| | IMAGE_REL_BASED_ARM_MOV32T = 7, 628| | IMAGE_REL_BASED_MIPS_JMPADDR16 = 9, 629| | IMAGE_REL_BASED_DIR64 = 10 630| | }; 631| | 632| | enum ImportType { 633| | IMPORT_CODE = 0, 634| | IMPORT_DATA = 1, 635| | IMPORT_CONST = 2 636| | }; 637| | 638| | enum ImportNameType { 639| | /// Import is by ordinal. This indicates that the value in the Ordinal/Hint 640| | /// field of the import header is the import's ordinal. If this constant is 641| | /// not specified, then the Ordinal/Hint field should always be interpreted 642| | /// as the import's hint. 643| | IMPORT_ORDINAL = 0, 644| | /// The import name is identical to the public symbol name 645| | IMPORT_NAME = 1, 646| | /// The import name is the public symbol name, but skipping the leading ?, 647| | /// @, or optionally _. 648| | IMPORT_NAME_NOPREFIX = 2, 649| | /// The import name is the public symbol name, but skipping the leading ?, 650| | /// @, or optionally _, and truncating at the first @. 651| | IMPORT_NAME_UNDECORATE = 3 652| | }; 653| | 654| | struct ImportHeader { 655| | uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). 656| | uint16_t Sig2; ///< Must be 0xFFFF. 657| | uint16_t Version; 658| | uint16_t Machine; 659| | uint32_t TimeDateStamp; 660| | uint32_t SizeOfData; 661| | uint16_t OrdinalHint; 662| | uint16_t TypeInfo; 663| | 664| 0| ImportType getType() const { 665| 0| return static_cast(TypeInfo & 0x3); 666| 0| } 667| | 668| 0| ImportNameType getNameType() const { 669| 0| return static_cast((TypeInfo & 0x1C) >> 3); 670| 0| } 671| | }; 672| | 673| | enum CodeViewIdentifiers { 674| | DEBUG_SECTION_MAGIC = 0x4, 675| | DEBUG_SYMBOL_SUBSECTION = 0xF1, 676| | DEBUG_LINE_TABLE_SUBSECTION = 0xF2, 677| | DEBUG_STRING_TABLE_SUBSECTION = 0xF3, 678| | DEBUG_INDEX_SUBSECTION = 0xF4, 679| | 680| | // Symbol subsections are split into records of different types. 681| | DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, 682| | DEBUG_SYMBOL_TYPE_PROC_END = 0x114F 683| | }; 684| | 685| 0| inline bool isReservedSectionNumber(int32_t SectionNumber) { 686| 0| return SectionNumber <= 0; 687| 0| } 688| | 689| |} // End namespace COFF. 690| |} // End namespace llvm. 691| | 692| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Compiler.h: 1| |//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines several macros, based on the current compiler. This allows 11| |// use of compiler-specific features in a way that remains portable. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_COMPILER_H 16| |#define LLVM_SUPPORT_COMPILER_H 17| | 18| |#include "llvm/Config/llvm-config.h" 19| | 20| |#ifndef __has_feature 21| |# define __has_feature(x) 0 22| |#endif 23| | 24| |#ifndef __has_extension 25| |# define __has_extension(x) 0 26| |#endif 27| | 28| |#ifndef __has_attribute 29| |# define __has_attribute(x) 0 30| |#endif 31| | 32| |#ifndef __has_builtin 33| |# define __has_builtin(x) 0 34| |#endif 35| | 36| |/// \macro LLVM_GNUC_PREREQ 37| |/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't 38| |/// available. 39| |#ifndef LLVM_GNUC_PREREQ 40| |# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 42| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43| | ((maj) << 20) + ((min) << 10) + (patch)) 44| |# elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45| |# define LLVM_GNUC_PREREQ(maj, min, patch) \ 46| | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47| |# else 48| |# define LLVM_GNUC_PREREQ(maj, min, patch) 0 49| |# endif 50| |#endif 51| | 52| |/// \macro LLVM_MSC_PREREQ 53| |/// \brief Is the compiler MSVC of at least the specified version? 54| |/// The common \param version values to check for are: 55| |/// * 1800: Microsoft Visual Studio 2013 / 12.0 56| |/// * 1900: Microsoft Visual Studio 2015 / 14.0 57| |#ifdef _MSC_VER 58| |#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) 59| | 60| |// We require at least MSVC 2013. 61| |#if !LLVM_MSC_PREREQ(1800) 62| |#error LLVM requires at least MSVC 2013. 63| |#endif 64| | 65| |#else 66| |#define LLVM_MSC_PREREQ(version) 0 67| |#endif 68| | 69| |#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) 70| |#define LLVM_NOEXCEPT noexcept 71| |#else 72| |#define LLVM_NOEXCEPT 73| |#endif 74| | 75| |/// \brief Does the compiler support r-value reference *this? 76| |/// 77| |/// Sadly, this is separate from just r-value reference support because GCC 78| |/// implemented this later than everything else. 79| |#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) 80| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 81| |#else 82| |#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 83| |#endif 84| | 85| |/// Expands to '&' if r-value references are supported. 86| |/// 87| |/// This can be used to provide l-value/r-value overrides of member functions. 88| |/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS 89| |#if LLVM_HAS_RVALUE_REFERENCE_THIS 90| |#define LLVM_LVALUE_FUNCTION & 91| |#else 92| |#define LLVM_LVALUE_FUNCTION 93| |#endif 94| | 95| |#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) 96| |# define LLVM_CONSTEXPR constexpr 97| |#else 98| |# define LLVM_CONSTEXPR 99| |#endif 100| | 101| |/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked 102| |/// into a shared library, then the class should be private to the library and 103| |/// not accessible from outside it. Can also be used to mark variables and 104| |/// functions, making them private to any shared library they are linked into. 105| |/// On PE/COFF targets, library visibility is the default, so this isn't needed. 106| |#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 107| | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) 108| |#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) 109| |#else 110| |#define LLVM_LIBRARY_VISIBILITY 111| |#endif 112| | 113| |#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) 114| |#define LLVM_END_WITH_NULL __attribute__((sentinel)) 115| |#else 116| |#define LLVM_END_WITH_NULL 117| |#endif 118| | 119| |#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) 120| |#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) 121| |#else 122| |#define LLVM_ATTRIBUTE_USED 123| |#endif 124| | 125| |#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) 126| |#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) 127| |#else 128| |#define LLVM_ATTRIBUTE_UNUSED_RESULT 129| |#endif 130| | 131| |// Some compilers warn about unused functions. When a function is sometimes 132| |// used or not depending on build settings (e.g. a function only called from 133| |// within "assert"), this attribute can be used to suppress such warnings. 134| |// 135| |// However, it shouldn't be used for unused *variables*, as those have a much 136| |// more portable solution: 137| |// (void)unused_var_name; 138| |// Prefer cast-to-void wherever it is sufficient. 139| |#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) 140| |#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) 141| |#else 142| |#define LLVM_ATTRIBUTE_UNUSED 143| |#endif 144| | 145| |// FIXME: Provide this for PE/COFF targets. 146| |#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ 147| | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) 148| |#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) 149| |#else 150| |#define LLVM_ATTRIBUTE_WEAK 151| |#endif 152| | 153| |// Prior to clang 3.2, clang did not accept any spelling of 154| |// __has_attribute(const), so assume it is supported. 155| |#if defined(__clang__) || defined(__GNUC__) 156| |// aka 'CONST' but following LLVM Conventions. 157| |#define LLVM_READNONE __attribute__((__const__)) 158| |#else 159| |#define LLVM_READNONE 160| |#endif 161| | 162| |#if __has_attribute(pure) || defined(__GNUC__) 163| |// aka 'PURE' but following LLVM Conventions. 164| |#define LLVM_READONLY __attribute__((__pure__)) 165| |#else 166| |#define LLVM_READONLY 167| |#endif 168| | 169| |#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) 170| 0|#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) 171| 0|#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) 172| |#else 173| |#define LLVM_LIKELY(EXPR) (EXPR) 174| |#define LLVM_UNLIKELY(EXPR) (EXPR) 175| |#endif 176| | 177| |// C++ doesn't support 'extern template' of template specializations. GCC does, 178| |// but requires __extension__ before it. In the header, use this: 179| |// EXTERN_TEMPLATE_INSTANTIATION(class foo); 180| |// in the .cpp file, use this: 181| |// TEMPLATE_INSTANTIATION(class foo); 182| |#ifdef __GNUC__ 183| |#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X 184| |#define TEMPLATE_INSTANTIATION(X) template X 185| |#else 186| |#define EXTERN_TEMPLATE_INSTANTIATION(X) 187| |#define TEMPLATE_INSTANTIATION(X) 188| |#endif 189| | 190| |/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, 191| |/// mark a method "not for inlining". 192| |#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) 193| |#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) 194| |#elif defined(_MSC_VER) 195| |#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) 196| |#else 197| |#define LLVM_ATTRIBUTE_NOINLINE 198| |#endif 199| | 200| |/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do 201| |/// so, mark a method "always inline" because it is performance sensitive. GCC 202| |/// 3.4 supported this but is buggy in various cases and produces unimplemented 203| |/// errors, just use it in GCC 4.0 and later. 204| |#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) 205| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) 206| |#elif defined(_MSC_VER) 207| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline 208| |#else 209| |#define LLVM_ATTRIBUTE_ALWAYS_INLINE 210| |#endif 211| | 212| |#ifdef __GNUC__ 213| |#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) 214| |#elif defined(_MSC_VER) 215| |#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) 216| |#else 217| |#define LLVM_ATTRIBUTE_NORETURN 218| |#endif 219| | 220| |#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) 221| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) 222| |#else 223| |#define LLVM_ATTRIBUTE_RETURNS_NONNULL 224| |#endif 225| | 226| |/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress 227| |/// pedantic diagnostics. 228| |#ifdef __GNUC__ 229| 0|#define LLVM_EXTENSION __extension__ 230| |#else 231| |#define LLVM_EXTENSION 232| |#endif 233| | 234| |// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") 235| |#if __has_feature(attribute_deprecated_with_message) 236| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 237| | decl __attribute__((deprecated(message))) 238| |#elif defined(__GNUC__) 239| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 240| | decl __attribute__((deprecated)) 241| |#elif defined(_MSC_VER) 242| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 243| | __declspec(deprecated(message)) decl 244| |#else 245| |# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ 246| | decl 247| |#endif 248| | 249| |/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands 250| |/// to an expression which states that it is undefined behavior for the 251| |/// compiler to reach this point. Otherwise is not defined. 252| |#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) 253| 0|# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() 254| |#elif defined(_MSC_VER) 255| |# define LLVM_BUILTIN_UNREACHABLE __assume(false) 256| |#endif 257| | 258| |/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression 259| |/// which causes the program to exit abnormally. 260| |#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) 261| |# define LLVM_BUILTIN_TRAP __builtin_trap() 262| |#elif defined(_MSC_VER) 263| |// The __debugbreak intrinsic is supported by MSVC, does not require forward 264| |// declarations involving platform-specific typedefs (unlike RaiseException), 265| |// results in a call to vectored exception handlers, and encodes to a short 266| |// instruction that still causes the trapping behavior we want. 267| |# define LLVM_BUILTIN_TRAP __debugbreak() 268| |#else 269| |# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 270| |#endif 271| | 272| |/// \macro LLVM_ASSUME_ALIGNED 273| |/// \brief Returns a pointer with an assumed alignment. 274| |#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) 275| 0|# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) 276| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 277| |// As of today, clang does not support __builtin_assume_aligned. 278| |# define LLVM_ASSUME_ALIGNED(p, a) \ 279| | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) 280| |#else 281| |# define LLVM_ASSUME_ALIGNED(p, a) (p) 282| |#endif 283| | 284| |/// \macro LLVM_FUNCTION_NAME 285| |/// \brief Expands to __func__ on compilers which support it. Otherwise, 286| |/// expands to a compiler-dependent replacement. 287| |#if defined(_MSC_VER) 288| |# define LLVM_FUNCTION_NAME __FUNCTION__ 289| |#else 290| |# define LLVM_FUNCTION_NAME __func__ 291| |#endif 292| | 293| |/// \macro LLVM_MEMORY_SANITIZER_BUILD 294| |/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. 295| |#if __has_feature(memory_sanitizer) 296| |# define LLVM_MEMORY_SANITIZER_BUILD 1 297| |# include 298| |#else 299| |# define LLVM_MEMORY_SANITIZER_BUILD 0 300| |# define __msan_allocated_memory(p, size) 301| |# define __msan_unpoison(p, size) 302| |#endif 303| | 304| |/// \macro LLVM_ADDRESS_SANITIZER_BUILD 305| |/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. 306| |#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 307| |# define LLVM_ADDRESS_SANITIZER_BUILD 1 308| |#else 309| |# define LLVM_ADDRESS_SANITIZER_BUILD 0 310| |#endif 311| | 312| |/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST 313| |/// \brief Is unaligned memory access fast on the host machine. 314| |/// 315| |/// Don't specialize on alignment for platforms where unaligned memory accesses 316| |/// generates the same code as aligned memory accesses for common types. 317| |#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ 318| | defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ 319| | defined(_X86_) || defined(__i386) || defined(__i386__) 320| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 321| |#else 322| |# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 323| |#endif 324| | 325| |/// \brief Mark debug helper function definitions like dump() that should not be 326| |/// stripped from debug builds. 327| |// FIXME: Move this to a private config.h as it's not usable in public headers. 328| |#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED 330| |#else 331| |#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE 332| |#endif 333| | 334| |/// \macro LLVM_THREAD_LOCAL 335| |/// \brief A thread-local storage specifier which can be used with globals, 336| |/// extern globals, and static globals. 337| |/// 338| |/// This is essentially an extremely restricted analog to C++11's thread_local 339| |/// support, and uses that when available. However, it falls back on 340| |/// platform-specific or vendor-provided extensions when necessary. These 341| |/// extensions don't support many of the C++11 thread_local's features. You 342| |/// should only use this for PODs that you can statically initialize to 343| |/// some constant value. In almost all circumstances this is most appropriate 344| |/// for use with a pointer, integer, or small aggregation of pointers and 345| |/// integers. 346| |#if LLVM_ENABLE_THREADS 347| |#if __has_feature(cxx_thread_local) 348| |#define LLVM_THREAD_LOCAL thread_local 349| |#elif defined(_MSC_VER) 350| |// MSVC supports this with a __declspec. 351| |#define LLVM_THREAD_LOCAL __declspec(thread) 352| |#else 353| |// Clang, GCC, and other compatible compilers used __thread prior to C++11 and 354| |// we only need the restricted functionality that provides. 355| |#define LLVM_THREAD_LOCAL __thread 356| |#endif 357| |#else // !LLVM_ENABLE_THREADS 358| |// If threading is disabled entirely, this compiles to nothing and you get 359| |// a normal global variable. 360| |#define LLVM_THREAD_LOCAL 361| |#endif 362| | 363| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ConvertUTF.h: 1| |/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== 2| | * 3| | * The LLVM Compiler Infrastructure 4| | * 5| | * This file is distributed under the University of Illinois Open Source 6| | * License. See LICENSE.TXT for details. 7| | * 8| | *==------------------------------------------------------------------------==*/ 9| |/* 10| | * Copyright 2001-2004 Unicode, Inc. 11| | * 12| | * Disclaimer 13| | * 14| | * This source code is provided as is by Unicode, Inc. No claims are 15| | * made as to fitness for any particular purpose. No warranties of any 16| | * kind are expressed or implied. The recipient agrees to determine 17| | * applicability of information provided. If this file has been 18| | * purchased on magnetic or optical media from Unicode, Inc., the 19| | * sole remedy for any claim will be exchange of defective media 20| | * within 90 days of receipt. 21| | * 22| | * Limitations on Rights to Redistribute This Code 23| | * 24| | * Unicode, Inc. hereby grants the right to freely use the information 25| | * supplied in this file in the creation of products supporting the 26| | * Unicode Standard, and to make copies of this file in any form 27| | * for internal or external distribution as long as this notice 28| | * remains attached. 29| | */ 30| | 31| |/* --------------------------------------------------------------------- 32| | 33| | Conversions between UTF32, UTF-16, and UTF-8. Header file. 34| | 35| | Several funtions are included here, forming a complete set of 36| | conversions between the three formats. UTF-7 is not included 37| | here, but is handled in a separate source file. 38| | 39| | Each of these routines takes pointers to input buffers and output 40| | buffers. The input buffers are const. 41| | 42| | Each routine converts the text between *sourceStart and sourceEnd, 43| | putting the result into the buffer between *targetStart and 44| | targetEnd. Note: the end pointers are *after* the last item: e.g. 45| | *(sourceEnd - 1) is the last item. 46| | 47| | The return result indicates whether the conversion was successful, 48| | and if not, whether the problem was in the source or target buffers. 49| | (Only the first encountered problem is indicated.) 50| | 51| | After the conversion, *sourceStart and *targetStart are both 52| | updated to point to the end of last text successfully converted in 53| | the respective buffers. 54| | 55| | Input parameters: 56| | sourceStart - pointer to a pointer to the source buffer. 57| | The contents of this are modified on return so that 58| | it points at the next thing to be converted. 59| | targetStart - similarly, pointer to pointer to the target buffer. 60| | sourceEnd, targetEnd - respectively pointers to the ends of the 61| | two buffers, for overflow checking only. 62| | 63| | These conversion functions take a ConversionFlags argument. When this 64| | flag is set to strict, both irregular sequences and isolated surrogates 65| | will cause an error. When the flag is set to lenient, both irregular 66| | sequences and isolated surrogates are converted. 67| | 68| | Whether the flag is strict or lenient, all illegal sequences will cause 69| | an error return. This includes sequences such as: , , 70| | or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code 71| | must check for illegal sequences. 72| | 73| | When the flag is set to lenient, characters over 0x10FFFF are converted 74| | to the replacement character; otherwise (when the flag is set to strict) 75| | they constitute an error. 76| | 77| | Output parameters: 78| | The value "sourceIllegal" is returned from some routines if the input 79| | sequence is malformed. When "sourceIllegal" is returned, the source 80| | value will point to the illegal value that caused the problem. E.g., 81| | in UTF-8 when a sequence is malformed, it points to the start of the 82| | malformed sequence. 83| | 84| | Author: Mark E. Davis, 1994. 85| | Rev History: Rick McGowan, fixes & updates May 2001. 86| | Fixes & updates, Sept 2001. 87| | 88| |------------------------------------------------------------------------ */ 89| | 90| |#ifndef LLVM_SUPPORT_CONVERTUTF_H 91| |#define LLVM_SUPPORT_CONVERTUTF_H 92| | 93| |/* --------------------------------------------------------------------- 94| | The following 4 definitions are compiler-specific. 95| | The C standard does not guarantee that wchar_t has at least 96| | 16 bits, so wchar_t is no less portable than unsigned short! 97| | All should be unsigned values to avoid sign extension during 98| | bit mask & shift operations. 99| |------------------------------------------------------------------------ */ 100| | 101| |typedef unsigned int UTF32; /* at least 32 bits */ 102| |typedef unsigned short UTF16; /* at least 16 bits */ 103| |typedef unsigned char UTF8; /* typically 8 bits */ 104| |typedef unsigned char Boolean; /* 0 or 1 */ 105| | 106| |/* Some fundamental constants */ 107| 0|#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD 108| 0|#define UNI_MAX_BMP (UTF32)0x0000FFFF 109| 0|#define UNI_MAX_UTF16 (UTF32)0x0010FFFF 110| |#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF 111| 0|#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF 112| | 113| 0|#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 114| | 115| 0|#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF 116| 0|#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE 117| | 118| |typedef enum { 119| | conversionOK, /* conversion successful */ 120| | sourceExhausted, /* partial character in source, but hit end */ 121| | targetExhausted, /* insuff. room in target for conversion */ 122| | sourceIllegal /* source sequence is illegal/malformed */ 123| |} ConversionResult; 124| | 125| |typedef enum { 126| | strictConversion = 0, 127| | lenientConversion 128| |} ConversionFlags; 129| | 130| |/* This is for C++ and does no harm in C */ 131| |#ifdef __cplusplus 132| |extern "C" { 133| |#endif 134| | 135| |ConversionResult ConvertUTF8toUTF16 ( 136| | const UTF8** sourceStart, const UTF8* sourceEnd, 137| | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); 138| | 139| |/** 140| | * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an 141| | * incomplete code unit sequence, returns \c sourceExhausted. 142| | */ 143| |ConversionResult ConvertUTF8toUTF32Partial( 144| | const UTF8** sourceStart, const UTF8* sourceEnd, 145| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 146| | 147| |/** 148| | * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an 149| | * incomplete code unit sequence, returns \c sourceIllegal. 150| | */ 151| |ConversionResult ConvertUTF8toUTF32( 152| | const UTF8** sourceStart, const UTF8* sourceEnd, 153| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 154| | 155| |ConversionResult ConvertUTF16toUTF8 ( 156| | const UTF16** sourceStart, const UTF16* sourceEnd, 157| | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); 158| | 159| |ConversionResult ConvertUTF32toUTF8 ( 160| | const UTF32** sourceStart, const UTF32* sourceEnd, 161| | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); 162| | 163| |ConversionResult ConvertUTF16toUTF32 ( 164| | const UTF16** sourceStart, const UTF16* sourceEnd, 165| | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); 166| | 167| |ConversionResult ConvertUTF32toUTF16 ( 168| | const UTF32** sourceStart, const UTF32* sourceEnd, 169| | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); 170| | 171| |Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); 172| | 173| |Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); 174| | 175| |unsigned getNumBytesForUTF8(UTF8 firstByte); 176| | 177| |#ifdef __cplusplus 178| |} 179| | 180| |/*************************************************************************/ 181| |/* Below are LLVM-specific wrappers of the functions above. */ 182| | 183| |#include "llvm/ADT/ArrayRef.h" 184| |#include "llvm/ADT/StringRef.h" 185| | 186| |namespace llvm { 187| | 188| |/** 189| | * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on 190| | * WideCharWidth. The converted data is written to ResultPtr, which needs to 191| | * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, 192| | * ResultPtr will point one after the end of the copied string. On failure, 193| | * ResultPtr will not be changed, and ErrorPtr will be set to the location of 194| | * the first character which could not be converted. 195| | * \return true on success. 196| | */ 197| |bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, 198| | char *&ResultPtr, const UTF8 *&ErrorPtr); 199| | 200| |/** 201| | * Convert an Unicode code point to UTF8 sequence. 202| | * 203| | * \param Source a Unicode code point. 204| | * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least 205| | * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is 206| | * updated one past end of the converted sequence. 207| | * 208| | * \returns true on success. 209| | */ 210| |bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); 211| | 212| |/** 213| | * Convert the first UTF8 sequence in the given source buffer to a UTF32 214| | * code point. 215| | * 216| | * \param [in,out] source A pointer to the source buffer. If the conversion 217| | * succeeds, this pointer will be updated to point to the byte just past the 218| | * end of the converted sequence. 219| | * \param sourceEnd A pointer just past the end of the source buffer. 220| | * \param [out] target The converted code 221| | * \param flags Whether the conversion is strict or lenient. 222| | * 223| | * \returns conversionOK on success 224| | * 225| | * \sa ConvertUTF8toUTF32 226| | */ 227| |static inline ConversionResult convertUTF8Sequence(const UTF8 **source, 228| | const UTF8 *sourceEnd, 229| | UTF32 *target, 230| 0| ConversionFlags flags) { 231| 0| if (*source == sourceEnd) 232| 0| return sourceExhausted; 233| 0| unsigned size = getNumBytesForUTF8(**source); 234| 0| if ((ptrdiff_t)size > sourceEnd - *source) 235| 0| return sourceExhausted; 236| 0| return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); 237| 0|} ------------------ | Unexecuted instantiation: ConvertUTFWrapper.cpp:_ZN4llvmL19convertUTF8SequenceEPPKhS1_Pj15ConversionFlags ------------------ | Unexecuted instantiation: Unicode.cpp:_ZN4llvmL19convertUTF8SequenceEPPKhS1_Pj15ConversionFlags ------------------ 238| | 239| |/** 240| | * Returns true if a blob of text starts with a UTF-16 big or little endian byte 241| | * order mark. 242| | */ 243| |bool hasUTF16ByteOrderMark(ArrayRef SrcBytes); 244| | 245| |/** 246| | * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. 247| | * 248| | * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. 249| | * \param [out] Out Converted UTF-8 is stored here on success. 250| | * \returns true on success 251| | */ 252| |bool convertUTF16ToUTF8String(ArrayRef SrcBytes, std::string &Out); 253| | 254| |/** 255| | * Converts a UTF-8 string into a UTF-16 string with native endianness. 256| | * 257| | * \returns true on success 258| | */ 259| |bool convertUTF8ToUTF16String(StringRef SrcUTF8, 260| | SmallVectorImpl &DstUTF16); 261| | 262| |} /* end namespace llvm */ 263| | 264| |#endif 265| | 266| |/* --------------------------------------------------------------------- */ 267| | 268| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Debug.h: 1| |//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements a handy way of adding debugging information to your 11| |// code, without it being enabled all of the time, and without having to add 12| |// command line options to enable it. 13| |// 14| |// In particular, just wrap your code with the DEBUG() macro, and it will be 15| |// enabled automatically if you specify '-debug' on the command-line. 16| |// Alternatively, you can also define the DEBUG_TYPE macro to "foo" specify 17| |// that your debug code belongs to class "foo". Be careful that you only do 18| |// this after including Debug.h and not around any #include of headers. Headers 19| |// should define and undef the macro acround the code that needs to use the 20| |// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo' 21| |// to enable JUST the debug information for the foo class. 22| |// 23| |// When compiling without assertions, the -debug-* options and all code in 24| |// DEBUG() statements disappears, so it does not affect the runtime of the code. 25| |// 26| |//===----------------------------------------------------------------------===// 27| | 28| |#ifndef LLVM_SUPPORT_DEBUG_H 29| |#define LLVM_SUPPORT_DEBUG_H 30| | 31| |#include "llvm/Support/raw_ostream.h" 32| | 33| |// Undefine the DEBUG macro which is added by SwiftPM to avoid 34| |// conflict with another "DEBUG" symbol in this file. 35| |#ifdef SWIFT_PACKAGE 36| |#undef DEBUG 37| |#endif 38| | 39| |namespace llvm { 40| | 41| |#ifndef NDEBUG 42| |/// DebugFlag - This boolean is set to true if the '-debug' command line option 43| |/// is specified. This should probably not be referenced directly, instead, use 44| |/// the DEBUG macro below. 45| |/// 46| |extern bool DebugFlag; 47| | 48| |/// isCurrentDebugType - Return true if the specified string is the debug type 49| |/// specified on the command line, or if none was specified on the command line 50| |/// with the -debug-only=X option. 51| |/// 52| |bool isCurrentDebugType(const char *Type); 53| | 54| |/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X 55| |/// option were specified. Note that DebugFlag also needs to be set to true for 56| |/// debug output to be produced. 57| |/// 58| |void setCurrentDebugType(const char *Type); 59| | 60| |/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug 61| |/// information. In the '-debug' option is specified on the commandline, and if 62| |/// this is a debug build, then the code specified as the option to the macro 63| |/// will be executed. Otherwise it will not be. Example: 64| |/// 65| |/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n"); 66| |/// 67| |/// This will emit the debug information if -debug is present, and -debug-only 68| |/// is not specified, or is specified as "bitset". 69| |#define DEBUG_WITH_TYPE(TYPE, X) \ 70| 0| do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \ 71| 0| } while (0) 72| | 73| |#else 74| |#define isCurrentDebugType(X) (false) 75| |#define setCurrentDebugType(X) 76| |#define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) 77| |#endif 78| | 79| |/// EnableDebugBuffering - This defaults to false. If true, the debug 80| |/// stream will install signal handlers to dump any buffered debug 81| |/// output. It allows clients to selectively allow the debug stream 82| |/// to install signal handlers if they are certain there will be no 83| |/// conflict. 84| |/// 85| |extern bool EnableDebugBuffering; 86| | 87| |/// dbgs() - This returns a reference to a raw_ostream for debugging 88| |/// messages. If debugging is disabled it returns errs(). Use it 89| |/// like: dbgs() << "foo" << "bar"; 90| |raw_ostream &dbgs(); 91| | 92| |// DEBUG macro - This macro should be used by passes to emit debug information. 93| |// In the '-debug' option is specified on the commandline, and if this is a 94| |// debug build, then the code specified as the option to the macro will be 95| |// executed. Otherwise it will not be. Example: 96| |// 97| |// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); 98| |// 99| 0|#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) 100| | 101| |} // End llvm namespace 102| | 103| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Endian.h: 1| |//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic functions to read and write endian specific data. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_ENDIAN_H 15| |#define LLVM_SUPPORT_ENDIAN_H 16| | 17| |#include "llvm/Support/AlignOf.h" 18| |#include "llvm/Support/Host.h" 19| |#include "llvm/Support/SwapByteOrder.h" 20| | 21| |namespace llvm { 22| |namespace support { 23| |enum endianness {big, little, native}; 24| | 25| |// These are named values for common alignments. 26| |enum {aligned = 0, unaligned = 1}; 27| | 28| |namespace detail { 29| | /// \brief ::value is either alignment, or alignof(T) if alignment is 0. 30| | template 31| | struct PickAlignment { 32| | enum {value = alignment == 0 ? AlignOf::Alignment : alignment}; 33| | }; 34| |} // end namespace detail 35| | 36| |namespace endian { 37| |/// Swap the bytes of value to match the given endianness. 38| |template 39| 0|inline value_type byte_swap(value_type value) { 40| 0| if (endian != native && sys::IsBigEndianHost != (endian == big)) 41| 0| sys::swapByteOrder(value); 42| 0| return value; 43| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapItLNS0_10endiannessE1EEET_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapIjLNS0_10endiannessE1EEET_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapIyLNS0_10endiannessE1EEET_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapItLNS0_10endiannessE0EEET_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapIjLNS0_10endiannessE0EEET_S4_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian9byte_swapIyLNS0_10endiannessE0EEET_S4_ ------------------ 44| | 45| |/// Read a value of a particular endianness from memory. 46| |template 49| 0|inline value_type read(const void *memory) { 50| 0| value_type ret; 51| 0| 52| 0| memcpy(&ret, 53| 0| LLVM_ASSUME_ALIGNED(memory, 54| 0| (detail::PickAlignment::value)), 55| 0| sizeof(value_type)); 56| 0| return byte_swap(ret); 57| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readItLNS0_10endiannessE1ELm1EEET_PKv ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readIjLNS0_10endiannessE1ELm1EEET_PKv ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readIyLNS0_10endiannessE1ELm1EEET_PKv ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readItLNS0_10endiannessE0ELm1EEET_PKv ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readIjLNS0_10endiannessE0ELm1EEET_PKv ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian4readIyLNS0_10endiannessE0ELm1EEET_PKv ------------------ 58| | 59| |/// Read a value of a particular endianness from a buffer, and increment the 60| |/// buffer past that value. 61| |template 63| |inline value_type readNext(const CharT *&memory) { 64| | value_type ret = read(memory); 65| | memory += sizeof(value_type); 66| | return ret; 67| |} 68| | 69| |/// Write a value to memory with a particular endianness. 70| |template 73| 0|inline void write(void *memory, value_type value) { 74| 0| value = byte_swap(value); 75| 0| memcpy(LLVM_ASSUME_ALIGNED(memory, 76| 0| (detail::PickAlignment::value)), 77| 0| &value, 78| 0| sizeof(value_type)); 79| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeItLNS0_10endiannessE1ELm1EEEvPvT_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeIjLNS0_10endiannessE1ELm1EEEvPvT_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeIyLNS0_10endiannessE1ELm1EEEvPvT_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeItLNS0_10endiannessE0ELm1EEEvPvT_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeIjLNS0_10endiannessE0ELm1EEEvPvT_ ------------------ | Unexecuted instantiation: _ZN4llvm7support6endian5writeIyLNS0_10endiannessE0ELm1EEEvPvT_ ------------------ 80| |} // end namespace endian 81| | 82| |namespace detail { 83| |template 86| |struct packed_endian_specific_integral { 87| 0| operator value_type() const { 88| 0| return endian::read( 89| 0| (const void*)Value.buffer); 90| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralItLNS0_10endiannessE1ELm1EEcvtEv ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralIjLNS0_10endiannessE1ELm1EEcvjEv ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralIyLNS0_10endiannessE1ELm1EEcvyEv ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralItLNS0_10endiannessE0ELm1EEcvtEv ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralIjLNS0_10endiannessE0ELm1EEcvjEv ------------------ | Unexecuted instantiation: _ZNK4llvm7support6detail31packed_endian_specific_integralIyLNS0_10endiannessE0ELm1EEcvyEv ------------------ 91| | 92| 0| void operator=(value_type newValue) { 93| 0| endian::write( 94| 0| (void*)Value.buffer, newValue); 95| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralItLNS0_10endiannessE1ELm1EEaSEt ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralIjLNS0_10endiannessE1ELm1EEaSEj ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralIyLNS0_10endiannessE1ELm1EEaSEy ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralItLNS0_10endiannessE0ELm1EEaSEt ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralIjLNS0_10endiannessE0ELm1EEaSEj ------------------ | Unexecuted instantiation: _ZN4llvm7support6detail31packed_endian_specific_integralIyLNS0_10endiannessE0ELm1EEaSEy ------------------ 96| | 97| | packed_endian_specific_integral &operator+=(value_type newValue) { 98| | *this = *this + newValue; 99| | return *this; 100| | } 101| | 102| | packed_endian_specific_integral &operator-=(value_type newValue) { 103| | *this = *this - newValue; 104| | return *this; 105| | } 106| | 107| |private: 108| | AlignedCharArray::value, 109| | sizeof(value_type)> Value; 110| | 111| |public: 112| | struct ref { 113| | explicit ref(void *Ptr) : Ptr(Ptr) {} 114| | 115| | operator value_type() const { 116| | return endian::read(Ptr); 117| | } 118| | 119| | void operator=(value_type NewValue) { 120| | endian::write(Ptr, NewValue); 121| | } 122| | 123| | private: 124| | void *Ptr; 125| | }; 126| |}; 127| | 128| |} // end namespace detail 129| | 130| |typedef detail::packed_endian_specific_integral 131| | ulittle16_t; 132| |typedef detail::packed_endian_specific_integral 133| | ulittle32_t; 134| |typedef detail::packed_endian_specific_integral 135| | ulittle64_t; 136| | 137| |typedef detail::packed_endian_specific_integral 138| | little16_t; 139| |typedef detail::packed_endian_specific_integral 140| | little32_t; 141| |typedef detail::packed_endian_specific_integral 142| | little64_t; 143| | 144| |typedef detail::packed_endian_specific_integral 145| | aligned_ulittle16_t; 146| |typedef detail::packed_endian_specific_integral 147| | aligned_ulittle32_t; 148| |typedef detail::packed_endian_specific_integral 149| | aligned_ulittle64_t; 150| | 151| |typedef detail::packed_endian_specific_integral 152| | aligned_little16_t; 153| |typedef detail::packed_endian_specific_integral 154| | aligned_little32_t; 155| |typedef detail::packed_endian_specific_integral 156| | aligned_little64_t; 157| | 158| |typedef detail::packed_endian_specific_integral 159| | ubig16_t; 160| |typedef detail::packed_endian_specific_integral 161| | ubig32_t; 162| |typedef detail::packed_endian_specific_integral 163| | ubig64_t; 164| | 165| |typedef detail::packed_endian_specific_integral 166| | big16_t; 167| |typedef detail::packed_endian_specific_integral 168| | big32_t; 169| |typedef detail::packed_endian_specific_integral 170| | big64_t; 171| | 172| |typedef detail::packed_endian_specific_integral 173| | aligned_ubig16_t; 174| |typedef detail::packed_endian_specific_integral 175| | aligned_ubig32_t; 176| |typedef detail::packed_endian_specific_integral 177| | aligned_ubig64_t; 178| | 179| |typedef detail::packed_endian_specific_integral 180| | aligned_big16_t; 181| |typedef detail::packed_endian_specific_integral 182| | aligned_big32_t; 183| |typedef detail::packed_endian_specific_integral 184| | aligned_big64_t; 185| | 186| |typedef detail::packed_endian_specific_integral 187| | unaligned_uint16_t; 188| |typedef detail::packed_endian_specific_integral 189| | unaligned_uint32_t; 190| |typedef detail::packed_endian_specific_integral 191| | unaligned_uint64_t; 192| | 193| |typedef detail::packed_endian_specific_integral 194| | unaligned_int16_t; 195| |typedef detail::packed_endian_specific_integral 196| | unaligned_int32_t; 197| |typedef detail::packed_endian_specific_integral 198| | unaligned_int64_t; 199| | 200| |namespace endian { 201| 0|inline uint16_t read16le(const void *p) { return *(const ulittle16_t *)p; } 202| 0|inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; } 203| 0|inline uint64_t read64le(const void *p) { return *(const ulittle64_t *)p; } 204| 0|inline uint16_t read16be(const void *p) { return *(const ubig16_t *)p; } 205| 0|inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; } 206| 0|inline uint64_t read64be(const void *p) { return *(const ubig64_t *)p; } 207| | 208| 0|inline void write16le(void *p, uint16_t v) { *(ulittle16_t *)p = v; } 209| 0|inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; } 210| 0|inline void write64le(void *p, uint64_t v) { *(ulittle64_t *)p = v; } 211| 0|inline void write16be(void *p, uint16_t v) { *(ubig16_t *)p = v; } 212| 0|inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; } 213| 0|inline void write64be(void *p, uint64_t v) { *(ubig64_t *)p = v; } 214| |} // end namespace endian 215| |} // end namespace support 216| |} // end namespace llvm 217| | 218| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Errc.h: 1| |//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// While std::error_code works OK on all platforms we use, there are some 11| |// some problems with std::errc that can be avoided by using our own 12| |// enumeration: 13| |// 14| |// * std::errc is a namespace in some implementations. That meas that ADL 15| |// doesn't work and it is sometimes necessary to write std::make_error_code 16| |// or in templates: 17| |// using std::make_error_code; 18| |// make_error_code(...); 19| |// 20| |// with this enum it is safe to always just use make_error_code. 21| |// 22| |// * Some implementations define fewer names than others. This header has 23| |// the intersection of all the ones we support. 24| |// 25| |// * std::errc is just marked with is_error_condition_enum. This means that 26| |// common patters like AnErrorCode == errc::no_such_file_or_directory take 27| |// 4 virtual calls instead of two comparisons. 28| |//===----------------------------------------------------------------------===// 29| | 30| |#ifndef LLVM_SUPPORT_ERRC_H 31| |#define LLVM_SUPPORT_ERRC_H 32| | 33| |#include 34| | 35| |namespace llvm { 36| |enum class errc { 37| | argument_list_too_long = int(std::errc::argument_list_too_long), 38| | argument_out_of_domain = int(std::errc::argument_out_of_domain), 39| | bad_address = int(std::errc::bad_address), 40| | bad_file_descriptor = int(std::errc::bad_file_descriptor), 41| | broken_pipe = int(std::errc::broken_pipe), 42| | device_or_resource_busy = int(std::errc::device_or_resource_busy), 43| | directory_not_empty = int(std::errc::directory_not_empty), 44| | executable_format_error = int(std::errc::executable_format_error), 45| | file_exists = int(std::errc::file_exists), 46| | file_too_large = int(std::errc::file_too_large), 47| | filename_too_long = int(std::errc::filename_too_long), 48| | function_not_supported = int(std::errc::function_not_supported), 49| | illegal_byte_sequence = int(std::errc::illegal_byte_sequence), 50| | inappropriate_io_control_operation = 51| | int(std::errc::inappropriate_io_control_operation), 52| | interrupted = int(std::errc::interrupted), 53| | invalid_argument = int(std::errc::invalid_argument), 54| | invalid_seek = int(std::errc::invalid_seek), 55| | io_error = int(std::errc::io_error), 56| | is_a_directory = int(std::errc::is_a_directory), 57| | no_child_process = int(std::errc::no_child_process), 58| | no_lock_available = int(std::errc::no_lock_available), 59| | no_space_on_device = int(std::errc::no_space_on_device), 60| | no_such_device_or_address = int(std::errc::no_such_device_or_address), 61| | no_such_device = int(std::errc::no_such_device), 62| | no_such_file_or_directory = int(std::errc::no_such_file_or_directory), 63| | no_such_process = int(std::errc::no_such_process), 64| | not_a_directory = int(std::errc::not_a_directory), 65| | not_enough_memory = int(std::errc::not_enough_memory), 66| | operation_not_permitted = int(std::errc::operation_not_permitted), 67| | permission_denied = int(std::errc::permission_denied), 68| | read_only_file_system = int(std::errc::read_only_file_system), 69| | resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur), 70| | resource_unavailable_try_again = 71| | int(std::errc::resource_unavailable_try_again), 72| | result_out_of_range = int(std::errc::result_out_of_range), 73| | too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system), 74| | too_many_files_open = int(std::errc::too_many_files_open), 75| | too_many_links = int(std::errc::too_many_links) 76| |}; 77| | 78| 0|inline std::error_code make_error_code(errc E) { 79| 0| return std::error_code(static_cast(E), std::generic_category()); 80| 0|} 81| |} 82| | 83| |namespace std { 84| |template <> struct is_error_code_enum : std::true_type {}; 85| |} 86| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorHandling.h: 1| |//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines an API used to indicate fatal error conditions. Non-fatal 11| |// errors (most of them) should be handled through LLVMContext. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_ERRORHANDLING_H 16| |#define LLVM_SUPPORT_ERRORHANDLING_H 17| | 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include 21| | 22| |namespace llvm { 23| | class Twine; 24| | 25| | /// An error handler callback. 26| | typedef void (*fatal_error_handler_t)(void *user_data, 27| | const std::string& reason, 28| | bool gen_crash_diag); 29| | 30| | /// install_fatal_error_handler - Installs a new error handler to be used 31| | /// whenever a serious (non-recoverable) error is encountered by LLVM. 32| | /// 33| | /// If no error handler is installed the default is to print the error message 34| | /// to stderr, and call exit(1). If an error handler is installed then it is 35| | /// the handler's responsibility to log the message, it will no longer be 36| | /// printed to stderr. If the error handler returns, then exit(1) will be 37| | /// called. 38| | /// 39| | /// It is dangerous to naively use an error handler which throws an exception. 40| | /// Even though some applications desire to gracefully recover from arbitrary 41| | /// faults, blindly throwing exceptions through unfamiliar code isn't a way to 42| | /// achieve this. 43| | /// 44| | /// \param user_data - An argument which will be passed to the install error 45| | /// handler. 46| | void install_fatal_error_handler(fatal_error_handler_t handler, 47| | void *user_data = nullptr); 48| | 49| | /// Restores default error handling behaviour. 50| | void remove_fatal_error_handler(); 51| | 52| | /// ScopedFatalErrorHandler - This is a simple helper class which just 53| | /// calls install_fatal_error_handler in its constructor and 54| | /// remove_fatal_error_handler in its destructor. 55| | struct ScopedFatalErrorHandler { 56| | explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, 57| 0| void *user_data = nullptr) { 58| 0| install_fatal_error_handler(handler, user_data); 59| 0| } 60| | 61| 0| ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } 62| | }; 63| | 64| | /// Reports a serious error, calling any installed error handler. These 65| | /// functions are intended to be used for error conditions which are outside 66| | /// the control of the compiler (I/O errors, invalid user input, etc.) 67| | /// 68| | /// If no error handler is installed the default is to print the message to 69| | /// standard error, followed by a newline. 70| | /// After the error handler is called this function will call exit(1), it 71| | /// does not return. 72| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, 73| | bool gen_crash_diag = true); 74| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, 75| | bool gen_crash_diag = true); 76| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, 77| | bool gen_crash_diag = true); 78| | LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, 79| | bool gen_crash_diag = true); 80| | 81| | /// This function calls abort(), and prints the optional message to stderr. 82| | /// Use the llvm_unreachable macro (that adds location info), instead of 83| | /// calling this function directly. 84| | LLVM_ATTRIBUTE_NORETURN void 85| | llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, 86| | unsigned line=0); 87| |} 88| | 89| |/// Marks that the current location is not supposed to be reachable. 90| |/// In !NDEBUG builds, prints the message and location info to stderr. 91| |/// In NDEBUG builds, becomes an optimizer hint that the current location 92| |/// is not supposed to be reachable. On compilers that don't support 93| |/// such hints, prints a reduced message instead. 94| |/// 95| |/// Use this instead of assert(0). It conveys intent more clearly and 96| |/// allows compilers to omit some unnecessary code. 97| |#ifndef NDEBUG 98| |#define llvm_unreachable(msg) \ 99| 0| ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) 100| |#elif defined(LLVM_BUILTIN_UNREACHABLE) 101| |#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE 102| |#else 103| |#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() 104| |#endif 105| | 106| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ErrorOr.h: 1| |//===- llvm/Support/ErrorOr.h - Error Smart Pointer -----------------------===// 2| |// 3| |// The LLVM Linker 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |/// 10| |/// \file 11| |/// 12| |/// Provides ErrorOr smart pointer. 13| |/// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_ERROROR_H 17| |#define LLVM_SUPPORT_ERROROR_H 18| | 19| |#include "llvm/ADT/PointerIntPair.h" 20| |#include "llvm/Support/AlignOf.h" 21| |#include 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |template 27| |typename std::enable_if< std::is_constructible::value 28| | , typename std::remove_reference::type>::type && 29| 0| moveIfMoveConstructible(V &Val) { 30| 0| return std::move(Val); 31| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm23moveIfMoveConstructibleINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEES6_EEONS1_9enable_ifIXsr3std16is_constructibleIT_T0_EE5valueENS1_16remove_referenceIS9_E4typeEE4typeERS9_ ------------------ | Unexecuted instantiation: _ZN4llvm23moveIfMoveConstructibleINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES7_EEONS1_9enable_ifIXsr3std16is_constructibleIT_T0_EE5valueENS1_16remove_referenceISA_E4typeEE4typeERSA_ ------------------ 32| | 33| |template 34| |typename std::enable_if< !std::is_constructible::value 35| | , typename std::remove_reference::type>::type & 36| |moveIfMoveConstructible(V &Val) { 37| | return Val; 38| |} 39| | 40| |/// \brief Stores a reference that can be changed. 41| |template 42| |class ReferenceStorage { 43| | T *Storage; 44| | 45| |public: 46| | ReferenceStorage(T &Ref) : Storage(&Ref) {} 47| | 48| | operator T &() const { return *Storage; } 49| | T &get() const { return *Storage; } 50| |}; 51| | 52| |/// \brief Represents either an error or a value T. 53| |/// 54| |/// ErrorOr is a pointer-like class that represents the result of an 55| |/// operation. The result is either an error, or a value of type T. This is 56| |/// designed to emulate the usage of returning a pointer where nullptr indicates 57| |/// failure. However instead of just knowing that the operation failed, we also 58| |/// have an error_code and optional user data that describes why it failed. 59| |/// 60| |/// It is used like the following. 61| |/// \code 62| |/// ErrorOr getBuffer(); 63| |/// 64| |/// auto buffer = getBuffer(); 65| |/// if (error_code ec = buffer.getError()) 66| |/// return ec; 67| |/// buffer->write("adena"); 68| |/// \endcode 69| |/// 70| |/// 71| |/// Implicit conversion to bool returns true if there is a usable value. The 72| |/// unary * and -> operators provide pointer like access to the value. Accessing 73| |/// the value when there is an error has undefined behavior. 74| |/// 75| |/// When T is a reference type the behaivor is slightly different. The reference 76| |/// is held in a std::reference_wrapper::type>, and 77| |/// there is special handling to make operator -> work as if T was not a 78| |/// reference. 79| |/// 80| |/// T cannot be a rvalue reference. 81| |template 82| |class ErrorOr { 83| | template friend class ErrorOr; 84| | static const bool isRef = std::is_reference::value; 85| | typedef ReferenceStorage::type> wrap; 86| | 87| |public: 88| | typedef typename std::conditional::type storage_type; 89| | 90| |private: 91| | typedef typename std::remove_reference::type &reference; 92| | typedef const typename std::remove_reference::type &const_reference; 93| | typedef typename std::remove_reference::type *pointer; 94| | 95| |public: 96| | template 97| | ErrorOr(E ErrorCode, 98| | typename std::enable_if::value || 99| | std::is_error_condition_enum::value, 100| | void *>::type = 0) 101| 0| : HasError(true) { 102| 0| new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); 103| 0| } 104| | 105| 0| ErrorOr(std::error_code EC) : HasError(true) { 106| 0| new (getErrorStorage()) std::error_code(EC); 107| 0| } 108| | 109| 0| ErrorOr(T Val) : HasError(false) { 110| 0| new (getStorage()) storage_type(moveIfMoveConstructible(Val)); 111| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEEC2ES6_ ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEC2ES7_ ------------------ 112| | 113| | ErrorOr(const ErrorOr &Other) { 114| | copyConstruct(Other); 115| | } 116| | 117| | template 118| | ErrorOr( 119| | const ErrorOr &Other, 120| | typename std::enable_if::value>::type * = 121| | nullptr) { 122| | copyConstruct(Other); 123| | } 124| | 125| | template 126| | explicit ErrorOr( 127| | const ErrorOr &Other, 128| | typename std::enable_if< 129| | !std::is_convertible::value>::type * = nullptr) { 130| | copyConstruct(Other); 131| | } 132| | 133| 0| ErrorOr(ErrorOr &&Other) { 134| 0| moveConstruct(std::move(Other)); 135| 0| } 136| | 137| | template 138| | ErrorOr( 139| | ErrorOr &&Other, 140| | typename std::enable_if::value>::type * = 141| | nullptr) { 142| | moveConstruct(std::move(Other)); 143| | } 144| | 145| | // This might eventually need SFINAE but it's more complex than is_convertible 146| | // & I'm too lazy to write it right now. 147| | template 148| | explicit ErrorOr( 149| | ErrorOr &&Other, 150| | typename std::enable_if::value>::type * = 151| | nullptr) { 152| | moveConstruct(std::move(Other)); 153| | } 154| | 155| | ErrorOr &operator=(const ErrorOr &Other) { 156| | copyAssign(Other); 157| | return *this; 158| | } 159| | 160| 0| ErrorOr &operator=(ErrorOr &&Other) { 161| 0| moveAssign(std::move(Other)); 162| 0| return *this; 163| 0| } 164| | 165| 0| ~ErrorOr() { 166| 0| if (!HasError) 167| 0| getStorage()->~storage_type(); 168| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEED2Ev ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEED2Ev ------------------ 169| | 170| | /// \brief Return false if there is an error. 171| 0| explicit operator bool() const { 172| 0| return !HasError; 173| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEcvbEv ------------------ | Unexecuted instantiation: _ZNK4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEEcvbEv ------------------ 174| | 175| 0| reference get() { return *getStorage(); } 176| | const_reference get() const { return const_cast *>(this)->get(); } 177| | 178| 0| std::error_code getError() const { 179| 0| return HasError ? *getErrorStorage() : std::error_code(); 180| 0| } 181| | 182| | pointer operator ->() { 183| | return toPointer(getStorage()); 184| | } 185| | 186| 0| reference operator *() { 187| 0| return *getStorage(); 188| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEdeEv ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEEdeEv ------------------ 189| | 190| |private: 191| | template 192| | void copyConstruct(const ErrorOr &Other) { 193| | if (!Other.HasError) { 194| | // Get the other value. 195| | HasError = false; 196| | new (getStorage()) storage_type(*Other.getStorage()); 197| | } else { 198| | // Get other's error. 199| | HasError = true; 200| | new (getErrorStorage()) std::error_code(Other.getError()); 201| | } 202| | } 203| | 204| | template 205| 0| static bool compareThisIfSameType(const T1 &a, const T1 &b) { 206| 0| return &a == &b; 207| 0| } 208| | 209| | template 210| | static bool compareThisIfSameType(const T1 &a, const T2 &b) { 211| | return false; 212| | } 213| | 214| | template 215| | void copyAssign(const ErrorOr &Other) { 216| | if (compareThisIfSameType(*this, Other)) 217| | return; 218| | 219| | this->~ErrorOr(); 220| | new (this) ErrorOr(Other); 221| | } 222| | 223| | template 224| 0| void moveConstruct(ErrorOr &&Other) { 225| 0| if (!Other.HasError) { 226| 0| // Get the other value. 227| 0| HasError = false; 228| 0| new (getStorage()) storage_type(std::move(*Other.getStorage())); 229| 0| } else { 230| 0| // Get other's error. 231| 0| HasError = true; 232| 0| new (getErrorStorage()) std::error_code(Other.getError()); 233| 0| } 234| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE13moveConstructIS6_EEvONS0_IT_EE ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE13moveConstructIS7_EEvONS0_IT_EE ------------------ 235| | 236| | template 237| 0| void moveAssign(ErrorOr &&Other) { 238| 0| if (compareThisIfSameType(*this, Other)) 239| 0| return; 240| 0| 241| 0| this->~ErrorOr(); 242| 0| new (this) ErrorOr(std::move(Other)); 243| 0| } 244| | 245| | pointer toPointer(pointer Val) { 246| | return Val; 247| | } 248| | 249| | pointer toPointer(wrap *Val) { 250| | return &Val->get(); 251| | } 252| | 253| 0| storage_type *getStorage() { 254| 0| assert(!HasError && "Cannot get value when an error exists!"); 255| 0| return reinterpret_cast(TStorage.buffer); 256| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE10getStorageEv ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE10getStorageEv ------------------ 257| | 258| | const storage_type *getStorage() const { 259| | assert(!HasError && "Cannot get value when an error exists!"); 260| | return reinterpret_cast(TStorage.buffer); 261| | } 262| | 263| 0| std::error_code *getErrorStorage() { 264| 0| assert(HasError && "Cannot get error when a value exists!"); 265| 0| return reinterpret_cast(ErrorStorage.buffer); 266| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__110unique_ptrINS_12MemoryBufferENS1_14default_deleteIS3_EEEEE15getErrorStorageEv ------------------ | Unexecuted instantiation: _ZN4llvm7ErrorOrINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE15getErrorStorageEv ------------------ 267| | 268| 0| const std::error_code *getErrorStorage() const { 269| 0| return const_cast *>(this)->getErrorStorage(); 270| 0| } 271| | 272| | 273| | union { 274| | AlignedCharArrayUnion TStorage; 275| | AlignedCharArrayUnion ErrorStorage; 276| | }; 277| | bool HasError : 1; 278| |}; 279| | 280| |template 281| |typename std::enable_if::value || 282| | std::is_error_condition_enum::value, 283| | bool>::type 284| |operator==(ErrorOr &Err, E Code) { 285| | return std::error_code(Err) == Code; 286| |} 287| |} // end namespace llvm 288| | 289| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/FileSystem.h: 1| |//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::fs namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |// All functions return an error_code and their actual work via the last out 15| |// argument. The out argument is defined if and only if errc::success is 16| |// returned. A function may return any error code in the generic or system 17| |// category. However, they shall be equivalent to any error conditions listed 18| |// in each functions respective documentation if the condition applies. [ note: 19| |// this does not guarantee that error_code will be in the set of explicitly 20| |// listed codes, but it does guarantee that if any of the explicitly listed 21| |// errors occur, the correct error_code will be used ]. All functions may 22| |// return errc::not_enough_memory if there is not enough memory to complete the 23| |// operation. 24| |// 25| |//===----------------------------------------------------------------------===// 26| | 27| |#ifndef LLVM_SUPPORT_FILESYSTEM_H 28| |#define LLVM_SUPPORT_FILESYSTEM_H 29| | 30| |#include "llvm/ADT/IntrusiveRefCntPtr.h" 31| |#include "llvm/ADT/SmallString.h" 32| |#include "llvm/ADT/Twine.h" 33| |#include "llvm/Support/DataTypes.h" 34| |#include "llvm/Support/ErrorHandling.h" 35| |#include "llvm/Support/TimeValue.h" 36| |#include 37| |#include 38| |#include 39| |#include 40| |#include 41| |#include 42| |#include 43| | 44| |#ifdef HAVE_SYS_STAT_H 45| |#include 46| |#endif 47| | 48| |namespace llvm { 49| |namespace sys { 50| |namespace fs { 51| | 52| |/// An enumeration for the file system's view of the type. 53| |enum class file_type { 54| | status_error, 55| | file_not_found, 56| | regular_file, 57| | directory_file, 58| | symlink_file, 59| | block_file, 60| | character_file, 61| | fifo_file, 62| | socket_file, 63| | type_unknown 64| |}; 65| | 66| |/// space_info - Self explanatory. 67| |struct space_info { 68| | uint64_t capacity; 69| | uint64_t free; 70| | uint64_t available; 71| |}; 72| | 73| |enum perms { 74| | no_perms = 0, 75| | owner_read = 0400, 76| | owner_write = 0200, 77| | owner_exe = 0100, 78| | owner_all = owner_read | owner_write | owner_exe, 79| | group_read = 040, 80| | group_write = 020, 81| | group_exe = 010, 82| | group_all = group_read | group_write | group_exe, 83| | others_read = 04, 84| | others_write = 02, 85| | others_exe = 01, 86| | others_all = others_read | others_write | others_exe, 87| | all_read = owner_read | group_read | others_read, 88| | all_write = owner_write | group_write | others_write, 89| | all_exe = owner_exe | group_exe | others_exe, 90| | all_all = owner_all | group_all | others_all, 91| | set_uid_on_exe = 04000, 92| | set_gid_on_exe = 02000, 93| | sticky_bit = 01000, 94| | perms_not_known = 0xFFFF 95| |}; 96| | 97| |// Helper functions so that you can use & and | to manipulate perms bits: 98| 0|inline perms operator|(perms l , perms r) { 99| 0| return static_cast( 100| 0| static_cast(l) | static_cast(r)); 101| 0|} 102| 0|inline perms operator&(perms l , perms r) { 103| 0| return static_cast( 104| 0| static_cast(l) & static_cast(r)); 105| 0|} 106| 0|inline perms &operator|=(perms &l, perms r) { 107| 0| l = l | r; 108| 0| return l; 109| 0|} 110| 0|inline perms &operator&=(perms &l, perms r) { 111| 0| l = l & r; 112| 0| return l; 113| 0|} 114| 0|inline perms operator~(perms x) { 115| 0| return static_cast(~static_cast(x)); 116| 0|} 117| | 118| |class UniqueID { 119| | uint64_t Device; 120| | uint64_t File; 121| | 122| |public: 123| 0| UniqueID() {} 124| 0| UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 125| 0| bool operator==(const UniqueID &Other) const { 126| 0| return Device == Other.Device && File == Other.File; 127| 0| } 128| 0| bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 129| 0| bool operator<(const UniqueID &Other) const { 130| 0| return std::tie(Device, File) < std::tie(Other.Device, Other.File); 131| 0| } 132| 0| uint64_t getDevice() const { return Device; } 133| 0| uint64_t getFile() const { return File; } 134| |}; 135| | 136| |/// file_status - Represents the result of a call to stat and friends. It has 137| |/// a platform-specific member to store the result. 138| |class file_status 139| |{ 140| | #if defined(LLVM_ON_UNIX) 141| | dev_t fs_st_dev; 142| | ino_t fs_st_ino; 143| | time_t fs_st_mtime; 144| | uid_t fs_st_uid; 145| | gid_t fs_st_gid; 146| | off_t fs_st_size; 147| | #elif defined (LLVM_ON_WIN32) 148| | uint32_t LastWriteTimeHigh; 149| | uint32_t LastWriteTimeLow; 150| | uint32_t VolumeSerialNumber; 151| | uint32_t FileSizeHigh; 152| | uint32_t FileSizeLow; 153| | uint32_t FileIndexHigh; 154| | uint32_t FileIndexLow; 155| | #endif 156| | friend bool equivalent(file_status A, file_status B); 157| | file_type Type; 158| | perms Perms; 159| |public: 160| | #if defined(LLVM_ON_UNIX) 161| | file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 162| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), 163| 0| Type(file_type::status_error), Perms(perms_not_known) {} 164| | 165| | file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 166| | fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), 167| 0| Perms(perms_not_known) {} 168| | 169| | file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, 170| | uid_t UID, gid_t GID, off_t Size) 171| | : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), 172| 0| fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} 173| | #elif defined(LLVM_ON_WIN32) 174| | file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), 175| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 176| | FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), 177| | Perms(perms_not_known) {} 178| | 179| | file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), 180| | VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 181| | FileIndexHigh(0), FileIndexLow(0), Type(Type), 182| | Perms(perms_not_known) {} 183| | 184| | file_status(file_type Type, uint32_t LastWriteTimeHigh, 185| | uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, 186| | uint32_t FileSizeHigh, uint32_t FileSizeLow, 187| | uint32_t FileIndexHigh, uint32_t FileIndexLow) 188| | : LastWriteTimeHigh(LastWriteTimeHigh), 189| | LastWriteTimeLow(LastWriteTimeLow), 190| | VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), 191| | FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), 192| | FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} 193| | #endif 194| | 195| | // getters 196| 0| file_type type() const { return Type; } 197| 0| perms permissions() const { return Perms; } 198| | TimeValue getLastModificationTime() const; 199| | UniqueID getUniqueID() const; 200| | 201| | #if defined(LLVM_ON_UNIX) 202| 0| uint32_t getUser() const { return fs_st_uid; } 203| 0| uint32_t getGroup() const { return fs_st_gid; } 204| 0| uint64_t getSize() const { return fs_st_size; } 205| | #elif defined (LLVM_ON_WIN32) 206| | uint32_t getUser() const { 207| | return 9999; // Not applicable to Windows, so... 208| | } 209| | uint32_t getGroup() const { 210| | return 9999; // Not applicable to Windows, so... 211| | } 212| | uint64_t getSize() const { 213| | return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 214| | } 215| | #endif 216| | 217| | // setters 218| 0| void type(file_type v) { Type = v; } 219| 0| void permissions(perms p) { Perms = p; } 220| |}; 221| | 222| |/// file_magic - An "enum class" enumeration of file types based on magic (the first 223| |/// N bytes of the file). 224| |struct file_magic { 225| | enum Impl { 226| | unknown = 0, ///< Unrecognized file 227| | bitcode, ///< Bitcode file 228| | archive, ///< ar style archive file 229| | elf, ///< ELF Unknown type 230| | elf_relocatable, ///< ELF Relocatable object file 231| | elf_executable, ///< ELF Executable image 232| | elf_shared_object, ///< ELF dynamically linked shared lib 233| | elf_core, ///< ELF core image 234| | macho_object, ///< Mach-O Object file 235| | macho_executable, ///< Mach-O Executable 236| | macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 237| | macho_core, ///< Mach-O Core File 238| | macho_preload_executable, ///< Mach-O Preloaded Executable 239| | macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 240| | macho_dynamic_linker, ///< The Mach-O dynamic linker 241| | macho_bundle, ///< Mach-O Bundle file 242| | macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 243| | macho_dsym_companion, ///< Mach-O dSYM companion file 244| | macho_kext_bundle, ///< Mach-O kext bundle file 245| | macho_universal_binary, ///< Mach-O universal binary 246| | coff_object, ///< COFF object file 247| | coff_import_library, ///< COFF import library 248| | pecoff_executable, ///< PECOFF executable file 249| | windows_resource ///< Windows compiled resource file (.rc) 250| | }; 251| | 252| 0| bool is_object() const { 253| 0| return V == unknown ? false : true; 254| 0| } 255| | 256| 0| file_magic() : V(unknown) {} 257| 0| file_magic(Impl V) : V(V) {} 258| 0| operator Impl() const { return V; } 259| | 260| |private: 261| | Impl V; 262| |}; 263| | 264| |/// @} 265| |/// @name Physical Operators 266| |/// @{ 267| | 268| |/// @brief Make \a path an absolute path. 269| |/// 270| |/// Makes \a path absolute using the current directory if it is not already. An 271| |/// empty \a path will result in the current directory. 272| |/// 273| |/// /absolute/path => /absolute/path 274| |/// relative/../path => /relative/../path 275| |/// 276| |/// @param path A path that is modified to be an absolute path. 277| |/// @returns errc::success if \a path has been made absolute, otherwise a 278| |/// platform-specific error_code. 279| |std::error_code make_absolute(SmallVectorImpl &path); 280| | 281| |/// @brief Create all the non-existent directories in path. 282| |/// 283| |/// @param path Directories to create. 284| |/// @returns errc::success if is_directory(path), otherwise a platform 285| |/// specific error_code. If IgnoreExisting is false, also returns 286| |/// error if the directory already existed. 287| |std::error_code create_directories(const Twine &path, 288| | bool IgnoreExisting = true); 289| | 290| |/// @brief Create the directory in path. 291| |/// 292| |/// @param path Directory to create. 293| |/// @returns errc::success if is_directory(path), otherwise a platform 294| |/// specific error_code. If IgnoreExisting is false, also returns 295| |/// error if the directory already existed. 296| |std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); 297| | 298| |/// @brief Create a link from \a from to \a to. 299| |/// 300| |/// The link may be a soft or a hard link, depending on the platform. The caller 301| |/// may not assume which one. Currently on windows it creates a hard link since 302| |/// soft links require extra privileges. On unix, it creates a soft link since 303| |/// hard links don't work on SMB file systems. 304| |/// 305| |/// @param to The path to hard link to. 306| |/// @param from The path to hard link from. This is created. 307| |/// @returns errc::success if the link was created, otherwise a platform 308| |/// specific error_code. 309| |std::error_code create_link(const Twine &to, const Twine &from); 310| | 311| |/// @brief Get the current path. 312| |/// 313| |/// @param result Holds the current path on return. 314| |/// @returns errc::success if the current path has been stored in result, 315| |/// otherwise a platform-specific error_code. 316| |std::error_code current_path(SmallVectorImpl &result); 317| | 318| |/// @brief Remove path. Equivalent to POSIX remove(). 319| |/// 320| |/// @param path Input path. 321| |/// @returns errc::success if path has been removed or didn't exist, otherwise a 322| |/// platform-specific error code. If IgnoreNonExisting is false, also 323| |/// returns error if the file didn't exist. 324| |std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 325| | 326| |/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 327| |/// 328| |/// @param from The path to rename from. 329| |/// @param to The path to rename to. This is created. 330| |std::error_code rename(const Twine &from, const Twine &to); 331| | 332| |/// @brief Copy the contents of \a From to \a To. 333| |/// 334| |/// @param From The path to copy from. 335| |/// @param To The path to copy to. This is created. 336| |std::error_code copy_file(const Twine &From, const Twine &To); 337| | 338| |/// @brief Resize path to size. File is resized as if by POSIX truncate(). 339| |/// 340| |/// @param FD Input file descriptor. 341| |/// @param Size Size to resize to. 342| |/// @returns errc::success if \a path has been resized to \a size, otherwise a 343| |/// platform-specific error_code. 344| |std::error_code resize_file(int FD, uint64_t Size); 345| | 346| |/// @} 347| |/// @name Physical Observers 348| |/// @{ 349| | 350| |/// @brief Does file exist? 351| |/// 352| |/// @param status A file_status previously returned from stat. 353| |/// @returns True if the file represented by status exists, false if it does 354| |/// not. 355| |bool exists(file_status status); 356| | 357| |enum class AccessMode { Exist, Write, Execute }; 358| | 359| |/// @brief Can the file be accessed? 360| |/// 361| |/// @param Path Input path. 362| |/// @returns errc::success if the path can be accessed, otherwise a 363| |/// platform-specific error_code. 364| |std::error_code access(const Twine &Path, AccessMode Mode); 365| | 366| |/// @brief Does file exist? 367| |/// 368| |/// @param Path Input path. 369| |/// @returns True if it exists, false otherwise. 370| 0|inline bool exists(const Twine &Path) { 371| 0| return !access(Path, AccessMode::Exist); 372| 0|} 373| | 374| |/// @brief Can we execute this file? 375| |/// 376| |/// @param Path Input path. 377| |/// @returns True if we can execute it, false otherwise. 378| 0|inline bool can_execute(const Twine &Path) { 379| 0| return !access(Path, AccessMode::Execute); 380| 0|} 381| | 382| |/// @brief Can we write this file? 383| |/// 384| |/// @param Path Input path. 385| |/// @returns True if we can write to it, false otherwise. 386| 0|inline bool can_write(const Twine &Path) { 387| 0| return !access(Path, AccessMode::Write); 388| 0|} 389| | 390| |/// @brief Do file_status's represent the same thing? 391| |/// 392| |/// @param A Input file_status. 393| |/// @param B Input file_status. 394| |/// 395| |/// assert(status_known(A) || status_known(B)); 396| |/// 397| |/// @returns True if A and B both represent the same file system entity, false 398| |/// otherwise. 399| |bool equivalent(file_status A, file_status B); 400| | 401| |/// @brief Do paths represent the same thing? 402| |/// 403| |/// assert(status_known(A) || status_known(B)); 404| |/// 405| |/// @param A Input path A. 406| |/// @param B Input path B. 407| |/// @param result Set to true if stat(A) and stat(B) have the same device and 408| |/// inode (or equivalent). 409| |/// @returns errc::success if result has been successfully set, otherwise a 410| |/// platform-specific error_code. 411| |std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 412| | 413| |/// @brief Simpler version of equivalent for clients that don't need to 414| |/// differentiate between an error and false. 415| 0|inline bool equivalent(const Twine &A, const Twine &B) { 416| 0| bool result; 417| 0| return !equivalent(A, B, result) && result; 418| 0|} 419| | 420| |/// @brief Does status represent a directory? 421| |/// 422| |/// @param status A file_status previously returned from status. 423| |/// @returns status.type() == file_type::directory_file. 424| |bool is_directory(file_status status); 425| | 426| |/// @brief Is path a directory? 427| |/// 428| |/// @param path Input path. 429| |/// @param result Set to true if \a path is a directory, false if it is not. 430| |/// Undefined otherwise. 431| |/// @returns errc::success if result has been successfully set, otherwise a 432| |/// platform-specific error_code. 433| |std::error_code is_directory(const Twine &path, bool &result); 434| | 435| |/// @brief Simpler version of is_directory for clients that don't need to 436| |/// differentiate between an error and false. 437| 0|inline bool is_directory(const Twine &Path) { 438| 0| bool Result; 439| 0| return !is_directory(Path, Result) && Result; 440| 0|} 441| | 442| |/// @brief Does status represent a regular file? 443| |/// 444| |/// @param status A file_status previously returned from status. 445| |/// @returns status_known(status) && status.type() == file_type::regular_file. 446| |bool is_regular_file(file_status status); 447| | 448| |/// @brief Is path a regular file? 449| |/// 450| |/// @param path Input path. 451| |/// @param result Set to true if \a path is a regular file, false if it is not. 452| |/// Undefined otherwise. 453| |/// @returns errc::success if result has been successfully set, otherwise a 454| |/// platform-specific error_code. 455| |std::error_code is_regular_file(const Twine &path, bool &result); 456| | 457| |/// @brief Simpler version of is_regular_file for clients that don't need to 458| |/// differentiate between an error and false. 459| 0|inline bool is_regular_file(const Twine &Path) { 460| 0| bool Result; 461| 0| if (is_regular_file(Path, Result)) 462| 0| return false; 463| 0| return Result; 464| 0|} 465| | 466| |/// @brief Does this status represent something that exists but is not a 467| |/// directory, regular file, or symlink? 468| |/// 469| |/// @param status A file_status previously returned from status. 470| |/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 471| |bool is_other(file_status status); 472| | 473| |/// @brief Is path something that exists but is not a directory, 474| |/// regular file, or symlink? 475| |/// 476| |/// @param path Input path. 477| |/// @param result Set to true if \a path exists, but is not a directory, regular 478| |/// file, or a symlink, false if it does not. Undefined otherwise. 479| |/// @returns errc::success if result has been successfully set, otherwise a 480| |/// platform-specific error_code. 481| |std::error_code is_other(const Twine &path, bool &result); 482| | 483| |/// @brief Get file status as if by POSIX stat(). 484| |/// 485| |/// @param path Input path. 486| |/// @param result Set to the file status. 487| |/// @returns errc::success if result has been successfully set, otherwise a 488| |/// platform-specific error_code. 489| |std::error_code status(const Twine &path, file_status &result); 490| | 491| |/// @brief A version for when a file descriptor is already available. 492| |std::error_code status(int FD, file_status &Result); 493| | 494| |/// @brief Get file size. 495| |/// 496| |/// @param Path Input path. 497| |/// @param Result Set to the size of the file in \a Path. 498| |/// @returns errc::success if result has been successfully set, otherwise a 499| |/// platform-specific error_code. 500| 0|inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 501| 0| file_status Status; 502| 0| std::error_code EC = status(Path, Status); 503| 0| if (EC) 504| 0| return EC; 505| 0| Result = Status.getSize(); 506| 0| return std::error_code(); 507| 0|} 508| | 509| |/// @brief Set the file modification and access time. 510| |/// 511| |/// @returns errc::success if the file times were successfully set, otherwise a 512| |/// platform-specific error_code or errc::function_not_supported on 513| |/// platforms where the functionality isn't available. 514| |std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); 515| | 516| |/// @brief Is status available? 517| |/// 518| |/// @param s Input file status. 519| |/// @returns True if status() != status_error. 520| |bool status_known(file_status s); 521| | 522| |/// @brief Is status available? 523| |/// 524| |/// @param path Input path. 525| |/// @param result Set to true if status() != status_error. 526| |/// @returns errc::success if result has been successfully set, otherwise a 527| |/// platform-specific error_code. 528| |std::error_code status_known(const Twine &path, bool &result); 529| | 530| |/// @brief Create a uniquely named file. 531| |/// 532| |/// Generates a unique path suitable for a temporary file and then opens it as a 533| |/// file. The name is based on \a model with '%' replaced by a random char in 534| |/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 535| |/// directory will be prepended. 536| |/// 537| |/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 538| |/// 539| |/// This is an atomic operation. Either the file is created and opened, or the 540| |/// file system is left untouched. 541| |/// 542| |/// The intendend use is for files that are to be kept, possibly after 543| |/// renaming them. For example, when running 'clang -c foo.o', the file can 544| |/// be first created as foo-abc123.o and then renamed. 545| |/// 546| |/// @param Model Name to base unique path off of. 547| |/// @param ResultFD Set to the opened file's file descriptor. 548| |/// @param ResultPath Set to the opened file's absolute path. 549| |/// @returns errc::success if Result{FD,Path} have been successfully set, 550| |/// otherwise a platform-specific error_code. 551| |std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 552| | SmallVectorImpl &ResultPath, 553| | unsigned Mode = all_read | all_write); 554| | 555| |/// @brief Simpler version for clients that don't want an open file. 556| |std::error_code createUniqueFile(const Twine &Model, 557| | SmallVectorImpl &ResultPath); 558| | 559| |/// @brief Create a file in the system temporary directory. 560| |/// 561| |/// The filename is of the form prefix-random_chars.suffix. Since the directory 562| |/// is not know to the caller, Prefix and Suffix cannot have path separators. 563| |/// The files are created with mode 0600. 564| |/// 565| |/// This should be used for things like a temporary .s that is removed after 566| |/// running the assembler. 567| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 568| | int &ResultFD, 569| | SmallVectorImpl &ResultPath); 570| | 571| |/// @brief Simpler version for clients that don't want an open file. 572| |std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 573| | SmallVectorImpl &ResultPath); 574| | 575| |std::error_code createUniqueDirectory(const Twine &Prefix, 576| | SmallVectorImpl &ResultPath); 577| | 578| |enum OpenFlags : unsigned { 579| | F_None = 0, 580| | 581| | /// F_Excl - When opening a file, this flag makes raw_fd_ostream 582| | /// report an error if the file already exists. 583| | F_Excl = 1, 584| | 585| | /// F_Append - When opening a file, if it already exists append to the 586| | /// existing file instead of returning an error. This may not be specified 587| | /// with F_Excl. 588| | F_Append = 2, 589| | 590| | /// The file should be opened in text mode on platforms that make this 591| | /// distinction. 592| | F_Text = 4, 593| | 594| | /// Open the file for read and write. 595| | F_RW = 8 596| |}; 597| | 598| 0|inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 599| 0| return OpenFlags(unsigned(A) | unsigned(B)); 600| 0|} 601| | 602| 0|inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 603| 0| A = A | B; 604| 0| return A; 605| 0|} 606| | 607| |std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 608| | OpenFlags Flags, unsigned Mode = 0666); 609| | 610| |std::error_code openFileForRead(const Twine &Name, int &ResultFD); 611| | 612| |/// @brief Identify the type of a binary file based on how magical it is. 613| |file_magic identify_magic(StringRef magic); 614| | 615| |/// @brief Get and identify \a path's type based on its content. 616| |/// 617| |/// @param path Input path. 618| |/// @param result Set to the type of file, or file_magic::unknown. 619| |/// @returns errc::success if result has been successfully set, otherwise a 620| |/// platform-specific error_code. 621| |std::error_code identify_magic(const Twine &path, file_magic &result); 622| | 623| |std::error_code getUniqueID(const Twine Path, UniqueID &Result); 624| | 625| |/// This class represents a memory mapped file. It is based on 626| |/// boost::iostreams::mapped_file. 627| |class mapped_file_region { 628| | mapped_file_region() = delete; 629| | mapped_file_region(mapped_file_region&) = delete; 630| | mapped_file_region &operator =(mapped_file_region&) = delete; 631| | 632| |public: 633| | enum mapmode { 634| | readonly, ///< May only access map via const_data as read only. 635| | readwrite, ///< May access map via data and modify it. Written to path. 636| | priv ///< May modify via data, but changes are lost on destruction. 637| | }; 638| | 639| |private: 640| | /// Platform-specific mapping state. 641| | uint64_t Size; 642| | void *Mapping; 643| | 644| | std::error_code init(int FD, uint64_t Offset, mapmode Mode); 645| | 646| |public: 647| | /// \param fd An open file descriptor to map. mapped_file_region takes 648| | /// ownership if closefd is true. It must have been opended in the correct 649| | /// mode. 650| | mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, 651| | std::error_code &ec); 652| | 653| | ~mapped_file_region(); 654| | 655| | uint64_t size() const; 656| | char *data() const; 657| | 658| | /// Get a const view of the data. Modifying this memory has undefined 659| | /// behavior. 660| | const char *const_data() const; 661| | 662| | /// \returns The minimum alignment offset must be. 663| | static int alignment(); 664| |}; 665| | 666| |/// Return the path to the main executable, given the value of argv[0] from 667| |/// program startup and the address of main itself. In extremis, this function 668| |/// may fail and return an empty path. 669| |std::string getMainExecutable(const char *argv0, void *MainExecAddr); 670| | 671| |/// @} 672| |/// @name Iterators 673| |/// @{ 674| | 675| |/// directory_entry - A single entry in a directory. Caches the status either 676| |/// from the result of the iteration syscall, or the first time status is 677| |/// called. 678| |class directory_entry { 679| | std::string Path; 680| | mutable file_status Status; 681| | 682| |public: 683| | explicit directory_entry(const Twine &path, file_status st = file_status()) 684| | : Path(path.str()) 685| 0| , Status(st) {} 686| | 687| 0| directory_entry() {} 688| | 689| 0| void assign(const Twine &path, file_status st = file_status()) { 690| 0| Path = path.str(); 691| 0| Status = st; 692| 0| } 693| | 694| | void replace_filename(const Twine &filename, file_status st = file_status()); 695| | 696| | const std::string &path() const { return Path; } 697| | std::error_code status(file_status &result) const; 698| | 699| | bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 700| 0| bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 701| | bool operator< (const directory_entry& rhs) const; 702| | bool operator<=(const directory_entry& rhs) const; 703| | bool operator> (const directory_entry& rhs) const; 704| | bool operator>=(const directory_entry& rhs) const; 705| |}; 706| | 707| |namespace detail { 708| | struct DirIterState; 709| | 710| | std::error_code directory_iterator_construct(DirIterState &, StringRef); 711| | std::error_code directory_iterator_increment(DirIterState &); 712| | std::error_code directory_iterator_destruct(DirIterState &); 713| | 714| | /// DirIterState - Keeps state for the directory_iterator. It is reference 715| | /// counted in order to preserve InputIterator semantics on copy. 716| | struct DirIterState : public RefCountedBase { 717| | DirIterState() 718| 0| : IterationHandle(0) {} 719| | 720| 0| ~DirIterState() { 721| 0| directory_iterator_destruct(*this); 722| 0| } 723| | 724| | intptr_t IterationHandle; 725| | directory_entry CurrentEntry; 726| | }; 727| |} 728| | 729| |/// directory_iterator - Iterates through the entries in path. There is no 730| |/// operator++ because we need an error_code. If it's really needed we can make 731| |/// it call report_fatal_error on error. 732| |class directory_iterator { 733| | IntrusiveRefCntPtr State; 734| | 735| |public: 736| 0| explicit directory_iterator(const Twine &path, std::error_code &ec) { 737| 0| State = new detail::DirIterState; 738| 0| SmallString<128> path_storage; 739| 0| ec = detail::directory_iterator_construct(*State, 740| 0| path.toStringRef(path_storage)); 741| 0| } 742| | 743| 0| explicit directory_iterator(const directory_entry &de, std::error_code &ec) { 744| 0| State = new detail::DirIterState; 745| 0| ec = detail::directory_iterator_construct(*State, de.path()); 746| 0| } 747| | 748| | /// Construct end iterator. 749| 0| directory_iterator() : State(nullptr) {} 750| | 751| | // No operator++ because we need error_code. 752| | directory_iterator &increment(std::error_code &ec) { 753| | ec = directory_iterator_increment(*State); 754| | return *this; 755| | } 756| | 757| 0| const directory_entry &operator*() const { return State->CurrentEntry; } 758| | const directory_entry *operator->() const { return &State->CurrentEntry; } 759| | 760| | bool operator==(const directory_iterator &RHS) const { 761| | if (State == RHS.State) 762| | return true; 763| | if (!RHS.State) 764| | return State->CurrentEntry == directory_entry(); 765| | if (!State) 766| | return RHS.State->CurrentEntry == directory_entry(); 767| | return State->CurrentEntry == RHS.State->CurrentEntry; 768| | } 769| | 770| | bool operator!=(const directory_iterator &RHS) const { 771| | return !(*this == RHS); 772| | } 773| | // Other members as required by 774| | // C++ Std, 24.1.1 Input iterators [input.iterators] 775| |}; 776| | 777| |namespace detail { 778| | /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 779| | /// reference counted in order to preserve InputIterator semantics on copy. 780| | struct RecDirIterState : public RefCountedBase { 781| | RecDirIterState() 782| | : Level(0) 783| 0| , HasNoPushRequest(false) {} 784| | 785| | std::stack > Stack; 786| | uint16_t Level; 787| | bool HasNoPushRequest; 788| | }; 789| |} 790| | 791| |/// recursive_directory_iterator - Same as directory_iterator except for it 792| |/// recurses down into child directories. 793| |class recursive_directory_iterator { 794| | IntrusiveRefCntPtr State; 795| | 796| |public: 797| 0| recursive_directory_iterator() {} 798| | explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) 799| 0| : State(new detail::RecDirIterState) { 800| 0| State->Stack.push(directory_iterator(path, ec)); 801| 0| if (State->Stack.top() == directory_iterator()) 802| 0| State.reset(); 803| 0| } 804| | // No operator++ because we need error_code. 805| 0| recursive_directory_iterator &increment(std::error_code &ec) { 806| 0| const directory_iterator end_itr; 807| 0| 808| 0| if (State->HasNoPushRequest) 809| 0| State->HasNoPushRequest = false; 810| 0| else { 811| 0| file_status st; 812| 0| if ((ec = State->Stack.top()->status(st))) return *this; 813| 0| if (is_directory(st)) { 814| 0| State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 815| 0| if (ec) return *this; 816| 0| if (State->Stack.top() != end_itr) { 817| 0| ++State->Level; 818| 0| return *this; 819| 0| } 820| 0| State->Stack.pop(); 821| 0| } 822| 0| } 823| 0| 824| 0| while (!State->Stack.empty() 825| 0| && State->Stack.top().increment(ec) == end_itr) { 826| 0| State->Stack.pop(); 827| 0| --State->Level; 828| 0| } 829| 0| 830| 0| // Check if we are done. If so, create an end iterator. 831| 0| if (State->Stack.empty()) 832| 0| State.reset(); 833| 0| 834| 0| return *this; 835| 0| } 836| | 837| 0| const directory_entry &operator*() const { return *State->Stack.top(); } 838| 0| const directory_entry *operator->() const { return &*State->Stack.top(); } 839| | 840| | // observers 841| | /// Gets the current level. Starting path is at level 0. 842| 0| int level() const { return State->Level; } 843| | 844| | /// Returns true if no_push has been called for this directory_entry. 845| 0| bool no_push_request() const { return State->HasNoPushRequest; } 846| | 847| | // modifiers 848| | /// Goes up one level if Level > 0. 849| 0| void pop() { 850| 0| assert(State && "Cannot pop an end iterator!"); 851| 0| assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 852| 0| 853| 0| const directory_iterator end_itr; 854| 0| std::error_code ec; 855| 0| do { 856| 0| if (ec) 857| 0| report_fatal_error("Error incrementing directory iterator."); 858| 0| State->Stack.pop(); 859| 0| --State->Level; 860| 0| } while (!State->Stack.empty() 861| 0| && State->Stack.top().increment(ec) == end_itr); 862| 0| 863| 0| // Check if we are done. If so, create an end iterator. 864| 0| if (State->Stack.empty()) 865| 0| State.reset(); 866| 0| } 867| | 868| | /// Does not go down into the current directory_entry. 869| 0| void no_push() { State->HasNoPushRequest = true; } 870| | 871| 0| bool operator==(const recursive_directory_iterator &RHS) const { 872| 0| return State == RHS.State; 873| 0| } 874| | 875| 0| bool operator!=(const recursive_directory_iterator &RHS) const { 876| 0| return !(*this == RHS); 877| 0| } 878| | // Other members as required by 879| | // C++ Std, 24.1.1 Input iterators [input.iterators] 880| |}; 881| | 882| |/// @} 883| | 884| |} // end namespace fs 885| |} // end namespace sys 886| |} // end namespace llvm 887| | 888| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/FileUtilities.h: 1| |//===- llvm/Support/FileUtilities.h - File System Utilities -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines a family of utility functions which are useful for doing 11| |// various things with files. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_FILEUTILITIES_H 16| |#define LLVM_SUPPORT_FILEUTILITIES_H 17| | 18| |#include "llvm/Support/FileSystem.h" 19| |#include "llvm/Support/Path.h" 20| | 21| |namespace llvm { 22| | 23| | /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if 24| | /// the files match, 1 if they are different, and 2 if there is a file error. 25| | /// This function allows you to specify an absolute and relative FP error that 26| | /// is allowed to exist. If you specify a string to fill in for the error 27| | /// option, it will set the string to an error message if an error occurs, or 28| | /// if the files are different. 29| | /// 30| | int DiffFilesWithTolerance(StringRef FileA, 31| | StringRef FileB, 32| | double AbsTol, double RelTol, 33| | std::string *Error = nullptr); 34| | 35| | 36| | /// FileRemover - This class is a simple object meant to be stack allocated. 37| | /// If an exception is thrown from a region, the object removes the filename 38| | /// specified (if deleteIt is true). 39| | /// 40| | class FileRemover { 41| | SmallString<128> Filename; 42| | bool DeleteIt; 43| | public: 44| 0| FileRemover() : DeleteIt(false) {} 45| | 46| | explicit FileRemover(const Twine& filename, bool deleteIt = true) 47| 0| : DeleteIt(deleteIt) { 48| 0| filename.toVector(Filename); 49| 0| } 50| | 51| 0| ~FileRemover() { 52| 0| if (DeleteIt) { 53| 0| // Ignore problems deleting the file. 54| 0| sys::fs::remove(Filename.str()); 55| 0| } 56| 0| } 57| | 58| | /// setFile - Give ownership of the file to the FileRemover so it will 59| | /// be removed when the object is destroyed. If the FileRemover already 60| | /// had ownership of a file, remove it first. 61| 0| void setFile(const Twine& filename, bool deleteIt = true) { 62| 0| if (DeleteIt) { 63| 0| // Ignore problems deleting the file. 64| 0| sys::fs::remove(Filename.str()); 65| 0| } 66| 0| 67| 0| Filename.clear(); 68| 0| filename.toVector(Filename); 69| 0| DeleteIt = deleteIt; 70| 0| } 71| | 72| | /// releaseFile - Take ownership of the file away from the FileRemover so it 73| | /// will not be removed when the object is destroyed. 74| 0| void releaseFile() { DeleteIt = false; } 75| | }; 76| |} // End llvm namespace 77| | 78| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Format.h: 1| |//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file implements the format() function, which can be used with other 11| |// LLVM subsystems to provide printf-style formatting. This gives all the power 12| |// and risk of printf. This can be used like this (with raw_ostreams as an 13| |// example): 14| |// 15| |// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; 16| |// 17| |// Or if you prefer: 18| |// 19| |// OS << format("mynumber: %4.5f\n", 1234.412); 20| |// 21| |//===----------------------------------------------------------------------===// 22| | 23| |#ifndef LLVM_SUPPORT_FORMAT_H 24| |#define LLVM_SUPPORT_FORMAT_H 25| | 26| |#include "llvm/ADT/STLExtras.h" 27| |#include "llvm/ADT/StringRef.h" 28| |#include "llvm/Support/DataTypes.h" 29| |#include 30| |#include 31| |#include 32| | 33| |namespace llvm { 34| | 35| |/// This is a helper class used for handling formatted output. It is the 36| |/// abstract base class of a templated derived class. 37| |class format_object_base { 38| |protected: 39| | const char *Fmt; 40| | ~format_object_base() = default; // Disallow polymorphic deletion. 41| | format_object_base(const format_object_base &) = default; 42| | virtual void home(); // Out of line virtual method. 43| | 44| | /// Call snprintf() for this object, on the given buffer and size. 45| | virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; 46| | 47| |public: 48| 0| format_object_base(const char *fmt) : Fmt(fmt) {} 49| | 50| | /// Format the object into the specified buffer. On success, this returns 51| | /// the length of the formatted string. If the buffer is too small, this 52| | /// returns a length to retry with, which will be larger than BufferSize. 53| 0| unsigned print(char *Buffer, unsigned BufferSize) const { 54| 0| assert(BufferSize && "Invalid buffer size!"); 55| 0| 56| 0| // Print the string, leaving room for the terminating null. 57| 0| int N = snprint(Buffer, BufferSize); 58| 0| 59| 0| // VC++ and old GlibC return negative on overflow, just double the size. 60| 0| if (N < 0) 61| 0| return BufferSize * 2; 62| 0| 63| 0| // Other implementations yield number of bytes needed, not including the 64| 0| // final '\0'. 65| 0| if (unsigned(N) >= BufferSize) 66| 0| return N + 1; 67| 0| 68| 0| // Otherwise N is the length of output (not including the final '\0'). 69| 0| return N; 70| 0| } 71| |}; 72| | 73| |/// These are templated helper classes used by the format function that 74| |/// capture the object to be formated and the format string. When actually 75| |/// printed, this synthesizes the string into a temporary buffer provided and 76| |/// returns whether or not it is big enough. 77| | 78| |template 79| |class format_object final : public format_object_base { 80| | std::tuple Vals; 81| | 82| | template 83| | int snprint_tuple(char *Buffer, unsigned BufferSize, 84| 0| index_sequence) const { 85| |#ifdef _MSC_VER 86| | return _snprintf(Buffer, BufferSize, Fmt, std::get(Vals)...); 87| |#else 88| | return snprintf(Buffer, BufferSize, Fmt, std::get(Vals)...); 89| 0|#endif 90| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiPvEE13snprint_tupleIJLm0ELm1EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJPKcEE13snprint_tupleIJLm0EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJPKcPvEE13snprint_tupleIJLm0ELm1EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiEE13snprint_tupleIJLm0EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiPKcEE13snprint_tupleIJLm0ELm1EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJimEE13snprint_tupleIJLm0ELm1EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJjEE13snprint_tupleIJLm0EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJdEE13snprint_tupleIJLm0EEEEiPcjNS_14index_sequenceIJXspT_EEEE ------------------ 91| | 92| |public: 93| | format_object(const char *fmt, const Ts &... vals) 94| 0| : format_object_base(fmt), Vals(vals...) {} ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJiPvEEC2EPKcRKiRKS1_ ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJPKcEEC2ES2_RKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJPKcPvEEC2ES2_RKS2_RKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJiEEC2EPKcRKi ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJiPKcEEC2ES2_RKiRKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJimEEC2EPKcRKiRKm ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJjEEC2EPKcRKj ------------------ | Unexecuted instantiation: _ZN4llvm13format_objectIJdEEC2EPKcRKd ------------------ 95| | 96| 0| int snprint(char *Buffer, unsigned BufferSize) const override { 97| 0| return snprint_tuple(Buffer, BufferSize, index_sequence_for()); 98| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiPvEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJPKcEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJPKcPvEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJiPKcEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJimEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJjEE7snprintEPcj ------------------ | Unexecuted instantiation: _ZNK4llvm13format_objectIJdEE7snprintEPcj ------------------ 99| |}; 100| | 101| |/// These are helper functions used to produce formatted output. They use 102| |/// template type deduction to construct the appropriate instance of the 103| |/// format_object class to simplify their construction. 104| |/// 105| |/// This is typically used like: 106| |/// \code 107| |/// OS << format("%0.4f", myfloat) << '\n'; 108| |/// \endcode 109| | 110| |template 111| 0|inline format_object format(const char *Fmt, const Ts &... Vals) { 112| 0| return format_object(Fmt, Vals...); 113| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJiPvEEENS_13format_objectIJDpT_EEEPKcDpRKS3_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJPKcEEENS_13format_objectIJDpT_EEES2_DpRKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJPKcPvEEENS_13format_objectIJDpT_EEES2_DpRKS5_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJiEEENS_13format_objectIJDpT_EEEPKcDpRKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJiPKcEEENS_13format_objectIJDpT_EEES2_DpRKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJimEEENS_13format_objectIJDpT_EEEPKcDpRKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJjEEENS_13format_objectIJDpT_EEEPKcDpRKS2_ ------------------ | Unexecuted instantiation: _ZN4llvm6formatIJdEEENS_13format_objectIJDpT_EEEPKcDpRKS2_ ------------------ 114| | 115| |/// This is a helper class used for left_justify() and right_justify(). 116| |class FormattedString { 117| | StringRef Str; 118| | unsigned Width; 119| | bool RightJustify; 120| | friend class raw_ostream; 121| |public: 122| | FormattedString(StringRef S, unsigned W, bool R) 123| 0| : Str(S), Width(W), RightJustify(R) { } 124| |}; 125| | 126| |/// left_justify - append spaces after string so total output is 127| |/// \p Width characters. If \p Str is larger that \p Width, full string 128| |/// is written with no padding. 129| 0|inline FormattedString left_justify(StringRef Str, unsigned Width) { 130| 0| return FormattedString(Str, Width, false); 131| 0|} 132| | 133| |/// right_justify - add spaces before string so total output is 134| |/// \p Width characters. If \p Str is larger that \p Width, full string 135| |/// is written with no padding. 136| 0|inline FormattedString right_justify(StringRef Str, unsigned Width) { 137| 0| return FormattedString(Str, Width, true); 138| 0|} 139| | 140| |/// This is a helper class used for format_hex() and format_decimal(). 141| |class FormattedNumber { 142| | uint64_t HexValue; 143| | int64_t DecValue; 144| | unsigned Width; 145| | bool Hex; 146| | bool Upper; 147| | bool HexPrefix; 148| | friend class raw_ostream; 149| |public: 150| | FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, 151| | bool Prefix) 152| | : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), 153| 0| HexPrefix(Prefix) {} 154| |}; 155| | 156| |/// format_hex - Output \p N as a fixed width hexadecimal. If number will not 157| |/// fit in width, full number is still printed. Examples: 158| |/// OS << format_hex(255, 4) => 0xff 159| |/// OS << format_hex(255, 4, true) => 0xFF 160| |/// OS << format_hex(255, 6) => 0x00ff 161| |/// OS << format_hex(255, 2) => 0xff 162| |inline FormattedNumber format_hex(uint64_t N, unsigned Width, 163| 0| bool Upper = false) { 164| 0| assert(Width <= 18 && "hex width must be <= 18"); 165| 0| return FormattedNumber(N, 0, Width, true, Upper, true); 166| 0|} 167| | 168| |/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not 169| |/// prepend '0x' to the outputted string. If number will not fit in width, 170| |/// full number is still printed. Examples: 171| |/// OS << format_hex_no_prefix(255, 4) => ff 172| |/// OS << format_hex_no_prefix(255, 4, true) => FF 173| |/// OS << format_hex_no_prefix(255, 6) => 00ff 174| |/// OS << format_hex_no_prefix(255, 2) => ff 175| |inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, 176| 0| bool Upper = false) { 177| 0| assert(Width <= 18 && "hex width must be <= 18"); 178| 0| return FormattedNumber(N, 0, Width, true, Upper, false); 179| 0|} 180| | 181| |/// format_decimal - Output \p N as a right justified, fixed-width decimal. If 182| |/// number will not fit in width, full number is still printed. Examples: 183| |/// OS << format_decimal(0, 5) => " 0" 184| |/// OS << format_decimal(255, 5) => " 255" 185| |/// OS << format_decimal(-1, 3) => " -1" 186| |/// OS << format_decimal(12345, 3) => "12345" 187| 0|inline FormattedNumber format_decimal(int64_t N, unsigned Width) { 188| 0| return FormattedNumber(0, N, Width, false, false, false); 189| 0|} 190| | 191| | 192| |} // end namespace llvm 193| | 194| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/ManagedStatic.h: 1| |//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the ManagedStatic class and the llvm_shutdown() function. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H 15| |#define LLVM_SUPPORT_MANAGEDSTATIC_H 16| | 17| |#include "llvm/Support/Atomic.h" 18| |#include "llvm/Support/Threading.h" 19| |#include "llvm/Support/Valgrind.h" 20| | 21| |namespace llvm { 22| | 23| |/// object_creator - Helper method for ManagedStatic. 24| |template 25| 0|void* object_creator() { 26| 0| return new C(); 27| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm14object_creatorINSt3__16vectorINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS6_IS8_EEEEEEPvv ------------------ | Unexecuted instantiation: _ZN4llvm14object_creatorINS_3sys10SmartMutexILb0EEEEEPvv ------------------ | Unexecuted instantiation: _ZN4llvm14object_creatorINSt3__16vectorINS1_4pairIPFvPvES4_EENS1_9allocatorIS7_EEEEEES4_v ------------------ | Unexecuted instantiation: _ZN4llvm14object_creatorINS_3sys10SmartMutexILb1EEEEEPvv ------------------ 28| | 29| |/// object_deleter - Helper method for ManagedStatic. 30| |/// 31| |template struct object_deleter { 32| 0| static void call(void * Ptr) { delete (T*)Ptr; } ------------------ | Unexecuted instantiation: _ZN4llvm14object_deleterINSt3__16vectorINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS6_IS8_EEEEE4callEPv ------------------ | Unexecuted instantiation: _ZN4llvm14object_deleterINS_3sys10SmartMutexILb0EEEE4callEPv ------------------ | Unexecuted instantiation: _ZN4llvm14object_deleterINSt3__16vectorINS1_4pairIPFvPvES4_EENS1_9allocatorIS7_EEEEE4callES4_ ------------------ | Unexecuted instantiation: _ZN4llvm14object_deleterINS_3sys10SmartMutexILb1EEEE4callEPv ------------------ 33| |}; 34| |template struct object_deleter { 35| | static void call(void * Ptr) { delete[] (T*)Ptr; } 36| |}; 37| | 38| |/// ManagedStaticBase - Common base class for ManagedStatic instances. 39| |class ManagedStaticBase { 40| |protected: 41| | // This should only be used as a static variable, which guarantees that this 42| | // will be zero initialized. 43| | mutable void *Ptr; 44| | mutable void (*DeleterFn)(void*); 45| | mutable const ManagedStaticBase *Next; 46| | 47| | void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; 48| |public: 49| | /// isConstructed - Return true if this object has not been created yet. 50| 0| bool isConstructed() const { return Ptr != nullptr; } 51| | 52| | void destroy() const; 53| |}; 54| | 55| |/// ManagedStatic - This transparently changes the behavior of global statics to 56| |/// be lazily constructed on demand (good for reducing startup times of dynamic 57| |/// libraries that link in LLVM components) and for making destruction be 58| |/// explicit through the llvm_shutdown() function call. 59| |/// 60| |template 61| |class ManagedStatic : public ManagedStaticBase { 62| |public: 63| | 64| | // Accessors. 65| 0| C &operator*() { 66| 0| void* tmp = Ptr; 67| 0| if (llvm_is_multithreaded()) sys::MemoryFence(); 68| 0| if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); 69| 0| TsanHappensAfter(this); 70| 0| 71| 0| return *static_cast(Ptr); 72| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINSt3__16vectorINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS6_IS8_EEEEEdeEv ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINS_3sys10SmartMutexILb0EEEEdeEv ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINSt3__16vectorINS1_4pairIPFvPvES4_EENS1_9allocatorIS7_EEEEEdeEv ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINS_3sys10SmartMutexILb1EEEEdeEv ------------------ 73| 0| C *operator->() { 74| 0| void* tmp = Ptr; 75| 0| if (llvm_is_multithreaded()) sys::MemoryFence(); 76| 0| if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); 77| 0| TsanHappensAfter(this); 78| 0| 79| 0| return static_cast(Ptr); 80| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINSt3__16vectorINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS6_IS8_EEEEEptEv ------------------ | Unexecuted instantiation: _ZN4llvm13ManagedStaticINSt3__16vectorINS1_4pairIPFvPvES4_EENS1_9allocatorIS7_EEEEEptEv ------------------ 81| | const C &operator*() const { 82| | void* tmp = Ptr; 83| | if (llvm_is_multithreaded()) sys::MemoryFence(); 84| | if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); 85| | TsanHappensAfter(this); 86| | 87| | return *static_cast(Ptr); 88| | } 89| | const C *operator->() const { 90| | void* tmp = Ptr; 91| | if (llvm_is_multithreaded()) sys::MemoryFence(); 92| | if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); 93| | TsanHappensAfter(this); 94| | 95| | return static_cast(Ptr); 96| | } 97| |}; 98| | 99| |/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 100| |void llvm_shutdown(); 101| | 102| |/// llvm_shutdown_obj - This is a simple helper class that calls 103| |/// llvm_shutdown() when it is destroyed. 104| |struct llvm_shutdown_obj { 105| 0| llvm_shutdown_obj() { } 106| 0| ~llvm_shutdown_obj() { llvm_shutdown(); } 107| |}; 108| | 109| |} 110| | 111| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MathExtras.h: 1| |//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains some functions that are useful for math stuff. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MATHEXTRAS_H 15| |#define LLVM_SUPPORT_MATHEXTRAS_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/SwapByteOrder.h" 19| |#include 20| |#include 21| |#include 22| | 23| |#ifdef _MSC_VER 24| |#include 25| |#endif 26| | 27| |namespace llvm { 28| |/// \brief The behavior an operation has on an input of 0. 29| |enum ZeroBehavior { 30| | /// \brief The returned value is undefined. 31| | ZB_Undefined, 32| | /// \brief The returned value is numeric_limits::max() 33| | ZB_Max, 34| | /// \brief The returned value is numeric_limits::digits 35| | ZB_Width 36| |}; 37| | 38| |namespace detail { 39| |template struct TrailingZerosCounter { 40| | static std::size_t count(T Val, ZeroBehavior) { 41| | if (!Val) 42| | return std::numeric_limits::digits; 43| | if (Val & 0x1) 44| | return 0; 45| | 46| | // Bisection method. 47| | std::size_t ZeroBits = 0; 48| | T Shift = std::numeric_limits::digits >> 1; 49| | T Mask = std::numeric_limits::max() >> Shift; 50| | while (Shift) { 51| | if ((Val & Mask) == 0) { 52| | Val >>= Shift; 53| | ZeroBits |= Shift; 54| | } 55| | Shift >>= 1; 56| | Mask >>= Shift; 57| | } 58| | return ZeroBits; 59| | } 60| |}; 61| | 62| |#if __GNUC__ >= 4 || _MSC_VER 63| |template struct TrailingZerosCounter { 64| | static std::size_t count(T Val, ZeroBehavior ZB) { 65| | if (ZB != ZB_Undefined && Val == 0) 66| | return 32; 67| | 68| |#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) 69| | return __builtin_ctz(Val); 70| |#elif _MSC_VER 71| | unsigned long Index; 72| | _BitScanForward(&Index, Val); 73| | return Index; 74| |#endif 75| | } 76| |}; 77| | 78| |#if !defined(_MSC_VER) || defined(_M_X64) 79| |template struct TrailingZerosCounter { 80| | static std::size_t count(T Val, ZeroBehavior ZB) { 81| | if (ZB != ZB_Undefined && Val == 0) 82| | return 64; 83| | 84| |#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) 85| | return __builtin_ctzll(Val); 86| |#elif _MSC_VER 87| | unsigned long Index; 88| | _BitScanForward64(&Index, Val); 89| | return Index; 90| |#endif 91| | } 92| |}; 93| |#endif 94| |#endif 95| |} // namespace detail 96| | 97| |/// \brief Count number of 0's from the least significant bit to the most 98| |/// stopping at the first 1. 99| |/// 100| |/// Only unsigned integral types are allowed. 101| |/// 102| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 103| |/// valid arguments. 104| |template 105| |std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 106| | static_assert(std::numeric_limits::is_integer && 107| | !std::numeric_limits::is_signed, 108| | "Only unsigned integral types are allowed."); 109| | return detail::TrailingZerosCounter::count(Val, ZB); 110| |} 111| | 112| |namespace detail { 113| |template struct LeadingZerosCounter { 114| | static std::size_t count(T Val, ZeroBehavior) { 115| | if (!Val) 116| | return std::numeric_limits::digits; 117| | 118| | // Bisection method. 119| | std::size_t ZeroBits = 0; 120| | for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) { 121| | T Tmp = Val >> Shift; 122| | if (Tmp) 123| | Val = Tmp; 124| | else 125| | ZeroBits |= Shift; 126| | } 127| | return ZeroBits; 128| | } 129| |}; 130| | 131| |#if __GNUC__ >= 4 || _MSC_VER 132| |template struct LeadingZerosCounter { 133| 0| static std::size_t count(T Val, ZeroBehavior ZB) { 134| 0| if (ZB != ZB_Undefined && Val == 0) 135| 0| return 32; 136| 0| 137| 0|#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) 138| 0| return __builtin_clz(Val); 139| |#elif _MSC_VER 140| | unsigned long Index; 141| | _BitScanReverse(&Index, Val); 142| | return Index ^ 31; 143| |#endif 144| | } 145| |}; 146| | 147| |#if !defined(_MSC_VER) || defined(_M_X64) 148| |template struct LeadingZerosCounter { 149| 0| static std::size_t count(T Val, ZeroBehavior ZB) { 150| 0| if (ZB != ZB_Undefined && Val == 0) 151| 0| return 64; 152| 0| 153| 0|#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) 154| 0| return __builtin_clzll(Val); 155| |#elif _MSC_VER 156| | unsigned long Index; 157| | _BitScanReverse64(&Index, Val); 158| | return Index ^ 63; 159| |#endif 160| | } 161| |}; 162| |#endif 163| |#endif 164| |} // namespace detail 165| | 166| |/// \brief Count number of 0's from the most significant bit to the least 167| |/// stopping at the first 1. 168| |/// 169| |/// Only unsigned integral types are allowed. 170| |/// 171| |/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are 172| |/// valid arguments. 173| |template 174| 0|std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { 175| 0| static_assert(std::numeric_limits::is_integer && 176| 0| !std::numeric_limits::is_signed, 177| 0| "Only unsigned integral types are allowed."); 178| 0| return detail::LeadingZerosCounter::count(Val, ZB); 179| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm17countLeadingZerosIjEEmT_NS_12ZeroBehaviorE ------------------ | Unexecuted instantiation: _ZN4llvm17countLeadingZerosIyEEmT_NS_12ZeroBehaviorE ------------------ 180| | 181| |/// \brief Get the index of the first set bit starting from the least 182| |/// significant bit. 183| |/// 184| |/// Only unsigned integral types are allowed. 185| |/// 186| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 187| |/// valid arguments. 188| |template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { 189| | if (ZB == ZB_Max && Val == 0) 190| | return std::numeric_limits::max(); 191| | 192| | return countTrailingZeros(Val, ZB_Undefined); 193| |} 194| | 195| |/// \brief Get the index of the last set bit starting from the least 196| |/// significant bit. 197| |/// 198| |/// Only unsigned integral types are allowed. 199| |/// 200| |/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are 201| |/// valid arguments. 202| |template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { 203| | if (ZB == ZB_Max && Val == 0) 204| | return std::numeric_limits::max(); 205| | 206| | // Use ^ instead of - because both gcc and llvm can remove the associated ^ 207| | // in the __builtin_clz intrinsic on x86. 208| | return countLeadingZeros(Val, ZB_Undefined) ^ 209| | (std::numeric_limits::digits - 1); 210| |} 211| | 212| |/// \brief Macro compressed bit reversal table for 256 bits. 213| |/// 214| |/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable 215| |static const unsigned char BitReverseTable256[256] = { 216| |#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 217| |#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) 218| |#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) 219| | R6(0), R6(2), R6(1), R6(3) 220| |#undef R2 221| |#undef R4 222| |#undef R6 223| |}; 224| | 225| |/// \brief Reverse the bits in \p Val. 226| |template 227| |T reverseBits(T Val) { 228| | unsigned char in[sizeof(Val)]; 229| | unsigned char out[sizeof(Val)]; 230| | std::memcpy(in, &Val, sizeof(Val)); 231| | for (unsigned i = 0; i < sizeof(Val); ++i) 232| | out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; 233| | std::memcpy(&Val, out, sizeof(Val)); 234| | return Val; 235| |} 236| | 237| |// NOTE: The following support functions use the _32/_64 extensions instead of 238| |// type overloading so that signed and unsigned integers can be used without 239| |// ambiguity. 240| | 241| |/// Hi_32 - This function returns the high 32 bits of a 64 bit value. 242| 0|inline uint32_t Hi_32(uint64_t Value) { 243| 0| return static_cast(Value >> 32); 244| 0|} 245| | 246| |/// Lo_32 - This function returns the low 32 bits of a 64 bit value. 247| 0|inline uint32_t Lo_32(uint64_t Value) { 248| 0| return static_cast(Value); 249| 0|} 250| | 251| |/// Make_64 - This functions makes a 64-bit integer from a high / low pair of 252| |/// 32-bit integers. 253| 0|inline uint64_t Make_64(uint32_t High, uint32_t Low) { 254| 0| return ((uint64_t)High << 32) | (uint64_t)Low; 255| 0|} 256| | 257| |/// isInt - Checks if an integer fits into the given bit width. 258| |template 259| |inline bool isInt(int64_t x) { 260| | return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 261| |} 262| |// Template specializations to get better code for common cases. 263| |template<> 264| 0|inline bool isInt<8>(int64_t x) { 265| 0| return static_cast(x) == x; 266| 0|} 267| |template<> 268| 0|inline bool isInt<16>(int64_t x) { 269| 0| return static_cast(x) == x; 270| 0|} 271| |template<> 272| 0|inline bool isInt<32>(int64_t x) { 273| 0| return static_cast(x) == x; 274| 0|} 275| | 276| |/// isShiftedInt - Checks if a signed integer is an N bit number shifted 277| |/// left by S. 278| |template 279| |inline bool isShiftedInt(int64_t x) { 280| | return isInt(x) && (x % (1< 285| |inline bool isUInt(uint64_t x) { 286| | return N >= 64 || x < (UINT64_C(1)<<(N)); 287| |} 288| |// Template specializations to get better code for common cases. 289| |template<> 290| 0|inline bool isUInt<8>(uint64_t x) { 291| 0| return static_cast(x) == x; 292| 0|} 293| |template<> 294| 0|inline bool isUInt<16>(uint64_t x) { 295| 0| return static_cast(x) == x; 296| 0|} 297| |template<> 298| 0|inline bool isUInt<32>(uint64_t x) { 299| 0| return static_cast(x) == x; 300| 0|} 301| | 302| |/// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted 303| |/// left by S. 304| |template 305| |inline bool isShiftedUInt(uint64_t x) { 306| | return isUInt(x) && (x % (1<> (64 - N))); 313| 0|} 314| | 315| |/// isIntN - Checks if an signed integer fits into the given (dynamic) 316| |/// bit width. 317| 0|inline bool isIntN(unsigned N, int64_t x) { 318| 0| return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); 319| 0|} 320| | 321| |/// isMask_32 - This function returns true if the argument is a sequence of ones 322| |/// starting at the least significant bit with the remainder zero (32 bit 323| |/// version). Ex. isMask_32(0x0000FFFFU) == true. 324| 0|inline bool isMask_32(uint32_t Value) { 325| 0| return Value && ((Value + 1) & Value) == 0; 326| 0|} 327| | 328| |/// isMask_64 - This function returns true if the argument is a sequence of ones 329| |/// starting at the least significant bit with the remainder zero (64 bit 330| |/// version). 331| 0|inline bool isMask_64(uint64_t Value) { 332| 0| return Value && ((Value + 1) & Value) == 0; 333| 0|} 334| | 335| |/// isShiftedMask_32 - This function returns true if the argument contains a 336| |/// sequence of ones with the remainder zero (32 bit version.) 337| |/// Ex. isShiftedMask_32(0x0000FF00U) == true. 338| 0|inline bool isShiftedMask_32(uint32_t Value) { 339| 0| return isMask_32((Value - 1) | Value); 340| 0|} 341| | 342| |/// isShiftedMask_64 - This function returns true if the argument contains a 343| |/// sequence of ones with the remainder zero (64 bit version.) 344| 0|inline bool isShiftedMask_64(uint64_t Value) { 345| 0| return isMask_64((Value - 1) | Value); 346| 0|} 347| | 348| |/// isPowerOf2_32 - This function returns true if the argument is a power of 349| |/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) 350| 0|inline bool isPowerOf2_32(uint32_t Value) { 351| 0| return Value && !(Value & (Value - 1)); 352| 0|} 353| | 354| |/// isPowerOf2_64 - This function returns true if the argument is a power of two 355| |/// > 0 (64 bit edition.) 356| 0|inline bool isPowerOf2_64(uint64_t Value) { 357| 0| return Value && !(Value & (Value - int64_t(1L))); 358| 0|} 359| | 360| |/// ByteSwap_16 - This function returns a byte-swapped representation of the 361| |/// 16-bit argument, Value. 362| 0|inline uint16_t ByteSwap_16(uint16_t Value) { 363| 0| return sys::SwapByteOrder_16(Value); 364| 0|} 365| | 366| |/// ByteSwap_32 - This function returns a byte-swapped representation of the 367| |/// 32-bit argument, Value. 368| 0|inline uint32_t ByteSwap_32(uint32_t Value) { 369| 0| return sys::SwapByteOrder_32(Value); 370| 0|} 371| | 372| |/// ByteSwap_64 - This function returns a byte-swapped representation of the 373| |/// 64-bit argument, Value. 374| 0|inline uint64_t ByteSwap_64(uint64_t Value) { 375| 0| return sys::SwapByteOrder_64(Value); 376| 0|} 377| | 378| |/// \brief Count the number of ones from the most significant bit to the first 379| |/// zero bit. 380| |/// 381| |/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. 382| |/// Only unsigned integral types are allowed. 383| |/// 384| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 385| |/// ZB_Undefined are valid arguments. 386| |template 387| |std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 388| | static_assert(std::numeric_limits::is_integer && 389| | !std::numeric_limits::is_signed, 390| | "Only unsigned integral types are allowed."); 391| | return countLeadingZeros(~Value, ZB); 392| |} 393| | 394| |/// \brief Count the number of ones from the least significant bit to the first 395| |/// zero bit. 396| |/// 397| |/// Ex. countTrailingOnes(0x00FF00FF) == 8. 398| |/// Only unsigned integral types are allowed. 399| |/// 400| |/// \param ZB the behavior on an input of all ones. Only ZB_Width and 401| |/// ZB_Undefined are valid arguments. 402| |template 403| |std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { 404| | static_assert(std::numeric_limits::is_integer && 405| | !std::numeric_limits::is_signed, 406| | "Only unsigned integral types are allowed."); 407| | return countTrailingZeros(~Value, ZB); 408| |} 409| | 410| |namespace detail { 411| |template struct PopulationCounter { 412| | static unsigned count(T Value) { 413| | // Generic version, forward to 32 bits. 414| | static_assert(SizeOfT <= 4, "Not implemented!"); 415| |#if __GNUC__ >= 4 416| | return __builtin_popcount(Value); 417| |#else 418| | uint32_t v = Value; 419| | v = v - ((v >> 1) & 0x55555555); 420| | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 421| | return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 422| |#endif 423| | } 424| |}; 425| | 426| |template struct PopulationCounter { 427| | static unsigned count(T Value) { 428| |#if __GNUC__ >= 4 429| | return __builtin_popcountll(Value); 430| |#else 431| | uint64_t v = Value; 432| | v = v - ((v >> 1) & 0x5555555555555555ULL); 433| | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 434| | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 435| | return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); 436| |#endif 437| | } 438| |}; 439| |} // namespace detail 440| | 441| |/// \brief Count the number of set bits in a value. 442| |/// Ex. countPopulation(0xF000F000) = 8 443| |/// Returns 0 if the word is zero. 444| |template 445| |inline unsigned countPopulation(T Value) { 446| | static_assert(std::numeric_limits::is_integer && 447| | !std::numeric_limits::is_signed, 448| | "Only unsigned integral types are allowed."); 449| | return detail::PopulationCounter::count(Value); 450| |} 451| | 452| |/// Log2_32 - This function returns the floor log base 2 of the specified value, 453| |/// -1 if the value is zero. (32 bit edition.) 454| |/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 455| 0|inline unsigned Log2_32(uint32_t Value) { 456| 0| return 31 - countLeadingZeros(Value); 457| 0|} 458| | 459| |/// Log2_64 - This function returns the floor log base 2 of the specified value, 460| |/// -1 if the value is zero. (64 bit edition.) 461| 0|inline unsigned Log2_64(uint64_t Value) { 462| 0| return 63 - countLeadingZeros(Value); 463| 0|} 464| | 465| |/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified 466| |/// value, 32 if the value is zero. (32 bit edition). 467| |/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 468| 0|inline unsigned Log2_32_Ceil(uint32_t Value) { 469| 0| return 32 - countLeadingZeros(Value - 1); 470| 0|} 471| | 472| |/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified 473| |/// value, 64 if the value is zero. (64 bit edition.) 474| 0|inline unsigned Log2_64_Ceil(uint64_t Value) { 475| 0| return 64 - countLeadingZeros(Value - 1); 476| 0|} 477| | 478| |/// GreatestCommonDivisor64 - Return the greatest common divisor of the two 479| |/// values using Euclid's algorithm. 480| 0|inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { 481| 0| while (B) { 482| 0| uint64_t T = B; 483| 0| B = A % B; 484| 0| A = T; 485| 0| } 486| 0| return A; 487| 0|} 488| | 489| |/// BitsToDouble - This function takes a 64-bit integer and returns the bit 490| |/// equivalent double. 491| 0|inline double BitsToDouble(uint64_t Bits) { 492| 0| union { 493| 0| uint64_t L; 494| 0| double D; 495| 0| } T; 496| 0| T.L = Bits; 497| 0| return T.D; 498| 0|} 499| | 500| |/// BitsToFloat - This function takes a 32-bit integer and returns the bit 501| |/// equivalent float. 502| 0|inline float BitsToFloat(uint32_t Bits) { 503| 0| union { 504| 0| uint32_t I; 505| 0| float F; 506| 0| } T; 507| 0| T.I = Bits; 508| 0| return T.F; 509| 0|} 510| | 511| |/// DoubleToBits - This function takes a double and returns the bit 512| |/// equivalent 64-bit integer. Note that copying doubles around 513| |/// changes the bits of NaNs on some hosts, notably x86, so this 514| |/// routine cannot be used if these bits are needed. 515| 0|inline uint64_t DoubleToBits(double Double) { 516| 0| union { 517| 0| uint64_t L; 518| 0| double D; 519| 0| } T; 520| 0| T.D = Double; 521| 0| return T.L; 522| 0|} 523| | 524| |/// FloatToBits - This function takes a float and returns the bit 525| |/// equivalent 32-bit integer. Note that copying floats around 526| |/// changes the bits of NaNs on some hosts, notably x86, so this 527| |/// routine cannot be used if these bits are needed. 528| 0|inline uint32_t FloatToBits(float Float) { 529| 0| union { 530| 0| uint32_t I; 531| 0| float F; 532| 0| } T; 533| 0| T.F = Float; 534| 0| return T.I; 535| 0|} 536| | 537| |/// MinAlign - A and B are either alignments or offsets. Return the minimum 538| |/// alignment that may be assumed after adding the two together. 539| 0|inline uint64_t MinAlign(uint64_t A, uint64_t B) { 540| 0| // The largest power of 2 that divides both A and B. 541| 0| // 542| 0| // Replace "-Value" by "1+~Value" in the following commented code to avoid 543| 0| // MSVC warning C4146 544| 0| // return (A | B) & -(A | B); 545| 0| return (A | B) & (1 + ~(A | B)); 546| 0|} 547| | 548| |/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. 549| |/// 550| |/// Alignment should be a power of two. This method rounds up, so 551| |/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. 552| 0|inline uintptr_t alignAddr(void *Addr, size_t Alignment) { 553| 0| assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && 554| 0| "Alignment is not a power of two!"); 555| 0| 556| 0| assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); 557| 0| 558| 0| return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); 559| 0|} 560| | 561| |/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment 562| |/// bytes, rounding up. 563| 0|inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { 564| 0| return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; 565| 0|} 566| | 567| |/// NextPowerOf2 - Returns the next power of two (in 64-bits) 568| |/// that is strictly greater than A. Returns zero on overflow. 569| 0|inline uint64_t NextPowerOf2(uint64_t A) { 570| 0| A |= (A >> 1); 571| 0| A |= (A >> 2); 572| 0| A |= (A >> 4); 573| 0| A |= (A >> 8); 574| 0| A |= (A >> 16); 575| 0| A |= (A >> 32); 576| 0| return A + 1; 577| 0|} 578| | 579| |/// Returns the power of two which is less than or equal to the given value. 580| |/// Essentially, it is a floor operation across the domain of powers of two. 581| 0|inline uint64_t PowerOf2Floor(uint64_t A) { 582| 0| if (!A) return 0; 583| 0| return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); 584| 0|} 585| | 586| |/// Returns the next integer (mod 2**64) that is greater than or equal to 587| |/// \p Value and is a multiple of \p Align. \p Align must be non-zero. 588| |/// 589| |/// Examples: 590| |/// \code 591| |/// RoundUpToAlignment(5, 8) = 8 592| |/// RoundUpToAlignment(17, 8) = 24 593| |/// RoundUpToAlignment(~0LL, 8) = 0 594| |/// RoundUpToAlignment(321, 255) = 510 595| |/// \endcode 596| 0|inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { 597| 0| return (Value + Align - 1) / Align * Align; 598| 0|} 599| | 600| |/// Returns the offset to the next integer (mod 2**64) that is greater than 601| |/// or equal to \p Value and is a multiple of \p Align. \p Align must be 602| |/// non-zero. 603| 0|inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { 604| 0| return RoundUpToAlignment(Value, Align) - Value; 605| 0|} 606| | 607| |/// SignExtend32 - Sign extend B-bit number x to 32-bit int. 608| |/// Usage int32_t r = SignExtend32<5>(x); 609| |template inline int32_t SignExtend32(uint32_t x) { 610| | return int32_t(x << (32 - B)) >> (32 - B); 611| |} 612| | 613| |/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. 614| |/// Requires 0 < B <= 32. 615| 0|inline int32_t SignExtend32(uint32_t X, unsigned B) { 616| 0| return int32_t(X << (32 - B)) >> (32 - B); 617| 0|} 618| | 619| |/// SignExtend64 - Sign extend B-bit number x to 64-bit int. 620| |/// Usage int64_t r = SignExtend64<5>(x); 621| |template inline int64_t SignExtend64(uint64_t x) { 622| | return int64_t(x << (64 - B)) >> (64 - B); 623| |} 624| | 625| |/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. 626| |/// Requires 0 < B <= 64. 627| 0|inline int64_t SignExtend64(uint64_t X, unsigned B) { 628| 0| return int64_t(X << (64 - B)) >> (64 - B); 629| 0|} 630| | 631| |extern const float huge_valf; 632| |} // End llvm namespace 633| | 634| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Memory.h: 1| |//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Memory class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORY_H 15| |#define LLVM_SUPPORT_MEMORY_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| | /// This class encapsulates the notion of a memory block which has an address 25| | /// and a size. It is used by the Memory class (a friend) as the result of 26| | /// various memory allocation operations. 27| | /// @see Memory 28| | /// @brief Memory block abstraction. 29| | class MemoryBlock { 30| | public: 31| 0| MemoryBlock() : Address(nullptr), Size(0) { } 32| 0| MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } 33| 0| void *base() const { return Address; } 34| 0| size_t size() const { return Size; } 35| | private: 36| | void *Address; ///< Address of first byte of memory area 37| | size_t Size; ///< Size, in bytes of the memory area 38| | friend class Memory; 39| | }; 40| | 41| | /// This class provides various memory handling functions that manipulate 42| | /// MemoryBlock instances. 43| | /// @since 1.4 44| | /// @brief An abstraction for memory operations. 45| | class Memory { 46| | public: 47| | enum ProtectionFlags { 48| | MF_READ = 0x1000000, 49| | MF_WRITE = 0x2000000, 50| | MF_EXEC = 0x4000000 51| | }; 52| | 53| | /// This method allocates a block of memory that is suitable for loading 54| | /// dynamically generated code (e.g. JIT). An attempt to allocate 55| | /// \p NumBytes bytes of virtual memory is made. 56| | /// \p NearBlock may point to an existing allocation in which case 57| | /// an attempt is made to allocate more memory near the existing block. 58| | /// The actual allocated address is not guaranteed to be near the requested 59| | /// address. 60| | /// \p Flags is used to set the initial protection flags for the block 61| | /// of the memory. 62| | /// \p EC [out] returns an object describing any error that occurs. 63| | /// 64| | /// This method may allocate more than the number of bytes requested. The 65| | /// actual number of bytes allocated is indicated in the returned 66| | /// MemoryBlock. 67| | /// 68| | /// The start of the allocated block must be aligned with the 69| | /// system allocation granularity (64K on Windows, page size on Linux). 70| | /// If the address following \p NearBlock is not so aligned, it will be 71| | /// rounded up to the next allocation granularity boundary. 72| | /// 73| | /// \r a non-null MemoryBlock if the function was successful, 74| | /// otherwise a null MemoryBlock is with \p EC describing the error. 75| | /// 76| | /// @brief Allocate mapped memory. 77| | static MemoryBlock allocateMappedMemory(size_t NumBytes, 78| | const MemoryBlock *const NearBlock, 79| | unsigned Flags, 80| | std::error_code &EC); 81| | 82| | /// This method releases a block of memory that was allocated with the 83| | /// allocateMappedMemory method. It should not be used to release any 84| | /// memory block allocated any other way. 85| | /// \p Block describes the memory to be released. 86| | /// 87| | /// \r error_success if the function was successful, or an error_code 88| | /// describing the failure if an error occurred. 89| | /// 90| | /// @brief Release mapped memory. 91| | static std::error_code releaseMappedMemory(MemoryBlock &Block); 92| | 93| | /// This method sets the protection flags for a block of memory to the 94| | /// state specified by /p Flags. The behavior is not specified if the 95| | /// memory was not allocated using the allocateMappedMemory method. 96| | /// \p Block describes the memory block to be protected. 97| | /// \p Flags specifies the new protection state to be assigned to the block. 98| | /// \p ErrMsg [out] returns a string describing any error that occurred. 99| | /// 100| | /// If \p Flags is MF_WRITE, the actual behavior varies 101| | /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the 102| | /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 103| | /// 104| | /// \r error_success if the function was successful, or an error_code 105| | /// describing the failure if an error occurred. 106| | /// 107| | /// @brief Set memory protection state. 108| | static std::error_code protectMappedMemory(const MemoryBlock &Block, 109| | unsigned Flags); 110| | 111| | /// This method allocates a block of Read/Write/Execute memory that is 112| | /// suitable for executing dynamically generated code (e.g. JIT). An 113| | /// attempt to allocate \p NumBytes bytes of virtual memory is made. 114| | /// \p NearBlock may point to an existing allocation in which case 115| | /// an attempt is made to allocate more memory near the existing block. 116| | /// 117| | /// On success, this returns a non-null memory block, otherwise it returns 118| | /// a null memory block and fills in *ErrMsg. 119| | /// 120| | /// @brief Allocate Read/Write/Execute memory. 121| | static MemoryBlock AllocateRWX(size_t NumBytes, 122| | const MemoryBlock *NearBlock, 123| | std::string *ErrMsg = nullptr); 124| | 125| | /// This method releases a block of Read/Write/Execute memory that was 126| | /// allocated with the AllocateRWX method. It should not be used to 127| | /// release any memory block allocated any other way. 128| | /// 129| | /// On success, this returns false, otherwise it returns true and fills 130| | /// in *ErrMsg. 131| | /// @brief Release Read/Write/Execute memory. 132| | static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); 133| | 134| | 135| | /// InvalidateInstructionCache - Before the JIT can run a block of code 136| | /// that has been emitted it must invalidate the instruction cache on some 137| | /// platforms. 138| | static void InvalidateInstructionCache(const void *Addr, size_t Len); 139| | 140| | /// setExecutable - Before the JIT can run a block of code, it has to be 141| | /// given read and executable privilege. Return true if it is already r-x 142| | /// or the system is able to change its previlege. 143| | static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); 144| | 145| | /// setWritable - When adding to a block of code, the JIT may need 146| | /// to mark a block of code as RW since the protections are on page 147| | /// boundaries, and the JIT internal allocations are not page aligned. 148| | static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); 149| | 150| | /// setRangeExecutable - Mark the page containing a range of addresses 151| | /// as executable. 152| | static bool setRangeExecutable(const void *Addr, size_t Size); 153| | 154| | /// setRangeWritable - Mark the page containing a range of addresses 155| | /// as writable. 156| | static bool setRangeWritable(const void *Addr, size_t Size); 157| | }; 158| |} 159| |} 160| | 161| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MemoryBuffer.h: 1| |//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the MemoryBuffer interface. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MEMORYBUFFER_H 15| |#define LLVM_SUPPORT_MEMORYBUFFER_H 16| | 17| |#include "llvm/ADT/Twine.h" 18| |#include "llvm/Support/CBindingWrapping.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include "llvm/Support/ErrorOr.h" 22| |#include 23| |#include 24| | 25| |namespace llvm { 26| |class MemoryBufferRef; 27| | 28| |/// This interface provides simple read-only access to a block of memory, and 29| |/// provides simple methods for reading files and standard input into a memory 30| |/// buffer. In addition to basic access to the characters in the file, this 31| |/// interface guarantees you can read one character past the end of the file, 32| |/// and that this character will read as '\0'. 33| |/// 34| |/// The '\0' guarantee is needed to support an optimization -- it's intended to 35| |/// be more efficient for clients which are reading all the data to stop 36| |/// reading when they encounter a '\0' than to continually check the file 37| |/// position to see if it has reached the end of the file. 38| |class MemoryBuffer { 39| | const char *BufferStart; // Start of the buffer. 40| | const char *BufferEnd; // End of the buffer. 41| | 42| | MemoryBuffer(const MemoryBuffer &) = delete; 43| | MemoryBuffer &operator=(const MemoryBuffer &) = delete; 44| |protected: 45| 0| MemoryBuffer() {} 46| | void init(const char *BufStart, const char *BufEnd, 47| | bool RequiresNullTerminator); 48| |public: 49| | virtual ~MemoryBuffer(); 50| | 51| 0| const char *getBufferStart() const { return BufferStart; } 52| 0| const char *getBufferEnd() const { return BufferEnd; } 53| 0| size_t getBufferSize() const { return BufferEnd-BufferStart; } 54| | 55| 0| StringRef getBuffer() const { 56| 0| return StringRef(BufferStart, getBufferSize()); 57| 0| } 58| | 59| | /// Return an identifier for this buffer, typically the filename it was read 60| | /// from. 61| 0| virtual const char *getBufferIdentifier() const { 62| 0| return "Unknown buffer"; 63| 0| } 64| | 65| | /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer 66| | /// if successful, otherwise returning null. If FileSize is specified, this 67| | /// means that the client knows that the file exists and that it has the 68| | /// specified size. 69| | /// 70| | /// \param IsVolatileSize Set to true to indicate that the file size may be 71| | /// changing, e.g. when libclang tries to parse while the user is 72| | /// editing/updating the file. 73| | static ErrorOr> 74| | getFile(const Twine &Filename, int64_t FileSize = -1, 75| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 76| | 77| | /// Given an already-open file descriptor, map some slice of it into a 78| | /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. 79| | /// Since this is in the middle of a file, the buffer is not null terminated. 80| | static ErrorOr> 81| | getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, 82| | int64_t Offset); 83| | 84| | /// Given an already-open file descriptor, read the file and return a 85| | /// MemoryBuffer. 86| | /// 87| | /// \param IsVolatileSize Set to true to indicate that the file size may be 88| | /// changing, e.g. when libclang tries to parse while the user is 89| | /// editing/updating the file. 90| | static ErrorOr> 91| | getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, 92| | bool RequiresNullTerminator = true, bool IsVolatileSize = false); 93| | 94| | /// Open the specified memory range as a MemoryBuffer. Note that InputData 95| | /// must be null terminated if RequiresNullTerminator is true. 96| | static std::unique_ptr 97| | getMemBuffer(StringRef InputData, StringRef BufferName = "", 98| | bool RequiresNullTerminator = true); 99| | 100| | static std::unique_ptr 101| | getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); 102| | 103| | /// Open the specified memory range as a MemoryBuffer, copying the contents 104| | /// and taking ownership of it. InputData does not have to be null terminated. 105| | static std::unique_ptr 106| | getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); 107| | 108| | /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note 109| | /// that the caller need not initialize the memory allocated by this method. 110| | /// The memory is owned by the MemoryBuffer object. 111| | static std::unique_ptr 112| | getNewMemBuffer(size_t Size, StringRef BufferName = ""); 113| | 114| | /// Allocate a new MemoryBuffer of the specified size that is not initialized. 115| | /// Note that the caller should initialize the memory allocated by this 116| | /// method. The memory is owned by the MemoryBuffer object. 117| | static std::unique_ptr 118| | getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); 119| | 120| | /// Read all of stdin into a file buffer, and return it. 121| | static ErrorOr> getSTDIN(); 122| | 123| | /// Open the specified file as a MemoryBuffer, or open stdin if the Filename 124| | /// is "-". 125| | static ErrorOr> 126| | getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1); 127| | 128| | /// Map a subrange of the the specified file as a MemoryBuffer. 129| | static ErrorOr> 130| | getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); 131| | 132| | //===--------------------------------------------------------------------===// 133| | // Provided for performance analysis. 134| | //===--------------------------------------------------------------------===// 135| | 136| | /// The kind of memory backing used to support the MemoryBuffer. 137| | enum BufferKind { 138| | MemoryBuffer_Malloc, 139| | MemoryBuffer_MMap 140| | }; 141| | 142| | /// Return information on the memory mechanism used to support the 143| | /// MemoryBuffer. 144| | virtual BufferKind getBufferKind() const = 0; 145| | 146| | MemoryBufferRef getMemBufferRef() const; 147| |}; 148| | 149| |class MemoryBufferRef { 150| | StringRef Buffer; 151| | StringRef Identifier; 152| | 153| |public: 154| 0| MemoryBufferRef() {} 155| | MemoryBufferRef(StringRef Buffer, StringRef Identifier) 156| 0| : Buffer(Buffer), Identifier(Identifier) {} 157| | 158| 0| StringRef getBuffer() const { return Buffer; } 159| | 160| 0| StringRef getBufferIdentifier() const { return Identifier; } 161| | 162| 0| const char *getBufferStart() const { return Buffer.begin(); } 163| 0| const char *getBufferEnd() const { return Buffer.end(); } 164| 0| size_t getBufferSize() const { return Buffer.size(); } 165| |}; 166| | 167| |// Create wrappers for C Binding types (see CBindingWrapping.h). 168| |typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; 169| |DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) 170| | 171| |} // end namespace llvm 172| | 173| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Mutex.h: 1| |//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::Mutex class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_MUTEX_H 15| |#define LLVM_SUPPORT_MUTEX_H 16| | 17| |#include "llvm/Support/Compiler.h" 18| |#include "llvm/Support/Threading.h" 19| |#include 20| | 21| |namespace llvm 22| |{ 23| | namespace sys 24| | { 25| | /// @brief Platform agnostic Mutex class. 26| | class MutexImpl 27| | { 28| | /// @name Constructors 29| | /// @{ 30| | public: 31| | 32| | /// Initializes the lock but doesn't acquire it. if \p recursive is set 33| | /// to false, the lock will not be recursive which makes it cheaper but 34| | /// also more likely to deadlock (same thread can't acquire more than 35| | /// once). 36| | /// @brief Default Constructor. 37| | explicit MutexImpl(bool recursive = true); 38| | 39| | /// Releases and removes the lock 40| | /// @brief Destructor 41| | ~MutexImpl(); 42| | 43| | /// @} 44| | /// @name Methods 45| | /// @{ 46| | public: 47| | 48| | /// Attempts to unconditionally acquire the lock. If the lock is held by 49| | /// another thread, this method will wait until it can acquire the lock. 50| | /// @returns false if any kind of error occurs, true otherwise. 51| | /// @brief Unconditionally acquire the lock. 52| | bool acquire(); 53| | 54| | /// Attempts to release the lock. If the lock is held by the current 55| | /// thread, the lock is released allowing other threads to acquire the 56| | /// lock. 57| | /// @returns false if any kind of error occurs, true otherwise. 58| | /// @brief Unconditionally release the lock. 59| | bool release(); 60| | 61| | /// Attempts to acquire the lock without blocking. If the lock is not 62| | /// available, this function returns false quickly (without blocking). If 63| | /// the lock is available, it is acquired. 64| | /// @returns false if any kind of error occurs or the lock is not 65| | /// available, true otherwise. 66| | /// @brief Try to acquire the lock. 67| | bool tryacquire(); 68| | 69| | //@} 70| | /// @name Platform Dependent Data 71| | /// @{ 72| | private: 73| | void* data_; ///< We don't know what the data will be 74| | 75| | /// @} 76| | /// @name Do Not Implement 77| | /// @{ 78| | private: 79| | MutexImpl(const MutexImpl &) = delete; 80| | void operator=(const MutexImpl &) = delete; 81| | /// @} 82| | }; 83| | 84| | 85| | /// SmartMutex - A mutex with a compile time constant parameter that 86| | /// indicates whether this mutex should become a no-op when we're not 87| | /// running in multithreaded mode. 88| | template 89| | class SmartMutex { 90| | MutexImpl impl; 91| | unsigned acquired; 92| | bool recursive; 93| | public: 94| | explicit SmartMutex(bool rec = true) : 95| 0| impl(rec), acquired(0), recursive(rec) { } ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb0EEC2Eb ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb1EEC2Eb ------------------ 96| | 97| 0| bool lock() { 98| 0| if (!mt_only || llvm_is_multithreaded()) { 99| 0| return impl.acquire(); 100| 0| } else { 101| 0| // Single-threaded debugging code. This would be racy in 102| 0| // multithreaded mode, but provides not sanity checks in single 103| 0| // threaded mode. 104| 0| assert((recursive || acquired == 0) && "Lock already acquired!!"); 105| 0| ++acquired; 106| 0| return true; 107| 0| } 108| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb0EE4lockEv ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb1EE4lockEv ------------------ 109| | 110| 0| bool unlock() { 111| 0| if (!mt_only || llvm_is_multithreaded()) { 112| 0| return impl.release(); 113| 0| } else { 114| 0| // Single-threaded debugging code. This would be racy in 115| 0| // multithreaded mode, but provides not sanity checks in single 116| 0| // threaded mode. 117| 0| assert(((recursive && acquired) || (acquired == 1)) && 118| 0| "Lock not acquired before release!"); 119| 0| --acquired; 120| 0| return true; 121| 0| } 122| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb0EE6unlockEv ------------------ | Unexecuted instantiation: _ZN4llvm3sys10SmartMutexILb1EE6unlockEv ------------------ 123| | 124| | bool try_lock() { 125| | if (!mt_only || llvm_is_multithreaded()) 126| | return impl.tryacquire(); 127| | else return true; 128| | } 129| | 130| | private: 131| | SmartMutex(const SmartMutex & original); 132| | void operator=(const SmartMutex &); 133| | }; 134| | 135| | /// Mutex - A standard, always enforced mutex. 136| | typedef SmartMutex Mutex; 137| | 138| | template 139| | class SmartScopedLock { 140| | SmartMutex& mtx; 141| | 142| | public: 143| 0| SmartScopedLock(SmartMutex& m) : mtx(m) { 144| 0| mtx.lock(); 145| 0| } 146| | 147| 0| ~SmartScopedLock() { 148| 0| mtx.unlock(); 149| 0| } 150| | }; 151| | 152| | typedef SmartScopedLock ScopedLock; 153| | } 154| |} 155| | 156| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/MutexGuard.h: 1| |//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines a guard for a block of code that ensures a Mutex is locked 11| |// upon construction and released upon destruction. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_MUTEXGUARD_H 16| |#define LLVM_SUPPORT_MUTEXGUARD_H 17| | 18| |#include "llvm/Support/Mutex.h" 19| | 20| |namespace llvm { 21| | /// Instances of this class acquire a given Mutex Lock when constructed and 22| | /// hold that lock until destruction. The intention is to instantiate one of 23| | /// these on the stack at the top of some scope to be assured that C++ 24| | /// destruction of the object will always release the Mutex and thus avoid 25| | /// a host of nasty multi-threading problems in the face of exceptions, etc. 26| | /// @brief Guard a section of code with a Mutex. 27| | class MutexGuard { 28| | sys::Mutex &M; 29| | MutexGuard(const MutexGuard &) = delete; 30| | void operator=(const MutexGuard &) = delete; 31| | public: 32| 0| MutexGuard(sys::Mutex &m) : M(m) { M.lock(); } 33| 0| ~MutexGuard() { M.unlock(); } 34| | /// holds - Returns true if this locker instance holds the specified lock. 35| | /// This is mostly used in assertions to validate that the correct mutex 36| | /// is held. 37| 0| bool holds(const sys::Mutex& lock) const { return &M == &lock; } 38| | }; 39| |} 40| | 41| |#endif // LLVM_SUPPORT_MUTEXGUARD_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Path.h: 1| |//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the llvm::sys::path namespace. It is designed after 11| |// TR2/boost filesystem (v3), but modified to remove exception handling and the 12| |// path class. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_PATH_H 17| |#define LLVM_SUPPORT_PATH_H 18| | 19| |#include "llvm/ADT/SmallString.h" 20| |#include "llvm/ADT/Twine.h" 21| |#include "llvm/Support/DataTypes.h" 22| |#include 23| | 24| |namespace llvm { 25| |namespace sys { 26| |namespace path { 27| | 28| |/// @name Lexical Component Iterator 29| |/// @{ 30| | 31| |/// @brief Path iterator. 32| |/// 33| |/// This is an input iterator that iterates over the individual components in 34| |/// \a path. The traversal order is as follows: 35| |/// * The root-name element, if present. 36| |/// * The root-directory element, if present. 37| |/// * Each successive filename element, if present. 38| |/// * Dot, if one or more trailing non-root slash characters are present. 39| |/// Traversing backwards is possible with \a reverse_iterator 40| |/// 41| |/// Iteration examples. Each component is separated by ',': 42| |/// @code 43| |/// / => / 44| |/// /foo => /,foo 45| |/// foo/ => foo,. 46| |/// /foo/bar => /,foo,bar 47| |/// ../ => ..,. 48| |/// C:\foo\bar => C:,/,foo,bar 49| |/// @endcode 50| |class const_iterator 51| | : public std::iterator { 52| | StringRef Path; ///< The entire path. 53| | StringRef Component; ///< The current component. Not necessarily in Path. 54| | size_t Position; ///< The iterators current position within Path. 55| | 56| | // An end iterator has Position = Path.size() + 1. 57| | friend const_iterator begin(StringRef path); 58| | friend const_iterator end(StringRef path); 59| | 60| |public: 61| 0| reference operator*() const { return Component; } 62| 0| pointer operator->() const { return &Component; } 63| | const_iterator &operator++(); // preincrement 64| | const_iterator &operator++(int); // postincrement 65| | bool operator==(const const_iterator &RHS) const; 66| 0| bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); } 67| | 68| | /// @brief Difference in bytes between this and RHS. 69| | ptrdiff_t operator-(const const_iterator &RHS) const; 70| |}; 71| | 72| |/// @brief Reverse path iterator. 73| |/// 74| |/// This is an input iterator that iterates over the individual components in 75| |/// \a path in reverse order. The traversal order is exactly reversed from that 76| |/// of \a const_iterator 77| |class reverse_iterator 78| | : public std::iterator { 79| | StringRef Path; ///< The entire path. 80| | StringRef Component; ///< The current component. Not necessarily in Path. 81| | size_t Position; ///< The iterators current position within Path. 82| | 83| | friend reverse_iterator rbegin(StringRef path); 84| | friend reverse_iterator rend(StringRef path); 85| | 86| |public: 87| 0| reference operator*() const { return Component; } 88| 0| pointer operator->() const { return &Component; } 89| | reverse_iterator &operator++(); // preincrement 90| | reverse_iterator &operator++(int); // postincrement 91| | bool operator==(const reverse_iterator &RHS) const; 92| 0| bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } 93| |}; 94| | 95| |/// @brief Get begin iterator over \a path. 96| |/// @param path Input path. 97| |/// @returns Iterator initialized with the first component of \a path. 98| |const_iterator begin(StringRef path); 99| | 100| |/// @brief Get end iterator over \a path. 101| |/// @param path Input path. 102| |/// @returns Iterator initialized to the end of \a path. 103| |const_iterator end(StringRef path); 104| | 105| |/// @brief Get reverse begin iterator over \a path. 106| |/// @param path Input path. 107| |/// @returns Iterator initialized with the first reverse component of \a path. 108| |reverse_iterator rbegin(StringRef path); 109| | 110| |/// @brief Get reverse end iterator over \a path. 111| |/// @param path Input path. 112| |/// @returns Iterator initialized to the reverse end of \a path. 113| |reverse_iterator rend(StringRef path); 114| | 115| |/// @} 116| |/// @name Lexical Modifiers 117| |/// @{ 118| | 119| |/// @brief Remove the last component from \a path unless it is the root dir. 120| |/// 121| |/// @code 122| |/// directory/filename.cpp => directory/ 123| |/// directory/ => directory 124| |/// filename.cpp => 125| |/// / => / 126| |/// @endcode 127| |/// 128| |/// @param path A path that is modified to not have a file component. 129| |void remove_filename(SmallVectorImpl &path); 130| | 131| |/// @brief Replace the file extension of \a path with \a extension. 132| |/// 133| |/// @code 134| |/// ./filename.cpp => ./filename.extension 135| |/// ./filename => ./filename.extension 136| |/// ./ => ./.extension 137| |/// @endcode 138| |/// 139| |/// @param path A path that has its extension replaced with \a extension. 140| |/// @param extension The extension to be added. It may be empty. It may also 141| |/// optionally start with a '.', if it does not, one will be 142| |/// prepended. 143| |void replace_extension(SmallVectorImpl &path, const Twine &extension); 144| | 145| |/// @brief Append to path. 146| |/// 147| |/// @code 148| |/// /foo + bar/f => /foo/bar/f 149| |/// /foo/ + bar/f => /foo/bar/f 150| |/// foo + bar/f => foo/bar/f 151| |/// @endcode 152| |/// 153| |/// @param path Set to \a path + \a component. 154| |/// @param a The component to be appended to \a path. 155| |void append(SmallVectorImpl &path, const Twine &a, 156| | const Twine &b = "", 157| | const Twine &c = "", 158| | const Twine &d = ""); 159| | 160| |/// @brief Append to path. 161| |/// 162| |/// @code 163| |/// /foo + [bar,f] => /foo/bar/f 164| |/// /foo/ + [bar,f] => /foo/bar/f 165| |/// foo + [bar,f] => foo/bar/f 166| |/// @endcode 167| |/// 168| |/// @param path Set to \a path + [\a begin, \a end). 169| |/// @param begin Start of components to append. 170| |/// @param end One past the end of components to append. 171| |void append(SmallVectorImpl &path, 172| | const_iterator begin, const_iterator end); 173| | 174| |/// @} 175| |/// @name Transforms (or some other better name) 176| |/// @{ 177| | 178| |/// Convert path to the native form. This is used to give paths to users and 179| |/// operating system calls in the platform's normal way. For example, on Windows 180| |/// all '/' are converted to '\'. 181| |/// 182| |/// @param path A path that is transformed to native format. 183| |/// @param result Holds the result of the transformation. 184| |void native(const Twine &path, SmallVectorImpl &result); 185| | 186| |/// Convert path to the native form in place. This is used to give paths to 187| |/// users and operating system calls in the platform's normal way. For example, 188| |/// on Windows all '/' are converted to '\'. 189| |/// 190| |/// @param path A path that is transformed to native format. 191| |void native(SmallVectorImpl &path); 192| | 193| |/// @} 194| |/// @name Lexical Observers 195| |/// @{ 196| | 197| |/// @brief Get root name. 198| |/// 199| |/// @code 200| |/// //net/hello => //net 201| |/// c:/hello => c: (on Windows, on other platforms nothing) 202| |/// /hello => 203| |/// @endcode 204| |/// 205| |/// @param path Input path. 206| |/// @result The root name of \a path if it has one, otherwise "". 207| |StringRef root_name(StringRef path); 208| | 209| |/// @brief Get root directory. 210| |/// 211| |/// @code 212| |/// /goo/hello => / 213| |/// c:/hello => / 214| |/// d/file.txt => 215| |/// @endcode 216| |/// 217| |/// @param path Input path. 218| |/// @result The root directory of \a path if it has one, otherwise 219| |/// "". 220| |StringRef root_directory(StringRef path); 221| | 222| |/// @brief Get root path. 223| |/// 224| |/// Equivalent to root_name + root_directory. 225| |/// 226| |/// @param path Input path. 227| |/// @result The root path of \a path if it has one, otherwise "". 228| |StringRef root_path(StringRef path); 229| | 230| |/// @brief Get relative path. 231| |/// 232| |/// @code 233| |/// C:\hello\world => hello\world 234| |/// foo/bar => foo/bar 235| |/// /foo/bar => foo/bar 236| |/// @endcode 237| |/// 238| |/// @param path Input path. 239| |/// @result The path starting after root_path if one exists, otherwise "". 240| |StringRef relative_path(StringRef path); 241| | 242| |/// @brief Get parent path. 243| |/// 244| |/// @code 245| |/// / => 246| |/// /foo => / 247| |/// foo/../bar => foo/.. 248| |/// @endcode 249| |/// 250| |/// @param path Input path. 251| |/// @result The parent path of \a path if one exists, otherwise "". 252| |StringRef parent_path(StringRef path); 253| | 254| |/// @brief Get filename. 255| |/// 256| |/// @code 257| |/// /foo.txt => foo.txt 258| |/// . => . 259| |/// .. => .. 260| |/// / => / 261| |/// @endcode 262| |/// 263| |/// @param path Input path. 264| |/// @result The filename part of \a path. This is defined as the last component 265| |/// of \a path. 266| |StringRef filename(StringRef path); 267| | 268| |/// @brief Get stem. 269| |/// 270| |/// If filename contains a dot but not solely one or two dots, result is the 271| |/// substring of filename ending at (but not including) the last dot. Otherwise 272| |/// it is filename. 273| |/// 274| |/// @code 275| |/// /foo/bar.txt => bar 276| |/// /foo/bar => bar 277| |/// /foo/.txt => 278| |/// /foo/. => . 279| |/// /foo/.. => .. 280| |/// @endcode 281| |/// 282| |/// @param path Input path. 283| |/// @result The stem of \a path. 284| |StringRef stem(StringRef path); 285| | 286| |/// @brief Get extension. 287| |/// 288| |/// If filename contains a dot but not solely one or two dots, result is the 289| |/// substring of filename starting at (and including) the last dot, and ending 290| |/// at the end of \a path. Otherwise "". 291| |/// 292| |/// @code 293| |/// /foo/bar.txt => .txt 294| |/// /foo/bar => 295| |/// /foo/.txt => .txt 296| |/// @endcode 297| |/// 298| |/// @param path Input path. 299| |/// @result The extension of \a path. 300| |StringRef extension(StringRef path); 301| | 302| |/// @brief Check whether the given char is a path separator on the host OS. 303| |/// 304| |/// @param value a character 305| |/// @result true if \a value is a path separator character on the host OS 306| |bool is_separator(char value); 307| | 308| |/// @brief Return the preferred separator for this platform. 309| |/// 310| |/// @result StringRef of the preferred separator, null-terminated. 311| |StringRef get_separator(); 312| | 313| |/// @brief Get the typical temporary directory for the system, e.g., 314| |/// "/var/tmp" or "C:/TEMP" 315| |/// 316| |/// @param erasedOnReboot Whether to favor a path that is erased on reboot 317| |/// rather than one that potentially persists longer. This parameter will be 318| |/// ignored if the user or system has set the typical environment variable 319| |/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. 320| |/// 321| |/// @param result Holds the resulting path name. 322| |void system_temp_directory(bool erasedOnReboot, SmallVectorImpl &result); 323| | 324| |/// @brief Get the user's home directory. 325| |/// 326| |/// @param result Holds the resulting path name. 327| |/// @result True if a home directory is set, false otherwise. 328| |bool home_directory(SmallVectorImpl &result); 329| | 330| |/// @brief Has root name? 331| |/// 332| |/// root_name != "" 333| |/// 334| |/// @param path Input path. 335| |/// @result True if the path has a root name, false otherwise. 336| |bool has_root_name(const Twine &path); 337| | 338| |/// @brief Has root directory? 339| |/// 340| |/// root_directory != "" 341| |/// 342| |/// @param path Input path. 343| |/// @result True if the path has a root directory, false otherwise. 344| |bool has_root_directory(const Twine &path); 345| | 346| |/// @brief Has root path? 347| |/// 348| |/// root_path != "" 349| |/// 350| |/// @param path Input path. 351| |/// @result True if the path has a root path, false otherwise. 352| |bool has_root_path(const Twine &path); 353| | 354| |/// @brief Has relative path? 355| |/// 356| |/// relative_path != "" 357| |/// 358| |/// @param path Input path. 359| |/// @result True if the path has a relative path, false otherwise. 360| |bool has_relative_path(const Twine &path); 361| | 362| |/// @brief Has parent path? 363| |/// 364| |/// parent_path != "" 365| |/// 366| |/// @param path Input path. 367| |/// @result True if the path has a parent path, false otherwise. 368| |bool has_parent_path(const Twine &path); 369| | 370| |/// @brief Has filename? 371| |/// 372| |/// filename != "" 373| |/// 374| |/// @param path Input path. 375| |/// @result True if the path has a filename, false otherwise. 376| |bool has_filename(const Twine &path); 377| | 378| |/// @brief Has stem? 379| |/// 380| |/// stem != "" 381| |/// 382| |/// @param path Input path. 383| |/// @result True if the path has a stem, false otherwise. 384| |bool has_stem(const Twine &path); 385| | 386| |/// @brief Has extension? 387| |/// 388| |/// extension != "" 389| |/// 390| |/// @param path Input path. 391| |/// @result True if the path has a extension, false otherwise. 392| |bool has_extension(const Twine &path); 393| | 394| |/// @brief Is path absolute? 395| |/// 396| |/// @param path Input path. 397| |/// @result True if the path is absolute, false if it is not. 398| |bool is_absolute(const Twine &path); 399| | 400| |/// @brief Is path relative? 401| |/// 402| |/// @param path Input path. 403| |/// @result True if the path is relative, false if it is not. 404| |bool is_relative(const Twine &path); 405| | 406| |} // end namespace path 407| |} // end namespace sys 408| |} // end namespace llvm 409| | 410| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/PointerLikeTypeTraits.h: 1| |//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the PointerLikeTypeTraits class. This allows data 11| |// structures to reason about pointers and other things that are pointer sized. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 16| |#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H 17| | 18| |#include "llvm/Support/DataTypes.h" 19| | 20| |namespace llvm { 21| | 22| |/// PointerLikeTypeTraits - This is a traits object that is used to handle 23| |/// pointer types and things that are just wrappers for pointers as a uniform 24| |/// entity. 25| |template 26| |class PointerLikeTypeTraits { 27| | // getAsVoidPointer 28| | // getFromVoidPointer 29| | // getNumLowBitsAvailable 30| |}; 31| | 32| |// Provide PointerLikeTypeTraits for non-cvr pointers. 33| |template 34| |class PointerLikeTypeTraits { 35| |public: 36| | static inline void *getAsVoidPointer(T* P) { return P; } 37| | static inline T *getFromVoidPointer(void *P) { 38| | return static_cast(P); 39| | } 40| | 41| | /// Note, we assume here that malloc returns objects at least 4-byte aligned. 42| | /// However, this may be wrong, or pointers may be from something other than 43| | /// malloc. In this case, you should specialize this template to reduce this. 44| | /// 45| | /// All clients should use assertions to do a run-time check to ensure that 46| | /// this is actually true. 47| | enum { NumLowBitsAvailable = 2 }; 48| |}; 49| | 50| |// Provide PointerLikeTypeTraits for const pointers. 51| |template 52| |class PointerLikeTypeTraits { 53| | typedef PointerLikeTypeTraits NonConst; 54| | 55| |public: 56| | static inline const void *getAsVoidPointer(const T* P) { 57| | return NonConst::getAsVoidPointer(const_cast(P)); 58| | } 59| | static inline const T *getFromVoidPointer(const void *P) { 60| | return NonConst::getFromVoidPointer(const_cast(P)); 61| | } 62| | enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; 63| |}; 64| | 65| |// Provide PointerLikeTypeTraits for uintptr_t. 66| |template<> 67| |class PointerLikeTypeTraits { 68| |public: 69| 0| static inline void *getAsVoidPointer(uintptr_t P) { 70| 0| return reinterpret_cast(P); 71| 0| } 72| 0| static inline uintptr_t getFromVoidPointer(void *P) { 73| 0| return reinterpret_cast(P); 74| 0| } 75| | // No bits are available! 76| | enum { NumLowBitsAvailable = 0 }; 77| |}; 78| | 79| |} // end namespace llvm 80| | 81| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Recycler.h: 1| |//==- llvm/Support/Recycler.h - Recycling Allocator --------------*- C++ -*-==// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the Recycler class template. See the doxygen comment for 11| |// Recycler for more details. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_RECYCLER_H 16| |#define LLVM_SUPPORT_RECYCLER_H 17| | 18| |#include "llvm/ADT/ilist.h" 19| |#include "llvm/Support/AlignOf.h" 20| |#include "llvm/Support/Allocator.h" 21| |#include "llvm/Support/ErrorHandling.h" 22| |#include 23| | 24| |namespace llvm { 25| | 26| |/// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for 27| |/// printing statistics. 28| |/// 29| |void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize); 30| | 31| |/// RecyclerStruct - Implementation detail for Recycler. This is a 32| |/// class that the recycler imposes on free'd memory to carve out 33| |/// next/prev pointers. 34| |struct RecyclerStruct { 35| | RecyclerStruct *Prev, *Next; 36| |}; 37| | 38| |template<> 39| |struct ilist_traits : 40| | public ilist_default_traits { 41| 0| static RecyclerStruct *getPrev(const RecyclerStruct *t) { return t->Prev; } 42| 0| static RecyclerStruct *getNext(const RecyclerStruct *t) { return t->Next; } 43| 0| static void setPrev(RecyclerStruct *t, RecyclerStruct *p) { t->Prev = p; } 44| 0| static void setNext(RecyclerStruct *t, RecyclerStruct *n) { t->Next = n; } 45| | 46| | mutable RecyclerStruct Sentinel; 47| 0| RecyclerStruct *createSentinel() const { 48| 0| return &Sentinel; 49| 0| } 50| 0| static void destroySentinel(RecyclerStruct *) {} 51| | 52| 0| RecyclerStruct *provideInitialHead() const { return createSentinel(); } 53| 0| RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); } 54| 0| static void noteHead(RecyclerStruct*, RecyclerStruct*) {} 55| | 56| 0| static void deleteNode(RecyclerStruct *) { 57| 0| llvm_unreachable("Recycler's ilist_traits shouldn't see a deleteNode call!"); 58| 0| } 59| |}; 60| | 61| |/// Recycler - This class manages a linked-list of deallocated nodes 62| |/// and facilitates reusing deallocated memory in place of allocating 63| |/// new memory. 64| |/// 65| |template::Alignment> 66| |class Recycler { 67| | /// FreeList - Doubly-linked list of nodes that have deleted contents and 68| | /// are not in active use. 69| | /// 70| | iplist FreeList; 71| | 72| |public: 73| | ~Recycler() { 74| | // If this fails, either the callee has lost track of some allocation, 75| | // or the callee isn't tracking allocations and should just call 76| | // clear() before deleting the Recycler. 77| | assert(FreeList.empty() && "Non-empty recycler deleted!"); 78| | } 79| | 80| | /// clear - Release all the tracked allocations to the allocator. The 81| | /// recycler must be free of any tracked allocations before being 82| | /// deleted; calling clear is one way to ensure this. 83| | template 84| | void clear(AllocatorType &Allocator) { 85| | while (!FreeList.empty()) { 86| | T *t = reinterpret_cast(FreeList.remove(FreeList.begin())); 87| | Allocator.Deallocate(t); 88| | } 89| | } 90| | 91| | /// Special case for BumpPtrAllocator which has an empty Deallocate() 92| | /// function. 93| | /// 94| | /// There is no need to traverse the free list, pulling all the objects into 95| | /// cache. 96| | void clear(BumpPtrAllocator&) { 97| | FreeList.clearAndLeakNodesUnsafely(); 98| | } 99| | 100| | template 101| | SubClass *Allocate(AllocatorType &Allocator) { 102| | static_assert(AlignOf::Alignment <= Align, 103| | "Recycler allocation alignment is less than object align!"); 104| | static_assert(sizeof(SubClass) <= Size, 105| | "Recycler allocation size is less than object size!"); 106| | return !FreeList.empty() ? 107| | reinterpret_cast(FreeList.remove(FreeList.begin())) : 108| | static_cast(Allocator.Allocate(Size, Align)); 109| | } 110| | 111| | template 112| | T *Allocate(AllocatorType &Allocator) { 113| | return Allocate(Allocator); 114| | } 115| | 116| | template 117| | void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { 118| | FreeList.push_front(reinterpret_cast(Element)); 119| | } 120| | 121| | void PrintStats() { 122| | PrintRecyclerStats(Size, Align, FreeList.size()); 123| | } 124| |}; 125| | 126| |} 127| | 128| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SMLoc.h: 1| |//===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMLoc class. This class encapsulates a location in 11| |// source code for use in diagnostics. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SMLOC_H 16| |#define LLVM_SUPPORT_SMLOC_H 17| | 18| |#include 19| | 20| |namespace llvm { 21| | 22| |/// Represents a location in source code. 23| |class SMLoc { 24| | const char *Ptr; 25| |public: 26| 0| SMLoc() : Ptr(nullptr) {} 27| | 28| 0| bool isValid() const { return Ptr != nullptr; } 29| | 30| 0| bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } 31| 0| bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } 32| | 33| 0| const char *getPointer() const { return Ptr; } 34| | 35| 0| static SMLoc getFromPointer(const char *Ptr) { 36| 0| SMLoc L; 37| 0| L.Ptr = Ptr; 38| 0| return L; 39| 0| } 40| |}; 41| | 42| |/// Represents a range in source code. 43| |/// 44| |/// SMRange is implemented using a half-open range, as is the convention in C++. 45| |/// In the string "abc", the range (1,3] represents the substring "bc", and the 46| |/// range (2,2] represents an empty range between the characters "b" and "c". 47| |class SMRange { 48| |public: 49| | SMLoc Start, End; 50| | 51| 0| SMRange() {} 52| 0| SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { 53| 0| assert(Start.isValid() == End.isValid() && 54| 0| "Start and end should either both be valid or both be invalid!"); 55| 0| } 56| | 57| 0| bool isValid() const { return Start.isValid(); } 58| |}; 59| | 60| |} // end namespace llvm 61| | 62| |#endif 63| | /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SourceMgr.h: 1| |//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares the SMDiagnostic and SourceMgr classes. This 11| |// provides a simple substrate for diagnostics, #include handling, and other low 12| |// level things for simple parsers. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_SOURCEMGR_H 17| |#define LLVM_SUPPORT_SOURCEMGR_H 18| | 19| |#include "llvm/ADT/ArrayRef.h" 20| |#include "llvm/ADT/StringRef.h" 21| |#include "llvm/ADT/Twine.h" 22| |#include "llvm/Support/MemoryBuffer.h" 23| |#include "llvm/Support/SMLoc.h" 24| |#include 25| | 26| |namespace llvm { 27| | class SourceMgr; 28| | class SMDiagnostic; 29| | class SMFixIt; 30| | class Twine; 31| | class raw_ostream; 32| | 33| |/// This owns the files read by a parser, handles include stacks, 34| |/// and handles diagnostic wrangling. 35| |class SourceMgr { 36| |public: 37| | enum DiagKind { 38| | DK_Error, 39| | DK_Warning, 40| | DK_Note 41| | }; 42| | 43| | /// Clients that want to handle their own diagnostics in a custom way can 44| | /// register a function pointer+context as a diagnostic handler. 45| | /// It gets called each time PrintMessage is invoked. 46| | typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); 47| |private: 48| | struct SrcBuffer { 49| | /// The memory buffer for the file. 50| | std::unique_ptr Buffer; 51| | 52| | /// This is the location of the parent include, or null if at the top level. 53| | SMLoc IncludeLoc; 54| | 55| 0| SrcBuffer() {} 56| | 57| | SrcBuffer(SrcBuffer &&O) 58| 0| : Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {} 59| | }; 60| | 61| | /// This is all of the buffers that we are reading from. 62| | std::vector Buffers; 63| | 64| | // This is the list of directories we should search for include files in. 65| | std::vector IncludeDirectories; 66| | 67| | /// This is a cache for line number queries, its implementation is really 68| | /// private to SourceMgr.cpp. 69| | mutable void *LineNoCache; 70| | 71| | DiagHandlerTy DiagHandler; 72| | void *DiagContext; 73| | 74| 0| bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } 75| | 76| | SourceMgr(const SourceMgr&) = delete; 77| | void operator=(const SourceMgr&) = delete; 78| |public: 79| | SourceMgr() 80| 0| : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} 81| | ~SourceMgr(); 82| | 83| 0| void setIncludeDirs(const std::vector &Dirs) { 84| 0| IncludeDirectories = Dirs; 85| 0| } 86| | 87| | /// Specify a diagnostic handler to be invoked every time PrintMessage is 88| | /// called. \p Ctx is passed into the handler when it is invoked. 89| 0| void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { 90| 0| DiagHandler = DH; 91| 0| DiagContext = Ctx; 92| 0| } 93| | 94| 0| DiagHandlerTy getDiagHandler() const { return DiagHandler; } 95| 0| void *getDiagContext() const { return DiagContext; } 96| | 97| 0| const SrcBuffer &getBufferInfo(unsigned i) const { 98| 0| assert(isValidBufferID(i)); 99| 0| return Buffers[i - 1]; 100| 0| } 101| | 102| 0| const MemoryBuffer *getMemoryBuffer(unsigned i) const { 103| 0| assert(isValidBufferID(i)); 104| 0| return Buffers[i - 1].Buffer.get(); 105| 0| } 106| | 107| 0| unsigned getNumBuffers() const { 108| 0| return Buffers.size(); 109| 0| } 110| | 111| 0| unsigned getMainFileID() const { 112| 0| assert(getNumBuffers()); 113| 0| return 1; 114| 0| } 115| | 116| 0| SMLoc getParentIncludeLoc(unsigned i) const { 117| 0| assert(isValidBufferID(i)); 118| 0| return Buffers[i - 1].IncludeLoc; 119| 0| } 120| | 121| | /// Add a new source buffer to this source manager. This takes ownership of 122| | /// the memory buffer. 123| | unsigned AddNewSourceBuffer(std::unique_ptr F, 124| 0| SMLoc IncludeLoc) { 125| 0| SrcBuffer NB; 126| 0| NB.Buffer = std::move(F); 127| 0| NB.IncludeLoc = IncludeLoc; 128| 0| Buffers.push_back(std::move(NB)); 129| 0| return Buffers.size(); 130| 0| } 131| | 132| | /// Search for a file with the specified name in the current directory or in 133| | /// one of the IncludeDirs. 134| | /// 135| | /// If no file is found, this returns 0, otherwise it returns the buffer ID 136| | /// of the stacked file. The full path to the included file can be found in 137| | /// \p IncludedFile. 138| | unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, 139| | std::string &IncludedFile); 140| | 141| | /// Return the ID of the buffer containing the specified location. 142| | /// 143| | /// 0 is returned if the buffer is not found. 144| | unsigned FindBufferContainingLoc(SMLoc Loc) const; 145| | 146| | /// Find the line number for the specified location in the specified file. 147| | /// This is not a fast method. 148| 0| unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { 149| 0| return getLineAndColumn(Loc, BufferID).first; 150| 0| } 151| | 152| | /// Find the line and column number for the specified location in the 153| | /// specified file. This is not a fast method. 154| | std::pair getLineAndColumn(SMLoc Loc, 155| | unsigned BufferID = 0) const; 156| | 157| | /// Emit a message about the specified location with the specified string. 158| | /// 159| | /// \param ShowColors Display colored messages if output is a terminal and 160| | /// the default error handler is used. 161| | void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, 162| | const Twine &Msg, 163| | ArrayRef Ranges = None, 164| | ArrayRef FixIts = None, 165| | bool ShowColors = true) const; 166| | 167| | /// Emits a diagnostic to llvm::errs(). 168| | void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 169| | ArrayRef Ranges = None, 170| | ArrayRef FixIts = None, 171| | bool ShowColors = true) const; 172| | 173| | /// Emits a manually-constructed diagnostic to the given output stream. 174| | /// 175| | /// \param ShowColors Display colored messages if output is a terminal and 176| | /// the default error handler is used. 177| | void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, 178| | bool ShowColors = true) const; 179| | 180| | /// Return an SMDiagnostic at the specified location with the specified 181| | /// string. 182| | /// 183| | /// \param Msg If non-null, the kind of message (e.g., "error") which is 184| | /// prefixed to the message. 185| | SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 186| | ArrayRef Ranges = None, 187| | ArrayRef FixIts = None) const; 188| | 189| | /// Prints the names of included files and the line of the file they were 190| | /// included from. A diagnostic handler can use this before printing its 191| | /// custom formatted message. 192| | /// 193| | /// \param IncludeLoc The location of the include. 194| | /// \param OS the raw_ostream to print on. 195| | void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; 196| |}; 197| | 198| | 199| |/// Represents a single fixit, a replacement of one range of text with another. 200| |class SMFixIt { 201| | SMRange Range; 202| | 203| | std::string Text; 204| | 205| |public: 206| | // FIXME: Twine.str() is not very efficient. 207| | SMFixIt(SMLoc Loc, const Twine &Insertion) 208| 0| : Range(Loc, Loc), Text(Insertion.str()) { 209| 0| assert(Loc.isValid()); 210| 0| } 211| | 212| | // FIXME: Twine.str() is not very efficient. 213| | SMFixIt(SMRange R, const Twine &Replacement) 214| 0| : Range(R), Text(Replacement.str()) { 215| 0| assert(R.isValid()); 216| 0| } 217| | 218| 0| StringRef getText() const { return Text; } 219| 0| SMRange getRange() const { return Range; } 220| | 221| 0| bool operator<(const SMFixIt &Other) const { 222| 0| if (Range.Start.getPointer() != Other.Range.Start.getPointer()) 223| 0| return Range.Start.getPointer() < Other.Range.Start.getPointer(); 224| 0| if (Range.End.getPointer() != Other.Range.End.getPointer()) 225| 0| return Range.End.getPointer() < Other.Range.End.getPointer(); 226| 0| return Text < Other.Text; 227| 0| } 228| |}; 229| | 230| | 231| |/// Instances of this class encapsulate one diagnostic report, allowing 232| |/// printing to a raw_ostream as a caret diagnostic. 233| |class SMDiagnostic { 234| | const SourceMgr *SM; 235| | SMLoc Loc; 236| | std::string Filename; 237| | int LineNo, ColumnNo; 238| | SourceMgr::DiagKind Kind; 239| | std::string Message, LineContents; 240| | std::vector > Ranges; 241| | SmallVector FixIts; 242| | 243| |public: 244| | // Null diagnostic. 245| | SMDiagnostic() 246| 0| : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} 247| | // Diagnostic with no location (e.g. file not found, command line arg error). 248| | SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) 249| | : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), 250| 0| Message(Msg) {} 251| | 252| | // Diagnostic with a location. 253| | SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 254| | int Line, int Col, SourceMgr::DiagKind Kind, 255| | StringRef Msg, StringRef LineStr, 256| | ArrayRef > Ranges, 257| | ArrayRef FixIts = None); 258| | 259| 0| const SourceMgr *getSourceMgr() const { return SM; } 260| 0| SMLoc getLoc() const { return Loc; } 261| | StringRef getFilename() const { return Filename; } 262| | int getLineNo() const { return LineNo; } 263| | int getColumnNo() const { return ColumnNo; } 264| | SourceMgr::DiagKind getKind() const { return Kind; } 265| | StringRef getMessage() const { return Message; } 266| 0| StringRef getLineContents() const { return LineContents; } 267| 0| ArrayRef > getRanges() const { 268| 0| return Ranges; 269| 0| } 270| | 271| 0| void addFixIt(const SMFixIt &Hint) { 272| 0| FixIts.push_back(Hint); 273| 0| } 274| | 275| 0| ArrayRef getFixIts() const { 276| 0| return FixIts; 277| 0| } 278| | 279| | void print(const char *ProgName, raw_ostream &S, 280| | bool ShowColors = true) const; 281| |}; 282| | 283| |} // end llvm namespace 284| | 285| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/SwapByteOrder.h: 1| |//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file declares generic and optimized functions to swap the byte order of 11| |// an integral type. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H 16| |#define LLVM_SUPPORT_SWAPBYTEORDER_H 17| | 18| |#include "llvm/Support/Compiler.h" 19| |#include "llvm/Support/DataTypes.h" 20| |#include 21| |#include 22| | 23| |namespace llvm { 24| |namespace sys { 25| | 26| |/// SwapByteOrder_16 - This function returns a byte-swapped representation of 27| |/// the 16-bit argument. 28| 0|inline uint16_t SwapByteOrder_16(uint16_t value) { 29| |#if defined(_MSC_VER) && !defined(_DEBUG) 30| | // The DLL version of the runtime lacks these functions (bug!?), but in a 31| | // release build they're replaced with BSWAP instructions anyway. 32| | return _byteswap_ushort(value); 33| |#else 34| | uint16_t Hi = value << 8; 35| 0| uint16_t Lo = value >> 8; 36| 0| return Hi | Lo; 37| 0|#endif 38| 0|} 39| | 40| |/// SwapByteOrder_32 - This function returns a byte-swapped representation of 41| |/// the 32-bit argument. 42| 0|inline uint32_t SwapByteOrder_32(uint32_t value) { 43| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 44| 0| return __builtin_bswap32(value); 45| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 46| 0| return _byteswap_ulong(value); 47| 0|#else 48| 0| uint32_t Byte0 = value & 0x000000FF; 49| 0| uint32_t Byte1 = value & 0x0000FF00; 50| 0| uint32_t Byte2 = value & 0x00FF0000; 51| 0| uint32_t Byte3 = value & 0xFF000000; 52| 0| return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 53| 0|#endif 54| 0|} 55| | 56| |/// SwapByteOrder_64 - This function returns a byte-swapped representation of 57| |/// the 64-bit argument. 58| 0|inline uint64_t SwapByteOrder_64(uint64_t value) { 59| 0|#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) 60| 0| return __builtin_bswap64(value); 61| 0|#elif defined(_MSC_VER) && !defined(_DEBUG) 62| 0| return _byteswap_uint64(value); 63| 0|#else 64| 0| uint64_t Hi = SwapByteOrder_32(uint32_t(value)); 65| 0| uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); 66| 0| return (Hi << 32) | Lo; 67| 0|#endif 68| 0|} 69| | 70| 0|inline unsigned char getSwappedBytes(unsigned char C) { return C; } 71| 0|inline signed char getSwappedBytes(signed char C) { return C; } 72| 0|inline char getSwappedBytes(char C) { return C; } 73| | 74| 0|inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } 75| 0|inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } 76| | 77| 0|inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } 78| 0|inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } 79| | 80| |#if __LONG_MAX__ == __INT_MAX__ 81| |inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } 82| |inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } 83| |#elif __LONG_MAX__ == __LONG_LONG_MAX__ 84| 0|inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } 85| 0|inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } 86| |#else 87| |#error "Unknown long size!" 88| |#endif 89| | 90| 0|inline unsigned long long getSwappedBytes(unsigned long long C) { 91| 0| return SwapByteOrder_64(C); 92| 0|} 93| 0|inline signed long long getSwappedBytes(signed long long C) { 94| 0| return SwapByteOrder_64(C); 95| 0|} 96| | 97| 0|inline float getSwappedBytes(float C) { 98| 0| union { 99| 0| uint32_t i; 100| 0| float f; 101| 0| } in, out; 102| 0| in.f = C; 103| 0| out.i = SwapByteOrder_32(in.i); 104| 0| return out.f; 105| 0|} 106| | 107| 0|inline float getSwappedBytes(double C) { 108| 0| union { 109| 0| uint64_t i; 110| 0| double d; 111| 0| } in, out; 112| 0| in.d = C; 113| 0| out.i = SwapByteOrder_64(in.i); 114| 0| return out.d; 115| 0|} 116| | 117| |template 118| 0|inline void swapByteOrder(T &Value) { 119| 0| Value = getSwappedBytes(Value); 120| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIyEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderIjEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm3sys13swapByteOrderItEEvRT_ ------------------ 121| | 122| |} // end namespace sys 123| |} // end namespace llvm 124| | 125| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/TimeValue.h: 1| |//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This header file declares the operating system TimeValue concept. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_TIMEVALUE_H 15| |#define LLVM_SUPPORT_TIMEVALUE_H 16| | 17| |#include "llvm/Support/DataTypes.h" 18| |#include 19| | 20| |namespace llvm { 21| |namespace sys { 22| | /// This class is used where a precise fixed point in time is required. The 23| | /// range of TimeValue spans many hundreds of billions of years both past and 24| | /// present. The precision of TimeValue is to the nanosecond. However, the 25| | /// actual precision of its values will be determined by the resolution of 26| | /// the system clock. The TimeValue class is used in conjunction with several 27| | /// other lib/System interfaces to specify the time at which a call should 28| | /// timeout, etc. 29| | /// @since 1.4 30| | /// @brief Provides an abstraction for a fixed point in time. 31| | class TimeValue { 32| | 33| | /// @name Constants 34| | /// @{ 35| | public: 36| | 37| | /// A constant TimeValue representing the smallest time 38| | /// value permissible by the class. MinTime is some point 39| | /// in the distant past, about 300 billion years BCE. 40| | /// @brief The smallest possible time value. 41| 0| static TimeValue MinTime() { 42| 0| return TimeValue ( INT64_MIN,0 ); 43| 0| } 44| | 45| | /// A constant TimeValue representing the largest time 46| | /// value permissible by the class. MaxTime is some point 47| | /// in the distant future, about 300 billion years AD. 48| | /// @brief The largest possible time value. 49| 0| static TimeValue MaxTime() { 50| 0| return TimeValue ( INT64_MAX,0 ); 51| 0| } 52| | 53| | /// A constant TimeValue representing the base time, 54| | /// or zero time of 00:00:00 (midnight) January 1st, 2000. 55| | /// @brief 00:00:00 Jan 1, 2000 UTC. 56| 0| static TimeValue ZeroTime() { 57| 0| return TimeValue ( 0,0 ); 58| 0| } 59| | 60| | /// A constant TimeValue for the Posix base time which is 61| | /// 00:00:00 (midnight) January 1st, 1970. 62| | /// @brief 00:00:00 Jan 1, 1970 UTC. 63| 0| static TimeValue PosixZeroTime() { 64| 0| return TimeValue ( PosixZeroTimeSeconds,0 ); 65| 0| } 66| | 67| | /// A constant TimeValue for the Win32 base time which is 68| | /// 00:00:00 (midnight) January 1st, 1601. 69| | /// @brief 00:00:00 Jan 1, 1601 UTC. 70| 0| static TimeValue Win32ZeroTime() { 71| 0| return TimeValue ( Win32ZeroTimeSeconds,0 ); 72| 0| } 73| | 74| | /// @} 75| | /// @name Types 76| | /// @{ 77| | public: 78| | typedef int64_t SecondsType; ///< Type used for representing seconds. 79| | typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. 80| | 81| | enum TimeConversions { 82| | NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion 83| | MICROSECONDS_PER_SECOND = 1000000, ///< One Million 84| | MILLISECONDS_PER_SECOND = 1000, ///< One Thousand 85| | NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand 86| | NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million 87| | NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) 88| | }; 89| | 90| | /// @} 91| | /// @name Constructors 92| | /// @{ 93| | public: 94| | /// \brief Default construct a time value, initializing to ZeroTime. 95| 0| TimeValue() : seconds_(0), nanos_(0) {} 96| | 97| | /// Caller provides the exact value in seconds and nanoseconds. The 98| | /// \p nanos argument defaults to zero for convenience. 99| | /// @brief Explicit constructor 100| | explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) 101| 6| : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } 102| | 103| | /// Caller provides the exact value as a double in seconds with the 104| | /// fractional part representing nanoseconds. 105| | /// @brief Double Constructor. 106| | explicit TimeValue( double new_time ) 107| 0| : seconds_( 0 ) , nanos_ ( 0 ) { 108| 0| SecondsType integer_part = static_cast( new_time ); 109| 0| seconds_ = integer_part; 110| 0| nanos_ = static_cast( (new_time - 111| 0| static_cast(integer_part)) * NANOSECONDS_PER_SECOND ); 112| 0| this->normalize(); 113| 0| } 114| | 115| | /// This is a static constructor that returns a TimeValue that represents 116| | /// the current time. 117| | /// @brief Creates a TimeValue with the current time (UTC). 118| | static TimeValue now(); 119| | 120| | /// @} 121| | /// @name Operators 122| | /// @{ 123| | public: 124| | /// Add \p that to \p this. 125| | /// @returns this 126| | /// @brief Incrementing assignment operator. 127| 0| TimeValue& operator += (const TimeValue& that ) { 128| 0| this->seconds_ += that.seconds_ ; 129| 0| this->nanos_ += that.nanos_ ; 130| 0| this->normalize(); 131| 0| return *this; 132| 0| } 133| | 134| | /// Subtract \p that from \p this. 135| | /// @returns this 136| | /// @brief Decrementing assignment operator. 137| 0| TimeValue& operator -= (const TimeValue &that ) { 138| 0| this->seconds_ -= that.seconds_ ; 139| 0| this->nanos_ -= that.nanos_ ; 140| 0| this->normalize(); 141| 0| return *this; 142| 0| } 143| | 144| | /// Determine if \p this is less than \p that. 145| | /// @returns True iff *this < that. 146| | /// @brief True if this < that. 147| 0| int operator < (const TimeValue &that) const { return that > *this; } 148| | 149| | /// Determine if \p this is greather than \p that. 150| | /// @returns True iff *this > that. 151| | /// @brief True if this > that. 152| 0| int operator > (const TimeValue &that) const { 153| 0| if ( this->seconds_ > that.seconds_ ) { 154| 0| return 1; 155| 0| } else if ( this->seconds_ == that.seconds_ ) { 156| 0| if ( this->nanos_ > that.nanos_ ) return 1; 157| 0| } 158| 0| return 0; 159| 0| } 160| | 161| | /// Determine if \p this is less than or equal to \p that. 162| | /// @returns True iff *this <= that. 163| | /// @brief True if this <= that. 164| 0| int operator <= (const TimeValue &that) const { return that >= *this; } 165| | 166| | /// Determine if \p this is greater than or equal to \p that. 167| | /// @returns True iff *this >= that. 168| 0| int operator >= (const TimeValue &that) const { 169| 0| if ( this->seconds_ > that.seconds_ ) { 170| 0| return 1; 171| 0| } else if ( this->seconds_ == that.seconds_ ) { 172| 0| if ( this->nanos_ >= that.nanos_ ) return 1; 173| 0| } 174| 0| return 0; 175| 0| } 176| | 177| | /// Determines if two TimeValue objects represent the same moment in time. 178| | /// @returns True iff *this == that. 179| 0| int operator == (const TimeValue &that) const { 180| 0| return (this->seconds_ == that.seconds_) && 181| 0| (this->nanos_ == that.nanos_); 182| 0| } 183| | 184| | /// Determines if two TimeValue objects represent times that are not the 185| | /// same. 186| | /// @returns True iff *this != that. 187| 0| int operator != (const TimeValue &that) const { return !(*this == that); } 188| | 189| | /// Adds two TimeValue objects together. 190| | /// @returns The sum of the two operands as a new TimeValue 191| | /// @brief Addition operator. 192| | friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); 193| | 194| | /// Subtracts two TimeValue objects. 195| | /// @returns The difference of the two operands as a new TimeValue 196| | /// @brief Subtraction operator. 197| | friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); 198| | 199| | /// @} 200| | /// @name Accessors 201| | /// @{ 202| | public: 203| | 204| | /// Returns only the seconds component of the TimeValue. The nanoseconds 205| | /// portion is ignored. No rounding is performed. 206| | /// @brief Retrieve the seconds component 207| 0| SecondsType seconds() const { return seconds_; } 208| | 209| | /// Returns only the nanoseconds component of the TimeValue. The seconds 210| | /// portion is ignored. 211| | /// @brief Retrieve the nanoseconds component. 212| 0| NanoSecondsType nanoseconds() const { return nanos_; } 213| | 214| | /// Returns only the fractional portion of the TimeValue rounded down to the 215| | /// nearest microsecond (divide by one thousand). 216| | /// @brief Retrieve the fractional part as microseconds; 217| 0| uint32_t microseconds() const { 218| 0| return nanos_ / NANOSECONDS_PER_MICROSECOND; 219| 0| } 220| | 221| | /// Returns only the fractional portion of the TimeValue rounded down to the 222| | /// nearest millisecond (divide by one million). 223| | /// @brief Retrieve the fractional part as milliseconds; 224| 0| uint32_t milliseconds() const { 225| 0| return nanos_ / NANOSECONDS_PER_MILLISECOND; 226| 0| } 227| | 228| | /// Returns the TimeValue as a number of microseconds. Note that the value 229| | /// returned can overflow because the range of a uint64_t is smaller than 230| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 231| | /// systems and is therefore provided. 232| | /// @brief Convert to a number of microseconds (can overflow) 233| 0| uint64_t usec() const { 234| 0| return seconds_ * MICROSECONDS_PER_SECOND + 235| 0| ( nanos_ / NANOSECONDS_PER_MICROSECOND ); 236| 0| } 237| | 238| | /// Returns the TimeValue as a number of milliseconds. Note that the value 239| | /// returned can overflow because the range of a uint64_t is smaller than 240| | /// the range of a TimeValue. Nevertheless, this is useful on some operating 241| | /// systems and is therefore provided. 242| | /// @brief Convert to a number of milliseconds (can overflow) 243| 0| uint64_t msec() const { 244| 0| return seconds_ * MILLISECONDS_PER_SECOND + 245| 0| ( nanos_ / NANOSECONDS_PER_MILLISECOND ); 246| 0| } 247| | 248| | /// Converts the TimeValue into the corresponding number of seconds 249| | /// since the epoch (00:00:00 Jan 1,1970). 250| 0| uint64_t toEpochTime() const { 251| 0| return seconds_ - PosixZeroTimeSeconds; 252| 0| } 253| | 254| | /// Converts the TimeValue into the corresponding number of "ticks" for 255| | /// Win32 platforms, correcting for the difference in Win32 zero time. 256| | /// @brief Convert to Win32's FILETIME 257| | /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) 258| 0| uint64_t toWin32Time() const { 259| 0| uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); 260| 0| result += nanos_ / NANOSECONDS_PER_WIN32_TICK; 261| 0| return result; 262| 0| } 263| | 264| | /// Provides the seconds and nanoseconds as results in its arguments after 265| | /// correction for the Posix zero time. 266| | /// @brief Convert to timespec time (ala POSIX.1b) 267| 0| void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { 268| 0| seconds = seconds_ - PosixZeroTimeSeconds; 269| 0| nanos = nanos_; 270| 0| } 271| | 272| | /// Provides conversion of the TimeValue into a readable time & date. 273| | /// @returns std::string containing the readable time value 274| | /// @brief Convert time to a string. 275| | std::string str() const; 276| | 277| | /// @} 278| | /// @name Mutators 279| | /// @{ 280| | public: 281| | /// The seconds component of the TimeValue is set to \p sec without 282| | /// modifying the nanoseconds part. This is useful for whole second 283| | /// arithmetic. 284| | /// @brief Set the seconds component. 285| 0| void seconds (SecondsType sec ) { 286| 0| this->seconds_ = sec; 287| 0| this->normalize(); 288| 0| } 289| | 290| | /// The nanoseconds component of the TimeValue is set to \p nanos without 291| | /// modifying the seconds part. This is useful for basic computations 292| | /// involving just the nanoseconds portion. Note that the TimeValue will be 293| | /// normalized after this call so that the fractional (nanoseconds) portion 294| | /// will have the smallest equivalent value. 295| | /// @brief Set the nanoseconds component using a number of nanoseconds. 296| 0| void nanoseconds ( NanoSecondsType nanos ) { 297| 0| this->nanos_ = nanos; 298| 0| this->normalize(); 299| 0| } 300| | 301| | /// The seconds component remains unchanged. 302| | /// @brief Set the nanoseconds component using a number of microseconds. 303| 0| void microseconds ( int32_t micros ) { 304| 0| this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; 305| 0| this->normalize(); 306| 0| } 307| | 308| | /// The seconds component remains unchanged. 309| | /// @brief Set the nanoseconds component using a number of milliseconds. 310| 0| void milliseconds ( int32_t millis ) { 311| 0| this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; 312| 0| this->normalize(); 313| 0| } 314| | 315| | /// @brief Converts from microsecond format to TimeValue format 316| 0| void usec( int64_t microseconds ) { 317| 0| this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; 318| 0| this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * 319| 0| NANOSECONDS_PER_MICROSECOND; 320| 0| this->normalize(); 321| 0| } 322| | 323| | /// @brief Converts from millisecond format to TimeValue format 324| 0| void msec( int64_t milliseconds ) { 325| 0| this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; 326| 0| this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * 327| 0| NANOSECONDS_PER_MILLISECOND; 328| 0| this->normalize(); 329| 0| } 330| | 331| | /// Converts the \p seconds argument from PosixTime to the corresponding 332| | /// TimeValue and assigns that value to \p this. 333| | /// @brief Convert seconds form PosixTime to TimeValue 334| 0| void fromEpochTime( SecondsType seconds ) { 335| 0| seconds_ = seconds + PosixZeroTimeSeconds; 336| 0| nanos_ = 0; 337| 0| this->normalize(); 338| 0| } 339| | 340| | /// Converts the \p win32Time argument from Windows FILETIME to the 341| | /// corresponding TimeValue and assigns that value to \p this. 342| | /// @brief Convert seconds form Windows FILETIME to TimeValue 343| 0| void fromWin32Time( uint64_t win32Time ) { 344| 0| this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; 345| 0| this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; 346| 0| } 347| | 348| | /// @} 349| | /// @name Implementation 350| | /// @{ 351| | private: 352| | /// This causes the values to be represented so that the fractional 353| | /// part is minimized, possibly incrementing the seconds part. 354| | /// @brief Normalize to canonical form. 355| | void normalize(); 356| | 357| | /// @} 358| | /// @name Data 359| | /// @{ 360| | private: 361| | /// Store the values as a . 362| | SecondsType seconds_;///< Stores the seconds part of the TimeVal 363| | NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal 364| | 365| | static const SecondsType PosixZeroTimeSeconds; 366| | static const SecondsType Win32ZeroTimeSeconds; 367| | /// @} 368| | 369| | }; 370| | 371| 0|inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { 372| 0| TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); 373| 0| sum.normalize (); 374| 0| return sum; 375| 0|} 376| | 377| 2|inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { 378| 2| TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); 379| 2| difference.normalize (); 380| 2| return difference; 381| 2|} 382| | 383| |} 384| |} 385| | 386| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/UnicodeCharRanges.h: 1| |//===--- UnicodeCharRanges.h - Types and functions for character ranges ---===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |#ifndef LLVM_SUPPORT_UNICODECHARRANGES_H 10| |#define LLVM_SUPPORT_UNICODECHARRANGES_H 11| | 12| |#include "llvm/ADT/ArrayRef.h" 13| |#include "llvm/ADT/SmallPtrSet.h" 14| |#include "llvm/Support/Compiler.h" 15| |#include "llvm/Support/Debug.h" 16| |#include "llvm/Support/Mutex.h" 17| |#include "llvm/Support/MutexGuard.h" 18| |#include "llvm/Support/raw_ostream.h" 19| |#include 20| | 21| |namespace llvm { 22| |namespace sys { 23| | 24| |#define DEBUG_TYPE "unicode" 25| | 26| |/// \brief Represents a closed range of Unicode code points [Lower, Upper]. 27| |struct UnicodeCharRange { 28| | uint32_t Lower; 29| | uint32_t Upper; 30| |}; 31| | 32| 0|inline bool operator<(uint32_t Value, UnicodeCharRange Range) { 33| 0| return Value < Range.Lower; 34| 0|} 35| 0|inline bool operator<(UnicodeCharRange Range, uint32_t Value) { 36| 0| return Range.Upper < Value; 37| 0|} 38| | 39| |/// \brief Holds a reference to an ordered array of UnicodeCharRange and allows 40| |/// to quickly check if a code point is contained in the set represented by this 41| |/// array. 42| |class UnicodeCharSet { 43| |public: 44| | typedef ArrayRef CharRanges; 45| | 46| | /// \brief Constructs a UnicodeCharSet instance from an array of 47| | /// UnicodeCharRanges. 48| | /// 49| | /// Array pointed by \p Ranges should have the lifetime at least as long as 50| | /// the UnicodeCharSet instance, and should not change. Array is validated by 51| | /// the constructor, so it makes sense to create as few UnicodeCharSet 52| | /// instances per each array of ranges, as possible. 53| |#ifdef NDEBUG 54| | LLVM_CONSTEXPR UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {} 55| |#else 56| 0| UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) { 57| 0| assert(rangesAreValid()); 58| 0| } 59| |#endif 60| | 61| | /// \brief Returns true if the character set contains the Unicode code point 62| | /// \p C. 63| 0| bool contains(uint32_t C) const { 64| 0| return std::binary_search(Ranges.begin(), Ranges.end(), C); 65| 0| } 66| | 67| |private: 68| | /// \brief Returns true if each of the ranges is a proper closed range 69| | /// [min, max], and if the ranges themselves are ordered and non-overlapping. 70| 0| bool rangesAreValid() const { 71| 0| uint32_t Prev = 0; 72| 0| for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); 73| 0| I != E; ++I) { 74| 0| if (I != Ranges.begin() && Prev >= I->Lower) { 75| 0| DEBUG(dbgs() << "Upper bound 0x"); 76| 0| DEBUG(dbgs().write_hex(Prev)); 77| 0| DEBUG(dbgs() << " should be less than succeeding lower bound 0x"); 78| 0| DEBUG(dbgs().write_hex(I->Lower) << "\n"); 79| 0| return false; 80| 0| } 81| 0| if (I->Upper < I->Lower) { 82| 0| DEBUG(dbgs() << "Upper bound 0x"); 83| 0| DEBUG(dbgs().write_hex(I->Lower)); 84| 0| DEBUG(dbgs() << " should not be less than lower bound 0x"); 85| 0| DEBUG(dbgs().write_hex(I->Upper) << "\n"); 86| 0| return false; 87| 0| } 88| 0| Prev = I->Upper; 89| 0| } 90| 0| 91| 0| return true; 92| 0| } 93| | 94| | const CharRanges Ranges; 95| |}; 96| | 97| |#undef DEBUG_TYPE // "unicode" 98| | 99| |} // namespace sys 100| |} // namespace llvm 101| | 102| | 103| |#endif // LLVM_SUPPORT_UNICODECHARRANGES_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/UniqueLock.h: 1| |//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines a guard for a block of code that ensures a Mutex is locked 11| |// upon construction and released upon destruction. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H 16| |#define LLVM_SUPPORT_UNIQUE_LOCK_H 17| | 18| |#include "llvm/Support/Mutex.h" 19| | 20| |namespace llvm { 21| | /// A pared-down imitation of std::unique_lock from C++11. Contrary to the 22| | /// name, it's really more of a wrapper for a lock. It may or may not have 23| | /// an associated mutex, which is guaranteed to be locked upon creation 24| | /// and unlocked after destruction. unique_lock can also unlock the mutex 25| | /// and re-lock it freely during its lifetime. 26| | /// @brief Guard a section of code with a mutex. 27| | template 28| | class unique_lock { 29| | MutexT *M; 30| | bool locked; 31| | 32| | unique_lock(const unique_lock &) = delete; 33| | void operator=(const unique_lock &) = delete; 34| | public: 35| | unique_lock() : M(nullptr), locked(false) {} 36| 0| explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); } 37| | 38| | void operator=(unique_lock &&o) { 39| | if (owns_lock()) 40| | M->unlock(); 41| | M = o.M; 42| | locked = o.locked; 43| | o.M = nullptr; 44| | o.locked = false; 45| | } 46| | 47| 0| ~unique_lock() { if (owns_lock()) M->unlock(); } 48| | 49| | void lock() { 50| | assert(!locked && "mutex already locked!"); 51| | assert(M && "no associated mutex!"); 52| | M->lock(); 53| | locked = true; 54| | } 55| | 56| 0| void unlock() { 57| 0| assert(locked && "unlocking a mutex that isn't locked!"); 58| 0| assert(M && "no associated mutex!"); 59| 0| M->unlock(); 60| 0| locked = false; 61| 0| } 62| | 63| 0| bool owns_lock() { return locked; } 64| | }; 65| |} 66| | 67| |#endif // LLVM_SUPPORT_UNIQUE_LOCK_H /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/Valgrind.h: 1| |//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// Methods for communicating with a valgrind instance this program is running 11| |// under. These are all no-ops unless LLVM was configured on a system with the 12| |// valgrind headers installed and valgrind is controlling this process. 13| |// 14| |//===----------------------------------------------------------------------===// 15| | 16| |#ifndef LLVM_SUPPORT_VALGRIND_H 17| |#define LLVM_SUPPORT_VALGRIND_H 18| | 19| |#include "llvm/Config/llvm-config.h" 20| |#include "llvm/Support/Compiler.h" 21| |#include 22| | 23| |#if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG) 24| |// tsan (Thread Sanitizer) is a valgrind-based tool that detects these exact 25| |// functions by name. 26| |extern "C" { 27| |void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); 28| |void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); 29| |void AnnotateIgnoreWritesBegin(const char *file, int line); 30| |void AnnotateIgnoreWritesEnd(const char *file, int line); 31| |} 32| |#endif 33| | 34| |namespace llvm { 35| |namespace sys { 36| | // True if Valgrind is controlling this process. 37| | bool RunningOnValgrind(); 38| | 39| | // Discard valgrind's translation of code in the range [Addr .. Addr + Len). 40| | // Otherwise valgrind may continue to execute the old version of the code. 41| | void ValgrindDiscardTranslations(const void *Addr, size_t Len); 42| | 43| |#if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG) 44| | // Thread Sanitizer is a valgrind tool that finds races in code. 45| | // See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations . 46| | 47| | // This marker is used to define a happens-before arc. The race detector will 48| | // infer an arc from the begin to the end when they share the same pointer 49| | // argument. 50| | #define TsanHappensBefore(cv) \ 51| 0| AnnotateHappensBefore(__FILE__, __LINE__, cv) 52| | 53| | // This marker defines the destination of a happens-before arc. 54| | #define TsanHappensAfter(cv) \ 55| 0| AnnotateHappensAfter(__FILE__, __LINE__, cv) 56| | 57| | // Ignore any races on writes between here and the next TsanIgnoreWritesEnd. 58| | #define TsanIgnoreWritesBegin() \ 59| 0| AnnotateIgnoreWritesBegin(__FILE__, __LINE__) 60| | 61| | // Resume checking for racy writes. 62| | #define TsanIgnoreWritesEnd() \ 63| 0| AnnotateIgnoreWritesEnd(__FILE__, __LINE__) 64| |#else 65| | #define TsanHappensBefore(cv) 66| | #define TsanHappensAfter(cv) 67| | #define TsanIgnoreWritesBegin() 68| | #define TsanIgnoreWritesEnd() 69| |#endif 70| |} 71| |} 72| | 73| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/YAMLParser.h: 1| |//===--- YAMLParser.h - Simple YAML parser --------------------------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This is a YAML 1.2 parser. 11| |// 12| |// See http://www.yaml.org/spec/1.2/spec.html for the full standard. 13| |// 14| |// This currently does not implement the following: 15| |// * Multi-line literal folding. 16| |// * Tag resolution. 17| |// * UTF-16. 18| |// * BOMs anywhere other than the first Unicode scalar value in the file. 19| |// 20| |// The most important class here is Stream. This represents a YAML stream with 21| |// 0, 1, or many documents. 22| |// 23| |// SourceMgr sm; 24| |// StringRef input = getInput(); 25| |// yaml::Stream stream(input, sm); 26| |// 27| |// for (yaml::document_iterator di = stream.begin(), de = stream.end(); 28| |// di != de; ++di) { 29| |// yaml::Node *n = di->getRoot(); 30| |// if (n) { 31| |// // Do something with n... 32| |// } else 33| |// break; 34| |// } 35| |// 36| |//===----------------------------------------------------------------------===// 37| | 38| |#ifndef LLVM_SUPPORT_YAMLPARSER_H 39| |#define LLVM_SUPPORT_YAMLPARSER_H 40| | 41| |#include "llvm/ADT/SmallString.h" 42| |#include "llvm/ADT/StringRef.h" 43| |#include "llvm/Support/Allocator.h" 44| |#include "llvm/Support/MemoryBuffer.h" 45| |#include "llvm/Support/SMLoc.h" 46| |#include 47| |#include 48| |#include 49| | 50| |namespace llvm { 51| |class SourceMgr; 52| |class raw_ostream; 53| |class Twine; 54| | 55| |namespace yaml { 56| | 57| |class document_iterator; 58| |class Document; 59| |class Node; 60| |class Scanner; 61| |struct Token; 62| | 63| |/// \brief Dump all the tokens in this stream to OS. 64| |/// \returns true if there was an error, false otherwise. 65| |bool dumpTokens(StringRef Input, raw_ostream &); 66| | 67| |/// \brief Scans all tokens in input without outputting anything. This is used 68| |/// for benchmarking the tokenizer. 69| |/// \returns true if there was an error, false otherwise. 70| |bool scanTokens(StringRef Input); 71| | 72| |/// \brief Escape \a Input for a double quoted scalar. 73| |std::string escape(StringRef Input); 74| | 75| |/// \brief This class represents a YAML stream potentially containing multiple 76| |/// documents. 77| |class Stream { 78| |public: 79| | /// \brief This keeps a reference to the string referenced by \p Input. 80| | Stream(StringRef Input, SourceMgr &); 81| | 82| | Stream(MemoryBufferRef InputBuffer, SourceMgr &); 83| | ~Stream(); 84| | 85| | document_iterator begin(); 86| | document_iterator end(); 87| | void skip(); 88| | bool failed(); 89| 0| bool validate() { 90| 0| skip(); 91| 0| return !failed(); 92| 0| } 93| | 94| | void printError(Node *N, const Twine &Msg); 95| | 96| |private: 97| | std::unique_ptr scanner; 98| | std::unique_ptr CurrentDoc; 99| | 100| | friend class Document; 101| |}; 102| | 103| |/// \brief Abstract base class for all Nodes. 104| |class Node { 105| | virtual void anchor(); 106| | 107| |public: 108| | enum NodeKind { 109| | NK_Null, 110| | NK_Scalar, 111| | NK_KeyValue, 112| | NK_Mapping, 113| | NK_Sequence, 114| | NK_Alias 115| | }; 116| | 117| | Node(unsigned int Type, std::unique_ptr &, StringRef Anchor, 118| | StringRef Tag); 119| | 120| | /// \brief Get the value of the anchor attached to this node. If it does not 121| | /// have one, getAnchor().size() will be 0. 122| 0| StringRef getAnchor() const { return Anchor; } 123| | 124| | /// \brief Get the tag as it was written in the document. This does not 125| | /// perform tag resolution. 126| 0| StringRef getRawTag() const { return Tag; } 127| | 128| | /// \brief Get the verbatium tag for a given Node. This performs tag resoluton 129| | /// and substitution. 130| | std::string getVerbatimTag() const; 131| | 132| 0| SMRange getSourceRange() const { return SourceRange; } 133| 0| void setSourceRange(SMRange SR) { SourceRange = SR; } 134| | 135| | // These functions forward to Document and Scanner. 136| | Token &peekNext(); 137| | Token getNext(); 138| | Node *parseBlockNode(); 139| | BumpPtrAllocator &getAllocator(); 140| | void setError(const Twine &Message, Token &Location) const; 141| | bool failed() const; 142| | 143| 0| virtual void skip() {} 144| | 145| 0| unsigned int getType() const { return TypeID; } 146| | 147| | void *operator new(size_t Size, BumpPtrAllocator &Alloc, 148| 0| size_t Alignment = 16) throw() { 149| 0| return Alloc.Allocate(Size, Alignment); 150| 0| } 151| | 152| 0| void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { 153| 0| Alloc.Deallocate(Ptr, Size); 154| 0| } 155| | 156| |protected: 157| | std::unique_ptr &Doc; 158| | SMRange SourceRange; 159| | 160| 0| void operator delete(void *) throw() {} 161| | 162| 0| virtual ~Node() {} 163| | 164| |private: 165| | unsigned int TypeID; 166| | StringRef Anchor; 167| | /// \brief The tag as typed in the document. 168| | StringRef Tag; 169| |}; 170| | 171| |/// \brief A null value. 172| |/// 173| |/// Example: 174| |/// !!null null 175| |class NullNode : public Node { 176| | void anchor() override; 177| | 178| |public: 179| | NullNode(std::unique_ptr &D) 180| 0| : Node(NK_Null, D, StringRef(), StringRef()) {} 181| | 182| 0| static inline bool classof(const Node *N) { return N->getType() == NK_Null; } 183| |}; 184| | 185| |/// \brief A scalar node is an opaque datum that can be presented as a 186| |/// series of zero or more Unicode scalar values. 187| |/// 188| |/// Example: 189| |/// Adena 190| |class ScalarNode : public Node { 191| | void anchor() override; 192| | 193| |public: 194| | ScalarNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 195| | StringRef Val) 196| 0| : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { 197| 0| SMLoc Start = SMLoc::getFromPointer(Val.begin()); 198| 0| SMLoc End = SMLoc::getFromPointer(Val.end()); 199| 0| SourceRange = SMRange(Start, End); 200| 0| } 201| | 202| | // Return Value without any escaping or folding or other fun YAML stuff. This 203| | // is the exact bytes that are contained in the file (after conversion to 204| | // utf8). 205| 0| StringRef getRawValue() const { return Value; } 206| | 207| | /// \brief Gets the value of this node as a StringRef. 208| | /// 209| | /// \param Storage is used to store the content of the returned StringRef iff 210| | /// it requires any modification from how it appeared in the source. 211| | /// This happens with escaped characters and multi-line literals. 212| | StringRef getValue(SmallVectorImpl &Storage) const; 213| | 214| | static inline bool classof(const Node *N) { 215| | return N->getType() == NK_Scalar; 216| | } 217| | 218| |private: 219| | StringRef Value; 220| | 221| | StringRef unescapeDoubleQuoted(StringRef UnquotedValue, 222| | StringRef::size_type Start, 223| | SmallVectorImpl &Storage) const; 224| |}; 225| | 226| |/// \brief A key and value pair. While not technically a Node under the YAML 227| |/// representation graph, it is easier to treat them this way. 228| |/// 229| |/// TODO: Consider making this not a child of Node. 230| |/// 231| |/// Example: 232| |/// Section: .text 233| |class KeyValueNode : public Node { 234| | void anchor() override; 235| | 236| |public: 237| | KeyValueNode(std::unique_ptr &D) 238| | : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), 239| 0| Value(nullptr) {} 240| | 241| | /// \brief Parse and return the key. 242| | /// 243| | /// This may be called multiple times. 244| | /// 245| | /// \returns The key, or nullptr if failed() == true. 246| | Node *getKey(); 247| | 248| | /// \brief Parse and return the value. 249| | /// 250| | /// This may be called multiple times. 251| | /// 252| | /// \returns The value, or nullptr if failed() == true. 253| | Node *getValue(); 254| | 255| 0| void skip() override { 256| 0| getKey()->skip(); 257| 0| getValue()->skip(); 258| 0| } 259| | 260| 0| static inline bool classof(const Node *N) { 261| 0| return N->getType() == NK_KeyValue; 262| 0| } 263| | 264| |private: 265| | Node *Key; 266| | Node *Value; 267| |}; 268| | 269| |/// \brief This is an iterator abstraction over YAML collections shared by both 270| |/// sequences and maps. 271| |/// 272| |/// BaseT must have a ValueT* member named CurrentEntry and a member function 273| |/// increment() which must set CurrentEntry to 0 to create an end iterator. 274| |template 275| |class basic_collection_iterator 276| | : public std::iterator { 277| |public: 278| 0| basic_collection_iterator() : Base(nullptr) {} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEC2Ev ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEC2Ev ------------------ 279| 0| basic_collection_iterator(BaseT *B) : Base(B) {} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEC2EPS2_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEC2EPS2_ ------------------ 280| | 281| 0| ValueT *operator->() const { 282| 0| assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 283| 0| return Base->CurrentEntry; 284| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEptEv ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEptEv ------------------ 285| | 286| | ValueT &operator*() const { 287| | assert(Base && Base->CurrentEntry && 288| | "Attempted to dereference end iterator!"); 289| | return *Base->CurrentEntry; 290| | } 291| | 292| | explicit operator ValueT *() const { 293| | assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 294| | return Base->CurrentEntry; 295| | } 296| | 297| 0| bool operator==(const basic_collection_iterator &Other) const { 298| 0| if (Base != Other.Base) 299| 0| return false; 300| 0| return !Base || Base->CurrentEntry == Other.Base->CurrentEntry; 301| 0| } ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEeqERKS4_ ------------------ | Unexecuted instantiation: _ZNK4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEeqERKS4_ ------------------ 302| 0| bool operator!=(const basic_collection_iterator &Other) { 303| 0| return !(*this == Other); 304| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEneERKS4_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEneERKS4_ ------------------ 305| | 306| 0| basic_collection_iterator &operator++() { 307| 0| assert(Base && "Attempted to advance iterator past end!"); 308| 0| Base->increment(); 309| 0| // Create an end iterator. 310| 0| if (!Base->CurrentEntry) 311| 0| Base = nullptr; 312| 0| return *this; 313| 0| } ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_11MappingNodeENS0_12KeyValueNodeEEppEv ------------------ | Unexecuted instantiation: _ZN4llvm4yaml25basic_collection_iteratorINS0_12SequenceNodeENS0_4NodeEEppEv ------------------ 314| | 315| |private: 316| | BaseT *Base; 317| |}; 318| | 319| |// The following two templates are used for both MappingNode and Sequence Node. 320| |template 321| 0|typename CollectionType::iterator begin(CollectionType &C) { 322| 0| assert(C.IsAtBeginning && "You may only iterate over a collection once!"); 323| 0| C.IsAtBeginning = false; 324| 0| typename CollectionType::iterator ret(&C); 325| 0| ++ret; 326| 0| return ret; 327| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml5beginINS0_11MappingNodeEEENT_8iteratorERS3_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml5beginINS0_12SequenceNodeEEENT_8iteratorERS3_ ------------------ 328| | 329| 0|template void skip(CollectionType &C) { 330| 0| // TODO: support skipping from the middle of a parsed collection ;/ 331| 0| assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); 332| 0| if (C.IsAtBeginning) 333| 0| for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; 334| 0| ++i) 335| 0| i->skip(); 336| 0|} ------------------ | Unexecuted instantiation: _ZN4llvm4yaml4skipINS0_11MappingNodeEEEvRT_ ------------------ | Unexecuted instantiation: _ZN4llvm4yaml4skipINS0_12SequenceNodeEEEvRT_ ------------------ 337| | 338| |/// \brief Represents a YAML map created from either a block map for a flow map. 339| |/// 340| |/// This parses the YAML stream as increment() is called. 341| |/// 342| |/// Example: 343| |/// Name: _main 344| |/// Scope: Global 345| |class MappingNode : public Node { 346| | void anchor() override; 347| | 348| |public: 349| | enum MappingType { 350| | MT_Block, 351| | MT_Flow, 352| | MT_Inline ///< An inline mapping node is used for "[key: value]". 353| | }; 354| | 355| | MappingNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 356| | MappingType MT) 357| | : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), 358| 0| IsAtEnd(false), CurrentEntry(nullptr) {} 359| | 360| | friend class basic_collection_iterator; 361| | typedef basic_collection_iterator iterator; 362| | template friend typename T::iterator yaml::begin(T &); 363| | template friend void yaml::skip(T &); 364| | 365| | iterator begin() { return yaml::begin(*this); } 366| | 367| 0| iterator end() { return iterator(); } 368| | 369| 0| void skip() override { yaml::skip(*this); } 370| | 371| | static inline bool classof(const Node *N) { 372| | return N->getType() == NK_Mapping; 373| | } 374| | 375| |private: 376| | MappingType Type; 377| | bool IsAtBeginning; 378| | bool IsAtEnd; 379| | KeyValueNode *CurrentEntry; 380| | 381| | void increment(); 382| |}; 383| | 384| |/// \brief Represents a YAML sequence created from either a block sequence for a 385| |/// flow sequence. 386| |/// 387| |/// This parses the YAML stream as increment() is called. 388| |/// 389| |/// Example: 390| |/// - Hello 391| |/// - World 392| |class SequenceNode : public Node { 393| | void anchor() override; 394| | 395| |public: 396| | enum SequenceType { 397| | ST_Block, 398| | ST_Flow, 399| | // Use for: 400| | // 401| | // key: 402| | // - val1 403| | // - val2 404| | // 405| | // As a BlockMappingEntry and BlockEnd are not created in this case. 406| | ST_Indentless 407| | }; 408| | 409| | SequenceNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, 410| | SequenceType ST) 411| | : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), 412| | IsAtEnd(false), 413| | WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. 414| 0| CurrentEntry(nullptr) {} 415| | 416| | friend class basic_collection_iterator; 417| | typedef basic_collection_iterator iterator; 418| | template friend typename T::iterator yaml::begin(T &); 419| | template friend void yaml::skip(T &); 420| | 421| | void increment(); 422| | 423| | iterator begin() { return yaml::begin(*this); } 424| | 425| 0| iterator end() { return iterator(); } 426| | 427| 0| void skip() override { yaml::skip(*this); } 428| | 429| | static inline bool classof(const Node *N) { 430| | return N->getType() == NK_Sequence; 431| | } 432| | 433| |private: 434| | SequenceType SeqType; 435| | bool IsAtBeginning; 436| | bool IsAtEnd; 437| | bool WasPreviousTokenFlowEntry; 438| | Node *CurrentEntry; 439| |}; 440| | 441| |/// \brief Represents an alias to a Node with an anchor. 442| |/// 443| |/// Example: 444| |/// *AnchorName 445| |class AliasNode : public Node { 446| | void anchor() override; 447| | 448| |public: 449| | AliasNode(std::unique_ptr &D, StringRef Val) 450| 0| : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} 451| | 452| 0| StringRef getName() const { return Name; } 453| | Node *getTarget(); 454| | 455| 0| static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } 456| | 457| |private: 458| | StringRef Name; 459| |}; 460| | 461| |/// \brief A YAML Stream is a sequence of Documents. A document contains a root 462| |/// node. 463| |class Document { 464| |public: 465| | /// \brief Root for parsing a node. Returns a single node. 466| | Node *parseBlockNode(); 467| | 468| | Document(Stream &ParentStream); 469| | 470| | /// \brief Finish parsing the current document and return true if there are 471| | /// more. Return false otherwise. 472| | bool skip(); 473| | 474| | /// \brief Parse and return the root level node. 475| 0| Node *getRoot() { 476| 0| if (Root) 477| 0| return Root; 478| 0| return Root = parseBlockNode(); 479| 0| } 480| | 481| 0| const std::map &getTagMap() const { return TagMap; } 482| | 483| |private: 484| | friend class Node; 485| | friend class document_iterator; 486| | 487| | /// \brief Stream to read tokens from. 488| | Stream &stream; 489| | 490| | /// \brief Used to allocate nodes to. All are destroyed without calling their 491| | /// destructor when the document is destroyed. 492| | BumpPtrAllocator NodeAllocator; 493| | 494| | /// \brief The root node. Used to support skipping a partially parsed 495| | /// document. 496| | Node *Root; 497| | 498| | /// \brief Maps tag prefixes to their expansion. 499| | std::map TagMap; 500| | 501| | Token &peekNext(); 502| | Token getNext(); 503| | void setError(const Twine &Message, Token &Location) const; 504| | bool failed() const; 505| | 506| | /// \brief Parse %BLAH directives and return true if any were encountered. 507| | bool parseDirectives(); 508| | 509| | /// \brief Parse %YAML 510| | void parseYAMLDirective(); 511| | 512| | /// \brief Parse %TAG 513| | void parseTAGDirective(); 514| | 515| | /// \brief Consume the next token and error if it is not \a TK. 516| | bool expectToken(int TK); 517| |}; 518| | 519| |/// \brief Iterator abstraction for Documents over a Stream. 520| |class document_iterator { 521| |public: 522| 0| document_iterator() : Doc(nullptr) {} 523| 0| document_iterator(std::unique_ptr &D) : Doc(&D) {} 524| | 525| 0| bool operator==(const document_iterator &Other) { 526| 0| if (isAtEnd() || Other.isAtEnd()) 527| 0| return isAtEnd() && Other.isAtEnd(); 528| 0| 529| 0| return Doc == Other.Doc; 530| 0| } 531| 0| bool operator!=(const document_iterator &Other) { return !(*this == Other); } 532| | 533| 0| document_iterator operator++() { 534| 0| assert(Doc && "incrementing iterator past the end."); 535| 0| if (!(*Doc)->skip()) { 536| 0| Doc->reset(nullptr); 537| 0| } else { 538| 0| Stream &S = (*Doc)->stream; 539| 0| Doc->reset(new Document(S)); 540| 0| } 541| 0| return *this; 542| 0| } 543| | 544| | Document &operator*() { return *Doc->get(); } 545| | 546| 0| std::unique_ptr &operator->() { return *Doc; } 547| | 548| |private: 549| 0| bool isAtEnd() const { return !Doc || !*Doc; } 550| | 551| | std::unique_ptr *Doc; 552| |}; 553| | 554| |} // End namespace yaml. 555| | 556| |} // End namespace llvm. 557| | 558| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/circular_raw_ostream.h: 1| |//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file contains raw_ostream implementations for streams to do circular 11| |// buffering of their output. 12| |// 13| |//===----------------------------------------------------------------------===// 14| | 15| |#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 16| |#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H 17| | 18| |#include "llvm/Support/raw_ostream.h" 19| | 20| |namespace llvm 21| |{ 22| | /// circular_raw_ostream - A raw_ostream which *can* save its data 23| | /// to a circular buffer, or can pass it through directly to an 24| | /// underlying stream if specified with a buffer of zero. 25| | /// 26| | class circular_raw_ostream : public raw_ostream { 27| | public: 28| | /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying 29| | /// stream and is responsible for cleanup, memory management 30| | /// issues, etc. 31| | /// 32| | static const bool TAKE_OWNERSHIP = true; 33| | 34| | /// REFERENCE_ONLY - Tell this stream it should not manage the 35| | /// held stream. 36| | /// 37| | static const bool REFERENCE_ONLY = false; 38| | 39| | private: 40| | /// TheStream - The real stream we output to. We set it to be 41| | /// unbuffered, since we're already doing our own buffering. 42| | /// 43| | raw_ostream *TheStream; 44| | 45| | /// OwnsStream - Are we responsible for managing the underlying 46| | /// stream? 47| | /// 48| | bool OwnsStream; 49| | 50| | /// BufferSize - The size of the buffer in bytes. 51| | /// 52| | size_t BufferSize; 53| | 54| | /// BufferArray - The actual buffer storage. 55| | /// 56| | char *BufferArray; 57| | 58| | /// Cur - Pointer to the current output point in BufferArray. 59| | /// 60| | char *Cur; 61| | 62| | /// Filled - Indicate whether the buffer has been completely 63| | /// filled. This helps avoid garbage output. 64| | /// 65| | bool Filled; 66| | 67| | /// Banner - A pointer to a banner to print before dumping the 68| | /// log. 69| | /// 70| | const char *Banner; 71| | 72| | /// flushBuffer - Dump the contents of the buffer to Stream. 73| | /// 74| 0| void flushBuffer() { 75| 0| if (Filled) 76| 0| // Write the older portion of the buffer. 77| 0| TheStream->write(Cur, BufferArray + BufferSize - Cur); 78| 0| // Write the newer portion of the buffer. 79| 0| TheStream->write(BufferArray, Cur - BufferArray); 80| 0| Cur = BufferArray; 81| 0| Filled = false; 82| 0| } 83| | 84| | void write_impl(const char *Ptr, size_t Size) override; 85| | 86| | /// current_pos - Return the current position within the stream, 87| | /// not counting the bytes currently in the buffer. 88| | /// 89| 0| uint64_t current_pos() const override { 90| 0| // This has the same effect as calling TheStream.current_pos(), 91| 0| // but that interface is private. 92| 0| return TheStream->tell() - TheStream->GetNumBytesInBuffer(); 93| 0| } 94| | 95| | public: 96| | /// circular_raw_ostream - Construct an optionally 97| | /// circular-buffered stream, handing it an underlying stream to 98| | /// do the "real" output. 99| | /// 100| | /// As a side effect, if BuffSize is nonzero, the given Stream is 101| | /// set to be Unbuffered. This is because circular_raw_ostream 102| | /// does its own buffering, so it doesn't want another layer of 103| | /// buffering to be happening underneath it. 104| | /// 105| | /// "Owns" tells the circular_raw_ostream whether it is 106| | /// responsible for managing the held stream, doing memory 107| | /// management of it, etc. 108| | /// 109| | circular_raw_ostream(raw_ostream &Stream, const char *Header, 110| | size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) 111| | : raw_ostream(/*unbuffered*/true), 112| | TheStream(nullptr), 113| | OwnsStream(Owns), 114| | BufferSize(BuffSize), 115| | BufferArray(nullptr), 116| | Filled(false), 117| 0| Banner(Header) { 118| 0| if (BufferSize != 0) 119| 0| BufferArray = new char[BufferSize]; 120| 0| Cur = BufferArray; 121| 0| setStream(Stream, Owns); 122| 0| } 123| | explicit circular_raw_ostream() 124| | : raw_ostream(/*unbuffered*/true), 125| | TheStream(nullptr), 126| | OwnsStream(REFERENCE_ONLY), 127| | BufferArray(nullptr), 128| | Filled(false), 129| 0| Banner("") { 130| 0| Cur = BufferArray; 131| 0| } 132| | 133| 0| ~circular_raw_ostream() { 134| 0| flush(); 135| 0| flushBufferWithBanner(); 136| 0| releaseStream(); 137| 0| delete[] BufferArray; 138| 0| } 139| | 140| | /// setStream - Tell the circular_raw_ostream to output a 141| | /// different stream. "Owns" tells circular_raw_ostream whether 142| | /// it should take responsibility for managing the underlying 143| | /// stream. 144| | /// 145| 0| void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { 146| 0| releaseStream(); 147| 0| TheStream = &Stream; 148| 0| OwnsStream = Owns; 149| 0| } 150| | 151| | /// flushBufferWithBanner - Force output of the buffer along with 152| | /// a small header. 153| | /// 154| | void flushBufferWithBanner(); 155| | 156| | private: 157| | /// releaseStream - Delete the held stream if needed. Otherwise, 158| | /// transfer the buffer settings from this circular_raw_ostream 159| | /// back to the underlying stream. 160| | /// 161| 0| void releaseStream() { 162| 0| if (!TheStream) 163| 0| return; 164| 0| if (OwnsStream) 165| 0| delete TheStream; 166| 0| } 167| | }; 168| |} // end llvm namespace 169| | 170| | 171| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/include/llvm/Support/raw_ostream.h: 1| |//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This file defines the raw_ostream class. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#ifndef LLVM_SUPPORT_RAW_OSTREAM_H 15| |#define LLVM_SUPPORT_RAW_OSTREAM_H 16| | 17| |#include "llvm/ADT/SmallVector.h" 18| |#include "llvm/ADT/StringRef.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/DataTypes.h" 21| |#include 22| | 23| |namespace llvm { 24| | class format_object_base; 25| | class FormattedString; 26| | class FormattedNumber; 27| | template 28| | class SmallVectorImpl; 29| | 30| | namespace sys { 31| | namespace fs { 32| | enum OpenFlags : unsigned; 33| | } 34| | } 35| | 36| |/// raw_ostream - This class implements an extremely fast bulk output stream 37| |/// that can *only* output to a stream. It does not support seeking, reopening, 38| |/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs 39| |/// a chunk at a time. 40| |class raw_ostream { 41| |private: 42| | void operator=(const raw_ostream &) = delete; 43| | raw_ostream(const raw_ostream &) = delete; 44| | 45| | /// The buffer is handled in such a way that the buffer is 46| | /// uninitialized, unbuffered, or out of space when OutBufCur >= 47| | /// OutBufEnd. Thus a single comparison suffices to determine if we 48| | /// need to take the slow path to write a single character. 49| | /// 50| | /// The buffer is in one of three states: 51| | /// 1. Unbuffered (BufferMode == Unbuffered) 52| | /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). 53| | /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && 54| | /// OutBufEnd - OutBufStart >= 1). 55| | /// 56| | /// If buffered, then the raw_ostream owns the buffer if (BufferMode == 57| | /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is 58| | /// managed by the subclass. 59| | /// 60| | /// If a subclass installs an external buffer using SetBuffer then it can wait 61| | /// for a \see write_impl() call to handle the data which has been put into 62| | /// this buffer. 63| | char *OutBufStart, *OutBufEnd, *OutBufCur; 64| | 65| | enum BufferKind { 66| | Unbuffered = 0, 67| | InternalBuffer, 68| | ExternalBuffer 69| | } BufferMode; 70| | 71| |public: 72| | // color order matches ANSI escape sequence, don't change 73| | enum Colors { 74| | BLACK=0, 75| | RED, 76| | GREEN, 77| | YELLOW, 78| | BLUE, 79| | MAGENTA, 80| | CYAN, 81| | WHITE, 82| | SAVEDCOLOR 83| | }; 84| | 85| | explicit raw_ostream(bool unbuffered=false) 86| 0| : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { 87| 0| // Start out ready to flush. 88| 0| OutBufStart = OutBufEnd = OutBufCur = nullptr; 89| 0| } 90| | 91| | virtual ~raw_ostream(); 92| | 93| | /// tell - Return the current offset with the file. 94| 0| uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } 95| | 96| | //===--------------------------------------------------------------------===// 97| | // Configuration Interface 98| | //===--------------------------------------------------------------------===// 99| | 100| | /// SetBuffered - Set the stream to be buffered, with an automatically 101| | /// determined buffer size. 102| | void SetBuffered(); 103| | 104| | /// SetBufferSize - Set the stream to be buffered, using the 105| | /// specified buffer size. 106| 0| void SetBufferSize(size_t Size) { 107| 0| flush(); 108| 0| SetBufferAndMode(new char[Size], Size, InternalBuffer); 109| 0| } 110| | 111| 0| size_t GetBufferSize() const { 112| 0| // If we're supposed to be buffered but haven't actually gotten around 113| 0| // to allocating the buffer yet, return the value that would be used. 114| 0| if (BufferMode != Unbuffered && OutBufStart == nullptr) 115| 0| return preferred_buffer_size(); 116| 0| 117| 0| // Otherwise just return the size of the allocated buffer. 118| 0| return OutBufEnd - OutBufStart; 119| 0| } 120| | 121| | /// SetUnbuffered - Set the stream to be unbuffered. When 122| | /// unbuffered, the stream will flush after every write. This routine 123| | /// will also flush the buffer immediately when the stream is being 124| | /// set to unbuffered. 125| 0| void SetUnbuffered() { 126| 0| flush(); 127| 0| SetBufferAndMode(nullptr, 0, Unbuffered); 128| 0| } 129| | 130| 0| size_t GetNumBytesInBuffer() const { 131| 0| return OutBufCur - OutBufStart; 132| 0| } 133| | 134| | //===--------------------------------------------------------------------===// 135| | // Data Output Interface 136| | //===--------------------------------------------------------------------===// 137| | 138| 0| void flush() { 139| 0| if (OutBufCur != OutBufStart) 140| 0| flush_nonempty(); 141| 0| } 142| | 143| 0| raw_ostream &operator<<(char C) { 144| 0| if (OutBufCur >= OutBufEnd) 145| 0| return write(C); 146| 0| *OutBufCur++ = C; 147| 0| return *this; 148| 0| } 149| | 150| 0| raw_ostream &operator<<(unsigned char C) { 151| 0| if (OutBufCur >= OutBufEnd) 152| 0| return write(C); 153| 0| *OutBufCur++ = C; 154| 0| return *this; 155| 0| } 156| | 157| 0| raw_ostream &operator<<(signed char C) { 158| 0| if (OutBufCur >= OutBufEnd) 159| 0| return write(C); 160| 0| *OutBufCur++ = C; 161| 0| return *this; 162| 0| } 163| | 164| 0| raw_ostream &operator<<(StringRef Str) { 165| 0| // Inline fast path, particularly for strings with a known length. 166| 0| size_t Size = Str.size(); 167| 0| 168| 0| // Make sure we can use the fast path. 169| 0| if (Size > (size_t)(OutBufEnd - OutBufCur)) 170| 0| return write(Str.data(), Size); 171| 0| 172| 0| memcpy(OutBufCur, Str.data(), Size); 173| 0| OutBufCur += Size; 174| 0| return *this; 175| 0| } 176| | 177| 0| raw_ostream &operator<<(const char *Str) { 178| 0| // Inline fast path, particularly for constant strings where a sufficiently 179| 0| // smart compiler will simplify strlen. 180| 0| 181| 0| return this->operator<<(StringRef(Str)); 182| 0| } 183| | 184| 0| raw_ostream &operator<<(const std::string &Str) { 185| 0| // Avoid the fast path, it would only increase code size for a marginal win. 186| 0| return write(Str.data(), Str.length()); 187| 0| } 188| | 189| | raw_ostream &operator<<(const llvm::SmallVectorImpl &Str) { 190| | return write(Str.data(), Str.size()); 191| | } 192| | 193| | raw_ostream &operator<<(unsigned long N); 194| | raw_ostream &operator<<(long N); 195| | raw_ostream &operator<<(unsigned long long N); 196| | raw_ostream &operator<<(long long N); 197| | raw_ostream &operator<<(const void *P); 198| 0| raw_ostream &operator<<(unsigned int N) { 199| 0| return this->operator<<(static_cast(N)); 200| 0| } 201| | 202| 0| raw_ostream &operator<<(int N) { 203| 0| return this->operator<<(static_cast(N)); 204| 0| } 205| | 206| | raw_ostream &operator<<(double N); 207| | 208| | /// write_hex - Output \p N in hexadecimal, without any prefix or padding. 209| | raw_ostream &write_hex(unsigned long long N); 210| | 211| | /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and 212| | /// anything that doesn't satisfy std::isprint into an escape sequence. 213| | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); 214| | 215| | raw_ostream &write(unsigned char C); 216| | raw_ostream &write(const char *Ptr, size_t Size); 217| | 218| | // Formatted output, see the format() function in Support/Format.h. 219| | raw_ostream &operator<<(const format_object_base &Fmt); 220| | 221| | // Formatted output, see the leftJustify() function in Support/Format.h. 222| | raw_ostream &operator<<(const FormattedString &); 223| | 224| | // Formatted output, see the formatHex() function in Support/Format.h. 225| | raw_ostream &operator<<(const FormattedNumber &); 226| | 227| | /// indent - Insert 'NumSpaces' spaces. 228| | raw_ostream &indent(unsigned NumSpaces); 229| | 230| | 231| | /// Changes the foreground color of text that will be output from this point 232| | /// forward. 233| | /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to 234| | /// change only the bold attribute, and keep colors untouched 235| | /// @param Bold bold/brighter text, default false 236| | /// @param BG if true change the background, default: change foreground 237| | /// @returns itself so it can be used within << invocations 238| | virtual raw_ostream &changeColor(enum Colors Color, 239| | bool Bold = false, 240| 0| bool BG = false) { 241| 0| (void)Color; 242| 0| (void)Bold; 243| 0| (void)BG; 244| 0| return *this; 245| 0| } 246| | 247| | /// Resets the colors to terminal defaults. Call this when you are done 248| | /// outputting colored text, or before program exit. 249| 0| virtual raw_ostream &resetColor() { return *this; } 250| | 251| | /// Reverses the forground and background colors. 252| 0| virtual raw_ostream &reverseColor() { return *this; } 253| | 254| | /// This function determines if this stream is connected to a "tty" or 255| | /// "console" window. That is, the output would be displayed to the user 256| | /// rather than being put on a pipe or stored in a file. 257| 0| virtual bool is_displayed() const { return false; } 258| | 259| | /// This function determines if this stream is displayed and supports colors. 260| 0| virtual bool has_colors() const { return is_displayed(); } 261| | 262| | //===--------------------------------------------------------------------===// 263| | // Subclass Interface 264| | //===--------------------------------------------------------------------===// 265| | 266| |private: 267| | /// write_impl - The is the piece of the class that is implemented 268| | /// by subclasses. This writes the \p Size bytes starting at 269| | /// \p Ptr to the underlying stream. 270| | /// 271| | /// This function is guaranteed to only be called at a point at which it is 272| | /// safe for the subclass to install a new buffer via SetBuffer. 273| | /// 274| | /// \param Ptr The start of the data to be written. For buffered streams this 275| | /// is guaranteed to be the start of the buffer. 276| | /// 277| | /// \param Size The number of bytes to be written. 278| | /// 279| | /// \invariant { Size > 0 } 280| | virtual void write_impl(const char *Ptr, size_t Size) = 0; 281| | 282| | // An out of line virtual method to provide a home for the class vtable. 283| | virtual void handle(); 284| | 285| | /// current_pos - Return the current position within the stream, not 286| | /// counting the bytes currently in the buffer. 287| | virtual uint64_t current_pos() const = 0; 288| | 289| |protected: 290| | /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is 291| | /// intended for use only by subclasses which can arrange for the output to go 292| | /// directly into the desired output buffer, instead of being copied on each 293| | /// flush. 294| 0| void SetBuffer(char *BufferStart, size_t Size) { 295| 0| SetBufferAndMode(BufferStart, Size, ExternalBuffer); 296| 0| } 297| | 298| | /// preferred_buffer_size - Return an efficient buffer size for the 299| | /// underlying output mechanism. 300| | virtual size_t preferred_buffer_size() const; 301| | 302| | /// getBufferStart - Return the beginning of the current stream buffer, or 0 303| | /// if the stream is unbuffered. 304| 0| const char *getBufferStart() const { return OutBufStart; } 305| | 306| | //===--------------------------------------------------------------------===// 307| | // Private Interface 308| | //===--------------------------------------------------------------------===// 309| |private: 310| | /// SetBufferAndMode - Install the given buffer and mode. 311| | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); 312| | 313| | /// flush_nonempty - Flush the current buffer, which is known to be 314| | /// non-empty. This outputs the currently buffered data and resets 315| | /// the buffer to empty. 316| | void flush_nonempty(); 317| | 318| | /// copy_to_buffer - Copy data into the buffer. Size must not be 319| | /// greater than the number of unused bytes in the buffer. 320| | void copy_to_buffer(const char *Ptr, size_t Size); 321| |}; 322| | 323| |//===----------------------------------------------------------------------===// 324| |// File Output Streams 325| |//===----------------------------------------------------------------------===// 326| | 327| |/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. 328| |/// 329| |class raw_fd_ostream : public raw_ostream { 330| | int FD; 331| | bool ShouldClose; 332| | 333| | /// Error This flag is true if an error of any kind has been detected. 334| | /// 335| | bool Error; 336| | 337| | /// Controls whether the stream should attempt to use atomic writes, when 338| | /// possible. 339| | bool UseAtomicWrites; 340| | 341| | uint64_t pos; 342| | 343| | /// write_impl - See raw_ostream::write_impl. 344| | void write_impl(const char *Ptr, size_t Size) override; 345| | 346| | /// current_pos - Return the current position within the stream, not 347| | /// counting the bytes currently in the buffer. 348| 0| uint64_t current_pos() const override { return pos; } 349| | 350| | /// preferred_buffer_size - Determine an efficient buffer size. 351| | size_t preferred_buffer_size() const override; 352| | 353| | /// error_detected - Set the flag indicating that an output error has 354| | /// been encountered. 355| 0| void error_detected() { Error = true; } 356| | 357| |public: 358| | /// Open the specified file for writing. If an error occurs, information 359| | /// about the error is put into EC, and the stream should be immediately 360| | /// destroyed; 361| | /// \p Flags allows optional flags to control how the file will be opened. 362| | /// 363| | /// As a special case, if Filename is "-", then the stream will use 364| | /// STDOUT_FILENO instead of opening a file. Note that it will still consider 365| | /// itself to own the file descriptor. In particular, it will close the 366| | /// file descriptor when it is done (this is necessary to detect 367| | /// output errors). 368| | raw_fd_ostream(StringRef Filename, std::error_code &EC, 369| | sys::fs::OpenFlags Flags); 370| | 371| | /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 372| | /// ShouldClose is true, this closes the file when the stream is destroyed. 373| | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); 374| | 375| | ~raw_fd_ostream(); 376| | 377| | /// close - Manually flush the stream and close the file. 378| | /// Note that this does not call fsync. 379| | void close(); 380| | 381| | /// seek - Flushes the stream and repositions the underlying file descriptor 382| | /// position to the offset specified from the beginning of the file. 383| | uint64_t seek(uint64_t off); 384| | 385| | /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for 386| | /// individual output routines where possible. 387| | /// 388| | /// Note that because raw_ostream's are typically buffered, this flag is only 389| | /// sensible when used on unbuffered streams which will flush their output 390| | /// immediately. 391| 0| void SetUseAtomicWrites(bool Value) { 392| 0| UseAtomicWrites = Value; 393| 0| } 394| | 395| | raw_ostream &changeColor(enum Colors colors, bool bold=false, 396| | bool bg=false) override; 397| | raw_ostream &resetColor() override; 398| | 399| | raw_ostream &reverseColor() override; 400| | 401| | bool is_displayed() const override; 402| | 403| | bool has_colors() const override; 404| | 405| | /// has_error - Return the value of the flag in this raw_fd_ostream indicating 406| | /// whether an output error has been encountered. 407| | /// This doesn't implicitly flush any pending output. Also, it doesn't 408| | /// guarantee to detect all errors unless the stream has been closed. 409| 0| bool has_error() const { 410| 0| return Error; 411| 0| } 412| | 413| | /// clear_error - Set the flag read by has_error() to false. If the error 414| | /// flag is set at the time when this raw_ostream's destructor is called, 415| | /// report_fatal_error is called to report the error. Use clear_error() 416| | /// after handling the error to avoid this behavior. 417| | /// 418| | /// "Errors should never pass silently. 419| | /// Unless explicitly silenced." 420| | /// - from The Zen of Python, by Tim Peters 421| | /// 422| 0| void clear_error() { 423| 0| Error = false; 424| 0| } 425| |}; 426| | 427| |/// outs() - This returns a reference to a raw_ostream for standard output. 428| |/// Use it like: outs() << "foo" << "bar"; 429| |raw_ostream &outs(); 430| | 431| |/// errs() - This returns a reference to a raw_ostream for standard error. 432| |/// Use it like: errs() << "foo" << "bar"; 433| |raw_ostream &errs(); 434| | 435| |/// nulls() - This returns a reference to a raw_ostream which simply discards 436| |/// output. 437| |raw_ostream &nulls(); 438| | 439| |//===----------------------------------------------------------------------===// 440| |// Output Stream Adaptors 441| |//===----------------------------------------------------------------------===// 442| | 443| |/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a 444| |/// simple adaptor class. This class does not encounter output errors. 445| |class raw_string_ostream : public raw_ostream { 446| | std::string &OS; 447| | 448| | /// write_impl - See raw_ostream::write_impl. 449| | void write_impl(const char *Ptr, size_t Size) override; 450| | 451| | /// current_pos - Return the current position within the stream, not 452| | /// counting the bytes currently in the buffer. 453| 0| uint64_t current_pos() const override { return OS.size(); } 454| |public: 455| 0| explicit raw_string_ostream(std::string &O) : OS(O) {} 456| | ~raw_string_ostream(); 457| | 458| | /// str - Flushes the stream contents to the target string and returns 459| | /// the string's reference. 460| 0| std::string& str() { 461| 0| flush(); 462| 0| return OS; 463| 0| } 464| |}; 465| | 466| |/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or 467| |/// SmallString. This is a simple adaptor class. This class does not 468| |/// encounter output errors. 469| |class raw_svector_ostream : public raw_ostream { 470| | SmallVectorImpl &OS; 471| | 472| | /// write_impl - See raw_ostream::write_impl. 473| | void write_impl(const char *Ptr, size_t Size) override; 474| | 475| | /// current_pos - Return the current position within the stream, not 476| | /// counting the bytes currently in the buffer. 477| | uint64_t current_pos() const override; 478| |public: 479| | /// Construct a new raw_svector_ostream. 480| | /// 481| | /// \param O The vector to write to; this should generally have at least 128 482| | /// bytes free to avoid any extraneous memory overhead. 483| | explicit raw_svector_ostream(SmallVectorImpl &O); 484| | ~raw_svector_ostream(); 485| | 486| | /// resync - This is called when the SmallVector we're appending to is changed 487| | /// outside of the raw_svector_ostream's control. It is only safe to do this 488| | /// if the raw_svector_ostream has previously been flushed. 489| | void resync(); 490| | 491| | /// str - Flushes the stream contents to the target vector and return a 492| | /// StringRef for the vector contents. 493| | StringRef str(); 494| |}; 495| | 496| |/// raw_null_ostream - A raw_ostream that discards all output. 497| |class raw_null_ostream : public raw_ostream { 498| | /// write_impl - See raw_ostream::write_impl. 499| | void write_impl(const char *Ptr, size_t size) override; 500| | 501| | /// current_pos - Return the current position within the stream, not 502| | /// counting the bytes currently in the buffer. 503| | uint64_t current_pos() const override; 504| | 505| |public: 506| 0| explicit raw_null_ostream() {} 507| | ~raw_null_ostream(); 508| |}; 509| | 510| |} // end llvm namespace 511| | 512| |#endif /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-llbuild/lib/llvm/Support/raw_ostream.cpp: 1| |//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// 2| |// 3| |// The LLVM Compiler Infrastructure 4| |// 5| |// This file is distributed under the University of Illinois Open Source 6| |// License. See LICENSE.TXT for details. 7| |// 8| |//===----------------------------------------------------------------------===// 9| |// 10| |// This implements support for bulk buffered stream output. 11| |// 12| |//===----------------------------------------------------------------------===// 13| | 14| |#include "llvm/Support/raw_ostream.h" 15| |#include "llvm/ADT/STLExtras.h" 16| |#include "llvm/ADT/SmallVector.h" 17| |#include "llvm/ADT/StringExtras.h" 18| |#include "llvm/Config/config.h" 19| |#include "llvm/Support/Compiler.h" 20| |#include "llvm/Support/ErrorHandling.h" 21| |#include "llvm/Support/FileSystem.h" 22| |#include "llvm/Support/Format.h" 23| |#include "llvm/Support/MathExtras.h" 24| |#include "llvm/Support/Process.h" 25| |#include "llvm/Support/Program.h" 26| |#include 27| |#include 28| |#include 29| |#include 30| | 31| |// may provide O_BINARY. 32| |#if defined(HAVE_FCNTL_H) 33| |# include 34| |#endif 35| | 36| |#if defined(HAVE_UNISTD_H) 37| |# include 38| |#endif 39| |#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) 40| |# include 41| |#endif 42| | 43| |#if defined(__CYGWIN__) 44| |#include 45| |#endif 46| | 47| |#if defined(_MSC_VER) 48| |#include 49| |#ifndef STDIN_FILENO 50| |# define STDIN_FILENO 0 51| |#endif 52| |#ifndef STDOUT_FILENO 53| |# define STDOUT_FILENO 1 54| |#endif 55| |#ifndef STDERR_FILENO 56| |# define STDERR_FILENO 2 57| |#endif 58| |#endif 59| | 60| |using namespace llvm; 61| | 62| 0|raw_ostream::~raw_ostream() { 63| 0| // raw_ostream's subclasses should take care to flush the buffer 64| 0| // in their destructors. 65| 0| assert(OutBufCur == OutBufStart && 66| 0| "raw_ostream destructor called with non-empty buffer!"); 67| 0| 68| 0| if (BufferMode == InternalBuffer) 69| 0| delete [] OutBufStart; 70| 0|} 71| | 72| |// An out of line virtual method to provide a home for the class vtable. 73| 0|void raw_ostream::handle() {} 74| | 75| 0|size_t raw_ostream::preferred_buffer_size() const { 76| 0| // BUFSIZ is intended to be a reasonable default. 77| 0| return BUFSIZ; 78| 0|} 79| | 80| 0|void raw_ostream::SetBuffered() { 81| 0| // Ask the subclass to determine an appropriate buffer size. 82| 0| if (size_t Size = preferred_buffer_size()) 83| 0| SetBufferSize(Size); 84| 0| else 85| 0| // It may return 0, meaning this stream should be unbuffered. 86| 0| SetUnbuffered(); 87| 0|} 88| | 89| |void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, 90| 0| BufferKind Mode) { 91| 0| assert(((Mode == Unbuffered && !BufferStart && Size == 0) || 92| 0| (Mode != Unbuffered && BufferStart && Size != 0)) && 93| 0| "stream must be unbuffered or have at least one byte"); 94| 0| // Make sure the current buffer is free of content (we can't flush here; the 95| 0| // child buffer management logic will be in write_impl). 96| 0| assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); 97| 0| 98| 0| if (BufferMode == InternalBuffer) 99| 0| delete [] OutBufStart; 100| 0| OutBufStart = BufferStart; 101| 0| OutBufEnd = OutBufStart+Size; 102| 0| OutBufCur = OutBufStart; 103| 0| BufferMode = Mode; 104| 0| 105| 0| assert(OutBufStart <= OutBufEnd && "Invalid size!"); 106| 0|} 107| | 108| 0|raw_ostream &raw_ostream::operator<<(unsigned long N) { 109| 0| // Zero is a special case. 110| 0| if (N == 0) 111| 0| return *this << '0'; 112| 0| 113| 0| char NumberBuffer[20]; 114| 0| char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 115| 0| char *CurPtr = EndPtr; 116| 0| 117| 0| while (N) { 118| 0| *--CurPtr = '0' + char(N % 10); 119| 0| N /= 10; 120| 0| } 121| 0| return write(CurPtr, EndPtr-CurPtr); 122| 0|} 123| | 124| 0|raw_ostream &raw_ostream::operator<<(long N) { 125| 0| if (N < 0) { 126| 0| *this << '-'; 127| 0| // Avoid undefined behavior on LONG_MIN with a cast. 128| 0| N = -(unsigned long)N; 129| 0| } 130| 0| 131| 0| return this->operator<<(static_cast(N)); 132| 0|} 133| | 134| 0|raw_ostream &raw_ostream::operator<<(unsigned long long N) { 135| 0| // Output using 32-bit div/mod when possible. 136| 0| if (N == static_cast(N)) 137| 0| return this->operator<<(static_cast(N)); 138| 0| 139| 0| char NumberBuffer[20]; 140| 0| char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 141| 0| char *CurPtr = EndPtr; 142| 0| 143| 0| while (N) { 144| 0| *--CurPtr = '0' + char(N % 10); 145| 0| N /= 10; 146| 0| } 147| 0| return write(CurPtr, EndPtr-CurPtr); 148| 0|} 149| | 150| 0|raw_ostream &raw_ostream::operator<<(long long N) { 151| 0| if (N < 0) { 152| 0| *this << '-'; 153| 0| // Avoid undefined behavior on INT64_MIN with a cast. 154| 0| N = -(unsigned long long)N; 155| 0| } 156| 0| 157| 0| return this->operator<<(static_cast(N)); 158| 0|} 159| | 160| 0|raw_ostream &raw_ostream::write_hex(unsigned long long N) { 161| 0| // Zero is a special case. 162| 0| if (N == 0) 163| 0| return *this << '0'; 164| 0| 165| 0| char NumberBuffer[20]; 166| 0| char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 167| 0| char *CurPtr = EndPtr; 168| 0| 169| 0| while (N) { 170| 0| uintptr_t x = N % 16; 171| 0| *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10); 172| 0| N /= 16; 173| 0| } 174| 0| 175| 0| return write(CurPtr, EndPtr-CurPtr); 176| 0|} 177| | 178| |raw_ostream &raw_ostream::write_escaped(StringRef Str, 179| 0| bool UseHexEscapes) { 180| 0| for (unsigned i = 0, e = Str.size(); i != e; ++i) { 181| 0| unsigned char c = Str[i]; 182| 0| 183| 0| switch (c) { 184| 0| case '\\': 185| 0| *this << '\\' << '\\'; 186| 0| break; 187| 0| case '\t': 188| 0| *this << '\\' << 't'; 189| 0| break; 190| 0| case '\n': 191| 0| *this << '\\' << 'n'; 192| 0| break; 193| 0| case '"': 194| 0| *this << '\\' << '"'; 195| 0| break; 196| 0| default: 197| 0| if (std::isprint(c)) { 198| 0| *this << c; 199| 0| break; 200| 0| } 201| 0| 202| 0| // Write out the escaped representation. 203| 0| if (UseHexEscapes) { 204| 0| *this << '\\' << 'x'; 205| 0| *this << hexdigit((c >> 4 & 0xF)); 206| 0| *this << hexdigit((c >> 0) & 0xF); 207| 0| } else { 208| 0| // Always use a full 3-character octal escape. 209| 0| *this << '\\'; 210| 0| *this << char('0' + ((c >> 6) & 7)); 211| 0| *this << char('0' + ((c >> 3) & 7)); 212| 0| *this << char('0' + ((c >> 0) & 7)); 213| 0| } 214| 0| } 215| 0| } 216| 0| 217| 0| return *this; 218| 0|} 219| | 220| 0|raw_ostream &raw_ostream::operator<<(const void *P) { 221| 0| *this << '0' << 'x'; 222| 0| 223| 0| return write_hex((uintptr_t) P); 224| 0|} 225| | 226| 0|raw_ostream &raw_ostream::operator<<(double N) { 227| |#ifdef _WIN32 228| | // On MSVCRT and compatible, output of %e is incompatible to Posix 229| | // by default. Number of exponent digits should be at least 2. "%+03d" 230| | // FIXME: Implement our formatter to here or Support/Format.h! 231| |#if __cplusplus >= 201103L && defined(__MINGW32__) 232| | // FIXME: It should be generic to C++11. 233| | if (N == 0.0 && std::signbit(N)) 234| | return *this << "-0.000000e+00"; 235| |#else 236| | int fpcl = _fpclass(N); 237| | 238| | // negative zero 239| | if (fpcl == _FPCLASS_NZ) 240| | return *this << "-0.000000e+00"; 241| |#endif 242| | 243| | char buf[16]; 244| | unsigned len; 245| | len = format("%e", N).snprint(buf, sizeof(buf)); 246| | if (len <= sizeof(buf) - 2) { 247| | if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { 248| | int cs = buf[len - 4]; 249| | if (cs == '+' || cs == '-') { 250| | int c1 = buf[len - 2]; 251| | int c0 = buf[len - 1]; 252| | if (isdigit(static_cast(c1)) && 253| | isdigit(static_cast(c0))) { 254| | // Trim leading '0': "...e+012" -> "...e+12\0" 255| | buf[len - 3] = c1; 256| | buf[len - 2] = c0; 257| | buf[--len] = 0; 258| | } 259| | } 260| | } 261| | return this->operator<<(buf); 262| | } 263| |#endif 264| | return this->operator<<(format("%e", N)); 265| 0|} 266| | 267| | 268| | 269| 0|void raw_ostream::flush_nonempty() { 270| 0| assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); 271| 0| size_t Length = OutBufCur - OutBufStart; 272| 0| OutBufCur = OutBufStart; 273| 0| write_impl(OutBufStart, Length); 274| 0|} 275| | 276| 0|raw_ostream &raw_ostream::write(unsigned char C) { 277| 0| // Group exceptional cases into a single branch. 278| 0| if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) { 279| 0| if (LLVM_UNLIKELY(!OutBufStart)) { 280| 0| if (BufferMode == Unbuffered) { 281| 0| write_impl(reinterpret_cast(&C), 1); 282| 0| return *this; 283| 0| } 284| 0| // Set up a buffer and start over. 285| 0| SetBuffered(); 286| 0| return write(C); 287| 0| } 288| 0| 289| 0| flush_nonempty(); 290| 0| } 291| 0| 292| 0| *OutBufCur++ = C; 293| 0| return *this; 294| 0|} 295| | 296| 0|raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { 297| 0| // Group exceptional cases into a single branch. 298| 0| if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) { 299| 0| if (LLVM_UNLIKELY(!OutBufStart)) { 300| 0| if (BufferMode == Unbuffered) { 301| 0| write_impl(Ptr, Size); 302| 0| return *this; 303| 0| } 304| 0| // Set up a buffer and start over. 305| 0| SetBuffered(); 306| 0| return write(Ptr, Size); 307| 0| } 308| 0| 309| 0| size_t NumBytes = OutBufEnd - OutBufCur; 310| 0| 311| 0| // If the buffer is empty at this point we have a string that is larger 312| 0| // than the buffer. Directly write the chunk that is a multiple of the 313| 0| // preferred buffer size and put the remainder in the buffer. 314| 0| if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) { 315| 0| assert(NumBytes != 0 && "undefined behavior"); 316| 0| size_t BytesToWrite = Size - (Size % NumBytes); 317| 0| write_impl(Ptr, BytesToWrite); 318| 0| size_t BytesRemaining = Size - BytesToWrite; 319| 0| if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) { 320| 0| // Too much left over to copy into our buffer. 321| 0| return write(Ptr + BytesToWrite, BytesRemaining); 322| 0| } 323| 0| copy_to_buffer(Ptr + BytesToWrite, BytesRemaining); 324| 0| return *this; 325| 0| } 326| 0| 327| 0| // We don't have enough space in the buffer to fit the string in. Insert as 328| 0| // much as possible, flush and start over with the remainder. 329| 0| copy_to_buffer(Ptr, NumBytes); 330| 0| flush_nonempty(); 331| 0| return write(Ptr + NumBytes, Size - NumBytes); 332| 0| } 333| 0| 334| 0| copy_to_buffer(Ptr, Size); 335| 0| 336| 0| return *this; 337| 0|} 338| | 339| 0|void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { 340| 0| assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); 341| 0| 342| 0| // Handle short strings specially, memcpy isn't very good at very short 343| 0| // strings. 344| 0| switch (Size) { 345| 0| case 4: OutBufCur[3] = Ptr[3]; [[clang::fallthrough]]; 346| 0| case 3: OutBufCur[2] = Ptr[2]; [[clang::fallthrough]]; 347| 0| case 2: OutBufCur[1] = Ptr[1]; [[clang::fallthrough]]; 348| 0| case 1: OutBufCur[0] = Ptr[0]; [[clang::fallthrough]]; 349| 0| case 0: break; 350| 0| default: 351| 0| memcpy(OutBufCur, Ptr, Size); 352| 0| break; 353| 0| } 354| 0| 355| 0| OutBufCur += Size; 356| 0|} 357| | 358| |// Formatted output. 359| 0|raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { 360| 0| // If we have more than a few bytes left in our output buffer, try 361| 0| // formatting directly onto its end. 362| 0| size_t NextBufferSize = 127; 363| 0| size_t BufferBytesLeft = OutBufEnd - OutBufCur; 364| 0| if (BufferBytesLeft > 3) { 365| 0| size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); 366| 0| 367| 0| // Common case is that we have plenty of space. 368| 0| if (BytesUsed <= BufferBytesLeft) { 369| 0| OutBufCur += BytesUsed; 370| 0| return *this; 371| 0| } 372| 0| 373| 0| // Otherwise, we overflowed and the return value tells us the size to try 374| 0| // again with. 375| 0| NextBufferSize = BytesUsed; 376| 0| } 377| 0| 378| 0| // If we got here, we didn't have enough space in the output buffer for the 379| 0| // string. Try printing into a SmallVector that is resized to have enough 380| 0| // space. Iterate until we win. 381| 0| SmallVector V; 382| 0| 383| 0| while (1) { 384| 0| V.resize(NextBufferSize); 385| 0| 386| 0| // Try formatting into the SmallVector. 387| 0| size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); 388| 0| 389| 0| // If BytesUsed fit into the vector, we win. 390| 0| if (BytesUsed <= NextBufferSize) 391| 0| return write(V.data(), BytesUsed); 392| 0| 393| 0| // Otherwise, try again with a new size. 394| 0| assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); 395| 0| NextBufferSize = BytesUsed; 396| 0| } 397| 0|} 398| | 399| 0|raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { 400| 0| unsigned Len = FS.Str.size(); 401| 0| int PadAmount = FS.Width - Len; 402| 0| if (FS.RightJustify && (PadAmount > 0)) 403| 0| this->indent(PadAmount); 404| 0| this->operator<<(FS.Str); 405| 0| if (!FS.RightJustify && (PadAmount > 0)) 406| 0| this->indent(PadAmount); 407| 0| return *this; 408| 0|} 409| | 410| 0|raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { 411| 0| if (FN.Hex) { 412| 0| unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; 413| 0| unsigned PrefixChars = FN.HexPrefix ? 2 : 0; 414| 0| unsigned Width = std::max(FN.Width, Nibbles + PrefixChars); 415| 0| 416| 0| char NumberBuffer[20] = "0x0000000000000000"; 417| 0| if (!FN.HexPrefix) 418| 0| NumberBuffer[1] = '0'; 419| 0| char *EndPtr = NumberBuffer+Width; 420| 0| char *CurPtr = EndPtr; 421| 0| const char A = FN.Upper ? 'A' : 'a'; 422| 0| unsigned long long N = FN.HexValue; 423| 0| while (N) { 424| 0| uintptr_t x = N % 16; 425| 0| *--CurPtr = (x < 10 ? '0' + x : A + x - 10); 426| 0| N /= 16; 427| 0| } 428| 0| 429| 0| return write(NumberBuffer, Width); 430| 0| } else { 431| 0| // Zero is a special case. 432| 0| if (FN.DecValue == 0) { 433| 0| this->indent(FN.Width-1); 434| 0| return *this << '0'; 435| 0| } 436| 0| char NumberBuffer[32]; 437| 0| char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 438| 0| char *CurPtr = EndPtr; 439| 0| bool Neg = (FN.DecValue < 0); 440| 0| uint64_t N = Neg ? -static_cast(FN.DecValue) : FN.DecValue; 441| 0| while (N) { 442| 0| *--CurPtr = '0' + char(N % 10); 443| 0| N /= 10; 444| 0| } 445| 0| int Len = EndPtr - CurPtr; 446| 0| int Pad = FN.Width - Len; 447| 0| if (Neg) 448| 0| --Pad; 449| 0| if (Pad > 0) 450| 0| this->indent(Pad); 451| 0| if (Neg) 452| 0| *this << '-'; 453| 0| return write(CurPtr, Len); 454| 0| } 455| 0|} 456| | 457| | 458| |/// indent - Insert 'NumSpaces' spaces. 459| 0|raw_ostream &raw_ostream::indent(unsigned NumSpaces) { 460| 0| static const char Spaces[] = " " 461| 0| " " 462| 0| " "; 463| 0| 464| 0| // Usually the indentation is small, handle it with a fastpath. 465| 0| if (NumSpaces < array_lengthof(Spaces)) 466| 0| return write(Spaces, NumSpaces); 467| 0| 468| 0| while (NumSpaces) { 469| 0| unsigned NumToWrite = std::min(NumSpaces, 470| 0| (unsigned)array_lengthof(Spaces)-1); 471| 0| write(Spaces, NumToWrite); 472| 0| NumSpaces -= NumToWrite; 473| 0| } 474| 0| return *this; 475| 0|} 476| | 477| | 478| |//===----------------------------------------------------------------------===// 479| |// Formatted Output 480| |//===----------------------------------------------------------------------===// 481| | 482| |// Out of line virtual method. 483| 0|void format_object_base::home() { 484| 0|} 485| | 486| |//===----------------------------------------------------------------------===// 487| |// raw_fd_ostream 488| |//===----------------------------------------------------------------------===// 489| | 490| |raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, 491| | sys::fs::OpenFlags Flags) 492| 0| : Error(false), UseAtomicWrites(false), pos(0) { 493| 0| EC = std::error_code(); 494| 0| // Handle "-" as stdout. Note that when we do this, we consider ourself 495| 0| // the owner of stdout. This means that we can do things like close the 496| 0| // file descriptor when we're done and set the "binary" flag globally. 497| 0| if (Filename == "-") { 498| 0| FD = STDOUT_FILENO; 499| 0| // If user requested binary then put stdout into binary mode if 500| 0| // possible. 501| 0| if (!(Flags & sys::fs::F_Text)) 502| 0| sys::ChangeStdoutToBinary(); 503| 0| // Close stdout when we're done, to detect any output errors. 504| 0| ShouldClose = true; 505| 0| return; 506| 0| } 507| 0| 508| 0| EC = sys::fs::openFileForWrite(Filename, FD, Flags); 509| 0| 510| 0| if (EC) { 511| 0| ShouldClose = false; 512| 0| return; 513| 0| } 514| 0| 515| 0| // Ok, we successfully opened the file, so it'll need to be closed. 516| 0| ShouldClose = true; 517| 0|} 518| | 519| |/// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If 520| |/// ShouldClose is true, this closes the file when the stream is destroyed. 521| |raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) 522| | : raw_ostream(unbuffered), FD(fd), 523| 0| ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) { 524| |#ifdef O_BINARY 525| | // Setting STDOUT to binary mode is necessary in Win32 526| | // to avoid undesirable linefeed conversion. 527| | // Don't touch STDERR, or w*printf() (in assert()) would barf wide chars. 528| | if (fd == STDOUT_FILENO) 529| | setmode(fd, O_BINARY); 530| |#endif 531| | 532| 0| // Get the starting position. 533| 0| off_t loc = ::lseek(FD, 0, SEEK_CUR); 534| 0| if (loc == (off_t)-1) 535| 0| pos = 0; 536| 0| else 537| 0| pos = static_cast(loc); 538| 0|} 539| | 540| 0|raw_fd_ostream::~raw_fd_ostream() { 541| 0| if (FD >= 0) { 542| 0| flush(); 543| 0| if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) 544| 0| error_detected(); 545| 0| } 546| 0| 547| |#ifdef __MINGW32__ 548| | // On mingw, global dtors should not call exit(). 549| | // report_fatal_error() invokes exit(). We know report_fatal_error() 550| | // might not write messages to stderr when any errors were detected 551| | // on FD == 2. 552| | if (FD == 2) return; 553| |#endif 554| | 555| 0| // If there are any pending errors, report them now. Clients wishing 556| 0| // to avoid report_fatal_error calls should check for errors with 557| 0| // has_error() and clear the error flag with clear_error() before 558| 0| // destructing raw_ostream objects which may have errors. 559| 0| if (has_error()) 560| 0| report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false); 561| 0|} 562| | 563| | 564| 0|void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { 565| 0| assert(FD >= 0 && "File already closed."); 566| 0| pos += Size; 567| 0| 568| 0| do { 569| 0| ssize_t ret; 570| 0| 571| 0| // Check whether we should attempt to use atomic writes. 572| 0| if (LLVM_LIKELY(!UseAtomicWrites)) { 573| 0| ret = ::write(FD, Ptr, Size); 574| 0| } else { 575| 0| // Use ::writev() where available. 576| 0|#if defined(HAVE_WRITEV) 577| 0| const void *Addr = static_cast(Ptr); 578| 0| struct iovec IOV = {const_cast(Addr), Size }; 579| 0| ret = ::writev(FD, &IOV, 1); 580| |#else 581| | ret = ::write(FD, Ptr, Size); 582| |#endif 583| | } 584| 0| 585| 0| if (ret < 0) { 586| 0| // If it's a recoverable error, swallow it and retry the write. 587| 0| // 588| 0| // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since 589| 0| // raw_ostream isn't designed to do non-blocking I/O. However, some 590| 0| // programs, such as old versions of bjam, have mistakenly used 591| 0| // O_NONBLOCK. For compatibility, emulate blocking semantics by 592| 0| // spinning until the write succeeds. If you don't want spinning, 593| 0| // don't use O_NONBLOCK file descriptors with raw_ostream. 594| 0| if (errno == EINTR || errno == EAGAIN 595| 0|#ifdef EWOULDBLOCK 596| 0| || errno == EWOULDBLOCK 597| 0|#endif 598| 0| ) 599| 0| continue; 600| 0| 601| 0| // Otherwise it's a non-recoverable error. Note it and quit. 602| 0| error_detected(); 603| 0| break; 604| 0| } 605| 0| 606| 0| // The write may have written some or all of the data. Update the 607| 0| // size and buffer pointer to reflect the remainder that needs 608| 0| // to be written. If there are no bytes left, we're done. 609| 0| Ptr += ret; 610| 0| Size -= ret; 611| 0| } while (Size > 0); 612| 0|} 613| | 614| 0|void raw_fd_ostream::close() { 615| 0| assert(ShouldClose); 616| 0| ShouldClose = false; 617| 0| flush(); 618| 0| if (sys::Process::SafelyCloseFileDescriptor(FD)) 619| 0| error_detected(); 620| 0| FD = -1; 621| 0|} 622| | 623| 0|uint64_t raw_fd_ostream::seek(uint64_t off) { 624| 0| flush(); 625| 0| pos = ::lseek(FD, off, SEEK_SET); 626| 0| if (pos != off) 627| 0| error_detected(); 628| 0| return pos; 629| 0|} 630| | 631| 0|size_t raw_fd_ostream::preferred_buffer_size() const { 632| 0|#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix) 633| 0| // Windows and Minix have no st_blksize. 634| 0| assert(FD >= 0 && "File not yet open!"); 635| 0| struct stat statbuf; 636| 0| if (fstat(FD, &statbuf) != 0) 637| 0| return 0; 638| 0| 639| 0| // If this is a terminal, don't use buffering. Line buffering 640| 0| // would be a more traditional thing to do, but it's not worth 641| 0| // the complexity. 642| 0| if (S_ISCHR(statbuf.st_mode) && isatty(FD)) 643| 0| return 0; 644| 0| // Return the preferred block size. 645| 0| return statbuf.st_blksize; 646| |#else 647| | return raw_ostream::preferred_buffer_size(); 648| |#endif 649| |} 650| | 651| |raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, 652| 0| bool bg) { 653| 0| if (sys::Process::ColorNeedsFlush()) 654| 0| flush(); 655| 0| const char *colorcode = 656| 0| (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) 657| 0| : sys::Process::OutputColor(colors, bold, bg); 658| 0| if (colorcode) { 659| 0| size_t len = strlen(colorcode); 660| 0| write(colorcode, len); 661| 0| // don't account colors towards output characters 662| 0| pos -= len; 663| 0| } 664| 0| return *this; 665| 0|} 666| | 667| 0|raw_ostream &raw_fd_ostream::resetColor() { 668| 0| if (sys::Process::ColorNeedsFlush()) 669| 0| flush(); 670| 0| const char *colorcode = sys::Process::ResetColor(); 671| 0| if (colorcode) { 672| 0| size_t len = strlen(colorcode); 673| 0| write(colorcode, len); 674| 0| // don't account colors towards output characters 675| 0| pos -= len; 676| 0| } 677| 0| return *this; 678| 0|} 679| | 680| 0|raw_ostream &raw_fd_ostream::reverseColor() { 681| 0| if (sys::Process::ColorNeedsFlush()) 682| 0| flush(); 683| 0| const char *colorcode = sys::Process::OutputReverse(); 684| 0| if (colorcode) { 685| 0| size_t len = strlen(colorcode); 686| 0| write(colorcode, len); 687| 0| // don't account colors towards output characters 688| 0| pos -= len; 689| 0| } 690| 0| return *this; 691| 0|} 692| | 693| 0|bool raw_fd_ostream::is_displayed() const { 694| 0| return sys::Process::FileDescriptorIsDisplayed(FD); 695| 0|} 696| | 697| 0|bool raw_fd_ostream::has_colors() const { 698| 0| return sys::Process::FileDescriptorHasColors(FD); 699| 0|} 700| | 701| |//===----------------------------------------------------------------------===// 702| |// outs(), errs(), nulls() 703| |//===----------------------------------------------------------------------===// 704| | 705| |/// outs() - This returns a reference to a raw_ostream for standard output. 706| |/// Use it like: outs() << "foo" << "bar"; 707| 0|raw_ostream &llvm::outs() { 708| 0| // Set buffer settings to model stdout behavior. 709| 0| // Delete the file descriptor when the program exits, forcing error 710| 0| // detection. If you don't want this behavior, don't use outs(). 711| 0| static raw_fd_ostream S(STDOUT_FILENO, true); 712| 0| return S; 713| 0|} 714| | 715| |/// errs() - This returns a reference to a raw_ostream for standard error. 716| |/// Use it like: errs() << "foo" << "bar"; 717| 0|raw_ostream &llvm::errs() { 718| 0| // Set standard error to be unbuffered by default. 719| 0| static raw_fd_ostream S(STDERR_FILENO, false, true); 720| 0| return S; 721| 0|} 722| | 723| |/// nulls() - This returns a reference to a raw_ostream which discards output. 724| 0|raw_ostream &llvm::nulls() { 725| 0| static raw_null_ostream S; 726| 0| return S; 727| 0|} 728| | 729| | 730| |//===----------------------------------------------------------------------===// 731| |// raw_string_ostream 732| |//===----------------------------------------------------------------------===// 733| | 734| 0|raw_string_ostream::~raw_string_ostream() { 735| 0| flush(); 736| 0|} 737| | 738| 0|void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { 739| 0| OS.append(Ptr, Size); 740| 0|} 741| | 742| |//===----------------------------------------------------------------------===// 743| |// raw_svector_ostream 744| |//===----------------------------------------------------------------------===// 745| | 746| |// The raw_svector_ostream implementation uses the SmallVector itself as the 747| |// buffer for the raw_ostream. We guarantee that the raw_ostream buffer is 748| |// always pointing past the end of the vector, but within the vector 749| |// capacity. This allows raw_ostream to write directly into the correct place, 750| |// and we only need to set the vector size when the data is flushed. 751| | 752| 0|raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O) : OS(O) { 753| 0| // Set up the initial external buffer. We make sure that the buffer has at 754| 0| // least 128 bytes free; raw_ostream itself only requires 64, but we want to 755| 0| // make sure that we don't grow the buffer unnecessarily on destruction (when 756| 0| // the data is flushed). See the FIXME below. 757| 0| OS.reserve(OS.size() + 128); 758| 0| SetBuffer(OS.end(), OS.capacity() - OS.size()); 759| 0|} 760| | 761| 0|raw_svector_ostream::~raw_svector_ostream() { 762| 0| // FIXME: Prevent resizing during this flush(). 763| 0| flush(); 764| 0|} 765| | 766| |/// resync - This is called when the SmallVector we're appending to is changed 767| |/// outside of the raw_svector_ostream's control. It is only safe to do this 768| |/// if the raw_svector_ostream has previously been flushed. 769| 0|void raw_svector_ostream::resync() { 770| 0| assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector"); 771| 0| 772| 0| if (OS.capacity() - OS.size() < 64) 773| 0| OS.reserve(OS.capacity() * 2); 774| 0| SetBuffer(OS.end(), OS.capacity() - OS.size()); 775| 0|} 776| | 777| 0|void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { 778| 0| if (Ptr == OS.end()) { 779| 0| // Grow the buffer to include the scratch area without copying. 780| 0| size_t NewSize = OS.size() + Size; 781| 0| assert(NewSize <= OS.capacity() && "Invalid write_impl() call!"); 782| 0| OS.set_size(NewSize); 783| 0| } else { 784| 0| assert(!GetNumBytesInBuffer()); 785| 0| OS.append(Ptr, Ptr + Size); 786| 0| } 787| 0| 788| 0| OS.reserve(OS.size() + 64); 789| 0| SetBuffer(OS.end(), OS.capacity() - OS.size()); 790| 0|} 791| | 792| 0|uint64_t raw_svector_ostream::current_pos() const { 793| 0| return OS.size(); 794| 0|} 795| | 796| 0|StringRef raw_svector_ostream::str() { 797| 0| flush(); 798| 0| return StringRef(OS.begin(), OS.size()); 799| 0|} 800| | 801| |//===----------------------------------------------------------------------===// 802| |// raw_null_ostream 803| |//===----------------------------------------------------------------------===// 804| | 805| 0|raw_null_ostream::~raw_null_ostream() { 806| 0|#ifndef NDEBUG 807| 0| // ~raw_ostream asserts that the buffer is empty. This isn't necessary 808| 0| // with raw_null_ostream, but it's better to have raw_null_ostream follow 809| 0| // the rules than to change the rules just for raw_null_ostream. 810| 0| flush(); 811| 0|#endif 812| 0|} 813| | 814| 0|void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { 815| 0|} 816| | 817| 0|uint64_t raw_null_ostream::current_pos() const { 818| 0| return 0; 819| 0|} <<<<<< EOF # path=Xcodeproj.framework.coverage.txt /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/PropertyList.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |/// A enum representing data types for legacy PropertyList type. 12| |/// Note that the `identifier` enum is not strictly necessary, 13| |/// but useful to semantically distinguish the strings that 14| |/// represents object identifiers from those that are just data. 15| |/// see: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html 16| |public enum PropertyList { 17| | case identifier(String) 18| | case string(String) 19| | case array([PropertyList]) 20| | case dictionary([String: PropertyList]) 21| | 22| 0| var string: String? { 23| 0| if case .string(let string) = self { 24| 0| return string 25| 0| } 26| 0| return nil 27| 0| } 28| | 29| 0| var array: [PropertyList]? { 30| 0| if case .array(let array) = self { 31| 0| return array 32| 0| } 33| 0| return nil 34| 0| } 35| |} 36| | 37| |extension PropertyList: ExpressibleByStringLiteral { 38| | public typealias UnicodeScalarLiteralType = StringLiteralType 39| | public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType 40| | 41| 0| public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { 42| 0| self = .string(value) 43| 0| } 44| 0| public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { 45| 0| self = .string(value) 46| 0| } 47| 0| public init(stringLiteral value: StringLiteralType) { 48| 0| self = .string(value) 49| 0| } 50| |} 51| | 52| |extension PropertyList: CustomStringConvertible { 53| 0| public var description: String { 54| 0| return serialize() 55| 0| } 56| |} 57| | 58| |extension PropertyList { 59| | /// Serializes the Plist enum to string. 60| 0| func serialize() -> String { 61| 0| return generatePlistRepresentation(plist: self, indentation: Indentation()) 62| 0| } 63| | 64| | /// Escapes the string for plist. 65| | /// Finds the instances of quote (") and backward slash (\) and prepends 66| | /// the escape character backward slash (\). 67| 0| static func escape(string: String) -> String { 68| 0| func needsEscape(_ char: UInt8) -> Bool { 69| 0| return char == UInt8(ascii: "\\") || char == UInt8(ascii: "\"") 70| 0| } 71| 0| 72| 0| guard let pos = string.utf8.index(where: needsEscape) else { 73| 0| return string 74| 0| } 75| 0| var newString = String(string[.. 0, "indentation level overflow") 93| 0| } 94| 0| mutating func decrease() { 95| 0| precondition(level > 0, "indentation level underflow") 96| 0| level -= 1 97| 0| } 98| 0| var description: String { 99| 0| return String(repeating: " ", count: level) 100| 0| } 101| | } 102| | 103| | /// Private function to generate OPENSTEP-style plist representation. 104| 0| fileprivate func generatePlistRepresentation(plist: PropertyList, indentation: Indentation) -> String { 105| 0| // Do the appropriate thing for each type of plist node. 106| 0| switch plist { 107| 0| 108| 0| case .identifier(let ident): 109| 0| // FIXME: we should assert that the identifier doesn't need quoting 110| 0| return ident 111| 0| 112| 0| case .string(let string): 113| 0| return "\"" + PropertyList.escape(string: string) + "\"" 114| 0| 115| 0| case .array(let array): 116| 0| var indent = indentation 117| 0| var str = "(\n" 118| 0| indent.increase() 119| 0| for (i, item) in array.enumerated() { 120| 0| str += "\(indent)\(generatePlistRepresentation(plist: item, indentation: indent))" 121| 0| str += (i != array.count - 1) ? ",\n" : "\n" 122| 0| } 123| 0| indent.decrease() 124| 0| str += "\(indent))" 125| 0| return str 126| 0| 127| 0| case .dictionary(let dict): 128| 0| var indent = indentation 129| 0| let dict = dict.sorted(by: { 130| 0| // Make `isa` sort first (just for readability purposes). 131| 0| switch ($0.key, $1.key) { 132| 0| case ("isa", "isa"): return false 133| 0| case ("isa", _): return true 134| 0| case (_, "isa"): return false 135| 0| default: return $0.key < $1.key 136| 0| } 137| 0| }) 138| 0| var str = "{\n" 139| 0| indent.increase() 140| 0| for item in dict { 141| 0| str += "\(indent)\(item.key) = \(generatePlistRepresentation(plist: item.value, indentation: indent));\n" 142| 0| } 143| 0| indent.decrease() 144| 0| str += "\(indent)}" 145| 0| return str 146| 0| } 147| 0| } 148| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/SchemesGenerator.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2018 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import PackageGraph 13| |import PackageModel 14| | 15| |/// Represents a scheme in Xcode for the project generation support. 16| |struct Scheme { 17| | 18| | /// The name of the scheme. 19| | var name: String 20| | 21| | /// The scheme filename. 22| 0| var filename: String { 23| 0| return name + ".xcscheme" 24| 0| } 25| | 26| | /// The list of regular targets contained in this scheme. 27| | var regularTargets: Set 28| | 29| | /// The list of test targets contained in this scheme. 30| | var testTargets: Set 31| | 32| 0| init(name: String, regularTargets: [ResolvedTarget], testTargets: [ResolvedTarget]) { 33| 0| self.name = name 34| 0| self.regularTargets = Set(regularTargets) 35| 0| self.testTargets = Set(testTargets) 36| 0| } 37| |} 38| | 39| |final class SchemesGenerator { 40| | 41| | private let graph: PackageGraph 42| | private let container: String 43| | private let schemesDir: AbsolutePath 44| | private let isCodeCoverageEnabled: Bool 45| | private let fs: FileSystem 46| | 47| | init( 48| | graph: PackageGraph, 49| | container: String, 50| | schemesDir: AbsolutePath, 51| | isCodeCoverageEnabled: Bool, 52| | fs: FileSystem 53| 0| ) { 54| 0| self.graph = graph 55| 0| self.container = container 56| 0| self.schemesDir = schemesDir 57| 0| self.isCodeCoverageEnabled = isCodeCoverageEnabled 58| 0| self.fs = fs 59| 0| } 60| | 61| 0| func buildSchemes() -> [Scheme] { 62| 0| let rootPackage = graph.rootPackages[0] 63| 0| 64| 0| var schemes: [Scheme] = [] 65| 0| 66| 0| // Create map of test target to set of its direct dependencies. 67| 0| let testTargetDepMap: [ResolvedTarget: Set] = { 68| 0| let testTargetDeps = rootPackage.targets.filter({ $0.type == .test }).map({ 69| 0| ($0, Set($0.dependencies.compactMap({ $0.target }))) 70| 0| }) 71| 0| return Dictionary(uniqueKeysWithValues: testTargetDeps) 72| 0| }() 73| 0| 74| 0| // Create one scheme per executable target. 75| 0| for target in rootPackage.targets where target.type == .executable { 76| 0| // Find all dependencies of this target within its package. 77| 0| let dependencies = try! topologicalSort(target.dependencies, successors: { 78| 0| $0.dependencies.compactMap({ $0.target }).map(ResolvedTarget.Dependency.target) 79| 0| }).compactMap({ $0.target }) 80| 0| 81| 0| // Include the test targets whose dependencies intersect with the 82| 0| // current target's (recursive) dependencies. 83| 0| let testTargets = testTargetDepMap.filter({ (testTarget, deps) in 84| 0| !deps.intersection(dependencies + [target]).isEmpty 85| 0| }).map({ $0.key }) 86| 0| 87| 0| schemes.append(Scheme( 88| 0| name: target.name, 89| 0| regularTargets: [target], 90| 0| testTargets: testTargets 91| 0| )) 92| 0| } 93| 0| 94| 0| // Finally, create one master scheme for the entire package. 95| 0| let regularTargets = rootPackage.targets.filter({ 96| 0| switch $0.type { 97| 0| case .test, .systemModule: 98| 0| return false 99| 0| case .executable, .library: 100| 0| return true 101| 0| } 102| 0| }) 103| 0| schemes.append(Scheme( 104| 0| name: rootPackage.name + "-Package", 105| 0| regularTargets: regularTargets, 106| 0| testTargets: rootPackage.targets.filter({ $0.type == .test }) 107| 0| )) 108| 0| 109| 0| return schemes 110| 0| } 111| | 112| 0| func generate() throws { 113| 0| let schemes = buildSchemes() 114| 0| for scheme in schemes { 115| 0| try create(scheme) 116| 0| } 117| 0| 118| 0| try disableSchemeAutoCreation() 119| 0| } 120| | 121| 0| private func create(_ scheme: Scheme) throws { 122| 0| assert(!scheme.regularTargets.isEmpty, "Scheme \(scheme.name) contains no target") 123| 0| 124| 0| let stream = BufferedOutputByteStream() 125| 0| stream <<< """ 126| 0| 127| 0| 128| 0| 129| 0| 130| 0| 131| 0| """ 132| 0| 133| 0| // Create buildable references for non-test targets. 134| 0| for target in scheme.regularTargets { 135| 0| stream <<< """ 136| 0| 137| 0| 142| 0| 143| 0| 144| 0| 145| 0| """ 146| 0| } 147| 0| 148| 0| stream <<< """ 149| 0| 150| 0| 151| 0| 152| 0| """ 153| 0| 154| 0| stream <<< """ 155| 0| 161| 0| 162| 0| 163| 0| """ 164| 0| 165| 0| // Create testable references. 166| 0| for target in scheme.testTargets { 167| 0| stream <<< """ 168| 0| 170| 0| 175| 0| 176| 0| 177| 0| 178| 0| """ 179| 0| } 180| 0| 181| 0| stream <<< """ 182| 0| 183| 0| 184| 0| 185| 0| """ 186| 0| 187| 0| if let target = scheme.regularTargets.first { 188| 0| if scheme.regularTargets.count == 1 && target.type == .executable { 189| 0| stream <<< """ 190| 0| 200| 0| 202| 0| 207| 0| 208| 0| 209| 0| 210| 0| 211| 0| 212| 0| 213| 0| """ 214| 0| } 215| 0| } 216| 0| 217| 0| stream <<< """ 218| 0| 219| 0| 220| 0| """ 221| 0| 222| 0| let file = schemesDir.appending(RelativePath(scheme.filename)) 223| 0| try fs.writeFileContents(file, bytes: stream.bytes) 224| 0| } 225| | 226| 0| private func disableSchemeAutoCreation() throws { 227| 0| let workspacePath = schemesDir.appending(RelativePath("../../project.xcworkspace")) 228| 0| 229| 0| // Write the settings file to disable automatic scheme creation. 230| 0| var stream = BufferedOutputByteStream() 231| 0| stream <<< """ 232| 0| 233| 0| 234| 0| 235| 0| 236| 0| IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 237| 0| 238| 0| 239| 0| 240| 0| """ 241| 0| let settingsPlist = workspacePath.appending(RelativePath("xcshareddata/WorkspaceSettings.xcsettings")) 242| 0| try fs.createDirectory(settingsPlist.parentDirectory, recursive: true) 243| 0| try fs.writeFileContents(settingsPlist, bytes: stream.bytes) 244| 0| 245| 0| // Write workspace contents file. 246| 0| let contentsFile = workspacePath.appending(RelativePath("contents.xcworkspacedata")) 247| 0| stream = BufferedOutputByteStream() 248| 0| stream <<< """ 249| 0| 250| 0| 252| 0| 254| 0| 255| 0| 256| 0| """ 257| 0| try fs.createDirectory(contentsFile.parentDirectory, recursive: true) 258| 0| try fs.writeFileContents(contentsFile, bytes: stream.bytes) 259| 0| } 260| |} 261| | 262| 0|func legacySchemeGenerator(container: String, graph: PackageGraph, codeCoverageEnabled: Bool, printer print: (String) -> Void) { 263| 0| print(""" 264| 0| 265| 0| 266| 0| 267| 0| 268| 0| """) 269| 0| 270| 0| // Create buildable references for non-test targets. 271| 0| for target in graph.reachableTargets where target.type != .test { 272| 0| // Ignore system targets. 273| 0| // 274| 0| // FIXME: We shouldn't need to manually do this here, instead this 275| 0| // should be phrased in terms of the set of targets we computed. 276| 0| if target.type == .systemModule { 277| 0| continue 278| 0| } 279| 0| 280| 0| print(""" 281| 0| 282| 0| 287| 0| 288| 0| 289| 0| """) 290| 0| } 291| 0| 292| 0| print(""" 293| 0| 294| 0| 295| 0| 301| 0| 302| 0| """) 303| 0| 304| 0| // Create testable references. 305| 0| for target in graph.reachableTargets where target.type == .test { 306| 0| print(""" 307| 0| 309| 0| 314| 0| 315| 0| 316| 0| """) 317| 0| } 318| 0| 319| 0| print(""" 320| 0| 321| 0| 322| 0| 323| 0| """) 324| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/Target+PBXProj.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | 10| | ----------------------------------------------------------------- 11| | 12| | In an effort to provide: 13| | 14| | 1. Unique reference identifiers 15| | 2. Human readable reference identifiers 16| | 3. Stable reference identifiers 17| | 18| | (as opposed to the generated UUIDs Xcode typically generates) 19| | 20| | We create identifiers with a constant-length unique prefix and 21| | a unique suffix where the suffix is the filename or target name 22| | and since we guarantee uniqueness at the PackageDescription 23| | layer for these properties we satisfy the above constraints. 24| |*/ 25| | 26| |import Foundation 27| | 28| |import Basic 29| |import PackageModel 30| |import PackageLoading 31| | 32| |extension ResolvedTarget { 33| | 34| 0| var infoPlistFileName: String { 35| 0| return "\(c99name)_Info.plist" 36| 0| } 37| | 38| 0| var productType: String { 39| 0| switch type { 40| 0| case .test: 41| 0| return "com.apple.product-type.bundle.unit-test" 42| 0| case .library: 43| 0| return "com.apple.product-type.framework" 44| 0| case .executable: 45| 0| return "com.apple.product-type.tool" 46| 0| case .systemModule: 47| 0| fatalError() 48| 0| } 49| 0| } 50| | 51| 0| var explicitFileType: String { 52| 0| switch type { 53| 0| case .test: 54| 0| return "compiled.mach-o.wrapper.cfbundle" 55| 0| case .library: 56| 0| return "wrapper.framework" 57| 0| case .executable: 58| 0| return "compiled.mach-o.executable" 59| 0| case .systemModule: 60| 0| fatalError() 61| 0| } 62| 0| } 63| | 64| 0| var productPath: RelativePath { 65| 0| switch type { 66| 0| case .test: 67| 0| return RelativePath("\(c99name).xctest") 68| 0| case .library: 69| 0| return RelativePath("\(c99name).framework") 70| 0| case .executable: 71| 0| return RelativePath(name) 72| 0| case .systemModule: 73| 0| fatalError() 74| 0| } 75| 0| } 76| | 77| 0| var productName: String { 78| 0| switch type { 79| 0| case .library: 80| 0| // you can go without a lib prefix, but something unexpected will break 81| 0| return "'lib$(TARGET_NAME)'" 82| 0| case .test, .executable: 83| 0| return "'$(TARGET_NAME)'" 84| 0| case .systemModule: 85| 0| fatalError() 86| 0| } 87| 0| } 88| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/XcodeProjectModel.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | 10| | ----------------------------------------------------------------------------- 11| | 12| | A very simple rendition of the Xcode project model. There is only sufficient 13| | functionality to allow creation of Xcode projects in a somewhat readable way, 14| | and serialization to .xcodeproj plists. There is no consistency checking to 15| | ensure, for example, that build settings have valid values, dependency cycles 16| | are not created, etc. 17| | 18| | Everything here is geared toward supporting project generation. The intended 19| | usage model is for custom logic to build up a project using Xcode terminology 20| | (e.g. "group", "reference", "target", "build phase"), but there is almost no 21| | provision for modifying the model after it has been built up. The intent is 22| | to create it as desired from the start. 23| | 24| | Rather than try to represent everything that Xcode's project model supports, 25| | the approach is to start small and to add functionality as needed. 26| | 27| | Note that this API represents only the project model — there is no notion of 28| | workspaces, schemes, etc (although schemes are represented individually in a 29| | separate API). The notion of build settings is also somewhat different from 30| | what it is in Xcode: instead of an open-ended mapping of build configuration 31| | names to dictionaries of build settings, here there is a single set of common 32| | build settings plus two overlay sets for debug and release. The generated 33| | project has just the two Debug and Release configurations, created by merging 34| | the common set into the release and debug sets. This allows a more natural 35| | configuration of the settings, since most values are the same between Debug 36| | and Release. Also, the build settings themselves are represented as structs 37| | of named fields, instead of dictionaries with arbitrary name strings as keys. 38| | 39| | It is expected that some of these simplifications will need to be lifted over 40| | time, based on need. That should be done carefully, however, to avoid ending 41| | up with an overly complicated model. 42| | 43| | Some things that are incomplete in even this first model: 44| | - copy files build phases are incomplete 45| | - shell script build phases are incomplete 46| | - file types in file references are specified using strings; should be enums 47| | so that the client doesn't have to hardcode the mapping to Xcode file type 48| | identifiers 49| | - debug and release settings override common settings; they should be merged 50| | in a way that respects `$(inhertied)` when the same setting is defined in 51| | common and in debug or release 52| | - there is no good way to control the ordering of the `Products` group in the 53| | main group; it needs to be added last in order to appear after the other 54| | references 55| |*/ 56| | 57| |public struct Xcode { 58| | 59| | /// An Xcode project, consisting of a tree of groups and file references, 60| | /// a list of targets, and some additional information. Note that schemes 61| | /// are outside of the project data model. 62| | public class Project { 63| | let mainGroup: Group 64| | var buildSettings: BuildSettingsTable 65| | var productGroup: Group? 66| | var projectDir: String 67| | var targets: [Target] 68| 0| init() { 69| 0| self.mainGroup = Group(path: "") 70| 0| self.buildSettings = BuildSettingsTable() 71| 0| self.productGroup = nil 72| 0| self.projectDir = "" 73| 0| self.targets = [] 74| 0| } 75| | 76| | /// Creates and adds a new target (which does not initially have any 77| | /// build phases). 78| 0| public func addTarget(objectID: String? = nil, productType: Target.ProductType?, name: String) -> Target { 79| 0| let target = Target(objectID: objectID, productType: productType, name: name) 80| 0| targets.append(target) 81| 0| return target 82| 0| } 83| | } 84| | 85| | /// Abstract base class for all items in the group hierarhcy. 86| | public class Reference { 87| | /// Relative path of the reference. It is usually a literal, but may 88| | /// in fact contain build settings. 89| | var path: String 90| | /// Determines the base path for the reference's relative path. 91| | var pathBase: RefPathBase 92| | /// Name of the reference, if different from the last path component 93| | /// (if not set, Xcode will use the last path component as the name). 94| | var name: String? 95| | 96| | /// Determines the base path for a reference's relative path (this is 97| | /// what for some reason is called a "source tree" in Xcode). 98| | public enum RefPathBase: String { 99| | /// Indicates that the path is relative to the source root (i.e. 100| | /// the "project directory"). 101| | case projectDir = "SOURCE_ROOT" 102| | /// Indicates that the path is relative to the path of the parent 103| | /// group. 104| | case groupDir = "" 105| | /// Indicates that the path is relative to the effective build 106| | /// directory (which varies depending on active scheme, active run 107| | /// destination, or even an overridden build setting. 108| | case buildDir = "BUILT_PRODUCTS_DIR" 109| | } 110| | 111| 0| init(path: String, pathBase: RefPathBase = .groupDir, name: String? = nil) { 112| 0| self.path = path 113| 0| self.pathBase = pathBase 114| 0| self.name = name 115| 0| } 116| | } 117| | 118| | /// A reference to a file system entity (a file, folder, etc). 119| | public class FileReference: Reference { 120| | var objectID: String? 121| | var fileType: String? 122| | 123| 0| init(path: String, pathBase: RefPathBase = .groupDir, name: String? = nil, fileType: String? = nil, objectID: String? = nil) { 124| 0| super.init(path: path, pathBase: pathBase, name: name) 125| 0| self.objectID = objectID 126| 0| self.fileType = fileType 127| 0| } 128| | } 129| | 130| | /// A group that can contain References (FileReferences and other Groups). 131| | /// The resolved path of a group is used as the base path for any child 132| | /// references whose source tree type is GroupRelative. 133| | public class Group: Reference { 134| | var subitems = [Reference]() 135| | 136| | /// Creates and appends a new Group to the list of subitems. 137| | /// The new group is returned so that it can be configured. 138| | @discardableResult public func addGroup( 139| | path: String, 140| | pathBase: RefPathBase = .groupDir, 141| | name: String? = nil 142| 0| ) -> Group { 143| 0| let group = Group(path: path, pathBase: pathBase, name: name) 144| 0| subitems.append(group) 145| 0| return group 146| 0| } 147| | 148| | /// Creates and appends a new FileReference to the list of subitems. 149| | @discardableResult public func addFileReference( 150| | path: String, 151| | pathBase: RefPathBase = .groupDir, 152| | name: String? = nil, 153| | fileType: String? = nil, 154| | objectID: String? = nil 155| 0| ) -> FileReference { 156| 0| let fref = FileReference(path: path, pathBase: pathBase, name: name, fileType: fileType, objectID: objectID) 157| 0| subitems.append(fref) 158| 0| return fref 159| 0| } 160| | } 161| | 162| | /// An Xcode target, representing a single entity to build. 163| | public class Target { 164| | var objectID: String? 165| | var name: String 166| | var productName: String 167| | var productType: ProductType? 168| | var buildSettings: BuildSettingsTable 169| | var buildPhases: [BuildPhase] 170| | var productReference: FileReference? 171| | var dependencies: [TargetDependency] 172| | public enum ProductType: String { 173| | case application = "com.apple.product-type.application" 174| | case staticArchive = "com.apple.product-type.library.static" 175| | case dynamicLibrary = "com.apple.product-type.library.dynamic" 176| | case framework = "com.apple.product-type.framework" 177| | case executable = "com.apple.product-type.tool" 178| | case unitTest = "com.apple.product-type.bundle.unit-test" 179| | } 180| 0| init(objectID: String?, productType: ProductType?, name: String) { 181| 0| self.objectID = objectID 182| 0| self.name = name 183| 0| self.productType = productType 184| 0| self.productName = name 185| 0| self.buildSettings = BuildSettingsTable() 186| 0| self.buildPhases = [] 187| 0| self.dependencies = [] 188| 0| } 189| | 190| | // FIXME: There's a lot repetition in these methods; using generics to 191| | // try to avoid that raised other issues in terms of requirements on 192| | // the Reference class, though. 193| | 194| | /// Adds a "headers" build phase, i.e. one that copies headers into a 195| | /// directory of the product, after suitable processing. 196| 0| @discardableResult public func addHeadersBuildPhase() -> HeadersBuildPhase { 197| 0| let phase = HeadersBuildPhase() 198| 0| buildPhases.append(phase) 199| 0| return phase 200| 0| } 201| | 202| | /// Adds a "sources" build phase, i.e. one that compiles sources and 203| | /// provides them to be linked into the executable code of the product. 204| 0| @discardableResult public func addSourcesBuildPhase() -> SourcesBuildPhase { 205| 0| let phase = SourcesBuildPhase() 206| 0| buildPhases.append(phase) 207| 0| return phase 208| 0| } 209| | 210| | /// Adds a "frameworks" build phase, i.e. one that links compiled code 211| | /// and libraries into the executable of the product. 212| 0| @discardableResult public func addFrameworksBuildPhase() -> FrameworksBuildPhase { 213| 0| let phase = FrameworksBuildPhase() 214| 0| buildPhases.append(phase) 215| 0| return phase 216| 0| } 217| | 218| | /// Adds a "copy files" build phase, i.e. one that copies files to an 219| | /// arbitrary location relative to the product. 220| 0| @discardableResult public func addCopyFilesBuildPhase(dstDir: String) -> CopyFilesBuildPhase { 221| 0| let phase = CopyFilesBuildPhase(dstDir: dstDir) 222| 0| buildPhases.append(phase) 223| 0| return phase 224| 0| } 225| | 226| | /// Adds a "shell script" build phase, i.e. one that runs a custom 227| | /// shell script as part of the build. 228| 0| @discardableResult public func addShellScriptBuildPhase(script: String) -> ShellScriptBuildPhase { 229| 0| let phase = ShellScriptBuildPhase(script: script) 230| 0| buildPhases.append(phase) 231| 0| return phase 232| 0| } 233| | 234| | /// Adds a dependency on another target. 235| | /// FIXME: We do not check for cycles. Should we? This is an extremely 236| | /// minimal API so it's not clear that we should. 237| 0| public func addDependency(on target: Target) { 238| 0| dependencies.append(TargetDependency(target: target)) 239| 0| } 240| | 241| | /// A simple wrapper to prevent ownership cycles in the `dependencies` 242| | /// property. 243| | struct TargetDependency { 244| | unowned var target: Target 245| | } 246| | } 247| | 248| | /// Abstract base class for all build phases in a target. 249| | public class BuildPhase { 250| | var files: [BuildFile] = [] 251| | 252| | /// Adds a new build file that refers to `fileRef`. 253| 0| @discardableResult public func addBuildFile(fileRef: FileReference) -> BuildFile { 254| 0| let buildFile = BuildFile(fileRef: fileRef) 255| 0| files.append(buildFile) 256| 0| return buildFile 257| 0| } 258| | } 259| | 260| | /// A "headers" build phase, i.e. one that copies headers into a directory 261| | /// of the product, after suitable processing. 262| | public class HeadersBuildPhase: BuildPhase { 263| | // Nothing extra yet. 264| | } 265| | 266| | /// A "sources" build phase, i.e. one that compiles sources and provides 267| | /// them to be linked into the executable code of the product. 268| | public class SourcesBuildPhase: BuildPhase { 269| | // Nothing extra yet. 270| | } 271| | 272| | /// A "frameworks" build phase, i.e. one that links compiled code and 273| | /// libraries into the executable of the product. 274| | public class FrameworksBuildPhase: BuildPhase { 275| | // Nothing extra yet. 276| | } 277| | 278| | /// A "copy files" build phase, i.e. one that copies files to an arbitrary 279| | /// location relative to the product. 280| | public class CopyFilesBuildPhase: BuildPhase { 281| | var dstDir: String 282| 0| init(dstDir: String) { 283| 0| self.dstDir = dstDir 284| 0| } 285| | } 286| | 287| | /// A "shell script" build phase, i.e. one that runs a custom shell script. 288| | public class ShellScriptBuildPhase: BuildPhase { 289| | var script: String 290| 0| init(script: String) { 291| 0| self.script = script 292| 0| } 293| | } 294| | 295| | /// A build file, representing the membership of a file reference in a 296| | /// build phase of a target. 297| | public class BuildFile { 298| | weak var fileRef: FileReference? 299| 0| init(fileRef: FileReference) { 300| 0| self.fileRef = fileRef 301| 0| } 302| | 303| | var settings = Settings() 304| | 305| | /// A set of file settings. 306| | public struct Settings { 307| | var ATTRIBUTES: [String]? 308| | } 309| | } 310| | 311| | /// A table of build settings, which for the sake of simplicity consists 312| | /// (in this simplified model) of a set of common settings, and a set of 313| | /// overlay settings for Debug and Release builds. There can also be a 314| | /// file reference to an .xcconfig file on which to base the settings. 315| | public class BuildSettingsTable { 316| | /// Common build settings are in both generated configurations (Debug 317| | /// and Release). 318| | var common = BuildSettings() 319| | 320| | /// Debug build settings are overlaid over the common settings in the 321| | /// generated Debug configuration. 322| | var debug = BuildSettings() 323| | 324| | /// Release build settings are overlaid over the common settings in the 325| | /// generated Release configuration. 326| | var release = BuildSettings() 327| | 328| | /// An optional file reference to an .xcconfig file. 329| | var xcconfigFileRef: FileReference? 330| | 331| | /// A set of build settings, which is represented as a struct of optional 332| | /// build settings. This is not optimally efficient, but it is great for 333| | /// code completion and type-checking. 334| | public struct BuildSettings { 335| | // Note: although some of these build settings sound like booleans, 336| | // they are all either strings or arrays of strings, because even 337| | // a boolean may be a macro reference expression. 338| | var CLANG_CXX_LANGUAGE_STANDARD: String? 339| | var CLANG_ENABLE_MODULES: String? 340| | var CLANG_ENABLE_OBJC_ARC: String? 341| | var COMBINE_HIDPI_IMAGES: String? 342| | var COPY_PHASE_STRIP: String? 343| | var DEBUG_INFORMATION_FORMAT: String? 344| | var DEFINES_MODULE: String? 345| | var DYLIB_INSTALL_NAME_BASE: String? 346| | var EMBEDDED_CONTENT_CONTAINS_SWIFT: String? 347| | var ENABLE_NS_ASSERTIONS: String? 348| | var ENABLE_TESTABILITY: String? 349| | var FRAMEWORK_SEARCH_PATHS: [String]? 350| | var GCC_C_LANGUAGE_STANDARD: String? 351| | var GCC_OPTIMIZATION_LEVEL: String? 352| | var GCC_PREPROCESSOR_DEFINITIONS: [String]? 353| | var HEADER_SEARCH_PATHS: [String]? 354| | var INFOPLIST_FILE: String? 355| | var LD_RUNPATH_SEARCH_PATHS: [String]? 356| | var LIBRARY_SEARCH_PATHS: [String]? 357| | var MACOSX_DEPLOYMENT_TARGET: String? 358| | var IPHONEOS_DEPLOYMENT_TARGET: String? 359| | var TVOS_DEPLOYMENT_TARGET: String? 360| | var WATCHOS_DEPLOYMENT_TARGET: String? 361| | var MODULEMAP_FILE: String? 362| | var ONLY_ACTIVE_ARCH: String? 363| | var OTHER_CFLAGS: [String]? 364| | var OTHER_LDFLAGS: [String]? 365| | var OTHER_SWIFT_FLAGS: [String]? 366| | var PRODUCT_BUNDLE_IDENTIFIER: String? 367| | var PRODUCT_MODULE_NAME: String? 368| | var PRODUCT_NAME: String? 369| | var PROJECT_NAME: String? 370| | var SDKROOT: String? 371| | var SKIP_INSTALL: String? 372| | var SUPPORTED_PLATFORMS: [String]? 373| | var SWIFT_ACTIVE_COMPILATION_CONDITIONS: [String]? 374| | var SWIFT_FORCE_STATIC_LINK_STDLIB: String? 375| | var SWIFT_FORCE_DYNAMIC_LINK_STDLIB: String? 376| | var SWIFT_OPTIMIZATION_LEVEL: String? 377| | var SWIFT_VERSION: String? 378| | var TARGET_NAME: String? 379| | var USE_HEADERMAP: String? 380| | var LD: String? 381| | 382| | init( 383| | CLANG_CXX_LANGUAGE_STANDARD: String? = nil, 384| | CLANG_ENABLE_MODULES: String? = nil, 385| | CLANG_ENABLE_OBJC_ARC: String? = nil, 386| | COMBINE_HIDPI_IMAGES: String? = nil, 387| | COPY_PHASE_STRIP: String? = nil, 388| | DEBUG_INFORMATION_FORMAT: String? = nil, 389| | DEFINES_MODULE: String? = nil, 390| | DYLIB_INSTALL_NAME_BASE: String? = nil, 391| | EMBEDDED_CONTENT_CONTAINS_SWIFT: String? = nil, 392| | ENABLE_NS_ASSERTIONS: String? = nil, 393| | ENABLE_TESTABILITY: String? = nil, 394| | FRAMEWORK_SEARCH_PATHS: [String]? = nil, 395| | GCC_C_LANGUAGE_STANDARD: String? = nil, 396| | GCC_OPTIMIZATION_LEVEL: String? = nil, 397| | GCC_PREPROCESSOR_DEFINITIONS: [String]? = nil, 398| | HEADER_SEARCH_PATHS: [String]? = nil, 399| | INFOPLIST_FILE: String? = nil, 400| | LD_RUNPATH_SEARCH_PATHS: [String]? = nil, 401| | LIBRARY_SEARCH_PATHS: [String]? = nil, 402| | MACOSX_DEPLOYMENT_TARGET: String? = nil, 403| | IPHONEOS_DEPLOYMENT_TARGET: String? = nil, 404| | TVOS_DEPLOYMENT_TARGET: String? = nil, 405| | WATCHOS_DEPLOYMENT_TARGET: String? = nil, 406| | MODULEMAP_FILE: String? = nil, 407| | ONLY_ACTIVE_ARCH: String? = nil, 408| | OTHER_CFLAGS: [String]? = nil, 409| | OTHER_LDFLAGS: [String]? = nil, 410| | OTHER_SWIFT_FLAGS: [String]? = nil, 411| | PRODUCT_BUNDLE_IDENTIFIER: String? = nil, 412| | PRODUCT_MODULE_NAME: String? = nil, 413| | PRODUCT_NAME: String? = nil, 414| | PROJECT_NAME: String? = nil, 415| | SDKROOT: String? = nil, 416| | SKIP_INSTALL: String? = nil, 417| | SUPPORTED_PLATFORMS: [String]? = nil, 418| | SWIFT_ACTIVE_COMPILATION_CONDITIONS: [String]? = nil, 419| | SWIFT_FORCE_STATIC_LINK_STDLIB: String? = nil, 420| | SWIFT_FORCE_DYNAMIC_LINK_STDLIB: String? = nil, 421| | SWIFT_OPTIMIZATION_LEVEL: String? = nil, 422| | SWIFT_VERSION: String? = nil, 423| | TARGET_NAME: String? = nil, 424| | USE_HEADERMAP: String? = nil, 425| | LD: String? = nil 426| 0| ) { 427| 0| self.CLANG_CXX_LANGUAGE_STANDARD = CLANG_CXX_LANGUAGE_STANDARD 428| 0| self.CLANG_ENABLE_MODULES = CLANG_ENABLE_MODULES 429| 0| self.CLANG_ENABLE_OBJC_ARC = CLANG_CXX_LANGUAGE_STANDARD 430| 0| self.COMBINE_HIDPI_IMAGES = COMBINE_HIDPI_IMAGES 431| 0| self.COPY_PHASE_STRIP = COPY_PHASE_STRIP 432| 0| self.DEBUG_INFORMATION_FORMAT = DEBUG_INFORMATION_FORMAT 433| 0| self.DEFINES_MODULE = DEFINES_MODULE 434| 0| self.DYLIB_INSTALL_NAME_BASE = DYLIB_INSTALL_NAME_BASE 435| 0| self.EMBEDDED_CONTENT_CONTAINS_SWIFT = EMBEDDED_CONTENT_CONTAINS_SWIFT 436| 0| self.ENABLE_NS_ASSERTIONS = ENABLE_NS_ASSERTIONS 437| 0| self.ENABLE_TESTABILITY = ENABLE_TESTABILITY 438| 0| self.FRAMEWORK_SEARCH_PATHS = FRAMEWORK_SEARCH_PATHS 439| 0| self.GCC_C_LANGUAGE_STANDARD = GCC_C_LANGUAGE_STANDARD 440| 0| self.GCC_OPTIMIZATION_LEVEL = GCC_OPTIMIZATION_LEVEL 441| 0| self.GCC_PREPROCESSOR_DEFINITIONS = GCC_PREPROCESSOR_DEFINITIONS 442| 0| self.HEADER_SEARCH_PATHS = HEADER_SEARCH_PATHS 443| 0| self.INFOPLIST_FILE = INFOPLIST_FILE 444| 0| self.LD_RUNPATH_SEARCH_PATHS = LD_RUNPATH_SEARCH_PATHS 445| 0| self.LIBRARY_SEARCH_PATHS = LIBRARY_SEARCH_PATHS 446| 0| self.MACOSX_DEPLOYMENT_TARGET = MACOSX_DEPLOYMENT_TARGET 447| 0| self.IPHONEOS_DEPLOYMENT_TARGET = IPHONEOS_DEPLOYMENT_TARGET 448| 0| self.TVOS_DEPLOYMENT_TARGET = TVOS_DEPLOYMENT_TARGET 449| 0| self.WATCHOS_DEPLOYMENT_TARGET = WATCHOS_DEPLOYMENT_TARGET 450| 0| self.MODULEMAP_FILE = MODULEMAP_FILE 451| 0| self.ONLY_ACTIVE_ARCH = ONLY_ACTIVE_ARCH 452| 0| self.OTHER_CFLAGS = OTHER_CFLAGS 453| 0| self.OTHER_LDFLAGS = OTHER_LDFLAGS 454| 0| self.OTHER_SWIFT_FLAGS = OTHER_SWIFT_FLAGS 455| 0| self.PRODUCT_BUNDLE_IDENTIFIER = PRODUCT_BUNDLE_IDENTIFIER 456| 0| self.PRODUCT_MODULE_NAME = PRODUCT_MODULE_NAME 457| 0| self.PRODUCT_NAME = PRODUCT_NAME 458| 0| self.PROJECT_NAME = PROJECT_NAME 459| 0| self.SDKROOT = SDKROOT 460| 0| self.SKIP_INSTALL = SKIP_INSTALL 461| 0| self.SUPPORTED_PLATFORMS = SUPPORTED_PLATFORMS 462| 0| self.SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_ACTIVE_COMPILATION_CONDITIONS 463| 0| self.SWIFT_FORCE_STATIC_LINK_STDLIB = SWIFT_FORCE_STATIC_LINK_STDLIB 464| 0| self.SWIFT_FORCE_DYNAMIC_LINK_STDLIB = SWIFT_FORCE_DYNAMIC_LINK_STDLIB 465| 0| self.SWIFT_OPTIMIZATION_LEVEL = SWIFT_OPTIMIZATION_LEVEL 466| 0| self.SWIFT_VERSION = SWIFT_VERSION 467| 0| self.TARGET_NAME = TARGET_NAME 468| 0| self.USE_HEADERMAP = USE_HEADERMAP 469| 0| self.LD = LD 470| 0| } 471| | } 472| | } 473| |} 474| | 475| |/// Adds the abililty to append to an option array of strings that hasn't yet 476| |/// been created. 477| |/// FIXME: While we want the end result of being able to say `FLAGS += ["-O"]` 478| |/// it is probably not how we want to implement it, since it changes behavior 479| |/// for all arrays of string. Instead, we should probably have a build setting 480| |/// struct that wraps a string, and then we can write this in terms of just 481| |/// build settings. 482| 0|public func += (lhs: inout [String]?, rhs: [String]) { 483| 0| if lhs == nil { 484| 0| lhs = rhs 485| 0| } else { 486| 0| lhs = lhs! + rhs 487| 0| } 488| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/XcodeProjectModelSerialization.swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| | 10| | ----------------------------------------------------------------- 11| | 12| | An extemely simple rendition of the Xcode project model into a plist. There 13| | is only enough functionality to allow serialization of Xcode projects. 14| |*/ 15| | 16| |extension Xcode.Project: PropertyListSerializable { 17| | 18| | /// Generates and returns the contents of a `project.pbxproj` plist. Does 19| | /// not generate any ancillary files, such as a set of schemes. 20| | /// 21| | /// Many complexities of the Xcode project model are not represented; we 22| | /// should not add functionality to this model unless it's needed, since 23| | /// implementation of the full Xcode project model would be unnecessarily 24| | /// complex. 25| 0| public func generatePlist() -> PropertyList { 26| 0| // The project plist is a bit special in that it's the archive for the 27| 0| // whole file. We create a plist serializer and serialize the entire 28| 0| // object graph to it, and then return an archive dictionary containing 29| 0| // the serialized object dictionaries. 30| 0| let serializer = PropertyListSerializer() 31| 0| serializer.serialize(object: self) 32| 0| return .dictionary([ 33| 0| "archiveVersion": .string("1"), 34| 0| "objectVersion": .string("46"), // Xcode 8.0 35| 0| "rootObject": .identifier(serializer.id(of: self)), 36| 0| "objects": .dictionary(serializer.idsToDicts), 37| 0| ]) 38| 0| } 39| | 40| | /// Called by the Serializer to serialize the Project. 41| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 42| 0| // Create a `PBXProject` plist dictionary. 43| 0| // Note: we skip things like the `Products` group; they get autocreated 44| 0| // by Xcode when it opens the project and notices that they are missing. 45| 0| // Note: we also skip schemes, since they are not in the project plist. 46| 0| var dict = [String: PropertyList]() 47| 0| dict["isa"] = .string("PBXProject") 48| 0| // Since the project file is generated, we opt out of upgrade-checking. 49| 0| // FIXME: Shoule we really? Why would we not want to get upgraded? 50| 0| dict["attributes"] = .dictionary(["LastUpgradeCheck": .string("9999"), 51| 0| "LastSwiftMigration": .string("9999")]) 52| 0| dict["compatibilityVersion"] = .string("Xcode 3.2") 53| 0| dict["developmentRegion"] = .string("English") 54| 0| // Build settings are a bit tricky; in Xcode, each is stored in a named 55| 0| // XCBuildConfiguration object, and the list of build configurations is 56| 0| // in turn stored in an XCConfigurationList. In our simplified model, 57| 0| // we have a BuildSettingsTable, with three sets of settings: one for 58| 0| // the common settings, and one each for the Debug and Release overlays. 59| 0| // So we consider the BuildSettingsTable to be the configuration list. 60| 0| dict["buildConfigurationList"] = .identifier(serializer.serialize(object: buildSettings)) 61| 0| dict["mainGroup"] = .identifier(serializer.serialize(object: mainGroup)) 62| 0| dict["hasScannedForEncodings"] = .string("0") 63| 0| dict["knownRegions"] = .array([.string("en")]) 64| 0| if let productGroup = productGroup { 65| 0| dict["productRefGroup"] = .identifier(serializer.id(of: productGroup)) 66| 0| } 67| 0| dict["projectDirPath"] = .string(projectDir) 68| 0| // Ensure that targets are output in a sorted order. 69| 0| let sortedTargets = targets.sorted(by: { $0.name < $1.name }) 70| 0| dict["targets"] = .array(sortedTargets.map({ target in 71| 0| .identifier(serializer.serialize(object: target)) 72| 0| })) 73| 0| return dict 74| 0| } 75| |} 76| | 77| |/// Private helper function that constructs and returns a partial property list 78| |/// dictionary for references. The caller can add to the returned dictionary. 79| |/// FIXME: It would be nicer to be able to use inheritance to serialize the 80| |/// attributes inherited from Reference, but but in Swift 3.0 we get an error 81| |/// that "declarations in extensions cannot override yet". 82| |fileprivate func makeReferenceDict( 83| | reference: Xcode.Reference, 84| | serializer: PropertyListSerializer, 85| | xcodeClassName: String 86| 0|) -> [String: PropertyList] { 87| 0| var dict = [String: PropertyList]() 88| 0| dict["isa"] = .string(xcodeClassName) 89| 0| dict["path"] = .string(reference.path) 90| 0| if let name = reference.name { 91| 0| dict["name"] = .string(name) 92| 0| } 93| 0| dict["sourceTree"] = .string(reference.pathBase.rawValue) 94| 0| return dict 95| 0|} 96| | 97| |extension Xcode.Group: PropertyListSerializable { 98| | 99| | /// Called by the Serializer to serialize the Group. 100| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 101| 0| // Create a `PBXGroup` plist dictionary. 102| 0| // FIXME: It would be nicer to be able to use inheritance for the code 103| 0| // inherited from Reference, but but in Swift 3.0 we get an error that 104| 0| // "declarations in extensions cannot override yet". 105| 0| var dict = makeReferenceDict(reference: self, serializer: serializer, xcodeClassName: "PBXGroup") 106| 0| dict["children"] = .array(subitems.map({ reference in 107| 0| // For the same reason, we have to cast as `PropertyListSerializable` 108| 0| // here; as soon as we try to make Reference conform to the protocol, 109| 0| // we get the problem of not being able to override `serialize(to:)`. 110| 0| .identifier(serializer.serialize(object: reference as! PropertyListSerializable)) 111| 0| })) 112| 0| return dict 113| 0| } 114| |} 115| | 116| |extension Xcode.FileReference: PropertyListSerializable { 117| | 118| | /// Called by the Serializer to serialize the FileReference. 119| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 120| 0| // Create a `PBXFileReference` plist dictionary. 121| 0| // FIXME: It would be nicer to be able to use inheritance for the code 122| 0| // inherited from Reference, but but in Swift 3.0 we get an error that 123| 0| // "declarations in extensions cannot override yet". 124| 0| var dict = makeReferenceDict(reference: self, serializer: serializer, xcodeClassName: "PBXFileReference") 125| 0| if let fileType = fileType { 126| 0| dict["explicitFileType"] = .string(fileType) 127| 0| } 128| 0| // FileReferences don't need to store a name if it's the same as the path. 129| 0| if name == path { 130| 0| dict["name"] = nil 131| 0| } 132| 0| return dict 133| 0| } 134| |} 135| | 136| |extension Xcode.Target: PropertyListSerializable { 137| | 138| | /// Called by the Serializer to serialize the Target. 139| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 140| 0| // Create either a `PBXNativeTarget` or an `PBXAggregateTarget` plist 141| 0| // dictionary (depending on whether or not we have a product type). 142| 0| var dict = [String: PropertyList]() 143| 0| dict["isa"] = .string(productType == nil ? "PBXAggregateTarget" : "PBXNativeTarget") 144| 0| dict["name"] = .string(name) 145| 0| // Build settings are a bit tricky; in Xcode, each is stored in a named 146| 0| // XCBuildConfiguration object, and the list of build configurations is 147| 0| // in turn stored in an XCConfigurationList. In our simplified model, 148| 0| // we have a BuildSettingsTable, with three sets of settings: one for 149| 0| // the common settings, and one each for the Debug and Release overlays. 150| 0| // So we consider the BuildSettingsTable to be the configuration list. 151| 0| // This is the same situation as for Project. 152| 0| dict["buildConfigurationList"] = .identifier(serializer.serialize(object: buildSettings)) 153| 0| dict["buildPhases"] = .array(buildPhases.map({ phase in 154| 0| // Here we have the same problem as for Reference; we cannot inherit 155| 0| // functionality since we're in an extension. 156| 0| .identifier(serializer.serialize(object: phase as! PropertyListSerializable)) 157| 0| })) 158| 0| /// Private wrapper class for a target dependency relation. This is 159| 0| /// glue between our value-based settings structures and the Xcode 160| 0| /// project model's identity-based TargetDependency objects. 161| 0| class TargetDependency: PropertyListSerializable { 162| 0| var target: Xcode.Target 163| 0| init(target: Xcode.Target) { 164| 0| self.target = target 165| 0| } 166| 0| func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 167| 0| // Create a `PBXTargetDependency` plist dictionary. 168| 0| var dict = [String: PropertyList]() 169| 0| dict["isa"] = .string("PBXTargetDependency") 170| 0| dict["target"] = .identifier(serializer.id(of: target)) 171| 0| return dict 172| 0| } 173| 0| } 174| 0| dict["dependencies"] = .array(dependencies.map({ dep in 175| 0| // In the Xcode project model, target dependencies are objects, 176| 0| // so we need a helper class here. 177| 0| .identifier(serializer.serialize(object: TargetDependency(target: dep.target))) 178| 0| })) 179| 0| dict["productName"] = .string(productName) 180| 0| if let productType = productType { 181| 0| dict["productType"] = .string(productType.rawValue) 182| 0| } 183| 0| if let productReference = productReference { 184| 0| dict["productReference"] = .identifier(serializer.id(of: productReference)) 185| 0| } 186| 0| return dict 187| 0| } 188| |} 189| | 190| |/// Private helper function that constructs and returns a partial property list 191| |/// dictionary for build phases. The caller can add to the returned dictionary. 192| |/// FIXME: It would be nicer to be able to use inheritance to serialize the 193| |/// attributes inherited from BuildPhase, but but in Swift 3.0 we get an error 194| |/// that "declarations in extensions cannot override yet". 195| |fileprivate func makeBuildPhaseDict( 196| | buildPhase: Xcode.BuildPhase, 197| | serializer: PropertyListSerializer, 198| | xcodeClassName: String 199| 0|) -> [String: PropertyList] { 200| 0| var dict = [String: PropertyList]() 201| 0| dict["isa"] = .string(xcodeClassName) 202| 0| dict["files"] = .array(buildPhase.files.map({ file in 203| 0| .identifier(serializer.serialize(object: file)) 204| 0| })) 205| 0| return dict 206| 0|} 207| | 208| |extension Xcode.HeadersBuildPhase: PropertyListSerializable { 209| | 210| | /// Called by the Serializer to serialize the HeadersBuildPhase. 211| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 212| 0| // Create a `PBXHeadersBuildPhase` plist dictionary. 213| 0| // FIXME: It would be nicer to be able to use inheritance for the code 214| 0| // inherited from BuildPhase, but but in Swift 3.0 we get an error that 215| 0| // "declarations in extensions cannot override yet". 216| 0| return makeBuildPhaseDict(buildPhase: self, serializer: serializer, xcodeClassName: "PBXHeadersBuildPhase") 217| 0| } 218| |} 219| | 220| |extension Xcode.SourcesBuildPhase: PropertyListSerializable { 221| | 222| | /// Called by the Serializer to serialize the SourcesBuildPhase. 223| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 224| 0| // Create a `PBXSourcesBuildPhase` plist dictionary. 225| 0| // FIXME: It would be nicer to be able to use inheritance for the code 226| 0| // inherited from BuildPhase, but but in Swift 3.0 we get an error that 227| 0| // "declarations in extensions cannot override yet". 228| 0| return makeBuildPhaseDict(buildPhase: self, serializer: serializer, xcodeClassName: "PBXSourcesBuildPhase") 229| 0| } 230| |} 231| | 232| |extension Xcode.FrameworksBuildPhase: PropertyListSerializable { 233| | 234| | /// Called by the Serializer to serialize the FrameworksBuildPhase. 235| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 236| 0| // Create a `PBXFrameworksBuildPhase` plist dictionary. 237| 0| // FIXME: It would be nicer to be able to use inheritance for the code 238| 0| // inherited from BuildPhase, but but in Swift 3.0 we get an error that 239| 0| // "declarations in extensions cannot override yet". 240| 0| return makeBuildPhaseDict(buildPhase: self, serializer: serializer, xcodeClassName: "PBXFrameworksBuildPhase") 241| 0| } 242| |} 243| | 244| |extension Xcode.CopyFilesBuildPhase: PropertyListSerializable { 245| | 246| | /// Called by the Serializer to serialize the FrameworksBuildPhase. 247| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 248| 0| // Create a `PBXCopyFilesBuildPhase` plist dictionary. 249| 0| // FIXME: It would be nicer to be able to use inheritance for the code 250| 0| // inherited from BuildPhase, but but in Swift 3.0 we get an error that 251| 0| // "declarations in extensions cannot override yet". 252| 0| var dict = makeBuildPhaseDict( 253| 0| buildPhase: self, 254| 0| serializer: serializer, 255| 0| xcodeClassName: "PBXCopyFilesBuildPhase") 256| 0| dict["dstPath"] = .string("") // FIXME: needs to be real 257| 0| dict["dstSubfolderSpec"] = .string("") // FIXME: needs to be real 258| 0| return dict 259| 0| } 260| |} 261| | 262| |extension Xcode.ShellScriptBuildPhase: PropertyListSerializable { 263| | 264| | /// Called by the Serializer to serialize the ShellScriptBuildPhase. 265| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 266| 0| // Create a `PBXShellScriptBuildPhase` plist dictionary. 267| 0| // FIXME: It would be nicer to be able to use inheritance for the code 268| 0| // inherited from BuildPhase, but but in Swift 3.0 we get an error that 269| 0| // "declarations in extensions cannot override yet". 270| 0| var dict = makeBuildPhaseDict( 271| 0| buildPhase: self, 272| 0| serializer: serializer, 273| 0| xcodeClassName: "PBXShellScriptBuildPhase") 274| 0| dict["shellPath"] = .string("/bin/sh") // FIXME: should be settable 275| 0| dict["shellScript"] = .string(script) 276| 0| return dict 277| 0| } 278| |} 279| | 280| |extension Xcode.BuildFile: PropertyListSerializable { 281| | 282| | /// Called by the Serializer to serialize the BuildFile. 283| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 284| 0| // Create a `PBXBuildFile` plist dictionary. 285| 0| var dict = [String: PropertyList]() 286| 0| dict["isa"] = .string("PBXBuildFile") 287| 0| if let fileRef = fileRef { 288| 0| dict["fileRef"] = .identifier(serializer.id(of: fileRef)) 289| 0| } 290| 0| 291| 0| let settingsDict = settings.asPropertyList() 292| 0| if !settingsDict.isEmpty { 293| 0| dict["settings"] = settingsDict 294| 0| } 295| 0| 296| 0| return dict 297| 0| } 298| |} 299| | 300| |extension Xcode.BuildSettingsTable: PropertyListSerializable { 301| | 302| | /// Called by the Serializer to serialize the BuildFile. It is serialized 303| | /// as an XCBuildConfigurationList and two additional XCBuildConfiguration 304| | /// objects (one for debug and one for release). 305| 0| fileprivate func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 306| 0| /// Private wrapper class for BuildSettings structures. This is glue 307| 0| /// between our value-based settings structures and the Xcode project 308| 0| /// model's identity-based XCBuildConfiguration objects. 309| 0| class BuildSettingsDictWrapper: PropertyListSerializable { 310| 0| let name: String 311| 0| var baseSettings: BuildSettings 312| 0| var overlaySettings: BuildSettings 313| 0| let xcconfigFileRef: Xcode.FileReference? 314| 0| 315| 0| init( 316| 0| name: String, 317| 0| baseSettings: BuildSettings, 318| 0| overlaySettings: BuildSettings, 319| 0| xcconfigFileRef: Xcode.FileReference? 320| 0| ) { 321| 0| self.name = name 322| 0| self.baseSettings = baseSettings 323| 0| self.overlaySettings = overlaySettings 324| 0| self.xcconfigFileRef = xcconfigFileRef 325| 0| } 326| 0| 327| 0| func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] { 328| 0| // Create a `XCBuildConfiguration` plist dictionary. 329| 0| var dict = [String: PropertyList]() 330| 0| dict["isa"] = .string("XCBuildConfiguration") 331| 0| dict["name"] = .string(name) 332| 0| // Combine the base settings and the overlay settings. 333| 0| dict["buildSettings"] = combineBuildSettingsPropertyLists( 334| 0| baseSettings: baseSettings.asPropertyList(), 335| 0| overlaySettings: overlaySettings.asPropertyList()) 336| 0| // Add a reference to the base configuration, if there is one. 337| 0| if let xcconfigFileRef = xcconfigFileRef { 338| 0| dict["baseConfigurationReference"] = .identifier(serializer.id(of: xcconfigFileRef)) 339| 0| } 340| 0| return dict 341| 0| } 342| 0| } 343| 0| 344| 0| // Create a `XCConfigurationList` plist dictionary. 345| 0| var dict = [String: PropertyList]() 346| 0| dict["isa"] = .string("XCConfigurationList") 347| 0| dict["buildConfigurations"] = .array([ 348| 0| // We use a private wrapper to "objectify" our two build settings 349| 0| // structures (which, being structs, are value types). 350| 0| .identifier(serializer.serialize(object: BuildSettingsDictWrapper( 351| 0| name: "Debug", 352| 0| baseSettings: common, 353| 0| overlaySettings: debug, 354| 0| xcconfigFileRef: xcconfigFileRef))), 355| 0| .identifier(serializer.serialize(object: BuildSettingsDictWrapper( 356| 0| name: "Release", 357| 0| baseSettings: common, 358| 0| overlaySettings: release, 359| 0| xcconfigFileRef: xcconfigFileRef))), 360| 0| ]) 361| 0| // FIXME: What is this, and why are we setting it? 362| 0| dict["defaultConfigurationIsVisible"] = .string("0") 363| 0| // FIXME: Should we allow this to be set in the model? 364| 0| dict["defaultConfigurationName"] = .string("Release") 365| 0| return dict 366| 0| } 367| |} 368| | 369| |protocol PropertyListDictionaryConvertible { 370| | func asPropertyList() -> PropertyList 371| |} 372| | 373| |extension PropertyListDictionaryConvertible { 374| | // FIXME: Internal only for unit testing. 375| | // 376| | /// Returns a property list representation of the build settings, in which 377| | /// every struct field is represented as a dictionary entry. Fields of 378| | /// type `String` are represented as `PropertyList.string` values; fields 379| | /// of type `[String]` are represented as `PropertyList.array` values with 380| | /// `PropertyList.string` values as the array elements. The property list 381| | /// dictionary only contains entries for struct fields that aren't nil. 382| | /// 383| | /// Note: BuildSettings is a value type and PropertyListSerializable only 384| | /// applies to classes. Creating a property list representation is totally 385| | /// independent of that serialization infrastructure (though it might well 386| | /// be invoked during of serialization of actual model objects). 387| 0| func asPropertyList() -> PropertyList { 388| 0| // Borderline hacky, but the main thing is that adding or changing a 389| 0| // build setting does not require any changes to the property list 390| 0| // representation code. Using a handcoded serializer might be more 391| 0| // efficient but not even remotely as robust, and robustness is the 392| 0| // key factor for this use case, as there aren't going to be millions 393| 0| // of BuildSettings structs. 394| 0| var dict = [String: PropertyList]() 395| 0| let mirror = Mirror(reflecting: self) 396| 0| for child in mirror.children { 397| 0| guard let name = child.label else { 398| 0| preconditionFailure("unnamed build settings are not supported") 399| 0| } 400| 0| switch child.value { 401| 0| case nil: 402| 0| continue 403| 0| case let value as String: 404| 0| dict[name] = .string(value) 405| 0| case let value as [String]: 406| 0| dict[name] = .array(value.map({ .string($0) })) 407| 0| default: 408| 0| // FIXME: I haven't found a way of distinguishing a value of an 409| 0| // unexpected type from a value that is nil; they all seem to go 410| 0| // throught the `default` case instead of the `nil` case above. 411| 0| // Hopefully someone reading this will clue me in about what I 412| 0| // did wrong. But currently we will silently fail to serialize 413| 0| // any struct field that isn't a `String` or a `[String]` (or 414| 0| // an optional of either of those two). 415| 0| // This would only come up if a field were to be added of a type 416| 0| // other than `String` or `[String]`. 417| 0| continue 418| 0| } 419| 0| } 420| 0| return .dictionary(dict) 421| 0| } 422| |} 423| | 424| |extension Xcode.BuildFile.Settings: PropertyListDictionaryConvertible {} 425| |extension Xcode.BuildSettingsTable.BuildSettings: PropertyListDictionaryConvertible {} 426| | 427| |/// Private helper function that combines a base property list and an overlay 428| |/// property list, respecting the semantics of `$(inherited)` as we go. 429| |fileprivate func combineBuildSettingsPropertyLists( 430| | baseSettings: PropertyList, 431| | overlaySettings: PropertyList 432| 0|) -> PropertyList { 433| 0| // Extract the base and overlay dictionaries. 434| 0| guard case let .dictionary(baseDict) = baseSettings else { 435| 0| preconditionFailure("base settings plist must be a dictionary") 436| 0| } 437| 0| guard case let .dictionary(overlayDict) = overlaySettings else { 438| 0| preconditionFailure("overlay settings plist must be a dictionary") 439| 0| } 440| 0| 441| 0| // Iterate over the overlay values and apply them to the base. 442| 0| var resultDict = baseDict 443| 0| for (name, value) in overlayDict { 444| 0| if let array = baseDict[name]?.array, let overlayArray = value.array, overlayArray.first?.string == "$(inherited)" { 445| 0| resultDict[name] = .array(array + overlayArray.dropFirst()) 446| 0| } else { 447| 0| resultDict[name] = value 448| 0| } 449| 0| } 450| 0| return .dictionary(resultDict) 451| 0|} 452| | 453| |/// A simple property list serializer with the same semantics as the Xcode 454| |/// property list serializer. Not generally reusable at this point, but only 455| |/// because of implementation details (architecturally it isn't tied to Xcode). 456| |fileprivate class PropertyListSerializer { 457| | 458| | /// Private struct that represents a strong reference to a serializable 459| | /// object. This prevents any temporary objects from being deallocated 460| | /// during the serialization and replaced with other objects having the 461| | /// same object identifier (a violation of our assumptions) 462| | struct SerializedObjectRef: Hashable, Equatable { 463| | let object: PropertyListSerializable 464| | 465| 0| init(_ object: PropertyListSerializable) { 466| 0| self.object = object 467| 0| } 468| | 469| 0| func hash(into hasher: inout Hasher) { 470| 0| hasher.combine(ObjectIdentifier(object)) 471| 0| } 472| | 473| 0| static func == (lhs: SerializedObjectRef, rhs: SerializedObjectRef) -> Bool { 474| 0| return lhs.object === rhs.object 475| 0| } 476| | } 477| | 478| | /// Maps objects to the identifiers that have been assigned to them. The 479| | /// next identifier to be assigned is always one greater than the number 480| | /// of entries in the mapping. 481| | var objsToIds = [SerializedObjectRef: String]() 482| | 483| | /// Maps serialized objects ids to dictionaries. This may contain fewer 484| | /// entries than `objsToIds`, since ids are assigned upon reference, but 485| | /// plist dictionaries are created only upon actual serialization. This 486| | /// dictionary is what gets written to the property list. 487| | var idsToDicts = [String: PropertyList]() 488| | 489| | /// Returns the quoted identifier for the object, assigning one if needed. 490| 0| func id(of object: PropertyListSerializable) -> String { 491| 0| // We need a "serialized object ref" wrapper for the `objsToIds` map. 492| 0| let serObjRef = SerializedObjectRef(object) 493| 0| if let id = objsToIds[serObjRef] { 494| 0| return "\"\(id)\"" 495| 0| } 496| 0| // We currently always assign identifiers starting at 1 and going up. 497| 0| // FIXME: This is a suboptimal format for object identifier strings; 498| 0| // for debugging purposes they should at least sort in numeric order. 499| 0| let id = object.objectID ?? "OBJ_\(objsToIds.count + 1)" 500| 0| objsToIds[serObjRef] = id 501| 0| return "\"\(id)\"" 502| 0| } 503| | 504| | /// Serializes `object` by asking it to construct a plist dictionary and 505| | /// then adding that dictionary to the serializer. This may in turn cause 506| | /// recursive invocations of `serialize(object:)`; the closure of these 507| | /// invocations end up serializing the whole object graph. 508| 0| @discardableResult func serialize(object: PropertyListSerializable) -> String { 509| 0| // Assign an id for the object, if it doesn't already have one. 510| 0| let id = self.id(of: object) 511| 0| 512| 0| // If that id is already in `idsToDicts`, we've detected recursion or 513| 0| // repeated serialization. 514| 0| precondition(idsToDicts[id] == nil, "tried to serialize \(object) twice") 515| 0| 516| 0| // Set a sentinel value in the `idsToDicts` mapping to detect recursion. 517| 0| idsToDicts[id] = .dictionary([:]) 518| 0| 519| 0| // Now recursively serialize the object, and store the result (replacing 520| 0| // the sentinel). 521| 0| idsToDicts[id] = .dictionary(object.serialize(to: self)) 522| 0| 523| 0| // Finally, return the identifier so the caller can store it (usually in 524| 0| // an attribute in its own serialization dictionary). 525| 0| return id 526| 0| } 527| |} 528| | 529| |fileprivate protocol PropertyListSerializable: class { 530| | /// Called by the Serializer to construct and return a dictionary for a 531| | /// serializable object. The entries in the dictionary should represent 532| | /// the receiver's attributes and relationships, as PropertyList values. 533| | /// 534| | /// Every object that is written to the Serializer is assigned an id (an 535| | /// arbitrary but unique string). Forward references can use `id(of:)` 536| | /// of the Serializer to assign and access the id before the object is 537| | /// actually written. 538| | /// 539| | /// Implementations can use the Serializer's `serialize(object:)` method 540| | /// to serialize owned objects (getting an id to the serialized object, 541| | /// which can be stored in one of the attributes) or can use the `id(of:)` 542| | /// method to store a reference to an unowned object. 543| | /// 544| | /// The implementation of this method for each serializable objects looks 545| | /// something like this: 546| | /// 547| | /// // Create a `PBXSomeClassOrOther` plist dictionary. 548| | /// var dict = [String: PropertyList]() 549| | /// dict["isa"] = .string("PBXSomeClassOrOther") 550| | /// dict["name"] = .string(name) 551| | /// if let path = path { dict["path"] = .string(path) } 552| | /// dict["mainGroup"] = .identifier(serializer.serialize(object: mainGroup)) 553| | /// dict["subitems"] = .array(subitems.map({ .string($0.id) })) 554| | /// dict["cross-ref"] = .identifier(serializer.id(of: unownedObject)) 555| | /// return dict 556| | /// 557| | /// FIXME: I'm not totally happy with how this looks. It's far too clunky 558| | /// and could be made more elegant. However, since the Xcode project model 559| | /// is static, this is not something that will need to evolve over time. 560| | /// What does need to evolve, which is how the project model is constructed 561| | /// from the package contents, is where the elegance and simplicity really 562| | /// matters. So this is acceptable for now in the interest of getting it 563| | /// done. 564| | 565| | /// A custom ID to use for the instance, if enabled. 566| | /// 567| | /// This ID must be unique across the entire serialized graph. 568| | var objectID: String? { get } 569| | 570| | /// Should create and return a property list dictionary of the object's 571| | /// attributes. This function may also use the serializer's `serialize()` 572| | /// function to serialize other objects, and may use `id(of:)` to access 573| | /// ids of objects that either have or will be serialized. 574| | func serialize(to serializer: PropertyListSerializer) -> [String: PropertyList] 575| |} 576| | 577| |extension PropertyListSerializable { 578| 0| var objectID: String? { 579| 0| return nil 580| 0| } 581| |} 582| | 583| |extension PropertyList { 584| 0| var isEmpty: Bool { 585| 0| switch self { 586| 0| case let .identifier(string): return string.isEmpty 587| 0| case let .string(string): return string.isEmpty 588| 0| case let .array(array): return array.isEmpty 589| 0| case let .dictionary(dictionary): return dictionary.isEmpty 590| 0| } 591| 0| } 592| |} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/generate().swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import POSIX 13| |import PackageGraph 14| |import PackageModel 15| |import PackageLoading 16| |import SourceControl 17| |import SPMUtility 18| | 19| |public struct XcodeprojOptions { 20| | /// The build flags. 21| | public var flags: BuildFlags 22| | 23| | /// If provided, a path to an xcconfig file to be included by the project. 24| | /// 25| | /// This allows the client to override settings defined in the project itself. 26| | public var xcconfigOverrides: AbsolutePath? 27| | 28| | /// Whether code coverage should be enabled in the generated scheme. 29| | public var isCodeCoverageEnabled: Bool 30| | 31| | /// Whether to use legacy scheme generation logic. 32| | public var useLegacySchemeGenerator: Bool 33| | 34| | /// Run watchman to auto-generate the project file on changes. 35| | public var enableAutogeneration: Bool 36| | 37| | /// Whether to add extra files to the generated project. 38| | public var addExtraFiles: Bool 39| | 40| | /// Reference to manifest loader, if present. 41| | public var manifestLoader: ManifestLoader? 42| | 43| | public init( 44| | flags: BuildFlags = BuildFlags(), 45| | xcconfigOverrides: AbsolutePath? = nil, 46| | isCodeCoverageEnabled: Bool? = nil, 47| | useLegacySchemeGenerator: Bool? = nil, 48| | enableAutogeneration: Bool? = nil, 49| | addExtraFiles: Bool? = nil 50| 0| ) { 51| 0| self.flags = flags 52| 0| self.xcconfigOverrides = xcconfigOverrides 53| 0| self.isCodeCoverageEnabled = isCodeCoverageEnabled ?? false 54| 0| self.useLegacySchemeGenerator = useLegacySchemeGenerator ?? false 55| 0| self.enableAutogeneration = enableAutogeneration ?? false 56| 0| self.addExtraFiles = addExtraFiles ?? true 57| 0| } 58| |} 59| | 60| |// Determine the path of the .xcodeproj wrapper directory. 61| 0|public func buildXcodeprojPath(outputDir: AbsolutePath, projectName: String) -> AbsolutePath { 62| 0| let xcodeprojName = "\(projectName).xcodeproj" 63| 0| return outputDir.appending(RelativePath(xcodeprojName)) 64| 0|} 65| | 66| |/// Generates an Xcode project and all needed support files. The .xcodeproj 67| |/// wrapper directory is created to the path specified by `xcodeprojPath` 68| |/// Returns the generated project. All ancillary files will 69| |/// be generated inside of the .xcodeproj wrapper directory. 70| |@discardableResult 71| |public func generate( 72| | projectName: String, 73| | xcodeprojPath: AbsolutePath, 74| | graph: PackageGraph, 75| | repositoryProvider: RepositoryProvider = GitRepositoryProvider(), 76| | options: XcodeprojOptions, 77| | diagnostics: DiagnosticsEngine 78| 0|) throws -> Xcode.Project { 79| 0| // Note that the output directory might be completely separate from the 80| 0| // path of the root package (which is where the sources live). 81| 0| 82| 0| let srcroot = graph.rootPackages[0].path 83| 0| 84| 0| // Determine the path of the scheme directory (it's inside the .xcodeproj). 85| 0| let schemesDir = xcodeprojPath.appending(components: "xcshareddata", "xcschemes") 86| 0| 87| 0| // Create the .xcodeproj wrapper directory. 88| 0| try makeDirectories(xcodeprojPath) 89| 0| try makeDirectories(schemesDir) 90| 0| 91| 0| let extraDirs: [AbsolutePath] 92| 0| var extraFiles = [AbsolutePath]() 93| 0| 94| 0| if options.addExtraFiles { 95| 0| // Find the paths of any extra directories that should be added as folder 96| 0| // references in the project. 97| 0| extraDirs = try findDirectoryReferences(path: srcroot) 98| 0| 99| 0| if try repositoryProvider.checkoutExists(at: srcroot) { 100| 0| let workingCheckout = try repositoryProvider.openCheckout(at: srcroot) 101| 0| extraFiles = try getExtraFilesFor(package: graph.rootPackages[0], in: workingCheckout) 102| 0| } 103| 0| } else { 104| 0| extraDirs = [] 105| 0| } 106| 0| 107| 0| // FIXME: This could be more efficient by directly writing to a stream 108| 0| // instead of first creating a string. 109| 0| // 110| 0| /// Generate the contents of project.xcodeproj (inside the .xcodeproj). 111| 0| let project = try pbxproj(xcodeprojPath: xcodeprojPath, graph: graph, extraDirs: extraDirs, extraFiles: extraFiles, options: options, diagnostics: diagnostics) 112| 0| try open(xcodeprojPath.appending(component: "project.pbxproj")) { stream in 113| 0| // Serialize the project model we created to a plist, and return 114| 0| // its string description. 115| 0| let str = "// !$*UTF8*$!\n" + project.generatePlist().description 116| 0| stream(str) 117| 0| } 118| 0| 119| 0| try generateSchemes( 120| 0| graph: graph, 121| 0| container: xcodeprojPath.relative(to: srcroot).pathString, 122| 0| schemesDir: schemesDir, 123| 0| options: options, 124| 0| schemeContainer: xcodeprojPath.relative(to: srcroot).pathString 125| 0| ) 126| 0| 127| 0| for target in graph.reachableTargets where target.type == .library || target.type == .test { 128| 0| ///// For framework targets, generate target.c99Name_Info.plist files in the 129| 0| ///// directory that Xcode project is generated 130| 0| let name = target.infoPlistFileName 131| 0| try open(xcodeprojPath.appending(RelativePath(name))) { print in 132| 0| print(""" 133| 0| 134| 0| 135| 0| 136| 0| CFBundleDevelopmentRegion 137| 0| en 138| 0| CFBundleExecutable 139| 0| $(EXECUTABLE_NAME) 140| 0| CFBundleIdentifier 141| 0| $(PRODUCT_BUNDLE_IDENTIFIER) 142| 0| CFBundleInfoDictionaryVersion 143| 0| 6.0 144| 0| CFBundleName 145| 0| $(PRODUCT_NAME) 146| 0| CFBundlePackageType 147| 0| \(target.type == .test ? "BNDL" : "FMWK") 148| 0| CFBundleShortVersionString 149| 0| 1.0 150| 0| CFBundleSignature 151| 0| ???? 152| 0| CFBundleVersion 153| 0| $(CURRENT_PROJECT_VERSION) 154| 0| NSPrincipalClass 155| 0| 156| 0| 157| 0| 158| 0| """) 159| 0| } 160| 0| } 161| 0| 162| 0| return project 163| 0|} 164| | 165| |/// Writes the contents to the file specified. 166| |/// 167| |/// This method doesn't rewrite the file in case the new and old contents of 168| |/// file are same. 169| 0|func open(_ path: AbsolutePath, body: ((String) -> Void) throws -> Void) throws { 170| 0| let stream = BufferedOutputByteStream() 171| 0| try body { line in 172| 0| stream <<< line 173| 0| stream <<< "\n" 174| 0| } 175| 0| // If the file exists with the identical contents, we don't need to rewrite it. 176| 0| // 177| 0| // This avoids unnecessarily triggering Xcode reloads of the project file. 178| 0| if let contents = try? localFileSystem.readFileContents(path), contents == stream.bytes { 179| 0| return 180| 0| } 181| 0| 182| 0| // Write the real file. 183| 0| try localFileSystem.writeFileContents(path, bytes: stream.bytes) 184| 0|} 185| | 186| |/// Finds directories that will be added as blue folder 187| |/// Excludes hidden directories, Xcode projects and reserved directories 188| 0|func findDirectoryReferences(path: AbsolutePath) throws -> [AbsolutePath] { 189| 0| let rootDirectories = try walk(path, recursively: false) 190| 0| 191| 0| return rootDirectories.filter({ 192| 0| if $0.suffix == ".xcodeproj" { return false } 193| 0| if $0.suffix == ".playground" { return false } 194| 0| if $0.basename.hasPrefix(".") { return false } 195| 0| if PackageBuilder.predefinedTestDirectories.contains($0.basename) { return false } 196| 0| return isDirectory($0) 197| 0| }) 198| 0|} 199| | 200| |func generateSchemes( 201| | graph: PackageGraph, 202| | container: String, 203| | schemesDir: AbsolutePath, 204| | options: XcodeprojOptions, 205| | schemeContainer: String 206| 0|) throws { 207| 0| if options.useLegacySchemeGenerator { 208| 0| // The scheme acts like an aggregate target for all our targets it has all 209| 0| // tests associated so testing works. We suffix the name of this scheme with 210| 0| // -Package so its name doesn't collide with any products or target with 211| 0| // same name. 212| 0| let schemeName = "\(graph.rootPackages[0].name)-Package.xcscheme" 213| 0| try open(schemesDir.appending(RelativePath(schemeName))) { stream in 214| 0| legacySchemeGenerator( 215| 0| container: schemeContainer, 216| 0| graph: graph, 217| 0| codeCoverageEnabled: options.isCodeCoverageEnabled, 218| 0| printer: stream) 219| 0| } 220| 0| 221| 0| // We generate this file to ensure our main scheme is listed before any 222| 0| // inferred schemes Xcode may autocreate. 223| 0| try open(schemesDir.appending(component: "xcschememanagement.plist")) { print in 224| 0| print(""" 225| 0| 226| 0| 227| 0| 228| 0| SchemeUserState 229| 0| 230| 0| \(schemeName) 231| 0| 232| 0| 233| 0| SuppressBuildableAutocreation 234| 0| 235| 0| 236| 0| 237| 0| """) 238| 0| } 239| 0| } else { 240| 0| try SchemesGenerator( 241| 0| graph: graph, 242| 0| container: schemeContainer, 243| 0| schemesDir: schemesDir, 244| 0| isCodeCoverageEnabled: options.isCodeCoverageEnabled, 245| 0| fs: localFileSystem 246| 0| ).generate() 247| 0| } 248| 0|} 249| | 250| |// Find and return non-source files in the source directories and root that should be added 251| |// as a reference to the project. 252| 0|func getExtraFilesFor(package: ResolvedPackage, in workingCheckout: WorkingCheckout) throws -> [AbsolutePath] { 253| 0| let srcroot = package.path 254| 0| var extraFiles = try findNonSourceFiles(path: srcroot, manifestVersion: package.manifest.manifestVersion) 255| 0| 256| 0| for target in package.targets { 257| 0| let sourcesDirectory = target.sources.root 258| 0| if localFileSystem.isDirectory(sourcesDirectory) { 259| 0| let sourcesExtraFiles = try findNonSourceFiles(path: sourcesDirectory, manifestVersion: package.manifest.manifestVersion, recursively: true) 260| 0| extraFiles.append(contentsOf: sourcesExtraFiles) 261| 0| } 262| 0| } 263| 0| 264| 0| let isIgnored = try workingCheckout.areIgnored(extraFiles) 265| 0| extraFiles = extraFiles.enumerated().filter({ !isIgnored[$0.offset] }).map({ $0.element }) 266| 0| 267| 0| return extraFiles 268| 0|} 269| | 270| |/// Finds the non-source files from `path` 271| |/// - parameters: 272| |/// - path: The path of the directory to get the files from 273| |/// - recursively: Specifies if the directory at `path` should be searched recursively 274| 0|func findNonSourceFiles(path: AbsolutePath, manifestVersion: ManifestVersion, recursively: Bool = false) throws -> [AbsolutePath] { 275| 0| let filesFromPath = try walk(path, recursively: recursively) 276| 0| 277| 0| return filesFromPath.filter({ 278| 0| if !isFile($0) { return false } 279| 0| if $0.basename.hasPrefix(".") { return false } 280| 0| if $0.basename == "Package.resolved" { return false } 281| 0| if let `extension` = $0.extension, SupportedLanguageExtension.validExtensions(manifestVersion: manifestVersion).contains(`extension`) { 282| 0| return false 283| 0| } 284| 0| return true 285| 0| }) 286| 0|} /Users/travis/build/eneko/CommandRegistry/.build/checkouts/swift-package-manager/Sources/Xcodeproj/pbxproj().swift: 1| |/* 2| | This source file is part of the Swift.org open source project 3| | 4| | Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 5| | Licensed under Apache License v2.0 with Runtime Library Exception 6| | 7| | See http://swift.org/LICENSE.txt for license information 8| | See http://swift.org/CONTRIBUTORS.txt for Swift project authors 9| |*/ 10| | 11| |import Basic 12| |import POSIX 13| |import PackageGraph 14| |import PackageModel 15| |import PackageLoading 16| |import SPMUtility 17| | 18| |/// Errors encounter during Xcode project generation 19| |public enum ProjectGenerationError: Swift.Error { 20| | /// The given xcconfig override file does not exist 21| | case xcconfigOverrideNotFound(path: AbsolutePath) 22| |} 23| | 24| |/// Generates the contents of the `project.pbxproj` for the package graph. The 25| |/// project file is generated with the assumption that it will be written to an 26| |/// .xcodeproj wrapper at `xcodeprojPath` (this affects relative references to 27| |/// ancillary files inside the wrapper). Note that the root directory of the 28| |/// sources is not necessarily related to this path; the source root directory 29| |/// is the path of the root package in the package graph, independent of the 30| |/// directory to which the .xcodeproj is being generated. 31| |public func pbxproj( 32| | xcodeprojPath: AbsolutePath, 33| | graph: PackageGraph, 34| | extraDirs: [AbsolutePath], 35| | extraFiles: [AbsolutePath], 36| | options: XcodeprojOptions, 37| | diagnostics: DiagnosticsEngine, 38| | fileSystem: FileSystem = localFileSystem 39| 0| ) throws -> Xcode.Project { 40| 0| return try xcodeProject( 41| 0| xcodeprojPath: xcodeprojPath, 42| 0| graph: graph, 43| 0| extraDirs: extraDirs, 44| 0| extraFiles: extraFiles, 45| 0| options: options, 46| 0| fileSystem: fileSystem, 47| 0| diagnostics: diagnostics) 48| 0|} 49| | 50| |// FIXME: Handle case insensitive filesystems. 51| |// 52| |/// A set of c99 target names that are invalid for Xcode Framework targets. 53| |/// They will conflict with the required Framework directory structure, 54| |/// and cause a linker error (SR-3398). 55| |fileprivate let invalidXcodeModuleNames = Set(["Modules", "Headers", "Versions"]) 56| | 57| |func xcodeProject( 58| | xcodeprojPath: AbsolutePath, 59| | graph: PackageGraph, 60| | extraDirs: [AbsolutePath], 61| | extraFiles: [AbsolutePath], 62| | options: XcodeprojOptions, 63| | fileSystem: FileSystem, 64| | diagnostics: DiagnosticsEngine, 65| | warningStream: OutputByteStream = stdoutStream 66| 0|) throws -> Xcode.Project { 67| 0| 68| 0| // Create the project. 69| 0| let project = Xcode.Project() 70| 0| 71| 0| // Generates a dummy target to provide autocompletion for the manifest file. 72| 0| func createPackageDescriptionTarget(for package: ResolvedPackage, manifestFileRef: Xcode.FileReference) { 73| 0| guard let manifestLoader = options.manifestLoader else { return } 74| 0| 75| 0| let pdTarget = project.addTarget( 76| 0| objectID: "\(package.name)::SwiftPMPackageDescription", 77| 0| productType: .framework, name: "\(package.name)PackageDescription") 78| 0| let compilePhase = pdTarget.addSourcesBuildPhase() 79| 0| compilePhase.addBuildFile(fileRef: manifestFileRef) 80| 0| 81| 0| var interpreterFlags = manifestLoader.interpreterFlags(for: package.manifest.manifestVersion) 82| 0| if !interpreterFlags.isEmpty { 83| 0| // Patch the interpreter flags to use Xcode supported toolchain macro instead of the resolved path. 84| 0| interpreterFlags[3] = "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/\(package.manifest.manifestVersion.runtimeSubpath.pathString)" 85| 0| } 86| 0| pdTarget.buildSettings.common.OTHER_SWIFT_FLAGS += interpreterFlags 87| 0| pdTarget.buildSettings.common.SWIFT_VERSION = package.manifest.manifestVersion.swiftLanguageVersion.xcodeBuildSettingValue 88| 0| pdTarget.buildSettings.common.LD = "/usr/bin/true" 89| 0| } 90| 0| 91| 0| // Determine the source root directory (which is NOT necessarily related in 92| 0| // any way to `xcodeprojPath`, i.e. we cannot assume that the Xcode project 93| 0| // will be generated into to the source root directory). 94| 0| let sourceRootDir = graph.rootPackages[0].path 95| 0| 96| 0| // Set the project's notion of the source root directory to be a relative 97| 0| // path from the directory that contains the .xcodeproj to the source root 98| 0| // directory (note that those two directories might or might be the same). 99| 0| // The effect is to make any `projectDir`-relative path be relative to the 100| 0| // source root directory, i.e. the path of the root package. 101| 0| project.projectDir = sourceRootDir.relative(to: xcodeprojPath.parentDirectory).pathString 102| 0| 103| 0| // Configure the project settings. 104| 0| let projectSettings = project.buildSettings 105| 0| 106| 0| // First of all, set a standard definition of `PROJECT_NAME`. 107| 0| projectSettings.common.PRODUCT_NAME = "$(TARGET_NAME)" 108| 0| 109| 0| // Set the SUPPORTED_PLATFORMS to all platforms. 110| 0| // FIXME: This doesn't seem correct, but was what the old project generation 111| 0| // code did, so for now we do so too. 112| 0| projectSettings.common.SUPPORTED_PLATFORMS = [ 113| 0| "macosx", 114| 0| "iphoneos", 115| 0| "iphonesimulator", 116| 0| "appletvos", 117| 0| "appletvsimulator", 118| 0| "watchos", 119| 0| "watchsimulator", 120| 0| ] 121| 0| 122| 0| // Set the default `SDKROOT` to the latest macOS SDK. 123| 0| projectSettings.common.SDKROOT = "macosx" 124| 0| 125| 0| // Default to @rpath-based install names. Any target that links against 126| 0| // these products will need to establish the appropriate runpath search 127| 0| // paths so that all the products can be found. 128| 0| projectSettings.common.DYLIB_INSTALL_NAME_BASE = "@rpath" 129| 0| 130| 0| // Add any additional compiler and linker flags the user has specified. 131| 0| if !options.flags.cCompilerFlags.isEmpty { 132| 0| projectSettings.common.OTHER_CFLAGS = options.flags.cCompilerFlags 133| 0| } 134| 0| if !options.flags.linkerFlags.isEmpty { 135| 0| projectSettings.common.OTHER_LDFLAGS = options.flags.linkerFlags 136| 0| } 137| 0| if !options.flags.swiftCompilerFlags.isEmpty { 138| 0| projectSettings.common.OTHER_SWIFT_FLAGS = options.flags.swiftCompilerFlags 139| 0| } 140| 0| 141| 0| // Also set the `Xcode` build preset in Swift to let code conditionalize on 142| 0| // being built in Xcode. 143| 0| projectSettings.common.OTHER_SWIFT_FLAGS += ["-DXcode"] 144| 0| projectSettings.common.MACOSX_DEPLOYMENT_TARGET = "10.10" 145| 0| 146| 0| // Prevent Xcode project upgrade warnings. 147| 0| projectSettings.common.COMBINE_HIDPI_IMAGES = "YES" 148| 0| 149| 0| // Defined for regular `swift build` instantiations, so also should be defined here. 150| 0| projectSettings.common.SWIFT_ACTIVE_COMPILATION_CONDITIONS += ["$(inherited)", "SWIFT_PACKAGE"] 151| 0| projectSettings.common.GCC_PREPROCESSOR_DEFINITIONS += ["$(inherited)", "SWIFT_PACKAGE=1"] 152| 0| 153| 0| // Opt out of headermaps. The semantics of the build should be explicitly 154| 0| // defined by the project structure, so that we don't get any additional 155| 0| // magic behavior that isn't present in `swift build`. 156| 0| projectSettings.common.USE_HEADERMAP = "NO" 157| 0| 158| 0| // Enable `Automatic Reference Counting` for Objective-C sources 159| 0| projectSettings.common.CLANG_ENABLE_OBJC_ARC = "YES" 160| 0| 161| 0| // Add some debug-specific settings. 162| 0| projectSettings.debug.COPY_PHASE_STRIP = "NO" 163| 0| projectSettings.debug.DEBUG_INFORMATION_FORMAT = "dwarf" 164| 0| projectSettings.debug.ENABLE_NS_ASSERTIONS = "YES" 165| 0| projectSettings.debug.GCC_OPTIMIZATION_LEVEL = "0" 166| 0| projectSettings.debug.GCC_PREPROCESSOR_DEFINITIONS = ["$(inherited)", "DEBUG=1"] 167| 0| projectSettings.debug.ONLY_ACTIVE_ARCH = "YES" 168| 0| projectSettings.debug.SWIFT_OPTIMIZATION_LEVEL = "-Onone" 169| 0| projectSettings.debug.SWIFT_ACTIVE_COMPILATION_CONDITIONS += ["$(inherited)", "DEBUG"] 170| 0| 171| 0| // Add some release-specific settings. 172| 0| projectSettings.release.COPY_PHASE_STRIP = "YES" 173| 0| projectSettings.release.DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym" 174| 0| projectSettings.release.GCC_OPTIMIZATION_LEVEL = "s" 175| 0| projectSettings.release.SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule" 176| 0| 177| 0| // Add a file reference for the package manifest itself. 178| 0| // FIXME: We should parameterize this so that a package can return the path 179| 0| // of its manifest file. 180| 0| let manifestFileRef = project.mainGroup.addFileReference(path: "Package.swift", fileType: "sourcecode.swift") 181| 0| createPackageDescriptionTarget(for: graph.rootPackages[0], manifestFileRef: manifestFileRef) 182| 0| 183| 0| // Add a group for the overriding .xcconfig file, if we have one. 184| 0| let xcconfigOverridesFileRef: Xcode.FileReference? 185| 0| if let xcconfigPath = options.xcconfigOverrides { 186| 0| // Verify that the xcconfig override file exists 187| 0| if !fileSystem.exists(xcconfigPath) { 188| 0| throw ProjectGenerationError.xcconfigOverrideNotFound(path: xcconfigPath) 189| 0| } 190| 0| 191| 0| // Create a "Configs" group whose path is the same as the project path. 192| 0| let xcconfigsGroup = project.mainGroup.addGroup(path: "", name: "Configs") 193| 0| 194| 0| // Create a file reference for the .xcconfig file (with a path relative 195| 0| // to the group). 196| 0| xcconfigOverridesFileRef = xcconfigsGroup.addFileReference( 197| 0| path: xcconfigPath.relative(to: sourceRootDir).pathString, 198| 0| name: xcconfigPath.basename) 199| 0| 200| 0| // We don't assign the file reference as the xcconfig file reference of 201| 0| // the project's build settings, because if we do, the xcconfig cannot 202| 0| // override any of the default build settings at the project level. So 203| 0| // we instead assign it to each target. 204| 0| 205| 0| // We may instead want to emit all build settings to separate .xcconfig 206| 0| // files that use `#include` to include the overriding .xcconfig file. 207| 0| } else { 208| 0| // Otherwise, we don't create an .xcconfig file reference. 209| 0| xcconfigOverridesFileRef = nil 210| 0| } 211| 0| 212| 0| // Determine the list of external package dependencies, if any. 213| 0| let externalPackages = graph.packages.filter({ !graph.rootPackages.contains($0) }) 214| 0| 215| 0| // Build a backmap of targets and products to packages. 216| 0| var packagesByTarget = [ResolvedTarget: ResolvedPackage]() 217| 0| for package in graph.packages { 218| 0| for target in package.targets { 219| 0| packagesByTarget[target] = package 220| 0| } 221| 0| } 222| 0| var packagesByProduct = [ResolvedProduct: ResolvedPackage]() 223| 0| for package in graph.packages { 224| 0| for product in package.products { 225| 0| packagesByProduct[product] = package 226| 0| } 227| 0| } 228| 0| 229| 0| // To avoid creating multiple groups for the same path, we keep a mapping 230| 0| // of the paths we've seen and the corresponding groups we've created. 231| 0| var srcPathsToGroups: [AbsolutePath: Xcode.Group] = [:] 232| 0| 233| 0| // Private helper function to make a group (or return an existing one) for 234| 0| // a particular path, including any intermediate groups that may be needed. 235| 0| // A name can be specified, if different from the last path component (any 236| 0| // custom name does not apply to any intermediate groups). 237| 0| func makeGroup(for path: AbsolutePath, named name: String? = nil) -> Xcode.Group { 238| 0| // Check if we already have a group. 239| 0| if let group = srcPathsToGroups[path] { 240| 0| // We do, so we just return it without creating anything. 241| 0| return group 242| 0| } 243| 0| 244| 0| // No existing group, so start by making sure we have the parent. Note 245| 0| // that we don't pass along any custom name for any parent groups. 246| 0| let parentGroup = makeGroup(for: path.parentDirectory) 247| 0| 248| 0| // Now we have a parent, so we can create a group, optionally using the 249| 0| // custom name we were given. 250| 0| let group = parentGroup.addGroup(path: path.basename, pathBase: .groupDir, name: name ?? path.basename) 251| 0| 252| 0| // Add the new group to the mapping, so future lookups will find it. 253| 0| srcPathsToGroups[path] = group 254| 0| return group 255| 0| } 256| 0| 257| 0| // Add a mapping from the project dir to the main group, as a backstop for 258| 0| // any paths that get that far (which does not happen in standard package 259| 0| // layout). 260| 0| srcPathsToGroups[sourceRootDir] = project.mainGroup 261| 0| 262| 0| // Private helper function that creates a source group for one or more 263| 0| // targets (which could be regular targets, tests, etc). If there is a 264| 0| // single target whose source directory's basename is not equal to the 265| 0| // target name (i.e. the "flat" form of a single-target package), then 266| 0| // the top-level group will itself represent that target; otherwise, it 267| 0| // will have one subgroup for each target. 268| 0| // 269| 0| // The provided name is always used for the top-level group, whether or 270| 0| // not it represents a single target or is the parent of a collection of 271| 0| // targets. 272| 0| // 273| 0| // Regardless of the layout case, this function adds a mapping from the 274| 0| // source directory of each target to the corresponding group, so that 275| 0| // source files added later will be able to find the right group. 276| 0| @discardableResult 277| 0| func createSourceGroup(named groupName: String, for targets: [ResolvedTarget], in parentGroup: Xcode.Group) -> Xcode.Group? { 278| 0| let targets = targets.sorted { $0.name < $1.name } 279| 0| // Look for the special case of a single target in a flat layout. 280| 0| let needsSourcesGroup: Bool 281| 0| if let target = targets.spm_only { 282| 0| // FIXME: This is somewhat flaky; packages should have a notion of 283| 0| // what kind of layout they have. But at least this is just a 284| 0| // heuristic and won't affect the functioning of the Xcode project. 285| 0| needsSourcesGroup = (target.sources.root.basename == target.name) 286| 0| } else { 287| 0| needsSourcesGroup = true 288| 0| } 289| 0| 290| 0| // If we need a sources group, create one. 291| 0| let sourcesGroup = needsSourcesGroup ? 292| 0| parentGroup.addGroup(path: "", pathBase: .projectDir, name: groupName) : nil 293| 0| 294| 0| // Create a group for each target. 295| 0| for target in targets { 296| 0| // The sources could be anywhere, so we use a project-relative path. 297| 0| let path = target.sources.root.relative(to: sourceRootDir).pathString 298| 0| let name = (sourcesGroup == nil ? groupName : target.name) 299| 0| let group = (sourcesGroup ?? parentGroup) 300| 0| .addGroup(path: (path == "." ? "" : path), pathBase: .projectDir, name: name) 301| 0| 302| 0| // Associate the group with the target's root path. 303| 0| srcPathsToGroups[target.sources.root] = group 304| 0| } 305| 0| 306| 0| return sourcesGroup ?? srcPathsToGroups[targets[0].sources.root] 307| 0| } 308| 0| 309| 0| let (rootModules, testModules) = { () -> ([ResolvedTarget], [ResolvedTarget]) in 310| 0| var targets = graph.rootPackages[0].targets 311| 0| let secondPartitionIndex = targets.partition(by: { $0.type == .test }) 312| 0| return (Array(targets[.. SourceKit cannot handle relative include paths (working directory) 504| 0| switch depModule.underlyingTarget { 505| 0| case let systemTarget as SystemLibraryTarget: 506| 0| hdrInclPaths.append("$(SRCROOT)/\(systemTarget.path.relative(to: sourceRootDir).pathString)") 507| 0| if let pkgArgs = pkgConfigArgs(for: systemTarget, diagnostics: diagnostics) { 508| 0| targetSettings.common.OTHER_LDFLAGS += pkgArgs.libs 509| 0| targetSettings.common.OTHER_SWIFT_FLAGS += pkgArgs.cFlags 510| 0| targetSettings.common.OTHER_CFLAGS += pkgArgs.cFlags 511| 0| } 512| 0| case let clangTarget as ClangTarget: 513| 0| hdrInclPaths.append("$(SRCROOT)/\(clangTarget.includeDir.relative(to: sourceRootDir).pathString)") 514| 0| default: 515| 0| continue 516| 0| } 517| 0| } 518| 0| targetSettings.common.HEADER_SEARCH_PATHS = hdrInclPaths 519| 0| 520| 0| // Add framework search path to build settings. 521| 0| targetSettings.common.FRAMEWORK_SEARCH_PATHS = ["$(inherited)", "$(PLATFORM_DIR)/Developer/Library/Frameworks"] 522| 0| 523| 0| // Add a file reference for the target's product. 524| 0| let productRef = productsGroup.addFileReference(path: target.productPath.pathString, pathBase: .buildDir, objectID: "\(package.name)::\(target.name)::Product") 525| 0| 526| 0| // Set that file reference as the target's product reference. 527| 0| xcodeTarget.productReference = productRef 528| 0| 529| 0| // Add a compile build phase (which Xcode calls "Sources"). 530| 0| let compilePhase = xcodeTarget.addSourcesBuildPhase() 531| 0| 532| 0| // We don't add dependencies yet — we do so in a separate pass, since 533| 0| // some dependencies might be on targets that we have not yet created. 534| 0| 535| 0| // We also don't add the link phase yet, since we'll do so at the same 536| 0| // time as we set up dependencies. 537| 0| 538| 0| // Record the target that we created for this target, for later passes. 539| 0| modulesToTargets[target] = xcodeTarget 540| 0| 541| 0| // Go through the target source files. As we do, we create groups for 542| 0| // any path components other than the last one. We also add build files 543| 0| // to the compile phase of the target we created. 544| 0| for sourceFile in target.sources.paths { 545| 0| // Find or make a group for the parent directory of the source file. 546| 0| // We know that there will always be one, because we created groups 547| 0| // for the source directories of all the targets. 548| 0| let group = makeGroup(for: sourceFile.parentDirectory) 549| 0| 550| 0| // Create a reference for the source file. We don't set its file 551| 0| // type; rather, we let Xcode determine it based on the suffix. 552| 0| let srcFileRef = group.addFileReference(path: sourceFile.basename) 553| 0| 554| 0| // Also add the source file to the compile phase. 555| 0| compilePhase.addBuildFile(fileRef: srcFileRef) 556| 0| } 557| 0| 558| 0| // Set C/C++ language standard. 559| 0| if case let clangTarget as ClangTarget = target.underlyingTarget { 560| 0| targetSettings.common.GCC_C_LANGUAGE_STANDARD = clangTarget.cLanguageStandard 561| 0| targetSettings.common.CLANG_CXX_LANGUAGE_STANDARD = clangTarget.cxxLanguageStandard 562| 0| } 563| 0| 564| 0| // Add the `include` group for a libary C language target. 565| 0| if case let clangTarget as ClangTarget = target.underlyingTarget, 566| 0| clangTarget.type == .library, 567| 0| fileSystem.isDirectory(clangTarget.includeDir) { 568| 0| let includeDir = clangTarget.includeDir 569| 0| let includeGroup = makeGroup(for: includeDir) 570| 0| // FIXME: Support C++ headers. 571| 0| for header in try walk(includeDir, fileSystem: fileSystem) where header.extension == "h" { 572| 0| let group = makeGroup(for: header.parentDirectory) 573| 0| group.addFileReference(path: header.basename) 574| 0| } 575| 0| 576| 0| // Disable defines target for clang target because our clang targets are not proper framework targets. 577| 0| // Also see: 578| 0| targetSettings.common.DEFINES_MODULE = "NO" 579| 0| 580| 0| // Generate a modulemap for clangTarget (if not provided by user) and 581| 0| // add to the build settings. 582| 0| var moduleMapPath: AbsolutePath? 583| 0| 584| 0| // If the modulemap is generated (as opposed to user provided). 585| 0| var isGenerated = false 586| 0| 587| 0| // If user provided the modulemap no need to generate. 588| 0| if fileSystem.isFile(clangTarget.moduleMapPath) { 589| 0| moduleMapPath = clangTarget.moduleMapPath 590| 0| } else if includeGroup.subitems.contains(where: { $0.path == clangTarget.c99name + ".h" }) { 591| 0| // If an umbrella header exists, enable Xcode's builtin module's feature rather than generating 592| 0| // a custom module map. This increases the compatibility of generated Xcode projects. 593| 0| let headerPhase = xcodeTarget.addHeadersBuildPhase() 594| 0| for case let header as Xcode.FileReference in includeGroup.subitems { 595| 0| let buildFile = headerPhase.addBuildFile(fileRef: header) 596| 0| buildFile.settings.ATTRIBUTES = ["Public"] 597| 0| } 598| 0| targetSettings.common.CLANG_ENABLE_MODULES = "YES" 599| 0| targetSettings.common.DEFINES_MODULE = "YES" 600| 0| } else { 601| 0| // Generate and drop the modulemap inside Xcodeproj folder. 602| 0| let path = xcodeprojPath.appending(components: "GeneratedModuleMap", clangTarget.c99name) 603| 0| var moduleMapGenerator = ModuleMapGenerator(for: clangTarget, fileSystem: fileSystem) 604| 0| try moduleMapGenerator.generateModuleMap(inDir: path) 605| 0| moduleMapPath = path.appending(component: moduleMapFilename) 606| 0| isGenerated = true 607| 0| } 608| 0| 609| 0| if let moduleMapPath = moduleMapPath { 610| 0| includeGroup.addFileReference(path: moduleMapPath.pathString, name: moduleMapPath.basename) 611| 0| // Save this modulemap path mapped to target so we can later wire it up for its dependees. 612| 0| modulesToModuleMap[target] = (moduleMapPath, isGenerated) 613| 0| } 614| 0| } 615| 0| } 616| 0| 617| 0| // Go through each target and add its build settings. 618| 0| for (target, xcodeTarget) in modulesToTargets { 619| 0| for (decl, assignments) in target.underlyingTarget.buildSettings.assignments { 620| 0| // Process each assignment of a build settings declaration. 621| 0| for assignment in assignments { 622| 0| // Skip this assignment if it doesn't contain macOS platform. 623| 0| if let platformsCondition = assignment.conditions.compactMap({ $0 as? BuildSettings.PlatformsCondition }).first { 624| 0| if !platformsCondition.platforms.contains(.macOS) { 625| 0| continue 626| 0| } 627| 0| } 628| 0| let config = assignment.conditions.compactMap({ $0 as? BuildSettings.ConfigurationCondition }).first?.config 629| 0| appendSetting(assignment.value, forDecl: decl, to: xcodeTarget.buildSettings, config: config) 630| 0| } 631| 0| } 632| 0| } 633| 0| 634| 0| // Go through all the target/target pairs again, and add target dependencies 635| 0| // for any target dependencies. As we go, we also add link phases and set 636| 0| // up the targets to link against the products of the dependencies. 637| 0| for (target, xcodeTarget) in modulesToTargets { 638| 0| // Add link build phase (which Xcode calls "Frameworks & Libraries"). 639| 0| // We need to do this whether or not there are dependencies on other 640| 0| // targets. 641| 0| let linkPhase = xcodeTarget.addFrameworksBuildPhase() 642| 0| 643| 0| // For each target on which this one depends, add a target dependency 644| 0| // and also link against the target's product. 645| 0| for dependency in target.recursiveDependencies() { 646| 0| // We should never find ourself in the list of dependencies. 647| 0| assert(dependency != target) 648| 0| 649| 0| // Find the target that corresponds to the other target. 650| 0| guard let otherTarget = modulesToTargets[dependency] else { 651| 0| // FIXME: We're depending on a target for which we didn't create 652| 0| // a target. This is unexpected, and we should report this as 653| 0| // an error. 654| 0| // FIXME: Or is it? What about system targets, can we depend 655| 0| // on those? If so, we would just link and not depend, right? 656| 0| continue 657| 0| } 658| 0| 659| 0| // Add a dependency on the other target. 660| 0| xcodeTarget.addDependency(on: otherTarget) 661| 0| 662| 0| // If it's a library, we also add want to link against its product. 663| 0| if dependency.type == .library { 664| 0| _ = linkPhase.addBuildFile(fileRef: otherTarget.productReference!) 665| 0| } 666| 0| // For swift targets, if a clang dependency has a modulemap, add it via -fmodule-map-file. 667| 0| if let moduleMap = modulesToModuleMap[dependency], target.underlyingTarget is SwiftTarget { 668| 0| assert(dependency.underlyingTarget is ClangTarget) 669| 0| xcodeTarget.buildSettings.common.OTHER_SWIFT_FLAGS += [ 670| 0| "-Xcc", 671| 0| "-fmodule-map-file=$(SRCROOT)/\(moduleMap.path.relative(to: sourceRootDir).pathString)", 672| 0| ] 673| 0| // Workaround for a interface generation bug. 674| 0| if moduleMap.isGenerated { 675| 0| xcodeTarget.buildSettings.common.HEADER_SEARCH_PATHS += [ 676| 0| "$(SRCROOT)/\(moduleMap.path.parentDirectory.relative(to: sourceRootDir).pathString)" 677| 0| ] 678| 0| } 679| 0| } 680| 0| } 681| 0| } 682| 0| 683| 0| // Create an aggregate target for every product for which there isn't already 684| 0| // a target with the same name. 685| 0| let targetNames: Set = Set(modulesToTargets.values.map({ $0.name })) 686| 0| for product in graph.reachableProducts { 687| 0| // Go on to next product if we already have a target with the same name. 688| 0| if targetNames.contains(product.name) { continue } 689| 0| // Otherwise, create an aggreate target. 690| 0| let package = packagesByProduct[product]! 691| 0| let aggregateTarget = project.addTarget( 692| 0| objectID: "\(package.name)::\(product.name)::ProductTarget", 693| 0| productType: nil, name: product.name) 694| 0| // Add dependencies on the targets created for each of the dependencies. 695| 0| for target in product.targets { 696| 0| // Find the target that corresponds to the target. There might not 697| 0| // be one, since we don't create targets for every kind of target 698| 0| // (such as system targets). 699| 0| // TODO: We will need to decide how this should best be handled; it 700| 0| // would make sense to at least emit a warning. 701| 0| guard let depTarget = modulesToTargets[target] else { 702| 0| continue 703| 0| } 704| 0| // Add a dependency on the dependency target. 705| 0| aggregateTarget.addDependency(on: depTarget) 706| 0| } 707| 0| } 708| 0| 709| 0| return project 710| 0|} 711| | 712| |extension ResolvedTarget { 713| | 714| 0| var buildableName: String { 715| 0| return productName 716| 0| } 717| | 718| 0| var blueprintName: String { 719| 0| return name 720| 0| } 721| |} 722| | 723| |private extension SupportedLanguageExtension { 724| 0| var xcodeFileType: String { 725| 0| switch self { 726| 0| case .c: 727| 0| return "sourcecode.c.c" 728| 0| case .m: 729| 0| return "sourcecode.c.objc" 730| 0| case .cxx, .cc, .cpp: 731| 0| return "sourcecode.cpp.cpp" 732| 0| case .mm: 733| 0| return "sourcecode.cpp.objcpp" 734| 0| case .swift: 735| 0| return "sourcecode.swift" 736| 0| case .s, .S: 737| 0| return "sourcecode.assembly" 738| 0| } 739| 0| } 740| |} 741| | 742| |private extension ResolvedTarget { 743| 0| func fileType(forSource source: RelativePath) -> String { 744| 0| switch underlyingTarget { 745| 0| case is SwiftTarget: 746| 0| // SwiftModules only has one type of source so just always return this. 747| 0| return SupportedLanguageExtension.swift.xcodeFileType 748| 0| 749| 0| case is ClangTarget: 750| 0| guard let suffix = source.suffix else { 751| 0| fatalError("Source \(source) doesn't have an extension in C family target \(name)") 752| 0| } 753| 0| // Suffix includes `.` so drop it. 754| 0| assert(suffix.hasPrefix(".")) 755| 0| let fileExtension = String(suffix.dropFirst()) 756| 0| guard let ext = SupportedLanguageExtension(rawValue: fileExtension) else { 757| 0| fatalError("Unknown source extension \(source) in C family target \(name)") 758| 0| } 759| 0| return ext.xcodeFileType 760| 0| 761| 0| default: 762| 0| fatalError("unexpected target type") 763| 0| } 764| 0| } 765| |} 766| | 767| |private extension SwiftLanguageVersion { 768| | /// Returns the build setting value for the given Swift language version. 769| 0| var xcodeBuildSettingValue: String { 770| 0| // Swift version setting are represented differently in Xcode: 771| 0| // 3 -> 3.0, 4 -> 4.0, 4.2 -> 4.2 772| 0| var swiftVersion = "\(rawValue)" 773| 0| if !rawValue.contains(".") { 774| 0| swiftVersion += ".0" 775| 0| } 776| 0| return swiftVersion 777| 0| } 778| |} 779| | 780| | 781| |func appendSetting( 782| | _ value: [String], 783| | forDecl decl: BuildSettings.Declaration, 784| | to table: Xcode.BuildSettingsTable, 785| | config: BuildConfiguration? = nil 786| 0|) { 787| 0| switch decl { 788| 0| // FIXME: This switch case is kind of sad but we need to convert Xcode's 789| 0| // build model to be of reference type in order to avoid it. 790| 0| case .SWIFT_ACTIVE_COMPILATION_CONDITIONS: 791| 0| switch config { 792| 0| case .debug?: 793| 0| table.debug.SWIFT_ACTIVE_COMPILATION_CONDITIONS += value 794| 0| case .release?: 795| 0| table.release.SWIFT_ACTIVE_COMPILATION_CONDITIONS += value 796| 0| case nil: 797| 0| table.common.SWIFT_ACTIVE_COMPILATION_CONDITIONS += value 798| 0| } 799| 0| 800| 0| case .OTHER_SWIFT_FLAGS: 801| 0| switch config { 802| 0| case .debug?: 803| 0| table.debug.OTHER_SWIFT_FLAGS += value 804| 0| case .release?: 805| 0| table.release.OTHER_SWIFT_FLAGS += value 806| 0| case nil: 807| 0| table.common.OTHER_SWIFT_FLAGS += value 808| 0| } 809| 0| 810| 0| case .GCC_PREPROCESSOR_DEFINITIONS: 811| 0| switch config { 812| 0| case .debug?: 813| 0| table.debug.GCC_PREPROCESSOR_DEFINITIONS += value 814| 0| case .release?: 815| 0| table.release.GCC_PREPROCESSOR_DEFINITIONS += value 816| 0| case nil: 817| 0| table.common.GCC_PREPROCESSOR_DEFINITIONS += value 818| 0| } 819| 0| case .HEADER_SEARCH_PATHS: 820| 0| switch config { 821| 0| case .debug?: 822| 0| table.debug.HEADER_SEARCH_PATHS += value 823| 0| case .release?: 824| 0| table.release.HEADER_SEARCH_PATHS += value 825| 0| case nil: 826| 0| table.common.HEADER_SEARCH_PATHS += value 827| 0| } 828| 0| case .OTHER_CFLAGS: 829| 0| switch config { 830| 0| case .debug?: 831| 0| table.debug.OTHER_CFLAGS += value 832| 0| case .release?: 833| 0| table.release.OTHER_CFLAGS += value 834| 0| case nil: 835| 0| table.common.OTHER_CFLAGS += value 836| 0| } 837| 0| 838| 0| 839| 0| case .OTHER_LDFLAGS: 840| 0| switch config { 841| 0| case .debug?: 842| 0| table.debug.OTHER_LDFLAGS += value 843| 0| case .release?: 844| 0| table.release.OTHER_LDFLAGS += value 845| 0| case nil: 846| 0| table.common.OTHER_LDFLAGS += value 847| 0| } 848| 0| case .LINK_LIBRARIES: 849| 0| let value = value.map({ "-l" + $0 }) 850| 0| 851| 0| switch config { 852| 0| case .debug?: 853| 0| table.debug.OTHER_LDFLAGS += value 854| 0| case .release?: 855| 0| table.release.OTHER_LDFLAGS += value 856| 0| case nil: 857| 0| table.common.OTHER_LDFLAGS += value 858| 0| } 859| 0| case .LINK_FRAMEWORKS: 860| 0| let value = value.flatMap({ ["-framework", $0] }) 861| 0| 862| 0| switch config { 863| 0| case .debug?: 864| 0| table.debug.OTHER_LDFLAGS += value 865| 0| case .release?: 866| 0| table.release.OTHER_LDFLAGS += value 867| 0| case nil: 868| 0| table.common.OTHER_LDFLAGS += value 869| 0| } 870| 0| 871| 0| default: 872| 0| fatalError("Unhandled decl \(decl)") 873| 0| } 874| 0|} <<<<<< EOF # path=fixes ./.build/checkouts/swift-llbuild/products/llbuild/main.cpp:12,14,16,19,22,25,36,37,41,47,52,56,57,61,66,67,73,74,85,86 ./.build/checkouts/swift-llbuild/products/swift-build-tool/main.cpp:12,14,19,23,26,33,37,40,41,44,45,49,51,58,59,63,66,71,81,82,86,87,91,97,98,100,101,105,109,111 ./.build/checkouts/swift-llbuild/products/llbuildSwift/BuildSystemBindings.swift:8,10,16,18,24,27,28,33,36,39,40,44,45,46,50,51,54,57,58,71,74,76,77,78,84,90,91,96,100,101,104,105,108,109,110,114,117,120,123,124,136,137,138,139,165,166,167,168,180,181,182,183,193,194,195,196,200,203,204,212,214,215,219,220,225,227,228,233,235,236,240,241,244,245,248,249,250,256,259,260,263,264,267,268,269,274,279,280,281,288,296,302,303,304,310,311,312,313,318,321,324,328,329,332,333,334,341,343,344,351,354,355,358,363,368,376,379,385,391,397,401,404,407,410,413,417,421,433,439,445,455,459,477,478,483,487,491,494,495,498,499,500,505,508,511,514,517,520,522,526,527,530,534,537,540,543,553,562,578,583,592,594,599,601,603,605,606,609,610,614,615,625,626,636,637,641,642,644,648,649,653,654,658,659,662,666,667,669,671,672,678,679,685,686,699,700,704,705,714,715,722,725,726,729,730,738,739,741,742,745,746,749,750,753,754,757,758,761,762,765,766,769,770,773,774,777,778,781,782,785,786,789,790,793,794,797,798,801,802,805,806,807,814,815,816,818,822,823,827,828,832,833,837,838,839 ./.build/checkouts/swift-llbuild/products/llbuildSwift/CoreBindings.swift:8,10,12,18,21,22,28,29,32,33,38,39,42,43,47,49,52,53,55,58,59,61,64,68,69,73,74,80,81,82,83,86,87,91,94,95,98,102,103,107,108,114,115,116,127,128,129,146,155,158,159,164,165,192,202,212,213,224,230,231,234,235,236,244,245,250,263,271,293,304,305,314,315,316,322,325,326,330,331,334,335,338,339,342,343,346,347,348,373,376,379,382,385,388,391,393,396,397,401,402,403,408,409,414,415,416,425,434,435,436,440,441,442,444,448,449,450,454,455,456,460,461,462,466,467,468,470,474,475,479,480,484,485,488,491,500,504,508,509,510,514,521,529,533,537,541,542,545,550,551,552 ./.build/checkouts/swift-llbuild/products/libllbuild/C-API.cpp:12,15,17,19,21,25,27,28,31 ./.build/checkouts/swift-llbuild/products/libllbuild/include/llbuild/buildsystem.h:16,19,23,26,43,46,55,60,63,66,69,73,75,78,84,89,91,94,97,100,103,106,114,124,133,136,143,147,150,153,156,159,162,165,168,171,175,180,184,189,193,203,209,212,215,226,231,234,236,239,244,252,257,276,283,287,292,294,297,305,307,310,322,336,345,351,367,373,380,387,394,401,408,415,429,438,447,459,468,489,492,500,504,521,535,549,555,557,560,565,567,577,580,588,590,593,597,601,605,611,616,627,640,654,661,668,677,687,689,696,699,702,706,710,714,716,720,726,730,739,751 ./.build/checkouts/swift-llbuild/products/libllbuild/include/llbuild/core.h:16,19,23,26,29,32,35,48,54,57,61,67,70,76,85,90,95,98,108,115,121,125,143,152,161,179,189,214,227,229,232,237,240,247,256,269,273,277,281,283 ./.build/checkouts/swift-llbuild/products/libllbuild/include/llbuild/llbuild.h:16,19,33,37,43,49,75,78,81,84,87 ./.build/checkouts/swift-llbuild/products/libllbuild/Core-C-API.cpp:12,15,19,22,25,27,29,32,34,38,39,40,46,51,64,65,73,74,83,84,88,89,92,93,97,98,99,101,108,111,119,120,124,125,126,133,134,144,145,152,154,156,164,165,169,170,176,186,187,191,192,196,198,200,201,207,208,217,218,225,226,234,235,244,245,248,249,252,253,256 ./.build/checkouts/swift-llbuild/products/libllbuild/BuildSystem-C-API.cpp:12,15,24,29,33,37,39,41,45,50,55,56,58,59,64,65,70,71,77,82,84,85,89,90,92,93,97,98,102,111,112,116,117,125,126,135,137,140,154,156,157,164,168,169,174,175,177,178,182,190,191,192,202,205,206,214,215,216,222,223,224,231,232,233,239,240,241,248,249,250,258,259,260,268,269,270,278,279,280,286,288,296,298,299,300,304,312,313,314,318,319,320,324,330,337,338,339,347,348,349,361,362,363,373,374,375,386,392,393,394,398,399,400,403,445,446,448,449,453,457,462,463,464,468,469,470,474,475,479,480,488,491,492,498,502,508,510,512,513,524,525,527,530,532,534,537,550,551,560,561,566,576,583,589,592,596,597,600,601,604,605,609,613,614,618,619,622,624,627,631,637,638,644,645,651,652,657,658,662,664,666,671,674,683,684,695,699,703,704,711,713,717,718,725,727,728,738,743,744,752,753,754,756,757,762,763,767,768,772,773,781,786,788,790,791,792,804,805,806,818,820,821,824,825,833,834,838,839,843,844,848,849,853,854,861,864,865,869,873,874,879,880,884,888,889,893,897,898,912,913,914,932,933,934 ./.build/checkouts/swift-llbuild/Package@swift-4.2.swift:2,5,7,25,32,40,47,49,75,77,94,96,109,115 ./.build/checkouts/swift-llbuild/include/libstdc++14-workaround.h:12,14,22 ./.build/checkouts/swift-llbuild/include/llbuild/Core/BuildDB.h:12,15,18,20,24,27,30,35,46,52,53,57,62,63,69,74,89,102,111,122,132,133,134,135 ./.build/checkouts/swift-llbuild/include/llbuild/Core/MakefileDepsParser.h:12,15,17,19,21,24,32,41,52,66,70,74,78,81,82,83,84 ./.build/checkouts/swift-llbuild/include/llbuild/Core/BuildEngine.h:12,15,17,20,27,30,35,38,42,48,51,63,70,101,104,111,122,133,164,167,171,175,179,182,185,195,199,204,213,231,239,244,246,270,274,279,282,288,291,294,296,299,306,321,331,336,339,341,344,352,355,371,379,401,412,415,416,417,418 ./.build/checkouts/swift-llbuild/include/llbuild/Core/DependencyInfoParser.h:12,15,17,19,21,24,31,40,45,48,51,58,61,65,68,69,70,71 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildSystemCommandInterface.h:12,15,18,21,22,24,27,28,29,31,35,44,47,49,51,53,55,58,61,63,66,69,71,74,77,80,83,84,85,86 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildSystem.h:12,15,19,22,27,32,33,35,42,44,53,61,64,68,74,78,91,94,97,102,114,124,127,130,137,152,167,177,182,187,192,197,202,208,214,218,223,226,229,232,237,240,245,250,258,265,268,271,274,275,276,277 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildKey.h:12,15,22,24,27,32,37,40,43,46,49,53,56,59,62,67,71,78,79,83,90,102,103,107,111,112,116,117,121,122,127,128,133,134,138,139,143,144,148,149,153,154,158,159,163,165,179,180,181,186,189,192,195,199,203,204,210,211,218,219,223,224,230,231,237,238,245,246,250,251,255,256,260,261,263,266,271,272,274,276,279,281,284,285,286,287 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildValue.h:12,15,23,28,30,33,34,37,42,46,49,52,55,58,61,64,67,71,74,77,80,84,87,90,93,96,99,101,104,107,110,115,119,126,130,131,134,135,138,139,144,153,161,162,163,164,168,170,172,173,177,178,182,183,192,193,194,206,209,210,216,226,229,230,232,236,237,238,241,244,247,251,254,258,261,264,267,270,274,277,280,283,286,289,292,295,296,298,301,306,310,313,315,322,328,329,333,334,338,339,343,344,349,350,353,354,358,359,365,366,375,376,377,381,382,384,387,391,393,395,398,400,403,404,405,409,414,419,421,427,428,436,439,440,443,445,446,456,457,460,462,463,464,465 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildFile.h:12,15,18,20,26,29,31,32,33,35,38,49,55,60,63,66,69,72,76,79,82,87,99,111,117,121,125,129,139,145,153,156,162,163,164,165 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildSystemFrontend.h:12,15,21,25,29,31,33,34,35,38,40,41,42,44,48,65,67,69,74,77,80,82,84,87,97,102,107,110,114,121,124,127,140,144,147,150,153,158,161,164,169,171,179,183,190,205,211,216,221,226,231,236,241,253,256,268,277,284,296,304,323,326,328,330,333,336,339,340,346,349,352,355,358,361,364,367,370,372,380,383,386,390,395,399,400,401,402 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/ExternalCommand.h:12,15,19,23,26,30,33,34,36,39,47,50,59,62,67,70,73,77,80,83,86,90,93,95,97,100,107,110,113,116,119,127,130,132,135,138,142,148,149,150,151 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildNode.h:12,15,17,21,23,26,29,30,31,33,40,45,48,53,60,66,74,77,81,85,87,89,92,93,101,105,106,109,112,114,118,119,120,121,122 ./.build/checkouts/swift-llbuild/include/llbuild/BuildSystem/BuildDescription.h:12,15,19,23,29,31,33,35,36,37,39,42,49,56,63,65,69,71,82,87,97,103,106,109,111,115,122,125,130,134,136,138,140,152,159,161,165,167,178,182,184,187,190,192,195,199,203,207,218,220,232,237,239,247,249,251,254,257,258,260,268,271,272,278,281,284,287,290,292,294,296,299,303,306,309,312,315,318,321,324,327,330,333,337,342,343,348,349,354,355,360,361,364,365,366,367 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/FileSystem.h:12,15,19,21,23,25,27,28,29,32,40,44,50,56,62,69,76,84,87,88,93,97,98,99,103,105,106,110,111,115,116,119,122,123,126,133,135,136,139,142,144,146,147,148,149 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/CrossPlatformCompatibility.h:16,19,33,44 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Version.h:12,15,17,19,21,23,28,29,30 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/FileInfo.h:24,27,29,32,35,40,43,46,50,54,57,60,62,78,85,86,89,95,98,99,110,116,120,122,131,138,140,141,142,143 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Compiler.h:16,17,20,24,32,37,41,59 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/StringList.h:12,15,17,19,22,28,31,40,44,45,52,53,59,68,70,71,76,77,85,87,88,96,98,99,101,105,107,112,113,116,118,119,120,121,123 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Stat.h:12,15,17,19,23,36,40,44,48,52,56,60,64,70,73,74,75,76 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/POSIXEnvironment.h:12,15,17,21,25,30,32,33,36,41,46,49,53,56,69,70,71,77,82,85,87,88,89,90 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/LLVM.h:12,15,19,35,38,39,55,58,59 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/ExecutionQueue.h:12,15,19,21,24,26,28,34,37,40,44,45,54,59,63,67,71,73,76,84,86,90,93,96,98,101,104,105,115,148,150,154,167,169,185,189,201,213,215,219,223,229,230,231 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/BinaryCoding.h:12,15,18,21,24,27,33,47,52,56,60,61,65,66,71,72,77,78,83,84,93,94,98,99,104,105,109,110,114,115,119,121,130,133,136,142,147,152,153,157,164,168,169,172,175,178,181,184,192,193,202,203,208,209,213,215,220,222,223,224,225 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/SerialQueue.h:12,15,17,20,24,28,31,35,36,37,38 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/PlatformUtility.h:17,20,28,32,49,52,58,66,69,78,80,88,90,91,92,93 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Hashing.h:12,15,18,21,24,26,32,38,40,43,48,49,54,55,60,61,66,68,69,72,77,80,82,83,84,85 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Subprocess.h:12,15,20,22,28,31,33,39,42,45,49,52,54,55,57,63,68,69,71,76,80,84,86,89,93,94,96,99,101,102,105,106,108,116,119,122,125,128,131,134,137,143,146,147,150,152,153,156,157,160,174,178,191,201,209,222,223,230,234,239,280,282,283,284,285 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/ShellUtility.h:12,15,18,20,23,32,39,40,41,42 ./.build/checkouts/swift-llbuild/include/llbuild/Basic/Tracing.h:12,15,18,22,32,33,43,44,48,49,53,54,58,59,61,67,69,72,77,78,82,84,85,90,91,98,99,100,107,108,113,114,120,121,125,126,135,143,149,150,155,159,171,177,178,183,187,191,192,193,194 ./.build/checkouts/swift-llbuild/include/llbuild/Ninja/ManifestLoader.h:12,15,17,20,23,28,33,36,39,59,63,67,70,74,75,76,77 ./.build/checkouts/swift-llbuild/include/llbuild/Ninja/Manifest.h:12,15,18,24,30,33,36,41,44,47,51,52,56,57,61,62,69,72,74,76,82,85,88,93,96,99,101,104,107,109,118,123,128,132,135,141,144,148,154,156,160,164,178,181,182,184,186,188,191,194,195,198,201,202,205,208,209,214,215,218,221,222,225,229,230,234,237,238,242,245,246,250,254,255,260,263,264,268,271,272,277,280,281,285,288,289,293,296,302,309,312,314,317,320,321,325,331,334,341,344,351,358,361,364,367,370,373,378,381,384,385,388,391,394,395,398,401,402,405,408,409,412,415,416,419,420,423,425,426,427,428 ./.build/checkouts/swift-llbuild/include/llbuild/Ninja/Parser.h:12,15,17,20,22,25,28,35,37,39,42,47,54,59,67,70,91,101,109,117,127,135,143,153,161,164,168,172,174,178,179,180,181 ./.build/checkouts/swift-llbuild/include/llbuild/Ninja/Lexer.h:12,15,17,19,21,24,44,48,54,57,61,62,66,81,85,88,92,96,101,104,108,111,115,119,122,126,130,134,139,142,145,148,151,158,159,167,168,171,172,173,174 ./.build/checkouts/swift-llbuild/include/llbuild/Commands/Commands.h:17,20,22,24,27,30,33,36,40,41,42,43 ./.build/checkouts/swift-llbuild/include/llvm/ADT/SmallPtrSet.h:14,17,26,28,30,59,63,73,75,80,86,91,92,99,100,105,111,120,121,124,125,128,131,134,140,144,155,156,159,162,163,174,176,181,188,191,193,197,198,203,204,207,209,214,229,234,235,244,255,259,267,268,273,274,278,279,284,285,288,291,293,301,311,315,316,322,323,329,330,334,336,337,338,344,345,346 ./.build/checkouts/swift-llbuild/include/llvm/ADT/ilist_node.h:14,17,19,22,35,38,52,56,60,64,66,67,71,75,77,78,82,86,88,89,93,97,99,100,103,104,105 ./.build/checkouts/swift-llbuild/include/llvm/ADT/edit_distance.h:15,18,22,24,57,65,67,70,74,80,84,86,87,90,94,95,98,99,100,101 ./.build/checkouts/swift-llbuild/include/llvm/ADT/StringSwitch.h:15,19,21,45,49,53,59,60,62,63,69,70,72,73,79,80,82,83,88,89,94,95,101,102,109,110,114,116,117,121,123,124,125 ./.build/checkouts/swift-llbuild/include/llvm/ADT/iterator_range.h:18,21,23,25,33,38,42,49,50,53,54,55 ./.build/checkouts/swift-llbuild/include/llvm/ADT/None.h:15,18,24,25 ./.build/checkouts/swift-llbuild/include/llvm/ADT/STLExtras.h:16,19,28,30,34,39,42,44,49,51,56,58,66,71,76,77,88,90,99,100,101,102,106,120,124,126,129,132,135,136,140,144,149,154,157,161,164,168,170,174,176,179,181,187,188,189,196,197,201,207,209,215,217,219,223,226,230,235,239,243,248,249,260,261,268,269,270,292,293,306,307,311,319,320,328,329,333,335,347,348,362,363,368,372,374,379,381,386,388,393,395,408,410,411,412 ./.build/checkouts/swift-llbuild/include/llvm/ADT/StringMap.h:13,16,21,29,35,38,64,65,68,75,80,84,93,94,97,100,106,108,117,123,126,127,130,132,137,139,146,152,155,158,164,165,169,170,176,177,180,181,187,188,198,199,204,206,207,217,221,224,228,231,236,237,239,242,247,250,253,256,259,262,263,268,269,274,275,283,284,287,288,292,293,302,308,311,312,323,330,333,334,338,345,347,348,351,352,357,358,363,364,370,371,381,382,383,385,387,388,395,397,402,403,406,409,410,413,416,417,422,425,426,431,433,441,444,447,449,450,451 ./.build/checkouts/swift-llbuild/include/llvm/ADT/Twine.h:9,12,18,24,87,90,93,96,99,102,105,109,113,117,120,124,127,132,134,148,160,166,167,174,175,180,181,185,189,190,194,195,199,200,204,205,209,210,217,221,225,233,235,236,239,242,245,249,253,257,258,260,273,275,276,282,283,289,290,295,296,301,302,307,308,313,314,319,320,325,326,331,332,337,338,343,344,349,356,357,364,365,370,371,375,382,383,387,392,393,398,407,408,409,413,415,419,422,426,437,438,439,444,452,456,459,462,465,468,471,476,482,492,496,497,499,500,503,504,507,510,511,514,517,518,522,523,525,526 ./.build/checkouts/swift-llbuild/include/llvm/ADT/DenseMapInfo.h:13,16,19,21,29,37,42,46,49,57,59,67,69,76,79,81,88,92,94,102,104,109,113,116,118,125,129,131,138,142,146,159,163,165,166,167 ./.build/checkouts/swift-llbuild/include/llvm/ADT/DenseMap.h:13,16,31,33,44,45,50,59,66,69,72,75,76,79,81,86,87,90,96,97,104,106,107,110,111,116,117,123,129,130,142,149,150,158,159,168,172,173,182,188,189,195,196,197,202,208,215,216,221,223,224,227,228,233,235,236,239,240,246,247,252,255,259,266,267,271,272,276,282,283,286,301,304,306,307,313,314,320,323,335,336,337,341,342,345,349,352,355,356,360,363,366,369,372,375,378,381,384,387,390,393,396,397,400,401,404,405,406,410,414,415,419,423,424,427,431,432,453,455,459,464,466,467,477,481,482,490,499,500,508,509,515,520,521,522,530,531,539,541,551,556,560,561,565,566,570,571,576,577,581,582,588,589,594,595,602,603,612,613,614,621,622,623,627,633,634,636,639,640,644,652,653,656,657,661,664,665,668,671,672,675,676,679,680,686,687,690,692,704,708,713,717,721,722,726,727,731,732,737,738,742,743,749,768,777,778,780,785,786,789,807,808,809,814,815,820,821,828,829,837,839,840,846,848,849,853,857,862,876,878,879,886,887,894,895,897,900,901,905,912,917,918,921,922,926,930,931,934,937,938,945,949,954,958,959,962,966,969,970,974,977,978,985,987,993,1005,1009,1010,1019,1022,1025,1026,1029,1032,1033,1038,1041,1042,1047,1051,1053,1058,1059,1060,1061 ./.build/checkouts/swift-llbuild/include/llvm/ADT/Optional.h:15,18,26,28,35,40,44,45,48,53,54,61,63,70,72,73,80,81,84,85,97,99,100,107,108,113,114,115,118,119,124,131,135,136,140,144,145,149,153,156,162,171,180,189,198,207,216,217,218 ./.build/checkouts/swift-llbuild/include/llvm/ADT/IntrusiveRefCntPtr.h:20,23,28,30,33,47,51,56,58,70,74,76,81,82,86,87,92,103,106,109,115,117,138,141,143,146,147,150,151,154,155,159,160,165,166,170,171,173,175,177,179,181,186,187,191,192,195,196,200,204,208,210,211,215,217,218,222,224,225,229,231,232,236,238,239,243,245,246,250,251,255,256,260,261,265,266,270,275,277,282,284,285,286 ./.build/checkouts/swift-llbuild/include/llvm/ADT/ArrayRef.h:9,12,16,18,36,38,42,45,49,52,55,59,63,67,74,75,80,85,90,98,102,105,108,111,113,116,121,122,127,128,134,135,143,144,149,150,156,157,162,163,170,171,177,178,184,185,188,205,207,210,213,216,220,223,227,231,236,238,241,244,249,250,255,256,261,262,268,269,276,278,281,286,287,292,293,298,299,304,305,310,311,316,317,322,323,327,331,332,336,337,339,345,346 ./.build/checkouts/swift-llbuild/include/llvm/ADT/StringExtras.h:13,16,20,23,29,30,34,35,45,46,62,63,68,70,71,75,76,80,82,86,87,89,91,92,96,98,102,103,106,107,108,114,115,120,129,135,147,148,164,165,166,167,174,179,181,182,189,198,200,201,208,209,210,211 ./.build/checkouts/swift-llbuild/include/llvm/ADT/StringRef.h:9,12,19,25,29,31,45,49,52,58,59,63,66,72,73,79,80,84,88,90,92,95,98,99,103,107,110,113,118,119,124,125,131,132,138,139,143,144,151,156,157,160,164,185,190,191,195,199,200,204,207,208,212,217,218,221,226,227,230,234,244,245,251,263,265,266,272,277,278,284,288,294,299,300,306,310,316,320,328,329,333,350,351,364,365,369,372,375,379,392,393,399,400,406,407,422,423,439,440,456,457,475,491,492,497,498,503,504,509,510,513,516,519,520,523,524,527,528,531,532,535,536,539,540,543,544,546,549,553,554 ./.build/checkouts/swift-llbuild/include/llvm/ADT/Hashing.h:44,47,57,59,74,79,82,85,88,91,92,96,107,112,116,120,121,137,138,144,151,152,159,160,166,173,174,177,178,188,189,197,198,202,203,208,209,217,218,240,241,253,255,256,262,273,274,285,286,303,304,310,312,313,320,332,333,334,351,361,368,377,378,396,397,414,424,429,434,436,437,455,462,465,467,468,469,470,471,472,482,483,484,488,500,508,524,536,540,546,548,549,558,561,562,573,579,583,585,587,588,589,590,606,607,612,624,625,626,627,628,635,636,642,643,649,650,656,657,658,659 ./.build/checkouts/swift-llbuild/include/llvm/ADT/SmallString.h:13,16,19,21,29,32,36,39,43,47,48,54,55,60,61,66,67,71,76,77,80,81,82,86,87,91,92,96,101,102,106,107,112,113,117,118,123,124,128,132,133,137,138,142,149,150,157,158,165,166,173,174,179,180,187,188,193,194,201,202,207,208,216,217,221,225,226,231,232,236,248,249,262,263,265,268,274,275,278,283,284,288,292,294,295,296 ./.build/checkouts/swift-llbuild/include/llvm/ADT/PointerIntPair.h:13,16,21,23,26,54,58,61,69,72,73,77,78,81,82,90,91,95,99,100,107,108,116,118,119,122,123,129,130,133,136,137,143,144,152,158,167,172,176,179,189,193,197,202,203 ./.build/checkouts/swift-llbuild/include/llvm/ADT/SmallVector.h:13,16,30,32,37,41,45,50,51,55,56,59,61,69,76,79,82,83,88,89,93,94,102,105,110,120,126,129,132,137,141,145,146,150,154,155,159,163,165,172,177,178,179,188,189,199,200,207,208,214,215,220,227,228,234,235,239,241,252,255,258,262,266,267,268,275,278,284,285,291,292,299,300,307,308,320,321,326,333,334,337,339,340,346,351,356,357,362,366,367,368,372,373,384,385,386,396,397,398,402,403,408,409,411,419,423,424,430,434,435,438,439,446,447,451,452,456,463,464,469,477,478,483,484,487,492,493,498,504,507,508,513,514,517,522,527,533,536,537,541,545,546,549,552,555,564,567,570,571,574,580,583,587,588,593,597,598,601,603,606,609,618,621,624,625,628,634,639,640,644,645,648,649,655,656,658,660,664,667,668,672,673,686,688,689,693,700,705,711,725,726,727,733,745,748,752,753,766,767,771,775,776,781,791,792,802,806,809,811,812,826,827,831,834,837,838,849,864,865,869,870,874,875,880,881,884,885,889,890,894,895,899,900,904,905,909,910,914,915,919,921,925,926,927,928,935,936,942,943,944 ./.build/checkouts/swift-llbuild/include/llvm/ADT/ilist.h:37,40,46,48,51,61,65,68,79,82,87,97,99,100,104,106,114,121,131,136,140,147,152,159,175,179,185,192,193,197,198,201,203,207,210,211,217,221,226,231,232,236,243,248,254,258,262,266,267,268,271,273,276,279,283,286,288,289,315,323,328,329,332,337,350,356,357,362,366,370,374,375,381,382,387,388,393,397,401,405,406,410,411,417,423,426,427,433,434,440,448,457,458,462,463,468,469,479,480,481,492,500,509,513,520,524,526,530,531,532,534,538,542,543,548,549,551,558,562,563,567,568,573,578,581,583,584,589,593,596,599,602,603,608,612,613,614,618,621,622,632,641,642,643,649,654,657,658,659,665,666,667 ./.build/checkouts/swift-llbuild/include/llvm/Config/config.h:2,5,7,11,14,17,24,27,30,38,41,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,94,101,108,115,118,121,124,128,131,134,139,144,149,152,155,158,161,164,169,172,176,179,182,186,189,192,195,200,205,210,215,220,223,228,231,234,239,243,246 ./.build/checkouts/swift-llbuild/include/llvm/Config/llvm-config.h:2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59,62,67,70,73,76,79,82,85,88,90 ./.build/checkouts/swift-llbuild/include/llvm/Support/FileSystem.h:26,29,43,47,51,65,72,96,101,105,109,113,116,117,121,127,131,135,139,164,168,178,183,194,200,208,211,214,216,221,251,254,255,259,263,267,280,289,297,310,317,325,331,337,345,349,356,358,365,372,373,380,381,388,389,400,412,418,419,425,434,440,441,447,456,464,465,472,482,490,493,507,508,515,521,529,554,558,570,574,577,580,584,589,593,597,600,601,605,606,609,611,614,622,624,631,638,643,645,652,654,657,661,665,670,674,681,686,688,692,693,695,698,706,709,713,719,722,723,727,728,734,741,742,746,747,750,755,756,759,768,769,772,776,784,789,790,795,803,807,819,821,822,823,828,829,833,835,836,839,843,846,852,862,866,867,870,873,874,877,881,883,884,885,886,887 ./.build/checkouts/swift-llbuild/include/llvm/Support/TimeValue.h:13,16,19,32,36,43,44,51,52,58,59,65,66,72,73,80,89,96,102,113,114,119,132,133,142,143,148,157,159,160,165,173,175,176,182,183,188,193,198,203,208,213,219,220,226,227,236,237,246,247,252,253,262,263,270,271,276,288,289,299,300,306,307,313,314,321,322,329,330,338,339,346,347,356,364,368,370,375,376,381,382,383,384,385 ./.build/checkouts/swift-llbuild/include/llvm/Support/Casting.h:14,17,21,23,27,34,38,47,49,57,59,66,70,72,76,78,83,85,90,92,97,99,104,106,115,117,123,125,135,136,140,142,143,152,156,160,164,165,173,179,185,195,197,204,206,211,226,227,233,234,240,241,253,254,263,264,271,272,273,281,287,288,293,294,299,300,309,310,316,317,322,323,324,325 ./.build/checkouts/swift-llbuild/include/llvm/Support/Errc.h:29,32,34,77,80,81,82,85 ./.build/checkouts/swift-llbuild/include/llvm/Support/CBindingWrapping.h:13,16,18,23,26,27,30,34,35,38,44,45 ./.build/checkouts/swift-llbuild/include/llvm/Support/Debug.h:27,30,32,38,40,47,53,59,72,78,86,91,100,101,102 ./.build/checkouts/swift-llbuild/include/llvm/Support/AlignOf.h:14,17,20,29,41,46,52,59,69,72,78,83,89,98,100,104,106,110,118,126,134,142,150,151,154,160,165,167,169,177,180,190,191,209 ./.build/checkouts/swift-llbuild/include/llvm/Support/Compiler.h:14,17,19,23,27,31,35,51,59,64,68,74,84,94,100,112,118,124,130,144,152,161,168,176,189,199,211,219,225,233,248,257,271,283,292,303,311,324,333,362 ./.build/checkouts/swift-llbuild/include/llvm/Support/Locale.h:3,5,9,12,13,14,15,16 ./.build/checkouts/swift-llbuild/include/llvm/Support/MathExtras.h:13,16,22,26,37,45,54,57,59,61,67,75,77,83,91,95,96,110,111,117,126,128,130,136,144,146,152,160,164,165,179,180,191,193,194,205,210,211,224,235,236,240,244,245,249,250,255,256,261,266,270,274,275,281,282,287,292,296,300,301,307,308,313,314,319,320,326,327,333,334,340,341,346,347,352,353,358,359,364,365,370,371,376,377,392,393,408,409,423,425,437,439,440,450,451,457,458,463,464,470,471,476,477,485,487,488,498,499,509,510,522,523,535,536,546,547,555,557,559,560,565,566,577,578,584,585,598,599,605,606,611,612,617,618,623,624,629,630,632,633 ./.build/checkouts/swift-llbuild/include/llvm/Support/Host.h:13,16,18,26,28,31,37,39,40,41 ./.build/checkouts/swift-llbuild/include/llvm/Support/Path.h:15,18,23,27,30,55,59,67,71,82,85,94,99,104,109,114,118,130,144,159,173,177,185,192,196,208,221,229,241,253,267,285,301,307,312,323,329,337,345,353,361,369,377,385,393,399,405,406,407,408,409 ./.build/checkouts/swift-llbuild/include/llvm/Support/Endian.h:13,16,20,24,27,34,35,43,44,51,57,58,67,68,79,80,81,90,91,95,96,100,101,105,106,110,114,117,118,121,122,127,128,129,136,143,150,157,164,171,178,185,192,199,207,214,215,216,217 ./.build/checkouts/swift-llbuild/include/llvm/Support/SMLoc.h:14,17,19,21,27,29,32,34,39,41,50,55,56,59,60,61,63 ./.build/checkouts/swift-llbuild/include/llvm/Support/FileUtilities.h:14,17,20,22,34,35,45,49,50,55,56,57,65,66,70,71,76,77 ./.build/checkouts/swift-llbuild/include/llvm/Support/circular_raw_ostream.h:14,17,19,21,33,38,44,49,53,57,61,66,71,82,83,85,93,94,122,131,132,138,139,149,150,155,166,168,169,170 ./.build/checkouts/swift-llbuild/include/llvm/Support/ManagedStatic.h:13,16,20,22,27,28,37,46,51,54,63,70,72,78,80,86,88,94,96,98,101,108,109,110 ./.build/checkouts/swift-llbuild/include/llvm/Support/Valgrind.h:15,18,22,31,33,38,42,46,52,56,60,70,71,72 ./.build/checkouts/swift-llbuild/include/llvm/Support/Threading.h:14,17,22,37,38 ./.build/checkouts/swift-llbuild/include/llvm/Support/UniqueLock.h:14,17,19,31,37,45,46,48,54,55,61,62,65,66 ./.build/checkouts/swift-llbuild/include/llvm/Support/ErrorOr.h:15,18,24,31,32,38,39,44,47,51,86,89,94,103,104,107,108,111,112,115,116,123,124,131,132,135,136,143,144,153,154,158,159,163,164,168,169,173,174,177,180,181,184,185,188,189,201,202,203,207,208,212,213,218,221,222,233,234,235,240,243,244,247,248,251,252,256,257,261,262,266,267,270,271,272,279,286,287,288 ./.build/checkouts/swift-llbuild/include/llvm/Support/SwapByteOrder.h:14,17,22,25,38,39,54,55,68,69,73,76,79,89,92,95,96,105,106,115,116,120,121,122,123,124 ./.build/checkouts/swift-llbuild/include/llvm/Support/Signals.h:14,17,20,23,25,29,34,38,43,46,49,54,65,66,67 ./.build/checkouts/swift-llbuild/include/llvm/Support/Recycler.h:14,17,23,25,30,37,45,49,51,55,58,60,71,78,79,88,89,90,98,99,109,110,114,115,119,120,123,125,126,127 ./.build/checkouts/swift-llbuild/include/llvm/Support/PointerLikeTypeTraits.h:14,17,19,21,31,39,40,49,54,58,61,64,71,74,78,79,80 ./.build/checkouts/swift-llbuild/include/llvm/Support/DataTypes.h:21,23,25,28,33,39,43,49,51,54,58,67,77,83,91,99,101,112,116 ./.build/checkouts/swift-llbuild/include/llvm/Support/Unicode.h:14,17,19,23,28,46,62,63,64,65,66 ./.build/checkouts/swift-llbuild/include/llvm/Support/Allocator.h:20,23,33,35,56,57,70,71,74,78,79,86,88,92,96,97,100,103,104,107,110,112,117,118,143,150,162,163,167,168,172,179,185,186,192,197,203,204,208,211,214,224,225,231,237,238,248,249,252,254,257,259,267,268,272,273,279,282,285,288,293,296,303,304,309,314,315,328,331,332,333,346,347,348,351,355,363,369,373,374,384,392,394,395,400,401,403,404,408,409,410,426,427,431,432 ./.build/checkouts/swift-llbuild/include/llvm/Support/UnicodeCharRanges.h:11,20,23,25,31,34,37,38,45,58,60,65,66,80,87,89,90,92,93,96,98,99,100,101,102 ./.build/checkouts/swift-llbuild/include/llvm/Support/Process.h:24,27,35,38,40,41,47,54,65,71,75,82,90,96,105,110,115,120,125,129,136,143,148,153,159,164,171,174,178,181,186,187,188,189 ./.build/checkouts/swift-llbuild/include/llvm/Support/ConvertUTF.h:30,32,34,38,41,46,50,54,62,67,72,76,83,87,89,92,100,105,112,114,117,124,129,134,138,146,154,158,162,166,170,172,174,176,178,179,182,185,187,199,211,237,238,244,253,261,263,265,267 ./.build/checkouts/swift-llbuild/include/llvm/Support/Memory.h:13,16,20,23,40,52,81,92,110,124,133,134,139,144,149,153,158,159,160 ./.build/checkouts/swift-llbuild/include/llvm/Support/SourceMgr.h:15,18,25,32,42,51,54,56,60,63,66,70,73,75,82,85,86,92,93,96,100,101,105,106,109,110,114,115,119,120,130,131,140,145,150,151,156,166,172,179,188,197,198,202,204,210,211,216,217,220,227,229,230,242,251,258,269,270,273,274,277,278,282,283,284 ./.build/checkouts/swift-llbuild/include/llvm/Support/Errno.h:13,16,18,21,27,30,31,32,33 ./.build/checkouts/swift-llbuild/include/llvm/Support/YAMLParser.h:37,40,49,54,56,62,66,71,74,81,84,92,93,95,99,102,106,116,119,123,127,131,134,142,144,146,150,151,154,155,159,161,163,170,177,181,184,192,200,201,206,213,216,217,220,225,235,240,247,254,258,259,262,263,268,280,284,285,290,291,295,296,301,304,305,313,314,318,327,328,336,337,347,354,359,364,366,368,370,373,374,380,383,394,408,415,420,422,424,426,428,431,432,440,447,451,454,456,460,467,469,473,479,480,482,486,489,493,497,500,505,508,511,514,518,524,528,530,532,540,542,543,545,547,550,553,554,555,556,557 ./.build/checkouts/swift-llbuild/include/llvm/Support/ErrorHandling.h:14,17,21,24,29,48,51,59,60,63,80,87,88,105 ./.build/checkouts/swift-llbuild/include/llvm/Support/raw_ostream.h:13,16,22,29,33,34,35,44,64,70,84,89,90,92,95,99,103,109,110,116,119,120,128,129,132,133,137,141,142,148,149,155,156,162,163,167,171,175,176,180,182,183,187,188,191,192,200,201,204,205,207,210,214,217,220,223,226,229,230,245,246,250,253,258,261,265,281,284,288,296,297,301,305,312,317,322,326,332,336,340,342,345,349,352,356,370,374,376,380,384,393,394,398,400,402,404,411,412,424,426,430,434,438,442,447,450,457,463,465,471,474,485,490,495,500,504,509,510,511 ./.build/checkouts/swift-llbuild/include/llvm/Support/Mutex.h:13,16,20,22,24,27,31,38,42,47,53,60,68,74,83,84,96,107,108,109,121,122,123,128,129,134,137,141,145,146,149,151,153,154,155 ./.build/checkouts/swift-llbuild/include/llvm/Support/Program.h:13,16,21,24,32,45,48,51,54,71,77,120,130,134,144,168,189,190,191 ./.build/checkouts/swift-llbuild/include/llvm/Support/Format.h:22,25,32,34,43,46,49,55,58,62,67,70,72,77,81,90,91,95,98,100,109,113,114,125,131,132,138,139,155,166,167,179,180,189,190,191,192,193 ./.build/checkouts/swift-llbuild/include/llvm/Support/type_traits.h:13,16,19,24,26,49,55,64,72,76,82,87,93,94,95,99 ./.build/checkouts/swift-llbuild/include/llvm/Support/COFF.h:22,25,29,35,38,41,44,49,60,70,73,88,91,114,117,154,163,167,170,173,179,183,216,235,241,245,249,262,265,302,308,322,342,360,370,379,387,393,400,410,417,424,435,446,449,454,455,460,461,466,467,471,494,500,534,539,556,559,578,604,618,631,637,653,663,666,667,670,672,679,684,687,688,689,690,691 ./.build/checkouts/swift-llbuild/include/llvm/Support/MutexGuard.h:14,17,19,39,40 ./.build/checkouts/swift-llbuild/include/llvm/Support/MemoryBuffer.h:13,16,24,27,41,50,54,57,58,63,64,76,83,93,99,102,107,113,119,122,127,131,135,141,145,148,152,157,159,161,166,170,171,172 ./.build/checkouts/swift-llbuild/include/llvm/Support/WindowsError.h:9,12,14,17,18 ./.build/checkouts/swift-llbuild/include/llvm/Support/Atomic.h:13,16,18,22,36,37,38 ./.build/checkouts/swift-llbuild/unittests/Core/BuildEngineCancellationTest.cpp:12,14,16,19,21,24,27,29,40,41,44,45,50,52,59,67,68,75,80,84,85,86,90,95,96,97,103,104,107,109,112,118,119,125,126,138,149,156,163,164,195,209,210,211 ./.build/checkouts/swift-llbuild/unittests/Core/BuildEngineTest.cpp:12,14,16,19,21,24,27,29,35,43,44,49,50,55,56,60,62,69,77,78,85,90,94,95,96,100,105,106,107,113,114,117,119,122,128,129,153,160,169,170,208,216,217,252,260,268,273,274,348,358,368,378,386,403,411,412,423,426,431,433,435,438,445,452,459,475,478,482,487,488,498,524,525,526,530,533,537,538,541,546,549,553,554,559,560,565,567,599,605,610,617,618,623,624,648,654,663,664,681,696,698,703,704,717,722,723,742,750,765,773,788,796,798,800,803,804,806,811,812,814,821,822,823,824 ./.build/checkouts/swift-llbuild/unittests/Core/MakefileDepsParserTest.cpp:12,14,16,19,22,24,31,34,35,39,40,45,48,51,59,69,80,92,102,112,124,125,137,146,155,156,157 ./.build/checkouts/swift-llbuild/unittests/Core/DependencyInfoParserTest.cpp:12,14,16,19,22,24,31,34,35,38,39,42,43,46,47,50,52,56,58,65,66,68,75,76,78,85,86,88,96,97,99,114,115,116,117 ./.build/checkouts/swift-llbuild/unittests/Core/DepsBuildEngineTest.cpp:12,14,20,22,26,29,31,39,40,45,46,50,52,59,67,68,74,79,83,85,86,91,92,93,99,100,103,105,108,113,114,128,151,171,176,181,182,187,199,200,201,202,205,213,222,235,236,241,246,250,252,254,261,263,264,283,294,295,296,299,300,301 ./.build/checkouts/swift-llbuild/unittests/Core/SQLiteBuildDBTest.cpp:12,14,17,19,21,24,32,37,41,44,50,54,59,62,63,71,76,80,84,91,95,102,108,111 ./.build/checkouts/swift-llbuild/unittests/CAPI/C-API.cpp:12,14,16,18,23,24,25 ./.build/checkouts/swift-llbuild/unittests/CAPI/BuildSystem-C-API.cpp:12,19,21,23,37,39,41,42,52,54,55,56,57,69,75,89,94,95,100,101,104,121,125,126,134,135,146,150,154,156,163,169,170,172,173,178,183,184,190,191,198,199,201,202,210,211,215,216,226,227,235,236,240,241,251,252,262,263,268,269,275,276,281,286,289,292,318,323,338,341,344,350,351,355,360,363,368,369,373,376,377,378 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/TempDir.cpp:12,14,17,21,26,31,36,37,51,57,58 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/MockBuildSystemDelegate.h:12,15,19,23,26,31,34,38,41,43,45,48,51,55,59,61,63,66,68,71,72,73,75,80,83,84,85,88,89,95,96,101,102,103,105,111,112,113,115,121,122,123,126,129,130,131,136,137,138,143,144,145,151,152,153,159,162,163,164,170,173,174,176,177,178 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/BuildSystemTaskTests.cpp:12,15,22,27,30,32,38,40,47,49,54,55,59,60,62,65,66,69,70,75,76,82,84,85,88,90,96,99,102,103,106,107,110,111,114,115,118,120,124,129,134,135,141,147,148,152,156,162,167,168,169,173,179,184,185,190,191,197,199,205,206,208,213,214,215,219,221,228,229,234,236,240,262,263,270,274,278,282,283,284,289,295,300,301,306,312,317,318,325,329,333,345,349,353,365,370,371,374,379,380,383,387,397,401,404,405,411,422,423,424,427,429,433,434,435,441,444,448,452,466,467,473,484,485,489,492,501,502,506,509,513,517,524,525,527,530,531,535,538,540,545,551,552,553,557,561,568,569,578,583,585,592,593,596,599,603,607,614,615,617,620,621,625,628,630,637,643,644,645,649,653,661,662,671,676,679,681,690,691,694,697,701,705,712,713,715,718,719,723,726,728,733,739,740,741,745,749,757,758,765,770,777,778,781,784,788,792,799,800,802,805,806,810,813,815,820,826,827,828,832,836,844,845,854,859,861,864,872,873,876,879,883,887,894,895,897,900,903,904,908,911,913,917,923,924,926,932,933,934,938,942,949,950,957,961,967,968,970,974,975,981,984,985,986,987,993,999,1000,1006,1007,1009,1016,1021,1022,1024,1027,1031,1053,1054,1062,1066,1070,1074,1075,1079,1080 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/TempDir.h:12,15,18,20,28,30,34,38,39,40 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/MockBuildSystemDelegate.cpp:12,14,19,21,24,25,26,27 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/BuildSystemFrontendTest.cpp:12,14,20,27,29,32,37,38,45,47,54,58,64,65,66,68,73,74,78,79,82,88,90,92,99,100,102,109,110,113,114,116,117,119,122,124,125,127,130,132,133,135,138,139,142,143,145,146,148,151,153,154,156,160,162,163,165,168,170,171,174,178,180,181,184,188,190,191,194,195,197,201,203,204,212,216,217,223,225,227,228,235,238,244,250,257,258,261,264,282,286,287,291,293,296,311,313,314,315,316,323,326,332,339,340,343,347,377,378,380,382,385,400,403,404,405,406,413,416,426,429,432,442,443,450,453,477,480,483,499,500,506,509,512,513,514,517,527,539,540,543,544,545 ./.build/checkouts/swift-llbuild/unittests/BuildSystem/BuildValueTest.cpp:12,15,17,21,23,28,29,32,35,36,38,42,43,45,49,50,55,56,61,63,67,68,70,75,76,78,83,84,90,91,97,99,103,104,106,111,112,114,119,120,126,127,131,133,137,138,140,145,146,148,153,154,156,162,163,164,167,168,174,175,176,183,184,185,186 ./.build/checkouts/swift-llbuild/unittests/Basic/FileSystemTest.cpp:12,14,19,24,26,29,31,35,39,45,46,49,52,55,58,62,63,66,70,73,79,80,84,86,92,93,97,101,102,105,108,114,115,119,122,128,129,133,138,143,147,155,156,160,164,170,171,174,177,180,183,189,190,191 ./.build/checkouts/swift-llbuild/unittests/Basic/LaneBasedExecutionQueueTest.cpp:12,16,21,23,29,32,37,48,52,57,67,71,74,83,84,85,88,89,99,112,115,124,125,126,129,130,137,142,147,152,157,158,162,163,164,166,172,173,174,176,177,178 ./.build/checkouts/swift-llbuild/unittests/Basic/ShellUtilityTest.cpp:12,14,16,19,21,26,30,34,38,42,46,50,54,55,56 ./.build/checkouts/swift-llbuild/unittests/Basic/BinaryCodingTests.cpp:12,14,16,19,22,26,29,30,37,41,43,45,51,52,60,61,68,73,76,77,87,88,94,98,106,107,111,112,113 ./.build/checkouts/swift-llbuild/unittests/Basic/POSIXEnvironmentTest.cpp:12,14,16,19,26,31,32 ./.build/checkouts/swift-llbuild/unittests/Basic/SerialQueueTest.cpp:12,14,16,19,21,24,28,42,46,47,48 ./.build/checkouts/swift-llbuild/unittests/Ninja/LexerTest.cpp:12,14,16,18,20,22,26,30,33,40,48,56,64,72,80,84,85,91,96,102,109,116,123,130,134,135,140,148,156,164,172,176,177,183,188,208,212,213,220,223,231,240,247,254,260,264,265,274,277,285,293,300,306,310,311,316,319,342,346,347,348 ./.build/checkouts/swift-llbuild/utils/Xcode/LitXCTestAdaptor/LitTests.m:7,10,12,14,16,18,22,25,31,34,37,38 ./.build/checkouts/swift-llbuild/utils/unittest/UnitTestMain/TestMain.cpp:6,8,11,13 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-death-test.h:37,40,42,44,46,53,55,57,64,65,66,68,166,172,177,183,188,190,199,202,214,259,262,265,267,270,273,276,293,294,295 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-llbuild-config.h:2,5,8 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-spi.h:34,37,39,41,43,61,67,71,74,83,87,90,92,109,112,113,114,115,116,156,173,219,233 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h:67,70,73,75,78,81,94,95,106,111,118,121,122,128,136,139,140,144,149,154,160,161,167,168,173,175,176,181,185,191,195,196,200,203,206,207,211,212,219,221,225,226,230,231,238,239,240,241,242 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-string.h:40,43,48,51,53,56,61,70,75,85,96,103,109,117,126,141,146,149,152,155,159,163,164,165,166 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h:36,39,41,43,46,48,53,55,61,83,93,100,107,110,113,122,125,129,131,135,138,146,153,157,175,176,180,182,217,228,240,244,245,250,256,259,264,266,311,313,314,315,316 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-port.h:42,45,112,153,184,190,260,270,275,282,285,294,298,305,322,335,355,367,391,412,417,427,430,432,438,440,442,446,448,452,454,496,505,509,511,513,519,526,528,535,540,542,548,551,566,571,573,577,583,585,588,590,592,598,609,614,618,627,640,645,660,667,673,675,683,690,706,707,708,710,719,724,728,742,748,750,757,772,774,787,799,804,806,814,822,826,831,833,847,869,874,880,891,904,910,918,920,925,935,939,946,959,972,984,996,998,1000,1011,1013,1018,1033,1040,1045,1088,1094,1099,1102,1108,1114,1118,1120,1127,1130,1134,1139,1140,1145,1147,1148,1149,1153,1154,1157,1160,1162,1170,1173,1175,1177,1179,1182,1185,1195,1198,1199,1201,1204,1207,1208,1210,1213,1216,1222,1224,1227,1229,1231,1233,1236,1240,1246,1252,1259,1266,1269,1271,1274,1277,1279,1283,1286,1288,1311,1321,1328,1330,1353,1386,1387,1393,1394,1405,1413,1414,1416,1427,1429,1432,1435,1438,1441,1443,1447,1448,1450,1463,1465,1469,1481,1484,1485,1492,1493,1504,1505,1506,1510,1513,1515,1517,1530,1532,1536,1540,1542,1545,1557,1560,1564,1569,1580,1590,1591,1608,1619,1621,1626,1627,1628,1633,1634,1643,1648,1652,1654,1676,1681,1684,1686,1688,1692,1696,1700,1706,1709,1712,1715,1725,1727,1730,1733,1735,1742,1752,1756,1760,1770,1775,1779,1786,1789,1793,1799,1802,1804,1811,1815,1816,1820,1823,1826,1860,1862,1867,1875,1877,1882,1883,1887,1888,1891,1892,1898,1902,1907,1911,1917,1918,1921,1924,1926,1929,1931,1940,1941,1950,1951,1957,1958,1975,1979,1983,1991,1994,1995,1999,2009,2011,2014,2017,2019,2021,2030,2035,2036,2046,2050,2054,2055,2060,2067,2069,2074,2082,2083,2089,2090,2095,2096,2102,2106,2111,2115,2121,2122,2125,2128,2132,2135,2137,2139,2144,2152,2155,2157,2167,2169,2182,2184,2188,2202,2210,2217,2220,2223,2226,2231,2236,2241,2252,2254,2259,2262,2265,2268,2271,2274,2277,2280,2284,2285,2288,2291,2292,2298,2299,2305,2307,2309,2311,2313,2318,2328,2331,2342,2344,2346,2348,2354,2358,2360,2362,2364,2367,2368,2372,2378,2382,2389,2392,2409,2410,2412,2421,2422,2423,2440,2450,2476,2488,2501,2508,2510,2515,2519,2522,2529,2537,2539,2545,2553,2559,2560,2561,2562 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h:34,37,98 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-internal.h:36,39,41,43,50,54,64,69,80,83,85,87,94,97,99,104,108,125,137,141,143,154,156,163,169,175,185,190,195,196,197,205,226,233,269,271,274,278,281,284,288,291,305,313,315,323,324,328,329,332,334,337,340,343,346,352,353,364,367,368,375,398,399,400,408,409,412,419,424,432,441,444,455,456,463,469,473,476,480,488,490,499,501,505,508,512,541,546,548,553,565,569,570,573,574,579,580,586,589,593,600,603,604,610,611,616,638,652,656,658,667,669,689,691,693,697,702,704,713,715,717,730,733,736,739,748,757,759,761,765,770,775,779,787,792,800,808,818,823,827,835,840,852,861,866,879,900,910,938,939,943,950,952,956,959,963,968,969,978,980,981,989,991,992,996,999,1003,1008,1009,1017,1018,1019,1026,1042,1046,1047,1051,1052,1056,1057,1061,1062,1070,1071,1077,1085,1086,1092,1093,1097,1100,1101,1102,1103,1107,1110,1113,1116,1119,1125,1151,1165,1183,1184,1196,1210,1214,1226,1238,1240 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h:4,35,45,48,54,56,58,65,68,72,74,80,85,86,90,93,98,103,104,108,112,117,123,124,128,133,139,145,146,150,156,162,168,169,173,180,187,194,195,199,207,214,221,222,226,235,243,250,251,255,265,273,281,282,286,297,305,313,314,318,330,339,347,348,352,365,374,383,384,388,402,412,421,422,426,441,451,460,461,465,481,491,501,502,506,523,535,545,546,550,568,580,590,591,595,614,626,637,638,642,662,674,685,686,690,711,724,735,736,740,762,776,788,789,793,816,830,842,843,847,871,886,898,899,903,928,943,956,957,961,987,1002,1015,1016,1020,1047,1063,1076,1077,1081,1109,1126,1140,1141,1145,1174,1191,1205,1206,1210,1240,1257,1271,1272,1276,1307,1325,1340,1341,1345,1377,1396,1411,1412,1416,1449,1468,1483,1484,1488,1522,1542,1558,1559,1563,1598,1618,1634,1635,1639,1675,1695,1711,1712,1716,1753,1774,1791,1792,1796,1834,1856,1873,1874,1878,1917,1939,1956,1957,1961,2001,2023,2041,2042,2046,2087,2110,2128,2129,2133,2175,2199,2217,2218,2222,2265,2289,2308,2309,2313,2357,2381,2400,2401,2405,2450,2475,2494,2495,2499,2545,2570,2590,2591,2595,2642,2668,2688,2689,2693,2741,2768,2788,2789,2793,2842,2869,2890,2891,2895,2945,2972,2993,2994,2998,3049,3076,3097,3098,3102,3154,3166,3171,3174,3177,3178,3191,3193,3196,3205,3207,3210,3227,3228,3239,3240,3244,3251,3252,3255,3267,3270,3274,3275,3281,3286,3290,3293,3294,3310,3312,3315,3324,3328,3330,3333,3351,3352,3366,3367,3371,3379,3380,3383,3398,3401,3406,3407,3413,3419,3423,3427,3428,3447,3449,3452,3461,3465,3469,3471,3474,3493,3494,3511,3512,3517,3526,3527,3530,3548,3551,3557,3558,3564,3570,3574,3578,3579,3601,3603,3606,3615,3619,3623,3627,3629,3632,3652,3653,3673,3674,3679,3689,3690,3693,3714,3717,3724,3725,3733,3740,3744,3748,3749,3774,3776,3779,3788,3792,3796,3800,3804,3806,3809,3830,3831,3854,3855,3860,3871,3872,3875,3899,3902,3910,3911,3919,3926,3931,3935,3936,3964,3966,3969,3978,3982,3986,3990,3994,3998,4000,4003,4025,4026,4052,4053,4058,4070,4071,4074,4101,4104,4113,4114,4122,4131,4136,4141,4142,4173,4175,4178,4187,4191,4195,4199,4203,4207,4211,4213,4216,4239,4240,4269,4270,4275,4288,4289,4292,4322,4325,4335,4336,4344,4353,4358,4363,4364,4398,4400,4403,4412,4416,4420,4424,4428,4432,4436,4440,4442,4445,4469,4470,4502,4503,4509,4523,4524,4527,4560,4563,4574,4575,4583,4593,4598,4603,4604,4641,4643,4646,4655,4659,4663,4667,4671,4675,4679,4683,4687,4689,4692,4717,4718,4753,4754,4760,4775,4776,4779,4815,4818,4830,4831,4849,4850,4854,4858,4872,4873,4877,4882,4898,4899,4903,4909,4926,4927,4931,4938,4958,4959,4963,4971,4993,4994,4998,5007,5032,5033,5037,5047,5075,5076,5080,5091,5121,5122,5126,5138,5140,5141,5142,5143,5145 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h:31,33,36,38,43,51,53,55,66,73,75,77,86,89,118,128,135,136,143,149,152,155,156,162,169,171,176,186,189,193,194,197,201,213,216,219,220,228,231,235,238,249,250,256,259,265,273,274,277,285,286,298,301,304,305,308,315,318,322,325,337,346,347,355,365,368,371,381,382,391,392,397,401,402,416,417,420,423,432,435,449,451,454,455,459,473,483,486,490,508,512,529,540,558,563,570,573,578,582,584,596,597,598,599,600,611,631,639,644,649,650,652,653,658,661,675,676,677,700,702,703,708,710,715,716,717,720,722,725,726,727,728,730 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h:4,35,43,46,48,56,59,66,82,84,86,88,89,91,95,98,103,109,116,119,121,132,138,144,150,157,164,171,178,185,193,201,209,217,226,236,246,256,266,276,287,298,309,320,331,343,355,367,380,393,407,421,435,449,463,478,493,508,523,538,554,570,587,604,621,639,657,675,693,711,712,713,714,759,1619,1621,1623,1639,1642,1649,1656,1659,1661,1672,1678,1685,1692,1699,1707,1715,1723,1732,1741,1750,1760,1771,1782,1794,1806,1818,1831,1844,1857,1871,1885,1899,1914,1929,1944,1961,1978,1995,2013,2031,2049,2068,2087,2106,2126,2146,2166,2187,2208,2230,2253,2276,2299,2323,2347,2371,2396,2421,2422,2467,3296,3300,3305,3325,3327,3328,3329,3330 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h:39,42,44,47,58,63,66,67,71,72,75,76,79,82,91,97,109,112,117,125,133,139,145,151,155,159,164,168,171,192,194,199,202,203,204,205 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/custom/gtest-port.h:65,68 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/custom/gtest.h:37,40 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/custom/gtest-printers.h:38,41 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h:4,35,37,40,42,55,63,86,108,114,120,124,130,133,140,143,146,151,156,161,166,171,176,181,186,191,196,201,202,203,211,216,218,220,222,225,227,231,232,234,239,240,243,248,250,253,255,260,262,266,272,273,275,281,282,286,291,293,296,298,301,303,307,308,310,317,318,323,328,330,334,336,340,342,346,347,349,357,358,364,369,371,375,378,382,384,388,389,391,400,401,408,413,415,420,423,427,429,433,434,436,446,447,455,460,462,467,470,474,476,480,481,483,494,495,504,509,511,517,520,524,526,530,531,533,545,546,556,561,563,569,572,576,578,582,583,585,598,599,610,615,618,624,627,632,634,638,639,641,655,656,668,670,674,676,680,681,685,686,690,691,696,697,702,703,708,709,714,715,720,721,727,728,734,735,737,739,744,749,754,759,764,769,774,779,784,789,794,800,802,804,806,813,818,825,830,837,842,849,854,861,866,873,878,885,890,897,902,909,914,921,926,927,928,933,934,939,940,942,944,946,953,959,961,968,970,971,972,979,980,984,987,988,989,990,1002,1014,1019 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-message.h:45,48,50,52,54,57,66,72,77,82,84,88,90,122,126,130,131,135,136,143,169,170,194,196,198,208,209,213,214,219,225,231,237,239,251,252,260,262,265,270,274,275,277,285,286,287,288,289 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-param-test.h:4,43,45,50,52,60,64,68,74,75,78,79,103,107,126,129,162,167,171,174,175,179,180,182,184,188,195,197,199,218,246,247,251,252,316,317,321,322,327,328,351,352,356,357,361,362,366,367,372,373,379,380,387,388,395,396,403,404,411,412,421,422,431,432,441,442,452,453,463,464,476,477,489,490,502,503,515,516,528,529,542,543,558,559,574,575,590,591,606,607,624,625,642,643,661,662,680,681,699,700,719,720,740,741,761,762,782,783,803,804,826,827,850,851,874,875,898,899,922,923,947,948,974,975,1001,1002,1028,1029,1055,1056,1083,1084,1111,1112,1140,1141,1169,1170,1199,1200,1223,1224,1279,1280,1286,1287,1297,1298,1308,1309,1319,1320,1332,1333,1345,1346,1359,1360,1376,1378,1379,1380,1409,1421,1440,1441,1442,1444 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-typed-test.h:31,34,36,38,42,44,55,61,65,73,77,83,84,86,88,102,104,111,116,123,124,126,133,144,148,150,153,155,157,163,170,190,192,194,196,204,211,218,225,241,249,262,264 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest_pred_impl.h:29,34,37,42,71,74,81,82,92,96,97,103,111,121,122,123,136,142,143,149,159,169,170,171,187,195,196,202,214,224,225,226,245,255,256,262,276,286,287,288,310,322,323,329,345,355,356,357 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest_prod.h:33,36,38,56,59 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-test-part.h:32,35,38,40,43,45,59,72,73,76,81,82,86,89,92,95,98,101,104,107,111,121,124,132,135,138,141,144,147,152,155,157,174,177,178,179,180,181 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest.h:50,53,57,59,69,84,86,88,91,94,98,103,107,111,115,119,122,126,130,133,137,142,147,150,152,168,169,170,178,263,265,280,282,287,288,291,294,301,305,310,311,318,319,326,327,330,339,342,345,349,376,381,384,392,400,403,406,410,426,430,433,436,441,449,452,456,458,477,481,483,495,496,500,501,505,506,510,511,518,529,532,536,539,542,545,548,551,554,559,564,574,578,579,583,584,587,596,602,605,608,611,614,617,621,630,634,651,654,657,664,665,672,673,676,679,697,704,705,708,727,737,742,743,747,750,751,769,773,776,797,800,803,810,811,814,817,820,823,826,829,832,835,838,841,844,848,852,856,859,863,864,868,871,875,878,882,883,886,890,894,898,899,903,904,909,910,914,915,919,920,924,925,928,931,955,959,978,981,990,996,999,1005,1008,1011,1014,1017,1020,1023,1026,1029,1032,1036,1040,1064,1070,1075,1080,1088,1089,1099,1100,1108,1112,1119,1126,1131,1138,1142,1159,1167,1171,1176,1181,1184,1193,1196,1199,1202,1206,1209,1212,1215,1218,1221,1224,1227,1231,1234,1237,1241,1245,1249,1253,1265,1276,1283,1287,1291,1304,1307,1310,1315,1319,1323,1329,1333,1354,1355,1366,1370,1372,1385,1386,1396,1398,1400,1401,1409,1424,1425,1437,1439,1462,1463,1481,1483,1495,1496,1507,1520,1522,1533,1535,1543,1551,1559,1567,1568,1576,1584,1585,1586,1613,1622,1624,1638,1641,1642,1646,1650,1656,1657,1667,1678,1682,1694,1699,1703,1705,1708,1709,1710,1745,1751,1762,1763,1769,1770,1773,1777,1780,1783,1787,1789,1791,1808,1811,1817,1820,1826,1829,1835,1844,1857,1873,1877,1923,1938,1953,1956,1960,1964,1968,1972,1976,1980,1996,2005,2014,2028,2032,2036,2040,2044,2048,2052,2057,2064,2065,2067,2079,2082,2085,2088,2090,2105,2120,2155,2156,2172,2185,2191,2217,2221,2222,2223,2233,2236,2237 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/include/gtest/gtest-printers.h:31,94,97,103,105,108,112,114,118,124,133,145,147,152,162,164,178,180,213,214,215,216,217,221,238,253,254,255,256,259,273,280,282,289,291,294,302,303,308,310,313,321,322,325,330,335,340,342,355,356,366,369,386,387,392,393,396,398,399,432,433,434,435,443,444,481,482,486,495,496,500,501,510,515,516,521,524,527,530,531,542,544,547,556,557,558,564,566,570,571,577,579,584,586,593,597,602,605,606,610,611,615,616,620,621,625,626,631,632,638,639,645,646,652,653,659,660,667,669,674,676,687,688,697,711,712,715,736,738,739,743,747,756,758,766,771,774,775,778,782,788,795,802,812,813,820,822,832,833,836,842,844,848,849,860,861,863,873,879,882,888,893,899,902,907,912,932,936,937,946,948,954,958,966,967,977,979,980,981,987,988,989,990,995 ./.build/checkouts/swift-llbuild/utils/unittest/googletest/src/gtest-internal-inl.h:29,36,39,47,54,58,60,65,69,72,74,81,83,87,104,107,111,114,117,120,126,133,140,147,148,158,159,183,184,204,205,226,234,249,255,265,270,277,279,290,292,293,298,299,305,306,321,328,329,330,335,336,342,343,353,357,358,362,376,379,384,386,393,398,401,407,412,416,422,430,435,439,443,448,451,455,462,472,475,478,488,491,494,503,510,513,517,520,524,527,530,533,537,540,543,546,549,552,555,558,562,565,568,573,574,580,581,587,588,591,595,598,605,610,622,637,659,660,665,666,672,674,678,679,685,686,694,700,704,705,709,710,716,721,729,732,736,740,744,747,748,752,759,760,764,765,767,770,774,780,787,790,793,797,800,804,807,811,814,818,823,826,829,833,837,841,847,852,856,859,865,871,881,885,891,894,897,900,904,907,914,917,921,924,929,930,932,948,950,955,957,961,973,975,979,981,985,987,990,992,994,998,1003,1005,1007,1020,1021,1024,1025,1029,1031,1033,1041,1044,1047,1051,1053,1060,1061,1065,1066,1071,1077,1078,1079,1083,1088,1091,1092,1096,1099,1102,1105,1108,1111,1112,1117,1120,1121,1125,1126,1131,1132,1135,1136,1141,1142,1145,1146,1152,1153,1161,1162,1166,1170,1172,1174,1177,1179,1180,1181,1182 ./.build/checkouts/swift-llbuild/utils/ptreetime/libptreetime/ptreetime_interpose.c:12,31,44,53,56,61,64,68,72,73,84,85,92,93,94,103,104,108,109,110,115,119,130,133,134,137,140,146,147,151,154,155,156,161,165,177,180,189,190,194,199,200,202,203,206,209,210,213,215,217,222,223,230,232,234,242,244 ./.build/checkouts/swift-llbuild/examples/swift-bindings/core/basic.swift:2,4,9,14,15,19,20,21,24,25,29,30,31,34,42,48,56,58,59,60,61,68,71,72,73,76,80,82,86,90 ./.build/checkouts/swift-llbuild/examples/GameOfLife/Package.swift:2,4,15 ./.build/checkouts/swift-llbuild/examples/GameOfLife/Sources/GameOfLife/LifeBoard.swift:8,14,19,21,22,26,27,28 ./.build/checkouts/swift-llbuild/examples/GameOfLife/Sources/GameOfLife/LifeBoard+Build.swift:8,10,17,18,25,26,28,29,30 ./.build/checkouts/swift-llbuild/examples/GameOfLife/Sources/GameOfLife/BuildLife.swift:8,10,12,19,24,25,29,30,37,43,44,45,47,51,53,58,59,60,64,67,68,71,72,75,76,77,82,85,88,92,93,103,104,105,106,107,111,118,119,120,127,131,132,133,135,136,137,140,142,145,146,147,153,155,161,162,168,169,170,171,175,176,179,180,181,186,191,192,195,196,197,199,204,205,208,211,212,219,220,224,225,228,229,237,238,239,240,242,243 ./.build/checkouts/swift-llbuild/examples/GameOfLife/Sources/LifeServer/main.swift:8,11,13,16,18,23,26,29,39,40,41,42,48,50,51,55,62,68,77,78,83,84,86,87 ./.build/checkouts/swift-llbuild/examples/c-api/buildsystem/main.c:17,19,23,28,33,34,38,39,58,60,62,71,72,74,82,83,85,88,97,105,107,114,120,121,123,124,129,134,135,141,142,149,150,152,153,161,162,166,167,177,178,186,187,191,192,202,203,213,214,219,220,223,226,227,229,234,249,252,255,261,265,266,269,271 ./.build/checkouts/swift-llbuild/Package.swift:2,5,7,25,32,40,47,49,76,78,95,97,110,112 ./.build/checkouts/swift-llbuild/lib/Core/BuildEngineTrace.h:12,15,18,21,24,30,35,39,43,49,54,57,60,63,77,79,82,96,98,101,104,106,109,110,111,112 ./.build/checkouts/swift-llbuild/lib/Core/BuildDB.cpp:12,14,17,19 ./.build/checkouts/swift-llbuild/lib/Core/MakefileDepsParser.cpp:12,14,16,20,22,24,36,37,38,42,49,50,53,55,56,57,61,65,70,71,74,75,76,80,84,85,86,87,92,98,102,118,125,126,131,132,133,139,144,148,157,159,167,168,171,178,187,196,199,201,202 ./.build/checkouts/swift-llbuild/lib/Core/DependencyInfoParser.cpp:12,14,17,19,21,23,32,36,41,44,47,51,52,53,60,61,66,67,80,84,90,91,99,102,103,107,108,112,113,117,118,122,123,124 ./.build/checkouts/swift-llbuild/lib/Core/BuildEngine.cpp:12,14,17,20,22,35,38,40,42,47,48,50,52,56,61,63,65,68,71,74,77,80,83,97,111,120,126,129,132,136,139,142,150,152,155,158,169,173,174,179,182,183,186,187,190,191,194,195,199,200,211,212,220,221,225,229,232,233,237,241,245,247,256,264,285,296,297,300,305,308,311,314,318,321,325,326,327,348,350,362,369,370,376,378,379,385,386,387,389,392,402,406,410,414,416,423,424,437,438,445,446,458,460,461,469,473,477,482,486,488,489,492,496,501,504,508,513,515,518,519,529,530,534,535,537,538,545,551,558,560,563,573,574,577,580,594,595,604,605,610,615,616,621,625,626,630,631,636,637,648,649,650,659,662,666,672,673,680,682,685,687,688,692,694,697,704,705,706,709,719,720,723,727,742,743,744,748,750,753,757,767,768,770,784,790,794,795,798,799,803,805,808,811,814,818,823,826,827,830,831,835,838,843,844,847,849,852,858,859,865,870,880,890,891,901,902,903,907,908,914,915,919,922,924,929,930,931,940,943,949,950,952,953,963,964,965,968,969,970,972,973,985,988,991,994,995,998,1009,1013,1015,1016,1027,1028,1029,1035,1039,1045,1046,1047,1053,1059,1060,1061,1062,1069,1070,1071,1078,1079,1083,1095,1101,1105,1106,1113,1114,1119,1120,1122,1123,1127,1133,1140,1143,1144,1151,1152,1156,1158,1159,1164,1167,1174,1175,1180,1184,1187,1191,1192,1193,1195,1196,1203,1204,1205,1207,1208,1215,1216,1217,1219,1220,1240,1241,1242,1244,1264,1265,1273,1274,1275,1278,1279,1284,1290,1291,1292,1295,1296,1299,1300,1303,1309,1310,1316,1317,1320,1325,1328,1329,1335,1339,1340,1345,1346,1349,1352,1353,1358,1363,1364,1379,1380,1381,1383,1384,1386,1389,1398,1399,1400,1410,1413,1417,1428,1430,1431,1434,1443,1448,1449,1454,1455,1463,1464,1471,1476,1477,1480,1483,1486,1487,1494,1495,1502,1511,1519,1521,1522,1526,1527,1530,1535,1536,1539,1542,1543,1545,1548,1550,1555,1557,1558,1565,1566,1568,1569,1572,1573,1578,1583,1584,1587,1588,1592,1595,1600,1601,1604,1612,1613,1615,1618,1619,1622,1623,1625,1628,1630,1633,1634,1635,1637,1640,1641,1642,1645,1646,1649,1650,1653,1654,1657,1658,1661,1662,1665,1666,1669,1670,1673,1674,1678,1679,1682,1683,1687,1688,1691,1692,1695,1696,1701 ./.build/checkouts/swift-llbuild/lib/Core/BuildEngineTrace.cpp:12,14,16,20,22,25,27,29,33,39,42,46,47,50,52,55,59,63,64,66,67,69,72,77,82,85,87,88,91,96,101,112,114,115,118,120,121,124,127,128,132,135,136,140,143,144,147,150,151,155,158,159,163,166,167,171,174,175,179,182,183,186,188,189,192,195,196,200,204,207,208,211,213,214,216,219,222,223,226,229,230,234,237,238,243,246,247,252,255,256,259,262,263,266,269,270,274,277,278,283,287,288,291,294,295,298,301,302,305,308 ./.build/checkouts/swift-llbuild/lib/Core/SQLiteBuildDB.cpp:12,14,18,22,27,29,32,34,39,44,51,54,56,62,63,64,66,76,79,81,84,87,92,96,99,100,103,104,109,122,123,124,130,131,147,158,160,161,166,175,182,183,184,187,197,204,211,222,223,231,232,236,237,244,245,246,252,257,262,267,272,277,282,284,285,288,304,307,308,312,317,318,321,324,325,328,332,333,344,345,351,352,355,357,360,361,364,367,368,377,382,383,386,387,391,401,407,414,417,418,424,429,437,445,446,457,463,472,480,481,492,496,500,501,502,508,515,521,523,524,526,527,531,536,541,545,553,556,557,561,562,577,579,580,609,610,612,613,616,619,625,629,630,632,633,636,641,645,646,648,649,653,656,666,667,669,674,675,677,678,687,688,690,701,705,708,709,723,724,727,728,738,739,744,753,758,760,764,767,771,774,776,777,778,783,784 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildSystemFrontend.cpp:12,14,23,31,36,40,42,59,63,64,65,72,76,80,82,83,87,88,101,108,115,124,133,139,144,151,158,164,165,166,167,177,214,216,217,219,220,222,224,226,230,232,234,239,243,244,248,249,256,257,265,266,274,275,283,285,287,295,298,302,304,307,310,313,318,322,324,332,334,335,339,341,344,345,349,350,351,352,360,361,362,363,366,367,371,373,374,377,379,380,383,385,386,389,391,392,395,397,398,402,403,409,411,431,432,433,434,439,441,442,446,452,453,463,464,465,470,471,475,478,482,483,484,487,490,494,495,500,501,502,505,508,509,512,513,515,516,519,520,525,526,535,539,540,543,544,548,549,553,554,558,559,561,562,567,571,575,577,578,582,583,588,592,596,598,599,603,604,606,607,609,610,613,614,620,621,627,632,633,639,643,644,650,655,658,660,661,663,669,672,674,675,681,682,683,686,693,697,704,705,710,711,712,725,726,731,732,733,735,736,740,744,747,754,755,756,760,761,763,764,768,769,773,774,778,780,781,783,784,788,789,794,800 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildFile.cpp:12,14,18,23,26,29,30,32,34,36,45,46,50,51,58,59,63,64,73,75,76,83,85,86,90,91,92,94,98,101,104,107,110,113,116,119,124,125,133,134,137,138,141,142,147,148,151,152,157,160,161,167,173,176,178,179,185,191,193,194,200,202,208,212,213,218,220,226,227,231,233,234,240,241,245,247,248,254,255,259,261,262,268,269,273,275,276,282,283,287,289,290,295,296,298,299,305,311,315,316,326,329,330,331,336,337,339,340,347,352,353,358,363,364,369,374,375,376,379,388,394,395,401,402,408,415,419,420,425,430,431,437,438,439,440,441,443,444,451,456,457,462,465,472,473,479,480,483,486,487,489,490,493,497,498,501,503,504,511,516,517,522,528,533,538,539,542,551,557,558,564,565,571,578,582,583,588,593,594,600,601,602,603,604,606,607,614,619,620,625,630,631,638,645,652,653,662,663,667,673,679,680,683,689,690,696,697,703,704,707,713,714,720,723,724,730,731,737,742,743,746,755,761,762,768,769,775,782,786,787,792,797,798,804,805,806,807,808,811,814,815,817,818,824,827,828,831,841,842,844,847,853,854,860,861,864,865,869,870,882,884,885,886,888,892,893,894,897,898,902 ./.build/checkouts/swift-llbuild/lib/BuildSystem/ExternalCommand.cpp:12,14,23,26,32,36,41,44,49,50,54,55,62,63,64,70,71,72,81,89,97,103,104,110,116,117,126,130,138,139,146,149,153,155,156,162,166,170,174,178,194,201,202,205,206,209,210,216,221,222,223,230,231,232,238,247,257,266,273,274,278,282,285,292,298,299,300,306,310,314,316,317,337,338,340,341,352,355,356,359,361,369,370,371,385,386,387,388,393,408,411 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildNode.cpp:12,14,18,21,25,38,50,63,76,87,92,93,97,98,104,105,109,110,117,118,122,123,127,128,129,132,133,136 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildSystem.cpp:12,16,34,47,52,60,65,67,69,71,73,75,79,82,86,88,91,95,96,98,100,104,108,110,113,115,118,121,124,128,131,134,137,139,146,149,152,154,166,168,171,174,177,180,183,186,189,192,196,199,202,205,208,209,213,214,218,219,222,223,227,228,232,233,236,237,239,248,251,252,255,256,259,260,266,267,270,271,275,276,279,280,284,285,288,295,296,302,303,304,307,310,315,316,319,320,323,324,333,335,336,339,340,343,345,348,349,353,354,358,363,364,368,369,372,374,376,380,381,382,385,386,387,392,397,401,408,409,410,414,415,420,423,424,425,431,432,439,441,443,449,452,453,456,457,460,465,467,468,473,476,477,480,481,484,485,488,499,500,503,504,508,509,531,532,534,539,545,546,549,550,553,554,557,563,564,566,567,570,574,576,585,587,593,594,599,600,603,604,608,609,613,614,618,620,621,630,632,638,642,643,646,647,651,652,656,657,661,663,664,669,670,673,674,677,678,682,683,686,691,693,694,704,709,712,721,722,727,728,731,732,736,740,741,747,748,750,753,754,758,765,771,774,776,777,781,784,788,815,816,819,820,826,827,828,831,835,836,840,841,844,849,850,851,862,863,869,870,871,875,887,891,895,901,904,910,911,912,914,915,917,918,923,926,929,960,961,964,965,971,972,973,978,979,983,984,986,991,992,996,1000,1001,1002,1006,1023,1024,1027,1028,1034,1035,1036,1042,1043,1044,1061,1066,1069,1073,1076,1079,1082,1088,1099,1100,1101,1104,1105,1112,1118,1119,1128,1130,1131,1138,1145,1150,1151,1153,1154,1159,1160,1165,1169,1182,1183,1184,1188,1189,1194,1195,1211,1216,1219,1223,1226,1229,1235,1241,1242,1245,1246,1253,1258,1267,1269,1270,1277,1284,1289,1290,1292,1293,1298,1299,1304,1306,1316,1317,1318,1332,1333,1341,1342,1343,1347,1348,1352,1353,1357,1361,1363,1364,1370,1371,1377,1378,1386,1387,1396,1397,1403,1408,1409,1412,1418,1420,1422,1434,1437,1444,1445,1449,1452,1453,1463,1466,1467,1471,1475,1490,1492,1493,1510,1512,1513,1523,1527,1537,1539,1540,1552,1554,1555,1567,1569,1570,1583,1584,1600,1601,1614,1615,1632,1633,1634,1641,1654,1656,1657,1668,1669,1681,1682,1692,1694,1695,1706,1708,1709,1720,1721,1732,1734,1742,1743,1755,1757,1758,1759,1762,1763,1768,1769,1774,1775,1778,1779,1781,1791,1792,1794,1798,1799,1801,1803,1807,1808,1810,1811,1815,1822,1826,1827,1833,1834,1839,1840,1846,1847,1849,1850,1852,1856,1858,1861,1862,1865,1866,1876,1877,1888,1889,1892,1894,1898,1904,1910,1917,1918,1921,1923,1925,1931,1936,1940,1943,1946,1949,1952,1955,1958,1961,1964,1967,1970,1975,1982,1986,1989,1993,1997,2000,2001,2012,2013,2021,2022,2027,2033,2039,2040,2042,2043,2045,2046,2062,2066,2074,2075,2082,2083,2092,2094,2095,2098,2101,2106,2107,2124,2128,2134,2135,2140,2143,2145,2149,2150,2155,2158,2159,2167,2168,2169,2198,2205,2212,2226,2230,2231,2233,2234,2242,2243,2248,2254,2255,2257,2258,2270,2273,2274,2276,2277,2283,2294,2295,2308,2312,2313,2316,2318,2322,2325,2333,2338,2340,2346,2353,2354,2357,2359,2361,2365,2368,2372,2373,2383,2384,2394,2398,2404,2405,2410,2411,2414,2417,2422,2423,2426,2429,2430,2438,2439,2440,2454,2455,2457,2465,2468,2469,2471,2476,2477,2484,2489,2490,2503,2507,2508,2511,2513,2517,2523,2529,2536,2537,2540,2542,2544,2547,2551,2552,2555,2558,2559,2563,2564,2576,2582,2589,2595,2596,2600,2601,2609,2621,2632,2634,2636,2637,2644,2646,2650,2653,2656,2659,2662,2665,2668,2671,2674,2677,2682,2694,2695,2699,2700,2713,2718,2723,2727,2731,2734,2735,2736,2739,2744,2745,2749,2752,2763,2764,2765,2766,2803,2807,2816,2817,2819,2820,2828,2831,2832,2845,2846,2848,2849,2854,2855,2861,2870,2871,2873,2886,2889,2902,2909,2914,2915,2917,2919,2921,2922,2931,2932,2944,2948,2954,2955,2964,2965,2966,2969,2972,2974,2979,2980,2986,2998,2999,3009,3010,3012,3013,3026,3033,3040,3047,3048,3056,3057,3065,3068,3072,3080,3081,3084,3089,3090,3101,3102,3105,3107,3111,3117,3118,3125,3126,3133,3134,3137,3138,3143,3144,3146,3148,3149,3151,3155,3156,3165,3166,3167,3173,3179,3183,3190,3192,3193,3208,3212,3213,3217,3221,3227,3233,3240,3241,3244,3246,3248,3252,3256,3259,3262,3265,3270,3271,3277,3279,3280,3284,3285,3288,3289,3300,3303,3310,3311,3312,3318,3319,3320,3329,3330,3331,3343,3344,3350,3357,3358,3367,3371,3376,3377,3384,3388,3392,3396,3402,3404,3405,3415,3416,3417,3421,3422,3427,3428,3438,3439,3443,3447,3448,3449,3459,3464,3465,3467,3472,3473,3477,3480,3481,3485,3489,3495,3501,3508,3509,3512,3514,3516,3518,3521,3534,3535,3544,3545,3551,3552,3553,3562,3563,3564,3565,3569,3573,3574,3577,3578,3579,3583,3590,3591,3592,3595,3596,3597,3605,3606,3610,3614,3620,3626,3633,3634,3637,3639,3641,3644,3649,3652,3654,3657,3658,3661,3662,3665,3672,3673,3679,3680,3682,3683,3686,3689,3695,3702,3708,3710,3711,3714,3720,3721,3730,3733,3734,3739,3740,3743,3748,3749,3754,3755,3759,3760,3764,3768,3770,3771,3782,3783,3785,3787,3791,3797,3798,3803,3804,3805,3809,3810,3817,3818,3819,3820,3822,3825,3826,3831,3835,3841,3847,3854,3855,3858,3860,3862,3865,3866,3869,3870,3877,3878,3887,3894,3902,3903,3904,3905,3907,3908,3914,3915,3933,3934,3936,3937,3940,3941,3943,3944,3947,3948,3953,3954,3955,3956,3958,3961,3962,3963,3966,3967,3970,3971,3974,3975,3978,3979,3984,3985,3989,3990,3994,3995,3998,3999,4002,4003,4007,4008,4009,4012,4013,4027,4036 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildDescription.cpp:12,14,17,19,21,23,26 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildValue.cpp:12,14,16,18,20,23,45,47,48,53,69,70,72,81,83,85 ./.build/checkouts/swift-llbuild/lib/BuildSystem/BuildKey.cpp:12,14,17,19,22,37,39,40,47,52,58,63,67,71,75,78,79,81 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Memory.cpp:14,18 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Mutex.cpp:13,16,21,31,33,35,39,42,46,51,57,63,67,71,74,75,78,83,84,87,90,93,94,97,100,103,104,107,110,113,114,115,116 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Program.cpp:13,19,24,28,40,41,44,46,47,58,60,61 ./.build/checkouts/swift-llbuild/lib/llvm/Support/ConvertUTF.c:30,32,44,46,48,49,55,57,60,67,69,87,95,104,106,114,115,117,128,139,142,148,154,158,159,163,164,166,191,196,203,204,208,210,217,220,248,253,260,261,269,270,275,281,283,287,288,290,309,310,322,323,328,334,336,340,341,343,354,364,372,373,375,378,379,381,390,392,393,395,400,402,411,414,419,428,429,432,435,438,441,444,447,452,455,457,462,465,467,472,475,477,478,485,486,488,495,496,498,509,511,512,514,526,531,542,544,548,558,561,569,575,579,580,584,585,587,604,613,614,617,618,634,635,646,648,661,664,668,669,673,674,682,683,689,690,692,697,704,707 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Process.cpp:13,20,23,28,38,39,46,49,54,58,62,68,69,70,72,73,74,76,86,87,92 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Locale.cpp:3,7,14,15,27,28,29,30,31 ./.build/checkouts/swift-llbuild/lib/llvm/Support/FileUtilities.cpp:14,25,28,29,37,38,39,46,47,48,52,61,62,66,68,69,77,78,86,93,105,111,114,115,121,124,125,126,134,136,137,155,157,158,159,163,164,184,186,192,194,204,209,215,216,222,224,230,236,237,238,249,254,258,259,261 ./.build/checkouts/swift-llbuild/lib/llvm/Support/TimeValue.cpp:13,16,19,24,37,38,45,46,47,48,49 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Twine.cpp:9,15,20,24,25,29,30,36,37,47,50,51,56,57,99,100,101,149,150,151,155,156,163,164,167,168,171 ./.build/checkouts/swift-llbuild/lib/llvm/Support/ConvertUTFWrapper.cpp:9,14,16,30,57,61,62,73,76,77,82,83,86,90,94,97,106,107,111,117,121,125,126,131,132,136,142,143,146,155,159,163,164,169,170,171,172 ./.build/checkouts/swift-llbuild/lib/llvm/Support/YAMLParser.cpp:13,24,27,36,40,50,60,61,71,85,86,90,93,95,96,107,134,138,141,142,143,149,151,155,159,164,166,172,175,176,178,195,198,200,201,206,214,224,239,253,255,256,264,267,270,274,275,279,285,286,289,290,294,295,298,301,302,311,312,332,341,349,357,365,374,382,387,390,394,399,405,408,412,418,421,424,427,430,433,436,439,442,445,448,451,454,457,460,463,466,469,472,475,478,481,484,487,490,493,496,499,502,507,510,514,515,516,517,544,545,546,618,624,626,627,637,639,640,679,696,700,702,703,706,707,710,711,726,727,738,739,742,751,753,754,760,765,766,768,769,777,791,793,794,802,803,807,808,809,816,817,824,825,833,835,836,841,842,847,848,865,867,868,880,882,883,888,889,897,898,910,911,912,923,924,925,929,930,936,942,943,945,946,955,960,962,963,968,969,980,981,982,993,994,995,998,1000,1007,1008,1014,1015,1019,1025,1026,1032,1039,1055,1057,1058,1063,1070,1071,1079,1082,1087,1088,1101,1102,1112,1113,1124,1125,1129,1132,1139,1140,1153,1156,1159,1165,1166,1173,1174,1179,1192,1193,1229,1230,1231,1232,1236,1237,1243,1245,1247,1249,1250,1260,1266,1267,1274,1280,1281,1285,1294,1304,1305,1306,1309,1311,1315,1320,1323,1325,1327,1328,1344,1345,1349,1350,1355,1358,1360,1362,1363,1382,1383,1386,1387,1391,1392,1398,1399,1413,1414,1419,1422,1424,1426,1427,1431,1433,1436,1438,1440,1443,1450,1457,1460,1463,1466,1469,1472,1475,1478,1481,1484,1487,1490,1493,1496,1499,1502,1515,1518,1519,1522,1525,1527,1529,1535,1536,1540,1543,1546,1547,1550,1551,1555,1556,1562,1563,1587,1590,1591,1592,1603,1604,1606,1607,1610,1611,1614,1615,1618,1619,1622,1623,1626,1627,1630,1631,1632,1633,1657,1660,1662,1665,1666,1680,1682,1704,1777,1789,1801,1802,1804,1805,1808,1809,1814,1820,1823,1824,1829,1830,1833,1834,1841,1843,1851,1852,1856,1858,1859,1864,1865,1868,1869,1875,1882,1883,1901,1922,1923,1924,1925,1931,1943,1956,1965,1971,2001,2006,2009,2010,2011,2012,2017,2023,2024,2037,2039,2040,2043,2044,2047,2048,2051,2052,2055,2056,2071,2079,2085,2086,2147,2150,2151,2164,2166,2167,2170,2171,2181,2182,2188,2190 ./.build/checkouts/swift-llbuild/lib/llvm/Support/IntrusiveRefCntPtr.cpp:9,11,13 ./.build/checkouts/swift-llbuild/lib/llvm/Support/StringRef.cpp:9,15,17,22,27,28,33,34,37,38,47,49,50,58,59,64,65,70,71,87,94,97,101,102,111,112,116,121,123,124,129,131,132,136,137,146,153,154,157,163,168,173,174,176,177,190,192,193,203,208,209,217,218,228,233,234,244,249,250,258,259,269,274,275,280,287,291,295,296,300,312,313,318,319,323,324,328,329,332,334,335,336,344,347,360,365,369,373,375,376,378,379,383,392,393,401,404,405,406,410 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Unix/Unix.h:13,16,21,32,36,40,45,49,53,57,61,77,78 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Allocator.cpp:13,21,23,25,33,34,35,36,43,44,45 ./.build/checkouts/swift-llbuild/lib/llvm/Support/circular_raw_ostream.cpp:13,17,22,23,35,36,37,38,44,45 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Debug.cpp:25,31,33,36,38,44,46,58,60,61,69,70,71,72,75,79,83,85,92,94,95,96,98,100,110,111,117,127,129,131,132,139,140,141,143 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Errno.cpp:13,18,22,27,30,34,36,46,73,74,75,76 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Path.cpp:13,25,31,34,38,46,53,56,63,72,73,77,81,82,88,91,93,98,102,104,105,114,120,127,128,132,134,135,138,140,143,148,151,153,154,155,161,168,176,177,178,185,191,192,202,203,205,206,215,216,223,225,226,228,229,233,240,241,247,248,251,254,259,260,267,279,280,285,286,292,293,294,298,300,301,304,305,308,309,315,316,323,324,335,336,339,344,350,351,355,356,369,377,378,379,383,384,385,387,388,400,404,405,406,409,410,423,428,429,433,434,435,438,439,443,444,453,459,466,471,475,476,480,481,483,484,485,490,491,498,499,504,505,510,515,519,522,523,532,533,545,546,548,549,552,553,565,566,578,579,587,588,589,591,594,595,599,601,602,606,608,609,613,615,616,620,622,623,627,629,630,634,636,637,641,643,644,648,650,651,655,662,664,665,668,669,670,671,673,681,682,687,688,693,694,705,706,713,714,719,720,725,726,727,735,736,739,746,750,755,763,764,772,773,779,784,785,788,789,793,800,806,809,811,812,820,821,834,837,841,845,846,849,850,853,854,857,858,865,866,869,870,877,878,883,884,891,892,899,900,913,918,923,933,948,962,966,968,976,978,996,1010,1012,1023,1029,1037,1039,1044,1047,1049,1050,1055,1060,1063,1064,1067,1068,1069,1070,1071,1072 ./.build/checkouts/swift-llbuild/lib/llvm/Support/raw_ostream.cpp:13,30,35,42,46,59,61,67,70,71,74,78,79,87,88,97,104,106,107,112,116,120,122,123,129,130,132,133,138,142,146,148,149,155,156,158,159,164,168,173,174,176,177,182,200,201,213,214,215,216,218,219,222,224,225,237,242,258,259,260,262,265,266,267,268,274,275,283,287,288,290,291,294,295,303,307,308,310,322,325,326,332,333,335,337,338,341,353,354,356,357,366,371,372,376,377,382,385,388,392,396,397,398,408,409,415,427,428,435,444,454,455,456,457,463,467,473,475,476,477,481,484,485,489,506,507,509,513,514,517,518,531,538,539,545,546,554,561,562,563,567,570,583,584,600,604,605,612,613,621,622,629,630,638,649,650,663,665,666,676,678,679,689,691,692,695,696,699,700,704,713,714,721,722,727,728,729,733,736,737,740,741,745,751,759,760,764,765,771,775,776,786,787,790,791,794,795,799,800,804,812,813,815,816,819 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Atomic.cpp:13,16,18,24,28,41,42,58,59,71,72,84,85,97,98,105,107,108,115,117 ./.build/checkouts/swift-llbuild/lib/llvm/Support/SmallVector.cpp:13,16,25,29,35,36,40 ./.build/checkouts/swift-llbuild/lib/llvm/Support/MathExtras.cpp:13,15,21,23,31,32 ./.build/checkouts/swift-llbuild/lib/llvm/Support/MemoryBuffer.cpp:13,37,41,43,52,53,57,63,64,70,71,75,79,80,87,88,92,93,96,98,99,103,110,111,116,117,127,128,143,146,150,153,154,162,163,168,172,173,178,179,180,184,191,194,195,198,199,202,203,212,213,214,218,219,222,224,225,238,241,243,244,245,251,252,257,265,271,272,285,290,293,294,304,305,312,317,325,327,328,334,344,352,354,356,357,366,367,374,375,377,383,395,399,402,403,405,406,412,413,420,421,428,430,431,436 ./.build/checkouts/swift-llbuild/lib/llvm/Support/ErrorHandling.cpp:14,30,38,40,42,45,47,54,55,60,61,64,65,68,69,72,73,77,83,84,97,98,103,105,106,124,125,131,132,136,137,140,141,143,145,150,204,205,206 ./.build/checkouts/swift-llbuild/lib/llvm/Support/StringExtras.cpp:13,18,30,31,42,45,47,48,58,59 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Hashing.cpp:15,17,19,24,29 ./.build/checkouts/swift-llbuild/lib/llvm/Support/SourceMgr.cpp:15,25,27,34,35,38,39,40,45,46,53,60,61,64,66,67,76,77,83,85,89,92,101,102,107,111,117,121,122,125,128,130,134,135,136,141,148,152,155,162,169,175,179,185,190,191,193,194,198,199,206,207,212,213,215,216,222,223,228,229,233,243,244,249,252,254,260,262,266,275,286,292,297,300,302,310,312,313,314,322,323,329,331,332,335,336,341,344,347,353,358,360,361,378,379,383,384,386,389,392,402,404,407,414,415,422,428,433,435,438,445,446,452,454,457,461,467,468,481,483 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Signals.cpp:14,17,20,25,26,27 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Windows/WindowsSupport.h:16,21,24,28,33,45,57,60,61,66,72,75,79,80,85,86,92,93,97,98,101,103,106,109,110,113,114,117,119,123,125,128,131,132,135,136,139,141,145,147,149,155,159,166,167,172,173,181,182,183,184 ./.build/checkouts/swift-llbuild/lib/llvm/Support/StringMap.cpp:13,19,22,27,28,34,35,42,46,50,51,52,63,67,79,80,83,84,93,100,101,102,105,109,110,111,112,122,129,137,144,145,146,149,153,154,155,163,164,170,176,178,179,180,181,187,198,199,208,223,224,230,236,237,238,240,245 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Threading.cpp:14,20,22,29,30,33,42,43,49,53,58,59,63,66,69,73,78,82,84,85,89,93,102,103,110,111 ./.build/checkouts/swift-llbuild/lib/llvm/Support/ManagedStatic.cpp:13,21,23,30,31,37,40,43,51,55,61,65,66,67,75,78,82,83,87,90 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Unicode.cpp:14,18,22,212,214,215,228,231,311,314,337,341,342,360,362,363,364,365,366,367 ./.build/checkouts/swift-llbuild/lib/llvm/Support/SmallPtrSet.cpp:14,20,22,26,30,35,36,45,50,52,53,62,63,68,75,76,88,89,91,92,96,102,103,116,120,125,128,129,130,136,139,145,153,162,163,166,167,168,172,180,181,184,187,190,191,196,201,210,211,217,218,223,227,243,245,246,249,253,256,257,261,264,272,273,278,284,285,288,296,297,299,312,313,326,327,334,335,339 ./.build/checkouts/swift-llbuild/lib/llvm/Support/Valgrind.cpp:15,18,21,24,25,31,36,37,41,43,44,46,49,50,52,53,55,64,73,74 ./.build/checkouts/swift-llbuild/lib/Basic/FileInfo.cpp:12,14,16,19,22,25,26,34,42,43,60,65,66,68 ./.build/checkouts/swift-llbuild/lib/Basic/Version.cpp:12,14,16,18,21,29,31,32,33 ./.build/checkouts/swift-llbuild/lib/Basic/LaneBasedExecutionQueue.cpp:12,14,16,22,29,31,35,38,44,46,48,52,54,58,61,62,66,71,74,81,84,87,94,96,103,107,108,111,124,127,134,140,142,146,149,153,154,158,163,165,169,173,174,175,176,179,186,187,193,194,195,202,208,209,210,213,217,218,221,222,223,226,230,232,233,234,235,238,243,245,246,248,255,256,258,262,263,264,272,275,279,280,288,289,290,296,300,304,305,314,315,316,321,331,341,343,351,353,365,367,371,375,376,381,382,385,386,389,391,395,399,400,405,406,409,410,413,415,425,426,427,428,429,433,435,442,444,445 ./.build/checkouts/swift-llbuild/lib/Basic/Tracing.cpp:12,14,16,18,19 ./.build/checkouts/swift-llbuild/lib/Basic/FileSystem.cpp:12,16,21,24,30,40,41,43,58,67,69,70,74,78,79,86,90,92,95,98,99,102,107,109,110,112,113,114,117,119,125,131,132,133,137,139,143,149,150,152,153,159,161,162,166,167,172,173,178,183,185,190,191,197,198,199,201,202,205,206,209,211,212,213,216,217,221 ./.build/checkouts/swift-llbuild/lib/Basic/PlatformUtility.cpp:9,15,27,30,39,40,47,48,53,55,73,75,103,114,115,122,123,130,131,138,139,146,147,155,156,163,164,171,172,193,194,201,202,210,211,218,223,228,229,232,233,235,238,239,245,248,257,258,266,267,285,286,293,306,307,316,317,330,331,338 ./.build/checkouts/swift-llbuild/lib/Basic/Subprocess.cpp:12,14,17,24,27,43,46,51,52,55,57,58,63,65,66,68,72,81,92,94,97,99,102,117,118,119,121,122,123,126,127,130,131,137,138,139,141,142,143,149,150,151,154,160,168,169,170,171,180,184,186,189,202,204,205,209,210,212,219,222,228,229,233,236,237,240,242,243,246,261,262,265,268,272,273,290,299,314,315,329,338,343,346,361,362,371,374,383,384,398,400,407,408,421,431,434,439,450,455,466,475,478,482,491,497,499,503,509,510,515,521,522,531,532,538,545,557,564,565,576,577,581,589,591,598,599,613,614,615,619,624,628,630,635,640,647,648,649,654,656,658,677,678,698,699,700,701,709,710,715,716,720,724,725,744,752,767,776,777,778,781,782,789,794,795,801,811,812,823,826,827,836,841,847,848,849,857,861,862,864,865,875,880,881,888,891 ./.build/checkouts/swift-llbuild/lib/Basic/ExecutionQueue.cpp:12,14,18,21,24,25,27,28,30,31,34,35,36,38,39,52,53,64,65,67,68,69 ./.build/checkouts/swift-llbuild/lib/Basic/Hashing.cpp:12,14,16,18,21,24,25,26,27 ./.build/checkouts/swift-llbuild/lib/Basic/ShellUtility.cpp:12,15,18,20,23,28,29,38,39,48,49,51,52,59,60,61,62 ./.build/checkouts/swift-llbuild/lib/Basic/LeanWindows.h:12,15,19,23 ./.build/checkouts/swift-llbuild/lib/Basic/SerialQueue.cpp:12,14,16,22,25,27,36,39,42,45,51,53,57,58,61,62,66,69,70,71,76,77,83,84,88,91,92,95,103,107,109,114,115,116,119,122,124,125,126,129,130,131,134,135,138,139,142 ./.build/checkouts/swift-llbuild/lib/Ninja/ManifestLoader.cpp:12,14,19,23,26,29,31,33,34,36,38,52,60,65,71,75,76,77,81,85,90,92,93,104,110,112,113,116,117,122,126,130,131,145,146,150,154,160,161,169,170,176,177,191,192,202,205,206,210,212,214,215,225,226,230,231,232,238,247,248,251,253,256,257,259,262,263,268,272,274,275,280,285,286,288,289,290,295,302,310,311,312,313,321,327,332,333,343,345,352,354,355,359,361,362,367,369,372,377,379,380,391,395,397,406,415,417,418,423,432,433,435,444,445,449,461,464,472,488,490,497,502,503,504,513,514,515,519,523,525,526,529,532,537,538,543,544,549,551,555,562,565,566,567,571,575,576,577,580,583,588,589,594,595,600,608,609,610,614,617,618,619,622,623,624,626,630,631,632,635,636,640,642,643,646 ./.build/checkouts/swift-llbuild/lib/Ninja/Lexer.cpp:12,14,16,21,24,26,47,49,51,52,58,60,62,66,67,68,70,71,76,77,81,89,90,96,97,99,100,105,106,115,116,117,127,132,139,144,145,147,148,153,154,158,161,162,165,166,172,176,179,184,185,187,188,192,194,195,197,198,203,209,210,214,216,217,219,220,235,239,241,242,243,256,261,262,264,265,270,275,278,286,287,293,297,298,303,305,306,310,312,313 ./.build/checkouts/swift-llbuild/lib/Ninja/Manifest.cpp:12,14,16,19,30,31,37,41,42,48 ./.build/checkouts/swift-llbuild/lib/Ninja/Parser.cpp:12,14,17,20,22,24,25,27,29,33,36,39,42,43,46,47,49,54,55,59,60,68,69,78,79,80,86,89,90,93,105,110,114,118,120,124,127,128,129,134,139,141,143,144,153,159,163,168,172,176,177,178,186,187,189,195,196,205,214,215,221,222,224,230,231,233,234,240,241,247,252,253,256,261,262,267,268,270,271,280,284,285,287,291,292,294,295,322,323,330,332,333,341,348,349,364,365,366,367,379,380,381,388,394,399,405,406,412,417,419,424,426,431,432,434,439,440,441,444,448,449,452,454,455,462,466,467,469,473,474,476,478,479,486,490,491,493,497,498,500,502,503,504,505,507,511,512,513,516,517,521,523,524,527 ./.build/checkouts/swift-llbuild/lib/Commands/CommandLineStatusOutput.h:12,15,17,20,25,28,30,33,36,39,44,47,53,56,62,63,64,65 ./.build/checkouts/swift-llbuild/lib/Commands/CommandLineStatusOutput.cpp:12,14,16,19,21,25,28,31,34,37,39,44,45,46,49,50,54,60,66,67,68,70,71,76,77,81,82,86,87,91,98,99,100,103,107,108,110,111,116,120,134,136,138,139,144,145,148,154,155,156,160,164,167,169,170,171,174,177,178,179,182,183,186,187,190,191,195,196,199,200,204,205,209,210,213,214,218,219,220,221 ./.build/checkouts/swift-llbuild/lib/Commands/NinjaCommand.cpp:12,14,21,24,29,33,45,46,48,51,56,57,65,66,71,74,78,86,88,90,91,93,95,101,104,108,109,113,114,116,117,120,121,124,125,132,133,142,144,145,152,153,169,177,181,182,190,191,196,197,203,204,212,213,218,219,225,226,234,235,240,242,243,244,246,248,251,254,258,259,261,263,265,268,270,273,281,282,285,288,291,292,295,298,301,302,305,309,310,311,318,319,327,328,338,339,341,342,344,346,351,355,356,361,363,364,374,383,384,387,389,390,391,398,399,411,413,414,418,422,426,433,438,440,447,456,458,459,460,466,473,478,483,485,486,502,512,515,517,523,535,536,541,544,545,547,548,562,564,565,567,568,570,575,607,608 ./.build/checkouts/swift-llbuild/lib/Commands/NinjaBuildCommand.cpp:12,14,23,25,29,31,35,38,49,60,64,68,70,74,75,82,83,87,88,90,91,98,99,146,147,149,157,160,165,168,171,174,178,181,184,189,193,196,201,202,206,208,212,216,217,218,224,228,229,230,233,236,241,249,252,255,256,261,265,266,269,270,275,276,283,284,294,295,296,300,301,306,317,318,320,321,335,336,338,341,343,345,348,354,357,360,372,375,378,381,390,393,403,405,408,411,415,418,425,428,431,435,439,440,443,448,451,456,457,462,467,468,469,477,481,484,485,489,490,495,502,503,506,515,521,523,524,528,535,539,543,544,547,556,561,562,563,571,572,586,587,595,596,602,603,607,608,612,613,619,620,623,624,630,631,633,636,642,646,651,661,669,670,676,679,680,683,684,686,692,693,697,704,705,707,710,716,720,721,726,728,729,739,747,748,751,754,757,763,767,771,775,779,782,792,793,798,802,809,811,816,825,826,827,828,829,835,836,839,840,849,858,860,865,867,868,874,876,877,878,882,886,887,888,902,905,906,907,912,916,920,941,942,943,945,946,951,952,961,969,970,971,973,974,984,987,992,994,995,996,997,999,1001,1008,1009,1016,1019,1020,1022,1024,1035,1046,1047,1049,1060,1063,1064,1074,1079,1081,1082,1091,1098,1099,1104,1105,1123,1125,1126,1137,1146,1147,1153,1154,1163,1165,1166,1167,1176,1188,1193,1194,1204,1208,1214,1215,1221,1222,1227,1231,1232,1233,1236,1238,1240,1241,1246,1249,1252,1254,1260,1261,1266,1267,1270,1272,1274,1275,1282,1286,1290,1294,1295,1296,1302,1303,1304,1310,1312,1314,1315,1326,1332,1336,1337,1341,1342,1347,1358,1363,1371,1372,1374,1377,1378,1382,1386,1398,1400,1401,1405,1409,1415,1416,1423,1430,1431,1433,1434,1438,1442,1448,1451,1452,1459,1472,1473,1474,1478,1485,1496,1499,1500,1513,1514,1517,1520,1521,1525,1528,1529,1530,1537,1549,1554,1555,1559,1562,1579,1589,1597,1605,1613,1620,1627,1634,1641,1648,1655,1665,1674,1682,1692,1700,1708,1717,1718,1719,1723,1724,1728,1729,1736,1737,1743,1744,1750,1760,1761,1765,1766,1768,1769,1770,1779,1785,1793,1794,1796,1799,1804,1809,1810,1820,1822,1823,1828,1829,1830,1832,1833,1835,1838,1849,1850,1851,1858,1859,1860,1877,1884,1885,1887,1896,1897,1910,1916,1931,1934,1935,1936,1940,1944,1945,1951,1952,1960,1961,1963,1964,1969,1973,1978,1979,1980,1986,1987,1988,1989,1990,1991,1996,1997,2015,2019,2020,2023,2024,2028,2032,2033,2045,2053,2054,2059,2060,2064,2065,2070,2071,2076,2077,2080 ./.build/checkouts/swift-llbuild/lib/Commands/BuildEngineCommand.cpp:12,14,17,19,28,31,33,35,40,49,58,62,64,66,73,81,82,87,90,102,103,109,111,115,118,121,124,128,129,133,135,140,143,144,154,155,156,162,166,170,171,172,178,179,184,185,188,190,197,203,210,211,216,217,221,225,233,234,235,244,246,249,250,256,257,259,260,275,276,283,286,294,301,308,316,323,324,325,329,330,337,344,345,350,351,356,357,359,360,361,362,364,373,374,379,386,387 ./.build/checkouts/swift-llbuild/lib/Commands/BuildSystemCommand.cpp:12,14,23,29,31,34,41,46,48,50,56,62,64,68,69,71,73,77,81,83,86,88,91,95,98,102,107,109,118,120,122,131,133,135,137,140,144,147,148,151,152,157,158,159,168,170,171,172,181,183,184,185,190,192,201,203,205,214,216,218,219,223,226,236,238,241,245,250,252,261,263,265,274,276,278,279,285,286,288,290,293,294,304,305,306,318,319,320,322,323,328,329,331,332,337,344,346,347,348,352,353,354,361,362,363,365,366,371,372,373,384,385,388,392,395,404,405,406,411,412,414,420,422,423,424,426,429,436,439,442,446,450,451,456,462,463,464,472,476,479,480,484,485,501,507,511,512,520,524,525,529,532,533,537,538,542,544,547,555,556,560,563,568,574,575,580,581,585,595,596,598,599,601,602,603,604,606,616,617,622,632,633 ./.build/checkouts/swift-llbuild/lib/Commands/CommandUtil.h:12,15,17,19,23,26,29,30,31,35,37,39,42,46,51,52,53,54,55 ./.build/checkouts/swift-llbuild/lib/Commands/NinjaBuildCommand.h:12,15,18,21,23,24,25,26 ./.build/checkouts/swift-llbuild/lib/Commands/CommandUtil.cpp:12,15,19,22,24,27,29,33,34,38,40,41,44,45,61,62,65,68,69,77,90,91,92,93,96,100,104,112,115,125,127,128,133,134,139,140,152,153,157,167,168,170,171,174,177 ./.build/checkouts/swift-package-manager/Tests/FunctionalPerformanceTests/BuildPerfTests.swift:3,6,10,17,19,24,25,28,29,32,33,36,37,40,41,44,45,55,56,57,58,67,68,69,70 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/StringConversionsPerfTests.swift:3,6,10,12,15,25,26,28,29,30 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/PathPerfTests.swift:3,6,10,12,15,17,28,30,31,32,34 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/SHA256PerfTests.swift:3,6,10,12,15,22,26,27,28,29 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/ByteStringPerfTests.swift:3,6,10,12,15,27,28,30,31,32 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/OutputByteStreamPerfTests.swift:3,6,10,12,15,16,19,22,23,24,28,29,30,37,42,43,44,46,54,56,57,58,59,67,69,70,71,72,79,81,82,83,84,88,94,96,97,98,99,105,111,113,114,115,116,120,126,128,129,130,131,135,141,143,144,145,146,150,156,158,159,160,161,165,171,173,174,175,176,182,191,194,196,197,198,199,206,211,216,222,223,224,225 ./.build/checkouts/swift-package-manager/Tests/BasicPerformanceTests/SortedArrayPerfTests.swift:3,6,10,13,20,21,22,23,26,31,32,33,34,37,41,42,43,46,51,52,53,54 ./.build/checkouts/swift-package-manager/Tests/SPMPackageEditorTests/AddTargetDependencyTests.swift:3,6,10,12,14,20,42,50,54,76,77,103,115,140,141,142 ./.build/checkouts/swift-package-manager/Tests/SPMPackageEditorTests/PackageEditorTests.swift:3,6,10,14,16,22,41,48,51,55,59,60,63,68,93,96,97 ./.build/checkouts/swift-package-manager/Tests/SPMPackageEditorTests/AddPackageDependencyTests.swift:3,6,10,12,14,20,35,36,42,46,62,63,74,75,81,93,94,108,109,115,129,130,140,141,147,159,160,174,175,181,193,194,200,211,212,218,223,235,236 ./.build/checkouts/swift-package-manager/Tests/SPMPackageEditorTests/AddTargetTests.swift:3,6,10,12,14,20,39,44,48,73,74 ./.build/checkouts/swift-package-manager/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift:3,6,10,12,18,20,22,25,27,53,54,55,56,61,74,75,78,83,90,91,97,101,107,112,113,114,115,116,121,124,130,131,132,133,138,141,147,148,149,150,155,158,164,165,166,167,172,175,181,182,183,184,191,192,193,194,201,202,203,204,205,207,210,211,214,215,218,219,222,223,227,233,234,235,236,242,243,244,281,287,290,291,296,316,317,320,321,333,334,337,338,341,342,344,345,346 ./.build/checkouts/swift-package-manager/Tests/PackageGraphPerformanceTests/PackageGraphPerfTests.swift:3,6,10,12,17,19,24,30,41,60,61,62,72,73,74 ./.build/checkouts/swift-package-manager/Tests/LinuxMain.swift:2,17,33 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/XcodeProjectModelTests.swift:3,6,10,15,17,24,31,35,39,44,47,54,60,67,71,74,76,77,81,86,92,100,106,108,109,113,118,123,129,137,142,151,153,154,158,163,165,167,168,172,177,182,185,187,188,192,196,206,207 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/PackageGraphTests.swift:3,6,10,12,18,35,74,76,78,81,104,106,115,119,123,130,131,141,142,154,155,167,168,174,175,184,185,186,187,192,209,215,219,220,221,222,232,248,261,264,265,266,267,274,290,292,302,310,318,319,320,321,329,336,350,359,366,368,372,376,379,380,388,403,406,410,411,412,413,414,415,418,419,423,427,428,431,432,436,438,439,442,443,448,451,454,455,458,459,462,463,464,465,471,475,478,480,481,482,487,489 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/FunctionalTests.swift:3,6,10,12,19,30,32,33,43,49,51,52,61,76,84,86,87,99,101,102,108,111,123,125,126,127,132,133,140,143,147,153,154,157,159,170,171,172,173,180,181 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/PropertyListTests.swift:3,6,10,13,19,20 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/XCTestManifests.swift:3,15,16,32,33,46,47,55,56,66,67,80,81,91 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/XcodeProjectModelSerializationTests.swift:3,6,10,15,17,21,24,29,31,34,39,41,46,48,53,55,60,62,67,69,74,76,77,79,82,85,88,91,94,99,100,108,109,113,115,119,120,125,127,129,133,134,139,141,143,144,146,149,152,155,160,161,165,166,170,171,176,178,180,181 ./.build/checkouts/swift-package-manager/Tests/XcodeprojTests/GenerateXcodeprojTests.swift:3,6,10,19,27,28,33,47,51,54,59,64,68,70,74,76,77,93,103,104,105,111,125,131,134,135,138,144,159,163,165,166,167,170,176,178,193,197,199,200,201,204,210,212,227,231,233,236,237,238,241,247,249,264,268,272,274,275,276,279,282,285,291,306,310,313,316,317,318 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/ToolsVersionTests.swift:3,6,10,12,20,22,26,32,47,52,57,65,69,81,88,91,97,101,107,108,119,122,128,129,139,143,144,145 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/ModuleMapTests.swift:3,6,10,17,19,27,32,34,35,36,39,41,47,48,49,52,54,62,64,65,68,69,70 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/SwiftPMXCTestHelperTests.swift:3,6,10,17,42,44,45,46,47,56,61,62 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/MiscellaneousTests.swift:3,6,10,19,21,23,25,28,33,34,35,37,40,47,48,49,51,55,60,61,62,75,78,80,81,95,98,99,101,102,103,108,109,110,118,122,126,128,132,133,134,142,147,151,155,159,160,161,169,174,178,182,186,187,188,193,194,195,205,207,208,218,219,229,230,243,244,249,251,252,258,260,261,266,268,269,277,279,292,295,299,301,302,303,308,311,313,321,324,327,334,335,340,343,347,350,355,357,358,363,366,368,374,375,376,382,387,389,392,394,396,402,410,411,420,421,427,429,431,433,434 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/XCTestManifests.swift:3,15,16,28,29,54,55,64,65,73,74,82,83,91,92,103 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/VersionSpecificTests.swift:3,6,10,12,16,18,24,30,46,50,58,63,68,85,88,95,96,112,116,120,121,122 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/CFamilyTargetTests.swift:3,6,10,19,21,27,30,32,33,35,42,43,44,54,55,56,65,66,67,74,75,76,85,87,88 ./.build/checkouts/swift-package-manager/Tests/FunctionalTests/DependencyResolutionTests.swift:3,6,10,12,18,23,26,27,28,32,33,34,38,41,42,43,51,52,58,59,60,66,67,68 ./.build/checkouts/swift-package-manager/Tests/POSIXTests/EnvTests.swift:3,6,10,12,15,19,20,23,24,33,34,41,47,51,53,54 ./.build/checkouts/swift-package-manager/Tests/POSIXTests/PosixTests.swift:3,6,10,12,14,17,19,21,23,29,33,38,39,40 ./.build/checkouts/swift-package-manager/Tests/POSIXTests/ReaddirTests.swift:3,6,10,12,14,18,19,20,30,32,33,41,43,44,52,54,56,57,58 ./.build/checkouts/swift-package-manager/Tests/POSIXTests/XCTestManifests.swift:3,13,14,22,23,31,32,40,41,49 ./.build/checkouts/swift-package-manager/Tests/POSIXTests/usleep.swift:3,6,10,12,15,17,24,26,27 ./.build/checkouts/swift-package-manager/Tests/BasicTests/SHA256Tests.swift:3,6,10,12,14,16,25,29,30,36,38,39,44,45 ./.build/checkouts/swift-package-manager/Tests/BasicTests/EditDistanceTests.swift:3,6,10,12,14,16,24,25 ./.build/checkouts/swift-package-manager/Tests/BasicTests/TemporaryFileTests.swift:3,6,10,12,14,16,25,28,35,41,43,46,47,52,55,62,68,70,75,76,88,91,94,95,103,105,114,119,127,129,130,143,146,147,157,160,161 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ObjectIdentifierProtocolTests.swift:3,6,10,12,14,19,20,21,23,25,32,36,40,44,48,51,52 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ProcessSetTests.swift:3,6,10,16,20,21,24,25,28,29,32,35,39,50,54,60,63,64,66,70,71,73,75,76 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ThreadTests.swift:3,6,10,12,14,16,18,21,24,25,28,30,31,35,38,39,42,43,48,51,52,56,61,63,67,68,69,71,72 ./.build/checkouts/swift-package-manager/Tests/BasicTests/RegExTests.swift:3,6,10,13,15,21,22,27,28 ./.build/checkouts/swift-package-manager/Tests/BasicTests/LockTests.swift:3,6,10,12,15,25,26,28,29,35,43,44,47,49,50 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ResultTests.swift:3,6,10,12,15,18,19,23,24,26,28,32,34,41,42,49,50,57,61,63,64,68,70,71,76,78,79,86,87,94,95,102,109,110,111,116,122,123,124,125,128,131,132,133,138,140,141,146,148,153,156,157,162,165,166,167,170,173,174,180,181,184,185,189,190,191,192,201,202 ./.build/checkouts/swift-package-manager/Tests/BasicTests/DeltaAlgorithmTests.swift:3,6,10,12,14,16,19,26,28,29,35,37,38,44,46,47,48 ./.build/checkouts/swift-package-manager/Tests/BasicTests/CollectionAlgorithmsTests.swift:3,6,10,12,14,20,21 ./.build/checkouts/swift-package-manager/Tests/BasicTests/JSONTests.swift:3,6,10,12,14,20,21,29,30,35,36,48,49,54,55,61,66,74,76,79,83,86,94,95,97,98 ./.build/checkouts/swift-package-manager/Tests/BasicTests/KeyedPairTests.swift:3,6,10,12,14,22,25,26,27,31,33,34,41,43,44 ./.build/checkouts/swift-package-manager/Tests/BasicTests/POSIXTests.swift:3,6,10,12,14,16,22,27,35,44,45 ./.build/checkouts/swift-package-manager/Tests/BasicTests/DictionaryExtensionsTests.swift:3,6,10,13,15,19,22,24,25,29,30 ./.build/checkouts/swift-package-manager/Tests/BasicTests/AwaitTests.swift:3,6,10,13,15,17,20,21,25,26,27,31,32,33,37,43,44,45 ./.build/checkouts/swift-package-manager/Tests/BasicTests/CacheableSequenceTests.swift:3,6,10,12,14,22,23 ./.build/checkouts/swift-package-manager/Tests/BasicTests/PathShimTests.swift:3,6,10,13,16,18,22,27,31,34,37,40,43,46,47,51,55,58,61,62,67,68,69,71,81,83,85,86,96,97,99,100,105,109,113,115,117,118,122,127,129,131,135,137,138 ./.build/checkouts/swift-package-manager/Tests/BasicTests/DictionaryLiteralExtensionsTests.swift:3,6,10,13,15,19,20,24,29,30 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ProcessTests.swift:3,6,10,14,16,19,23,24,33,34,40,41,42,46,55,56,61,62,68,69,70,75,78,84,86,89,90,91,92,100,102,110,111,112,113,114,116,125,134,135,144,155,161,162,163,167,170,173,174,177,178,183,186,187,194,195,202,203,210,211,212 ./.build/checkouts/swift-package-manager/Tests/BasicTests/XCTestManifests.swift:3,11,12,25,26,34,35,43,44,52,53,61,62,72,73,81,82,92,93,102,103,112,113,121,122,141,142,152,153,162,163,174,175,183,184,192,193,202,203,211,212,220,221,229,230,245,246,254,255,265,266,293,294,303,304,319,320,329,330,342,343,352,353,365,366,375,376,386,387,400,401,409,410,420,421,429,430,441,442,452,453,497 ./.build/checkouts/swift-package-manager/Tests/BasicTests/TupleTests.swift:3,6,10,12,14,16,20,23,24 ./.build/checkouts/swift-package-manager/Tests/BasicTests/PathTests.swift:3,6,10,13,16,18,27,28,43,44,52,53,59,60,66,67,73,74,89,90,118,119,135,136,151,152,176,177,184,185,195,204,209,218,219,229,246,247,256,257,265,266,274,275,278,281,282,285,286,287,290,293,294,297,298,299,303,304,307,308,314,315,323,324,330,331,339,340,341,343,345,347 ./.build/checkouts/swift-package-manager/Tests/BasicTests/miscTests.swift:3,6,10,14,16,19,25,27,31,35,39,47,48,49,54,55,60,63,64 ./.build/checkouts/swift-package-manager/Tests/BasicTests/OutputByteStreamTests.swift:3,6,10,12,14,18,25,28,32,33,36,38,41,42,48,52,56,60,61,62,69,77,82,86,90,91,97,98,103,104,109,110,115,119,120,125,126,131,135,136,141,145,149,153,154,155,158,161,162,167,170,172,173,176,178,181,182,188,189,192,195,199,200,202,206,207,209,212,214,215 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ConditionTests.swift:3,6,10,13,15,26,27,29,32,36,38,41,42,53,54,57,58,61,65,67,71,72,77,84,85,86,88,93,95,96 ./.build/checkouts/swift-package-manager/Tests/BasicTests/ByteStringTests.swift:3,6,10,12,14,19,20,21,27,28,30,32,35,36,41,42,46,47,50,51,57,63,64,69,70 ./.build/checkouts/swift-package-manager/Tests/BasicTests/FileSystemTests.swift:3,6,10,12,17,19,21,24,28,38,48,56,65,69,73,78,79,83,87,89,94,96,101,103,108,109,110,113,121,122,129,130,131,134,143,154,159,163,167,170,172,176,179,181,185,188,190,195,198,200,201,205,206,207,209,212,215,218,221,224,228,229,237,238,245,249,253,259,265,267,274,277,279,280,284,295,299,303,306,308,312,315,318,322,325,327,332,335,337,338,345,349,352,353,357,358,359,361,367,370,376,381,382,387,391,395,400,401,406,409,414,415,420,426,428,429,430,443,451 ./.build/checkouts/swift-package-manager/Tests/BasicTests/GraphAlgorithmsTests.swift:3,6,10,12,14,16,19,22,23,26,29,30,33,34,41,51,55,56,61,71,75,76,86,89,91,92,93,97,100,101,105,106 ./.build/checkouts/swift-package-manager/Tests/BasicTests/CStringArrayTests.swift:3,6,10,13,21,22 ./.build/checkouts/swift-package-manager/Tests/BasicTests/SortedArrayTests.swift:3,6,10,12,14,16,27,30,33,36,39,42,43,54,57,60,63,66,67,71,74,77,78,83,86,89,90,94,95 ./.build/checkouts/swift-package-manager/Tests/BasicTests/SynchronizedQueueTests.swift:3,6,10,12,14,20,24,26,27,31,32,33,38,40,41,44,47,50,56,58,59,60,67,68,69,70,71,77,80,81,82,87,90,92,96,105,109,110,112,113,114,123,124,125,126,127,133,136,137 ./.build/checkouts/swift-package-manager/Tests/BasicTests/LazyCacheTests.swift:3,6,10,12,14,19,25,26,27,28,36,37,38,39 ./.build/checkouts/swift-package-manager/Tests/BasicTests/TerminalControllerTests.swift:3,6,10,15,21,22,26,30,34,38,42,46,47 ./.build/checkouts/swift-package-manager/Tests/BasicTests/JSONMapperTests.swift:3,6,10,13,17,21,22,28,29,33,34,37,38,39,48,57,58,69,70,79,80,81,83,98,99,107,108,115,116,123,124,133,134,142,143,144 ./.build/checkouts/swift-package-manager/Tests/BasicTests/OrderedDictionaryTests.swift:3,6,10,12,14,19,22,25,28,29 ./.build/checkouts/swift-package-manager/Tests/BasicTests/CollectionExtensionsTests.swift:3,6,10,13,19,20 ./.build/checkouts/swift-package-manager/Tests/BasicTests/OrderedSetTests.swift:3,6,10,12,14,16,23,32,39,46,52,53 ./.build/checkouts/swift-package-manager/Tests/BasicTests/StringConversionsTests.swift:3,6,10,13,15,17,20,23,27,30,33,36,39,40,44,47,48 ./.build/checkouts/swift-package-manager/Tests/BasicTests/DiagnosticsEngineTests.swift:3,6,10,12,14,22,24,26,29,30,31,43,45,49,50,53,56,57,58,67,72,76,84,85,87,88,96,107,111,112,117,118,127,131,135,136 ./.build/checkouts/swift-package-manager/Tests/BuildTests/IncrementalBuildTests.swift:3,6,10,12,17,18,39,44,49,51,59,62,66,69,74,77,80,81,82,85 ./.build/checkouts/swift-package-manager/Tests/BuildTests/XCTestManifests.swift:3,34,35,43,44,57,58,65 ./.build/checkouts/swift-package-manager/Tests/BuildTests/BuildPlanTests.swift:3,6,10,12,18,20,40,52,53,60,61,62,64,68,69,87,88,94,109,114,117,120,123,141,143,144,154,183,188,200,201,206,220,222,225,228,244,245,255,283,285,288,291,297,304,307,313,321,337,343,345,346,354,371,374,377,393,401,402,403,410,425,429,432,438,445,448,464,465,473,490,494,500,501,513,544,547,550,551,558,573,582,585,588,605,606,612,633,637,639,655,656,663,678,683,689,690,696,723,727,730,738,752,761,762,763,769,787,792,795,798,801,817,819,820,827,845,851,854,863,872,875,881,882,890,933,938,943,946,947,952,964,969,970,971,977,999,1002,1004,1005,1011,1029,1032,1034,1038,1039,1046,1062,1066,1073,1076,1083,1084,1091,1106,1109,1112,1118,1121,1122,1126,1127,1133,1168,1173,1180,1187,1193,1230,1236,1237,1240,1241,1242,1250,1255,1270,1273,1297,1299,1323,1329,1336,1337,1340,1343,1346,1349,1352,1355,1356,1359,1362,1365,1368,1371,1372,1373,1379,1389,1395,1403,1406,1407,1408,1410,1413,1414,1416,1420,1425,1426,1429,1430,1433,1434,1438,1440,1441,1446,1448,1449,1450,1458,1459,1460,1467,1468,1469 ./.build/checkouts/swift-package-manager/Tests/BuildTests/SwiftCompilerOutputParserTests.swift:3,6,10,13,17,20,21,24,25,37,38,39,44,47,50,53,59,62,65,68,71,74,76,87,89,95,102,104,106,113,116,119,121,128,131,134,153,155,156,162,163,170,171,175,178,181,187,190,191,195,198,201,204,210,213,214,218,221,226,229,235,238,239,243,246,248,251,254,260,263,264,268,271,277,280,283,289,292,293 ./.build/checkouts/swift-package-manager/Tests/TestSupportTests/TestSupportTests.swift:3,6,10,12,14,19,23,28,33,37,38 ./.build/checkouts/swift-package-manager/Tests/TestSupportTests/XCTestManifests.swift:3,11,12,17 ./.build/checkouts/swift-package-manager/Tests/PackageGraphTests/PackageGraphTests.swift:3,6,10,12,17,19,29,70,79,80,81,88,116,123,124,125,132,168,170,171,178,194,196,197,207,235,241,242,243,249,272,274,275,283,331,334,335,336,344,392,396,397,398,406,461,464,465,466,472,498,502,503,504,509,522,525,526,527,535,583,586,587,588,594,614,617,618,627,669,672,673,674,681,718,720,721,730,772,777,778,779 ./.build/checkouts/swift-package-manager/Tests/PackageGraphTests/PubgrubTests.swift:3,6,10,12,18,20,22,24,26,28,30,32,35,38,39,43,44,48,49,55,56,59,60,63,64,74,76,77,86,87,88,91,92,95,98,102,103,112,113,114,115,118,120,122,125,126,133,135,147,149,150,154,155,159,161,162,167,169,170,174,175,179,187,188,189,190,191,194,208,212,216,219,220,221,227,228,231,237,239,244,247,251,252,258,263,268,272,276,278,282,286,287,302,307,312,317,318,324,329,330,339,345,346,357,364,365,374,377,378,383,389,399,400,407,412,413,420,427,428,436,444,445,448,453,458,459,463,469,470,474,477,478,484,490,492,495,502,503,514,517,519,531,532,533,549,552,554,566,567,568,586,589,591,602,603,604,607,610,616,621,631,632,639,643,644,653,656,658,664,665,666,674,700,704,707,709,721,722,723,727,736,739,741,744,745,746,753,771,774,776,779,780,781,782,786,791,792,795,810,811,813,817,818,819,824,825,828,829 ./.build/checkouts/swift-package-manager/Tests/PackageGraphTests/XCTestManifests.swift:3,26,27,50,51,79,80,93,94,102 ./.build/checkouts/swift-package-manager/Tests/PackageGraphTests/DependencyResolverTests.swift:3,6,10,12,16,18,20,23,25,27,32,46,58,64,65,70,81,82,85,88,95,98,109,110,120,126,134,139,144,148,154,165,167,174,179,180,184,195,204,210,220,221,230,238,239,241,248,249,260,265,266,287,295,296,297,303,311,318,324,325,326,327,331,333,343,348,349,350,361,362,368,374,380,381,382,385,395,401,410,419,420,421,435,436,442,452,453,457,472,473,474,483,484,485,486,490,492,499,504,512,523,524,525,528,535,542,548,549,550,559,562,563,567,576,579,589,600,609,610,626,634,644,645,657,662,663,670,671,681,682,694,695,705,706,712,713,714,734,744,745,758,759,770,771,772,780,787,788,789,790,806,813,814,817,824,825,826,841,846,847,849,854,859,866,867,868,870,872,879,888,889,890,891,897,898,905,906,911,915,919,920,921,922,929,930,941,942,943,944,946,947,961,974,977,978,980,981,982,991,992,993,997,1002,1003,1005,1006,1012,1022,1023,1025,1026,1032,1038,1040,1044,1045,1046,1052,1056,1059,1060,1061,1068,1075,1076,1077,1078,1085,1094,1095 ./.build/checkouts/swift-package-manager/Tests/PackageGraphTests/RepositoryPackageContainerProviderTests.swift:3,6,10,12,18,20,24,27,29,34,35,38,39,42,43,46,47,51,52,55,56,59,60,63,64,67,68,73,74,75,79,82,91,92,93,96,97,101,102,105,106,109,110,113,114,117,118,119,122,124,127,128,130,131,132,138,147,148,151,152,153,158,162,164,169,180,181,213,223,225,231,232,235,238,249,252,260,268,269,272,275,278,280,284,288,292,296,299,307,313,314,321,322,331,332,339,340,341,344,347,360,363,371,379,380,383,386,398,401,409,417,418 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingPerformanceTests/ManifestLoadingTests.swift:3,6,10,12,16,19,25,26,27,39,40,41,42,43,59,65,66,67,68,69 ./.build/checkouts/swift-package-manager/Tests/PackageDescription4Tests/VersionTests.swift:3,6,10,13,15,23,25,26,27 ./.build/checkouts/swift-package-manager/Tests/PackageDescription4Tests/XCTestManifests.swift:3,11,12,17 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/ProgressAnimationTests.swift:3,6,10,16,18,23,33,35,38,41,42,47,48,53,54,58,67,69,72,75,76,81,82,93,97,98,100,101,106,107,112,113,114,118,122,124,125,129,130,132,133 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/VersionTests.swift:3,6,10,13,15,33,34,35,36,37,44,48,49,58,59,68,69,76,77,87,92,93,102,107,108,117,122,123,133,138,139,146,154,159,161,162,163,164,173,174,181,182,190,191,199,200,210,211,212,216,221,226,227,230,236,241,242,251,256,257,262,270,271,278,286,287,288 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/StringConversionTests.swift:3,6,10,13,15,21,22,24,27,32,36,42,47,51,55,56 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/StringTests.swift:3,6,10,13,21,22,27,28,33,34,43,44,49,50,56,57,58,68,69 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/CollectionTests.swift:3,6,10,13,15,17,21,22,28,29,30 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/InterruptHandlerTests.swift:3,6,10,16,28,32,34,35 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/XCTestManifests.swift:3,24,25,33,34,42,43,58,59,70,71,81,82,91,92,104,105,113,114,129,130,139,140,155 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/miscTests.swift:3,6,10,15,20,23,26,29,30,39,44,45,46 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/SimplePersistenceTests.swift:3,6,10,14,16,21,31,32,36,37,45,46,47,53,54,57,58,61,62,63,68,76,77,80,81,86,87,88,93,102,103,107,108,114,115,116,117,125,131,137,141,148,149,150,153,156,160,166,170,174,180,181,187,192,193,195,196,200,203,206,207 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/PkgConfigParserTests.swift:3,6,10,14,16,18,34,35,36,43,44,45,52,53,54,61,62,63,70,71,72,76,86,89,90,91,96,105,108,109,111,112,119,120,121,127,128 ./.build/checkouts/swift-package-manager/Tests/UtilityTests/ArgumentParserTests.swift:3,6,10,15,19,20,27,28,29,34,42,43,45,48,60,73,88,97,98,104,111,112,118,119,125,126,132,133,140,141,149,150,157,158,159,162,165,166,170,172,173,178,187,188,199,200,201,202,206,210,218,222,226,230,235,237,240,249,250,255,257,260,263,270,272,280,285,286,291,292,297,298,303,304,308,317,321,327,331,336,337,340,343,347,349,354,356,361,366,367,372,373,378,379,380,382,387,390,391,394,398,401,405,407,410,413,414,417,420,425,426,431,432,436,438,445,452,453,460,461,462,469,470,476,477,483,484,489,490,491,494,497,506,522,523,524,526,543,544,545,547,548,551,555,557,561,563,567,572,577,582,587,588,591,595,600,604,609,613,618,619,623,629,630,637,638,641,644,647,650,653,660,661,664,667,668,672,678,679,686,687,694,695,698,701,704,707,714,715,721,722,725,726 ./.build/checkouts/swift-package-manager/Tests/WorkspaceTests/InitTests.swift:3,6,10,17,19,21,28,34,36,39,50,51,52,59,65,67,70,71,78,83,88,94,95,96,103,109,111,114,121,126,131,135,136,137,144,150,152,155,165,166,167,169,173,179,183,185,189,190,194,198,202,208,209,210,221,222 ./.build/checkouts/swift-package-manager/Tests/WorkspaceTests/ToolsVersionWriterTests.swift:3,6,10,12,16,18,23,26,27,31,34,35,39,42,43,48,51,52,57,60,61,66,69,70,75,78,79,84,88,89,94,95,96,101,102,110,112,115,118,122,123,124 ./.build/checkouts/swift-package-manager/Tests/WorkspaceTests/PinsStoreTests.swift:3,6,10,12,20,22,24,33,38,45,48,50,62,63,69,72,78,84,85,91,97,98,99,103,106,109,116,118,125,126,130,132,133,136,137,142,145,149,151,154,158,159 ./.build/checkouts/swift-package-manager/Tests/WorkspaceTests/XCTestManifests.swift:3,16,17,27,28,37,38,83,84,92 ./.build/checkouts/swift-package-manager/Tests/WorkspaceTests/WorkspaceTests.swift:3,6,10,12,20,22,24,28,71,85,87,91,92,98,99,101,104,107,113,114,115,120,124,125,127,136,137,148,149,152,153,164,165,167,168,169,170,174,213,220,222,225,226,227,231,256,260,261,262,263,268,307,314,316,319,322,323,328,367,375,377,380,383,392,394,397,401,402,406,437,450,456,458,462,463,464,468,508,519,521,525,529,530,531,540,542,546,550,554,555,556,560,600,608,609,612,613,625,628,631,646,649,653,658,659,664,673,680,683,684,692,695,696,704,707,708,717,723,726,727,728,732,743,748,750,751,752,756,810,819,821,825,826,830,835,837,840,842,847,849,850,854,885,889,890,895,899,906,908,911,912,915,922,924,927,928,929,933,964,969,970,975,977,978,983,984,989,991,992,997,998,999,1003,1054,1057,1058,1063,1064,1065,1069,1108,1112,1121,1123,1127,1128,1129,1133,1162,1168,1170,1173,1176,1177,1181,1184,1187,1188,1193,1194,1197,1200,1201,1202,1206,1226,1232,1234,1235,1237,1242,1245,1246,1247,1248,1252,1282,1286,1287,1288,1289,1293,1323,1325,1329,1332,1336,1337,1341,1342,1346,1347,1348,1349,1353,1393,1399,1401,1402,1407,1410,1412,1417,1418,1423,1424,1427,1428,1433,1434,1435,1440,1443,1446,1451,1455,1456,1457,1461,1490,1493,1498,1501,1503,1509,1510,1513,1514,1515,1519,1537,1542,1547,1549,1552,1555,1556,1560,1564,1565,1571,1572,1576,1579,1580,1581,1585,1625,1634,1636,1640,1641,1645,1649,1653,1654,1661,1662,1666,1670,1674,1675,1679,1683,1687,1688,1692,1696,1700,1701,1702,1707,1738,1744,1746,1749,1750,1766,1769,1772,1773,1774,1778,1817,1823,1825,1828,1831,1834,1835,1842,1843,1851,1852,1853,1854,1858,1890,1894,1896,1901,1902,1903,1907,1951,1961,1963,1967,1968,1973,1974,1978,1979,1980,1981,1985,2028,2034,2037,2038,2039,2040,2044,2073,2078,2080,2083,2084,2091,2094,2095,2099,2102,2103,2104,2108,2135,2138,2146,2148,2151,2152,2158,2161,2162,2168,2171,2172,2173,2177,2204,2207,2215,2217,2220,2221,2227,2230,2231,2237,2240,2241,2242,2246,2284,2287,2295,2297,2300,2301,2307,2310,2311,2312,2316,2354,2357,2365,2367,2370,2374,2375,2381,2384,2388,2389,2390,2394,2421,2427,2430,2433,2434,2437,2440,2443,2444,2445,2449,2513,2519,2521,2526,2527,2530,2534,2540,2542,2548,2549,2550,2554,2620,2633,2641,2643,2647,2648,2652,2653,2656,2657,2665,2667,2671,2672,2676,2677,2678,2682,2722,2729,2733,2737,2738,2744,2748,2751,2752,2757,2758,2762,2766,2767,2771,2775,2779,2780,2784,2788,2792,2793,2794,2795,2800,2801 ./.build/checkouts/swift-package-manager/Tests/PackageModelTests/ToolsVersionTests.swift:3,6,10,12,14,16,18,46,50,52,53,65,69,70,71,72 ./.build/checkouts/swift-package-manager/Tests/PackageModelTests/SwiftLanguageVersionTests.swift:3,6,10,12,14,16,18,20,28,32,35,36,48,52,53,54,55,61,69,70 ./.build/checkouts/swift-package-manager/Tests/PackageModelTests/XCTestManifests.swift:3,11,12,21,22,35,36,44,45,53 ./.build/checkouts/swift-package-manager/Tests/PackageModelTests/TargetTests.swift:3,6,10,13,15,23,24,25,31,32,33,35,41,44,45,46,53,57,58,59,66,70,71,72,79,83,84,85,94,102,107,108,109,118,126,131,132,133,134,141,142 ./.build/checkouts/swift-package-manager/Tests/PackageModelTests/PackageModelTests.swift:3,6,10,12,14,16,18,22,23,32,33,34,40,41 ./.build/checkouts/swift-package-manager/Tests/ExtraTests/Tests/LinuxMain.swift:2,4,7 ./.build/checkouts/swift-package-manager/Tests/ExtraTests/Tests/ExtraTests/XCTestManifests.swift:3,11,12,17 ./.build/checkouts/swift-package-manager/Tests/ExtraTests/Tests/ExtraTests/FSWatchTests.swift:2,5,7,11,17,21,22,25,28,32,33,36,37,39,40,41,44,46,49,50,53,55,58,59,60 ./.build/checkouts/swift-package-manager/Tests/ExtraTests/Package.swift:2,4 ./.build/checkouts/swift-package-manager/Tests/CommandsTests/TestToolTests.swift:3,6,10,12,15,19,20,23,24,27,28,31,32,45,53,54,55,57,58,67,68,70,71,79,80,82,83 ./.build/checkouts/swift-package-manager/Tests/CommandsTests/RunToolTests.swift:3,6,10,12,17,21,22,25,26,29,30,33,34,37,40,45,49,55,56,57,58,66,67,70,73,74,75,81,82,83,90,92,93,94,102,103,104,105,117,125,126,127,129,130 ./.build/checkouts/swift-package-manager/Tests/CommandsTests/XCTestManifests.swift:3,17,18,45,46,62,63,76,77,85 ./.build/checkouts/swift-package-manager/Tests/CommandsTests/BuildToolTests.swift:3,6,10,12,17,21,22,27,28,36,37,40,41,44,45,48,49,58,66,67,68,72,79,80,85,86,93,94,100,101,107,108,114,115,121,122,128,129,135,136,137,138,142,151,152,154,165,174,175,177,190,191,192,193,202,203,204,205 ./.build/checkouts/swift-package-manager/Tests/CommandsTests/PackageToolTests.swift:3,6,10,13,23,28,29,32,33,36,37,40,41,45,50,51,52,56,61,66,70,71,72,78,86,88,89,93,95,100,101,102,130,131,132,138,146,147,148,155,159,160,161,168,173,179,180,181,188,194,195,196,203,208,214,215,216,222,223,227,230,234,239,243,250,256,259,265,268,271,277,283,288,293,294,295,299,306,312,313,314,318,326,330,334,337,338,339,343,347,348,350,353,359,366,367,374,375,381,382,383,390,392,396,399,404,405,409,419,420,421,425,426,432,433,442,443,448,449,456,457,466,468,469,470,471,478,490,492,493,506,513,514,517,519,520,521,526,529,534,537,540,541,543,544,546,548,550,551,552,559,566,571,576,582,591,592,593,596,597,601,604,607,608,611,612,613,614 ./.build/checkouts/swift-package-manager/Tests/SourceControlTests/RepositoryManagerTests.swift:3,6,10,12,15,17,19,23,24,25,28,29,33,36,37,40,41,44,45,48,49,52,53,56,57,58,65,66,70,71,72,75,80,82,87,88,89,92,93,97,98,101,102,105,106,107,111,114,116,119,120,123,124,127,128,131,132,136,137,138,142,143,144,148,149,150,154,155,156,157,164,168,174,175,178,182,186,190,191,199,202,203,205,209,213,218,221,227,228,232,233,237,238,239,258,259,260,265,271,273,276,280,289,293,301,303,306,310,311,312,324,333,334,335,336,341,342,343,344,345,352,355,361,368,374,375,376,386,390,394,398,404,405,406 ./.build/checkouts/swift-package-manager/Tests/SourceControlTests/XCTestManifests.swift:3,27,28,37,38,51,52,59 ./.build/checkouts/swift-package-manager/Tests/SourceControlTests/InMemoryGitRepositoryTests.swift:3,6,10,12,16,18,23,27,31,34,37,41,45,49,54,58,65,69,73,74,79,89,92,96,101,107,111,114,117,118 ./.build/checkouts/swift-package-manager/Tests/SourceControlTests/GitRepositoryTests.swift:3,6,10,12,16,18,20,31,32,39,46,49,54,62,63,65,69,73,77,78,79,80,85,88,91,92,104,109,113,118,127,136,142,143,144,145,151,155,163,164,165,172,190,197,200,211,217,218,222,223,227,230,231,235,238,239,243,244,245,254,262,268,274,279,289,290,291,292,301,309,315,322,326,330,331,332,339,343,349,354,361,367,368,369,377,380,393,394,395,402,406,408,410,412,414,416,420,421,422,429,440,443,450,451,452,460,464,465,481,488,493,494,495,499,516,521,525,528,532,539,549,556,562,570,574,575,576,585,593,598,601,605,606,607,615,618,623,626,627,628,636,639,642,643,644 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/WhitelistTests.swift:3,6,10,13,19,20,26,27,33,34,39,42,43 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/PackageBuilderTests.swift:3,6,10,13,17,19,22,27,38,39,40,41,46,55,56,57,61,65,72,79,83,84,85,86,91,103,104,108,109,111,117,118,119,130,141,143,144,145,152,164,165,166,167,173,184,185,186,198,199,213,214,215,223,239,240,241,255,256,257,275,276,277,278,285,297,298,302,303,307,308,309,310,316,336,340,341,342,343,350,363,364,365,379,401,403,408,409,413,414,418,419,423,424,426,427,428,434,449,450,465,467,471,472,476,477,479,480,481,491,502,504,506,511,512,517,518,519,520,527,538,540,544,545,550,551,556,557,562,563,566,567,568,575,584,591,594,595,596,603,604,605,606,612,627,628,633,634,635,636,651,652,657,658,662,663,664,665,673,685,686,687,693,705,707,713,714,719,720,721,722,723,729,738,739,740,753,754,755,768,769,770,783,784,785,803,804,815,816,817,823,836,837,838,839,844,851,854,855,864,865,866,871,880,881,886,895,896,897,902,911,912,913,914,920,932,933,937,938,940,941,942,947,952,955,956,964,967,968,969,973,979,980,981,982,988,997,998,1000,1004,1006,1007,1012,1014,1015,1020,1022,1023,1028,1030,1031,1035,1036,1041,1042,1043,1045,1051,1059,1062,1063,1064,1071,1081,1082,1094,1097,1099,1100,1101,1102,1105,1112,1115,1116,1117,1123,1131,1133,1135,1138,1141,1142,1144,1145,1146,1153,1168,1169,1170,1171,1178,1195,1198,1201,1202,1203,1210,1222,1224,1225,1226,1232,1247,1252,1255,1256,1257,1258,1264,1279,1280,1295,1296,1297,1302,1315,1316,1317,1322,1329,1334,1335,1336,1344,1358,1366,1370,1373,1376,1377,1378,1393,1401,1405,1408,1411,1412,1413,1414,1423,1431,1435,1436,1437,1438,1446,1456,1460,1461,1462,1463,1472,1482,1486,1511,1519,1522,1523,1528,1531,1534,1535,1544,1548,1549,1550,1552,1553,1554,1559,1572,1575,1576,1589,1592,1593,1594,1601,1620,1626,1627,1628,1629,1631,1636,1637,1640,1643,1646,1649,1675,1680,1681,1685,1686,1690,1691,1694,1695,1696,1702,1703,1704,1708,1711,1712,1716,1719,1722,1723,1727,1731,1734,1735,1738,1741,1742,1746,1747,1750,1751,1752,1755,1758,1759,1763,1765,1766,1770,1773,1774,1775,1779,1782,1783,1786,1787,1790,1791,1795,1800,1801,1802,1803,1807,1809,1810,1814,1815,1816 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/PD5LoadingTests.swift:3,6,10,12,18,22,38,40,41,54,55,56,80,83,91,96,100,103,108,113,114,115,125,128,129,138,145,148,149,150,164,172,173,185,191,192,204,210,211,221,227,228,229,260,263,267,270,273,276,277,278 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/ModuleMapGenerationTests.swift:3,6,10,12,16,18,23,29,30,32,35,36,37,42,48,49,51,54,55,56,58,64,65,67,72,73,74,79,86,92,93,100,101,113,114,115,122,123,124,130,136,137,138,151,156,157,159,163,168,169,173,174,180,181,182,185,186,189,190,193,194,198,200,201 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/PkgConfigTests.swift:3,6,10,12,18,26,27,28,30,33,39,40,61,67,68,69,79,80,94,95,96,97,102,106,107 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/PD4LoadingTests.swift:3,6,10,12,15,18,20,23,28,39,41,42,47,55,56,57,62,66,67,71,75,76,80,84,85,86,95,101,102,103,123,131,140,145,146,147,159,160,171,172,181,182,183,208,209,210,241,242,243,264,265,266,285,288,291,292,293,315,321,327,328,329,347,354,355,356,374,375,376,381,386,391,393,400,405,408,409,410 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/PD4_2LoadingTests.swift:3,6,10,12,18,22,38,40,41,54,55,56,80,83,91,96,100,103,108,113,114,115,126,133,135,136,148,149,163,164,173,180,183,184,185,196,200,201,210,217,220,221,222,242,249,252,253,254,282,285,288,294,298,301,304,307,308,309,338,344,345,346,354,373,378,382,383,384,408,409,415,416,417,439,447,448,449,453,467,468,470,473,480,485,486,489,493,494,498,499,502,503,504,508,522,523,525,528,535,540,541,545,546,550,552,560,562,563,567,568,573,574,575,576,580,583,584,587,588,592,593,594 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/XCTestManifests.swift:3,15,16,63,64,83,84,102,103,114,115,124,125,136,137,148,149,161 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/ToolsVersionLoaderTests.swift:3,6,10,12,15,19,21,23,31,32,34,47,54,55,56,57,64,65,66,74,75,76,77,87,88,89,92,93,100,108,109,114,118,119,124,125,128,131,136,137,142,143,148,149,150,156,162,166,167,171,172,176,177,181,182,183,188,195,196,197 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/Inputs/target-deps-manifest.swift:2 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/Inputs/package-deps-manifest.swift:2 ./.build/checkouts/swift-package-manager/Tests/PackageLoadingTests/Inputs/trivial-manifest.swift:2 ./.build/checkouts/swift-package-manager/Examples/package-info/Package.swift:3 ./.build/checkouts/swift-package-manager/Examples/package-info/Sources/package-info/main.swift:2,5,8,11,14 ./.build/checkouts/swift-package-manager/Examples/package-info/Sources/package-info/SwiftPMHelper.swift:2,5,14,17,20,21,28,29,33,36,42,43 ./.build/checkouts/swift-package-manager/Package.swift:2,5,8,12,14,59,83,85,114,116,125,127,132,134,147,149,174,176,185,244,253,259,265,266,276 ./.build/checkouts/swift-package-manager/Sources/POSIX/Error.swift:3,6,10,37,38,42,52,56,59,61,63,64,117,118,119 ./.build/checkouts/swift-package-manager/Sources/POSIX/env.swift:3,6,10,15,19,20,24,25,26,30,31 ./.build/checkouts/swift-package-manager/Sources/POSIX/isatty.swift:3,6,10,12,15 ./.build/checkouts/swift-package-manager/Sources/POSIX/realpath.swift:3,6,10,14,18,29 ./.build/checkouts/swift-package-manager/Sources/POSIX/getcwd.swift:3,6,10,18,30,34,35,41 ./.build/checkouts/swift-package-manager/Sources/POSIX/readdir.swift:3,6,10,12,21,22,23,24 ./.build/checkouts/swift-package-manager/Sources/POSIX/rename.swift:3,6,10,13,17 ./.build/checkouts/swift-package-manager/Sources/POSIX/exit.swift:3,6,10,12,15 ./.build/checkouts/swift-package-manager/Sources/POSIX/stat.swift:3,6,10,12,15,20,21,25,36,37,38,39,42,45,48,51,54,58,59,65,73,76,77,78,84,85,91 ./.build/checkouts/swift-package-manager/Sources/POSIX/usleep.swift:3,6,10,12,17 ./.build/checkouts/swift-package-manager/Sources/POSIX/chdir.swift:3,6,10,13,22,23,26,27,28,30,36,37,40 ./.build/checkouts/swift-package-manager/Sources/TestSupport/FileSystemExtensions.swift:3,6,10,12,16,20,27,32,33,34,38,39,44,45,46,50,51,59,62,63,64,65,73,74,75 ./.build/checkouts/swift-package-manager/Sources/TestSupport/MockManifestLoader.swift:3,6,10,12,18,21,22,36,40,41,42,44,47,48,60,62,63 ./.build/checkouts/swift-package-manager/Sources/TestSupport/TestWorkspace.swift:3,6,10,12,19,21,32,46,51,53,54,57,58,61,62,66,71,73,76,81,88,93,110,111,112,114,115,119,120,124,125,127,128,132,133,148,150,153,154,157,158,161,164,168,169,176,177,178,196,197,209,211,212,219,220,226,227,233,234,247,248,256,257,271,272,278,282,283,285,287,290,291,295,296,299,300,305,315,319,323,324,325,326,327,342,343,350,351,352,355,358,359,362,363,368,378,381,382,383,384,391,392,393,394,396,399,400,404,413,414,421,422,423,424,426,429,433,434,435,440,444,445,448,449,450,452,462,481,482,494,495,496,498,500,502,505,506,509,510,513,514,517,518,521,522,525,526,529,530,533,534 ./.build/checkouts/swift-package-manager/Sources/TestSupport/GitRepositoryExtensions.swift:3,6,10,14,18,22,23,28,29,33,34,38,39,43,44,52,53,57,58,62,63 ./.build/checkouts/swift-package-manager/Sources/TestSupport/PackageGraphTester.swift:3,6,10,12,15,18,19,22,25,26,29,30,33,34,41,42,49,50,53,54,58,60,61,62,70,71,72 ./.build/checkouts/swift-package-manager/Sources/TestSupport/MockDependencyGraph.swift:3,6,10,12,19,24,27,30,35,36,37,42,45,49,50,54,55,56,63,66,69,72,75,79,80,84,85,94,95,109,120,126,127,130,139,140,151,168,172,173,184,185 ./.build/checkouts/swift-package-manager/Sources/TestSupport/DiagnosticsEngine.swift:3,6,10,13,15,19,30,31,32,35,36,39,40,43,44,45,54,59,60,63,64,65,68,70,76,77,78,89,90,93,97,98 ./.build/checkouts/swift-package-manager/Sources/TestSupport/XCTestCasePerf.swift:3,6,10,12,20,24,26 ./.build/checkouts/swift-package-manager/Sources/TestSupport/misc.swift:3,6,10,13,22,26,43,46,51,52,56,61,62,68,79,80,83,91,92,93,105,106,118,119,129,132,133,134,138,139,141,157,161,163,164,182,186,187,188,194,195,198,199,211,219,220,233,234,252,253,254,258,263,265,266,276,277,279,280,296,298,299,300,303 ./.build/checkouts/swift-package-manager/Sources/TestSupport/AssertMatch.swift:3,6,10,12,14,18,21,24,33,34,38,41,44,47,48,49,55,72,73,74,78,84,90,94,97,101,102,103,108,111,113,114,116,117,120,121,124,127,128,132,134,138,139,142,145 ./.build/checkouts/swift-package-manager/Sources/TestSupport/XCTAssertHelpers.swift:3,6,10,12,16,20,44,46,48,49,50,51,63,65,67,68,69,81,83,90,93,94,95,99,100,101,105,106,107,111,112,113,127,128,129,143,144,145,154,159,160,161,167 ./.build/checkouts/swift-package-manager/Sources/TestSupport/SwiftPMProduct.swift:3,6,10,13,17,21,25,26,37,43,49,50,66,67,68,83,87,90,94,100,101,107,111,121,125,127,129,130,138,139,141,142 ./.build/checkouts/swift-package-manager/Sources/TestSupport/MockDependencyResolver.swift:3,6,12,16,18,20,22,24,33,46,48,49,50,51,58,59,60,67,68,69,72,73,75,77,79,81,83,85,88,91,92,96,97,101,102,108,109,112,113,116,117,127,129,130,139,140,141,145,146,147,153,167,169,170,172,173,174,177,180,184,185,194,195,196,197,200,202,203,215,218,219,220,222,227,234,243,244,254,257,258,259,260,268,270 ./.build/checkouts/swift-package-manager/Sources/TestSupport/PseudoTerminal.swift:3,6,10,13,18,24,27,31,32,37,39,40,43,44,47,48,52,53 ./.build/checkouts/swift-package-manager/Sources/TestSupport/Manifest.swift:3,6,10,14,47,48,81,82,83,87,88 ./.build/checkouts/swift-package-manager/Sources/TestSupport/JSONExtensions.swift:3,6,10,12,19,21,22,26,28,29,33,35,36,39,40,43,44,49,51,53,54 ./.build/checkouts/swift-package-manager/Sources/TestSupport/Resources.swift:3,6,10,17,22,24,26,28,31,32,35,36,40,42,44,46,59,60 ./.build/checkouts/swift-package-manager/Sources/SPMLibc/libc.swift:3,6,10,16 ./.build/checkouts/swift-package-manager/Sources/SPMLLBuild/llbuild.swift:3,6,10,18,20,23,24,29,32,33,36,37,39,42,45,46,51,52,53,55,58,59,62,63,69,70,73,74,77,78,79,82,84,87,88,93,94,97,98,99,102,108,109,111,112,115,116,119,120,123,124,127,128,130,133,134,136,137,139,140,142,143,144,146,148,151,155,156,159,160,163,164,167,168,169,173,174,177,178,181,182,183,187,188,191,192,193,198,199,204,207 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/RepositoryPackageContainerProvider.swift:3,6,10,12,18,25,29,33,36,39,59,60,76,78,79,96,98,99,100,101,105,106,114,115,116,118,122,124,126,129,132,135,138,139,142,143,146,147,150,151,154,155,168,169,170,178,181,186,187,190,195,196,205,206,209,210,215,216,234,235,238,239,240,243,247,250,253,256,257,261,268,269,274,275,278,279,283,286,289,292,295,299,309,314,319,323,333,334,337,338,341,342,346,347,351,352,359,360,371,372,373,384,385,386,394,398,399,400,407,410,418,420,421,425,426,437,438,445,447,448 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/RawPackageConstraints.swift:3,6,10,13,23,24,25,27,35,36 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/DependencyResolver.swift:3,6,10,14,18,21,26,42,43,44,59,60,62,63,64,65,70,73,76,79,98,102,107,109,110,111,123,124,125,138,141,145,146,147,148,151,154,164,167,175,181,182,183,184,190,193,196,200,201,202,225,228,235,248,257,262,269,270,274,281,282,286,289,292,298,299,304,305,308,309,310,314,317,318,321,322,333,336,339,342,353,354,355,356,371,374,377,381,382,389,390,394,395,399,400,413,417,420,426,430,437,443,447,451,452,453,459,460,472,474,476,477,479,482,483,486,487,490,491,494,495,496,513,519,523,524,529,530,531,536,540,543,545,546,547,561,562,571,574,575,576,578,579,592,598,600,601,602,608,612,622,623,625,626,637,642,644,650,655,659,660,661,668,669,670,679,680,681,683,684,686,689,691,699,700,701,702,703,712,713,715,716,779,785,788,791,794,797,800,803,808,813,817,818,821,822,823,826,836,847,848,853,862,865,866,889,892,893,894,909,910,919,928,929,930,937,941,942,947,948,950,951,953,954,981,992,993,999,1000,1005,1010,1011,1015,1022,1025,1026,1032,1035,1039,1041,1045,1052,1055,1060,1061,1066,1067,1083,1091,1092,1095,1096,1101,1103,1104,1120,1124,1125,1136,1138,1139,1154,1165,1166,1184,1185,1193,1194,1202,1203,1211,1213,1214,1216,1219,1227,1228,1231,1234,1241,1242,1246,1247,1251,1252,1257,1258,1259,1269,1270,1273,1281,1282,1283,1284,1285,1286,1287,1295,1298,1302,1303,1306,1310,1311,1314,1327,1343,1344,1345,1348,1352,1355,1358,1366,1370,1378,1379,1382,1387,1392,1397,1399,1404,1405,1408,1410,1411,1419,1420,1428,1429,1430,1433,1436,1439,1444,1446,1447,1452,1454,1455,1456 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraphLoader.swift:3,6,10,16,25,27,28,39,42,46,47,48,59,62,66,67,68,72,75,78,81,84,85,91,96,99,102,105,106,107,108,113,125,140,141,148,151,160,161,166,171,182,186,190,192,193,202,204,206,212,213,214,225,228,234,241,242,246,247,248,249,250,260,265,268,275,279,285,289,294,295,300,301,308,315,317,318,322,323,326,329,333,336,343,346,352,357,360,372,374,375,385,386,387,389,390,391,392,403,404,405,407,408,411,414,422,425,426,430,431,432,435,438,441,445,446,452,453,454,457,460,463,466,469,473,474,483,484,485,486,487,492,495,498,500,501,506,507,508,511,514,517,520,523,526,527,535,536 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraph.swift:3,6,10,13,18,22,25,28,31,34,40,45,46,50,51,62,70,72,80,82,87,91,98,99,100,103,104 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/Pubgrub.swift:3,6,10,14,18,22,27,28,31,32,36,37,44,45,52,53,58,59,68,70,78,79,80,90,98,101,106,110,111,112,113,116,117,123,124,134,136,137,140,143,144,151,152,157,158,164,166,171,174,179,181,182,183,184,192,193,194,202,203,204,211,212,213,214,220,221,238,239,240,243,245,246,247,252,253,254,261,265,266,270,271,274,281,283,284,286,291,294,295,298,299,300,307,308,309,348,352,354,355,362,365,367,368,369,370,384,395,396,400,406,407,419,420,421,429,430,431,432,437,440,443,447,452,456,457,462,463,464,469,470,477,478,487,488,493,497,498,500,506,507,508,513,517,519,522,523,524,526,527,532,537,538,539,544,545,546,552,553,554,561,562,564,565,569,570,578,580,581,582,602,610,612,613,627,634,635,642,643,644,652,653,657,658,662,674,680,683,687,692,695,696,697,700,703,706,709,714,715,728,729,740,741,746,749,750,754,755,764,765,773,776,777,778,779,781,790,791,792,797,800,801,804,805,816,817,829,831,840,841,857,858,860,861,863,864,873,881,882,886,887,888,895,898,907,912,919,920,923,929,930,931,932,933,936,939,945,947,948,949,953,954,956,958,959,964,965,972,978,981,985,993,997,998,1003,1004,1005,1006,1009,1010,1015,1017,1018,1020,1023,1026,1027,1033,1034,1036,1037,1044,1045,1048,1052,1053,1057,1063,1064,1067,1072,1080,1081,1082,1086,1087,1089,1090,1092,1094,1102,1103,1104,1106,1109,1111,1112,1118,1120,1124,1125,1130,1152,1168,1175,1176,1177,1187,1188,1198,1212,1218,1219,1220,1222,1240,1241,1242,1244,1247,1250,1253,1260,1261,1265,1266,1270,1271,1276,1277,1278,1283,1292,1293,1294,1303,1315,1316,1317 ./.build/checkouts/swift-package-manager/Sources/PackageGraph/PackageGraphRoot.swift:3,6,10,13,16,19,21,24,27,32,33,34,37,42,44,51,54,57,66,67,80,83,84,85,88,91,94,99,102,103,115,116,117,119,125,128,130,133,135,138,141,142,143 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/pbxproj().swift:3,6,10,17,22,23,48,49,56,67,70,74,80,85,89,90,95,102,105,108,121,124,129,133,136,139,140,145,148,152,157,160,170,176,182,189,190,193,199,204,210,211,214,220,221,226,227,228,232,242,243,247,251,255,256,261,288,289,293,301,304,305,307,308,314,317,320,324,333,336,342,347,355,356,357,358,362,367,368,372,373,377,380,384,401,402,408,409,415,418,423,427,429,446,447,449,450,453,474,476,477,478,487,491,492,501,511,516,517,519,522,525,528,531,534,537,540,549,553,556,557,562,563,574,575,579,583,586,597,607,608,613,614,615,616,626,627,630,631,632,633,642,648,657,658,661,665,678,679,680,681,682,703,706,707,708,710,711,713,716,717,720,721,722,738,739,740,741,748,752,758,760,763,764,765,766,775,777,778,779,780,798,799,808,809,818,827,836,837,838,847,850,858,861,869,870,873,874 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/XcodeProjectModel.swift:3,6,9,11,17,23,26,38,42,56,58,74,75,82,83,84,95,109,110,115,116,117,122,127,128,129,135,146,147,159,160,161,179,188,189,193,200,201,208,209,216,217,224,225,232,233,239,240,245,246,247,251,257,258,259,264,265,270,271,276,277,284,285,286,292,293,294,301,302,304,308,309,310,319,323,327,330,381,470,471,472,473,474,487,488 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/PropertyList.swift:3,6,10,21,25,27,28,32,34,35,36,40,43,46,49,50,51,55,56,57,62,63,70,71,74,79,81,83,84,85,93,97,100,101,102,107,111,114,122,126,136,142,146,147,148 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/XcodeProjectModelSerialization.swift:3,6,9,11,15,17,38,39,66,74,75,76,92,95,96,98,113,114,115,117,127,131,133,134,135,137,165,172,173,182,185,187,188,189,206,207,209,217,218,219,221,229,230,231,233,241,242,243,245,259,260,261,263,277,278,279,281,289,290,294,295,297,298,299,301,314,325,326,339,341,342,343,366,367,368,371,372,399,418,419,421,422,423,426,436,439,440,448,449,451,452,457,464,467,468,471,472,475,476,477,482,488,495,502,503,511,515,518,522,526,527,528,564,569,575,576,580,581,582,590,591,592 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/SchemesGenerator.swift:3,6,10,14,17,20,24,25,28,31,36,37,38,40,46,59,60,63,65,73,80,86,92,93,101,108,110,111,116,117,119,120,123,130,132,144,146,147,151,153,162,164,177,179,180,184,186,212,214,215,216,219,221,224,225,228,244,259,260,261,269,278,279,290,291,303,317,318,324 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/Target+PBXProj.swift:3,6,9,11,13,17,19,25,27,31,33,36,37,48,49,50,61,62,63,74,75,76,86,87,88 ./.build/checkouts/swift-package-manager/Sources/Xcodeproj/generate().swift:3,6,10,18,22,27,30,33,36,39,42,57,58,59,64,65,81,83,86,90,93,98,102,105,106,117,118,126,159,160,161,163,164,174,180,181,184,185,190,198,199,219,220,238,247,248,249,255,261,262,263,266,268,269,276,283,286 ./.build/checkouts/swift-package-manager/Sources/SPMPackageEditor/ManifestRewriter.swift:3,6,10,12,21,24,25,28,32,33,36,41,42,51,54,55,59,66,71,72,78,80,81,90,93,94,100,101,107,108,111,114,115,120,122,123,132,135,136,139,142,143,147,149,150,151,153,156,159,162,163,170,172,173,174,177,179,183,184,190,191,194,196,197,198,201,204,210,212,213,214,217,220,223,224,228,231,234,235,239,240,242,243,244,246,249,252,262,266,267,268,272,275,276,280,282,283,284,287,290,293,297,298,302,309,311,320,330,331,339,344,347,350,351,352,355,358,361,362,365,372,373,378,380,381,382,385,388,392,393,395,398,405,412,420,430,435,437,438 ./.build/checkouts/swift-package-manager/Sources/SPMPackageEditor/PackageEditor.swift:3,6,10,18,24,27,31,32,36,37,41,42,46,52,55,56,61,62,76,85,86,91,92,97,105,106,109,110,116,122,123,129,132,139,140,149,152,153,155,156,157,158,159,166,167,168,169,170,175,181,182,183,184,192,201,202,203,204,210,219,220,221,226,235,236,237,238,246,247,248,249,252,255,258,261,264,268,272,278,279,286,289,297,298 ./.build/checkouts/swift-package-manager/Sources/swiftpm-xctest-helper/main.swift:3,6,10,14,24,27,30,35,37,39,55,67,68,81,84,91,92,98,107,108,113,114,120,122,123,124,133,134,136,140 ./.build/checkouts/swift-package-manager/Sources/Workspace/ManagedDependency.swift:3,6,10,16,22,25,28,35,38,43,44,53,54,55,56,59,62,65,72,82,83,95,96,107,108,119,120,129,130,136,137,145,146,149,150,151,169,170,171,184,185,186,187,190,193,198,199,200,201,207,212,215,218,221,228,242,243,244,248,251,252,253,261,262,264,265,268,269,273,274,277,278,282,283,286,287,292,293,298,299 ./.build/checkouts/swift-package-manager/Sources/Workspace/CheckoutState.swift:3,6,10,15,20,23,26,29,39,40,44,45,49,50,53,54,55,57,64,66,67,68,70,78,79,86,87,88,93,95,96,97 ./.build/checkouts/swift-package-manager/Sources/Workspace/ToolsVersionWriter.swift:3,6,10,15,24,27,34,38,40,41,43,47,48 ./.build/checkouts/swift-package-manager/Sources/Workspace/PinsStore.swift:3,6,10,16,21,24,31,32,33,38,41,44,49,53,54,56,75,76,77,93,94,100,101,106,114,115,119,120,127,128,135,136,137,140,148,149,151,152,155,156,162,163,164,174,175,183,184 ./.build/checkouts/swift-package-manager/Sources/Workspace/Workspace.swift:3,6,10,18,21,24,27,30,33,36,39,42,45,48,49,56,57,60,61,64,67,68,71,72,80,81,84,85,88,89,90,94,97,100,107,108,109,116,117,118,119,137,140,142,147,148,152,153,157,158,162,163,168,176,184,186,195,197,198,202,204,219,223,224,226,227,232,237,249,251,252,253,256,259,262,265,268,271,274,277,280,283,286,289,292,295,298,301,305,345,360,363,365,366,382,383,384,386,388,416,417,418,439,440,466,469,470,481,484,487,488,495,506,510,511,514,515,520,521,522,534,536,539,540,552,555,558,562,566,567,570,573,576,579,583,587,590,593,595,601,602,617,624,626,638,639,649,650,662,663,672,678,679,681,682,683,685,687,700,702,703,714,717,718,722,728,735,736,742,747,754,756,760,763,764,768,772,773,774,781,785,786,791,792,793,799,800,806,807,815,818,823,830,831,832,840,843,844,848,852,853,863,864,869,870,871,872,873,875,877,886,888,892,893,895,896,897,899,901,909,910,911,925,926,927,936,938,939,949,955,956,957,958,963,964,970,973,982,983,986,988,989,990,996,997,1005,1006,1009,1017,1018,1032,1040,1041,1049,1050,1061,1062,1063,1065,1067,1077,1078,1090,1093,1096,1100,1101,1110,1111,1112,1120,1126,1128,1133,1134,1135,1137,1144,1148,1149,1151,1152,1166,1169,1172,1175,1181,1182,1184,1188,1189,1192,1195,1207,1209,1214,1215,1217,1218,1221,1226,1229,1235,1245,1246,1251,1252,1253,1257,1262,1263,1266,1293,1294,1295,1297,1299,1300,1312,1315,1318,1325,1326,1327,1332,1333,1334,1340,1345,1351,1352,1356,1357,1365,1366,1369,1374,1377,1378,1379,1381,1382,1387,1388,1391,1396,1397,1399,1404,1408,1409,1411,1412,1413,1416,1421,1424,1426,1435,1436,1437,1438,1441,1444,1447,1450,1461,1462,1463,1464,1465,1475,1500,1501,1502,1506,1511,1512,1519,1522,1523,1531,1539,1540,1541,1552,1555,1556,1563,1566,1567,1568,1573,1574,1576,1577,1590,1591,1592,1601,1603,1608,1612,1619,1622,1623,1625,1626,1627,1633,1637,1638,1641,1645,1651,1659,1661,1665,1666,1667,1668,1669,1670,1672,1674,1694,1695,1703,1704,1705,1706,1716,1717,1718,1719,1723,1724,1725,1737,1743,1749,1750,1756,1758,1759,1760,1764,1765,1768,1771,1775,1777,1778,1797,1800,1803,1808,1815,1817,1818,1824,1835,1838,1843,1844,1846,1847,1850,1853,1854,1866,1867,1870,1873,1882,1883,1889,1890,1893,1896,1899,1900,1901,1907,1910,1914,1915,1921,1922,1926,1927 ./.build/checkouts/swift-package-manager/Sources/Workspace/Export.swift:3,6,10,13 ./.build/checkouts/swift-package-manager/Sources/Workspace/InitPackage.swift:3,6,10,13,18,25,28,29,30,33,36,39,42,45,49,50,57,58,62,71,72,76,77,82,83,87,89,91,93,98,108,109,116,130,131,133,134,139,143,144,149,150,154,156,158,159,160,165,166,173,175,176,177,181,185,188,191,192,195,198,205,206,211,215,216,217,218,222,226,227,234,235,237,238,239,243,247,250,256,257,258,263,265,269,271,272,273,279,286,287,291,292,294,295,296,302,308,312,313,315,318,321,324,327,329,330,336,341,342,346,347,349,350,351,356,364,365,369,375,377,379,380,381,382,383,385,388,389,395,396,397 ./.build/checkouts/swift-package-manager/Sources/Workspace/Destination.swift:5,9,12,13,21,22,23,24,27,39,42,45,48,51,54,76,79,80,90,102,104,105,109,128,129,134,137,141,143,146,149,150,152,157,158,159,161,164,166,170,171,180,181 ./.build/checkouts/swift-package-manager/Sources/Workspace/Diagnostics.swift:3,6,10,17,24,26,30,31,32,41,44,48,50,51,54,56,60,61,62,76,77,78,79,81,90,94,97,101,102,106,109,111,115,123,124,126,127,130,133,137,138,139,140,147,149,153,154,155,157,159,169,172,173,183,186,187,195,198,199,209,212,213,223,226,227,237,240,241,251,254,255,266,269,272,275,276,288,291,294,297,298,310,313,316,319,320,322,334,337,338,350,353,354,366,369,372,373,385,388,391,392,400,402,404,407,408,409,418,420,422,423,432,434,435,443,445,446,453,455,457,458,462,463,464 ./.build/checkouts/swift-package-manager/Sources/Workspace/UserToolchain.swift:3,6,10,12,18,24,30,39,40,41,44,47,50,52,54,57,58,62,63,68,71,74,77,85,88,92,93,95,96,103,104,105,109,113,124,125,129,130,133,134,137,143,144,149,150,156,158,164,167,170,175,176,182,184,185,191,193,194,198,202,204,207,210,215,216,217,226,230,234,237,246,247,248,249,255,256 ./.build/checkouts/swift-package-manager/Sources/TestSupportExecutable/main.swift:3,8,24,27,28,29,32,37,39,40,44,45,46,48,54,55,61,66,67,70,74,76,87,94,104,108,112,127,132 ./.build/checkouts/swift-package-manager/Sources/Basic/LazyCache.swift:3,6,10,38,42,43,54,55,56,57 ./.build/checkouts/swift-package-manager/Sources/Basic/ObjectIdentifierProtocol.swift:3,6,10,15,19,20,23,24 ./.build/checkouts/swift-package-manager/Sources/Basic/CacheableSequence.swift:3,6,10,15,18,21,24,25,28,29,44,49,50,51,52,56,59,62,65,66,71,73,74 ./.build/checkouts/swift-package-manager/Sources/Basic/Process.swift:3,6,10,12,17,20,24,27,28,32,35,36,39,42,46,50,66,69,70,82,83,87,88,92,93,100,101,102,107,112,113,121,128,129,130,137,138,139,140,143,146,149,152,156,157,160,163,166,171,176,177,178,181,184,187,190,193,197,200,206,229,230,239,250,251,252,257,260,265,266,270,271,280,285,301,303,306,313,314,316,325,331,345,349,350,354,357,358,361,364,369,370,373,376,381,382,385,386,387,393,397,398,402,408,411,412,422,423,424,432,444,453,454,455,460,461,468,469,470,484,485,489,490,506,508,509,513,514,517,518,519,521,527,530,531,534,535,538,539,542,543,546,547,553,554,555,561,562,563,569,570,571,572,583,586,587,593,595,603,604,605,607,608,609 ./.build/checkouts/swift-package-manager/Sources/Basic/SHA256.swift:3,6,10,14,17,20,25,37,40,43,46,49,50,53,54,57,58,66,68,69,70,73,77,78,81,84,88,89,98,99,102,103,106,122,123,124,133,139,143,152,153,162,163,168,171,177,180,184,186,187,188,190,196,197,198,203,204,205,214,216,217,218 ./.build/checkouts/swift-package-manager/Sources/Basic/SynchronizedQueue.swift:3,6,10,16,19,24,25,35,36,37,46,47,50,51,52 ./.build/checkouts/swift-package-manager/Sources/Basic/CollectionAlgorithms.swift:3,6,10,12,19,20,21,22,24,30,32,33,34,42,43 ./.build/checkouts/swift-package-manager/Sources/Basic/Condition.swift:3,6,10,12,17,20,24,25,31,32,37,38,43,44,51,52 ./.build/checkouts/swift-package-manager/Sources/Basic/KeyedPair.swift:3,6,10,35,38,43,44,47,48,51 ./.build/checkouts/swift-package-manager/Sources/Basic/DictionaryExtensions.swift:3,6,10,17,18,19,25,26,27,35,36,38,39,40,47,48 ./.build/checkouts/swift-package-manager/Sources/Basic/Result.swift:3,6,10,17,20,24,25,29,30,37,38,39,47,48,49,57,58,59,69,70,71,72,73,81,82,83,84,89,96,97,98,101,102,103,106,109,113,114,115,124,125,126,130,131,142,145,146,147,148,160,161,162,163,165,169,170,180,181,182,187,197,198,199 ./.build/checkouts/swift-package-manager/Sources/Basic/FileSystem.swift:3,6,10,14,23,29,35,43,51,59,65,68,69,83,84,85,86,89,93,94,98,108,109,110,111,124,127,130,133,136,142,149,152,155,160,167,172,177,183,186,187,195,196,203,204,208,209,213,214,220,222,223,230,231,234,235,238,239,240,243,247,249,250,253,254,257,258,261,262,265,266,270,271,275,276,282,283,284,288,290,293,296,300,301,305,306,309,313,314,318,319,321,322,324,325,329,332,335,342,348,349,350,356,358,367,371,373,375,376,378,379,385,387,395,398,400,401,402,407,418,419,420,424,425,426,432,434,438,443,445,448,450,456,458,463,467,472,476,482,485,486,489,493,494,499,500,505,508,509,510,518,521,522,526,527,531,539,540,541,544,547,548,554,556,557,558,561,564,565,571,572,579,580,584,585,589,590,593,594,597,598,600,606,607,608,613,617,618,619,624,628,629,630,635,636,641,642,646,647,651,652,656,659,660,663,664,669,678,684,685,686,691,692,699,700,703,704,707,708,713,714,719,720,723,724,730,731,735,736,741,742,749,750,751,754,755,760,761,768,771,772,775,776,777,793,796,800,801,809,810,811,813,816,817,820,821,824,825,828,829,832,833,837,838,841,842,845,846,850,851,854,855,859,860,863,864,867,868,869,872,883,884,885,889,894,899,900,901,902 ./.build/checkouts/swift-package-manager/Sources/Basic/Lock.swift:3,6,10,13,17,20,21,27,28,29,32,33,40,43,50,51,61,63,68,72,73,74,79,80,84,85,91,92 ./.build/checkouts/swift-package-manager/Sources/Basic/TemporaryFile.swift:3,6,10,15,19,24,27,28,36,37,38,39,52,54,55,61,67,70,73,77,80,83,86,107,112,116,119,120,125,126,127,128,132,133,134,152,153,169,170,171,172,177,180,183,203,208,211,212,214,215,222,223,224,225,229,230 ./.build/checkouts/swift-package-manager/Sources/Basic/DiagnosticsEngine.swift:3,6,10,12,15,18,19,24,25,26,30,34,40,41,42,50,51,59,60,68,69,85,91,92,95,98,104,105,111,112,113,116,119,122,157,158,159,164,165,169,170,171,176,177,180,185,188,191,194,195,199,200,203,210,213,216,228,229,233,234,235,251,252,254,256,259,262,266,268,273,277,278,281,282,285,288,289,298,299,300,301,302,307,308,309,315,318,319,320,327,328,334,335,337 ./.build/checkouts/swift-package-manager/Sources/Basic/EditDistance.swift:3,6,10,32,33,34,36 ./.build/checkouts/swift-package-manager/Sources/Basic/misc.swift:3,6,10,14,24,25,26,28,45,49,52,53,72,76,77,88,89,92,96,102,103,105,106,116,119,123,124,125,129,130,135,136,142,143,144,149,150 ./.build/checkouts/swift-package-manager/Sources/Basic/JSON.swift:3,6,9,11,16,18,25,28,34,37,40,43,46,49,50,53,56,57,69,70,71,72,93,94,95,96,98,106,108,109,113,114,115,120,121,125,145,154,162,164,165,166,167,169,171,175,176,184,193,200,201,213,214,223,225,239,241,244,245,246,251,260,261,262,266,267,274,275,276,278,282,283,284,288,289,290,294,295,296,300,301,302,306,307,308,312,313,314,318,319,320,324,325,326,330,331,332,338,339,340,341,345,346,347,351,352 ./.build/checkouts/swift-package-manager/Sources/Basic/Thread.swift:3,6,10,12,17,21,24,27,32,43,48,49,50,52,53,57,58,64,65,66,67,68,72,75,78,79,82,83 ./.build/checkouts/swift-package-manager/Sources/Basic/Path.swift:3,6,10,39,40,43,47,48,57,58,67,68,69,80,82,90,91,94,95,99,100,110,111,112,117,118,122,123,129,130,135,136,142,143,147,148,152,153,159,167,168,173,174,175,186,187,192,195,198,201,206,207,214,215,216,235,244,245,253,254,255,260,261,265,266,272,273,278,279,284,285,293,294,295,300,301,305,306,307,312,313,317,318,319,324,325,326,331,332,336,337,338,343,344,348,349,350,359,371,376,380,381,390,395,399,400,403,404,407,408,419,420,440,441,444,445,446,452,453,463,464,465,466,485,501,507,510,511,518,519,520,521,528,535,538,541,560,565,566,568,573,582,583,584,589,592,593,600,603,621,627,634,635,637,642,650,651,652,656,659 ./.build/checkouts/swift-package-manager/Sources/Basic/Await.swift:3,6,10,19,20,28,29,33,34,36 ./.build/checkouts/swift-package-manager/Sources/Basic/OrderedSet.swift:3,6,10,16,22,25,30,31,40,41,42,44,47,50,53,57,58,69,71,72,78,79,85,86,91,92,93,101,102,103,109,110,111,114,115 ./.build/checkouts/swift-package-manager/Sources/Basic/RegEx.swift:3,6,10,12,18,30,31,46,51,52,53,54 ./.build/checkouts/swift-package-manager/Sources/Basic/OutputByteStream.swift:3,6,10,13,17,18,22,23,49,52,55,58,59,67,68,69,74,75,90,113,122,123,124,125,126,135,139,142,145,149,153,154,156,160,161,165,166,170,171,173,178,179,182,183,186,187,190,191,200,201,206,207,211,212,225,228,229,233,241,247,251,252,256,259,264,266,267,268,279,283,284,285,289,290,294,295,296,300,301,302,306,307,308,312,313,314,318,319,320,321,327,328,330,337,338,343,344,349,350,355,356,360,361,362,366,367,368,372,373,374,378,379,380,384,385,386,390,391,392,396,397,398,402,403,404,406,412,415,418,419,420,424,427,431,432,433,437,440,446,447,448,452,456,459,464,465,466,470,476,479,485,487,488,489,493,496,502,504,505,506,512,516,522,524,525,526,530,534,540,541,543,544,545,546,555,560,565,566,567,568,571,575,580,581,585,586,587,588,589,592,595,600,601,608,609,613,614,617,618,621,624,625,626,629,634,635,638,639,640,643,646,649,652,658,659,676,680,681,685,686,687,690,691,702,704,705,706,716,718,719,720,721,724,725,731,735,736,737,738,743 ./.build/checkouts/swift-package-manager/Sources/Basic/PathShims.swift:3,6,10,15,19,23,35,37,38,45,46,54,56,57,65,67,68,74,76,77,84,85,90,91,98,99,105,106,111,114,116,129,130,135,138,140,150,151,158,161,171,172,184,186,187,191,193,194,195,196,204,213,214,215 ./.build/checkouts/swift-package-manager/Sources/Basic/Tuple.swift:3,6,10,19,20,22 ./.build/checkouts/swift-package-manager/Sources/Basic/DictionaryLiteralExtensions.swift:3,6,10,22,24,25,26,32,36,37,39,40 ./.build/checkouts/swift-package-manager/Sources/Basic/StringConversions.swift:3,6,10,35,36,37,39,46,50,51,55,56,59,65,66,67,69,71,72,76,77,78,83,86,87,93,104,107,108,110,111,113,114 ./.build/checkouts/swift-package-manager/Sources/Basic/CollectionExtensions.swift:3,6,10,15,16,23,24,25 ./.build/checkouts/swift-package-manager/Sources/Basic/ProcessSet.swift:3,6,10,13,17,18,23,26,29,32,35,38,41,45,46,59,61,62,63,71,72,75,88,89,90,93,94,96,101,105,106,109,110,117,118,119,120 ./.build/checkouts/swift-package-manager/Sources/Basic/TerminalController.swift:3,6,10,13,17,22,25,28,29,33,38,42,54,55,56,57,60,63,66,69,72,76,80,81,87,89,90,94,95,100,103,104,113,114,123,126,127,131,132,137,138,143,144,149,150,155,156,162,163,169,171,172 ./.build/checkouts/swift-package-manager/Sources/Basic/CStringArray.swift:3,6,10,12,20,24,25,29,30,31 ./.build/checkouts/swift-package-manager/Sources/Basic/OrderedDictionary.swift:3,6,10,15,19,23,28,29,37,43,44,45,46,60,61,66,67,76,80,81,82,88,89,90,91,99,100,103,104,105,113,114 ./.build/checkouts/swift-package-manager/Sources/Basic/GraphAlgorithms.swift:3,6,10,14,15,25,34,35,36,37,39,40,68,69,77,81,82,85,86,97,98,100,101,118,126,127,131,132,137,138,142,143,146 ./.build/checkouts/swift-package-manager/Sources/Basic/ByteString.swift:3,6,10,27,31,32,36,37,41,42,46,47,51,52,56,57,61,62,63,70,71,73,74,82,83,84,93,94,95,99,100,101,106,107,108,113,116,119,122,123 ./.build/checkouts/swift-package-manager/Sources/Basic/DeltaAlgorithm.swift:3,6,10,31,33,41,44,45,56,57,61,64,66,67,78,79,83,84,89,91,92,107,108,121,122,123,125,126 ./.build/checkouts/swift-package-manager/Sources/Basic/JSONMapper.swift:3,6,10,15,16,18,23,26,29,30,35,36,40,41,45,46,51,52,56,57,64,66,67,74,76,77,83,86,88,89,92,93,99,101,102,105,106,110,112,113,114,116,121,123,124,125,130,132,133,134,139,141,142,143,148,150,151 ./.build/checkouts/swift-package-manager/Sources/Basic/SortedArray.swift:3,6,10,13,16,20,25,26,32,35,36,41,42,45,48,51,58,59,60,62,65,66,68,69,75,79,80,83,85,90,92,106,107,108,115,116,117,121,122,125,126,127,130,133,134,137,138,141,142,145,146,149,150,151,155,156,157,162,163 ./.build/checkouts/swift-package-manager/Sources/clibc/libc.c:3,6,10,14 ./.build/checkouts/swift-package-manager/Sources/clibc/include/clibc.h:2,6,9,16,23 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/Version+StringLiteralConvertible.swift:3,6,10,12,23,24,25,28,29,32,33,34,36,43,44,48,56,58,62,67,68,73,74 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/BuildSettings.swift:3,6,10,14,17,18,21,24,25,28,31,35,36,47,48,49,52,55,58,61,62,66,69,70,76,77,83,85,86,90,91,92,96,99,100,106,107,113,115,116,120,121,122,126,129,130,134,135,139,140,141,145,148,149,153,154,158,159,163,164 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/PackageDependency.swift:3,6,10,12,20,21,29,30,41,42,55,56,63,65,66,72,73,77,78,82,83,87,88 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/Target.swift:3,6,10,13,19,20,32,33,36,42,52,58,62,63,66,71,74,79,82,85,88,91,94,124,129,130,131,157,158,183,184,202,204,205,221,222,225,235,239,240,244,245,249,250,254,255,256,257,266,267,275,276,285,286,287,289,297,298 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/Version.swift:3,6,10,13,16,19,22,25,28,43,44,45,50,53,54,57,58,61,62,67,68,71,79,80,81,83,84,85,91,94,96,97,98,103,104 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/ManifestVersion.swift:3,6,10,18,22,23,33,38,39 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/PackageRequirement.swift:3,6,10,12,20,21,29,30,38,39,48,49,58,59,65,66,73,74,94,112,114,115 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/LanguageStandardSettings.swift:3,6,10,25,26,39,40,49,54,55,60,72,73,76,77 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/Package.swift:3,6,10,17,20,23,39,47,48,49,52,55,60,61,62,65,70,75,78,81,84,87,95,98,101,125,151,153,165,166,167,168,171,179,188,189,198,199,200,202,215,216,220,226,228,242,243,244,249,250,254,255,266,275,277,278,279,285,286,291,292,307,320,322,323,324,326,331,332,336,337,346,349 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/Product.swift:3,6,10,16,17,20,23,24,29,30,33,37,38,45,46,47,53,54,59,60,63,68,73,74,82,83,84,92,93,100,101,105,106 ./.build/checkouts/swift-package-manager/Sources/PackageDescription4/SupportedPlatforms.swift:3,6,10,13,16,19,20,26,27,30,33,36,41,42,46,47,53,54,58,59,65,66,70,71,77,78,82,83,89,90,91,97,100,103,104,110,111,115,118,121,122,127,128,132,135,138,139,145,146,150,153,156,157,162,163,164,169,170,175,176,184,185,187,188 ./.build/checkouts/swift-package-manager/Sources/swift-test/main.swift:3,6,10,12 ./.build/checkouts/swift-package-manager/Sources/swiftpm-manifest-tool/main.swift:3,6,10,15,18,22,23,28,29,33,36,41,42,47,48,51,52,54,58,59,62,65,69,70,73,75,76,77,80,84,90,96,101,106,110,112,117,120,123,126,129,130,135 ./.build/checkouts/swift-package-manager/Sources/PackageModel/PackageModel+Codable.swift:3,6,10,13,17,18,29,30,31,36,46,47,48,49,53,54,64,65,66,71,81,82,83,84,88,89,107,108,109,114,134,135,136,137,141,142,156,157,158,163,178,179,180 ./.build/checkouts/swift-package-manager/Sources/PackageModel/ResolvedModels.swift:3,6,10,12,15,18,21,24,29,30,31,36,37,38,39,42,46,47,50,59,61,62,66,67,71,72,76,77,82,83,86,87,88,91,94,98,99,103,104,108,109,112,115,118,129,130,133,134,135,137,140,144,145,148,152,153,156,163,164,169,176,177,180,181,182,184,192,193,194,196,204,207,208 ./.build/checkouts/swift-package-manager/Sources/PackageModel/BuildSettings.swift:3,6,10,12,16,21,22,23,24,27,30,36,42,47,50,53,54,59,60,66,67,68,71,72,73,78,81,82,83,88,92,96,97,98,102,105,106,111,112,113,120,123,126,131,132,138,139,141,144,148,149,150,154,155,156,158,159,161,162,163 ./.build/checkouts/swift-package-manager/Sources/PackageModel/ToolsVersion.swift:3,6,10,12,15,18,22,28,31,42,46,47,51,52,56,57,60,66,76,77,83,84,86,89,90,92,95,96,97,100,103,106,109,112,117,122,125,128,137,141,144,145,149,150,152,155,156,158,161,162,165,166,168,171,172,175,176,179,180,181,186,187,192,193 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Target.swift:3,6,10,12,20,21,27,30,33,36,39,42,45,48,52,53,56,74,75,76,78,81,91,98,100,108,110,111,114,136,137,138,140,143,146,150,151,155,176,177,178,180,183,186,189,192,195,223,224,225,229,230,231,239,241,242 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Sources.swift:3,6,10,13,18,21,22,27,28,34,37,38,39,57,62,67,72,77,86,87,88,92,93,102,103 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Platform.swift:3,6,10,13,17,20,23,28,29,33,34,35,40,46,51,52,58,59,62,65,68,74,76,77,93,94,95,97,100,101,103,106,107,108,113,116,120,121 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Package.swift:3,6,10,13,16,48,51,55,56,59,62,67,72,87,88,91,92,100,102,103,104,105,109,110,111,113,114,119,124,128,129,131,132,135,138,143,147,155,156,159,160,163,164,170,171,179,180,184,185,188,189 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Manifest.swift:3,6,10,13,19,33,34,35,41,42,43,52,53,54,55,59,62,65,71,77,80,83,86,89,92,95,98,101,104,107,110,113,144,145,148,149,154,155,160,167,168,179,180,181,184,190,191,197,200,201,204,205,206,209,212,215,218,224,225,228,231,234,237,240,243,260,261,272,273,274,277,280,283,286,296,297,298,303,304,307,315,318,319,322,323,336,337,338,339,342,345,350,351,352,356,360,361,362,365,368,371,376,377,378,385,386,393,395,396,399,402,405,408,414,431,432,437,438,439 ./.build/checkouts/swift-package-manager/Sources/PackageModel/Product.swift:3,6,10,12,15,18,21,24,27,28,31,34,37,52,53,54,55,56,58,61,64,70,73,76,82,85,90,91,92,96,97 ./.build/checkouts/swift-package-manager/Sources/Commands/Options.swift:3,6,10,15,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,78 ./.build/checkouts/swift-package-manager/Sources/Commands/GenerateLinuxMain.swift:3,6,10,14,20,23,24,27,30,34,35,45,47,53,55,59,71,74,75,78,81,83,86,87,90,92,95,96,100,102,107,112,116,117,120,121,122,124,129,132,133,135,139,143,144,147,148,149,153,157,158,161,162,163,166,174,176,179,180,181,182,191,192,200,201,204,205,208,209 ./.build/checkouts/swift-package-manager/Sources/Commands/SwiftTestTool.swift:3,6,10,12,18,20,21,30,32,33,41,43,44,53,55,56,65,67,69,71,72,81,83,84,88,89,97,98,99,100,107,108,111,112,115,116,119,120,122,123,126,129,132,135,138,140,143,144,155,156,163,164,167,176,177,179,182,186,193,197,198,209,217,222,223,236,241,242,246,250,251,264,265,266,269,270,273,274,283,288,289,294,295,308,311,312,315,316,317,318,323,327,328,331,332,337,341,348,349,351,353,354,367,371,372,379,380,383,384,391,392,394,399,404,409,414,419,423,427,433,438,439,452,458,460,461,482,492,493,498,501,507,508,512,513,514,515,516,521,524,528,529,530,538,541,543,546,549,551,553,574,575,582,586,592,595,596,618,621,623,624,639,642,644,645,648,649,650,658,659,662,665,668,671,674,677,680,682,685,688,691,694,711,716,717,720,722,723,729,730,735,736,744,750,751,752,758,776,778,779,783,787,791,795,796,801,802,803,806,809,814,815,816,820,821,822,829,831,832,833,836,841,844,845,848,851,863,864,877,878,884,885,891,896,901,904,905,906,907,914,915,928,929,930,931,935,936,937,945,957,958,965,966,971,975,976,980,981,985,988,991,992,998,1001,1004,1010,1012,1020,1022,1025,1026,1028,1029,1032,1034,1035 ./.build/checkouts/swift-package-manager/Sources/Commands/Error.swift:3,6,10,18,22,25,26,34,35,36,37,40,44,47,48,49,52,56,60,63,64,65,71,72,74,76,81,82,86,87,97,98,105,106,107,113,116,119,122,125,130,131,139,140,141,142,150,151,152,160,161 ./.build/checkouts/swift-package-manager/Sources/Commands/SwiftRunTool.swift:3,6,10,16,19,24,27,30,31,42,43,44,45,54,56,57,64,67,69,70,73,76,79,82,85,86,91,92,95,104,105,110,114,117,122,133,134,138,141,146,147,152,153,156,157,158,167,168,173,177,178,182,183,185,186,187,194,195,198,199,210,212,214,215,221,226,235,240,241,242,245,249,250 ./.build/checkouts/swift-package-manager/Sources/Commands/SwiftTool.swift:3,6,10,24,32,34,35,44,46,47,56,57,66,68,69,78,80,81,83,86,91,92,97,98,100,101,106,107,109,110,115,116,121,122,127,128,133,134,140,141,142,145,146,151,152,153,156,159,162,164,167,168,169,173,176,179,184,186,187,191,192,195,198,202,205,209,212,215,218,221,225,234,236,243,250,253,275,281,287,292,298,303,307,311,316,321,325,329,335,340,345,350,354,359,364,369,374,378,381,385,388,395,396,401,412,415,417,421,422,426,431,434,435,436,439,440,443,444,449,450,453,454,457,461,468,473,492,493,504,509,511,512,518,519,520,524,525,534,535,540,545,546,551,552,553,561,569,574,578,579,580,584,585,588,589,599,600,601,605,607,608,613,614,620,623,628,630,631,638,639,640,646,650,651,657,660,672,674,678,679,686,692,699,700,703,704,705,709,714,729,737,741,749,760,765,766,767,772,775,778,781,782,795,801,807,809,810,811,812,818,825,826,828,829,836,837,862,865,868,869,875 ./.build/checkouts/swift-package-manager/Sources/Commands/SwiftPackageTool.swift:3,6,10,21,29,31,32,40,42,44,45,53,55,56,59,68,69,74,79,80,83,89,90,97,98,103,104,106,111,115,116,118,119,123,129,131,134,137,144,148,151,162,163,166,171,174,182,187,194,198,201,207,212,214,221,222,225,228,240,242,245,253,255,263,264,270,279,285,290,291,295,311,315,318,319,320,328,330,348,354,359,368,374,389,399,408,414,421,425,436,438,452,454,463,465,501,511,521,536,540,541,542,548,551,552,553,555,557,559,562,569,570,572,575,581,584,585,587,593,595,600,602,607,609,613,615,616,635,639,640,649,650,651,659,660,661,668,669,670,679,680,681,685,686,687,691,692 ./.build/checkouts/swift-package-manager/Sources/Commands/show-dependencies.swift:3,6,10,13,25,27,28,31,32,37,41,42,44,46,53,54,55,56,62,63,64,65,73,74,75,78,79,80,81,91,94,95,96,97,103,104,112,113,114,115,126,127,129,130,131,134,147,148,149,156,157,158 ./.build/checkouts/swift-package-manager/Sources/Commands/Completions+zsh.swift:3,6,10,14,23,29,63,64,69,70,75,76,77,79,80,85,89,90,91,93,96,98 ./.build/checkouts/swift-package-manager/Sources/Commands/Completions+bash.swift:3,6,10,14,17,24,26,28,30,37,39,41,50,52,56,71,73,80,81,84,85,88,89,90,92,97,101,105,106,107,109,112,114 ./.build/checkouts/swift-package-manager/Sources/Commands/SwiftBuildTool.swift:3,6,10,15,26,28,30,31,34,43,44,53,55,59,62,65,66,67,73,78,83,88,89,97,98,101,102,103,104,110,113,116,117,121,124,125,128,129,132,133,137,138,140,141,144,147,150,153,154,158,161,164,165,169,181,182,183,184,188,189 ./.build/checkouts/swift-package-manager/Sources/Commands/WatchmanHelper.swift:3,6,10,15,23,25,26,28,31,34,37,40,42,53,54,58,59,62,70,72,76,78,79,86,89,91,94,95,99,102,103 ./.build/checkouts/swift-package-manager/Sources/Commands/Describe.swift:3,6,10,13,17,20,21,28,30,31,33,43,44,45,52,53,54,56,70,71,81,82,83,87,88,89,93,94 ./.build/checkouts/swift-package-manager/Sources/Build/llbuild.swift:3,6,10,15,18,21,24,27,30,33,39,40,43,46,49,53,54,57,60,67,73,78,79,83,84,86,87,88,92,105,106,107,114,115,127,128,130,136,137,139,140,158,159,165,166,172,183,184,185,190,196,201,204,205,206,207,215,216,219,224,228,234,235,236,237,248,254,255,256,260,261,264,265,266,280,281,282,285,286 ./.build/checkouts/swift-package-manager/Sources/Build/Command.swift:3,6,10,12,19,23,24,31,34,38,43,44,45,49,50 ./.build/checkouts/swift-package-manager/Sources/Build/BuildPlan.swift:3,6,10,17,19,28,29,34,44,46,47,50,53,57,58,63,64,68,69,73,74,77,80,83,90,91,100,110,117,118,120,121,124,127,130,133,136,139,143,148,151,154,155,158,159,186,187,198,199,202,204,205,213,217,219,220,227,228,229,233,234,235,238,241,244,252,253,254,255,258,261,265,266,269,272,276,277,281,282,285,288,292,293,303,304,305,309,316,317,324,330,339,340,344,349,351,354,357,361,363,364,369,373,379,383,386,389,391,392,401,404,405,406,410,416,417,419,420,421,436,437,438,442,443,444,447,450,453,457,458,462,463,467,468,472,473,476,480,481,484,492,493,499,508,509,518,522,523,527,528,532,533,536,540,541,546,550,554,557,563,569,572,574,575,579,585,586,588,589,597,598,599,603,604,605,608,611,614,618,619,623,630,643,644,645,646,651,655,658,661,665,666,670,671,677,678,687,688,695,701,702,707,711,712,725,734,735,737,738,743,745,753,754,755,758,763,764,768,771,772,775,776,780,786,792,797,798,800,801,802,805,809,812,819,820,821,822,825,828,831,834,838,839,843,844,847,850,862,866,875,876,877,878,891,892,893,897,898,902,903,908,912,916,917,918,925,926,931,932,941,944,947,948,954,955,956,966,967,968,972,976,977,982,987,990,991,998,999,1000,1004,1010,1011,1020,1028,1037,1038,1040,1045,1055,1062,1063,1068,1069,1070,1071,1075,1076,1077,1079,1080,1092,1093,1094,1095,1105,1119,1120,1121,1122,1128,1132,1135,1143,1144,1145,1146,1151,1152,1153,1155,1156,1162,1167,1175,1178,1179,1182,1183,1194,1197,1201,1202 ./.build/checkouts/swift-package-manager/Sources/Build/Toolchain.swift:3,6,10,13,17,20,23,28,31,34,37,38,42,43,46,47 ./.build/checkouts/swift-package-manager/Sources/Build/BuildDelegate.swift:3,6,10,15,24,26,27,36,38,39,48,50,51,61,63,65,66,75,77,79,80,89,91,93,94,103,105,107,108,120,122,125,126,138,140,143,144,156,158,161,162,169,170,171,172,181,184,185,188,199,200,201,202,210,221,222,225,226,229,230,233,234,237,238,242,243,244,246,247,250,253,262,263,264,265,268,269,271,272,275,276,279,280,283,284,291,292,295,296,298,299,302,303,308,309,315,316,319,320,323,324 ./.build/checkouts/swift-package-manager/Sources/Build/Triple.swift:3,6,10,21,26,31,32,41,42,46,47,53,60,61,65,66,69,72,73,76,77,79,82,83,86,92,93,98,99,100,102,103,106,107,110,111,114,115,122,123,133,153,154,165,166,167 ./.build/checkouts/swift-package-manager/Sources/Build/SwiftCompilerOutputParser.swift:3,6,10,13,20,21,25,26,29,30,35,36,39,40,45,48,49,52,58,59,62,65,68,71,74,78,79,85,91,92,93,94,96,101,104,105,106,114,119,124,127,131,132,136,142,143,144,145,150,151,154,155,158,159,165,170,171,172,173,178,179,184,185,186,190,191,206,207,208,209,213 ./.build/checkouts/swift-package-manager/Sources/Build/ToolProtocol.swift:3,6,10,15,20,23,28,29,33,38,39,40,47,53,60,63,64,65,66,73,82,83,84,85,89,94,95,96,99,102,106,107,110,112,116,117,146,147 ./.build/checkouts/swift-package-manager/Sources/Build/Sanitizers.swift:3,6,10,13,19,26,27,28,29,34,40,41,45,46,50,51,55,56,59,60,61,68 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/BuildFlags.swift:3,6,10,16,19,22,25,28,39,40 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Process.swift:3,6,10,12,23,25,26 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/ArgumentParserShellCompletion.swift:3,6,10,13,15,17,26,35,38,49,51,53,55,56,58,62,63,65,75,76,82,87,88,93,95,98,107,109,111,116,117,118,120,123,124,125,133,135,136,149,155,161,163,164,165,167,173,179,182,183,189,191,192,196,198,206,211,213,220,227,229,234,236,238,241,242,243,250,251,258,261,262,268,277,280,281,282,283,291,292 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Version.swift:3,6,10,12,15,18,21,24,27,30,45,46,47,49,52,53,57,60,61,64,65,68,69,74,75,78,86,87,88,90,91,92,98,101,103,104,105,107,115,121,123,127,132,133,140,141,142,144,148,150,151,154,155,158,159,160,165,168,170,171,174,175,182,183,184,189,190,194,199,200,202,203,204,206,212,213,214,222,223,225,231,232,233,235,242,243,249,250,251,254,255 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/StringExtensions.swift:3,6,10,22,24,25,34,35,36,40,43,48,57,58,59,68,69,70,72,73,83,84,85 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/misc.swift:3,6,10,13,23,31,33,34,44 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/StringMangling.swift:3,6,10,14,33,35,37,38,222,224,241,242,243,249,250,255,256 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/FSWatch.swift:3,6,10,15,19,20,23,26,29,32,33,36,37,38,41,44,49,53,62,65,75,76,77,84,85,92,93,100,101,102,107,108,116,118,120,124,125,128,133,134,138,141,142,147,150,158,160,163,166,169,176,179,182,185,188,191,206,207,210,213,216,219,222,225,228,231,234,237,240,243,246,254,255,258,263,264,265,268,271,273,276,280,281,283,284,287,290,291,292,299,300,305,306,310,313,314,318,319,326,331,334,340,344,346,349,352,359,360,361,364,369,374,378,379,385,386,388,389,390,391,397,401,406,410,413,414,419,420,427,428,429,430,431,432,434,435,438,439,440,442,445,446,469,470,471,494,495,496,498,500,502,512,515,518,521,522,523,526,527,530,534,535,541,544,547,550,553,560,564,575,576,588,593,599,602,603,607,608 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/InterruptHandler.swift:3,6,10,14,20,24,27,35,39,54,55,69,73,74,76,78,79,85,86 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Verbosity.swift:3,6,10,15,24,25,26,36,37,38,39 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/SimplePersistence.swift:3,6,10,12,18,21,22,25,26,32,35,36,37,38,47,49,50,53,56,59,62,65,79,80,87,88,89,94,99,104,107,110,111,113,114,122,123,127,128,130,131,134,139,140,143,146,151,152,156,157 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/PkgConfig.swift:3,6,10,14,19,28,29,30,31,39,41,42,46,49,60,74,81,82,83,84,97,98,100,101,102,107,110,113,116,119,122,148,152,155,168,169,170,173,174,178,180,181,182,195,200,201,206,208,209,212,220,232,233,234,235,249,250,251,260,265,266,282,283,287,288,300,304,305,307,308,325,326,337,346,347,349,350,359,364,365,366,376,381,382,386,389,390 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Versioning.swift:3,6,10,12,19,22,25,32,38,41,43,44,50,52,53,63,64,65,66,70,71,74,80,84 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/URL.swift:3,6,10,12,19,29,30,31,35,36,37,39,40 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Platform.swift:3,6,10,13,18,22,23,35,38,40,41,46,57,59,71,72 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/CollectionExtensions.swift:3,6,10,14,18,30,31,33,34,35 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Git.swift:3,6,10,13,23,24,25,26,33,40,42,43,44,47,48,56,57,58,61,69,70,71,78,85,90,94,96,97,99,100 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/Diagnostics.swift:3,6,10,12,15,18,19,27,29,31,34,35,36,39,42,44,47,48,49,51,55,56,71,72,73,80,81,98,99,100,119,120,121,122,125,129,132,135,139,140,145,148,149,150,153,156,159,163,164,167,168,169,170,178,179,194,197,204,206,209,212,213 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/ProgressAnimation.swift:3,6,10,12,21,26,29,30,37,41,42,49,50,56,57,59,60,65,66,67,69,70,71,75,78,79,82,86,87,89,90,92,93,94,99,102,103,106,108,116,117,119,120,124,125,126,129,130,131,140,141,142,148,152,153,156,162,163,168,169,171,172,174,175,176,182,186,187,192,193,196,203,204,210,213,217,225,226,228,229,233,234,239,240,241,250,251,252,256,267,271,272,273,276,277,280,281,284,285 ./.build/checkouts/swift-package-manager/Sources/SPMUtility/ArgumentParser.swift:3,6,10,14,17,20,23,26,29,32,33,47,48,49,50,54,57,60,63,64,74,75,76,77,93,94,95,96,101,106,107,112,115,118,121,124,125,133,136,137,139,143,144,146,147,152,153,155,156,158,159,169,170,171,173,174,181,182,187,188,190,191,192,198,205,206,207,209,210,215,218,221,226,231,232,234,241,242,246,247,248,250,251,252,261,264,268,271,274,277,280,288,289,292,295,296,299,300,301,306,307,313,315,317,320,322,324,326,334,335,341,342,343,349,350,354,355,359,360,362,363,364,368,370,372,375,377,379,381,383,391,392,398,399,400,403,405,411,414,415,417,418,419,425,427,429,431,433,435,437,440,443,446,457,458,470,471,474,475,478,479,482,483,484,492,495,498,501,502,506,511,514,517,520,525,526,546,548,549,550,556,557,561,562,566,567,571,572,582,583,586,588,589,594,596,597,602,604,605,606,609,613,616,619,622,625,628,633,648,649,657,658,668,672,673,684,688,689,702,705,706,710,711,725,728,729,733,734,742,743,745,750,753,758,759,762,763,768,769,770,774,775,784,788,792,796,807,812,813,817,818,829,830,836,837,844,849,851,852,858,868,869,885,887,888,890,897,898,907,908,912,913,914,922,923,924,931,932,933,937,938,941,942,943,948,951,954,955,964,965,966,975,976,977,987,988,989,999,1000,1001,1013,1014,1015,1029,1030,1031,1040,1041,1042,1052,1053,1054,1063,1064,1065,1075,1076,1077,1086,1087,1088,1092,1093,1098,1099,1104,1105,1106 ./.build/checkouts/swift-package-manager/Sources/swift-run/main.swift:3,6,10,12 ./.build/checkouts/swift-package-manager/Sources/swift-package/main.swift:3,6,10,12 ./.build/checkouts/swift-package-manager/Sources/swift-build/main.swift:3,6,10,12 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/ManifestLoader.swift:3,6,10,18,22,25,27,29,30,38,41,46,47,50,53,54,55,66,72,73,76,80,81,82,83,102,103,128,129,130,134,135,144,149,152,163,164,174,175,192,193,209,212,217,218,227,228,237,241,242,259,261,263,264,270,271,272,286,287,291,292,297,299,300,308,313,318,322,330,339,344,348,356,357,360,361,363,364,379,380,385,393,394,399,400,407,410,412,415,429,431,432,436,437,442,443,447,451,454,456,457,475,478,479,483,486,490,491,492,504,505,506,507,509,511,513,515,528,529,530,531,537,541,544,545,547,549,552,557,558,563,566,567,573,574,575,581,585,586,589,590,592,596,597,601,602,603,607,611,613,614,616,618,620,624,625,628,632,634,635,638,639,644,645,646,652,656,657,660,661,663,667,668,674,675 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/ManifestBuilder.swift:3,6,10,12,25,29,34,35 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/PackageBuilder.swift:3,6,10,14,17,22,23,26,29,32,35,38,41,44,47,50,53,56,59,62,63,92,102,103,104,105,113,114,115,116,118,121,127,128,131,134,135,136,146,147,148,149,155,156,157,158,164,165,166,174,175,176,177,185,188,191,194,197,202,205,232,233,240,249,250,253,254,258,261,271,272,273,274,276,277,279,284,285,287,290,293,296,303,304,306,307,311,315,316,317,320,321,332,333,336,337,342,343,346,350,353,354,358,366,367,376,377,388,389,395,396,400,401,403,404,407,410,416,420,422,423,428,435,436,440,441,446,449,451,452,458,460,461,469,470,479,480,499,501,505,508,513,526,531,533,536,539,551,553,566,567,569,570,578,579,580,588,594,595,603,604,609,610,616,617,625,626,629,632,645,646,650,651,657,660,665,666,670,671,675,681,684,706,708,721,722,723,728,732,736,742,743,748,749,758,759,766,767,774,775,786,787,788,792,796,797,802,803,806,807,809,810,815,816,818,821,826,828,829,832,836,841,843,844,847,849,853,854,859,860,862,868,873,876,878,881,889,890,891,895,896,897,902,905,913,914,922,924,929,930,931,936,938,939,943,952,953,954,964,968,974,983,987,988,991,1001,1005,1006,1018,1020,1027,1030,1031,1032,1044,1045,1046,1059,1060,1061,1063,1064,1080,1081,1082,1084,1085,1086,1087,1090,1093,1096,1100,1101,1104,1109,1113,1114,1115,1126,1130,1131 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/PackageDescription4Loader.swift:3,6,10,14,28,31,33,34,38,39,42,47,49,50,51,55,56,60,63,67,68,71,78,81,84,86,91,92,94,95,97,98,103,107,120,121,128,129,131,132,136,140,141,145,146,150,154,155,161,162,169,170,171,176,180,183,184,191,192,193,194,206,207,208,209,213,217,220,231,232,234,237,238,239,240,248,249,250,257,260,265,269,272,275,276,277,278,282,287,288,292,293,298,299,301,302,307,308,309,321,322,323,324,328,332,336,339,342,343,344 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/ToolsVersionLoader.swift:3,6,10,15,18,27,28,44,45,46,51,57,58,62,65,68,72,80,81,82,84,85,86,88,90,93,94,97,102,103,104,105,113,115,116,120,132,135,136,140,142,143,156,160,161,169 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/Diagnostics.swift:3,6,10,14,16,27,29,32,35,36,47,49,52,55,56,72,74,76,78,79,89,92,93,102,104,105,113,115,117,118,125,127,129,130,137,139,141,142,149,151,152,160,162,164,165,166,174,176,178 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/ModuleMapGenerator.swift:3,6,10,13,15,19,21,22,26,27,30,31,32,36,37,40,41,42,54,57,60,63,72,73,76,81,82,83,88,92,93,101,102,104,107,114,117,119,126,131,134,136,138,139,149,150,151,155,156,165,168,171,173,178,180,181,182,188,189,190,191,207,208,209 ./.build/checkouts/swift-package-manager/Sources/PackageLoading/Target+PkgConfig.swift:3,6,10,14,17,20,23,26,29,32,38,39,40,54,55,56,61,65,74,77,80,85,86,96,97,98,106,107,108,116,120,121,123,124,139,144,145,149,150,151,155,156,157,175,176,181,182,187,188,190,192,193,196,198,199,215,221,225,229,230,232,234,235,239,243,244,247,248,249,257,259,261,264,265,266,275,277,280,284,285 ./.build/checkouts/swift-package-manager/Sources/SourceControl/InMemoryGitRepository.swift:3,6,10,15,21,22,33,39,42,46,47,48,51,54,57,61,62,66,67,70,73,76,83,84,92,96,97,111,112,117,123,124,129,136,137,146,160,161,162,165,166,171,173,174,177,178,181,182,183,185,188,189,192,193,196,197,200,201,204,205,208,209,212,213,216,217,220,221,224,225,229,230,233,234,237,238,239,243,244,247,248,251,252,256,257,258,262,263,266,267,270,271,274,275,278,279,282,283,284,289,292,295,298,299,305,306,310,311,314,317,318,321,322,332,333,336,337,340,341 ./.build/checkouts/swift-package-manager/Sources/SourceControl/SwiftPMConfig.swift:3,6,10,12,15,21,24,27,28,29,32,37,40,47,48,52,53,58,59,70,72,73,77,78,82,83,87,88,89,92,95,96,102,103,108,109,110,115,118,122,123 ./.build/checkouts/swift-package-manager/Sources/SourceControl/RepositoryManager.swift:3,6,10,13,16,21,24,27,30,31,37,38,41,44,50,53,56,59,60,63,66,72,75,83,89,90,97,98,103,104,115,116,123,124,125,128,131,134,141,146,149,152,158,161,164,184,188,193,202,205,206,207,230,236,240,241,244,245,247,250,251,254,261,265,266,279,280,284,285,298,299,300,304,305,306,307,308,314,318,319,328,330,331,332,337,338,350,351,358,364,365,366,373,374,375,381,382,383,386,396,397,400,401,402,406,407 ./.build/checkouts/swift-package-manager/Sources/SourceControl/GitRepository.swift:3,6,10,14,17,18,21,24,27,28,35,37,40,53,54,55,58,59,66,92,93,94,97,100,101,104,105,106,110,113,114,130,136,137,144,152,153,155,156,157,162,165,166,176,193,194,195,196,199,202,205,206,209,212,213,216,219,222,232,233,234,245,246,247,263,264,265,267,274,277,278,279,282,289,290,293,294,297,298,304,305,306,314,316,318,319,320,323,324,326,332,333,334,340,341,342,350,351,352,360,361,362,369,370,377,378,379,386,387,388,394,398,400,401,406,411,412,413,422,424,427,428,430,431,432,434,445,449,454,455,456,461,463,464,471,472,477,494,495,499,503,505,506,510,511,513,514,516,517,527,528,529,537,539,542,545,548,551,556,557,559,567,571,572,575,581,582,584,585,587,588,593,594,599,600,606,607,608,613,617,618,619,624,628,629,630,635,639,640,641,645,647,648,651,652,656,659,660,662,663,667,670,673,675,676,678,681,682,685,686,689,690,693,694,697,698,701,702,703,709,710,711 ./.build/checkouts/swift-package-manager/Sources/SourceControl/Repository.swift:3,6,10,12,17,21,22,31,33,34,40,42,43,44,48,49,50,55,57,58,61,62,63,74,83,99,102,109,110,114,115,116,138,144,151,156,159,175,176,182,185,190,193,197,200,203,206,211,214,217,218,222,223,224,233,236,237,238,243,245,246 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/InternalExecutableAsDependency/Foo/Foo.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/InternalExecutableAsDependency/Foo/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/InternalExecutableAsDependency/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/InternalExecutableAsDependency/Bar/Bar.swift:4 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Cat/Cat.swift:2,7 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Foo/Foo.swift:2,6 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Foo/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Baz/Baz.swift:5 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Bar/Bar.swift:3,7,10 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Complex/Sources/Sound/Sound.swift:4,7,8 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Simple/Foo/Foo.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Simple/Foo/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Simple/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/Internal/Simple/Bar/Bar.swift:4 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/FisherYates/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/FisherYates/src/Fisher-Yates_Shuffle.swift:6,11,13,14,15,21,30,31,32,33 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/deck-of-playing-cards/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/deck-of-playing-cards/src/Deck.swift:3,6,10,13,16,20,25,26,27,29,30,33,34,37,38,41,43,44,45,47,51,52 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/app/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/app/main.swift:3,6,10,14,16,18,21,22,27,28,30 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/PlayingCard/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/PlayingCard/src/Rank.swift:5,6,8,10,19,20,21,23,33,34,35 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/PlayingCard/src/PlayingCard.swift:4,8,9,10,12,14,17,18,20,24,25 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Complex/PlayingCard/src/Suit.swift:3,4,6,8,19,20,21,23,31,32,33 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Simple/Foo/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Simple/Foo/Foo.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Simple/Bar/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/Simple/Bar/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/CUsingCDep/Foo/Foo.c:2,3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/CUsingCDep/Foo/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/CUsingCDep/Bar/Package.swift:3,14,15 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/CUsingCDep/Bar/Sources/SwiftExec/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/DependencyResolution/External/CUsingCDep/Bar/Sources/SeaLover/Sea.c:2,5 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/-DSWIFT_PACKAGE/Package.swift:2,4 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/-DSWIFT_PACKAGE/Sources/SwiftExec/main.swift:2,7,9,16 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/-DSWIFT_PACKAGE/Sources/CLib/include/CLib.h:5 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/-DSWIFT_PACKAGE/Sources/CLib/foo.c:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/CSystemModule/Package.swift:3,11 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModuleUserClang/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModuleUserClang/Sources/main.c:3,7 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModule/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModule/Sources/SystemModule.c:6 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModuleUser/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PkgConfig/SystemModuleUser/Sources/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Tests/LinuxMain.swift:2,4,7 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Tests/libTests/libTests.swift:3,7,8 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Tests/libTests/XCTestManifests.swift:2,7,8,14 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Package.swift:2,4 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Sources/exec/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ThreadRace/Sources/lib/lib.swift:2,5,10,11,14,16 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/Spaces Fixture/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/Spaces Fixture/Sources/Module Name 1/Foo.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/Spaces Fixture/Sources/Module Name 2/main.swift:2,5 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageWithNonc99NameModules/Package.swift:3,12 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageWithNonc99NameModules/Sources/C D/cd.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageWithNonc99NameModules/Sources/A-B/ab.swift:2,5 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageWithNonc99NameModules/Sources/B-C/bc.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/MultipleExecutables/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/Internal/Foo/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/Internal/Package.swift:2,4 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/External/dep2/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/External/dep2/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/External/root/Package.swift:3,13 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/DependencyEdges/External/dep1/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooLib1/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooLib1/Sources/FooLib1/FooLib1.swift:3,6,7 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooLib1/Sources/cli/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/app/Package.swift:3,13 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooExec/FooExec.swift:3,7,11,12 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooExec/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooLib2/FooLib2.swift:3,6,7 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ExactDependencies/FooLib2/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ParseableInterfaces/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SystemModules/CFake/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SystemModules/TestExec/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SystemModules/TestExec/Sources/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/MissingDependency/Bar/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/MissingDependency/Bar/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/OverrideSwiftcArgs/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/OverrideSwiftcArgs/Sources/main.swift:6 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/EchoExecutable/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/EchoExecutable/Sources/secho/main.swift:6 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/UnreachableTargets/A/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/UnreachableTargets/A/Sources/ATarget/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/UnreachableTargets/C/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/UnreachableTargets/B/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/UnreachableTargets/B/Sources/BTarget1/BTarget1.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ParallelTestsPkg/Tests/ParallelTestsPkgTests/ParallelTestsFailureTests.swift:3,5,8,9 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ParallelTestsPkg/Tests/ParallelTestsPkgTests/ParallelTestsTests.swift:3,5,8,9,12,13 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ParallelTestsPkg/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/ParallelTestsPkg/Sources/ParallelTestsPkg/ParallelTestsPkg.swift:2,5 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageEdit/foo/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageEdit/baz/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageEdit/baz/Sources/baz.swift:2,4 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/PackageEdit/bar/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SwiftPMXCTestHelper/Tests/SwiftPMXCTestHelperTests/SwiftPMXCTestHelperTests.swift:3,5,7,8,10,11,13,14,16,17 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SwiftPMXCTestHelper/Tests/ObjCTests/ObjCTests.m:2,5,7,9,10,12,13,15,16 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SwiftPMXCTestHelper/Package.swift:3,12 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/SwiftPMXCTestHelper/Sources/SwiftPMXCTestHelper.swift:2,3 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/CompileFails/Package.swift:2,4 ./.build/checkouts/swift-package-manager/Fixtures/Miscellaneous/CompileFails/Foo.swift:3,5 ./.build/checkouts/swift-package-manager/Fixtures/ValidLayouts/SingleModule/ExecutableNew/Package.swift:3,5 ./.build/checkouts/swift-package-manager/Fixtures/ValidLayouts/SingleModule/Library/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ValidLayouts/SingleModule/Library/Sources/Library/Foo.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ObjCmacOSPackage/Tests/ObjCmacOSPackageTests/HelloWorldTest.m:2,4,6,8,10,13,14,20,21,27,28,34,35 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ObjCmacOSPackage/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ObjCmacOSPackage/Sources/include/HelloWorldExample.h:2,4,6 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ObjCmacOSPackage/Sources/HelloWorldExample.m:3,8,10 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibrarySources/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibrarySources/Sources/Foo.c:6 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CDynamicLookup/Foo.c:2,9 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CDynamicLookup/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/SwiftCMixed/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/SwiftCMixed/Sources/CExec/main.c:3,7 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/SwiftCMixed/Sources/SeaExec/main.swift:2,5 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/SwiftCMixed/Sources/SeaLib/Foo.c:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibraryWithSpaces/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibraryWithSpaces/Sources/Bar with spaces/Bar.c:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibraryWithSpaces/Sources/Foo/Foo.c:2,8 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibraryWithSpaces/Sources/Baz/main.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/CLibraryWithSpaces/Sources/Bar/Bar.c:3,9 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/UmbrellaHeaderFlat/UmbrellaHeader.c:2,8 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/NoIncludeDir/Jaz.c:1,7 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/FlatInclude/FlatInclude.c:2,8 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/Baz/main.swift:5 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/UmbellaModuleNameInclude/Jaz.c:2,8 ./.build/checkouts/swift-package-manager/Fixtures/CFamilyTargets/ModuleMapGenerationCases/Sources/UmbrellaHeader/UmbrellaHeader.c:2,8 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Direct/App/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Direct/App/main.swift:2 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Direct/CFoo/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Direct/CFoo/C/foo.c:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageB/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageB/Sources/y/y.swift:4,17,19,26,27 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageC/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageC/Sources/x/x.swift:4,17,19,26,27 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageA/Package.swift:3 ./.build/checkouts/swift-package-manager/Fixtures/ModuleMaps/Transitive/packageA/Sources/main.swift:4,17,19,23,26,31 ./.build/checkouts/Logger/Tests/LoggerTests/LoggerTests.swift:3,5,13,15,16,24,26,27,35,37,38,44,46,47,54,55,63,64,72,73,79,82,86,89,93,96,100,103,104,114 ./.build/checkouts/Logger/Tests/LoggerTests/XCTestManifests.swift:2,8 ./.build/checkouts/Logger/Tests/LinuxMain.swift:2,4 ./.build/checkouts/Logger/Package.swift:3,5 ./.build/checkouts/Logger/Sources/Logger/Logger.swift:2,4,7,9,12,15,16,19,20,23,24,26,29,32,33,36,37,40,41,42,43,45,48 ./Tests/PublicTests/CommandWithArgumentTests.swift:3,5,7,14,15,16,17,23,25,29,34,35,36 ./Tests/PublicTests/XCTestManifests.swift:2,9,10,15,16,24,25,33 ./Tests/PublicTests/SyntaxSugarTests.swift:3,5,11,12,15,16,22,23,26,27,33,34,37,38,44,47,50,51,54,57,60,61,62 ./Tests/PublicTests/CommandTests.swift:4,10,11,16,17,25,28,29,30,36,39,42,43 ./Tests/TestTool/Tests/LinuxMain.swift:2,4,7 ./Tests/TestTool/Tests/TestToolTests/TestToolTests.swift:3,9,13,14,16,20,23,26,29,31,32,38,43,44 ./Tests/TestTool/Tests/TestToolTests/XCTestManifests.swift:2,7,8,14 ./Tests/TestTool/Package.swift:3,5 ./Tests/TestTool/Sources/TestTool/Commands.swift:3,7,10,13,14,17,18,19,23,26,29,33,34,39,42,43,44,45 ./Tests/TestTool/Sources/TestTool/main.swift:2 ./Tests/LinuxMain.swift:2,5,9 ./Tests/InternalTests/RegistryTests.swift:5,7,11,12,16,17,24,26,29,30,31 ./Tests/InternalTests/XCTestManifests.swift:2,9,10,16 ./Package.swift:3 ./Sources/CommandRegistry/CommandRegistry.swift:5,7,10,12,15,16,22,23,29,30,37,40,44,47,48,49,53,54,55,58,59,65,66,75,76,80,83,84,85,86 ./Sources/CommandRegistry/Command.swift:4,10,13,14,18,19 ./Sources/CommandRegistry/SugarCommand.swift:5,13,22,23,26,27,30,31,32,38,39 ./Sources/CommandRegistry/TypeAliases.swift:3 <<<<<< EOF